#ifndef _IMAGE_H #define _IMAGE_H #include #include #include #include //>>>>>>>>>>>>>>>>>>>>>>>>> Error Handleing Cluge //!!!!!!!!!!!!!!!!!!!!!!!!! This must be addressed #define GENFERR(x) PAUSE((x)) #define GENNFERR(x) PAUSE((x)) //>>>>>>>>>>>>>>>>>>>>>>>>>>> Errors #define IERR_OK (1<<0) #define IERR_FILE (1<<1) #define IERR_NOIMAGE (1<<2) //>>>>>>>>>>>>>>>>>>>>>>>>>>>> Flags #define IMG_LOCKED (1<<0) #define IMG_ISDATA (1<<1) //>>>>>>>>>>>>>>>>>>>>>>>>>>>> Macros #define RGB16(r,g,b) ((((WORD)r&0xf8)<<8)|(((WORD)g&0xfc)<<3)|(((WORD)b&0xf8)>>3)) #define RGB24(r,g,b,a,mr,mg,mb,ma) (PMASK24(r,mr)|PMASK24(g,mg)|PMASK24(b,mb)|PMASK24(a,ma)) #define PMASK24(p,mp) ((((DWORD)(p))|((DWORD)(p)<<8)|((DWORD)(p)<<16)|((DWORD)(p)<<24))&(mp)) #define Mask(x,y) ((x)&(~(y))) //>>>>>>>>>>>>>>>>>>>>>>>>>>> Structs/unions enum ITYPE {ITYPE_RGB,ITYPE_INDEXED} ; enum RMETHOD {RMD_REDC,RMD_BLUEC,RMD_GREENC,RMD_ALPHAC,RMD_MAX,RMD_BHT} ; //>>>>>>>>>>>>>>>>>>>>>>>>>>> custom types typedef unsigned long int DWORD; typedef unsigned short int WORD; typedef unsigned char BYTE; typedef int BOOL; #define TRUE 1 #define FALSE 0 //>>>>>>>>>>>>>>>>>>>>>>>>>>> Classes class Image; class RGBMask; class ImgRGBColor; class RGBPixel; class FRect { public: float top,left,right,bottom; FRect(float x1=0,float y1=0,float x2=0,float y2=0) {top=y1; bottom=y2; left=x1; right=x2; } FRect(double x1,double y1=0,double x2=0,double y2=0) {top=(float)y1; bottom=(float)y2; left=(float)x1; right=(float)x2; } FRect(int x1,int y1,int x2,int y2) {top=(float)y1; bottom=(float)y2; left=(float)x1; right=(float)x2; } }; class TRect:public RECT { public: TRect(int x1=0,int y1=0,int x2=0,int y2=0) {top=y1; bottom=y2; left=x1; right=x2; } TRect(FRect &rct) {top=(int)rct.top; bottom=(int)rct.bottom; left=(int)rct.left; right=(int)rct.right; } }; class RGBPixel { public: union { unsigned long int dword; unsigned short int wrd[2]; unsigned char com[4]; }; RGBPixel(const ImgRGBColor &col,const RGBMask &mask) { Set(col,mask); } void Set(const ImgRGBColor &col,const RGBMask &mask); void Set(const ImgRGBColor &col); friend ImgRGBColor; }; class RGBMask { protected: DWORD R,G,B,A; DWORD irs,igs,ibs,ias; DWORD rbs,gbs,bbs,albs; DWORD ras,gas,bas,aas; DWORD bits; // DWORD rmax,gmax,bmax,amax; public: RGBMask(DWORD r=0xff0000,DWORD g=0x00ff00,DWORD b=0x0000ff,DWORD a=0) { Set(r,g,b,a); } int Set(DWORD r=0xff0000,DWORD g=0x00ff00,DWORD b=0x0000ff,DWORD a=0); int IsValid() { return R && B && G; } int operator==(RGBMask &mask) { return (R==mask.R)&&(G==mask.G)&&(B==mask.B)&&(A==mask.A); } DWORD GetRMask() {return R;} DWORD GetGMask() {return G;} DWORD GetBMask() {return B;} DWORD GetAMask() {return A;} DWORD GetRBits() {return rbs;} DWORD GetGBits() {return gbs;} DWORD GetBBits() {return bbs;} DWORD GetABits() {return albs;} DWORD GetBpp() {return bits;} friend class ImgRGBColor; friend class RGBPixel; }; class ImgRGBColor { private: public: int r,g,b,a; void Bound(); //makes sure color is in valid range //construction ImgRGBColor() {} ImgRGBColor(int ir,int ig,int ib,int ia=255) { Set(ir,ig,ib,ia);} ImgRGBColor(float ir,float ig,float ib,float ia=1.0) { Set(ir,ig,ib,ia);} ImgRGBColor(DWORD ir,DWORD ig,DWORD ib,DWORD ia=255) { Set(ir,ig,ib,ia);} ImgRGBColor(RGBPixel &pix,RGBMask &mask) { Set(pix,mask); } ImgRGBColor(COLORREF col) { Set(col&0xff,(col>>8)&0xff,(col>>16)&0xff); } //initalization void Set(DWORD ir,DWORD ig,DWORD ib,DWORD ia=255) { r=ir; g=ig; b=ib; a=ia; } void Set(int ir,int ig,int ib,int ia=255) { r=ir; g=ig; b=ib; a=ia; } void Set(float ir,float ig,float ib,float ia=1.0) { Set((int)(ir*255),(int)(ig*255),(int)(ib*255),(int)(ia*255));} void SetBounded(int ir,int ig,int ib,int ia=255) { Set(ir,ig,ib,ia); Bound(); } //keeps values in legal range void Set(const RGBPixel &pix,const RGBMask &mask); //conditionals int operator==(const ImgRGBColor &ac) { return (r==ac.r) && (g==ac.g) && (b==ac.b); } int operator!=(const ImgRGBColor &ac) { return (r!=ac.r) || (g!=ac.g) || (b!=ac.b); } int LSDiff(const ImgRGBColor &ac) { return abs(ac.r-r)+abs(ac.g-g)+abs(ac.b-b)+abs(ac.a-a); } //least squares difference void Merge(const ImgRGBColor &ac,int dw=1,int sw=1); //weighted merge void Blend(const ImgRGBColor &ac,float trans=.5); //weighted merge void ContrastBy(float cont) { SetBounded((int)((r-128*cont)+128),(int)((g-128*cont)+128),(int)((b-128*cont)+128)); } void BrightenBy(float bgt) { SetBounded((int)(r*bgt),(int)(g*bgt),(int)(b*bgt)); } //operators ImgRGBColor &operator-(int col) { Set(r-col,g-col,b-col,a); return *this; } ImgRGBColor &operator-(float col) { Set(r-col*255,g-col*255,b-col*255,(float)(a/255.0)); return *this; } ImgRGBColor &operator+(int col) { Set(r+col,g+col,b+col,a); return *this; } ImgRGBColor &operator+(float col) { Set(r+col*255,g+col*255,b+col*255,(float)(a/255.0)); return *this; } ImgRGBColor &operator=(int col) { Set(col,col,col); return *this;} ImgRGBColor &operator=(float col) { Set(col,col,col); return *this;} ImgRGBColor &operator++() { Set(r+1,g+1,b+1,a); return *this; } ImgRGBColor &operator--() { Set(r-1,g-1,b-1,a); return *this; } ImgRGBColor &operator+=(const ImgRGBColor &ac) { Set(r+ac.r,g+ac.g,b+ac.b); return *this; } ImgRGBColor operator+(const ImgRGBColor &ac) { return ImgRGBColor(r+ac.r,g+ac.g,b+ac.b); } ImgRGBColor operator/(int dv) { return ImgRGBColor(r/dv,g/dv,b/dv); } ImgRGBColor &operator=(const ImgRGBColor &ac) { r=ac.r; g=ac.g; b=ac.b; a=ac.a; return *this; } //operations void Invert() { r=255-r; g=255-g; b=255-b; a=255-a; } void MakeBW() { r=g=b=(BYTE)(g*0.59f+b*0.11f+r*0.3f); } float GetBrightness() { return (g*0.59f+b*0.11f+r*0.3f)*(1/255.0f);} friend class RGBPixel; friend class Image; friend class DXImage; friend class OctTree; }; class Point { public: int x,y,z; Point(int ix=0,int iy=0,int iz=0); int XDist(int); int YDist(int); double Dist(int,int); int XDist(Point p); int YDist(Point p); double Dist(Point p); }; class ImageOperator { protected: int Rows,Cols; float **dat; float Sum; void CalculateSum(); void Create(int sr,int sc); void Destroy(); public: ImageOperator() {Rows=Cols=0; dat=new float *[0];} ImageOperator(int sr,int sc) { ImageOperator(); Create(sr,sc); } ~ImageOperator() {Destroy(); } float GetWeight(int r,int c) {return dat[r][c];} float GetTotal() {return Sum;} int GetRows() {return Rows;} int GetCols() {return Cols;} void CreateGaussian(float pix); void CreateGaussian(int xl,int yl); void CreateMean(int sx,int sy); friend class Image; }; class Histogram { friend class Image; protected: int Data[256]; int Peak; public: Histogram(); Histogram(Image &img,RMETHOD rmet=RMD_REDC); ~Histogram(); void Clear(); int GetBottom(float per=0.5); int GetTop(float per=0.5); }; class RGBHistogram { friend class Image; protected: Histogram RHist,GHist,BHist; public: RGBHistogram(); RGBHistogram(Image &img); void Clear(); ImgRGBColor GetBottom(float per=0.5); ImgRGBColor GetTop(float per=0.5); }; class Image { protected: int Flag; BYTE *Data; char fname[MAX_PATH]; ImgRGBColor *pal; RGBMask Mask; int Bpp,Pitch; int xlen,ylen; int xpos,ypos,vxlen,vylen; ITYPE itype; // Internal memory Management int LockStack; virtual void IAlloc(); virtual void IFree(); virtual void SetData(BYTE *); //assume to be corrrctly for formated with Pitch=xlen virtual void RealizePalette(); //makes the new pallette take effect void AllocPal() {if(pal) return; else pal=new ImgRGBColor[256];} // Internal data Management void Init(); void CorrectPitch(); //corrects the pitch of loaded image //Multiple or incorrect calls will corrupt data void DeInterlace(); //deinterlaces a 4 interlaced image void DePitch(BYTE *); //fills buffer with copy of depitched data void MaskFrom(RGBMask &imask); //Remask the data from this mask to correct mask //Internal Manipulation void Difference(); void UnDifference(); void InternalLoadPng(); void InternalSavePng(); public: void FillHistogram(Histogram *hist,RMETHOD rmet=RMD_REDC); void FillHistogram(RGBHistogram *hist); void MaskTo(RGBMask &omask); //Remask the data from this mask to correct mask int GetXPos() {return xpos;} int GetYPos() {return ypos;} void ResetPos() {xpos=ypos=0;} void IgnoreVDims() {xpos=ypos=0; vxlen=xlen; vylen=ylen;} int GetHeight() {return ylen;} int GetWidth() {return xlen;} int GetVHeight() {return vylen;} int GetVWidth() {return vxlen;} int GetPitch() {return Pitch;} int GetIType() {return itype;} int GetBpp() {return Bpp;} char *GetFileName() {return fname;} Image(); Image(Image &img); Image(char *); Image(int xl,int yl); Image(int xl,int yl,ImgRGBColor col); void Delete(); int IsData(); bool HasAlpha() {return Mask.GetABits()!=0;} //>>>>>>>>>>>>>>>>>>>> creation void CreateGrid(int xlen=320,int ylen=200,int gx=10,int gy=10,ImgRGBColor bgk=ImgRGBColor(0,0,0),ImgRGBColor frg=ImgRGBColor(255,255,255),ITYPE itp=ITYPE_RGB,int bpp=24); void CreateFade(int xl=320,int yl=200,ImgRGBColor rgb1=ImgRGBColor(255,255,255),ImgRGBColor rgb2=ImgRGBColor(0,0,0),int ort=0,ITYPE itp=ITYPE_RGB,int bpp=24); void CreateSolid(int xl=320,int yl=200,ImgRGBColor col=ImgRGBColor(0,0,0),ITYPE itp=ITYPE_RGB,int bpp=24); void CreateBlank(int xl=320,int yl=200,ITYPE itp=ITYPE_RGB,int bpp=24); void CreateBlank(int xl,int yl,ITYPE itp,int bpp,RGBMask &msk); void FillColor(ImgRGBColor fcol=ImgRGBColor(0,0,0)); //>>>>>>>>>>>>>>>>>>>> enhancment void Swap(const ImgRGBColor &,const ImgRGBColor &); void ReplaceAlpha(int acutoff=0,const ImgRGBColor &bcol=ImgRGBColor(0,0,0)); //Replaces alpha <= this value with color void GaussianBlur(float pix); void MeanBlur(int xs,int ys); void ApplyOperator(ImageOperator &Opt); void Pad(int pixs=1); void MakeSlopeMap(float xscale=1.0f,float yscale=1.0f,float zscale=1.0f,ImgRGBColor lowcol=ImgRGBColor(255,0,0),ImgRGBColor highcol=ImgRGBColor(255,0,0)); void MakeContourMap(float xscale=1.0f,float yscale=1.0f,float zscale=1.0f,int step=10,ImgRGBColor bgcol=ImgRGBColor(0,0,0),ImgRGBColor lolinecol=ImgRGBColor(255,255,255),ImgRGBColor highlinecol=ImgRGBColor(255,255,255)); void ShowSlopeLimit(float xscale=1.0f,float yscale=1.0f,float zscale=1.0f,float limit=45.0f,ImgRGBColor lowcol=ImgRGBColor(255,0,0),ImgRGBColor highcol=ImgRGBColor(255,0,0)); float GetBrightness(); void BrightenBy(float bght); void ContrastBy(float bght); void AdjustToRange(ImgRGBColor &maxcol,ImgRGBColor &mincol); void AutoAdjust(); //>>>>>>>>>>>>>>>>>>>> Memory Management virtual BYTE *Lock(); virtual void UnLock(); //>>>>>>>>>>>>>>>>>>>> External Pallete Management virtual void SetPaletteEntry(int idx,int r,int g ,int b); void SetPaletteEntry(int idx,float r,float g,float b); void SetPaletteEntry(int,const ImgRGBColor &rgb); ImgRGBColor GetPaletteEntry(int); void MakeGrayscalePalette(); void MakePalette(ImgRGBColor low,ImgRGBColor high); //>>>>>>>>>>>>>>>>>>>> manipulation void MakeRGB(RGBMask msk=RGBMask(0xff0000,0x00ff00,0x0000ff,0)); void MakeRGB24(); void MakeRGB16(RGBMask msk=RGBMask(0xf800,0x07E0,0x001f,0)); void MakeBW(); void Invert(); void Quantize(); void Crop(int x1,int y1,int x2, int y2); Point Crop(ImgRGBColor ccl=ImgRGBColor(0,0,0)); void ReduceTo8Bit(RMETHOD rm); void Blt(Image &img,RECT &dst); void Blt(Image &img,RECT dst,RECT &src); void Blt(Image &img,FRect dst); void Blt(Image &img,FRect dst,FRect src); void Blt(Image &img,int x=0,int y=0); void Blt(Image &img,int x,int y,RECT &src); void Blt(Image &img,int x,int y,FRect src); void BltDominantColor(Image &img,RECT dst,RECT &src); void BltBlend(Image &img,float efact,RECT &src,float tfact,float rfact,float bfact,float lfact); // Blends edges of image into other images that are sampled differently // efact = % of edge to blend 0-1 // tfact = reduction coefficent of above image <0 if same as this image void Rotate180(); //>>>>>>>>>>>>>>>>>>>> Super Cool Manipulations void CreateDifferentialMap(); void CreateDifferentialMap(float *, int); //>>>>>>>>>>>>>>>>>>>> File management void Load(FILE *); void Load(char *); void Load(); int IsTiff(FILE *); void LoadTiff(FILE *); void LoadTiff(char *); void SaveTiff(FILE *); void SaveTiff(char *); int IsGif(FILE *fl); void LoadGif(FILE *); void LoadGif(char *); void SaveGif(FILE *); void SaveGif(char *); int IsTga(); void LoadTga(FILE *); void SaveTga(FILE *); void GetTgaInfo(FILE *); void SaveTga(char *); void LoadTga(char *); void GetTgaInfo(char *); void LoadTga(Stuff::FileStream *stream); void GetTgaInfo(Stuff::FileStream *stream); void SaveTga(Stuff::FileStream *stream); int IsPng(); int IsPng(FILE *fl); void LoadPng(FILE *); void SavePng(FILE *); void GetPngInfo(FILE *); void LoadPng(char *); void SavePng(char *); void GetPngInfo(char *); int IsPng(Stuff::FileStream *stream); void LoadPng(Stuff::FileStream *stream); void SavePng(Stuff::FileStream *stream); void GetPngInfo(Stuff::FileStream *stream); void SaveRaw(FILE *); void SaveRaw(char *); //>>>>>>>>>>>>>>>>>>>> matinaance ImgRGBColor GetColor(Point &p); Image &operator=(Image &img); bool operator==(Image &img); bool operator!=(Image &img) {return !(*this==img);} ~Image(); friend class OctQuant; // Octree color quantization }; //Inline functions __inline void RGBPixel::Set(const ImgRGBColor &col,const RGBMask &mask) { switch(mask.bits) { case 16: wrd[0]=(WORD)(((col.r>>mask.ras)<>mask.gas)<>mask.bas)<>mask.aas)<>mask.ras)<>mask.gas)<>mask.bas)<>mask.aas)<>16)&0xff); } break; case 32: dword=((col.r>>mask.ras)<>mask.gas)<>mask.bas)<>mask.aas)<>mask.irs)<>mask.igs)<>mask.ibs)<>mask.ias)<255) r=255; else if(r<0) r=0; if(g>255) g=255; else if(g<0) g=0; if(b>255) b=255; else if(b<0) b=0; } __inline void ImgRGBColor::Merge(const ImgRGBColor &ac,int dw,int sw) //weighted merge { r=(r*dw+ac.r*sw)/(dw+sw); g=(g*dw+ac.g*sw)/(dw+sw); b=(b*dw+ac.b*sw)/(dw+sw); } __inline void ImgRGBColor::Blend(const ImgRGBColor &ac,float trans) //weighted merge { r=(unsigned long)(r*(1-trans)+ac.r*trans); g=(unsigned long)(g*(1-trans)+ac.g*trans); b=(unsigned long)(b*(1-trans)+ac.b*trans); } #endif