ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ra_xim.c
Revision: 3.2
Committed: Mon Jun 30 14:59:12 2003 UTC (20 years, 9 months ago) by schorsch
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R6P1, rad3R6
Changes since 3.1: +6 -10 lines
Log Message:
Replaced most outdated BSD function calls with their posix equivalents, and cleaned up a few other platform dependencies.

File Contents

# Content
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 ***/