/*
 *
 * $Header: /usr/u/wjr/src/ADT/RCS/image.h,v 1.14 1992/08/20 21:09:19 rucklidg Exp $
 *
 * Copyright (c) 1990, 1991, 1992 Cornell University.  All Rights Reserved.  
 *  
 * Copyright (c) 1991, 1992 Xerox Corporation.  All Rights Reserved.  
 *  
 * Use, reproduction, preparation of derivative works, and distribution
 * of this software is permitted.  Any copy of this software or of any
 * derivative work must include both the above copyright notices of
 * Cornell University and Xerox Corporation and this paragraph.  Any
 * distribution of this software or derivative works must comply with all
 * applicable United States export control laws.  This software is made
 * available AS IS, and XEROX CORPORATION DISCLAIMS ALL WARRANTIES,
 * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
 * AND NOTWITHSTANDING ANY OTHER PROVISION CONTAINED HEREIN, ANY
 * LIABILITY FOR DAMAGES RESULTING FROM THE SOFTWARE OR ITS USE IS
 * EXPRESSLY DISCLAIMED, WHETHER ARISING IN CONTRACT, TORT (INCLUDING
 * NEGLIGENCE) OR STRICT LIABILITY, EVEN IF XEROX CORPORATION IS ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGES.
 */
/*
 * Header file for image maintenance routines
 */

#ifndef IMAGE_H
#define IMAGE_H

/* For FILE */
#include <stdio.h>
#include "strings.h"
#include "misc.h"

#ifdef	IMAGE_CHECKALL
/* Need eassert() and panic() */
#include "panic.h"
#endif

/* The number of colours per component (or total for gray images) */
#define	COLDEPTH	8
#define COLRNG		(1 << COLDEPTH)

typedef unsigned short ImageType;

/* The image types */
#define	IMAGE_GRAY	((ImageType) (1 <<  0))
#define	IMAGE_FLOAT	((ImageType) (1 <<  1))
#define	IMAGE_RGB	((ImageType) (1 <<  2))
#define	IMAGE_DOUBLE	((ImageType) (1 <<  3))
#define	IMAGE_BINARY	((ImageType) (1 <<  4))
#define	IMAGE_LONG	((ImageType) (1 <<  5))
#define	IMAGE_PTR	((ImageType) (1 <<  6))
#define	IMAGE_SHORT	((ImageType) (1 <<  7))
#define IMAGE_HSV       ((ImageType) (1 <<  8))
#define IMAGE_RGBF      ((ImageType) (1 <<  9))
#define IMAGE_STRUCT    ((ImageType) (1 << 10))

#define IMAGE_ANY       (IMAGE_GRAY   | IMAGE_FLOAT | IMAGE_RGB  | IMAGE_DOUBLE |      \
			 IMAGE_BINARY | IMAGE_LONG  | IMAGE_PTR  | IMAGE_SHORT  |      \
			 IMAGE_HSV    | IMAGE_RGBF  | IMAGE_STRUCT)


struct ImageHeader;

#define DEF_IMG(imgname, elemtype)                                                     \
  typedef elemtype * imgname ## PixPtr;                                                \
  typedef struct {                                                                     \
    elemtype **data;                                                                   \
    struct ImageHeader *header;                                                        \
    struct {void *ptr;} userdata;                                                      \
  } * imgname ## Image;

  DEF_IMG(Gray,     uchar);                  /* Several types of image */
  DEF_IMG(Float,    float);
  DEF_IMG(RGB,      RGB);
  DEF_IMG(Double,   double);
  DEF_IMG(Binary,   char);
  DEF_IMG(Long,     long);
  DEF_IMG(Ptr,      void *);
  DEF_IMG(Short,    short);
  DEF_IMG(HSV,      HSV);
  DEF_IMG(RGBFloat, RGBFloat);

  DEF_IMG(Any,    void);		     /* generic image */

#undef DEF_IMG

