ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ra_xim.c
Revision: 3.1
Committed: Sat Feb 22 02:07:28 2003 UTC (21 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R5
Log Message:
Changes and check-in for 3.5 release
Includes new source files and modifications not recorded for many years
See ray/doc/notes/ReleaseNotes for notes between 3.1 and 3.5 release

File Contents

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