【乾貨】」首個「 .NET Core 驗證碼組件

前言

 

  衆所周知,Dotnet Core目前沒有圖形API,之前的System.Drawing程序集並無包含在Dotnet Core 1.0環境中。不過在dotnet core labs項目裏能夠見到MS已經在移植這個項目,不過目前的版本只能在Windows上和NET541+或DNX環境中才可使用。git

  不過在dotnetConf的第兩天有一個叫作SkiaSharp的開源項目被說起;它是Google開源的跨平臺2D圖形API,Skia的.NET封裝;目前只能在Full Framework上運行,不過它之後會支持Core。github

 現狀

  據我瞭解,Dotnet Core目前沒有可用的驗證碼組件可用,緣由就是沒有Core的圖形接口。因此個人方案是經過開源的圖形庫來對dotnet core進行支持。windows

使用CImg開源庫

  CImg 庫是一個免費、開源的圖像處理C++庫,名稱原意是 Cool Image,正如其名,CImg是一個很是優秀、功能強大、代碼簡潔、使用方便的C++ 圖像處理庫。它不只很是適合科學家、研究生作科研時使用,也適合在工業應用工程開發中使用,更適合的是,對於有志於開發簡潔、高效、功能強大的圖像處理庫的人而言,CImg的源碼是不可多得的學習和參考資料。框架

  CImg 官網:http://cimg.sourceforge.net/dom

 

  可移植性:它徹底兼容於操做系統如Windows, Unix, Linux, MacOS X, *BSD...,也徹底兼容與編譯器如 VC++, g++, icc...等,具備高度的可移植性。ide

 

  輕便性:CImg 很是輕便,整個庫只用一個文件:cimg.h。任何C++應用程序只須要將該頭文件包含進工程中便可使用該庫的所有功能。它只定義了四了類(模板)和兩個名稱空間。該庫只依賴與標準C++和STL,只在顯示類部分依賴與操做系統的GDI,不再依賴任何其餘的外部庫。學習

C++封裝:

  我把繪圖邏輯都放到了一個C++項目中,再用Core項目使用DllImport進行調用。測試

  並且想到跨平臺在Win下咱們使用Win32的DLL庫進行編譯,在Linux下使用g++直接對源代碼進行連接編譯; this

  下面是項目中最主要的CaptchaImage.cpp,Win32下它會被放到項目中spa

 1 #include "stdafx.h"
 2 #include "CaptchaImage.h"
 3 #include "CImg.h"
 4 using namespace cimg_library;
 5 
 6 Export_API void GCaptcha(char* file_o, char *captcha_text, int count, int width ,int height , int offset ,int quality, int isjpeg, int fontSize)
 7 {
 8     // Create captcha image
 9     //----------------------
10     // Write colored and distorted text
11     CImg<unsigned char> captcha(width, height, 1, 3, 0), color(3);
12     const unsigned char red[] = { 255,0,0 }, green[] = { 0,255,0 }, blue[] = { 0,0,255 };
13 
14     char letter[2] = { 0 };
15     for (unsigned int k = 0; k<count; ++k) {
16         CImg<unsigned char> tmp;
17         *letter = captcha_text[k];
18         if (*letter) {
19             cimg_forX(color, i) color[i] = (unsigned char)(128 + (std::rand() % 127));
20             tmp.draw_text((int)(2 + 8 * cimg::rand()),
21                           (int)(12 * cimg::rand()), letter, red, 0, 1, fontSize).resize(-100, -100, 1, 3);
22 
23             const float sin_offset = (float)cimg::crand() * 3, sin_freq = (float)cimg::crand() / 7;
24             
25             cimg_forYC(captcha, y, v) captcha.get_shared_row(y, 0, v).shift((int)(4 * std::cos(y*sin_freq + sin_offset)));
26             
27             captcha.draw_image(count + offset * k, tmp);
28         }
29     }
30 
31     // Add geometric and random noise
32     CImg<unsigned char> copy = (+captcha).fill(0);
33     for (unsigned int l = 0; l<3; ++l) {
34         if (l) copy.blur(0.5f).normalize(0, 148);
35         for (unsigned int k = 0; k<10; ++k) {
36             cimg_forX(color, i) color[i] = (unsigned char)(128 + cimg::rand() * 127);
37             if (cimg::rand() < 0.5f) {
38                 copy.draw_circle((int)(cimg::rand()*captcha.width()),
39                                      (int)(cimg::rand()*captcha.height()),
40                                      (int)(cimg::rand() * 30),
41                                      color.data(), 0.6f, ~0U);
42             }
43             else {
44                 copy.draw_line((int)(cimg::rand()*captcha.width()),
45                                     (int)(cimg::rand()*captcha.height()),
46                                     (int)(cimg::rand()*captcha.width()),
47                                     (int)(cimg::rand()*captcha.height()),
48                                     color.data(), 0.6f);
49             }
50         }
51     }
52     captcha |= copy;
53     captcha.noise(10, 2);
54 
55     captcha = (+captcha).fill(255) - captcha;
56 
57     // Write output image and captcha text
58     //-------------------------------------
59     //std::printf("%s\n",captcha_text);
60 
61     if (isjpeg) {
62         captcha.save_jpeg(file_o, quality);
63     }
64     else {
65         captcha.save(file_o);
66     }
67 
68 }
CaptchaImage.cpp

  頭文件:

