├── Captcha.pro
├── Captcha.sln
├── Captcha.vcxproj
├── Generate VC Project.bat
├── LICENSE.txt
├── README.md
├── captcha.cpp
├── captcha.h
├── dialog.cpp
├── dialog.h
├── dialog.ui
├── difficultylevels.jpg
└── main.cpp
/Captcha.pro:
--------------------------------------------------------------------------------
1 | #-------------------------------------------------
2 | #
3 | # Project created by QtCreator 2014-05-12T15:45:08
4 | #
5 | #-------------------------------------------------
6 |
7 | QT += core gui
8 |
9 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
10 |
11 | TARGET = Captcha
12 | TEMPLATE = app
13 |
14 |
15 | SOURCES += main.cpp\
16 | captcha.cpp \
17 | dialog.cpp
18 |
19 |
20 | HEADERS += dialog.h \
21 | captcha.h
22 |
23 | FORMS += dialog.ui
24 |
--------------------------------------------------------------------------------
/Captcha.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Express 2013 for Windows Desktop
4 | VisualStudioVersion = 12.0.30110.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Captcha", "Captcha.vcxproj", "{F19E1CA4-CE81-3016-AB44-89501511C06A}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|x64 = Debug|x64
11 | Release|x64 = Release|x64
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {F19E1CA4-CE81-3016-AB44-89501511C06A}.Debug|x64.ActiveCfg = Debug|x64
15 | {F19E1CA4-CE81-3016-AB44-89501511C06A}.Debug|x64.Build.0 = Debug|x64
16 | {F19E1CA4-CE81-3016-AB44-89501511C06A}.Release|x64.ActiveCfg = Release|x64
17 | {F19E1CA4-CE81-3016-AB44-89501511C06A}.Release|x64.Build.0 = Release|x64
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | EndGlobal
23 |
--------------------------------------------------------------------------------
/Captcha.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Release
6 | x64
7 |
8 |
9 | Debug
10 | x64
11 |
12 |
13 |
14 | {F19E1CA4-CE81-3016-AB44-89501511C06A}
15 | Captcha
16 | Qt4VSv1.0
17 |
18 |
19 |
20 | v120
21 | release\
22 | false
23 | NotSet
24 | Application
25 | release\
26 | Captcha
27 |
28 |
29 | v120
30 | debug\
31 | false
32 | NotSet
33 | Application
34 | debug\
35 | Captcha
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | release\
48 | release\
49 | Captcha
50 | true
51 | false
52 | debug\
53 | debug\
54 | Captcha
55 | true
56 |
57 |
58 |
59 | "C:\Qt\Qt5.3.0\5.3\msvc2013_64_opengl\include";"C:\Qt\Qt5.3.0\5.3\msvc2013_64_opengl\include\QtWidgets";"C:\Qt\Qt5.3.0\5.3\msvc2013_64_opengl\include\QtGui";"C:\Qt\Qt5.3.0\5.3\msvc2013_64_opengl\include\QtCore";"release";".";C:\Qt\Qt5.3.0\5.3\msvc2013_64_opengl\mkspecs\win32-msvc2013;%(AdditionalIncludeDirectories)
60 | -Zm200 -w34100 -w34189 %(AdditionalOptions)
61 | release\
62 | false
63 | None
64 | Sync
65 | release\
66 | MaxSpeed
67 | _WINDOWS;UNICODE;WIN32;WIN64;QT_NO_DEBUG;QT_WIDGETS_LIB;QT_GUI_LIB;QT_CORE_LIB;NDEBUG;%(PreprocessorDefinitions)
68 | false
69 |
70 | MultiThreadedDLL
71 | true
72 | true
73 | true
74 | Level3
75 |
76 |
77 | glu32.lib;opengl32.lib;gdi32.lib;user32.lib;qtmain.lib;C:\Qt\Qt5.3.0\5.3\msvc2013_64_opengl\lib\Qt5Widgets.lib;C:\Qt\Qt5.3.0\5.3\msvc2013_64_opengl\lib\Qt5Gui.lib;C:\Qt\Qt5.3.0\5.3\msvc2013_64_opengl\lib\Qt5Core.lib;%(AdditionalDependencies)
78 | C:\Qt\Qt5.3.0\5.3\msvc2013_64_opengl\lib;%(AdditionalLibraryDirectories)
79 | "/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions)
80 | true
81 | false
82 | true
83 | false
84 | $(OutDir)\Captcha.exe
85 | true
86 | Windows
87 | true
88 |
89 |
90 | Unsigned
91 | None
92 | 0
93 |
94 |
95 | _WINDOWS;UNICODE;WIN32;WIN64;QT_NO_DEBUG;QT_WIDGETS_LIB;QT_GUI_LIB;QT_CORE_LIB;%(PreprocessorDefinitions)
96 |
97 |
98 |
99 |
100 | "C:\Qt\Qt5.3.0\5.3\msvc2013_64_opengl\include";"C:\Qt\Qt5.3.0\5.3\msvc2013_64_opengl\include\QtWidgets";"C:\Qt\Qt5.3.0\5.3\msvc2013_64_opengl\include\QtGui";"C:\Qt\Qt5.3.0\5.3\msvc2013_64_opengl\include\QtCore";"debug";".";C:\Qt\Qt5.3.0\5.3\msvc2013_64_opengl\mkspecs\win32-msvc2013;%(AdditionalIncludeDirectories)
101 | -Zm200 -w34100 -w34189 %(AdditionalOptions)
102 | debug\
103 | false
104 | ProgramDatabase
105 | Sync
106 | debug\
107 | Disabled
108 | _WINDOWS;UNICODE;WIN32;WIN64;QT_WIDGETS_LIB;QT_GUI_LIB;QT_CORE_LIB;%(PreprocessorDefinitions)
109 | false
110 | MultiThreadedDebugDLL
111 | true
112 | true
113 | true
114 | Level3
115 |
116 |
117 | glu32.lib;opengl32.lib;gdi32.lib;user32.lib;qtmaind.lib;C:\Qt\Qt5.3.0\5.3\msvc2013_64_opengl\lib\Qt5Widgetsd.lib;C:\Qt\Qt5.3.0\5.3\msvc2013_64_opengl\lib\Qt5Guid.lib;C:\Qt\Qt5.3.0\5.3\msvc2013_64_opengl\lib\Qt5Cored.lib;%(AdditionalDependencies)
118 | C:\Qt\Qt5.3.0\5.3\msvc2013_64_opengl\lib;%(AdditionalLibraryDirectories)
119 | "/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions)
120 | true
121 | true
122 | true
123 | $(OutDir)\Captcha.exe
124 | true
125 | Windows
126 | true
127 |
128 |
129 | Unsigned
130 | None
131 | 0
132 |
133 |
134 | _WINDOWS;UNICODE;WIN32;WIN64;QT_WIDGETS_LIB;QT_GUI_LIB;QT_CORE_LIB;_DEBUG;%(PreprocessorDefinitions)
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 | captcha.h;%(AdditionalInputs)
145 | C:\Qt\Qt5.3.0\5.3\msvc2013_64_opengl\bin\moc.exe -DUNICODE -DWIN32 -DWIN64 -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -D_MSC_VER=1800 -D_WIN32 -D_WIN64 -IC:/Qt/Qt5.3.0/5.3/msvc2013_64_opengl/mkspecs/win32-msvc2013 -IC:/Users/Omkar.Omkar-PC/Documents/QT5-Projects/Captcha -IC:/Qt/Qt5.3.0/5.3/msvc2013_64_opengl/include -IC:/Qt/Qt5.3.0/5.3/msvc2013_64_opengl/include/QtWidgets -IC:/Qt/Qt5.3.0/5.3/msvc2013_64_opengl/include/QtGui -IC:/Qt/Qt5.3.0/5.3/msvc2013_64_opengl/include/QtCore captcha.h -o release\moc_captcha.cpp
146 | MOC captcha.h
147 | release\moc_captcha.cpp;%(Outputs)
148 | captcha.h;%(AdditionalInputs)
149 | C:\Qt\Qt5.3.0\5.3\msvc2013_64_opengl\bin\moc.exe -DUNICODE -DWIN32 -DWIN64 -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -D_MSC_VER=1800 -D_WIN32 -D_WIN64 -IC:/Qt/Qt5.3.0/5.3/msvc2013_64_opengl/mkspecs/win32-msvc2013 -IC:/Users/Omkar.Omkar-PC/Documents/QT5-Projects/Captcha -IC:/Qt/Qt5.3.0/5.3/msvc2013_64_opengl/include -IC:/Qt/Qt5.3.0/5.3/msvc2013_64_opengl/include/QtWidgets -IC:/Qt/Qt5.3.0/5.3/msvc2013_64_opengl/include/QtGui -IC:/Qt/Qt5.3.0/5.3/msvc2013_64_opengl/include/QtCore captcha.h -o debug\moc_captcha.cpp
150 | MOC captcha.h
151 | debug\moc_captcha.cpp;%(Outputs)
152 |
153 |
154 | dialog.h;%(AdditionalInputs)
155 | C:\Qt\Qt5.3.0\5.3\msvc2013_64_opengl\bin\moc.exe -DUNICODE -DWIN32 -DWIN64 -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -D_MSC_VER=1800 -D_WIN32 -D_WIN64 -IC:/Qt/Qt5.3.0/5.3/msvc2013_64_opengl/mkspecs/win32-msvc2013 -IC:/Users/Omkar.Omkar-PC/Documents/QT5-Projects/Captcha -IC:/Qt/Qt5.3.0/5.3/msvc2013_64_opengl/include -IC:/Qt/Qt5.3.0/5.3/msvc2013_64_opengl/include/QtWidgets -IC:/Qt/Qt5.3.0/5.3/msvc2013_64_opengl/include/QtGui -IC:/Qt/Qt5.3.0/5.3/msvc2013_64_opengl/include/QtCore dialog.h -o release\moc_dialog.cpp
156 | MOC dialog.h
157 | release\moc_dialog.cpp;%(Outputs)
158 | dialog.h;%(AdditionalInputs)
159 | C:\Qt\Qt5.3.0\5.3\msvc2013_64_opengl\bin\moc.exe -DUNICODE -DWIN32 -DWIN64 -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -D_MSC_VER=1800 -D_WIN32 -D_WIN64 -IC:/Qt/Qt5.3.0/5.3/msvc2013_64_opengl/mkspecs/win32-msvc2013 -IC:/Users/Omkar.Omkar-PC/Documents/QT5-Projects/Captcha -IC:/Qt/Qt5.3.0/5.3/msvc2013_64_opengl/include -IC:/Qt/Qt5.3.0/5.3/msvc2013_64_opengl/include/QtWidgets -IC:/Qt/Qt5.3.0/5.3/msvc2013_64_opengl/include/QtGui -IC:/Qt/Qt5.3.0/5.3/msvc2013_64_opengl/include/QtCore dialog.h -o debug\moc_dialog.cpp
160 | MOC dialog.h
161 | debug\moc_dialog.cpp;%(Outputs)
162 |
163 |
164 |
165 |
166 | true
167 |
168 |
169 | true
170 |
171 |
172 | true
173 |
174 |
175 | true
176 |
177 |
178 |
179 |
180 |
181 | Document
182 | dialog.ui;%(AdditionalInputs)
183 | C:\Qt\Qt5.3.0\5.3\msvc2013_64_opengl\bin\uic.exe dialog.ui -o ui_dialog.h
184 | UIC dialog.ui
185 | ui_dialog.h;%(Outputs)
186 | dialog.ui;%(AdditionalInputs)
187 | C:\Qt\Qt5.3.0\5.3\msvc2013_64_opengl\bin\uic.exe dialog.ui -o ui_dialog.h
188 | UIC dialog.ui
189 | ui_dialog.h;%(Outputs)
190 |
191 |
192 |
193 |
194 |
--------------------------------------------------------------------------------
/Generate VC Project.bat:
--------------------------------------------------------------------------------
1 | qmake -spec win32-msvc2013 -tp vc
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2014 Omkar Kanase
2 |
3 | This software is provided 'as-is', without any express or implied
4 | warranty. In no event will the authors be held liable for any damages
5 | arising from the use of this software.
6 | Permission is granted to anyone to use this software for any purpose,
7 | including commercial applications, and to alter it and redistribute it
8 | freely, subject to the following restrictions:
9 | 1. The origin of this software must not be misrepresented; you must not
10 | claim that you wrote the original software. If you use this software
11 | in a product, an acknowledgment in the product documentation would be
12 | appreciated but is not required.
13 | 2. Altered source versions must be plainly marked as such, and must not be
14 | misrepresented as being the original software.
15 | 3. This notice may not be removed or altered from any source distribution.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | QtCaptcha 1.0
2 | =========
3 |
4 | Captcha generator for Qt
5 |
6 | Usage Example :
7 |
8 | QPainter painter(this);
9 | Captcha cp;
10 | cp.generateText();
11 | painter.drawImage(30, 30, cp.captchaImage());
12 |
13 |
14 | Example 2 :
15 |
16 | QPainter painter(this);
17 | Captcha cp;
18 | cp.randomize();
19 | cp.setDifficulty(3);
20 | cp.generateText();
21 | painter.drawImage(30, 30, cp.captchaImage());
22 |
23 | Example 3 (using predefined words dictionary) :
24 |
25 | QPainter painter(this);
26 | Captcha cp;
27 | cp.randomize();
28 | cp.setDifficulty(3);
29 | cp.loadDictionary("dictionary.txt");
30 | cp.setTextGeneration(Captcha::TextGeneration_Dictionary);
31 | cp.generateText();
32 | painter.drawImage(30, 30, cp.captchaImage());
33 |
34 | Difficulty Levels Screen shot:
35 |
36 | 
37 |
38 | Performance (intel Core i7 2630QM 2.0GHz / Single Thread):
39 |
40 | - Difficulty 0 : 1068/s
41 | - Difficulty 1 : 975/s
42 | - Difficulty 2 : 843/s
43 | - Difficulty 3 : 560/s
44 | - Difficulty 4 : 534/s
45 | - Difficulty 5 : 412/s
46 |
47 | Performance (intel Core i7 2630QM 2.0GHz / Multi Thread):
48 |
49 | - Difficulty 0:
50 |
51 | - 2 Threads : 2324
52 | - 4 Threads : 2686
53 | - 8 Threads : 2718
54 |
55 | - Difficulty 1:
56 |
57 | - 2 Threads : 2155
58 | - 4 Threads : 2558
59 | - 8 Threads : 3119
60 |
61 | - Difficulty 2:
62 |
63 | - 2 Threads : 1943
64 | - 4 Threads : 2660
65 | - 8 Threads : 2790
66 |
67 | - Difficulty 3:
68 |
69 | - 2 Threads : 1338
70 | - 4 Threads : 1604
71 | - 8 Threads : 1503
72 |
73 | - Difficulty 4:
74 |
75 | - 2 Threads : 1329
76 | - 4 Threads : 1594
77 | - 8 Threads : 1510
78 |
--------------------------------------------------------------------------------
/captcha.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2014 Omkar Kanase
3 | *
4 | * This software is provided 'as-is', without any express or implied
5 | * warranty. In no event will the authors be held liable for any damages
6 | * arising from the use of this software.
7 | * Permission is granted to anyone to use this software for any purpose,
8 | * including commercial applications, and to alter it and redistribute it
9 | * freely, subject to the following restrictions:
10 | * 1. The origin of this software must not be misrepresented; you must not
11 | * claim that you wrote the original software. If you use this software
12 | * in a product, an acknowledgment in the product documentation would be
13 | * appreciated but is not required.
14 | * 2. Altered source versions must be plainly marked as such, and must not be
15 | * misrepresented as being the original software.
16 | * 3. This notice may not be removed or altered from any source distribution.
17 | */
18 |
19 | #include "captcha.h"
20 |
21 | Captcha::Captcha(QObject *parent) :
22 | QObject(parent)
23 | {
24 | m_hmod1 = 0.0;
25 | m_hmod2 = 0.0;
26 |
27 | m_vmod1 = 0.0;
28 | m_vmod2 = 0.0;
29 |
30 | m_font.setStyleStrategy(QFont::ForceOutline);
31 | m_font.setPointSize(30);
32 | m_font.setBold(true);
33 | m_font.setLetterSpacing(QFont::PercentageSpacing, QFont::SemiCondensed);
34 |
35 | m_captchaImage = QImage(200, 100, QImage::Format_RGB32);
36 | m_deformationType = Deform_SinCurve;
37 | m_captchaText = "Test";
38 |
39 | m_textGeneration = TextGeneration_Random;
40 | m_fontColor = Qt::black;
41 | m_backColor = Qt::white;
42 | m_padding = 5;
43 |
44 | m_drawLines = true;
45 | m_drawEllipses = true;
46 | m_drawNoise = true;
47 | m_noiseCount = 100;
48 | m_lineCount = 5;
49 | m_ellipseCount = 1;
50 |
51 | m_lineWidth = 2;
52 | m_ellipseMinRadius = 20;
53 | m_ellipseMaxRadius = 40;
54 |
55 | m_noisePointSize = 3;
56 |
57 | setSinDeform(8, 10, 5, 15);
58 | }
59 |
60 | void Captcha::setDifficulty(int val)
61 | {
62 | if (val == 0)
63 | {
64 | m_drawLines = false;
65 | m_drawEllipses = false;
66 | m_drawNoise = false;
67 | setSinDeform(10, 10, 5, 20);
68 | }
69 | else if (val == 1)
70 | {
71 | m_drawLines = true;
72 | m_lineWidth = 3;
73 | m_lineCount = 5;
74 | m_drawEllipses = false;
75 | m_drawNoise = false;
76 | setSinDeform(10, 15, 5, 20);
77 | }
78 | else if (val == 2)
79 | {
80 | m_drawLines = true;
81 | m_lineWidth = 2;
82 | m_lineCount = 5;
83 | m_drawEllipses = true;
84 | m_ellipseCount = 1;
85 | m_ellipseMinRadius = 20;
86 | m_ellipseMaxRadius = 40;
87 | m_drawNoise = false;
88 | setSinDeform(10, 15, 5, 15);
89 | }
90 | else if (val == 3)
91 | {
92 | m_drawLines = true;
93 | m_lineWidth = 2;
94 | m_lineCount = 3;
95 | m_drawEllipses = true;
96 | m_ellipseCount = 1;
97 | m_ellipseMinRadius = 20;
98 | m_ellipseMaxRadius = 40;
99 | m_drawNoise = true;
100 | m_noiseCount = 100;
101 | m_noisePointSize = 3;
102 | setSinDeform(8, 13, 5, 15);
103 | }
104 | else if (val == 4)
105 | {
106 | m_drawLines = true;
107 | m_lineWidth = 3;
108 | m_lineCount = 5;
109 | m_drawEllipses = true;
110 | m_ellipseCount = 1;
111 | m_ellipseMinRadius = 20;
112 | m_ellipseMaxRadius = 40;
113 | m_drawNoise = true;
114 | m_noiseCount = 100;
115 | m_noisePointSize = 3;
116 | setSinDeform(8, 10, 5, 10);
117 | }
118 | else
119 | {
120 | m_drawLines = true;
121 | m_lineWidth = 4;
122 | m_lineCount = 7;
123 | m_drawEllipses = true;
124 | m_ellipseCount = 1;
125 | m_ellipseMinRadius = 20;
126 | m_ellipseMaxRadius = 40;
127 | m_drawNoise = true;
128 | m_noiseCount = 200;
129 | m_noisePointSize = 3;
130 | setSinDeform(8, 10, 5, 10);
131 | }
132 | }
133 |
134 | QFont Captcha::font() const
135 | {
136 | return m_font;
137 | }
138 |
139 | QImage Captcha::captchaImage() const
140 | {
141 | return m_captchaImage;
142 | }
143 |
144 | Captcha::DeformType Captcha::deformationType() const
145 | {
146 | return m_deformationType;
147 | }
148 |
149 | QString Captcha::captchaText() const
150 | {
151 | return m_captchaText;
152 | }
153 |
154 | Captcha::TextGenerationMode Captcha::textGeneration() const
155 | {
156 | return m_textGeneration;
157 | }
158 |
159 | const QStringList &Captcha::dictionary() const
160 | {
161 | return m_dictionary;
162 | }
163 |
164 | QColor Captcha::fontColor() const
165 | {
166 | return m_fontColor;
167 | }
168 |
169 | QColor Captcha::backColor() const
170 | {
171 | return m_backColor;
172 | }
173 |
174 | bool Captcha::drawLines() const
175 | {
176 | return m_drawLines;
177 | }
178 |
179 | bool Captcha::drawEllipses() const
180 | {
181 | return m_drawEllipses;
182 | }
183 |
184 | bool Captcha::drawNoise() const
185 | {
186 | return m_drawNoise;
187 | }
188 |
189 | int Captcha::noiseCount() const
190 | {
191 | return m_noiseCount;
192 | }
193 |
194 | int Captcha::lineCount() const
195 | {
196 | return m_lineCount;
197 | }
198 |
199 | int Captcha::ellipseCount() const
200 | {
201 | return m_ellipseCount;
202 | }
203 |
204 | int Captcha::lineWidth() const
205 | {
206 | return m_lineWidth;
207 | }
208 |
209 | int Captcha::ellipseMinRadius() const
210 | {
211 | return m_ellipseMinRadius;
212 | }
213 |
214 | int Captcha::ellipseMaxRadius() const
215 | {
216 | return m_ellipseMaxRadius;
217 | }
218 |
219 | int Captcha::noisePointSize() const
220 | {
221 | return m_noisePointSize;
222 | }
223 |
224 | void Captcha::setFont(const QFont &arg)
225 | {
226 | m_font = arg;
227 | }
228 |
229 | void Captcha::setDeformationType(Captcha::DeformType arg)
230 | {
231 | m_deformationType = arg;
232 | }
233 |
234 | void Captcha::updateCaptcha()
235 | {
236 | QPainterPath path;
237 | QFontMetrics fm(m_font);
238 |
239 | if (m_deformationType == Deform_SinCurve)
240 | {
241 |
242 | path.addText(m_vmod2 + m_padding, m_hmod2 - m_padding + fm.height(), font(), captchaText());
243 |
244 | qreal sinrandomness = ((qreal) qrand() / RAND_MAX) * 5.0;
245 |
246 | for (int i = 0; i < path.elementCount(); ++i)
247 | {
248 | const QPainterPath::Element& el = path.elementAt(i);
249 | qreal y = el.y + sin(el.x / m_hmod1 + sinrandomness) * m_hmod2;
250 | qreal x = el.x + sin(el.y / m_vmod1 + sinrandomness) * m_vmod2;
251 | path.setElementPositionAt(i, x, y);
252 | }
253 |
254 | m_captchaImage = QImage(fm.width(m_captchaText) + m_vmod2 * 2 + m_padding * 2, fm.height() + m_hmod2 * 2 + m_padding * 2, QImage::Format_RGB32);
255 | }
256 |
257 | m_captchaImage.fill(backColor());
258 | QPainter painter;
259 | painter.begin(&m_captchaImage);
260 | painter.setPen(Qt::NoPen);
261 | painter.setBrush(fontColor());
262 | painter.setRenderHint(QPainter::Antialiasing);
263 | painter.drawPath(path);
264 |
265 | if (m_drawLines)
266 | {
267 | painter.setPen(QPen(Qt::black, m_lineWidth));
268 | for (int i = 0; i < m_lineCount; i++)
269 | {
270 | int x1 = ((qreal) qrand() / RAND_MAX) * m_captchaImage.width();
271 | int y1 = ((qreal) qrand() / RAND_MAX) * m_captchaImage.height();
272 | int x2 = ((qreal) qrand() / RAND_MAX) * m_captchaImage.width();
273 | int y2 = ((qreal) qrand() / RAND_MAX) * m_captchaImage.height();
274 | painter.drawLine(x1, y1, x2, y2);
275 | }
276 | painter.setPen(Qt::NoPen);
277 | }
278 |
279 | if (m_drawEllipses)
280 | {
281 | for (int i = 0; i < m_ellipseCount; i++)
282 | {
283 | int x1 = m_ellipseMaxRadius / 2.0 + ((qreal) qrand() / RAND_MAX) * (m_captchaImage.width() - m_ellipseMaxRadius);
284 | int y1 = m_ellipseMaxRadius / 2.0 + ((qreal) qrand() / RAND_MAX) * (m_captchaImage.height() - m_ellipseMaxRadius);
285 | int rad1 = m_ellipseMinRadius + ((qreal) qrand() / RAND_MAX) * (m_ellipseMaxRadius - m_ellipseMinRadius);
286 | int rad2 = m_ellipseMinRadius + ((qreal) qrand() / RAND_MAX) * (m_ellipseMaxRadius - m_ellipseMinRadius);
287 | painter.setBrush(backColor());
288 | painter.setCompositionMode(QPainter::CompositionMode_Difference);
289 | painter.drawEllipse(QPoint(x1, y1), rad1, rad2);
290 | }
291 | }
292 |
293 | if (m_drawNoise)
294 | {
295 | for (int i = 0; i < m_noiseCount; i++)
296 | {
297 | int x1 = ((qreal) qrand() / RAND_MAX) * m_captchaImage.width();
298 | int y1 = ((qreal) qrand() / RAND_MAX) * m_captchaImage.height();
299 |
300 | QColor col = QColor(((qreal) qrand() / RAND_MAX) * 255, ((qreal) qrand() / RAND_MAX) * 255, ((qreal) qrand() / RAND_MAX) * 255);
301 |
302 | painter.setPen(QPen(col, m_noisePointSize));
303 | painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
304 | painter.drawPoint(x1, y1);
305 | }
306 | }
307 | painter.end();
308 | emit catpchaGenerated(m_captchaImage, m_captchaText);
309 | }
310 |
311 | void Captcha::randomize()
312 | {
313 | qsrand(QTime::currentTime().msec());
314 | }
315 |
316 | void Captcha::setCaptchaText(QString arg)
317 | {
318 | m_captchaText = arg;
319 | }
320 |
321 | void Captcha::setTextGeneration(Captcha::TextGenerationMode arg)
322 | {
323 | if (m_textGeneration != arg) generateText(m_captchaText.size());
324 | m_textGeneration = arg;
325 | }
326 |
327 | void Captcha::setDictionary(const QStringList &arg)
328 | {
329 | m_dictionary = arg;
330 | }
331 |
332 | void Captcha::loadDictionary(QString FileName)
333 | {
334 | QFile file(FileName);
335 | if (!file.open(QIODevice::ReadOnly))
336 | {
337 | qCritical() << "Unable to open dictionary file";
338 | return;
339 | }
340 |
341 | m_dictionary.clear();
342 | QTextStream text(&file);
343 | QString str = text.readLine();
344 | while (str.size() > 0)
345 | {
346 | m_dictionary.append(str);
347 | str = text.readLine();
348 | }
349 |
350 | if (m_dictionary.size() <= 0)
351 | {
352 | qWarning() << "No data loaded from dictionary file";
353 | }
354 | }
355 |
356 | void Captcha::setFontColor(QColor arg)
357 | {
358 | m_fontColor = arg;
359 | }
360 |
361 | void Captcha::setBackColor(QColor arg)
362 | {
363 | m_backColor = arg;
364 | }
365 |
366 | void Captcha::setSinDeform(qreal hAmplitude, qreal hFrequency, qreal vAmplitude, qreal vFrequency)
367 | {
368 | m_deformationType = Deform_SinCurve;
369 | m_hmod1 = hFrequency;
370 | m_hmod2 = hAmplitude;
371 |
372 | m_vmod1 = vFrequency;
373 | m_vmod2 = vAmplitude;
374 | }
375 |
376 | QPair Captcha::generateCaptcha()
377 | {
378 | generateText(m_captchaText.size());
379 | return QPair(m_captchaText, m_captchaImage);
380 | }
381 |
382 | void Captcha::setDrawLines(bool arg)
383 | {
384 | m_drawLines = arg;
385 | }
386 |
387 | void Captcha::setDrawEllipses(bool arg)
388 | {
389 | m_drawEllipses = arg;
390 | }
391 |
392 | void Captcha::setDrawNoise(bool arg)
393 | {
394 | m_drawNoise = arg;
395 | }
396 |
397 | void Captcha::setNoiseCount(int arg)
398 | {
399 | m_noiseCount = arg;
400 | }
401 |
402 | void Captcha::setLineCount(int arg)
403 | {
404 | m_lineCount = arg;
405 | }
406 |
407 | void Captcha::setEllipseCount(int arg)
408 | {
409 | m_ellipseCount = arg;
410 | }
411 |
412 | void Captcha::setLineWidth(int arg)
413 | {
414 | m_lineWidth = arg;
415 | }
416 |
417 | void Captcha::setEllipseMinRadius(int arg)
418 | {
419 | m_ellipseMinRadius = arg;
420 | }
421 |
422 | void Captcha::setEllipseMaxRadius(int arg)
423 | {
424 | m_ellipseMaxRadius = arg;
425 | }
426 |
427 | void Captcha::setNoisePointSize(int arg)
428 | {
429 | m_noisePointSize = arg;
430 | }
431 |
432 | void Captcha::generateText(int noOfChars, bool includeNumbers, bool includeSymbols, bool allCapital)
433 | {
434 | if (noOfChars <= 0)
435 | {
436 | qWarning() << "Unable to generate text : Invalid number of characters";
437 | return;
438 | }
439 |
440 | QString text;
441 |
442 | if (m_textGeneration == TextGeneration_Random)
443 | {
444 | QVector chars;
445 | for (int i = 0; i < noOfChars * 2; i++)
446 | {
447 | chars.push_back(65 + ((qreal) qrand() / RAND_MAX) * (90 - 65));
448 | if (!allCapital) chars.push_back(97 + ((qreal) qrand() / RAND_MAX) * (122 - 97));
449 | if (includeNumbers) chars.push_back(48 + ((qreal) qrand() / RAND_MAX) * (57 - 48));
450 | if (includeSymbols) chars.push_back(33 + ((qreal) qrand() / RAND_MAX) * (47 - 33));
451 | }
452 |
453 | for (int i = 0; i < noOfChars; i++)
454 | {
455 | text += chars[(qrand() / (qreal) RAND_MAX) * (chars.size() - 1.0)];
456 | }
457 |
458 | m_captchaText = text;
459 | }
460 | else if (m_textGeneration == TextGeneration_Dictionary)
461 | {
462 | if (m_dictionary.size() <= 5)
463 | {
464 | qWarning() << "In text generation : Dictionary size is too small";
465 | return;
466 | }
467 | m_captchaText = m_dictionary[(qrand() / (qreal) RAND_MAX) * (m_dictionary.size() - 1.0)];
468 | }
469 | else
470 | {
471 | qWarning() << "Unable to generate text : Invalid text generation mode";
472 | }
473 | updateCaptcha();
474 | }
475 |
--------------------------------------------------------------------------------
/captcha.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2014 Omkar Kanase
3 | *
4 | * This software is provided 'as-is', without any express or implied
5 | * warranty. In no event will the authors be held liable for any damages
6 | * arising from the use of this software.
7 | * Permission is granted to anyone to use this software for any purpose,
8 | * including commercial applications, and to alter it and redistribute it
9 | * freely, subject to the following restrictions:
10 | * 1. The origin of this software must not be misrepresented; you must not
11 | * claim that you wrote the original software. If you use this software
12 | * in a product, an acknowledgment in the product documentation would be
13 | * appreciated but is not required.
14 | * 2. Altered source versions must be plainly marked as such, and must not be
15 | * misrepresented as being the original software.
16 | * 3. This notice may not be removed or altered from any source distribution.
17 | */
18 |
19 | #ifndef CAPTCHA_H
20 | #define CAPTCHA_H
21 |
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 |
35 | class Captcha : public QObject
36 | {
37 | Q_OBJECT
38 | Q_ENUMS(DeformType)
39 | Q_ENUMS(TextGenerationMode)
40 | Q_PROPERTY(QFont font READ font WRITE setFont)
41 | Q_PROPERTY(QImage captchaImage READ captchaImage)
42 | Q_PROPERTY(QString captchaText READ captchaText WRITE setCaptchaText)
43 | Q_PROPERTY(DeformType deformationType READ deformationType WRITE setDeformationType)
44 | Q_PROPERTY(TextGenerationMode textGeneration READ textGeneration WRITE setTextGeneration)
45 | Q_PROPERTY(QStringList dictionary READ dictionary WRITE setDictionary)
46 | Q_PROPERTY(QColor fontColor READ fontColor WRITE setFontColor)
47 | Q_PROPERTY(QColor backColor READ backColor WRITE setBackColor)
48 | Q_PROPERTY(bool drawLines READ drawLines WRITE setDrawLines)
49 | Q_PROPERTY(bool drawEllipses READ drawEllipses WRITE setDrawEllipses)
50 | Q_PROPERTY(bool drawNoise READ drawNoise WRITE setDrawNoise)
51 | Q_PROPERTY(int noiseCount READ noiseCount WRITE setNoiseCount)
52 | Q_PROPERTY(int lineCount READ lineCount WRITE setLineCount)
53 | Q_PROPERTY(int ellipseCount READ ellipseCount WRITE setEllipseCount)
54 | Q_PROPERTY(int lineWidth READ lineWidth WRITE setLineWidth)
55 | Q_PROPERTY(int ellipseMinRadius READ ellipseMinRadius WRITE setEllipseMinRadius)
56 | Q_PROPERTY(int ellipseMaxRadius READ ellipseMaxRadius WRITE setEllipseMaxRadius)
57 | Q_PROPERTY(int noisePointSize READ noisePointSize WRITE setNoisePointSize)
58 |
59 | public:
60 | enum DeformType
61 | {
62 | Deform_SinCurve
63 | };
64 |
65 | enum TextGenerationMode
66 | {
67 | TextGeneration_Random,
68 | TextGeneration_Dictionary
69 | };
70 |
71 | public:
72 | explicit Captcha(QObject *parent = 0);
73 |
74 | QFont font() const;
75 | QImage captchaImage() const;
76 | DeformType deformationType() const;
77 | QString captchaText() const;
78 | TextGenerationMode textGeneration() const;
79 | const QStringList &dictionary() const;
80 | QColor fontColor() const;
81 | QColor backColor() const;
82 | bool drawLines() const;
83 | bool drawEllipses() const;
84 | bool drawNoise() const;
85 | int noiseCount() const;
86 | int lineCount() const;
87 | int ellipseCount() const;
88 | int lineWidth() const;
89 | int ellipseMinRadius() const;
90 | int ellipseMaxRadius() const;
91 | int noisePointSize() const;
92 |
93 | signals:
94 | void catpchaGenerated(const QImage& img, QString text);
95 |
96 | public slots:
97 | void setFont(const QFont& arg);
98 | void setDeformationType(DeformType arg);
99 | void updateCaptcha();
100 | void randomize();
101 | void generateText(int noOfChars = 5, bool includeNumbers = false, bool includeSymbols = false, bool allCapital = true);
102 | void setCaptchaText(QString arg);
103 | void setTextGeneration(TextGenerationMode arg);
104 | void setDictionary(const QStringList& arg);
105 | void loadDictionary(QString FileName);
106 | void setFontColor(QColor arg);
107 | void setBackColor(QColor arg);
108 | void setSinDeform(qreal hAmplitude, qreal hFrequency, qreal vAmplitude, qreal vFrequency);
109 | QPair generateCaptcha();
110 | void setDrawLines(bool arg);
111 | void setDrawEllipses(bool arg);
112 | void setDrawNoise(bool arg);
113 | void setNoiseCount(int arg);
114 | void setLineCount(int arg);
115 | void setEllipseCount(int arg);
116 | void setLineWidth(int arg);
117 | void setEllipseMinRadius(int arg);
118 | void setEllipseMaxRadius(int arg);
119 | void setNoisePointSize(int arg);
120 | void setDifficulty(int val);
121 |
122 | private:
123 | qreal m_hmod1;
124 | qreal m_hmod2;
125 |
126 | qreal m_vmod1;
127 | qreal m_vmod2;
128 |
129 | QFont m_font;
130 | QImage m_captchaImage;
131 | DeformType m_deformationType;
132 | QString m_captchaText;
133 | TextGenerationMode m_textGeneration;
134 | QStringList m_dictionary;
135 | QColor m_fontColor;
136 | QColor m_backColor;
137 | qreal m_padding;
138 | bool m_drawLines;
139 | bool m_drawEllipses;
140 | bool m_drawNoise;
141 | int m_noiseCount;
142 | int m_lineCount;
143 | int m_ellipseCount;
144 | int m_lineWidth;
145 | int m_ellipseMinRadius;
146 | int m_ellipseMaxRadius;
147 | int m_noisePointSize;
148 | };
149 |
150 | #endif // CAPTCHA_H
151 |
--------------------------------------------------------------------------------
/dialog.cpp:
--------------------------------------------------------------------------------
1 | #include "dialog.h"
2 | #include "ui_dialog.h"
3 | #include
4 | #include
5 | #include
6 |
7 | Dialog::Dialog(QWidget *parent) :
8 | QDialog(parent),
9 | ui(new Ui::Dialog)
10 | {
11 | ui->setupUi(this);
12 | }
13 |
14 | Dialog::~Dialog()
15 | {
16 | delete ui;
17 | }
18 |
19 |
20 | void Dialog::paintEvent(QPaintEvent *)
21 | {
22 | QPainter painter(this);
23 | Captcha cp;
24 | cp.randomize();
25 | cp.setDifficulty(3);
26 | /*cp.loadDictionary("dictionary.txt");
27 | cp.setTextGeneration(Captcha::TextGeneration_Dictionary);*/
28 | cp.generateText();
29 | painter.drawImage(30, 30, cp.captchaImage());
30 | }
31 |
--------------------------------------------------------------------------------
/dialog.h:
--------------------------------------------------------------------------------
1 | #ifndef DIALOG_H
2 | #define DIALOG_H
3 |
4 | #include
5 | #include "captcha.h"
6 | #include
7 |
8 |
9 | namespace Ui {
10 | class Dialog;
11 | }
12 |
13 | class Dialog : public QDialog
14 | {
15 | Q_OBJECT
16 |
17 | public:
18 | explicit Dialog(QWidget *parent = 0);
19 | ~Dialog();
20 |
21 | private:
22 | Ui::Dialog *ui;
23 |
24 | // QWidget interface
25 | protected:
26 | virtual void paintEvent(QPaintEvent *);
27 | };
28 |
29 | #endif // DIALOG_H
30 |
--------------------------------------------------------------------------------
/dialog.ui:
--------------------------------------------------------------------------------
1 |
2 | Dialog
3 |
4 |
5 |
6 | 0
7 | 0
8 | 400
9 | 300
10 |
11 |
12 |
13 | Dialog
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/difficultylevels.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omkar-developer/QtCaptcha/6356446e4864bcb7acfd332165f0073a247c71a0/difficultylevels.jpg
--------------------------------------------------------------------------------
/main.cpp:
--------------------------------------------------------------------------------
1 | #include "dialog.h"
2 | #include
3 |
4 | int main(int argc, char *argv[])
5 | {
6 | QApplication a(argc, argv);
7 | Dialog w;
8 | w.show();
9 |
10 | return a.exec();
11 | }
12 |
--------------------------------------------------------------------------------