#ifndef _GFilter_H #define _GFilter_H #include "GImage.h" /* GFilter is an abstract decendant of GImage. Derivatives of this class can * be used to filter an image in some way (scale, rotate, etc). Filters * defined in this file include: * * GFilter_GammaCorrection * GFilter_Scale * GFilter_Rotate (0, 90, 180, and 270 degrees only) * GFilter_ContrastAdjustment * GFilter_WhiteBalance * * Written by: Chris Studholme * Last Update: 25-May-2000 * Copyright: GPL (http://www.fsf.org/copyleft/gpl.html) */ class GFilter : public GImage { protected: GImage& src; protected: GFilter(GImage& image) : src(image) { } GImage* getSourceImage() { return &src; } /* These get???() routines are just defaults. They are all virtual and * should be overridden where necessary. */ const char* getComments() { return src.getComments(); } int getWidth() { return src.getWidth(); } int getHeight() { return src.getHeight(); } int getPreferredWidth() { return src.getPreferredWidth(); } int getPreferredHeight() { return src.getPreferredHeight(); } double getAspectRatio() { return src.getAspectRatio(); } }; class GFilter_GammaCorrection : public GFilter { /* * gamma correction filter */ protected: int min, range; short* table; public: GFilter_GammaCorrection(GImage& image, float gamma=1) : GFilter(image) { table=NULL; min=-16384; range=32768; setGammaCorrection(gamma); } ~GFilter_GammaCorrection() { if (table) delete[] table; } void setGammaCorrection(float gamma=1); void getPixel(short& red, short& green, short& blue, float x1, float y1, float x2, float y2); void getScanLineHorz(short* red, short* green, short* blue, float x1, float y1, float x2, float y2, int npixels); void getScanLineVert(short* red, short* green, short* blue, float x1, float y1, float x2, float y2, int npixels); }; class GFilter_ContrastAdjustment : public GFilter { /* * contrast adjustment filter */ protected: int min; int diff; public: GFilter_ContrastAdjustment(GImage& image, int min, int max) : GFilter(image) { setContrastAdjustment(min,max); } /* [min,max] is translated to [-16384,+16383] */ void setContrastAdjustment(int mn, int mx) { min=mn; diff=mx-mn; } void getPixel(short& red, short& green, short& blue, float x1, float y1, float x2, float y2); void getScanLineHorz(short* red, short* green, short* blue, float x1, float y1, float x2, float y2, int npixels); void getScanLineVert(short* red, short* green, short* blue, float x1, float y1, float x2, float y2, int npixels); }; class GFilter_WhiteBalance : public GFilter { /* * contrast adjustment filter */ protected: int rdiff,gdiff,bdiff; public: GFilter_WhiteBalance(GImage& image, float red=1, float blue=1) : GFilter(image) { setWhiteLevel(red,blue); } /* green is implied */ void setWhiteLevel(float red, float blue) { float green=1; if (red>1) { green/=red; blue/=red; red=1; } if (blue>1) { red/=blue; green/=blue; blue=1; } rdiff=(int)(32678*red); gdiff=(int)(32678*green); bdiff=(int)(32678*blue); } void getPixel(short& red, short& green, short& blue, float x1, float y1, float x2, float y2); void getScanLineHorz(short* red, short* green, short* blue, float x1, float y1, float x2, float y2, int npixels); void getScanLineVert(short* red, short* green, short* blue, float x1, float y1, float x2, float y2, int npixels); }; class GFilter_Scale : public GFilter { /* * scaling filter */ protected: double aspectratio; int w,h; float xfactor,xoffset; float yfactor,yoffset; public: GFilter_Scale(GImage& image) : GFilter(image) { aspectratio=src.getAspectRatio(); w=src.getWidth(); h=src.getHeight(); calculateConstants(); } /* if either of width or height are zero, it will be calculated; * both must not be zero */ GFilter_Scale(GImage& image, int width, int height, double aspect=1) : GFilter(image) { w=width; h=height; aspectratio=aspect; if (w==0) w = (int)((h*src.getWidth()*src.getAspectRatio())/(src.getHeight()*aspectratio)); else if (h==0) h = (int)((w*src.getHeight()*aspectratio)/(src.getWidth()*src.getAspectRatio())); calculateConstants(); } /* changing the aspect ratio does not change the image dimensions; * therefore, the image may end up cropped if the dimensions are not reset */ void setAspectRatio(double ratio) { aspectratio=ratio; calculateConstants(); } /* sets the maximum dimensions the image may have; one dimension may be * set smaller to maintain aspect ratio and not crop the image */ void setMaximumDimensions(int width, int height) { w=width; h=height; double temp = (src.getWidth()*src.getAspectRatio())/(src.getHeight()*aspectratio); int ow = (int)(h*temp); if (oww) w=ow; else { int oh = (int)(w/temp); if (oh>h) h=oh; } calculateConstants(); } /* sets the image dimensions exactly; if crop=true, the image may be * cropped to maintain aspect ratio; if crop=false, the aspect ratio * will be changed to ensure that the image is not cropped */ void setDimensions(int width, int height, bool crop=true) { w=width; h=height; if (!crop) aspectratio=h*src.getWidth()*src.getAspectRatio()/(w*src.getHeight()); calculateConstants(); } int getWidth() { return w; } int getUncropWidth() { int ow=(int)((h*src.getWidth()*src.getAspectRatio())/(src.getHeight()*aspectratio)); return ow>w?ow:w; } int getHeight() { return h; } int getUncropHeight() { int oh=(int)((w*src.getHeight()*aspectratio)/(src.getWidth()*src.getAspectRatio())); return oh>h?oh:h; } int getPreferredWidth() { return w; } int getPreferredHeight() { return h; } double getAspectRatio() { return aspectratio; } void getPixel(short& red, short& green, short& blue, float x1, float y1, float x2, float y2); void getScanLineHorz(short* red, short* green, short* blue, float x1, float y1, float x2, float y2, int npixels); void getScanLineVert(short* red, short* green, short* blue, float x1, float y1, float x2, float y2, int npixels); private: void calculateConstants(); }; class GFilter_Rotate : public GFilter { /* * rotate filter */ protected: int degree; public: GFilter_Rotate(GImage& image, int angle=0) : GFilter(image) { degree=(360+angle)%360; if (degree%90!=0) fprintf(stderr,"GFilter_Rotate: rotate angle must be multiple of 90 degrees %d\n",degree); } void setClockwiseRotate(int angle=90) { degree=(360+angle)%360; if (degree%90!=0) fprintf(stderr,"GFilter_Rotate: rotate angle must be multiple of 90 degrees %d\n",degree); } void setCounterClockwiseRotate(int angle=90) { degree=(360-angle)%360; if (degree%90!=0) fprintf(stderr,"GFilter_Rotate: rotate angle must be multiple of 90 degrees %d\n",degree); } int getWidth() { return (degree==90)||(degree==270) ? src.getHeight() : src.getWidth(); } int getHeight() { return (degree==90)||(degree==270) ? src.getWidth() : src.getHeight(); } int getPreferredWidth() { return (degree==90)||(degree==270) ? src.getPreferredHeight() : src.getPreferredWidth(); } int getPreferredHeight() { return (degree==90)||(degree==270) ? src.getPreferredWidth() : src.getPreferredHeight(); } double getAspectRatio() { return (degree==90)||(degree==270) ? 1/src.getAspectRatio() : src.getAspectRatio(); } void getPixel(short& red, short& green, short& blue, float x1, float y1, float x2, float y2); void getScanLineHorz(short* red, short* green, short* blue, float x1, float y1, float x2, float y2, int npixels); void getScanLineVert(short* red, short* green, short* blue, float x1, float y1, float x2, float y2, int npixels); }; #endif