typedef struct ImageHeader {		     /* An invisible image header type */
  int width, height;
  int xbase, ybase;
  ImageType tag;
  short elemsize, headsize;
  AnyImage anyim;
  String docstring;
  boolean wrapped;
  void *Ximage;				     /* only x-stuff knows about this */
} ImageHeader;


extern boolean ImageAllowLoadConversion;


/* and some manipulation routines */
extern void *imLoad(ImageType types, char *filename);
extern void *imLoadF(ImageType types, FILE *inFile);

extern void im_Free_(void *im, ImageType type);
extern void *im_LoadInto_(void *im, ImageHeader *header, char *filename);
extern void *im_LoadFInto_(void *im, ImageHeader *header, FILE *inFile);
extern int im_Save_(void *im, ImageHeader *header, char *filename);
extern int im_SaveF_(void *im, ImageHeader *header, FILE *outFile);
extern void *im_Dup_(void *im, ImageHeader *header);
extern void *im_Copy_(void *im, ImageHeader *ih, void *dst, ImageHeader *dh);
extern void *im_Down_(void *im, ImageHeader *header, int dx, int dy);
extern void im_Init_(void *im, ImageHeader *header, void *val);
extern void im_SetOffset_(void *im, ImageHeader *header, int xbase, int ybase);
extern void im_ApplyV_(void *f, void *im, ImageHeader *header);
extern void im_Apply_(void *f, void *im, ImageHeader *header);
extern void *im_NewOrWrap_(ImageType type, int width, int height, int xbase, int ybase,
			   void *raw, int elemsize, int headsize, void *dupimg);
extern void im_MaxAndMin_(void *im, ImageHeader *header, void *max, void *min);
extern void im_MaxAndMinNoInf_(void *im, ImageHeader *header, void *maxp, void *minp);
extern void *im_Crop_(void *im, ImageHeader *header, int xbase, int ybase, int w, int h);
extern void *im_Scale_(void *im, ImageHeader *header, double scale);


/* and some useful routines -- some are purposely *not* lvalues */
#ifndef	IMAGE_CHECKALL
#define	imGetWidth(i)	({ (i)->header->width; })
#define	imGetHeight(i)	({ (i)->header->height; })
#define	imGetXBase(i)	({ (i)->header->xbase; })
#define	imGetYBase(i)	({ (i)->header->ybase; })
#define imGetType(i)	({ (i)->header->tag; })
#define imDocString(i)  ((i)->header->docstring)
#define imUserData(i)   ((i)->userdata)
#else
#define	imGetWidth(i)	({ assert((i) != NULL); (i)->header->width; })
#define	imGetHeight(i)	({ assert((i) != NULL); (i)->header->height; })
#define	imGetXBase(i)	({ assert((i) != NULL); (i)->header->xbase; })
#define	imGetYBase(i)	({ assert((i) != NULL); (i)->header->ybase; })
#define imGetType(i)	({ assert((i) != NULL); (i)->header->tag; })
#define imDocString(i)  (eassert((i) != NULL), ((i)->header->docstring))
#define imUserData(i)   (eassert((i) != NULL), ((i)->userdata))
#endif
			 
/* Some additions for Greg ... William, I know you'll loathe the first two */
#define imGetStore(i)      ({ &(imRef((i), imGetXBase(i), imGetYBase(i))); })
#define imGetStoreLen(i)   (imGetWidth(i) * imGetHeight(i))
#define imGetXMax(i)       (imGetXBase(i) + imGetWidth(i)  - 1)
#define imGetYMax(i)       (imGetYBase(i) + imGetHeight(i) - 1)
#define imAnyImage(i)      ((i) ? (i)->header->anyim : (AnyImage) NULL)

/* define a new structure image type */
#define imDefStructImage(IMGNAME, ELEMTYPE, USERDATA)                                  \
  typedef struct {                                                                     \
    ELEMTYPE **data;                                                                   \
    ImageHeader *header;                                                               \
    USERDATA userdata;                                                                 \
  } *IMGNAME

typedef struct {void *ptr;} StdImUserData;   /* standard image user data field */

