ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/color.c
Revision: 2.21
Committed: Mon May 27 15:44:26 2019 UTC (4 years, 11 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R3
Changes since 2.20: +4 -4 lines
Log Message:
Fixed potential bug where RGB=(0.01953125 0.01953125 1)*2^N for any N could encode as an RLE start sequence

File Contents

# User Rev Content
1 greg 1.1 #ifndef lint
2 greg 2.21 static const char RCSid[] = "$Id: color.c,v 2.20 2019/02/23 19:11:25 greg Exp $";
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 greg 2.10 #include "copyright.h"
11 greg 1.1
12     #include <stdio.h>
13 greg 2.9 #include <stdlib.h>
14 greg 2.7 #include <math.h>
15 greg 1.1 #include "color.h"
16 greg 2.14
17     #ifdef getc_unlocked /* avoid horrendous overhead of flockfile */
18 greg 2.15 #undef getc
19     #undef putc
20 greg 2.19 #undef ferror
21 greg 2.14 #define getc getc_unlocked
22     #define putc putc_unlocked
23 greg 2.18 #define ferror ferror_unlocked
24 greg 2.14 #endif
25 greg 1.1
26 greg 1.14 #define MINELEN 8 /* minimum scanline length for encoding */
27 greg 2.6 #define MAXELEN 0x7fff /* maximum scanline length for encoding */
28 greg 1.14 #define MINRUN 4 /* minimum run length */
29    
30 greg 2.4
31 greg 1.14 char *
32 greg 2.17 tempbuffer( /* get a temporary buffer */
33     unsigned int len
34     )
35 greg 1.14 {
36     static char *tempbuf = NULL;
37 greg 2.5 static unsigned tempbuflen = 0;
38 greg 1.14
39 greg 2.20 if (!len | (len > tempbuflen)) {
40     if (tempbuflen)
41     free(tempbuf);
42     tempbuf = len ? (char *)malloc(len) : (char *)NULL;
43     tempbuflen = len*(tempbuf != NULL);
44 greg 1.14 }
45     return(tempbuf);
46     }
47    
48    
49 greg 2.9 int
50 greg 2.17 fwritecolrs( /* write out a colr scanline */
51     COLR *scanline,
52     int len,
53     FILE *fp
54     )
55 greg 1.1 {
56 greg 2.17 int i, j, beg, cnt = 1;
57 greg 1.14 int c2;
58 greg 1.1
59 schorsch 2.13 if ((len < MINELEN) | (len > MAXELEN)) /* OOBs, write out flat */
60 greg 1.14 return(fwrite((char *)scanline,sizeof(COLR),len,fp) - len);
61 greg 2.2 /* put magic header */
62     putc(2, fp);
63 greg 1.14 putc(2, fp);
64     putc(len>>8, fp);
65 greg 2.21 putc(len&0xff, fp);
66 greg 1.14 /* put components seperately */
67     for (i = 0; i < 4; i++) {
68     for (j = 0; j < len; j += cnt) { /* find next run */
69     for (beg = j; beg < len; beg += cnt) {
70 greg 2.20 for (cnt = 1; (cnt < 127) & (beg+cnt < len) &&
71 greg 1.14 scanline[beg+cnt][i] == scanline[beg][i]; cnt++)
72     ;
73     if (cnt >= MINRUN)
74     break; /* long enough */
75 greg 1.1 }
76 greg 2.20 if ((beg-j > 1) & (beg-j < MINRUN)) {
77 greg 1.15 c2 = j+1;
78     while (scanline[c2++][i] == scanline[j][i])
79     if (c2 == beg) { /* short run */
80     putc(128+beg-j, fp);
81     putc(scanline[j][i], fp);
82     j = beg;
83     break;
84     }
85     }
86     while (j < beg) { /* write out non-run */
87 greg 1.14 if ((c2 = beg-j) > 128) c2 = 128;
88     putc(c2, fp);
89     while (c2--)
90     putc(scanline[j++][i], fp);
91     }
92     if (cnt >= MINRUN) { /* write out run */
93     putc(128+cnt, fp);
94     putc(scanline[beg][i], fp);
95     } else
96     cnt = 0;
97     }
98 greg 1.1 }
99     return(ferror(fp) ? -1 : 0);
100     }
101    
102    
103 greg 2.9 static int
104 greg 2.19 oldreadcolrs( /* read in an old-style colr scanline */
105 greg 2.17 COLR *scanline,
106     int len,
107     FILE *fp
108     )
109 greg 2.9 {
110 greg 2.18 int rshift = 0;
111 greg 2.17 int i;
112 greg 2.9
113     while (len > 0) {
114     scanline[0][RED] = getc(fp);
115     scanline[0][GRN] = getc(fp);
116     scanline[0][BLU] = getc(fp);
117 greg 2.18 scanline[0][EXP] = i = getc(fp);
118     if (i == EOF)
119 greg 2.9 return(-1);
120 greg 2.20 if (scanline[0][GRN] == 1 &&
121     (scanline[0][RED] == 1) &
122     (scanline[0][BLU] == 1)) {
123     i = scanline[0][EXP] << rshift;
124     while (i--) {
125 greg 2.9 copycolr(scanline[0], scanline[-1]);
126 greg 2.20 if (--len <= 0)
127     return(0);
128 greg 2.9 scanline++;
129     }
130     rshift += 8;
131     } else {
132     scanline++;
133     len--;
134     rshift = 0;
135     }
136     }
137     return(0);
138     }
139    
140    
141     int
142 greg 2.17 freadcolrs( /* read in an encoded colr scanline */
143     COLR *scanline,
144     int len,
145     FILE *fp
146     )
147 greg 1.1 {
148 greg 2.17 int i, j;
149 greg 2.6 int code, val;
150 greg 1.14 /* determine scanline type */
151 schorsch 2.13 if ((len < MINELEN) | (len > MAXELEN))
152 greg 1.14 return(oldreadcolrs(scanline, len, fp));
153     if ((i = getc(fp)) == EOF)
154     return(-1);
155     if (i != 2) {
156     ungetc(i, fp);
157     return(oldreadcolrs(scanline, len, fp));
158     }
159     scanline[0][GRN] = getc(fp);
160     scanline[0][BLU] = getc(fp);
161     if ((i = getc(fp)) == EOF)
162     return(-1);
163 greg 2.21 if ((scanline[0][GRN] != 2) | ((scanline[0][BLU] & 0x80) != 0)) {
164 greg 1.14 scanline[0][RED] = 2;
165     scanline[0][EXP] = i;
166     return(oldreadcolrs(scanline+1, len-1, fp));
167     }
168     if ((scanline[0][BLU]<<8 | i) != len)
169     return(-1); /* length mismatch! */
170     /* read each component */
171     for (i = 0; i < 4; i++)
172     for (j = 0; j < len; ) {
173     if ((code = getc(fp)) == EOF)
174     return(-1);
175     if (code > 128) { /* run */
176 greg 2.6 code &= 127;
177 greg 2.9 if ((val = getc(fp)) == EOF)
178     return -1;
179 greg 2.16 if (j + code > len)
180     return -1; /* overrun */
181 greg 2.6 while (code--)
182     scanline[j++][i] = val;
183 greg 2.16 } else { /* non-run */
184     if (j + code > len)
185     return -1; /* overrun */
186 greg 2.9 while (code--) {
187     if ((val = getc(fp)) == EOF)
188     return -1;
189     scanline[j++][i] = val;
190     }
191 greg 2.16 }
192 greg 1.14 }
193 greg 1.1 return(0);
194     }
195    
196    
197 greg 2.9 int
198 greg 2.17 fwritescan( /* write out a scanline */
199     COLOR *scanline,
200     int len,
201     FILE *fp
202     )
203 greg 1.1 {
204 greg 1.14 COLR *clrscan;
205     int n;
206 greg 2.17 COLR *sp;
207 greg 1.14 /* get scanline buffer */
208     if ((sp = (COLR *)tempbuffer(len*sizeof(COLR))) == NULL)
209     return(-1);
210     clrscan = sp;
211     /* convert scanline */
212     n = len;
213     while (n-- > 0) {
214     setcolr(sp[0], scanline[0][RED],
215 greg 1.1 scanline[0][GRN],
216     scanline[0][BLU]);
217     scanline++;
218 greg 1.14 sp++;
219 greg 1.1 }
220 greg 1.14 return(fwritecolrs(clrscan, len, fp));
221 greg 1.1 }
222    
223    
224 greg 2.9 int
225 greg 2.17 freadscan( /* read in a scanline */
226     COLOR *scanline,
227     int len,
228     FILE *fp
229     )
230 greg 1.1 {
231 greg 2.17 COLR *clrscan;
232 greg 1.14
233     if ((clrscan = (COLR *)tempbuffer(len*sizeof(COLR))) == NULL)
234     return(-1);
235     if (freadcolrs(clrscan, len, fp) < 0)
236     return(-1);
237     /* convert scanline */
238     colr_color(scanline[0], clrscan[0]);
239     while (--len > 0) {
240     scanline++; clrscan++;
241 greg 2.20 if (clrscan[0][GRN] == clrscan[-1][GRN] &&
242     (clrscan[0][RED] == clrscan[-1][RED]) &
243     (clrscan[0][BLU] == clrscan[-1][BLU]) &
244     (clrscan[0][EXP] == clrscan[-1][EXP]))
245 greg 1.14 copycolor(scanline[0], scanline[-1]);
246     else
247     colr_color(scanline[0], clrscan[0]);
248 greg 1.1 }
249     return(0);
250     }
251    
252    
253 greg 2.9 void
254 greg 2.17 setcolr( /* assign a short color value */
255     COLR clr,
256     double r,
257     double g,
258     double b
259     )
260 greg 1.1 {
261     double d;
262     int e;
263    
264     d = r > g ? r : g;
265     if (b > d) d = b;
266    
267 greg 1.4 if (d <= 1e-32) {
268 greg 1.1 clr[RED] = clr[GRN] = clr[BLU] = 0;
269     clr[EXP] = 0;
270     return;
271     }
272    
273 greg 2.21 d = frexp(d, &e) * 256.0 / d;
274 greg 1.1
275 greg 2.11 if (r > 0.0)
276     clr[RED] = r * d;
277     else
278     clr[RED] = 0;
279     if (g > 0.0)
280     clr[GRN] = g * d;
281     else
282     clr[GRN] = 0;
283     if (b > 0.0)
284     clr[BLU] = b * d;
285     else
286     clr[BLU] = 0;
287    
288 greg 1.1 clr[EXP] = e + COLXS;
289     }
290    
291    
292 greg 2.9 void
293 greg 2.17 colr_color( /* convert short to float color */
294     COLOR col,
295     COLR clr
296     )
297 greg 1.1 {
298 greg 1.6 double f;
299 greg 1.1
300     if (clr[EXP] == 0)
301     col[RED] = col[GRN] = col[BLU] = 0.0;
302     else {
303 greg 1.2 f = ldexp(1.0, (int)clr[EXP]-(COLXS+8));
304 greg 1.1 col[RED] = (clr[RED] + 0.5)*f;
305     col[GRN] = (clr[GRN] + 0.5)*f;
306     col[BLU] = (clr[BLU] + 0.5)*f;
307     }
308 greg 1.6 }
309    
310    
311 greg 2.9 int
312 greg 2.17 bigdiff( /* c1 delta c2 > md? */
313     COLOR c1,
314     COLOR c2,
315     double md
316     )
317 greg 1.7 {
318 greg 2.17 int i;
319 greg 1.7
320     for (i = 0; i < 3; i++)
321     if (colval(c1,i)-colval(c2,i) > md*colval(c2,i) ||
322 greg 2.20 colval(c2,i)-colval(c1,i) > md*colval(c1,i))
323 greg 1.7 return(1);
324     return(0);
325     }