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, 10 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

# User Rev Content
1 greg 3.1 #ifndef lint
2 schorsch 3.2 static const char RCSid[] = "$Id: ra_xim.c,v 3.1 2003/02/22 02:07:28 greg Exp $";
3 greg 3.1 #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 schorsch 3.2 "$Header: /cvs/radiance/ray/src/px/ra_xim.c,v 3.1 2003/02/22 02:07:28 greg Exp $";
32 greg 3.1 #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 schorsch 3.2 * $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 greg 3.1 * 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 schorsch 3.2 memset(xim, '\0', sizeof(XimImage));
239 greg 3.1 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 ***/