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