1 |
#ifndef lint |
2 |
static const char RCSid[] = "$Id: ra_xim.c,v 3.1 2003/02/22 02:07:28 greg Exp $"; |
3 |
#endif |
4 |
/*********************************************************************** |
5 |
* Author: Philip Thompson ([email protected]) |
6 |
* - convert from RADIANCE image file format to Xim and vice-versa. |
7 |
* Copyright (c) 1990, Massachusetts Institute of Technology |
8 |
* Philip R. Thompson ([email protected]) |
9 |
* Computer Resource Laboratory (CRL) |
10 |
* Dept. of Architecture and Planning |
11 |
* M.I.T., Rm 9-526 |
12 |
* Cambridge, MA 02139 |
13 |
* This software and its documentation may be used, copied, modified, |
14 |
* and distributed for any purpose without fee, provided: |
15 |
* -- The above copyright notice appears in all copies. |
16 |
* -- This disclaimer appears in all source code copies. |
17 |
* -- The names of M.I.T. and the CRL are not used in advertising |
18 |
* or publicity pertaining to distribution of the software |
19 |
* without prior specific written permission from me or CRL. |
20 |
* I provide this software freely as a public service. It is NOT |
21 |
* public domain nor a commercial product, and therefore is not subject |
22 |
* to an an implied warranty of merchantability or fitness for a |
23 |
* particular purpose. I provide it as is, without warranty. |
24 |
* This software is furnished only on the basis that any party who |
25 |
* receives it indemnifies and holds harmless the parties who furnish |
26 |
* it against any claims, demands, or liabilities connected with using |
27 |
* it, furnishing it to others, or providing it to a third party. |
28 |
***********************************************************************/ |
29 |
#if (!defined(lint) && !defined(SABER)) |
30 |
static char radiance_rcsid[] = |
31 |
"$Header: /cvs/radiance/ray/src/px/ra_xim.c,v 3.1 2003/02/22 02:07:28 greg Exp $"; |
32 |
#endif |
33 |
|
34 |
#include <stdio.h> |
35 |
#include <math.h> |
36 |
#include <pwd.h> |
37 |
#include <sys/types.h> |
38 |
#include <string.h> |
39 |
#include <sys/time.h> |
40 |
|
41 |
/* XimHeader.h */ |
42 |
|
43 |
/* |
44 |
* Author: Philip R. Thompson |
45 |
* Address: [email protected], 9-526 |
46 |
* $Header: /cvs/radiance/ray/src/px/ra_xim.c,v 3.1 2003/02/22 02:07:28 greg Exp $ |
47 |
* $Date: 2003/02/22 02:07:28 $ |
48 |
* $Source: /cvs/radiance/ray/src/px/ra_xim.c,v $ |
49 |
* Copyright (c) 1989, 1990 Massachusetts Institute of Technology |
50 |
* 1988, Philip R. Thompson ([email protected]) |
51 |
* Computer Resource Laboratory (CRL) |
52 |
* Dept. of Architecture and Planning |
53 |
* M.I.T., Rm 9-526 |
54 |
* Cambridge, MA 02139 |
55 |
* This software and its documentation may be used, copied, modified, |
56 |
* and distributed for any purpose without fee, provided: |
57 |
* -- The above copyright notice appears in all copies. |
58 |
* -- This disclaimer appears in all source code copies. |
59 |
* -- The names of M.I.T. and the CRL are not used in advertising |
60 |
* or publicity pertaining to distribution of the software |
61 |
* without prior specific written permission from me or CRL. |
62 |
* I provide this software freely as a public service. It is NOT |
63 |
* public domain nor a commercial product, and therefore is not subject |
64 |
* to an an implied warranty of merchantability or fitness for a |
65 |
* particular purpose. I provide it as is, without warranty. |
66 |
* |
67 |
* This software is furnished only on the basis that any party who |
68 |
* receives it indemnifies and holds harmless the parties who furnish |
69 |
* it against any claims, demands, or liabilities connected with using |
70 |
* it, furnishing it to others, or providing it to a third party. |
71 |
*/ |
72 |
|
73 |
#define IMAGE_VERSION 3 |
74 |
#ifndef _BYTE |
75 |
typedef unsigned char byte; |
76 |
#define _BYTE 1 |
77 |
#endif |
78 |
#include <sys/types.h> |
79 |
|
80 |
|
81 |
/* External ascii file format |
82 |
* Note: size of header should be 1024 (1K) bytes. |
83 |
*/ |
84 |
typedef struct ImageHeader { |
85 |
char file_version[8]; /* header version */ |
86 |
char header_size[8]; /* Size of file header in bytes (1024) */ |
87 |
char image_width[8]; /* Width of the raster image */ |
88 |
char image_height[8]; /* Height of the raster imgage */ |
89 |
char num_colors[4]; /* Actual number of entries in c_map */ |
90 |
char greyscale[2]; /* Flag if no c_map needed */ |
91 |
char flag[2]; /* Not used */ |
92 |
char num_channels[3]; /* 0 or 1 = pixmap, 3 = RG&B buffers */ |
93 |
char bytes_per_line[5]; /* bytes per scanline */ |
94 |
char num_pictures[4]; /* Number of pictures in file */ |
95 |
char bits_per_channel[4]; /* usually 1 or 8 */ |
96 |
char alpha_channel[4]; /* Alpha channel flag */ |
97 |
char runlength[4]; /* Runlength encoded flag */ |
98 |
char author[48]; /* Name of who made it */ |
99 |
char date[32]; /* Date and time image was made */ |
100 |
char program[16]; /* Program that created this file */ |
101 |
char comment[96]; /* other viewing info. for this image */ |
102 |
unsigned char c_map[256][3]; /* RGB values of the pixmap indices */ |
103 |
} XimAsciiHeader; |
104 |
|
105 |
|
106 |
/* Internal binary format |
107 |
*/ |
108 |
typedef struct Color { |
109 |
byte red, grn, blu, pixel; |
110 |
} Color; |
111 |
|
112 |
typedef struct XimImage { |
113 |
int width; /* width of the image in pixels */ |
114 |
int height; /* height of the image in pixels */ |
115 |
int bytes_line; /* bytes to hold one scanline */ |
116 |
unsigned datasize; /* size of one channel of data */ |
117 |
short nchannels; /* data channels per pixel, usually 1 or3 */ |
118 |
short bits_channel; /* depth of a channel, usually 1 or 8 */ |
119 |
byte *data; /* pixmap or red channel data */ |
120 |
byte *grn_data; /* green channel data */ |
121 |
byte *blu_data; /* blue channel data */ |
122 |
byte *other; /* other (alpha) data */ |
123 |
short ncolors; /* number of colors in the color table */ |
124 |
Color *colors; /* colortable for pixmaps */ |
125 |
short curr_pic, npics; /* current & total file number of images */ |
126 |
unsigned alpha_flag: 1; /* alpha channel flag - "other" is used */ |
127 |
unsigned grey_flag : 1; /* is pixmap grey scaled */ |
128 |
unsigned packed_flag:1; /* is data packed in one chunk of memory */ |
129 |
unsigned runlen_flag:1; /* is data compressed flag (not used) */ |
130 |
unsigned : 0; /* future flags space and word alignment */ |
131 |
char *author; /* author credit, copyright, etc */ |
132 |
char *date; /* date image was made, grabbed, etc. */ |
133 |
char *program; /* program used to make this */ |
134 |
char *name; /* name of the image - usually filename */ |
135 |
short ncomments; /* number of comments strings */ |
136 |
char **comments; /* pointers to null terminated comments */ |
137 |
char *offset; /* original offset in memory when packed */ |
138 |
float gamcor; /* image storage gamma */ |
139 |
float chroma_red[2]; /* x, y image chromacity coords */ |
140 |
float chroma_grn[2]; |
141 |
float chroma_blu[2]; |
142 |
float chroma_wht[2]; |
143 |
} XimImage; |
144 |
|
145 |
|
146 |
/* Future external ascii variable length header - under review |
147 |
*/ |
148 |
#if (VERSION == 4) |
149 |
typedef struct XimAsciiHeader { |
150 |
char file_version[4]; /* header version */ |
151 |
char header_size[8]; /* Size of file header (fixed part only) */ |
152 |
char image_height[8]; /* Height of the raster imgage in pixels */ |
153 |
char image_width[8]; /* Width of the raster image in pixels */ |
154 |
char bytes_line[8]; /* Actual # of bytes separating scanlines */ |
155 |
char bits_channel[4]; /* Bits per channel (usually 1 or 8) */ |
156 |
char num_channels[4]; /* 1 = pixmap, 3 = RG&B buffers */ |
157 |
char alpha_channel[2]; /* Alpha channel flag */ |
158 |
char num_colors[4]; /* Number of entries in c_map (if any) */ |
159 |
char num_pictures[4]; /* Number of images in file */ |
160 |
char compress_flag[2]; /* Runlength encoded flag */ |
161 |
char greyscale_flag[2]; /* Greyscale flag */ |
162 |
char future_flags[4]; |
163 |
char author[48]; /* Name of who made it, from passwd entry */ |
164 |
char date[32]; /* Unix format date */ |
165 |
char program[32]; /* Program that created this */ |
166 |
char gamcor[12]; /* image storage gamma */ |
167 |
char chroma_red[24]; /* image red primary chromaticity coords. */ |
168 |
char chroma_grn[24]; /* " green " " " */ |
169 |
char chroma_blu[24]; /* " blue " " " */ |
170 |
char chroma_wht[24]; /* " white point " " */ |
171 |
char comment_length[8] /* Total length of all comments */ |
172 |
/* char *comment; Null separated comments */ |
173 |
/* byte c_map[]; RGB Colortable, (ncolors * 3 bytes) */ |
174 |
} XimAsciiHeader; |
175 |
#endif VERSION 4 |
176 |
|
177 |
#ifndef rnd |
178 |
#define rnd(x) ((int)((float)(x) + 0.5)) /* round a float to an int */ |
179 |
#endif |
180 |
|
181 |
/* Note: |
182 |
* - All external data is in char's in order to maintain easily |
183 |
* portability across machines and some human readibility. |
184 |
* - Images may be stored as bitmaps (8 pixels/byte), pixmaps |
185 |
* (1 byte /pixel) or as seperate red, green, blue channel data |
186 |
* (3 bytes/pixel). |
187 |
* - An alpha channel is optional and is found after every num_channels |
188 |
* of data. |
189 |
* - Pixmaps or RG&B (and alpha) channel data are stored respectively |
190 |
* after the header. |
191 |
* - If num_channels == 1 a pixmap is assumed and the colormap in the |
192 |
* header is used unless its greyscale. |
193 |
* - Datasize is for one channel. |
194 |
*/ |
195 |
|
196 |
/*** end ImageHeader.h ***/ |
197 |
|
198 |
#define XDECR 1 |
199 |
#define YDECR 2 |
200 |
#define YMAJOR 4 |
201 |
#define RED 0 |
202 |
#define GRN 1 |
203 |
#define BLU 2 |
204 |
#define EXP 3 |
205 |
#define MAXLINE 512 |
206 |
|
207 |
#define setcolor(col,r,g,b) (col[RED]=(r), col[GRN]=(g), col[BLU]=(b)) |
208 |
#define copycolr(c1,c2) (c1[0]=c2[0],c1[1]=c2[1], \ |
209 |
c1[2]=c2[2],c1[3]=c2[3]) |
210 |
#define copycolor(c1,c2) ((c1)[0]=(c2)[0],(c1)[1]=(c2)[1],\ |
211 |
(c1)[2]=(c2)[2]) |
212 |
#define COLXS 128 /* excess used for exponent */ |
213 |
typedef float COLOR[3]; /* red, green, blue */ |
214 |
typedef byte COLR[4]; /* red, green, blue, exponent */ |
215 |
|
216 |
#define FREE(a) if ((a) != NULL) free((char*)(a)), (a) = NULL |
217 |
|
218 |
char *AllocAndCopy(); |
219 |
extern debug_flag; |
220 |
static byte RadiancePixel(); |
221 |
|
222 |
|
223 |
XimReadRadiance(ifp, xim, gamcor) |
224 |
FILE *ifp; |
225 |
XimImage *xim; |
226 |
double gamcor; |
227 |
{ |
228 |
register int x, y, i; |
229 |
int width, height; |
230 |
COLOR *scanline; /* RADIANCE variable */ |
231 |
struct timeval time_val; |
232 |
struct timezone time_zone; |
233 |
struct passwd *getpwnam(), *getpwuid(), *pwd = NULL; |
234 |
char *login_ptr = NULL, *ctime(), *getlogin(); |
235 |
byte gmap[256]; |
236 |
|
237 |
/* get width, height from radiance file */ |
238 |
memset(xim, '\0', sizeof(XimImage)); |
239 |
if (!RadianceGetSize(ifp, &width, &height)) |
240 |
return 0; |
241 |
xim->width = xim->bytes_line = width; |
242 |
xim->height = height; |
243 |
xim->nchannels = 3; |
244 |
xim->bits_channel = 8; |
245 |
xim->datasize = xim->height * xim->bytes_line; |
246 |
xim->npics = 1; |
247 |
xim->data = (byte *)malloc(xim->datasize); |
248 |
xim->grn_data = (byte *)malloc(xim->datasize); |
249 |
xim->blu_data = (byte *)malloc(xim->datasize); |
250 |
if (!xim->data || !xim->grn_data || !xim->blu_data) { |
251 |
FREE(xim->data); |
252 |
FREE(xim->grn_data); |
253 |
FREE(xim->blu_data); |
254 |
XimWarn("XimReadRadiance: can't malloc xim buffers"); |
255 |
return 0; |
256 |
} |
257 |
if (!(scanline = (COLOR*)malloc(width * sizeof(COLOR)))) { |
258 |
XimWarn("XimReadRadiance: can't malloc scanline"); |
259 |
return(0); |
260 |
} |
261 |
for (i=0; i < 256; i++) { |
262 |
gmap[i] = (byte)(0.5 + 255.0 * pow(i / 255.0, 1.0/gamcor)); |
263 |
if (debug_flag) |
264 |
fprintf(stderr, "%2d: %u\n", i, gmap[i]); |
265 |
} |
266 |
for (y=0, i=0; y < height; y++) { |
267 |
if (!freadscan(scanline, width, ifp)) { |
268 |
XimWarn("freadscan: read error"); |
269 |
free((char*)scanline); |
270 |
return 0; |
271 |
} |
272 |
for (x=0; x < width; x++, i++) { |
273 |
xim->data[i] = gmap[RadiancePixel(scanline[x], RED)]; |
274 |
xim->grn_data[i] = gmap[RadiancePixel(scanline[x], GRN)]; |
275 |
xim->blu_data[i] = gmap[RadiancePixel(scanline[x], BLU)]; |
276 |
} |
277 |
} |
278 |
free((char*)scanline); |
279 |
xim->comments = (char**)calloc(2, sizeof(char*)); |
280 |
xim->comments[0] =AllocAndCopy("converted from RADIANCE format",40); |
281 |
xim->ncomments = 1; |
282 |
(void)gettimeofday(&time_val, &time_zone); |
283 |
xim->date = ctime(&time_val.tv_sec); |
284 |
xim->date[strlen(xim->date)-1] = '\0'; |
285 |
/* date points to static memory, so copy it to make freeable */ |
286 |
xim->date = AllocAndCopy(xim->date, strlen(xim->date)+1); |
287 |
if ((login_ptr = getlogin()) != NULL) |
288 |
pwd = getpwnam(login_ptr); |
289 |
else |
290 |
pwd = getpwuid(getuid()); |
291 |
if (pwd && !(xim->author = AllocAndCopy(pwd->pw_gecos, |
292 |
strlen(pwd->pw_gecos)+1))) { |
293 |
XimWarn("XimReadXwdFile: Can't AllocAndCopy author's name"); |
294 |
return 0; |
295 |
} else |
296 |
xim->author = NULL; |
297 |
return 1; |
298 |
} |
299 |
|
300 |
|
301 |
XimWriteRadiance(ofp, xim, gamcor) |
302 |
FILE *ofp; |
303 |
XimImage *xim; |
304 |
double gamcor; |
305 |
{ |
306 |
COLOR *scanline; |
307 |
int width, height; |
308 |
register int x, y; |
309 |
register byte *red, *grn, *blu; |
310 |
float gmap[256]; |
311 |
|
312 |
/* get width, height from xim */ |
313 |
width = xim->width; |
314 |
height = xim->height; |
315 |
|
316 |
/* allocate scan line space */ |
317 |
if (!(scanline = (COLOR *)malloc(width * sizeof(COLOR)))) { |
318 |
XimWarn("XimWriteRadiance: cant' alloc scanline"); |
319 |
return(0); |
320 |
} |
321 |
/* write out the RADIANCE header */ |
322 |
radiance_writeheader(ofp, width, height); |
323 |
red = xim->data; |
324 |
grn = xim->grn_data; |
325 |
blu = xim->blu_data; |
326 |
for (x=0; x < 256; x++) { |
327 |
gmap[x] = (float)pow((x / 255.0), gamcor); |
328 |
if (debug_flag) |
329 |
fprintf(stderr, "%2d: %f\n", x, gmap[x]); |
330 |
} |
331 |
for (y = 0; y < height; y++) { |
332 |
for (x = 0; x < width; x++) |
333 |
setcolor(scanline[x], gmap[red[x]], gmap[grn[x]], gmap[blu[x]]); |
334 |
radiance_writescanline(ofp, scanline, width); |
335 |
red += xim->bytes_line; |
336 |
grn += xim->bytes_line; |
337 |
blu += xim->bytes_line; |
338 |
} |
339 |
return 1; |
340 |
} |
341 |
|
342 |
static RadianceGetSize(fp, w, h) |
343 |
FILE *fp; |
344 |
int *w, *h; |
345 |
{ |
346 |
if (!GetHeader(fp, NULL)) |
347 |
return 0; |
348 |
if (fgetresolu(w, h, fp) != (YMAJOR | YDECR)) { |
349 |
fprintf(stderr, "bad RADIANCE format\n"); |
350 |
return 0; |
351 |
} |
352 |
return 1; |
353 |
} |
354 |
|
355 |
static byte RadiancePixel(pixel, chan) |
356 |
COLOR pixel; |
357 |
int chan; |
358 |
{ |
359 |
float value; |
360 |
|
361 |
value = pixel[chan]; |
362 |
if (value <= 0.0) |
363 |
return (byte)0; |
364 |
else if (value >= 1.0) |
365 |
return (byte)255; |
366 |
return (byte)((int)((value * 256.0))); |
367 |
} |
368 |
|
369 |
static radiance_writeheader(fp, x, y) |
370 |
FILE *fp; |
371 |
int x; |
372 |
int y; |
373 |
{ |
374 |
fputc('\n', fp); |
375 |
fputresolu(YMAJOR | YDECR, x, y, fp); |
376 |
fflush(fp); |
377 |
} |
378 |
|
379 |
|
380 |
radiance_writescanline(fp, buf, x) |
381 |
FILE *fp; |
382 |
COLOR *buf; |
383 |
int x; |
384 |
{ |
385 |
if (fwritescan(buf, x, fp) < 0) { |
386 |
fprintf(stderr, "write error?\n"); |
387 |
perror("fwrite"); |
388 |
exit(1); |
389 |
} |
390 |
} |
391 |
|
392 |
|
393 |
freadscan(scanline, len, fp) /* read in a scanline */ |
394 |
register COLOR *scanline; |
395 |
int len; |
396 |
register FILE *fp; |
397 |
{ |
398 |
COLR thiscolr; |
399 |
int rshift; |
400 |
register int i; |
401 |
|
402 |
rshift = 0; |
403 |
while (len > 0) { |
404 |
thiscolr[RED] = getc(fp); |
405 |
thiscolr[GRN] = getc(fp); |
406 |
thiscolr[BLU] = getc(fp); |
407 |
thiscolr[EXP] = getc(fp); |
408 |
if (feof(fp) || ferror(fp)) |
409 |
return 0; |
410 |
if (thiscolr[RED] == 1 && |
411 |
thiscolr[GRN] == 1 && |
412 |
thiscolr[BLU] == 1) { |
413 |
for (i = thiscolr[EXP] << rshift; i > 0; i--) { |
414 |
copycolor(scanline[0], scanline[-1]); |
415 |
scanline++; |
416 |
len--; |
417 |
} |
418 |
rshift += 8; |
419 |
} else { |
420 |
colr_color(scanline[0], thiscolr); |
421 |
scanline++; |
422 |
len--; |
423 |
rshift = 0; |
424 |
} |
425 |
} |
426 |
return 1; |
427 |
} |
428 |
|
429 |
|
430 |
colr_color(col, clr) /* convert short to float color */ |
431 |
register COLOR col; |
432 |
register COLR clr; |
433 |
{ |
434 |
double f; |
435 |
|
436 |
if (clr[EXP] == 0) |
437 |
col[RED] = col[GRN] = col[BLU] = 0.0; |
438 |
else { |
439 |
f = ldexp(1.0, (int) clr[EXP] - (COLXS + 8)); |
440 |
col[RED] = (clr[RED] + 0.5) * f; |
441 |
col[GRN] = (clr[GRN] + 0.5) * f; |
442 |
col[BLU] = (clr[BLU] + 0.5) * f; |
443 |
} |
444 |
} |
445 |
|
446 |
static GetHeader(fp, f) /* get header from file */ |
447 |
FILE *fp; |
448 |
int (*f)(); |
449 |
{ |
450 |
char buf[MAXLINE]; |
451 |
|
452 |
for (;;) { |
453 |
buf[MAXLINE - 2] = '\n'; |
454 |
if (fgets(buf, sizeof(buf), fp) == NULL) |
455 |
return (-1); |
456 |
if (buf[0] == '\n') |
457 |
return 1; |
458 |
if (buf[MAXLINE - 2] != '\n') { |
459 |
ungetc(buf[MAXLINE - 2], fp); /* prevent false end */ |
460 |
buf[MAXLINE - 2] = '\0'; |
461 |
} |
462 |
if (f != NULL) |
463 |
(*f)(buf); |
464 |
} |
465 |
} |
466 |
|
467 |
|
468 |
static fgetresolu(xrp, yrp, fp) /* get x and y resolution */ |
469 |
int *xrp, *yrp; |
470 |
FILE *fp; |
471 |
{ |
472 |
char buf[64], *xndx, *yndx; |
473 |
register char *cp; |
474 |
register int ord; |
475 |
|
476 |
if (fgets(buf, sizeof(buf), fp) == NULL) |
477 |
return (-1); |
478 |
xndx = yndx = NULL; |
479 |
for (cp = buf + 1; *cp; cp++) |
480 |
if (*cp == 'X') |
481 |
xndx = cp; |
482 |
else if (*cp == 'Y') |
483 |
yndx = cp; |
484 |
if (xndx == NULL || yndx == NULL) |
485 |
return (-1); |
486 |
ord = 0; |
487 |
if (xndx > yndx) |
488 |
ord |= YMAJOR; |
489 |
if (xndx[-1] == '-') |
490 |
ord |= XDECR; |
491 |
if (yndx[-1] == '-') |
492 |
ord |= YDECR; |
493 |
if ((*xrp = atoi(xndx + 1)) <= 0) |
494 |
return (-1); |
495 |
if ((*yrp = atoi(yndx + 1)) <= 0) |
496 |
return (-1); |
497 |
return(ord); |
498 |
} |
499 |
|
500 |
|
501 |
fputresolu(ord, xres, yres, fp) /* put x and y resolution */ |
502 |
register int ord; |
503 |
int xres, yres; |
504 |
FILE *fp; |
505 |
{ |
506 |
if (ord & YMAJOR) |
507 |
fprintf(fp, "%cY %d %cX %d\n", ord & YDECR ? '-' : '+', yres, |
508 |
ord & XDECR ? '-' : '+', xres); |
509 |
else |
510 |
fprintf(fp, "%cX %d %cY %d\n", ord & XDECR ? '-' : '+', xres, |
511 |
ord & YDECR ? '-' : '+', yres); |
512 |
} |
513 |
|
514 |
|
515 |
fwritescan(scanline, len, fp) /* write out a scanline */ |
516 |
register COLOR *scanline; |
517 |
int len; |
518 |
register FILE *fp; |
519 |
{ |
520 |
int rept; |
521 |
COLR lastcolr, thiscolr; |
522 |
|
523 |
lastcolr[RED] = lastcolr[GRN] = lastcolr[BLU] = 1; |
524 |
lastcolr[EXP] = 0; |
525 |
rept = 0; |
526 |
while (len > 0) { |
527 |
setcolr(thiscolr, scanline[0][RED], |
528 |
scanline[0][GRN], |
529 |
scanline[0][BLU]); |
530 |
if (thiscolr[EXP] == lastcolr[EXP] && |
531 |
thiscolr[RED] == lastcolr[RED] && |
532 |
thiscolr[GRN] == lastcolr[GRN] && |
533 |
thiscolr[BLU] == lastcolr[BLU]) |
534 |
rept++; |
535 |
else { |
536 |
while (rept) { /* write out count */ |
537 |
putc(1, fp); |
538 |
putc(1, fp); |
539 |
putc(1, fp); |
540 |
putc(rept & 255, fp); |
541 |
rept >>= 8; |
542 |
} |
543 |
putc(thiscolr[RED], fp); /* new color */ |
544 |
putc(thiscolr[GRN], fp); |
545 |
putc(thiscolr[BLU], fp); |
546 |
putc(thiscolr[EXP], fp); |
547 |
copycolr(lastcolr, thiscolr); |
548 |
rept = 0; |
549 |
} |
550 |
scanline++; |
551 |
len--; |
552 |
} |
553 |
while (rept) { /* write out count */ |
554 |
putc(1, fp); |
555 |
putc(1, fp); |
556 |
putc(1, fp); |
557 |
putc(rept & 255, fp); |
558 |
rept >>= 8; |
559 |
} |
560 |
return (ferror(fp) ? -1 : 0); |
561 |
} |
562 |
|
563 |
static setcolr(clr, r, g, b) /* assign a short color value */ |
564 |
register COLR clr; |
565 |
double r, g, b; |
566 |
{ |
567 |
double d, frexp(); |
568 |
int e; |
569 |
|
570 |
d = r > g ? r : g; |
571 |
if (b > d) |
572 |
d = b; |
573 |
if (d <= 1e-32) { |
574 |
clr[RED] = clr[GRN] = clr[BLU] = 0; |
575 |
clr[EXP] = 0; |
576 |
return; |
577 |
} |
578 |
d = frexp(d, &e) * 256.0 / d; |
579 |
|
580 |
clr[RED] = (byte)(r * d); |
581 |
clr[GRN] = (byte)(g * d); |
582 |
clr[BLU] = (byte)(b * d); |
583 |
clr[EXP] = (byte)(e + COLXS); |
584 |
} |
585 |
|
586 |
/*** radiance_io.c ***/ |