#define imNewStruct(imtype, w, h)     imNewOffsetStruct(imtype, (w), (h), 0, 0)
#define imNewOffsetStruct(imtype, w, h, x, y)                                          \
     ({ imtype __i;                                                                    \
	(imtype) im_NewOrWrap_(IMAGE_STRUCT, (w), (h), (x), (y), NULL,                 \
		      sizeof(typeof(**(__i->data))), sizeof(typeof(*__i)), NULL);})


#define imNULL ((AnyImage) NULL)
		
/*
 * These macros are strange - they attempt to make imFree etc somewhat
 * polymorphic by figuring out, in a context where the type is known (at
 * compile-time), the type of the image and passing that in. If it was
 * not done this way, imFree etc would not be able to figure out what
 * sort of Image they had been passed (since the structures may not match).
 *
 * imFree has imGetType and so implicitly checks for (i) != NULL
 */

#define imFree(i)	   ({ if ((void *) (i) != (void *) NULL) {                     \
				 im_Free_((void *)(i), imGetType((i)));                \
			         (i) = (typeof (i)) NULL;}})

#define imNew(t, w, h)                 imNewOffset((t), (w), (h), 0, 0)
#define imNewOffset(t, w, h, x, y)     im_NewOrWrap_((t), (w), (h), (x), (y),          \
						     NULL, 0, 0, NULL)
#define imWrap(r, t, w, h)             imWrapOffset((r), (t), (w), (h), 0, 0)
#define imWrapOffset(r, t, w, h, x, y) im_NewOrWrap_((t), (w), (h), (x), (y),          \
						     (void *) (r), 0, 0, NULL)

#ifndef	IMAGE_CHECKALL
#define imLoadInto(i, n)   im_LoadInto_((void *)(i), ((i)->header), (n))
#define imLoadFInto(i, f)  im_LoadFInto_((void *)(i), ((i)->header), (f))
#define imSave(i, n)	   im_Save_((void *)(i), ((i)->header), (n))
#define imSaveF(i, f)	   im_SaveF_((void *)(i), ((i)->header), (f))
#define	imDup(i)	   im_Dup_((void *)(i), ((i)->header))
#define	imCopy(dst, i)	   im_Copy_((void *)(i), ((i)->header), (void *)(dst), ((dst)->header))
#define	imDown(i, dx, dy)  im_Down_((void *)(i), ((i)->header), (dx), (dy))
#define imInit(i, val)     ({ typeof (**((i)->data)) __value = (val);                    \
			      im_Init_((void *)(i), ((i)->header), (void *) &__value);})
#define imSetOffset(i, x, y) im_SetOffset_((void *)(i), ((i)->header), (x), (y))
#define imApplyV(func, i)   ({ typeof (**((i)->data))                                          \
			      (*__func)(typeof (**((i)->data)) v) = func; \
			      im_ApplyV_((void *) __func, (void *)(i), ((i)->header));})
#define imApply(func, i)   ({ void                                                     \
			      (*__func)(typeof (*((i)->data)) v, int x, int y) = func; \
			      im_Apply_((void *) __func, (void *)(i), ((i)->header));})
#define imMaxAndMin(i, max, min)   ({ typeof (**((i)->data)) __max, __min;             \
					im_MaxAndMin_((void *)(i), ((i)->header),      \
						      (void *)&__max, (void *)&__min); \
					(min) = (typeof (min)) __min;                  \
					(max) = (typeof (max)) __max;})
#define imMaxAndMinNoInf(i, max, min)   ({ typeof (**((i)->data)) __max, __min;        \
					im_MaxAndMinNoInf_((void *)(i), ((i)->header), \
						      (void *)&__max, (void *)&__min); \
					(min) = (typeof (min)) __min;                  \
					(max) = (typeof (max)) __max;})
#define imCrop(im, xb, yb, w, h) ((typeof (im)) im_Crop_((void *) (im), ((im)->header), \
							 (xb), (yb), (w), (h)))
