home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Raytrace & Morphing / SOS-RAYTRACE.ISO / programm / source / radsrc22 / src / px / ra_xim.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-09-25  |  19.1 KB  |  588 lines

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