home *** CD-ROM | disk | FTP | other *** search
/ Encyclopedia of Graphics File Formats Companion / GFF_CD.ISO / formats / radiance / code / color.c next >
Encoding:
C/C++ Source or Header  |  1994-06-20  |  5.7 KB  |  284 lines

  1. /* Copyright (c) 1991 Regents of the University of California */
  2.  
  3. #ifndef lint
  4. static char SCCSid[] = "@(#)color.c 2.6 3/2/93 LBL";
  5. #endif
  6.  
  7. /*
  8.  *  color.c - routines for color calculations.
  9.  *
  10.  *     10/10/85
  11.  */
  12.  
  13. #include  <stdio.h>
  14.  
  15. #include  "color.h"
  16.  
  17. #define  MINELEN8/* minimum scanline length for encoding */
  18. #define  MAXELEN0x7fff/* maximum scanline length for encoding */
  19. #define  MINRUN4/* minimum run length */
  20.  
  21. #ifndef frexp
  22. extern double  frexp();
  23. #endif
  24.  
  25.  
  26. char *
  27. tempbuffer(len)/* get a temporary buffer */
  28. unsigned  len;
  29. {
  30. extern char  *malloc(), *realloc();
  31. static char  *tempbuf = NULL;
  32. static unsigned  tempbuflen = 0;
  33.  
  34. if (len > tempbuflen) {
  35. if (tempbuflen > 0)
  36. tempbuf = realloc(tempbuf, len);
  37. else
  38. tempbuf = malloc(len);
  39. tempbuflen = tempbuf==NULL ? 0 : len;
  40. }
  41. return(tempbuf);
  42. }
  43.  
  44.  
  45. fwritecolrs(scanline, len, fp)/* write out a colr scanline */
  46. register COLR  *scanline;
  47. unsigned  len;
  48. register FILE  *fp;
  49. {
  50. register int  i, j, beg, cnt;
  51. int  c2;
  52.  
  53. if (len < MINELEN | len > MAXELEN)/* OOBs, write out flat */
  54. return(fwrite((char *)scanline,sizeof(COLR),len,fp) - len);
  55. /* put magic header */
  56. putc(2, fp);
  57. putc(2, fp);
  58. putc(len>>8, fp);
  59. putc(len&255, fp);
  60. /* put components seperately */
  61. for (i = 0; i < 4; i++) {
  62.     for (j = 0; j < len; j += cnt) {/* find next run */
  63. for (beg = j; beg < len; beg += cnt) {
  64.     for (cnt = 1; cnt < 127 && beg+cnt < len &&
  65.     scanline[beg+cnt][i] == scanline[beg][i]; cnt++)
  66. ;
  67.     if (cnt >= MINRUN)
  68. break;/* long enough */
  69. }
  70. if (beg-j > 1 && beg-j < MINRUN) {
  71.     c2 = j+1;
  72.     while (scanline[c2++][i] == scanline[j][i])
  73. if (c2 == beg) {/* short run */
  74.     putc(128+beg-j, fp);
  75.     putc(scanline[j][i], fp);
  76.     j = beg;
  77.     break;
  78. }
  79. }
  80. while (j < beg) {/* write out non-run */
  81.     if ((c2 = beg-j) > 128) c2 = 128;
  82.     putc(c2, fp);
  83.     while (c2--)
  84. putc(scanline[j++][i], fp);
  85. }
  86. if (cnt >= MINRUN) {/* write out run */
  87.     putc(128+cnt, fp);
  88.     putc(scanline[beg][i], fp);
  89. } else
  90.     cnt = 0;
  91.     }
  92. }
  93. return(ferror(fp) ? -1 : 0);
  94. }
  95.  
  96.  
  97. freadcolrs(scanline, len, fp)/* read in an encoded colr scanline */
  98. register COLR  *scanline;
  99. int  len;
  100. register FILE  *fp;
  101. {
  102. register int  i, j;
  103. int  code, val;
  104. /* determine scanline type */
  105. if (len < MINELEN | len > MAXELEN)
  106. return(oldreadcolrs(scanline, len, fp));
  107. if ((i = getc(fp)) == EOF)
  108. return(-1);
  109. if (i != 2) {
  110. ungetc(i, fp);
  111. return(oldreadcolrs(scanline, len, fp));
  112. }
  113. scanline[0][GRN] = getc(fp);
  114. scanline[0][BLU] = getc(fp);
  115. if ((i = getc(fp)) == EOF)
  116. return(-1);
  117. if (scanline[0][GRN] != 2 || scanline[0][BLU] & 128) {
  118. scanline[0][RED] = 2;
  119. scanline[0][EXP] = i;
  120. return(oldreadcolrs(scanline+1, len-1, fp));
  121. }
  122. if ((scanline[0][BLU]<<8 | i) != len)
  123. return(-1);/* length mismatch! */
  124. /* read each component */
  125. for (i = 0; i < 4; i++)
  126.     for (j = 0; j < len; ) {
  127. if ((code = getc(fp)) == EOF)
  128.     return(-1);
  129. if (code > 128) {/* run */
  130.     code &= 127;
  131.     val = getc(fp);
  132.     while (code--)
  133. scanline[j++][i] = val;
  134. } else/* non-run */
  135.     while (code--)
  136. scanline[j++][i] = getc(fp);
  137.     }
  138. return(feof(fp) ? -1 : 0);
  139. }
  140.  
  141.  
  142. oldreadcolrs(scanline, len, fp)/* read in an old colr scanline */
  143. register COLR  *scanline;
  144. int  len;
  145. register FILE  *fp;
  146. {
  147. int  rshift;
  148. register int  i;
  149.  
  150. rshift = 0;
  151.  
  152. while (len > 0) {
  153. scanline[0][RED] = getc(fp);
  154. scanline[0][GRN] = getc(fp);
  155. scanline[0][BLU] = getc(fp);
  156. scanline[0][EXP] = getc(fp);
  157. if (feof(fp) || ferror(fp))
  158. return(-1);
  159. if (scanline[0][RED] == 1 &&
  160. scanline[0][GRN] == 1 &&
  161. scanline[0][BLU] == 1) {
  162. for (i = scanline[0][EXP] << rshift; i > 0; i--) {
  163. copycolr(scanline[0], scanline[-1]);
  164. scanline++;
  165. len--;
  166. }
  167. rshift += 8;
  168. } else {
  169. scanline++;
  170. len--;
  171. rshift = 0;
  172. }
  173. }
  174. return(0);
  175. }
  176.  
  177.  
  178. fwritescan(scanline, len, fp)/* write out a scanline */
  179. register COLOR  *scanline;
  180. int  len;
  181. FILE  *fp;
  182. {
  183. COLR  *clrscan;
  184. int  n;
  185. register COLR  *sp;
  186. /* get scanline buffer */
  187. if ((sp = (COLR *)tempbuffer(len*sizeof(COLR))) == NULL)
  188. return(-1);
  189. clrscan = sp;
  190. /* convert scanline */
  191. n = len;
  192. while (n-- > 0) {
  193. setcolr(sp[0], scanline[0][RED],
  194.   scanline[0][GRN],
  195.   scanline[0][BLU]);
  196. scanline++;
  197. sp++;
  198. }
  199. return(fwritecolrs(clrscan, len, fp));
  200. }
  201.  
  202.  
  203. freadscan(scanline, len, fp)/* read in a scanline */
  204. register COLOR  *scanline;
  205. int  len;
  206. FILE  *fp;
  207. {
  208. register COLR  *clrscan;
  209.  
  210. if ((clrscan = (COLR *)tempbuffer(len*sizeof(COLR))) == NULL)
  211. return(-1);
  212. if (freadcolrs(clrscan, len, fp) < 0)
  213. return(-1);
  214. /* convert scanline */
  215. colr_color(scanline[0], clrscan[0]);
  216. while (--len > 0) {
  217. scanline++; clrscan++;
  218. if (clrscan[0][RED] == clrscan[-1][RED] &&
  219.     clrscan[0][GRN] == clrscan[-1][GRN] &&
  220.     clrscan[0][BLU] == clrscan[-1][BLU] &&
  221.     clrscan[0][EXP] == clrscan[-1][EXP])
  222. copycolor(scanline[0], scanline[-1]);
  223. else
  224. colr_color(scanline[0], clrscan[0]);
  225. }
  226. return(0);
  227. }
  228.  
  229.  
  230. setcolr(clr, r, g, b)/* assign a short color value */
  231. register COLR  clr;
  232. double  r, g, b;
  233. {
  234. double  d;
  235. int  e;
  236.  
  237. d = r > g ? r : g;
  238. if (b > d) d = b;
  239.  
  240. if (d <= 1e-32) {
  241. clr[RED] = clr[GRN] = clr[BLU] = 0;
  242. clr[EXP] = 0;
  243. return;
  244. }
  245.  
  246. d = frexp(d, &e) * 256.0 / d;
  247.  
  248. clr[RED] = r * d;
  249. clr[GRN] = g * d;
  250. clr[BLU] = b * d;
  251. clr[EXP] = e + COLXS;
  252. }
  253.  
  254.  
  255. colr_color(col, clr)/* convert short to float color */
  256. register COLOR  col;
  257. register COLR  clr;
  258. {
  259. double  f;
  260.  
  261. if (clr[EXP] == 0)
  262. col[RED] = col[GRN] = col[BLU] = 0.0;
  263. else {
  264. f = ldexp(1.0, (int)clr[EXP]-(COLXS+8));
  265. col[RED] = (clr[RED] + 0.5)*f;
  266. col[GRN] = (clr[GRN] + 0.5)*f;
  267. col[BLU] = (clr[BLU] + 0.5)*f;
  268. }
  269. }
  270.  
  271.  
  272. bigdiff(c1, c2, md)/* c1 delta c2 > md? */
  273. register COLOR  c1, c2;
  274. double  md;
  275. {
  276. register int  i;
  277.  
  278. for (i = 0; i < 3; i++)
  279. if (colval(c1,i)-colval(c2,i) > md*colval(c2,i) ||
  280. colval(c2,i)-colval(c1,i) > md*colval(c1,i))
  281. return(1);
  282. return(0);
  283. }
  284.