#define imScale(im, sc) ((typeof (im)) im_Scale_((void *) (im), ((im)->header), (sc)))
#else
#define imLoadInto(i, n)   (eassert((i) != NULL),                                      \
			    (im_LoadInto_((void *)(i), ((i)->header), (n))))
#define imLoadFInto(i, f)  (eassert((i) != NULL),                                      \
			    (im_LoadFInto_((void *)(i), ((i)->header), (f))))
#define imSave(i, n)	   (eassert((i) != NULL),                                      \
			    (im_Save_((void *)(i), ((i)->header), (n))))
#define imSaveF(i, f)	   (eassert((i) != NULL),                                      \
			    (im_SaveF_((void *)(i), ((i)->header), (f))))
#define	imDup(i)	(eassert((i) != NULL), (im_Dup_((void *)(i), ((i)->header))))
#define	imCopy(dst, i)	(eassert((i) != NULL), (im_Copy_((void *)(i), ((i)->header), (void *)(dst), ((dst)->header))))
#define	imDown(i, dx, dy) (eassert((i) != NULL), (im_Down_((void *)(i), ((i)->header). (dx), (dy))))
#define imInit(i, val)  (eassert((i) != NULL),                                         \
			 ({ typeof (**((i)->data)) __value = (val);                    \
			    im_Init_((void *)(i), ((i)->header), (void *) &__value);}))
#define imSetOffset(i, x, y) (eassert((i) != NULL),                                    \
			    (im_SetOffset_((void *)(i), ((i)->header), (x), (y))))
#define imApplyV(func, i)   (eassert((i) != NULL), ({ typeof (**((i)->data))                              \
			      (*__func)(typeof (**((i)->data)) v) = func; \
			      im_ApplyV_((void *) __func, (void *)(i), ((i)->header));}))
#define imApply(func, i)   (eassert((i) != NULL), ({ void                              \
			      (*__func)(typeof (*((i)->data)) v, int x, int y) = func; \
			      im_Apply_((void *) __func, (void *)(i), ((i)->header));}))
#define imMaxAndMin(i, max, min)   (eassert((i) != NULL),                              \
				    ({ typeof (**((i)->data)) __max, __min;            \
					 im_MaxAndMin_((void *)(i), ((i)->header),     \
						       (void *)&__max, (void *)&__min); \
					 (min) = (typeof (min)) __min;                 \
					 (max) = (typeof (max)) __max;}))
#define imMaxAndMinNoInf(i, max, min)   (eassert((i) != NULL),                         \
				    ({ typeof (**((i)->data)) __max, __min;            \
					 im_MaxAndMinNoInf_((void *)(i), ((i)->header), \
						       (void *)&__max, (void *)&__min); \
					 (min) = (typeof (min)) __min;                 \
					 (max) = (typeof (max)) __max;}))
#define imCrop(im, xb, yb, w, h) ((typeof (im)) (eassert((im) != NULL),                \
						 im_Crop_((void *) (im), ((im)->header),\
							  (xb), (yb), (w), (h))))
#define imScale(im, sc) ((typeof (im)) (eassert((im) != NULL),                \
					im_Scale_((void *) (im), ((im)->header), (sc))))
#endif

#define  imBoundsCheck(i, x, y)    (imBoundsCheckX((i), (x))  &&                   \
                                    imBoundsCheckY((i), (y)))
#define  imBoundsCheckX(i, x)      (imBoundsCheckXMax((i), (x)) &&                 \
                                    imBoundsCheckXMin((i), (x)))
#define  imBoundsCheckY(i, y)      (imBoundsCheckYMax((i), (y)) &&                 \
                                    imBoundsCheckYMin((i), (y)))
#define  imBoundsCheckXMax(i, x)   ((x) <= imGetXMax((i)))
#define  imBoundsCheckXMin(i, x)   ((x) >= imGetXBase((i)))
#define  imBoundsCheckYMax(i, y)   ((y) <= imGetYMax((i)))
#define  imBoundsCheckYMin(i, y)   ((y) >= imGetYBase((i)))

