/* *******************************************************************/
/* Author      : Josh Grant
   Date        : May 6th, 2001
   Class       : Image
   Version     : 1.0
   Description : Create images of varying dimensions with either an XY
                 (Rectangular) or an ST (Spherical) coordinate system.  Also
		 choose between a black and white (BW) or red,green,blue
		 (RGB) color system.  The class provides funtions to set
		 points within the image domain to a color.  Colors are
		 stored as floats in the range [0.0, 1.0], as well as
		 unsigned char in the range [0, 255].  However, when
		 modifying a color only the float values are used.  The
		 unsigned char values are only used for saving an image to
		 file.  Also pixels are not directly modified with this
		 class.  Points within the image domain are specified and
		 set.  This makes updating textures in a 3D more easy.

		 An additional funtion called drawDot() will draw a dot with
		 a specified radius and filter.  The filters available are
		 BOX, TENT, QUADRATIC, CUBIC, and QUARTIC.  The drawDot()
		 function will draw the dot on either coordinate system.

   Public Funtions :
     Image (int s[2], color_t c, coord_t cs)
       - The only way to instantiate an Image object is to use this
         constructor.  The image size, color system, and the type of
	 coordinate system must all be provided here.
	 
     ~Image ()
     
     void clear ()
       - clears the image to black by setting all the values in the arrays to
         zero.
	 
     void drawDot (float p[3], float c[3], float r, filter_t f)
       - A dot is drawn with radius r and filter f at point p with color c.
       
     unsigned char* getValue (int *s, int &nc)
       - Returns the pixels in the image as an array of unsigned chars. The s
         and nc arguments are filled in with the dimensions of the image and
	 the number of components in the  image;  the  number of bytes in the
	 array returned will be s[0]*s[1]*nc.

     void setBackground (float c[3]);
       - Sets the background of the image to color c.

     void setPoint (float p[3], float c[3]);
       - Sets a point p with color c on the image.

     void writePPM (char *filename)
       - rites the current state of the image to a binary formatted PPM file
         with name filename.  If filename is set to NULL, then the file is
	 output to stdout.

   Example Instantiation:
     // The below code will create an RGB image of size 200x100 pixels.
     // Then a blue dot with radius 0.75 units will be drawn using a TENT
     // filter.  Last the image is written to a file called "bluedot.ppm"
     Image *image;
     int size[2]    = {200, 100};
     float blue[3]  = {0.0, 0.0, 1.0};
     float point[3] = {0.0, 0.0, 0.0};

     image = new Image(size, Image::RGB, Image::RECTANGULAR);

     // Since the number of pixels in the x direction is twice that in the
     // y direction, the bounds field should be updated so the dot isn't
     // elongated in the x direction.
     image->bounds[0] = -2.0;  // Minimum x value
     image->bounds[1] = -1.0;  // Minimum y value
     image->bounds[2] =  2.0;  // Maximum x value
     image->bounds[3] =  1.0;  // Maximum y value

     image->drawDot(point, blue, 0.75, Image::TENT);
     image->writePPM("bluedot.ppm");
*/
/* *******************************************************************/

#ifndef _IMAGE_
#define _IMAGE_

#include <stdio.h>
#include <math.h>
#include <string.h>
#include <iostream.h>

class Image {
public:
  enum color_t {
    BW,
    RGB
  };
  
  enum coord_t {
    RECTANGULAR,
    SPHERICAL
  };

  enum filter_t {
    BOX,
    TENT,
    QUADRATIC,
    CUBIC,
    QUARTIC
  };

  float             bounds[4];

                    Image         (int s[2], color_t c, coord_t cs);
                    ~Image        ();
  
  void              clear         ();
  void              drawDot       (float p[3], float c[3], float r,
				   filter_t f);
  unsigned char *   getValue      (int *s, int &nc);
  void              setBackground (float c[3]);
  void              setPoint      (float p[3], float c[3]);
  void              writePPM      (char *filename);
  

private:
  unsigned char *   bytes;
  float *           colors;
  coord_t           coordSystem;
  int               numComponents;
  int               size[2];
  float *           weights;

  void              drawSTDot     (float p[3], float c[3], float r,
				   filter_t f);
  void              drawXYDot     (float p[3], float c[3], float r,
				   filter_t f);
  float             filterVal     (float dist, float radius, filter_t f);
  void              getSTCoords   (float p[3], float &s, float &t);
  int               getSTIndex    (float s, float t);
  int               getXYIndex    (float x, float y);
  void              setPixel      (int index, float c[3], float w);

  /* Filter Functions */
  float             box           (float dist, float rad);
  float             tent          (float dist, float rad);
  float             quadratic     (float dist, float rad);
  float             cubic         (float dist, float rad);
  float             quartic       (float dist, float rad);

};

#endif // _IMAGE_