1 #ifdef PROJECT_EXPORTS
2 #define Export_API extern "C" __declspec(dllexport)
3 #else
4 #define Export_API extern "C"
5 #endif
6 
7 Export_API void GCaptcha(char* file_o, char *captcha_text, int count, int width, int height, int offset, int quality, int isjpeg, int fontSize);
CaptchaImage.h

  這裏爲了跨平臺編譯我將stdafx.h文件進行了修改以下:

1 #pragma once
2 #ifdef _MSC_VER //I'm in VS
3 #include "targetver.h"
4 #define WIN32_LEAN_AND_MEAN             // Exclude rarely-used stuff from Windows headers
5 // Windows Header Files:
6 #include <windows.h>
7 #endif
stdafx.h

Dotnet Core平臺封裝:

  1  public class CaptchaImageCore
  2     {
  3 
  4         [DllImport("libcaptchaimage.so", EntryPoint = "GCaptcha")]
  5         public static extern void libCaptcha(string file_o, string captcha_text, int count, int width, int height, int offset, int quality, int isjpeg, int fontSize);
  6 
  7 
  8         [DllImport("libcaptchaimage.dll", EntryPoint = "GCaptcha")]
  9         public static extern void GCaptcha(string file_o, string captcha_text, int count, int width, int height, int offset, int quality, int isjpeg, int fontSize);
 10 
 11         public string Text { set; get; }
 12 
 13         public int ImageWidth { set; get; }
 14         public int ImageHeight { set; get; }
 15 
 16         public int ImageOffset { set; get; }
 17 
 18         public int ImageQuality { set; get; }
 19 
 20         public int FontSize { set; get; }
 21 
 22 
 23         public CaptchaImageCore(int w,int h,int fontSize)
 24         {
 25             this.ImageWidth = w;
 26             this.ImageHeight = h;
 27             this.FontSize = fontSize;
 28             this.ImageOffset = 40;
 29             this.ImageQuality = 100;
 30             
 31         }
 32 
 33         public MemoryStream GetStream(string fileName)
 34         {
 35             this.Save(fileName);
 36             MemoryStream ms = new MemoryStream();
 37             using (var fileStream = new FileStream(fileName, FileMode.Open))
 38             {
 39                 fileStream.CopyTo(ms);
 40             }
 41             try
 42             {
 43                 File.Delete(fileName);
 44             }
 45             catch { }
 46             return ms;
 47 
 48         }
 49 
 50 
 51         public void Save(string fileName)
 52         {
 53             if (string.IsNullOrEmpty(fileName))
 54                 throw new NullReferenceException("file name is null");
 55             if (string.IsNullOrEmpty(this.Text))
 56                 this.Text = this.GenerateCheckCode();
 57 
 58 
 59 
 60             if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
 61             {
 62                 GCaptcha(fileName, this.Text, this.Text.Length, this.ImageWidth, this.ImageHeight,
 63                                           this.ImageOffset, this.ImageQuality, 0, this.FontSize);
 64             }
 65             else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
 66             {
 67                 libCaptcha(fileName, this.Text, this.Text.Length, this.ImageWidth, this.ImageHeight,
 68                                          this.ImageOffset, this.ImageQuality, 0, this.FontSize);
 69             }
 70         }
 71 
 72         public string GenerateCheckCode()
 73         {
 74             int number;
 75             char code;
 76             string checkCode = String.Empty;
 77 
 78             System.Random random = new Random();
 79 
 80             for (int i = 0; i < 5; i++)
 81             {
 82                 number = random.Next();
 83 
 84                 if (number % 2 == 0)
 85                     //生成'0'-'9'字符
 86                     code = (char)('0' + (char)(number % 10));
 87                 else
 88                     //生成'A'-'Z'字符
 89                     code = (char)('A' + (char)(number % 26));
 90 
 91                 checkCode += code.ToString();
 92             }
 93 
 94             return checkCode;
 95             //兩個字符相加等於=asicc碼加
 96         }
 97 
 98 
 99 
100     }
LibCaptchaImageWarp.cs

 編譯:

Win32編譯就不用說了,直接在VS2015裏編譯就好,可是必定要注意的是,要編譯爲X64平臺的目標代碼,由於咱們的Dotnet Core只支持x64平臺;

主要說下Linux編譯,目前我只在Ubuntu 14.04進行了編譯測試,編譯時CImg依賴也X11,因此要在編譯環境中安裝X11開發庫,固然Ubuntu也須要64位;

sudo apt-get install libx11-dev

接下下是編譯:

把那個Win32項目Copy到Linux中,而後Bash到目錄下執行:

g++ CaptchaImage.cpp -fPIC -shared -o libcaptchaimage.so

而後當你發佈程序時必定要將libcaptachaImageWarp.dll 和 Win32 Dll 或 libcaptchaimage.so 文件一塊兒放到程序執行目錄。

最後:

看看效果吧:

驗證碼源碼:https://github.com/maxzhang1985/YOYOFx/tree/master/Native

Demo:https://github.com/maxzhang1985/YOYOFx/tree/master/CoreHost

QQ羣:214741894

Demo和源碼在:https://github.com/maxzhang1985/YOYOFx

YOYOFx是一個基於Core和Owin的框架,項目沒有依賴微軟的MVC框架,支持在.net 4.5和Mono上直接SelfHost或使用Tinyfox跨平臺運行, 也支持在Dotnet Core 1.0 RC2 實現跨平臺運行; 框架剛剛寫出來尚未文檔,請你們見諒。

歡迎你們Star和Fork

相關文章
相關標籤/搜索