/* * image.h * * Copyright (c) 1990, 1991, 1992, 1993 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 #ifdef IMAGE_CHECKALL /* Need eassert() and panic() */ #include "panic.h" #endif /* For boolean */ #include "misc.h" /* The number of colours per component (or total for gray images) */ #define COLDEPTH 8 #define COLRNG (1 << COLDEPTH) #ifndef IMAGE_OLD_RGB typedef struct { unsigned char r, g, b; } RGB; #else typedef unsigned char RGB[3]; #endif typedef unsigned char ImageType; /* The image types */ #define IMAGE_GRAY ((ImageType)1) #define IMAGE_FLOAT ((ImageType)2) #define IMAGE_RGB ((ImageType)3) #define IMAGE_DOUBLE ((ImageType)4) #define IMAGE_BINARY ((ImageType)5) #define IMAGE_LONG ((ImageType)6) #define IMAGE_PTR ((ImageType)7) #define IMAGE_SHORT ((ImageType)8) /* Several types of image */ typedef struct { unsigned char **data; struct _ImageHeader *header; } *GrayImage; typedef unsigned char * GrayPixPtr; typedef struct { float **data; struct _ImageHeader *header; } *FloatImage; typedef float * FloatPixPtr; typedef struct { RGB **data; struct _ImageHeader *header; } *RGBImage; typedef RGB * RGBPixPtr; typedef struct { double **data; struct _ImageHeader *header; } *DoubleImage; typedef double * DoublePixPtr; typedef struct { char **data; struct _ImageHeader *header; } *BinaryImage; typedef char * BinaryPixPtr; typedef struct { long **data; struct _ImageHeader *header; } *LongImage; typedef long * LongPixPtr; typedef struct { void ***data; struct _ImageHeader *header; } *PtrImage; typedef void ** PtrPixPtr; typedef struct { short **data; struct _ImageHeader *header; } *ShortImage; typedef short * ShortPixPtr; /* An invisible image header type */ struct _ImageHeader { unsigned width, height; int xbase, ybase; ImageType tag; char *comment; union { GrayImage grayptr; FloatImage floatptr; RGBImage RGBptr; DoubleImage doubleptr; BinaryImage binaryptr; LongImage longptr; PtrImage ptrptr; ShortImage shortptr; } body; }; typedef struct _ImageHeader ImageHeader; /* and some manipulation routines */ extern void *imNew(ImageType type, unsigned width, unsigned height); extern void *imNewOffset(ImageType type, unsigned width, unsigned height, int xbase, int ybase); extern void im_Free_(void *im, ImageHeader *header); extern void *imLoad(ImageType type, char *filename); extern void *imLoadF(ImageType type, 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, boolean copycomment); extern void *im_Promote_(void *im, ImageHeader *header, ImageType promoteto); extern void imSetPromotion(ImageType promotefrom, ImageType promoteto, double slope, double offset); extern void *im_Demote_(void *im, ImageHeader *header, ImageType demoteto); extern void *im_Convert_(void *im, ImageHeader *header, ImageType convertto); extern boolean im_SetComment_(void *im, ImageHeader *header, char *newcomment); /* and some useful routines */ #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 imGetXMax(i) (((i)->header->xbase)+(int)((i)->header->width)-1) #define imGetYMax(i) (((i)->header->ybase)+(int)((i)->header->height)-1) #define imGetType(i) ((i)->header->tag) #define imGetComment(i) ((i)->header->comment) #else #define imGetWidth(i) (eassert((i) != NULL), ((i)->header->width)) #define imGetHeight(i) (eassert((i) != NULL), ((i)->header->height)) #define imGetXBase(i) (eassert((i) != NULL), ((i)->header->xbase)) #define imGetYBase(i) (eassert((i) != NULL), ((i)->header->ybase)) #define imGetXMax(i) (eassert((i) != NULL), (((i)->header->xbase)+(int)((i)->header->width)-1)) #define imGetYMax(i) (eassert((i) != NULL), (((i)->header->ybase)+(int)((i)->header->height)-1)) #define imGetType(i) (eassert((i) != NULL), ((i)->header->tag)) #define imGetComment(i) (eassert((i) != NULL), ((i)->header->comment)) #endif /* * 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). */ #ifndef IMAGE_CHECKALL #define imFree(i) im_Free_((void *)(i), ((i)->header)) #define imSetOffset(i, nx, ny) im_SetOffset_((i), ((i)->header), (nx), (ny)) #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), TRUE) #define imPromote(i, t) im_Promote_((void *)(i), ((i)->header), (t)) #define imDemote(i, t) im_Demote_((void *)(i), ((i)->header), (t)) #define imConvert(i, t) im_Convert_((void *)(i), ((i)->header), (t)) #define imSetComment(i, c) im_SetComment_((void *)(i), ((i)->header), (c)) #else #define imFree(i) (eassert((i) != NULL), (im_Free_((void *)(i), ((i)->header)))) #define imSetOffset(i,nx,ny) (eassert((i) != NULL), (im_SetOffset_((i), ((i)->header), (nx), (ny)))) #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), TRUE))) #define imPromote(i, t) (eassert((i) != NULL), (im_Promote_((void *)(i), ((i)->header), (t)))) #define imDemote(i, t) (eassert((i) != NULL), (im_Demote_((void *)(i), ((i)->header), (t)))) #define imConvert(i, t) (eassert((i) != NULL), (im_Convert_((void *)(i), ((i)->header), (t)))) #define imSetComment(i, c) (eassert((i) != NULL), im_SetComment_((void *)(i), ((i)->header), (c))) #endif /* 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), ((((int)(x) < (int)(i)->header->xbase) || ((int)(y) < (int)(i)->header->ybase) || ((int)(x) >= (int)(i)->header->xbase + (int)(i)->header->width) || ((int)(y) >= (int)(i)->header->ybase + (int)(i)->header->height)) ? ({ sprintf(__imPanicStr, "bounds check fail: %d <= %d < %d, %d <= %d < %d", (int)(i)->header->xbase, (int)(x), (int)(i)->header->xbase + (int)(i)->header->width, (int)(i)->header->ybase, (int)(y), (int)(i)->header->ybase + (int)(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->ybase+(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, but just saying &imRef doesn't work... */ #define imGetPixPtr(i, x, y) (eassert((i) != NULL), ((((int)(x) < (int)(i)->header->xbase) || ((int)(y) < (int)(i)->header->ybase) || ((int)(x) >= (int)(i)->header->xbase + (int)(i)->header->width) || ((int)(y) >= (int)(i)->header->ybase + (int)(i)->header->height)) ? ({ sprintf(__imPanicStr, "bounds check fail: %d <= %d < %d, %d <= %d < %d", (int)(i)->header->xbase, (int)(x), (int)(i)->header->xbase + (int)(i)->header->width, (int)(i)->header->ybase, (int)(y), (int)(i)->header->ybase + (int)(i)->header->height); panic(__imPanicStr);}), (&((i)->data[0][0])) : (&(((i)->data)[(y)][(x)])))) #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