--- /dev/null
+#include "../../../../include/freenet/captcha/freeimage/bitmap.h"\r
+\r
+#include <cmath>\r
+\r
+namespace FreeImage\r
+{\r
+\r
+Bitmap::Bitmap()\r
+{\r
+ m_bmp=0;\r
+}\r
+\r
+Bitmap::Bitmap(const Bitmap &bmp)\r
+{\r
+ m_bmp=0;\r
+ *this=bmp;\r
+}\r
+\r
+Bitmap::Bitmap(const std::string &typestr, const std::string &filename)\r
+{\r
+ m_bmp=0;\r
+ Load(typestr,filename);\r
+}\r
+\r
+Bitmap::Bitmap(FIBITMAP *bmp):m_bmp(bmp)\r
+{\r
+\r
+}\r
+\r
+Bitmap::Bitmap(const int width, const int height, const int bpp)\r
+{\r
+ m_bmp=FreeImage_Allocate(width,height,bpp,0,0,0);\r
+}\r
+\r
+Bitmap::~Bitmap()\r
+{\r
+ Destroy();\r
+}\r
+\r
+void Bitmap::AALine(const int x1, const int y1, const int x2, const int y2, const RGBQUAD color)\r
+{\r
+ RGBQUAD tempcol;\r
+ int height=Height();\r
+ int width=Width();\r
+ int fromx=x1;\r
+ int fromy=y1;\r
+ int tox=x2;\r
+ int toy=y2;\r
+ double sx=x2-x1;\r
+ double sy=y2-y1;\r
+\r
+ if(fabs(sx)<=0.8 && fabs(sy)<=0.8)\r
+ {\r
+ return;\r
+ }\r
+\r
+ double hypot=sqrt((sx*sx)+(sy*sy));\r
+ sx/=hypot;\r
+ sy/=hypot;\r
+\r
+ fromx<0 ? fromx=0 : false;\r
+ fromx>=width ? fromx=width-1 : false;\r
+ tox<0 ? tox=0 : false;\r
+ tox>=width ? tox=width-1 : false;\r
+ fromy<0 ? fromy=0 : false;\r
+ fromy>=height ? fromy=height-1 : false;\r
+ toy<0 ? toy=0 : false;\r
+ toy>=height ? toy=height-1 : false;\r
+\r
+ int lx=fromx;\r
+ int rx=tox;\r
+ if(rx<lx)\r
+ {\r
+ std::swap(rx,lx);\r
+ }\r
+ int ty=fromy;\r
+ int by=toy;\r
+ if(by<ty)\r
+ {\r
+ std::swap(ty,by);\r
+ }\r
+\r
+ for(int i=lx; i<=rx; i++)\r
+ {\r
+ for(int j=ty; j<=by; j++)\r
+ {\r
+ double ii=0;\r
+ double jj=0;\r
+ double dx=0.25;\r
+ double dy=0.25;\r
+ double x=i-1.5*dx;\r
+ double y=j-1.5*dy;\r
+ double temp=0;\r
+ \r
+ for(ii=-2; ii<=1; ii++)\r
+ {\r
+ for(jj=-2; jj<=1; jj++)\r
+ {\r
+ x=i+ii*dx+0.5*dx;\r
+ y=j+jj*dy+0.5*dy;\r
+ double temp1 = LineFunction( sx, sy , fromx, fromy, x,y );\r
+ temp1<=0.5 ? temp1=1.0 : temp1=0.0;\r
+ temp+=temp1;\r
+ }\r
+ }\r
+\r
+ temp/=16.0;\r
+ double minval=0.03125;\r
+\r
+ if(temp>minval)\r
+ {\r
+ FreeImage_GetPixelColor(m_bmp,i,(height-1)-j,&tempcol);\r
+ tempcol.rgbRed=((1.0-temp)*((double)tempcol.rgbRed)+temp*((double)color.rgbRed));\r
+ tempcol.rgbGreen=((1.0-temp)*((double)tempcol.rgbGreen)+temp*((double)color.rgbGreen));\r
+ tempcol.rgbBlue=((1.0-temp)*((double)tempcol.rgbBlue)+temp*((double)color.rgbBlue));\r
+ FreeImage_SetPixelColor(m_bmp,i,(height-1)-j,&tempcol);\r
+ }\r
+\r
+ }\r
+ }\r
+\r
+}\r
+\r
+void Bitmap::Blit(const Bitmap &bmp, const int destx, const int desty, const int sourcex, const int sourcey, const int w, const int h, const int alpha)\r
+{\r
+ if(m_bmp && bmp.m_bmp)\r
+ {\r
+ int width=w;\r
+ int height=h;\r
+ if(destx+width-1>=Width())\r
+ {\r
+ width=Width()-destx+1;\r
+ }\r
+ if(desty+height-1>=Height())\r
+ {\r
+ height=Height()-desty+1;\r
+ }\r
+ FIBITMAP *temp=FreeImage_Copy(bmp.m_bmp,sourcex,sourcey,sourcex+width-1,sourcey+height-1);\r
+ FreeImage_Paste(m_bmp,temp,destx,desty,alpha);\r
+ FreeImage_Unload(temp);\r
+ }\r
+}\r
+\r
+void Bitmap::BlitTrans(const Bitmap &bmp, const int destx, const int desty, const int sourcex, const int sourcey, const int w, const int h)\r
+{\r
+ if(m_bmp && bmp.m_bmp)\r
+ {\r
+ RGBQUAD sourcecol;\r
+ RGBQUAD destcol;\r
+ int sourcew=bmp.Width();\r
+ int sourceh=bmp.Height();\r
+ int destw=Width();\r
+ int desth=Height();\r
+ int dx=destx;\r
+ int dy=desty;\r
+ double alpha=0.0;\r
+ for(int y=sourcey; y<sourcey+h; y++, dy++)\r
+ {\r
+ dx=destx;\r
+ for(int x=sourcex; x<sourcex+w; x++, dx++)\r
+ {\r
+ if(y>=0 && y<sourceh && x>=0 && x<sourcew && dx>=0 && dx<destw && dy>=0 && dy<desth)\r
+ {\r
+ FreeImage_GetPixelColor(bmp.m_bmp,x,(sourceh-1)-y,&sourcecol);\r
+ if(sourcecol.rgbReserved==255) // opaque\r
+ {\r
+ FreeImage_SetPixelColor(m_bmp,dx,(desth-1)-dy,&sourcecol);\r
+ }\r
+ else if(sourcecol.rgbReserved>0) // some translucency\r
+ {\r
+ FreeImage_GetPixelColor(m_bmp,dx,(desth-1)-dy,&destcol);\r
+ alpha=(double)sourcecol.rgbReserved/255.0;\r
+ sourcecol.rgbRed=(sourcecol.rgbRed*alpha)+(destcol.rgbRed*(1.0-alpha));\r
+ sourcecol.rgbGreen=(sourcecol.rgbGreen*alpha)+(destcol.rgbGreen*(1.0-alpha));\r
+ sourcecol.rgbBlue=(sourcecol.rgbBlue*alpha)+(destcol.rgbBlue*(1.0-alpha));\r
+ sourcecol.rgbReserved<destcol.rgbReserved ? sourcecol.rgbReserved=destcol.rgbReserved : false;\r
+ FreeImage_SetPixelColor(m_bmp,dx,(desth-1)-dy,&sourcecol);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+void Bitmap::Clear(RGBQUAD color)\r
+{\r
+ if(m_bmp)\r
+ {\r
+ int h=FreeImage_GetHeight(m_bmp);\r
+ int w=FreeImage_GetWidth(m_bmp);\r
+ for(int y=0; y<h; y++)\r
+ {\r
+ for(int x=0; x<w; x++)\r
+ {\r
+ FreeImage_SetPixelColor(m_bmp,x,y,&color);\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+void Bitmap::ClearTransparent()\r
+{\r
+ if(m_bmp)\r
+ {\r
+ RGBQUAD color;\r
+ color.rgbRed=0;\r
+ color.rgbGreen=0;\r
+ color.rgbBlue=0;\r
+ color.rgbReserved=0;\r
+ int h=Height();\r
+ int w=Width();\r
+ for(int y=0; y<h; y++)\r
+ {\r
+ for(int x=0; x<w; x++)\r
+ {\r
+ FreeImage_SetPixelColor(m_bmp,x,y,&color);\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+void Bitmap::ConvertBPP(const int bpp)\r
+{\r
+ if(m_bmp)\r
+ {\r
+ FIBITMAP *temp;\r
+ switch(bpp)\r
+ {\r
+ case 2:\r
+ temp=FreeImage_ConvertToGreyscale(m_bmp);\r
+ Destroy();\r
+ m_bmp=temp;\r
+ break;\r
+ case 4:\r
+ temp=FreeImage_ConvertTo4Bits(m_bmp);\r
+ Destroy();\r
+ m_bmp=temp;\r
+ break;\r
+ case 8:\r
+ temp=FreeImage_ConvertTo8Bits(m_bmp);\r
+ Destroy();\r
+ m_bmp=temp;\r
+ break;\r
+ case 16:\r
+ temp=FreeImage_ConvertTo16Bits565(m_bmp);\r
+ Destroy();\r
+ m_bmp=temp;\r
+ break;\r
+ case 24:\r
+ temp=FreeImage_ConvertTo24Bits(m_bmp);\r
+ Destroy();\r
+ m_bmp=temp;\r
+ break;\r
+ case 32:\r
+ default:\r
+ temp=FreeImage_ConvertTo32Bits(m_bmp);\r
+ Destroy();\r
+ m_bmp=temp;\r
+ break;\r
+ }\r
+ }\r
+}\r
+\r
+const bool Bitmap::Create(const int width, const int height, const int bpp)\r
+{\r
+ Destroy();\r
+ m_bmp=FreeImage_Allocate(width,height,bpp,0,0,0);\r
+ if(m_bmp)\r
+ {\r
+ return true;\r
+ }\r
+ return false;\r
+}\r
+\r
+void Bitmap::Destroy()\r
+{\r
+ if(m_bmp)\r
+ {\r
+ FreeImage_Unload(m_bmp);\r
+ m_bmp=0;\r
+ }\r
+}\r
+\r
+void Bitmap::FastLine(const int x1, const int y1, const int x2, const int y2, RGBQUAD color)\r
+{\r
+ if(m_bmp)\r
+ {\r
+ int width=Width();\r
+ int height=Height();\r
+ int fromx=x1;\r
+ int fromy=y1;\r
+ int tox=x2;\r
+ int toy=y2;\r
+\r
+ fromx<0 ? fromx=0 : false;\r
+ fromx>=width ? fromx=width-1 : false;\r
+ tox<0 ? tox=0 : false;\r
+ tox>=width ? tox=width-1 : false;\r
+ fromy<0 ? fromy=0 : false;\r
+ fromy>=height ? fromy=height-1 : false;\r
+ toy<0 ? toy=0 : false;\r
+ toy>=height ? toy=height-1 : false;\r
+\r
+ int dx=tox-fromx;\r
+ int dy=toy-fromy;\r
+\r
+ if(dx==0 && dy==0)\r
+ {\r
+ return;\r
+ }\r
+\r
+ int xinc1=1;\r
+ if(dx<0)\r
+ {\r
+ xinc1=-1;\r
+ dx=-dx;\r
+ }\r
+ int yinc1=1;\r
+ if(dy<0)\r
+ {\r
+ yinc1=-1;\r
+ dy=-dy;\r
+ }\r
+\r
+ int x=fromx;\r
+ int y=fromy;\r
+ int xinc2=xinc1;\r
+ int yinc2=yinc1;\r
+\r
+ double den;\r
+ double num;\r
+ int numadd;\r
+ int numpixels;\r
+\r
+ if(dx>=dy)\r
+ {\r
+ xinc1=0;\r
+ yinc2=0;\r
+ den=dx+0.0;\r
+ num=0.5*dx;\r
+ numadd=dy;\r
+ numpixels=dx;\r
+ }\r
+ else\r
+ {\r
+ xinc2=0;\r
+ yinc1=0;\r
+ den=dy+0.0;\r
+ num=0.5*dy;\r
+ numadd=dx;\r
+ numpixels=dy;\r
+ }\r
+\r
+ int cpixel;\r
+ for(cpixel=0; cpixel<=numpixels; cpixel++)\r
+ {\r
+ FreeImage_SetPixelColor(m_bmp,x,(height-1)-y,&color);\r
+ num+=numadd;\r
+ if(num>=den)\r
+ {\r
+ num=-den;\r
+ x+=xinc1;\r
+ y+=yinc1;\r
+ }\r
+ x+=xinc2;\r
+ y+=yinc2;\r
+ }\r
+ }\r
+}\r
+\r
+RGBQUAD Bitmap::GetPixel(const int x, const int y) const\r
+{\r
+ RGBQUAD color;\r
+ color.rgbRed=0;\r
+ color.rgbGreen=0;\r
+ color.rgbBlue=0;\r
+ color.rgbReserved=0;\r
+\r
+ if(m_bmp && x>=0 && x<Width() && y>=0 && y<Height())\r
+ {\r
+ FreeImage_GetPixelColor(m_bmp,x,Height()-1-y,&color);\r
+ }\r
+\r
+ return color;\r
+\r
+}\r
+\r
+const int Bitmap::GetPixelIndex(const int x, const int y) const\r
+{\r
+ if(m_bmp)\r
+ {\r
+ BYTE index;\r
+ FreeImage_GetPixelIndex(m_bmp,x,Height()-1-y,&index);\r
+ return index;\r
+ }\r
+ else\r
+ {\r
+ return -1;\r
+ }\r
+}\r
+\r
+void Bitmap::HorizontalOffset(const int y, const double shift)\r
+{\r
+ if(m_bmp)\r
+ {\r
+ int width=Width();\r
+ int height=Height();\r
+ int startx=width-1;\r
+ int endx=ceil(shift);\r
+ int dx=-1;\r
+ int offset1=-(floor(shift));\r
+ int offset2=-(ceil(shift));\r
+ RGBQUAD color1;\r
+ RGBQUAD color2;\r
+ RGBQUAD newcolor;\r
+ double part2=shift-floor(shift);\r
+ double part1=1.0-part2;\r
+\r
+ if(shift<0)\r
+ {\r
+ startx=0;\r
+ endx=width-1-ceil(abs(shift));\r
+ dx=1;\r
+ offset1=-ceil(shift);\r
+ offset2=-floor(shift);\r
+ part2=abs(shift-ceil(shift));\r
+ part1=1.0-part2;\r
+ }\r
+\r
+ FreeImage_GetPixelColor(m_bmp,startx+offset1,(height-1)-y,&color1);\r
+ for(int x=startx+dx; x!=endx; x+=dx)\r
+ {\r
+ FreeImage_GetPixelColor(m_bmp,x+offset2,(height-1)-y,&color2);\r
+ \r
+ newcolor.rgbRed=(color1.rgbRed*part1)+(color2.rgbRed*part2);\r
+ newcolor.rgbGreen=(color1.rgbGreen*part1)+(color2.rgbGreen*part2);\r
+ newcolor.rgbBlue=(color1.rgbBlue*part1)+(color2.rgbBlue*part2);\r
+\r
+ FreeImage_SetPixelColor(m_bmp,x,(height-1)-y,&newcolor);\r
+\r
+ color1=color2;\r
+ }\r
+ }\r
+}\r
+\r
+void Bitmap::Line(const int x1, const int y1, const int x2, const int y2, const RGBQUAD color)\r
+{\r
+ if(m_bmp)\r
+ {\r
+ if(x1!=x2 && y1!=y2)\r
+ {\r
+ AALine(x1,y1,x2,y2,color);\r
+ }\r
+ else\r
+ {\r
+ FastLine(x1,y1,x2,y2,color);\r
+ }\r
+ }\r
+}\r
+\r
+double Bitmap::LineFunction(const double slopex, const double slopey, const int startx, const int starty, const double testx, const double testy)\r
+{\r
+ return fabs(slopex*(testy-starty)-slopey*(testx-startx));\r
+}\r
+\r
+const bool Bitmap::Load(const std::string &typestr, const std::string &filename)\r
+{\r
+ Destroy();\r
+ FREE_IMAGE_FORMAT type=FIF_BMP;\r
+ if(typestr.find("png")!=std::string::npos)\r
+ {\r
+ type=FIF_PNG;\r
+ }\r
+ m_bmp=FreeImage_Load(type,filename.c_str(),0);\r
+ if(m_bmp)\r
+ {\r
+ return true;\r
+ }\r
+ return false;\r
+}\r
+\r
+const bool Bitmap::LoadFromMemory(const std::string &typestr, std::vector<unsigned char> &data)\r
+{\r
+ bool loaded=false;\r
+ Destroy();\r
+ if(data.size()>0)\r
+ {\r
+ FREE_IMAGE_FORMAT type=FIF_BMP;\r
+ if(typestr.find("png")!=std::string::npos)\r
+ {\r
+ type=FIF_PNG;\r
+ }\r
+\r
+ FIMEMORY *mem=FreeImage_OpenMemory((BYTE *)&data[0],data.size());\r
+ m_bmp=FreeImage_LoadFromMemory(type,mem,0);\r
+ if(m_bmp)\r
+ {\r
+ loaded=true;\r
+ }\r
+ FreeImage_CloseMemory(mem);\r
+ }\r
+ return loaded;\r
+}\r
+\r
+Bitmap &Bitmap::operator=(const Bitmap &rhs)\r
+{\r
+ if(this!=&rhs)\r
+ {\r
+ Destroy();\r
+ if(rhs.Width()>0 && rhs.Height()>0)\r
+ {\r
+ m_bmp=FreeImage_Allocate(rhs.Width(),rhs.Height(),rhs.BPP(),0,0,0);\r
+ //FIBITMAP *temp=FreeImage_Copy(rhs.m_bmp,0,0,rhs.Width()-1,rhs.Height()-1);\r
+ //FreeImage_Paste(m_bmp,rhs.m_bmp,0,0,-1);\r
+ //FreeImage_Unload(temp);\r
+ Blit(rhs,0,0,0,0,rhs.Width(),rhs.Height(),-1);\r
+ }\r
+ }\r
+ return *this;\r
+}\r
+\r
+void Bitmap::PutPixel(const int x, const int y, RGBQUAD color)\r
+{\r
+ if(m_bmp && x>=0 && x<FreeImage_GetWidth(m_bmp) && y>=0 && y<FreeImage_GetHeight(m_bmp))\r
+ {\r
+ FreeImage_SetPixelColor(m_bmp,x,(Height()-1)-y,&color);\r
+ }\r
+}\r
+\r
+void Bitmap::Rect(const int x1, const int y1, const int w, const int h, const bool filled, RGBQUAD color)\r
+{\r
+ if(m_bmp)\r
+ {\r
+ int height=Height();\r
+ int width=Width();\r
+ for(int y=y1; y<y1+h; y++)\r
+ {\r
+ if(y>=0 && y<height)\r
+ {\r
+ for(int x=x1; x<x1+w; x++)\r
+ {\r
+ if(x>=0 && x<width)\r
+ {\r
+ if(x==x1 || x==x1+w-1 || y==y1 || y==y1+h-1 || filled)\r
+ {\r
+ FreeImage_SetPixelColor(m_bmp,x,(height-1)-y,&color);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+void Bitmap::Rotate(const double angle, const int shiftx, const int shifty, const int originx, const int originy)\r
+{\r
+ if(m_bmp)\r
+ {\r
+ int height=Height();\r
+ FIBITMAP *old=m_bmp;\r
+ m_bmp=FreeImage_RotateEx(m_bmp,angle,shiftx,-shifty,originx,(height-1)-originy,true);\r
+ FreeImage_Unload(old);\r
+ }\r
+}\r
+\r
+const bool Bitmap::Save(const std::string &filename) const\r
+{\r
+ if(m_bmp)\r
+ {\r
+ FREE_IMAGE_FORMAT type=FIF_BMP;\r
+\r
+ if(filename.find(".png")!=std::string::npos)\r
+ {\r
+ type=FIF_PNG;\r
+ }\r
+\r
+ if(FreeImage_Save(type,m_bmp,filename.c_str(),0))\r
+ {\r
+ return true;\r
+ }\r
+ }\r
+ return false;\r
+}\r
+\r
+const bool Bitmap::SaveToMemory(const std::string &typestr, std::vector<unsigned char> &data) const\r
+{\r
+ bool saved=false;\r
+ if(m_bmp)\r
+ {\r
+ FREE_IMAGE_FORMAT type=FIF_BMP;\r
+ if(typestr.find("png")!=std::string::npos)\r
+ {\r
+ type=FIF_PNG;\r
+ }\r
+ FIMEMORY *mem=FreeImage_OpenMemory(0,0);\r
+ if(FreeImage_SaveToMemory(type,m_bmp,mem,0))\r
+ {\r
+ FreeImage_SeekMemory(mem,0,SEEK_END);\r
+ data.resize(FreeImage_TellMemory(mem));\r
+ FreeImage_SeekMemory(mem,0,SEEK_SET);\r
+ FreeImage_ReadMemory(&data[0],1,data.size(),mem);\r
+ saved=true;\r
+ }\r
+ FreeImage_CloseMemory(mem);\r
+ }\r
+ return saved;\r
+}\r
+\r
+void Bitmap::SetTransparent()\r
+{\r
+ if(m_bmp)\r
+ {\r
+ FreeImage_SetTransparent(m_bmp,true);\r
+ }\r
+}\r
+\r
+void Bitmap::VerticalOffset(const int x, const double shift)\r
+{\r
+ if(m_bmp)\r
+ {\r
+ int width=Width();\r
+ int height=Height();\r
+ int starty=width-1;\r
+ int endy=ceil(shift);\r
+ int dy=-1;\r
+ int offset1=-(floor(shift));\r
+ int offset2=-(ceil(shift));\r
+ RGBQUAD color1;\r
+ RGBQUAD color2;\r
+ RGBQUAD newcolor;\r
+ double part2=shift-floor(shift);\r
+ double part1=1.0-part2;\r
+\r
+ if(shift<0)\r
+ {\r
+ starty=0;\r
+ endy=width-1-ceil(abs(shift));\r
+ dy=1;\r
+ offset1=-ceil(shift);\r
+ offset2=-floor(shift);\r
+ part2=abs(shift-ceil(shift));\r
+ part1=1.0-part2;\r
+ }\r
+\r
+ FreeImage_GetPixelColor(m_bmp,x,(height-1)-(starty+offset1),&color1);\r
+ for(int y=starty+dy; y!=endy; y+=dy)\r
+ {\r
+ FreeImage_GetPixelColor(m_bmp,x,(height-1)-(y+offset2),&color2);\r
+ \r
+ newcolor.rgbRed=(color1.rgbRed*part1)+(color2.rgbRed*part2);\r
+ newcolor.rgbGreen=(color1.rgbGreen*part1)+(color2.rgbGreen*part2);\r
+ newcolor.rgbBlue=(color1.rgbBlue*part1)+(color2.rgbBlue*part2);\r
+\r
+ FreeImage_SetPixelColor(m_bmp,x,(height-1)-y,&newcolor);\r
+\r
+ color1=color2;\r
+ }\r
+ }\r
+}\r
+\r
+} // namespace FreeImage\r