ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/color.c
Revision: 2.11
Committed: Mon Apr 7 15:43:08 2003 UTC (21 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.10: +13 -3 lines
Log Message:
Updated man pages and fixed ages old bug in conversion of negative colors

File Contents

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