ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/color.c
Revision: 2.14
Committed: Tue Dec 9 15:51:42 2003 UTC (20 years, 4 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.13: +6 -1 lines
Log Message:
Added redirection for getc() and putc() on threaded C library

File Contents

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