--- ray/src/common/color.c 1989/05/11 22:15:57 1.4 +++ ray/src/common/color.c 1991/08/28 08:39:47 1.15 @@ -1,4 +1,4 @@ -/* Copyright (c) 1986 Regents of the University of California */ +/* Copyright (c) 1991 Regents of the University of California */ #ifndef lint static char SCCSid[] = "$SunId$ LBL"; @@ -14,147 +14,127 @@ static char SCCSid[] = "$SunId$ LBL"; #include "color.h" -#ifdef SPEC_RGB -/* - * The following table contains the CIE tristimulus integrals - * for X, Y, and Z. The table is cumulative, so that - * each color coordinate integrates to 1. - */ +#define MINELEN 8 /* minimum scanline length for encoding */ +#define MINRUN 4 /* minimum run length */ -#define STARTWL 380 /* starting wavelength (nanometers) */ -#define INCWL 10 /* wavelength increment */ -#define NINC 40 /* # of values */ -static BYTE chroma[3][NINC] = { - { /* X */ - 0, 0, 0, 2, 6, 13, 22, 30, 36, 41, - 42, 43, 43, 44, 46, 52, 60, 71, 87, 106, - 128, 153, 178, 200, 219, 233, 243, 249, 252, 254, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 - }, { /* Y */ - 0, 0, 0, 0, 0, 1, 2, 4, 7, 11, - 17, 24, 34, 48, 64, 84, 105, 127, 148, 169, - 188, 205, 220, 232, 240, 246, 250, 253, 254, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 - }, { /* Z */ - 0, 0, 2, 10, 32, 66, 118, 153, 191, 220, - 237, 246, 251, 253, 254, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 - } -}; - - -spec_rgb(col, s, e) /* comput RGB color from spectral range */ -COLOR col; -int s, e; +char * +tempbuffer(len) /* get a temporary buffer */ +unsigned len; { - COLOR ciecolor; + extern char *malloc(), *realloc(); + static char *tempbuf = NULL; + static int tempbuflen = 0; - spec_cie(ciecolor, s, e); - cie_rgb(col, ciecolor); + if (len > tempbuflen) { + if (tempbuflen > 0) + tempbuf = realloc(tempbuf, len); + else + tempbuf = malloc(len); + tempbuflen = tempbuf==NULL ? 0 : len; + } + return(tempbuf); } -spec_cie(col, s, e) /* compute a color from a spectral range */ -COLOR col; /* returned color */ -int s, e; /* starting and ending wavelengths */ +fwritecolrs(scanline, len, fp) /* write out a colr scanline */ +register COLR *scanline; +int len; +register FILE *fp; { - register int i, d, r; + register int i, j, beg, cnt; + int c2; - s -= STARTWL; - if (s < 0) - s = 0; - - e -= STARTWL; - if (e >= INCWL*(NINC - 1)) - e = INCWL*(NINC - 1) - 1; - - d = e / INCWL; /* interpolate values */ - r = e % INCWL; - for (i = 0; i < 3; i++) - col[i] = chroma[i][d]*(INCWL - r) + chroma[i][d + 1]*r; - - d = s / INCWL; - r = s % INCWL; - for (i = 0; i < 3; i++) - col[i] -= chroma[i][d]*(INCWL - r) - chroma[i][d + 1]*r; - - col[RED] = (col[RED] + 0.5) / (256*INCWL); - col[GRN] = (col[GRN] + 0.5) / (256*INCWL); - col[BLU] = (col[BLU] + 0.5) / (256*INCWL); -} - - -cie_rgb(rgbcolor, ciecolor) /* convert CIE to RGB (NTSC) */ -register COLOR rgbcolor, ciecolor; -{ - static float cmat[3][3] = { - 1.73, -.48, -.26, - -.81, 1.65, -.02, - .08, -.17, 1.28, - }; - register int i; - - for (i = 0; i < 3; i++) { - rgbcolor[i] = cmat[i][0]*ciecolor[0] + - cmat[i][1]*ciecolor[1] + - cmat[i][2]*ciecolor[2] ; - if (rgbcolor[i] < 0.0) - rgbcolor[i] = 0.0; + if (len < MINELEN) /* too small to encode */ + return(fwrite((char *)scanline,sizeof(COLR),len,fp) - len); + if (len > 32767) /* too big! */ + return(-1); + putc(2, fp); /* put magic header */ + putc(2, fp); + putc(len>>8, fp); + putc(len&255, fp); + /* put components seperately */ + for (i = 0; i < 4; i++) { + for (j = 0; j < len; j += cnt) { /* find next run */ + for (beg = j; beg < len; beg += cnt) { + for (cnt = 1; cnt < 127 && beg+cnt < len && + scanline[beg+cnt][i] == scanline[beg][i]; cnt++) + ; + if (cnt >= MINRUN) + break; /* long enough */ + } + if (beg-j > 1 && beg-j < MINRUN) { + c2 = j+1; + while (scanline[c2++][i] == scanline[j][i]) + if (c2 == beg) { /* short run */ + putc(128+beg-j, fp); + putc(scanline[j][i], fp); + j = beg; + break; + } + } + while (j < beg) { /* write out non-run */ + if ((c2 = beg-j) > 128) c2 = 128; + putc(c2, fp); + while (c2--) + putc(scanline[j++][i], fp); + } + if (cnt >= MINRUN) { /* write out run */ + putc(128+cnt, fp); + putc(scanline[beg][i], fp); + } else + cnt = 0; + } } + return(ferror(fp) ? -1 : 0); } -#endif -fwritecolrs(scanline, len, fp) /* write out a colr scanline */ +freadcolrs(scanline, len, fp) /* read in an encoded colr scanline */ register COLR *scanline; int len; register FILE *fp; { - COLR lastcolr; - int rept; - - lastcolr[RED] = lastcolr[GRN] = lastcolr[BLU] = 1; - lastcolr[EXP] = 0; - rept = 0; - - while (len > 0) { - if (scanline[0][EXP] == lastcolr[EXP] && - scanline[0][RED] == lastcolr[RED] && - scanline[0][GRN] == lastcolr[GRN] && - scanline[0][BLU] == lastcolr[BLU]) - rept++; - else { - while (rept) { /* write out count */ - putc(1, fp); - putc(1, fp); - putc(1, fp); - putc(rept & 255, fp); - rept >>= 8; - } - putc(scanline[0][RED], fp); /* new color */ - putc(scanline[0][GRN], fp); - putc(scanline[0][BLU], fp); - putc(scanline[0][EXP], fp); - copycolr(lastcolr, scanline[0]); - rept = 0; - } - scanline++; - len--; + register int i, j; + int code; + /* determine scanline type */ + if (len < MINELEN) + return(oldreadcolrs(scanline, len, fp)); + if ((i = getc(fp)) == EOF) + return(-1); + if (i != 2) { + ungetc(i, fp); + return(oldreadcolrs(scanline, len, fp)); } - while (rept) { /* write out count */ - putc(1, fp); - putc(1, fp); - putc(1, fp); - putc(rept & 255, fp); - rept >>= 8; + scanline[0][GRN] = getc(fp); + scanline[0][BLU] = getc(fp); + if ((i = getc(fp)) == EOF) + return(-1); + if (scanline[0][GRN] != 2 || scanline[0][BLU] & 128) { + scanline[0][RED] = 2; + scanline[0][EXP] = i; + return(oldreadcolrs(scanline+1, len-1, fp)); } - return(ferror(fp) ? -1 : 0); + if ((scanline[0][BLU]<<8 | i) != len) + return(-1); /* length mismatch! */ + /* read each component */ + for (i = 0; i < 4; i++) + for (j = 0; j < len; ) { + if ((code = getc(fp)) == EOF) + return(-1); + if (code > 128) { /* run */ + scanline[j++][i] = getc(fp); + for (code &= 127; --code; j++) + scanline[j][i] = scanline[j-1][i]; + } else /* non-run */ + while (code--) + scanline[j++][i] = getc(fp); + } + return(feof(fp) ? -1 : 0); } -freadcolrs(scanline, len, fp) /* read in a colr scanline */ +oldreadcolrs(scanline, len, fp) /* read in an old colr scanline */ register COLR *scanline; int len; register FILE *fp; @@ -193,86 +173,50 @@ register FILE *fp; fwritescan(scanline, len, fp) /* write out a scanline */ register COLOR *scanline; int len; -register FILE *fp; +FILE *fp; { - COLR lastcolr, thiscolr; - int rept; - - lastcolr[RED] = lastcolr[GRN] = lastcolr[BLU] = 1; - lastcolr[EXP] = 0; - rept = 0; - - while (len > 0) { - setcolr(thiscolr, scanline[0][RED], + COLR *clrscan; + int n; + register COLR *sp; + /* get scanline buffer */ + if ((sp = (COLR *)tempbuffer(len*sizeof(COLR))) == NULL) + return(-1); + clrscan = sp; + /* convert scanline */ + n = len; + while (n-- > 0) { + setcolr(sp[0], scanline[0][RED], scanline[0][GRN], scanline[0][BLU]); - if (thiscolr[EXP] == lastcolr[EXP] && - thiscolr[RED] == lastcolr[RED] && - thiscolr[GRN] == lastcolr[GRN] && - thiscolr[BLU] == lastcolr[BLU]) - rept++; - else { - while (rept) { /* write out count */ - putc(1, fp); - putc(1, fp); - putc(1, fp); - putc(rept & 255, fp); - rept >>= 8; - } - putc(thiscolr[RED], fp); /* new color */ - putc(thiscolr[GRN], fp); - putc(thiscolr[BLU], fp); - putc(thiscolr[EXP], fp); - copycolr(lastcolr, thiscolr); - rept = 0; - } scanline++; - len--; + sp++; } - while (rept) { /* write out count */ - putc(1, fp); - putc(1, fp); - putc(1, fp); - putc(rept & 255, fp); - rept >>= 8; - } - return(ferror(fp) ? -1 : 0); + return(fwritecolrs(clrscan, len, fp)); } freadscan(scanline, len, fp) /* read in a scanline */ register COLOR *scanline; int len; -register FILE *fp; +FILE *fp; { - COLR thiscolr; - int rshift; - register int i; - - rshift = 0; - - while (len > 0) { - thiscolr[RED] = getc(fp); - thiscolr[GRN] = getc(fp); - thiscolr[BLU] = getc(fp); - thiscolr[EXP] = getc(fp); - if (feof(fp) || ferror(fp)) - return(-1); - if (thiscolr[RED] == 1 && - thiscolr[GRN] == 1 && - thiscolr[BLU] == 1) { - for (i = thiscolr[EXP] << rshift; i > 0; i--) { - copycolor(scanline[0], scanline[-1]); - scanline++; - len--; - } - rshift += 8; - } else { - colr_color(scanline[0], thiscolr); - scanline++; - len--; - rshift = 0; - } + register COLR *clrscan; + + if ((clrscan = (COLR *)tempbuffer(len*sizeof(COLR))) == NULL) + return(-1); + if (freadcolrs(clrscan, len, fp) < 0) + return(-1); + /* convert scanline */ + colr_color(scanline[0], clrscan[0]); + while (--len > 0) { + scanline++; clrscan++; + if (clrscan[0][RED] == clrscan[-1][RED] && + clrscan[0][GRN] == clrscan[-1][GRN] && + clrscan[0][BLU] == clrscan[-1][BLU] && + clrscan[0][EXP] == clrscan[-1][EXP]) + copycolor(scanline[0], scanline[-1]); + else + colr_color(scanline[0], clrscan[0]); } return(0); } @@ -308,7 +252,7 @@ colr_color(col, clr) /* convert short to float color register COLOR col; register COLR clr; { - double ldexp(), f; + double f; if (clr[EXP] == 0) col[RED] = col[GRN] = col[BLU] = 0.0; @@ -318,4 +262,18 @@ register COLR clr; col[GRN] = (clr[GRN] + 0.5)*f; col[BLU] = (clr[BLU] + 0.5)*f; } +} + + +bigdiff(c1, c2, md) /* c1 delta c2 > md? */ +register COLOR c1, c2; +double md; +{ + register int i; + + for (i = 0; i < 3; i++) + if (colval(c1,i)-colval(c2,i) > md*colval(c2,i) || + colval(c2,i)-colval(c1,i) > md*colval(c1,i)) + return(1); + return(0); }