ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/color.c
Revision: 2.22
Committed: Sat Mar 5 17:18:02 2022 UTC (2 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.21: +17 -8 lines
Log Message:
refactor: changed char *tempbuffer() to void *tempbuffer()

File Contents

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