home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 8 / CDASC08.ISO / NEWS / RADIANCE / SRC / COMMON / COLOR.C < prev    next >
C/C++ Source or Header  |  1993-10-07  |  6KB  |  282 lines

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