--- ray/src/common/color.c 1990/10/19 11:13:02 1.13
+++ ray/src/common/color.c 2003/02/22 02:07:22 2.9
@@ -1,68 +1,155 @@
-/* Copyright (c) 1986 Regents of the University of California */
-
#ifndef lint
-static char SCCSid[] = "$SunId$ LBL";
+static const char RCSid[] = "$Id: color.c,v 2.9 2003/02/22 02:07:22 greg Exp $";
#endif
-
/*
* color.c - routines for color calculations.
*
- * 10/10/85
+ * Externals declared in color.h
*/
+/* ====================================================================
+ * The Radiance Software License, Version 1.0
+ *
+ * Copyright (c) 1990 - 2002 The Regents of the University of California,
+ * through Lawrence Berkeley National Laboratory. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes Radiance software
+ * (http://radsite.lbl.gov/)
+ * developed by the Lawrence Berkeley National Laboratory
+ * (http://www.lbl.gov/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Radiance," "Lawrence Berkeley National Laboratory"
+ * and "The Regents of the University of California" must
+ * not be used to endorse or promote products derived from this
+ * software without prior written permission. For written
+ * permission, please contact radiance@radsite.lbl.gov.
+ *
+ * 5. Products derived from this software may not be called "Radiance",
+ * nor may "Radiance" appear in their name, without prior written
+ * permission of Lawrence Berkeley National Laboratory.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Lawrence Berkeley National Laboratory OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of Lawrence Berkeley National Laboratory. For more
+ * information on Lawrence Berkeley National Laboratory, please see
+ * .
+ */
+
#include
+#include
+
+#include
+
#include "color.h"
+#define MINELEN 8 /* minimum scanline length for encoding */
+#define MAXELEN 0x7fff /* maximum scanline length for encoding */
+#define MINRUN 4 /* minimum run length */
+
+char *
+tempbuffer(len) /* get a temporary buffer */
+unsigned int len;
+{
+ static char *tempbuf = NULL;
+ static unsigned tempbuflen = 0;
+
+ if (len > tempbuflen) {
+ if (tempbuflen > 0)
+ tempbuf = (char *)realloc(tempbuf, len);
+ else
+ tempbuf = (char *)malloc(len);
+ tempbuflen = tempbuf==NULL ? 0 : len;
+ }
+ return(tempbuf);
+}
+
+
+int
fwritecolrs(scanline, len, fp) /* write out a colr scanline */
register COLR *scanline;
int len;
register FILE *fp;
{
- COLR lastcolr;
- int rept;
+ register int i, j, beg, cnt = 1;
+ int c2;
- 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;
+ if (len < MINELEN | len > MAXELEN) /* OOBs, write out flat */
+ return(fwrite((char *)scanline,sizeof(COLR),len,fp) - len);
+ /* put magic header */
+ putc(2, fp);
+ 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;
}
- 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--;
+ 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;
+ }
}
- 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);
}
-freadcolrs(scanline, len, fp) /* read in a colr scanline */
+static int
+oldreadcolrs(scanline, len, fp) /* read in an old colr scanline */
register COLR *scanline;
int len;
register FILE *fp;
@@ -98,99 +185,115 @@ register FILE *fp;
}
+int
+freadcolrs(scanline, len, fp) /* read in an encoded colr scanline */
+register COLR *scanline;
+int len;
+register FILE *fp;
+{
+ register int i, j;
+ int code, val;
+ /* determine scanline type */
+ if (len < MINELEN | len > MAXELEN)
+ return(oldreadcolrs(scanline, len, fp));
+ if ((i = getc(fp)) == EOF)
+ return(-1);
+ if (i != 2) {
+ ungetc(i, fp);
+ return(oldreadcolrs(scanline, len, fp));
+ }
+ 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));
+ }
+ 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 */
+ code &= 127;
+ if ((val = getc(fp)) == EOF)
+ return -1;
+ while (code--)
+ scanline[j++][i] = val;
+ } else /* non-run */
+ while (code--) {
+ if ((val = getc(fp)) == EOF)
+ return -1;
+ scanline[j++][i] = val;
+ }
+ }
+ return(0);
+}
+
+
+int
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));
}
+int
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);
}
+void
setcolr(clr, r, g, b) /* assign a short color value */
register COLR clr;
double r, g, b;
{
- double frexp();
double d;
int e;
@@ -203,7 +306,7 @@ double r, g, b;
return;
}
- d = frexp(d, &e) * 256.0 / d;
+ d = frexp(d, &e) * 255.9999 / d;
clr[RED] = r * d;
clr[GRN] = g * d;
@@ -212,6 +315,7 @@ double r, g, b;
}
+void
colr_color(col, clr) /* convert short to float color */
register COLOR col;
register COLR clr;
@@ -229,6 +333,7 @@ register COLR clr;
}
+int
bigdiff(c1, c2, md) /* c1 delta c2 > md? */
register COLOR c1, c2;
double md;