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

# User Rev Content
1 greg 3.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 ***/