├── 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 | ![Alt text](/difficultylevels.jpg?raw=true "Difficulty Levels") 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 | --------------------------------------------------------------------------------