version 0.3.14
[fms.git] / src / freenet / captcha / freeimage / bitmap.cpp
diff --git a/src/freenet/captcha/freeimage/bitmap.cpp b/src/freenet/captcha/freeimage/bitmap.cpp
new file mode 100644 (file)
index 0000000..4c90fc1
--- /dev/null
@@ -0,0 +1,661 @@
+#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