home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 3 / Amiga Tools 3.iso / grafik / raytracing / rayshade-4.0.6.3 / libray / libimage / image.c next >
Encoding:
C/C++ Source or Header  |  1994-08-09  |  5.8 KB  |  266 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.  * image.c,v 4.1 1994/08/09 07:56:18 explorer Exp
  17.  *
  18.  * image.c,v
  19.  * Revision 4.1  1994/08/09  07:56:18  explorer
  20.  * Bump version to 4.1
  21.  *
  22.  * Revision 1.1.1.1  1994/08/08  04:52:03  explorer
  23.  * Initial import.  This is a prerelease of 4.0.6enh3, or 4.1 possibly.
  24.  *
  25.  * Revision 4.0  91/07/17  14:33:29  kolb
  26.  * Initial version.
  27.  * 
  28.  */
  29. #include <stdio.h>
  30. #include "libcommon/common.h"
  31. #include "image.h"
  32. #ifdef URT
  33. #include "rle.h"
  34. #endif
  35.  
  36. Image *image_list = NULL;        /* Linked list of images */
  37.  
  38. Image *
  39. ImageCreate(filename)
  40. char *filename;
  41. {
  42.     Image *new;
  43.  
  44.     new = (Image *)Malloc(sizeof(Image));
  45.     new->filename = strsave(filename);
  46.     new->width = 0;
  47.     new->height = 0;
  48.     new->chan = 0;
  49.     new->data = NULL;
  50.     new->next = image_list;
  51.     image_list = new;
  52.     return new;
  53. }
  54.  
  55. Image *
  56. ImageFind(name)
  57. char *name;
  58. {
  59.     Image *im;
  60.  
  61.     for (im = image_list; im; im = im->next) {
  62.         if (strcmp(im->filename, name) == 0)
  63.             return im;
  64.     }
  65.  
  66.     return (Image *)NULL;
  67. }
  68.  
  69. #ifdef URT
  70. Image *
  71. ImageRead(filename)
  72. char *filename;
  73. {
  74.     FILE *fp;
  75.     int i, y, chan;
  76.     rle_hdr in_hdr;
  77.     Image *image;
  78.     rle_pixel **inrows;
  79.  
  80.     /*
  81.      * See if image has been read before.
  82.      */
  83.     image = ImageFind(filename);
  84.     if (image)
  85.         return image;
  86.  
  87.     fp = fopen(filename, "r");
  88.     if (fp == (FILE *)NULL) {
  89.         RLerror(RL_ABORT, "Cannot open RLE file %s.\n",filename);
  90.         return (Image *)NULL;
  91.     }
  92.  
  93.     in_hdr.rle_file = fp;
  94.    
  95.     /* Try to open the RLE file */
  96.     if (rle_get_setup(&in_hdr) < 0) {
  97.         RLerror(RL_ABORT, "Error reading header of %s\n", filename);
  98.         return (Image *)NULL;
  99.     }
  100.  
  101.     /*
  102.      * Read new image
  103.      */
  104.     image = ImageCreate(filename);
  105.  
  106.     in_hdr.xmax -= in_hdr.xmin;
  107.     in_hdr.xmin = 0;
  108.     image->width = in_hdr.xmax + 1;
  109.     image->height = in_hdr.ymax - in_hdr.ymin + 1;
  110.     image->chan = in_hdr.ncolors;
  111.     image->has_alpha = in_hdr.alpha ? 1 : 0;
  112.     image->totalchan = image->chan + image->has_alpha;
  113.     image->chansize = image->width * image->height;
  114.  
  115.     image->data = (unsigned char *) Malloc(
  116.         image->chansize * image->totalchan * sizeof(unsigned char));
  117.  
  118.     /*
  119.      * Allocate array of pointers to pass to rle_getrow.
  120.      */
  121.     inrows = (rle_pixel **)Malloc(image->totalchan *
  122.             sizeof(rle_pixel *));
  123.     /*
  124.      * Set inrows to point to appropriate initial location in image.
  125.      */
  126.     inrows[0] = (rle_pixel *)image->data;
  127.     for (i = 1; i < image->totalchan; i++)
  128.         inrows[i] = inrows[i-1] + image->chansize;
  129.     if (image->has_alpha)
  130.         /* Alpha channel lives in channel -1 */
  131.         inrows++;
  132.  
  133.     /* Read the image */
  134.     for ( y = 0; y < image->height; y++ ) {
  135.         rle_getrow( &in_hdr, inrows );
  136.         /*
  137.          * Update inrows to point to next scanline for
  138.          * each channel.
  139.          */
  140.         for (i = 0; i < image->chan; i++)
  141.             inrows[i] += image->width;
  142.         if (image->has_alpha)
  143.             inrows[-1] += image->width;
  144.     }
  145.  
  146.     (void)fclose(fp);
  147.     return image;
  148. }
  149.  
  150. #else /* !URT */
  151.  
  152. Image *
  153. ImageRead(filename)
  154. char *filename;
  155. {
  156.     FILE *fp;
  157.     char buf[80];
  158.     Image *image;
  159.     int y, x;
  160.     unsigned char *rbuf, *gbuf, *bbuf;
  161.  
  162.     image = ImageFind(filename);
  163.     if (image)
  164.         return image;
  165.  
  166.     fp = fopen(filename, "r");
  167.     if (fp == (FILE *)NULL) {
  168.         RLerror(RL_ABORT, "Cannot open image file %s.\n",filename);
  169.         return (Image *)NULL;
  170.     }
  171.  
  172.     image = ImageCreate(filename);
  173.     /*
  174.      * Read image header.
  175.      */
  176.     if (fgets(buf, 100, fp) == (char *)NULL ||
  177.         sscanf(buf, "%d %d\n", &image->width, &image->height) != 2) {
  178.         RLerror(RL_ABORT, "Cannot read header of image file %s.\n",
  179.             filename);
  180.         fclose(fp);
  181.         return (Image *)NULL;
  182.     }
  183.     /*
  184.      * Generic image files always have 3 channels, no alpha.
  185.      */
  186.     image->chan = image->totalchan = 3;
  187.     image->has_alpha = 0;
  188.     image->chansize = image->width * image->height;
  189.  
  190.     image->data = (unsigned char *) Malloc(
  191.         image->chansize * image->totalchan * sizeof(unsigned char));
  192.  
  193.     rbuf = image->data;
  194.     gbuf = &image->data[image->chansize];
  195.     bbuf = &image->data[image->chansize+image->chansize];
  196.     for (y = 0; y < image->height; y++ ) {
  197.         for (x = 0; x < image->width; x++) {
  198.             *(rbuf++) = getc(fp);
  199.             *(gbuf++) = getc(fp);
  200.             *(bbuf++) = getc(fp);
  201.             if (feof(fp)) {
  202.                 RLerror(RL_ABORT,
  203.                 "Error reading image %s\n",filename);
  204.                 fclose(fp);
  205.                 return (Image *)NULL;
  206.             }
  207.         }
  208.     }
  209.  
  210.     (void)fclose(fp);
  211.     return image;
  212. }
  213. #endif
  214.  
  215. void
  216. ImageIndex(img, ix, iy, fx, fy, smooth, outval)
  217. Image *img;
  218. int ix, iy, smooth;
  219. Float fx, fy;
  220. Float outval[4];
  221. {
  222.     int xplus, yplus, chan, offset;
  223.     Float x0y0, x1y0, x0y1, x1y1;
  224.     unsigned char *data;
  225.  
  226.     if (smooth) {
  227.         /*
  228.          * bi-linear interp of four pixels.  Note this blends
  229.          * the top with the bottom, and the left with the right.
  230.          */
  231.         if (ix == img->width - 1)
  232.             xplus = 1 - img->width;
  233.         else 
  234.             xplus = 1;
  235.         if (iy == img->height - 1)
  236.             yplus = (1 - img->height) * img->width;
  237.         else
  238.             yplus = img->width;
  239.         data = img->data;
  240.         /* compute offset into first channel */
  241.         offset = ix + iy * img->width;
  242.         for (chan = 0; chan < img->totalchan; chan++) {
  243.             x0y0 = (Float)data[offset] / 255.0;
  244.             x1y0 = (Float)data[offset+xplus] / 255.0;
  245.             x0y1 = (Float)data[offset+yplus] / 255.0;
  246.             x1y1 = (Float)data[offset+xplus+yplus]/255.0;
  247.             outval[chan] = (x0y0*(1.0-fx)*(1.0-fy) +
  248.                     x1y0*(fx)*(1.0-fy) +
  249.                     x0y1*(1.0-fx)*(fy) +  x1y1*(fx)*(fy));
  250.             /* Make offset point to next channel */
  251.             offset += img->chansize;
  252.         }
  253.     } else {
  254.         /*
  255.          * Hard edged image pixels (rectangles)
  256.          * Compute offset into first channel
  257.          */
  258.         offset = ix + iy * img->width;
  259.         for (chan = 0; chan < img->totalchan; chan++) {
  260.             outval[chan] = (Float)img->data[offset]/255.0;
  261.             /* Make offset point to next channel */
  262.             offset += img->chansize;
  263.         }
  264.     }
  265. }
  266.