衆所周知,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 庫是一個免費、開源的圖像處理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++項目中,再用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 }
頭文件:
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);
這裏爲了跨平臺編譯我將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
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 }
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