home *** CD-ROM | disk | FTP | other *** search
/ Resource Library: Graphics / graphics-16000.iso / msdos / raytrace / rayshade / src / image.c < prev    next >
C/C++ Source or Header  |  1992-05-04  |  8KB  |  364 lines

  1. /*
  2.  * image.c
  3.  *
  4.  * Copyright (C) 1989, 1991, Rod G. Bogart, Craig E. Kolb
  5.  * All rights reserved.
  6.  *
  7.  * This software may be freely copied, modified, and redistributed
  8.  * provided that this copyright notice is preserved on all copies.
  9.  *
  10.  * You may not distribute this software, in whole or in part, as part of
  11.  * any commercial product without the express consent of the authors.
  12.  *
  13.  * There is no warranty or other guarantee of fitness of this software
  14.  * for any purpose.  It is provided solely "as is".
  15.  *
  16.  * $Id: image.c,v 4.0 91/07/17 14:33:29 kolb Exp Locker: kolb $
  17.  *
  18.  * $Log:    image.c,v $
  19.  * Revision 4.0  91/07/17  14:33:29  kolb
  20.  * Initial version.
  21.  *
  22.  */
  23. #include <stdio.h>
  24. #include "common.h"
  25. #include "image.h"
  26.  
  27. #if defined(__WATCOMC__) || defined(__BORLANDC__)
  28. #include <io.h>
  29. #include <fcntl.h>
  30. #undef URT
  31. #define TARGA
  32. #endif
  33.  
  34. #ifdef URT
  35. #include "rle.h"
  36. #endif
  37.  
  38. Image *image_list = NULL;        /* Linked list of images */
  39.  
  40. Image *
  41. ImageCreate(filename)
  42. char *filename;
  43. {
  44.     Image *new;
  45.  
  46.     new = (Image *)RayMalloc(sizeof(Image));
  47.     new->filename = strsave(filename);
  48.     new->width = 0;
  49.     new->height = 0;
  50.     new->chan = 0;
  51.     new->data = NULL;
  52.     new->next = image_list;
  53.     image_list = new;
  54.     return new;
  55. }
  56.  
  57. Image *
  58. ImageFind(name)
  59. char *name;
  60. {
  61.     Image *im;
  62.  
  63.     for (im = image_list; im; im = im->next) {
  64.         if (strcmp(im->filename, name) == 0)
  65.             return im;
  66.     }
  67.  
  68.     return (Image *)NULL;
  69. }
  70.  
  71. #ifdef URT
  72. Image *
  73. ImageRead(filename)
  74. char *filename;
  75. {
  76.     FILE *fp;
  77.     int i, y, chan;
  78.     rle_hdr in_hdr;
  79.     Image *image;
  80.     rle_pixel **inrows;
  81.  
  82.     /*
  83.      * See if image has been read before.
  84.      */
  85.     image = ImageFind(filename);
  86.     if (image)
  87.         return image;
  88.  
  89. #if defined(__WATCOMC__) || defined(__BORLANDC__)
  90.     fp = fopen(filename, "rb");
  91. #else
  92.     fp = fopen(filename, "r");
  93. #endif
  94.     if (fp == (FILE *)NULL) {
  95.         RLerror(RL_ABORT, "Cannot open RLE file %s.\n",filename);
  96.         return (Image *)NULL;
  97.     }
  98.  
  99.     in_hdr.rle_file = fp;
  100.    
  101.     /* Try to open the RLE file */
  102.     if (rle_get_setup(&in_hdr) < 0) {
  103.         RLerror(RL_ABORT, "Error reading header of %s\n", filename);
  104.         return (Image *)NULL;
  105.     }
  106.  
  107.     /*
  108.      * Read new image
  109.      */
  110.     image = ImageCreate(filename);
  111.  
  112.     in_hdr.xmax -= in_hdr.xmin;
  113.     in_hdr.xmin = 0;
  114.     image->width = in_hdr.xmax + 1;
  115.     image->height = in_hdr.ymax - in_hdr.ymin + 1;
  116.     image->chan = in_hdr.ncolors;
  117.     image->has_alpha = in_hdr.alpha ? 1 : 0;
  118.     image->totalchan = image->chan + image->has_alpha;
  119.     image->chansize = image->width * image->height;
  120.  
  121.     image->data = (unsigned char *) RayMalloc(
  122.         image->chansize * image->totalchan * sizeof(unsigned char));
  123.  
  124.     /*
  125.      * Allocate array of pointers to pass to rle_getrow.
  126.      */
  127.     inrows = (rle_pixel **)RayMalloc(image->totalchan *
  128.             sizeof(rle_pixel *));
  129.     /*
  130.      * Set inrows to point to appropriate initial location in image.
  131.      */
  132.     inrows[0] = (rle_pixel *)image->data;
  133.     for (i = 1; i < image->totalchan; i++)
  134.         inrows[i] = inrows[i-1] + image->chansize;
  135.     if (image->has_alpha)
  136.         /* Alpha channel lives in channel -1 */
  137.         inrows++;
  138.  
  139.     /* Read the image */
  140.     for ( y = 0; y < image->height; y++ ) {
  141.         rle_getrow( &in_hdr, inrows );
  142.         /*
  143.          * Update inrows to point to next scanline for
  144.          * each channel.
  145.          */
  146.         for (i = 0; i < image->chan; i++)
  147.             inrows[i] += image->width;
  148.         if (image->has_alpha)
  149.             inrows[-1] += image->width;
  150.     }
  151.  
  152.     (void)fclose(fp);
  153.     return image;
  154. }
  155.  
  156. #else /* !URT */
  157.  
  158. #ifdef TARGA
  159.  
  160. Image *
  161. ImageRead(filename)
  162. char *filename;
  163. {
  164.     FILE *fp;
  165.     unsigned char commbuf[256],fbuf[20];
  166.     Image *image;
  167.     int y, x;
  168.     unsigned char *rbuf, *gbuf, *bbuf;
  169.  
  170.     image = ImageFind(filename);
  171.     if (image)
  172.         return image;
  173.  
  174. #if defined(__WATCOMC__) || defined(__BORLANDC__)
  175.     fp = fopen(filename, "rb");
  176. #else
  177.     fp = fopen(filename, "r");
  178. #endif
  179.     if (fp == (FILE *)NULL) {
  180.         RLerror(RL_ABORT, "Cannot open image file %s.\n",filename);
  181.         return (Image *)NULL;
  182.     }
  183.  
  184.     image = ImageCreate(filename);
  185.     /*
  186.      * Read image header.
  187.      */
  188.     if (fread(fbuf, 18, 1, fp) != 1) {
  189.         RLerror(RL_ABORT, "Cannot read header of image file %s.\n",
  190.             filename);
  191.         fclose(fp);
  192.         return (Image *)NULL;
  193.     }
  194.  
  195.     image->width=fbuf[12]+fbuf[13]*256;
  196.     image->height=fbuf[14]+fbuf[15]*256;
  197.  
  198.     if ((fbuf[16]!=24) || (fbuf[7] >> 3)!=0) {
  199.         fclose(fp);
  200.         return (Image *)NULL;
  201.     }
  202.  
  203.     if (fbuf[0]!=0) {
  204.         if (fread(commbuf,1,fbuf[0],fp)!=fbuf[0]) {
  205.             fclose(fp);
  206.             return (Image *)NULL;
  207.             }
  208.     }
  209.  
  210.     /*
  211.      * Generic image files always have 3 channels, no alpha.
  212.      */
  213.     image->chan = image->totalchan = 3;
  214.     image->has_alpha = 0;
  215.     image->chansize = image->width * image->height;
  216.  
  217.     image->data = (unsigned char *) RayMalloc(
  218.         image->chansize * image->totalchan * sizeof(unsigned char));
  219.  
  220.     rbuf = image->data;
  221.     gbuf = &image->data[image->chansize];
  222.     bbuf = &image->data[image->chansize+image->chansize];
  223.     for (y = 0; y < image->height; y++ ) {
  224.         for (x = 0; x < image->width; x++) {
  225.             *(bbuf++) = getc(fp);
  226.             *(gbuf++) = getc(fp);
  227.             *(rbuf++) = getc(fp);
  228.             if (feof(fp)) {
  229.                 RLerror(RL_ABORT,
  230.                 "Error reading image %s\n",filename);
  231.                 fclose(fp);
  232.                 return (Image *)NULL;
  233.             }
  234.         }
  235.     }
  236.  
  237.     (void)fclose(fp);
  238.     return image;
  239. }
  240.  
  241. #else
  242.  
  243. Image *
  244. ImageRead(filename)
  245. char *filename;
  246. {
  247.     FILE *fp;
  248.     char buf[80];
  249.     Image *image;
  250.     int y, x;
  251.     unsigned char *rbuf, *gbuf, *bbuf;
  252.  
  253.     image = ImageFind(filename);
  254.     if (image)
  255.         return image;
  256.  
  257. #if defined(__WATCOMC__) || defined(__BORLANDC__)
  258.     fp = fopen(filename, "rb");
  259. #else
  260.     fp = fopen(filename, "r");
  261. #endif
  262.     if (fp == (FILE *)NULL) {
  263.         RLerror(RL_ABORT, "Cannot open image file %s.\n",filename);
  264.         return (Image *)NULL;
  265.     }
  266.  
  267.     image = ImageCreate(filename);
  268.     /*
  269.      * Read image header.
  270.      */
  271.     if (fgets(buf, 80, fp) == (char *)NULL ||
  272.         sscanf(buf, "%d %d\n", &image->width, &image->height) != 2) {
  273.         RLerror(RL_ABORT, "Cannot read header of image file %s.\n",
  274.             filename);
  275.         fclose(fp);
  276.         return (Image *)NULL;
  277.     }
  278.     /*
  279.      * Generic image files always have 3 channels, no alpha.
  280.      */
  281.     image->chan = image->totalchan = 3;
  282.     image->has_alpha = 0;
  283.     image->chansize = image->width * image->height;
  284.  
  285.     image->data = (unsigned char *) RayMalloc(
  286.         image->chansize * image->totalchan * sizeof(unsigned char));
  287.  
  288.     rbuf = image->data;
  289.     gbuf = &image->data[image->chansize];
  290.     bbuf = &image->data[image->chansize+image->chansize];
  291.     for (y = 0; y < image->height; y++ ) {
  292.         for (x = 0; x < image->width; x++) {
  293.             *(rbuf++) = getc(fp);
  294.             *(gbuf++) = getc(fp);
  295.             *(bbuf++) = getc(fp);
  296.             if (feof(fp)) {
  297.                 RLerror(RL_ABORT,
  298.                 "Error reading image %s\n",filename);
  299.                 fclose(fp);
  300.                 return (Image *)NULL;
  301.             }
  302.         }
  303.     }
  304.  
  305.     (void)fclose(fp);
  306.     return image;
  307. }
  308.  
  309. #endif
  310.  
  311. #endif
  312.  
  313. void
  314. ImageIndex(img, ix, iy, fx, fy, smooth, outval)
  315. Image *img;
  316. int ix, iy, smooth;
  317. Float fx, fy;
  318. Float outval[4];
  319. {
  320.     int xplus, yplus, chan, offset;
  321.     Float x0y0, x1y0, x0y1, x1y1;
  322.     unsigned char *data;
  323.  
  324.     if (smooth) {
  325.         /*
  326.          * bi-linear interp of four pixels.  Note this blends
  327.          * the top with the bottom, and the left with the right.
  328.          */
  329.         if (ix == img->width - 1)
  330.             xplus = 1 - img->width;
  331.         else 
  332.             xplus = 1;
  333.         if (iy == img->height - 1)
  334.             yplus = (1 - img->height) * img->width;
  335.         else
  336.             yplus = img->width;
  337.         data = img->data;
  338.         /* compute offset into first channel */
  339.         offset = ix + iy * img->width;
  340.         for (chan = 0; chan < img->totalchan; chan++) {
  341.             x0y0 = (Float)data[offset] / 255.0;
  342.             x1y0 = (Float)data[offset+xplus] / 255.0;
  343.             x0y1 = (Float)data[offset+yplus] / 255.0;
  344.             x1y1 = (Float)data[offset+xplus+yplus]/255.0;
  345.             outval[chan] = (x0y0*(1.0-fx)*(1.0-fy) +
  346.                     x1y0*(fx)*(1.0-fy) +
  347.                     x0y1*(1.0-fx)*(fy) +  x1y1*(fx)*(fy));
  348.             /* Make offset point to next channel */
  349.             offset += img->chansize;
  350.         }
  351.     } else {
  352.         /*
  353.          * Hard edged image pixels (rectangles)
  354.          * Compute offset into first channel
  355.          */
  356.         offset = ix + iy * img->width;
  357.         for (chan = 0; chan < img->totalchan; chan++) {
  358.             outval[chan] = (Float)img->data[offset]/255.0;
  359.             /* Make offset point to next channel */
  360.             offset += img->chansize;
  361.         }
  362.     }
  363. }
  364.