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