version 0.3.17
[fms.git] / src / freenet / captcha / alternatecaptcha2.cpp
1 #include "../../../include/freenet/captcha/alternatecaptcha2.h"\r
2 \r
3 #include <Poco/Path.h>\r
4 #include <Poco/DirectoryIterator.h>\r
5 \r
6 #include <cmath>\r
7 #include <vector>\r
8 #include <cstdlib>\r
9 \r
10 #ifdef ALTERNATE_CAPTCHA\r
11 \r
12 AlternateCaptcha2::AlternateCaptcha2()\r
13 {\r
14         AlternateCaptchaFonts fonts;\r
15         m_fonts=fonts.Fonts();\r
16 }\r
17 \r
18 void AlternateCaptcha2::Generate()\r
19 {\r
20         if(m_fonts.size()==0)\r
21         {\r
22                 return;\r
23         }\r
24 \r
25         std::string puzzlestring=GenerateRandomString(6);\r
26         std::vector<int> fontnums(puzzlestring.size(),0);\r
27         \r
28         m_solution.clear();\r
29         m_puzzle.clear();\r
30         \r
31         FreeImage::Bitmap bigbmp(300,300,32);\r
32         bigbmp.SetTransparent();\r
33 \r
34         // get total width of text\r
35         int textwidth=0;\r
36         for(int i=0; i<puzzlestring.size(); i++)\r
37         {\r
38                 fontnums[i]=rand()%m_fonts.size();\r
39                 textwidth+=m_fonts[fontnums[i]].Char(puzzlestring[i]).Width();\r
40         }\r
41 \r
42         RGBQUAD white;\r
43         white.rgbRed=255;\r
44         white.rgbGreen=255;\r
45         white.rgbBlue=255;\r
46         white.rgbReserved=255;\r
47         int numlines=(rand()%3)+2;\r
48         for(int i=0; i<numlines; i++)\r
49         {\r
50                 int x1=rand()%150;\r
51                 int y1=(rand()%80)+110;\r
52                 int x2=(rand()%150)+150;\r
53                 int y2=(rand()%80)+110;\r
54                 bigbmp.Line(x1,y1,x2,y2,white);\r
55                 bigbmp.Line(x1+1,y1,x2+1,y2,white);\r
56         }\r
57         \r
58         // draw the text on the bigbmp centered\r
59         int currentx=150-(textwidth/2);\r
60         for(int i=0; i<puzzlestring.size(); i++)\r
61         {\r
62                 FreeImage::Bitmap charbmp=m_fonts[fontnums[i]].Char(puzzlestring[i]);\r
63                 bigbmp.BlitTrans(charbmp,currentx,150-(charbmp.Height()/2),0,0,charbmp.Width(),charbmp.Height());\r
64                 currentx+=m_fonts[fontnums[i]].Char(puzzlestring[i]).Width();//+1;\r
65         }\r
66         \r
67         // rotate and skew the big bitmap a few times\r
68         int lastrot=0;\r
69         int thisrot=0;\r
70         int numrots=(rand()%4)+4;\r
71         for(int i=0; i<numrots; i++)\r
72         {\r
73                 thisrot=((rand()%180)-90);\r
74                 bigbmp.Rotate(-lastrot+thisrot,0,0,150,150);\r
75                 int offset=rand()%10000;\r
76                 float freq=3.0+(float(rand()%7000)/1000.0);\r
77                 float amp=1.0+(float(rand()%1000)/500.0);\r
78                 for(int y=0; y<bigbmp.Height(); y++)\r
79                 {\r
80                         double shift=sin((double)(y+offset)/freq)*amp;\r
81                         bigbmp.HorizontalOffset(y,shift);\r
82                 }\r
83                 lastrot=thisrot;\r
84         }\r
85 \r
86         // rotate the big bitmap back to (almost) horizontal\r
87         bigbmp.Rotate(-lastrot+((rand()%20)-10),0,0,150,150);\r
88 \r
89         // grab the center of the big bitmap as the final bitmap\r
90         FreeImage::Bitmap bmp(110,50,32);\r
91         bmp.SetTransparent();\r
92         bmp.Blit(bigbmp,0,0,95,125,110,50,255);\r
93 \r
94         m_solution.insert(m_solution.end(),puzzlestring.begin(),puzzlestring.end());\r
95         bmp.SaveToMemory("bmp",m_puzzle);\r
96 \r
97 }\r
98 \r
99 const std::string AlternateCaptcha2::GenerateRandomString(const int len)\r
100 {\r
101         // no l,1 O,0 because they look too much alike\r
102         static std::string chars="abcdefghijkmnopqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ23456789@#";\r
103         std::string temp="";\r
104         for(int i=0; i<len; i++)\r
105         {\r
106                 temp+=chars[rand()%chars.size()];\r
107         }\r
108         return temp;\r
109 }\r
110 \r
111 const bool AlternateCaptcha2::GetPuzzle(std::vector<unsigned char> &puzzle)\r
112 {\r
113         puzzle=m_puzzle;\r
114         return true;\r
115 }\r
116 \r
117 const bool AlternateCaptcha2::GetSolution(std::vector<unsigned char> &solution)\r
118 {\r
119         solution=m_solution;\r
120         return true;\r
121 }\r
122 \r
123 #endif  // ALTERNATE_CAPTCHA\r