ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/color.c
Revision: 2.9
Committed: Sat Feb 22 02:07:22 2003 UTC (21 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.8: +117 -50 lines
Log Message:
Changes and check-in for 3.5 release
Includes new source files and modifications not recorded for many years
See ray/doc/notes/ReleaseNotes for notes between 3.1 and 3.5 release

File Contents

# User Rev Content
1 greg 1.1 #ifndef lint
2 greg 2.9 static const char RCSid[] = "$Id$";
3 greg 1.1 #endif
4     /*
5     * color.c - routines for color calculations.
6     *
7 greg 2.9 * Externals declared in color.h
8     */
9    
10     /* ====================================================================
11     * The Radiance Software License, Version 1.0
12     *
13     * Copyright (c) 1990 - 2002 The Regents of the University of California,
14     * through Lawrence Berkeley National Laboratory. All rights reserved.
15     *
16     * Redistribution and use in source and binary forms, with or without
17     * modification, are permitted provided that the following conditions
18     * are met:
19     *
20     * 1. Redistributions of source code must retain the above copyright
21     * notice, this list of conditions and the following disclaimer.
22     *
23     * 2. Redistributions in binary form must reproduce the above copyright
24     * notice, this list of conditions and the following disclaimer in
25     * the documentation and/or other materials provided with the
26     * distribution.
27     *
28     * 3. The end-user documentation included with the redistribution,
29     * if any, must include the following acknowledgment:
30     * "This product includes Radiance software
31     * (http://radsite.lbl.gov/)
32     * developed by the Lawrence Berkeley National Laboratory
33     * (http://www.lbl.gov/)."
34     * Alternately, this acknowledgment may appear in the software itself,
35     * if and wherever such third-party acknowledgments normally appear.
36     *
37     * 4. The names "Radiance," "Lawrence Berkeley National Laboratory"
38     * and "The Regents of the University of California" must
39     * not be used to endorse or promote products derived from this
40     * software without prior written permission. For written
41     * permission, please contact [email protected].
42     *
43     * 5. Products derived from this software may not be called "Radiance",
44     * nor may "Radiance" appear in their name, without prior written
45     * permission of Lawrence Berkeley National Laboratory.
46     *
47     * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
48     * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
49     * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
50     * DISCLAIMED. IN NO EVENT SHALL Lawrence Berkeley National Laboratory OR
51     * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
52     * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
53     * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
54     * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
55     * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
56     * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
57     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58     * SUCH DAMAGE.
59     * ====================================================================
60     *
61     * This software consists of voluntary contributions made by many
62     * individuals on behalf of Lawrence Berkeley National Laboratory. For more
63     * information on Lawrence Berkeley National Laboratory, please see
64     * <http://www.lbl.gov/>.
65 greg 1.1 */
66    
67     #include <stdio.h>
68    
69 greg 2.9 #include <stdlib.h>
70    
71 greg 2.7 #include <math.h>
72    
73 greg 1.1 #include "color.h"
74    
75 greg 1.14 #define MINELEN 8 /* minimum scanline length for encoding */
76 greg 2.6 #define MAXELEN 0x7fff /* maximum scanline length for encoding */
77 greg 1.14 #define MINRUN 4 /* minimum run length */
78    
79 greg 2.4
80 greg 1.14 char *
81     tempbuffer(len) /* get a temporary buffer */
82 greg 2.9 unsigned int len;
83 greg 1.14 {
84     static char *tempbuf = NULL;
85 greg 2.5 static unsigned tempbuflen = 0;
86 greg 1.14
87     if (len > tempbuflen) {
88     if (tempbuflen > 0)
89 greg 2.9 tempbuf = (char *)realloc(tempbuf, len);
90 greg 1.14 else
91 greg 2.9 tempbuf = (char *)malloc(len);
92 greg 1.14 tempbuflen = tempbuf==NULL ? 0 : len;
93     }
94     return(tempbuf);
95     }
96    
97    
98 greg 2.9 int
99 greg 1.1 fwritecolrs(scanline, len, fp) /* write out a colr scanline */
100     register COLR *scanline;
101 greg 2.9 int len;
102 greg 1.1 register FILE *fp;
103     {
104 greg 2.9 register int i, j, beg, cnt = 1;
105 greg 1.14 int c2;
106 greg 1.1
107 greg 2.5 if (len < MINELEN | len > MAXELEN) /* OOBs, write out flat */
108 greg 1.14 return(fwrite((char *)scanline,sizeof(COLR),len,fp) - len);
109 greg 2.2 /* put magic header */
110     putc(2, fp);
111 greg 1.14 putc(2, fp);
112     putc(len>>8, fp);
113     putc(len&255, fp);
114     /* put components seperately */
115     for (i = 0; i < 4; i++) {
116     for (j = 0; j < len; j += cnt) { /* find next run */
117     for (beg = j; beg < len; beg += cnt) {
118     for (cnt = 1; cnt < 127 && beg+cnt < len &&
119     scanline[beg+cnt][i] == scanline[beg][i]; cnt++)
120     ;
121     if (cnt >= MINRUN)
122     break; /* long enough */
123 greg 1.1 }
124 greg 1.15 if (beg-j > 1 && beg-j < MINRUN) {
125     c2 = j+1;
126     while (scanline[c2++][i] == scanline[j][i])
127     if (c2 == beg) { /* short run */
128     putc(128+beg-j, fp);
129     putc(scanline[j][i], fp);
130     j = beg;
131     break;
132     }
133     }
134     while (j < beg) { /* write out non-run */
135 greg 1.14 if ((c2 = beg-j) > 128) c2 = 128;
136     putc(c2, fp);
137     while (c2--)
138     putc(scanline[j++][i], fp);
139     }
140     if (cnt >= MINRUN) { /* write out run */
141     putc(128+cnt, fp);
142     putc(scanline[beg][i], fp);
143     } else
144     cnt = 0;
145     }
146 greg 1.1 }
147     return(ferror(fp) ? -1 : 0);
148     }
149    
150    
151 greg 2.9 static int
152     oldreadcolrs(scanline, len, fp) /* read in an old colr scanline */
153     register COLR *scanline;
154     int len;
155     register FILE *fp;
156     {
157     int rshift;
158     register int i;
159    
160     rshift = 0;
161    
162     while (len > 0) {
163     scanline[0][RED] = getc(fp);
164     scanline[0][GRN] = getc(fp);
165     scanline[0][BLU] = getc(fp);
166     scanline[0][EXP] = getc(fp);
167     if (feof(fp) || ferror(fp))
168     return(-1);
169     if (scanline[0][RED] == 1 &&
170     scanline[0][GRN] == 1 &&
171     scanline[0][BLU] == 1) {
172     for (i = scanline[0][EXP] << rshift; i > 0; i--) {
173     copycolr(scanline[0], scanline[-1]);
174     scanline++;
175     len--;
176     }
177     rshift += 8;
178     } else {
179     scanline++;
180     len--;
181     rshift = 0;
182     }
183     }
184     return(0);
185     }
186    
187    
188     int
189 greg 1.14 freadcolrs(scanline, len, fp) /* read in an encoded colr scanline */
190 greg 1.1 register COLR *scanline;
191     int len;
192     register FILE *fp;
193     {
194 greg 1.14 register int i, j;
195 greg 2.6 int code, val;
196 greg 1.14 /* determine scanline type */
197 greg 2.5 if (len < MINELEN | len > MAXELEN)
198 greg 1.14 return(oldreadcolrs(scanline, len, fp));
199     if ((i = getc(fp)) == EOF)
200     return(-1);
201     if (i != 2) {
202     ungetc(i, fp);
203     return(oldreadcolrs(scanline, len, fp));
204     }
205     scanline[0][GRN] = getc(fp);
206     scanline[0][BLU] = getc(fp);
207     if ((i = getc(fp)) == EOF)
208     return(-1);
209     if (scanline[0][GRN] != 2 || scanline[0][BLU] & 128) {
210     scanline[0][RED] = 2;
211     scanline[0][EXP] = i;
212     return(oldreadcolrs(scanline+1, len-1, fp));
213     }
214     if ((scanline[0][BLU]<<8 | i) != len)
215     return(-1); /* length mismatch! */
216     /* read each component */
217     for (i = 0; i < 4; i++)
218     for (j = 0; j < len; ) {
219     if ((code = getc(fp)) == EOF)
220     return(-1);
221     if (code > 128) { /* run */
222 greg 2.6 code &= 127;
223 greg 2.9 if ((val = getc(fp)) == EOF)
224     return -1;
225 greg 2.6 while (code--)
226     scanline[j++][i] = val;
227 greg 1.14 } else /* non-run */
228 greg 2.9 while (code--) {
229     if ((val = getc(fp)) == EOF)
230     return -1;
231     scanline[j++][i] = val;
232     }
233 greg 1.14 }
234 greg 1.1 return(0);
235     }
236    
237    
238 greg 2.9 int
239 greg 1.1 fwritescan(scanline, len, fp) /* write out a scanline */
240     register COLOR *scanline;
241     int len;
242 greg 1.14 FILE *fp;
243 greg 1.1 {
244 greg 1.14 COLR *clrscan;
245     int n;
246     register COLR *sp;
247     /* get scanline buffer */
248     if ((sp = (COLR *)tempbuffer(len*sizeof(COLR))) == NULL)
249     return(-1);
250     clrscan = sp;
251     /* convert scanline */
252     n = len;
253     while (n-- > 0) {
254     setcolr(sp[0], scanline[0][RED],
255 greg 1.1 scanline[0][GRN],
256     scanline[0][BLU]);
257     scanline++;
258 greg 1.14 sp++;
259 greg 1.1 }
260 greg 1.14 return(fwritecolrs(clrscan, len, fp));
261 greg 1.1 }
262    
263    
264 greg 2.9 int
265 greg 1.1 freadscan(scanline, len, fp) /* read in a scanline */
266     register COLOR *scanline;
267     int len;
268 greg 1.14 FILE *fp;
269 greg 1.1 {
270 greg 1.14 register COLR *clrscan;
271    
272     if ((clrscan = (COLR *)tempbuffer(len*sizeof(COLR))) == NULL)
273     return(-1);
274     if (freadcolrs(clrscan, len, fp) < 0)
275     return(-1);
276     /* convert scanline */
277     colr_color(scanline[0], clrscan[0]);
278     while (--len > 0) {
279     scanline++; clrscan++;
280     if (clrscan[0][RED] == clrscan[-1][RED] &&
281     clrscan[0][GRN] == clrscan[-1][GRN] &&
282     clrscan[0][BLU] == clrscan[-1][BLU] &&
283     clrscan[0][EXP] == clrscan[-1][EXP])
284     copycolor(scanline[0], scanline[-1]);
285     else
286     colr_color(scanline[0], clrscan[0]);
287 greg 1.1 }
288     return(0);
289     }
290    
291    
292 greg 2.9 void
293 greg 1.1 setcolr(clr, r, g, b) /* assign a short color value */
294     register COLR clr;
295     double r, g, b;
296     {
297     double d;
298     int e;
299    
300     d = r > g ? r : g;
301     if (b > d) d = b;
302    
303 greg 1.4 if (d <= 1e-32) {
304 greg 1.1 clr[RED] = clr[GRN] = clr[BLU] = 0;
305     clr[EXP] = 0;
306     return;
307     }
308    
309 greg 2.8 d = frexp(d, &e) * 255.9999 / d;
310 greg 1.1
311     clr[RED] = r * d;
312     clr[GRN] = g * d;
313     clr[BLU] = b * d;
314     clr[EXP] = e + COLXS;
315     }
316    
317    
318 greg 2.9 void
319 greg 1.1 colr_color(col, clr) /* convert short to float color */
320     register COLOR col;
321     register COLR clr;
322     {
323 greg 1.6 double f;
324 greg 1.1
325     if (clr[EXP] == 0)
326     col[RED] = col[GRN] = col[BLU] = 0.0;
327     else {
328 greg 1.2 f = ldexp(1.0, (int)clr[EXP]-(COLXS+8));
329 greg 1.1 col[RED] = (clr[RED] + 0.5)*f;
330     col[GRN] = (clr[GRN] + 0.5)*f;
331     col[BLU] = (clr[BLU] + 0.5)*f;
332     }
333 greg 1.6 }
334    
335    
336 greg 2.9 int
337 greg 1.7 bigdiff(c1, c2, md) /* c1 delta c2 > md? */
338     register COLOR c1, c2;
339     double md;
340     {
341     register int i;
342    
343     for (i = 0; i < 3; i++)
344     if (colval(c1,i)-colval(c2,i) > md*colval(c2,i) ||
345     colval(c2,i)-colval(c1,i) > md*colval(c1,i))
346     return(1);
347     return(0);
348     }