/* and an access routine - gives an *lvalue* */
#ifndef	IMAGE_CHECKALL
#define	imRef(i, x, y)	(((i)->data)[(y)][(x)])
#else
static char __imPanicStr[100];
#define	imRef(i, x, y)	(eassert(i != NULL),                                       \
			 ((((x) < (i)->header->xbase) ||                           \
			   ((y) < (i)->header->ybase) ||                           \
			   ((x) >= (i)->header->xbase + (i)->header->width) ||     \
			   ((y) >= (i)->header->ybase + (i)->header->height))      \
			  ? ({sprintf(__imPanicStr,                                \
				      "image bounds check fail: "                  \
				      "%d <= %d < %d, %d <= %d < %d",              \
				      (i)->header->xbase,                          \
				      (x),                                         \
				      (i)->header->xbase + (i)->header->width,     \
				      (i)->header->ybase,                          \
				      (y),                                         \
				      (i)->header->ybase + (i)->header->height);   \
			       panic(__imPanicStr);}), ((i)->data[0][0])           \
			  : (((i)->data)[(y)][(x)])))
#endif





/* Here come macros for increased efficiency access */

#ifndef IMAGE_CHECKALL

#define imGetPixPtr(i, x, y) (&(imRef((i), (x), (y))))
#define imPtrRef(i, pp) (*(pp))
#define imPtrDup(i, pp) (pp)
#define imPtrUp(i, pp) ((pp) -= (i)->header->width)
#define imPtrDown(i, pp) ((pp) += (i)->header->width)
#define imPtrLeft(i, pp) ((pp)--)
#define imPtrRight(i, pp) ((pp)++)
#define imPtrEq(i, pp1, pp2) ((pp1) == (pp2))

#else

/* Check a pointer against bounds; eval expr if successful */
#define __IMPCHECK(i, pp, expr) (eassert((i) != NULL), ((((pp) < (&((i)->data[(i
)->header->ybase][(i)->header->xbase]))) || ((pp) > &((i)->data[(i)->header->yba
se+(int)(i)->header->height-1][(i)->header->xbase+(int)(i)->header->width-1]))) 
? (({ panic("PixPtr bounds check fail"); }), (expr)) : (expr)))

/* imRef is error-checked already */
#define imGetPixPtr(i, x, y) (&(imRef((i), (x), (y))))
#define imPtrRef(i, pp) __IMPCHECK((i), (pp), (*(pp)))
#define imPtrDup(i, pp) __IMPCHECK((i), (pp), (pp))
#define imPtrUp(i, pp) __IMPCHECK((i), (pp), ((pp) -= (i)->header->width))
#define imPtrDown(i, pp) __IMPCHECK((i), (pp), ((pp) += (i)->header->width))
#define imPtrLeft(i, pp) __IMPCHECK((i), (pp), ((pp)--))
#define imPtrRight(i, pp) __IMPCHECK((i), (pp), ((pp)++))
#define imPtrEq(i, pp1, pp2) __IMPCHECK((i), (pp1), __IMPCHECK((i), (pp2), ((pp1
) == (pp2))))

#endif



#endif



#if      0
/*
BEGIN DOCUMENTATION

image.h - Images
================
    
An image is just a rectangular array of some type (seven types are implemented here).

Exports:
     type GrayImage                 -- elemtype = uchar
     type FloatImage                -- elemtype = float
     type RGBImage                  -- elemtype = RGB = struct {uchar r, g, b;}
     type DoubleImage               -- elemtype = double
     type BinaryImage               -- elemtype = char
     type LongImage                 -- elemtype = long
     type PtrImage                  -- elemtype = void *
     type ShortImage                -- elemtype = short
     type RGBFloatImage             -- elemtype = RGBFloat = struct {float r, g, b;}
     type HSVImage                  -- elemtype = HSV = struct {float h, s, v;}
     type AnyImage                  -- elemtype = void

     constant ImageType IMAGE_GRAY
     constant ImageType IMAGE_FLOAT
     constant ImageType IMAGE_RGB
     constant ImageType IMAGE_DOUBLE
     constant ImageType IMAGE_BINARY
     constant ImageType IMAGE_LONG
     constant ImageType IMAGE_PTR
     constant ImageType IMAGE_SHORT
     constant ImageType IMAGE_RGBF
     constant ImageType IMAGE_HSV
     constant ImageType IMAGE_STRUCT
     
     void *imNew(ImageType type, int width, int height) - create
         a new image of the appropriate type. The pointer returned
         will be a GrayImage, FloatImage, RGBImage, DoubleImage, 
         BinaryImage or WhateverElseImage as appropriate.
                
     void *imNewOffset(ImageType type, int w, int h, int xbase, int ybase) -
         create a new image of the appropriate type 
         whose addressing begins at (xbase, ybase).
         imNew is equivalent to xbase = ybase = 0.

     void imFree(Image im) - free an image.

     Image imLoad(ImageType types, char *filename) - load an image from
         a file. TYPES is the bit-wise OR of any number of ImageTypes.
         The pointer returned will be to an image of one of the types
         specified, depending on the contents of the file.  The pointer
         may be cast to an AnyImage, its type determined with imGetType(),
         and then appropriately cast to the correct type.  On error,
         NULL will be returned.  The image's base will be (0,0). If the
         variable ImageAllowLoadConversion is non-zero, a conversion may be
         made.  These will automatically read gzipped images too.
            
     Image imLoadF(ImageType types, FILE *inFile) - load an image from a stream.

     Image imLoadInto(Image im, char *filename) - load from file into an image.

     Image imLoadFInto(Image im, FILE *infile) - load from streamm into an image.

     int imSave(Image im, char *filename) - save an image into a file.

        int imSaveF(Image im, FILE *outFile) - save an image to a stream.

        Image imDup(Image im) - duplicate an image -- create a new copy

     Image imCopy(dst, src) -- copy src image into dst image.  return dst.

     Image imDown(img, dx, dy) -- downsample image by dx in x and dy in y.
                                  creates a new image.

     void imInit(Image im, value) - initialize all elements of the image to value.
             Using macro hackery this actually works for any types, and is
             type checked.

     void imSetOffset(Image im, int xb, int yb) - set the x and y bases for
             an image to xb and yb.

     void imApply(void (*f)(ELTYPE *val, int x, int y), Image im) - apply the
             function f to each element of an image.  F takes a pointer to
             an image cell, and the x and y indices.

     Image imWrap(void *raw, ImageType type, int w, int h) - wrap an image
             structure around a raw pointer to storage representing an image
             of the specified type, and with the given width and height. The
             raw pointer should point to data laid out in row-major order.

     Image imWrapOffset(void *raw, ImageType type, int w, int h, int x0, int y0) -
             Same as imWrap() except specify an x and y base.

     void imMaxAndMin(Image im, max, min) - Determine the maximum and minimum
             values in the image, and assign them to MAX and MIN.  For RGB and
             HSV images, the result is the independent max/min for each component.

     void imMaxAndMinNoInf(Image im, max, min) - like above, but NaN and Inf values
             are ignored for types with floating-point element types.

     Image imCrop(Image im, int xb, int yb, int w, int h) - Copy the elements
             of the input image defined by xb, yb, w, and h into a new image
             and return it.  The area to copy need not be completely contained
             in the original image.

     String imDocString(Image im) - access the documentation string of an image.
             This string gets saved and loaded by imSave() and imLoad(), ...

     [???] imUserData(Image im) - access the user-data for an image.
             For all but Structure-Images, this is a structure containing a
             void *ptr, eg [???] = "struct {void *ptr;}".  Otherwise, it is
             the type specified as USERDATA to imDefStructImage().

     imGetStore(Image im) - return the raw pointer of an image, a pointer to
             the upper left pixel.  The data is stored in row major order.

     imGetStoreLen(Image im) - return the total size of the raw storage, eg. W*H.

     imDefStructImage(IMGNAME, ELEMTYPE, USERDATA) - Define a new struct image
             type, called IMGNAME, with pixels of type ELEMTYPE, and with
             userdata field of type USERDATA.  This is a declaration.
             You cant save and load struct-images, yet.

     Struct-Image imNewStruct(IMGNAME, w, h) - like imNew(), but takes the
             typename, as given in imDefStructImage() to allocate a struct-image

     Struct-Image imNewOffsetStruct(IMGNAME, w, h, xb, yb) - imNewOffset() for
             struct-images.

     int imGetWidth(Image im) - get the width of an image.

     int imGetHeight(Image im) - get the height of an image.

     int imGetXBase(Image im) - get the x-base of an image.

     int imGetYBase(Image im) - get the y-base of an image.
        
     int imGetXMax(Image im) - get the maximum x value of an image.

     int imGetYMax(Image im) - get the maximum y value of an image.

     ImageType imGetType(Image im) - get the type of an image.

     macro imRef(Image im, int x, int y) - access an element
                of some form of Image.

An image is a rectangular storage area, with each cell being of some
type. In this case, the types are unsigned char, float, RGB, double,
binary, long and void *. Float is large enough for most purposes for image
processing; for those for which it is not, DoubleImage is provided;
the space costs are much higher for this, so it should be avoided unless
necessary. Binary images can store 0 or 1 in each location. By convention,
0 is white and 1 is black in binary images.
PtrImages can store a void * pointer at each location. These images may
not be saved or loaded.

imNew creates an Image of the given size, of the appropriate type,
        returning (void *)NULL on failure. The Image returned
        contains all zeros. The return value should be cast to
        the appropriate type.

imNewOffset creates an image of the given size, of the appropriate type,
        returning (void *)NULL on failure. The valid range of addresses
        for the new image is (xbase..xbase+width-1, ybase..ybase+height-1).
        Addressing an image with a shifted base may be more efficient than
        performing the base shift for each access.

imFree frees the given Image.

imLoad attempts to load an Image from a file. It checks to see that
        what is stored in the file has the appropriate type, and if not
        returns NULL. It then attempts to load the image from the file,
        and if successful returns the (.*)Image as appropriate. If it
        fails, it returns NULL. The base of the loaded image is (0,0),
        regardless of what it was when it was saved.  If the variable
        ImageAllowLoadConversion is non-zero, conversion is attempted.
        Automatically converts and reads gzipped images.

imLoadF attempts to load an Image from a stdio stream. It performs the
        same operations as imLoad, except that it assumes the stream is
        open and correctly positioned. After loading, the stream is positioned
        to just after the image; it is not closed.

imSave attempts to write the given Image out to a file. If successful,
        it returns 0. If it fails, it returns -1. Files written by imSave
        from IMAGE_FLOAT, IMAGE_DOUBLE, IMAGE_LONG and IMAGE_SHORT images
        can only be re-read on same type of machine as they were written,
        unless two different machines happen to share a floating point format,
        endianness, and alignment restrictions. Luckily, this is often
        the case.

imDup makes an exact duplicate of an Image - another Image having
        the same size, type and offsets, and the same image data. It returns
        (void *)NULL if it cannot create the duplicate.

imSaveF performs the same function as imSave, except that it writes
        to a previously-opened stream. After the save, the stream
        is positioned after the newly-written data.

imGetWidth returns the width of the given Image.

imGetHeight returns the height of the given Image.

imGetType returns the ImageType of the given Image.

imRef gives access to an entry in an Image of some form (it works
        for all defined forms of Image). It gives an lvalue: it is valid
        to say imRef(i, x, y) = foo;

Some of these are implemented partially as macros for strange reasons.
As a result, they may not be entirely safety-checked. If you want to
have safety-checking in place, at a cost in speed and code size, put
-DIMAGE_CHECKALL on your gcc line, or add
#define IMAGE_CHECKALL
to your code somewhere before you include image.h

END DOCUMENTATION
*/
#endif   
