• [转载]用C#的GDI+技术生成复杂型彩色验证码


    http://my.oschina.net/idufei/blog/95502

    该类是生成一个验证码的类。本人集合了网上大部分的C#关于GDI+的文章进行多次改进,现在已经形成了可在生产环节中使用的验证码。

    该验证码加入了背景噪点,背景噪点曲线和直线,背景噪点文字以及扭曲,调暗,模糊等。完全可以实现防识别。

    对安全性要求比较高的网站尤其适用。

    同时该类还还收集了GDI+的图像处理方面的函数,包括雾化,扭曲,水波,锐化,高斯模糊,画直线,画曲线生成随机颜色,缩放图片,柔化图片,图片黑白化,增加曝光度,RGB滤镜,绘制圆角等功能。

    代码注释已经很详细了,就不再啰嗦了,有需要的就拿走吧。

       1 using System;
       2 using System.Collections.Generic;
       3 using System.Text;
       4 using System.IO;
       5 using System.Drawing;
       6 using System.Drawing.Drawing2D;
       7 using System.Drawing.Text;
       8 using System.Drawing.Imaging;
       9 
      10 /**********************
      11  * 验证码生成类
      12  * 作者:李飞麟
      13  * URL:http://www.xuehuwang.com 
      14  * Email:lifei6671@163.com 
      15  * 
      16  * *********************/
      17 namespace NS.DrawValidationCode
      18 {
      19     #region 验证码生成类
      20     /// <summary>
      21     /// 验证码生成类
      22     /// </summary>
      23     public class DrawValidationCode
      24     {
      25         #region 定义和初始化配置字段
      26         //用户存取验证码字符串
      27         private string validationCode = String.Empty;
      28         /// <summary>
      29         /// 获取系统生成的随机验证码
      30         /// </summary>
      31         public String ValidationCode
      32         {
      33             get { return validationCode; }
      34         }
      35         private Int32 validationCodeCount = 4;
      36         /// <summary>
      37         /// 获取和设置验证码字符串的长度
      38         /// </summary>
      39         public Int32 ValidationCodeCount
      40         {
      41             get { return validationCodeCount; }
      42             set { validationCodeCount = value; }
      43         }
      44         Graphics dc = null;
      45         private int bgWidth = 130;
      46         /// <summary>
      47         /// 验证码的宽度,默认为80
      48         /// </summary>
      49         public Int32 Width
      50         {
      51             get { return bgWidth; }
      52             set { bgWidth = value; }
      53         }
      54 
      55         private int bgHeight = 40;
      56         /// <summary>
      57         /// 验证码的高度,默认为40
      58         /// </summary>
      59         public Int32 Height
      60         {
      61             get { return bgHeight; }
      62             set { bgHeight = value; }
      63         }
      64         /* private string[] fontFace = { "Verdana", "Microsoft Sans Serif", "Comic Sans MS", "Arial", "宋体" };
      65          /// <summary>
      66          /// 验证码字体列表,默认为{ "Verdana", "Microsoft Sans Serif", "Comic Sans MS", "Arial", "宋体" }
      67          /// </summary>
      68          public String[] FontFace
      69          {
      70              get { return fontFace; }
      71              set { fontFace = value; }
      72          }*/
      73 
      74         private int fontMinSize = 15;
      75         /// <summary>
      76         /// 验证码字体的最小值,默认为15,建议不小于15像素
      77         /// </summary>
      78         public Int32 FontMinSize
      79         {
      80             get { return fontMinSize; }
      81             set { fontMinSize = value; }
      82         }
      83         private Int32 fontMaxSize = 20;
      84         /// <summary>
      85         /// 验证码字体的最大值,默认为20
      86         /// </summary>
      87         public Int32 FontMaxSize
      88         {
      89             get { return fontMaxSize; }
      90             set { fontMaxSize = value; }
      91         }
      92         private Color[] fontColor = { };
      93         /// <summary>
      94         /// 验证码字体的颜色,默认为系统自动生成字体颜色
      95         /// </summary>
      96         public Color[] FontColor
      97         {
      98             get { return fontColor; }
      99             set { fontColor = value; }
     100         }
     101         private Color backColor = Color.FromArgb(243, 255, 255);
     102         /// <summary>
     103         /// 验证码的背景色,默认为Color.FromArgb(243, 251, 254)
     104         /// </summary>
     105         public Color BackgroundColor
     106         {
     107             get { return backColor; }
     108             set { backColor = value; }
     109         }
     110         private Int32 bezierCount = 3;
     111         /// <summary>
     112         /// 贝塞尔曲线的条数,默认为3条
     113         /// </summary>
     114         public Int32 BezierCount
     115         {
     116             get { return bezierCount; }
     117             set { bezierCount = value; }
     118         }
     119         private Int32 lineCount = 3;
     120         /// <summary>
     121         /// 直线条数,默认为3条
     122         /// </summary>
     123         public Int32 LineCount
     124         {
     125             get { return lineCount; }
     126             set { lineCount = value; }
     127         }
     128         Random random;
     129 
     130         private String charCollection = "2,3,4,5,6,7,8,9,a,s,d,f,g,h,z,c,v,b,n,m,k,q,w,e,r,t,y,u,p,A,S,D,F,G,H,Z,C,V,B,N,M,K,Q,W,E,R,T,Y,U,P"; //定义验证码字符及出现频次 ,避免出现0 o j i l 1 x;  
     131         /// <summary>
     132         /// 随机字符串列表,请使用英文状态下的逗号分隔。
     133         /// </summary>
     134         public String CharCollection
     135         {
     136             get { return charCollection; }
     137             set { charCollection = value; }
     138         }
     139         private Int32 intCount = 4;
     140         /// <summary>
     141         /// 验证码字符串个数,默认为4个字符
     142         /// </summary>
     143         public Int32 IntCount
     144         {
     145             get { return intCount; }
     146             set { intCount = value; }
     147         }
     148         private Boolean isPixel = true;
     149         /// <summary>
     150         /// 是否添加噪点,默认添加,噪点颜色为系统随机生成。
     151         /// </summary>
     152         public Boolean IsPixel
     153         {
     154             get { return isPixel; }
     155             set { isPixel = value; }
     156         }
     157         private Boolean isRandString = true;
     158         /// <summary>
     159         /// 是否添加随机噪点字符串,默认添加
     160         /// </summary>
     161         public Boolean IsRandString
     162         {
     163             get { return isRandString; }
     164             set { isRandString = value; }
     165         }
     166         /// <summary>
     167         /// 随机背景字符串的个数
     168         /// </summary>
     169         public Int32 RandomStringCount
     170         {
     171             get;
     172             set;
     173         }
     174         private Int32 randomStringFontSize = 9;
     175         /// <summary>
     176         /// 随机背景字符串的大小
     177         /// </summary>
     178         public Int32 RandomStringFontSize
     179         {
     180             get { return randomStringFontSize; }
     181             set { randomStringFontSize = value; }
     182         }
     183         /// <summary>
     184         /// 是否对图片进行扭曲
     185         /// </summary>
     186         public Boolean IsTwist
     187         {
     188             get;
     189             set;
     190         }
     191         /// <summary>
     192         /// 边框样式
     193         /// </summary>
     194         public enum BorderStyle
     195         {
     196             /// <summary>
     197             /// 无边框
     198             /// </summary>
     199             None,
     200             /// <summary>
     201             /// 矩形边框
     202             /// </summary>
     203             Rectangle,
     204             /// <summary>
     205             /// 圆角边框
     206             /// </summary>
     207             RoundRectangle
     208         }
     209         private Int32 rotationAngle = 40;
     210         /// <summary>
     211         /// 验证码字符串随机转动的角度的最大值
     212         /// </summary>
     213         public Int32 RotationAngle
     214         {
     215             get { return rotationAngle; }
     216             set { rotationAngle = value; }
     217         }
     218         /// <summary>
     219         /// 设置或获取边框样式
     220         /// </summary>
     221         public BorderStyle Border
     222         {
     223             get;
     224             set;
     225         }
     226         private Point[] strPoint = null;
     227 
     228         private Double gaussianDeviation = 0;
     229         /// <summary>
     230         /// 对验证码图片进行高斯模糊的阀值,如果设置为0,则不对图片进行高斯模糊,该设置可能会对图片处理的性能有较大影响
     231         /// </summary>
     232         public Double GaussianDeviation
     233         {
     234             get { return gaussianDeviation; }
     235             set { gaussianDeviation = value; }
     236         }
     237         private Int32 brightnessValue = 0;
     238         /// <summary>
     239         /// 对图片进行暗度和亮度的调整,如果该值为0,则不调整。该设置会对图片处理性能有较大影响
     240         /// </summary>
     241         public Int32 BrightnessValue
     242         {
     243             get { return brightnessValue; }
     244             set { brightnessValue = value; }
     245         }
     246         #endregion
     247         /// <summary>
     248         /// 构造函数,用于初始化常用变量
     249         /// </summary>
     250         public DrawValidationCode()
     251         {
     252             random = new Random(Guid.NewGuid().GetHashCode());
     253             strPoint = new Point[validationCodeCount + 1];
     254             if (gaussianDeviation < 0) gaussianDeviation = 0;
     255         }
     256 
     257         /// <summary>
     258         /// 生成验证码
     259         /// </summary>
     260         /// <param name="target">用于存储图片的一般字节序列</param>
     261         public void CreateImage(Stream target)
     262         {
     263             Bitmap bit = new Bitmap(bgWidth + 1, bgHeight + 1);
     264             //写字符串
     265             dc = Graphics.FromImage(bit);
     266             dc.SmoothingMode = SmoothingMode.HighQuality;
     267             dc.TextRenderingHint = TextRenderingHint.ClearTypeGridFit; ;
     268             dc.InterpolationMode = InterpolationMode.HighQualityBilinear;
     269             dc.CompositingQuality = CompositingQuality.HighQuality;
     270 
     271             dc.Clear(Color.White);
     272             dc.DrawImageUnscaled(DrawBackground(), 0, 0);
     273             dc.DrawImageUnscaled(DrawRandomString(), 0, 0);
     274             //对图片文字进行扭曲
     275             bit = AdjustRippleEffect(bit, 5);
     276             //对图片进行高斯模糊
     277             if (gaussianDeviation > 0)
     278             {
     279                 Gaussian gau = new Gaussian();
     280                 bit = gau.FilterProcessImage(gaussianDeviation, bit);
     281             }
     282             //进行暗度和亮度处理
     283             if (brightnessValue != 0)
     284             {
     285                 //对图片进行调暗处理
     286                 bit = AdjustBrightness(bit, brightnessValue);
     287             }
     288             bit.Save(target, ImageFormat.Gif);
     289             //brush.Dispose();
     290             bit.Dispose();
     291             dc.Dispose();
     292         }
     293 
     294         #region 画验证码背景,例如,增加早点,添加曲线和直线等
     295         /// <summary>
     296         /// 画验证码背景,例如,增加早点,添加曲线和直线等
     297         /// </summary>
     298         /// <returns></returns>
     299         private Bitmap DrawBackground()
     300         {
     301             Bitmap bit = new Bitmap(bgWidth + 1, bgHeight + 1);
     302             Graphics g = Graphics.FromImage(bit);
     303             g.SmoothingMode = SmoothingMode.HighQuality;
     304 
     305             g.Clear(Color.White);
     306             Rectangle rectangle = new Rectangle(0, 0, bgWidth, bgHeight);
     307             Brush brush = new SolidBrush(backColor);
     308             g.FillRectangle(brush, rectangle);
     309 
     310             //画噪点
     311             if (isPixel)
     312             {
     313                 g.DrawImageUnscaled(DrawRandomPixel(30), 0, 0);
     314             }
     315             g.DrawImageUnscaled(DrawRandBgString(), 0, 0);
     316 
     317 
     318             //画曲线
     319             g.DrawImageUnscaled(DrawRandomBezier(bezierCount), 0, 0);
     320             //画直线
     321             g.DrawImageUnscaled(DrawRandomLine(lineCount), 0, 0);
     322 
     323             //dc.DrawImageUnscaled(DrawStringline(), 0, 0);
     324             if (Border == BorderStyle.Rectangle)
     325             {
     326                 //绘制边框
     327                 g.DrawRectangle(new Pen(Color.FromArgb(90, 87, 46)), 0, 0, bgWidth, bgHeight);
     328             }
     329             else if (Border == BorderStyle.RoundRectangle)
     330             {
     331                 //画圆角
     332                 DrawRoundRectangle(g, rectangle, Color.FromArgb(90, 87, 46), 1, 3);
     333             }
     334 
     335             return bit;
     336 
     337         }
     338         #endregion
     339 
     340         #region 画正弦曲线
     341         private Bitmap DrawTwist(Bitmap bmp, Int32 tWidth, Int32 tHeight, float angle, Color color)
     342         {
     343             //为了方便查看效果,在这里我定义了一个常量。
     344             //它在定义数组的长度和for循环中都要用到。
     345             int size = bgWidth;
     346 
     347             double[] x = new double[size];
     348             Bitmap b = new Bitmap(bmp.Width, bmp.Height);
     349             b.MakeTransparent();
     350             Graphics graphics = Graphics.FromImage(b);
     351             Pen pen = new Pen(color);
     352 
     353             //画正弦曲线的横轴间距参数。建议所用的值应该是 正数且是2的倍数。
     354             //在这里采用2。
     355             int val = 2;
     356 
     357             float temp = 0.0f;
     358 
     359             //把画布下移100。为什么要这样做,只要你把这一句给注释掉,运行一下代码,
     360             //你就会明白是为什么?
     361             graphics.TranslateTransform(0, 100);
     362             graphics.SmoothingMode = SmoothingMode.HighQuality;
     363             graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
     364             for (int i = 0; i < size; i++)
     365             {
     366                 //改变tWidth,实现正弦曲线宽度的变化。
     367                 //改tHeight,实现正弦曲线高度的变化。
     368                 x[i] = Math.Sin(2 * Math.PI * i / tWidth) * tHeight;
     369 
     370                 graphics.DrawLine(pen, i * val, temp, i * val + val / 2, (float)x[i]);
     371                 temp = (float)x[i];
     372             }
     373             graphics.RotateTransform(60, MatrixOrder.Prepend);
     374 
     375             //旋转图片
     376             // b = KiRotate(b, angle, Color.Transparent);
     377             return b;
     378         }
     379         #endregion
     380 
     381         #region 正弦曲线Wave扭曲图片
     382         /// <summary>
     383         /// 正弦曲线Wave扭曲图片
     384         /// </summary>
     385         /// <param name="srcBmp">图片路径</param>
     386         /// <param name="bXDir">如果扭曲则选择为True</param>
     387         /// <param name="dMultValue">波形的幅度倍数,越大扭曲的程度越高,一般为3</param>
     388         /// <param name="dPhase">波形的起始相位,取值区间[0-2*PI)</param>
     389         /// <returns></returns>
     390         public Bitmap TwistImage(Bitmap srcBmp, bool bXDir, double dMultValue, double dPhase)
     391         {
     392             System.Drawing.Bitmap destBmp = new Bitmap(srcBmp.Width, srcBmp.Height);
     393             double PI2 = 6.283185307179586476925286766559;
     394             // 将位图背景填充为白色
     395             System.Drawing.Graphics graph = System.Drawing.Graphics.FromImage(destBmp);
     396             graph.FillRectangle(new SolidBrush(System.Drawing.Color.White), 0, 0, destBmp.Width, destBmp.Height);
     397             graph.Dispose();
     398 
     399             double dBaseAxisLen = bXDir ? (double)destBmp.Height : (double)destBmp.Width;
     400 
     401             for (int i = 0; i < destBmp.Width; i++)
     402             {
     403                 for (int j = 0; j < destBmp.Height; j++)
     404                 {
     405                     double dx = 0;
     406                     dx = bXDir ? (PI2 * (double)j) / dBaseAxisLen : (PI2 * (double)i) / dBaseAxisLen;
     407                     dx += dPhase;
     408                     double dy = Math.Sin(dx);
     409 
     410                     // 取得当前点的颜色
     411                     int nOldX = 0, nOldY = 0;
     412                     nOldX = bXDir ? i + (int)(dy * dMultValue) : i;
     413                     nOldY = bXDir ? j : j + (int)(dy * dMultValue);
     414 
     415                     System.Drawing.Color color = srcBmp.GetPixel(i, j);
     416                     if (nOldX >= 0 && nOldX < destBmp.Width
     417                      && nOldY >= 0 && nOldY < destBmp.Height)
     418                     {
     419                         destBmp.SetPixel(nOldX, nOldY, color);
     420                     }
     421                 }
     422             }
     423             return destBmp;
     424         }
     425         #endregion
     426 
     427         #region 图片任意角度旋转
     428         /// <summary>
     429         /// 图片任意角度旋转
     430         /// </summary>
     431         /// <param name="bmp">原始图Bitmap</param>
     432         /// <param name="angle">旋转角度</param>
     433         /// <param name="bkColor">背景色</param>
     434         /// <returns>输出Bitmap</returns>
     435         public static Bitmap KiRotate(Bitmap bmp, float angle, Color bkColor)
     436         {
     437             int w = bmp.Width;
     438             int h = bmp.Height;
     439 
     440             PixelFormat pf;
     441 
     442             if (bkColor == Color.Transparent)
     443             {
     444                 pf = PixelFormat.Format32bppArgb;
     445             }
     446             else
     447             {
     448                 pf = bmp.PixelFormat;
     449             }
     450 
     451             Bitmap tmp = new Bitmap(w, h, pf);
     452             Graphics g = Graphics.FromImage(tmp);
     453             g.Clear(bkColor);
     454             g.DrawImageUnscaled(bmp, 1, 1);
     455             g.Dispose();
     456 
     457             GraphicsPath path = new GraphicsPath();
     458             path.AddRectangle(new RectangleF(0f, 0f, w, h));
     459             Matrix mtrx = new Matrix();
     460             mtrx.Rotate(angle);
     461             RectangleF rct = path.GetBounds(mtrx);
     462 
     463             Bitmap dst = new Bitmap((int)rct.Width, (int)rct.Height, pf);
     464             g = Graphics.FromImage(dst);
     465             g.Clear(bkColor);
     466             g.TranslateTransform(-rct.X, -rct.Y);
     467             g.RotateTransform(angle);
     468             g.InterpolationMode = InterpolationMode.HighQualityBilinear;
     469             g.DrawImageUnscaled(tmp, 0, 0);
     470             g.Dispose();
     471             tmp.Dispose();
     472 
     473             return dst;
     474         }
     475         #endregion
     476 
     477         #region 随机生成贝塞尔曲线
     478         /// <summary>
     479         /// 随机生成贝塞尔曲线
     480         /// </summary>
     481         /// <param name="bmp">一个图片的实例</param>
     482         /// <param name="lineNum">线条数量</param>
     483         /// <returns></returns>
     484         public Bitmap DrawRandomBezier(Int32 lineNum)
     485         {
     486             Bitmap b = new Bitmap(bgWidth, bgHeight);
     487             b.MakeTransparent();
     488             Graphics g = Graphics.FromImage(b);
     489             g.Clear(Color.Transparent);
     490             g.SmoothingMode = SmoothingMode.HighQuality;
     491             g.PixelOffsetMode = PixelOffsetMode.HighQuality;
     492 
     493             GraphicsPath gPath1 = new GraphicsPath();
     494             Int32 lineRandNum = random.Next(lineNum);
     495 
     496             for (int i = 0; i < (lineNum - lineRandNum); i++)
     497             {
     498                 Pen p = new Pen(GetRandomDeepColor());
     499                 Point[] point = {
     500                                     new Point(random.Next(1, (b.Width / 10)), random.Next(1, (b.Height))),
     501                                     new Point(random.Next((b.Width / 10) * 2, (b.Width / 10) * 4), random.Next(1, (b.Height))),
     502                                     new Point(random.Next((b.Width / 10) * 4, (b.Width / 10) * 6), random.Next(1, (b.Height))),
     503                                     new Point(random.Next((b.Width / 10) * 8, b.Width), random.Next(1, (b.Height)))
     504                                 };
     505 
     506                 gPath1.AddBeziers(point);
     507                 g.DrawPath(p, gPath1);
     508                 p.Dispose();
     509             }
     510             for (int i = 0; i < lineRandNum; i++)
     511             {
     512                 Pen p = new Pen(GetRandomDeepColor());
     513                 Point[] point = {
     514                             new Point(random.Next(1, b.Width), random.Next(1, b.Height)),
     515                             new Point(random.Next((b.Width / 10) * 2, b.Width), random.Next(1, b.Height)),
     516                             new Point(random.Next((b.Width / 10) * 4, b.Width), random.Next(1, b.Height)),
     517                             new Point(random.Next(1, b.Width), random.Next(1, b.Height))
     518                                 };
     519                 gPath1.AddBeziers(point);
     520                 g.DrawPath(p, gPath1);
     521                 p.Dispose();
     522             }
     523             return b;
     524         }
     525         #endregion
     526 
     527         #region 画直线
     528         /// <summary>
     529         /// 画直线
     530         /// </summary>
     531         /// <param name="bmp">一个bmp实例</param>
     532         /// <param name="lineNum">线条个数</param>
     533         /// <returns></returns>
     534         public Bitmap DrawRandomLine(Int32 lineNum)
     535         {
     536             if (lineNum < 0) throw new ArgumentNullException("参数bmp为空!");
     537             Bitmap b = new Bitmap(bgWidth, bgHeight);
     538             b.MakeTransparent();
     539             Graphics g = Graphics.FromImage(b);
     540             g.Clear(Color.Transparent);
     541             g.PixelOffsetMode = PixelOffsetMode.HighQuality;
     542             g.SmoothingMode = SmoothingMode.HighQuality;
     543             for (int i = 0; i < lineNum; i++)
     544             {
     545                 Pen p = new Pen(GetRandomDeepColor());
     546                 Point pt1 = new Point(random.Next(1, (b.Width / 5) * 2), random.Next(b.Height));
     547                 Point pt2 = new Point(random.Next((b.Width / 5) * 3, b.Width), random.Next(b.Height));
     548                 g.DrawLine(p, pt1, pt2);
     549                 p.Dispose();
     550             }
     551 
     552             return b;
     553         }
     554         #endregion
     555 
     556         #region 画随机噪点
     557         /// <summary>
     558         /// 画随机噪点
     559         /// </summary>
     560         /// <param name="pixNum">噪点的百分比</param>
     561         /// <returns></returns>
     562         public Bitmap DrawRandomPixel(Int32 pixNum)
     563         {
     564             Bitmap b = new Bitmap(bgWidth, bgHeight);
     565             b.MakeTransparent();
     566             Graphics graph = Graphics.FromImage(b);
     567             graph.SmoothingMode = SmoothingMode.HighQuality;
     568             graph.InterpolationMode = InterpolationMode.HighQualityBilinear;
     569 
     570             //画噪点 
     571             for (int i = 0; i < (bgHeight * bgWidth) / pixNum; i++)
     572             {
     573                 int x = random.Next(b.Width);
     574                 int y = random.Next(b.Height);
     575                 b.SetPixel(x, y, GetRandomDeepColor());
     576                 //下移坐标重新画点
     577                 if ((x + 1) < b.Width && (y + 1) < b.Height)
     578                 {
     579                     //画图片的前景噪音点
     580                     graph.DrawRectangle(new Pen(Color.Silver), random.Next(b.Width), random.Next(b.Height), 1, 1);
     581                 }
     582 
     583             }
     584 
     585             return b;
     586         }
     587         #endregion
     588 
     589         #region 画随机字符串中间连线
     590         /// <summary>
     591         /// 画随机字符串中间连线
     592         /// </summary>
     593         /// <returns></returns>
     594         private Bitmap DrawStringline()
     595         {
     596             Bitmap b = new Bitmap(bgWidth, bgHeight);
     597             b.MakeTransparent();
     598             Graphics g = Graphics.FromImage(b);
     599             g.SmoothingMode = SmoothingMode.AntiAlias;
     600 
     601             Point[] p = new Point[validationCodeCount];
     602             for (int i = 0; i < validationCodeCount; i++)
     603             {
     604                 p[i] = strPoint[i];
     605                 //throw new Exception(strPoint.Length.ToString());
     606             }
     607             // g.DrawBezier(new Pen(GetRandomDeepColor()), strPoint);
     608             //g.DrawClosedCurve(new Pen(GetRandomDeepColor()), strPoint);
     609             g.DrawCurve(new Pen(GetRandomDeepColor(), 1), strPoint);
     610 
     611             return b;
     612         }
     613         #endregion
     614 
     615         #region 写入验证码的字符串
     616         /// <summary>
     617         /// 写入验证码的字符串
     618         /// </summary>
     619         private Bitmap DrawRandomString()
     620         {
     621             if (fontMaxSize >= (bgHeight / 5) * 4) throw new ArgumentException("字体最大值参数FontMaxSize与验证码高度相近,这会导致描绘验证码字符串时出错,请重新设置参数!");
     622             Bitmap b = new Bitmap(bgWidth, bgHeight);
     623             b.MakeTransparent();
     624             Graphics g = Graphics.FromImage(b);
     625 
     626             g.Clear(Color.Transparent);
     627             g.PixelOffsetMode = PixelOffsetMode.Half;
     628             g.SmoothingMode = SmoothingMode.HighQuality;
     629             g.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit;
     630             g.InterpolationMode = InterpolationMode.HighQualityBilinear;
     631 
     632             char[] chars = GetRandomString(validationCodeCount).ToCharArray();//拆散字符串成单字符数组
     633             validationCode = chars.ToString();
     634 
     635             //设置字体显示格式
     636             StringFormat format = new StringFormat(StringFormatFlags.NoClip);
     637             format.Alignment = StringAlignment.Center;
     638             format.LineAlignment = StringAlignment.Center;
     639             FontFamily f = new FontFamily(GenericFontFamilies.Monospace);
     640 
     641 
     642             Int32 charNum = chars.Length;
     643 
     644             Point sPoint = new Point();
     645             Int32 fontSize = 9;
     646             for (int i = 0; i < validationCodeCount; i++)
     647             {
     648                 int findex = random.Next(5);
     649                 //定义字体
     650                 Font textFont = new Font(f, random.Next(fontMinSize, fontMaxSize), FontStyle.Bold);
     651                 //定义画刷,用于写字符串
     652                 //Brush brush = new SolidBrush(GetRandomDeepColor());
     653                 Int32 textFontSize = Convert.ToInt32(textFont.Size);
     654                 fontSize = textFontSize;
     655                 Point point = new Point(random.Next((bgWidth / charNum) * i + 5, (bgWidth / charNum) * (i + 1)), random.Next(bgHeight / 5 + textFontSize / 2, bgHeight - textFontSize / 2));
     656 
     657 
     658 
     659                 //如果当前字符X坐标小于字体的二分之一大小
     660                 if (point.X < textFontSize / 2)
     661                 {
     662                     point.X = point.X + textFontSize / 2;
     663                 }
     664                 //防止文字叠加
     665                 if (i > 0 && (point.X - sPoint.X < (textFontSize / 2 + textFontSize / 2)))
     666                 {
     667                     point.X = point.X + textFontSize;
     668                 }
     669                 //如果当前字符X坐标大于图片宽度,就减去字体的宽度
     670                 if (point.X > (bgWidth - textFontSize / 2))
     671                 {
     672                     point.X = bgWidth - textFontSize / 2;
     673                 }
     674 
     675                 sPoint = point;
     676 
     677                 float angle = random.Next(-rotationAngle, rotationAngle);//转动的度数
     678                 g.TranslateTransform(point.X, point.Y);//移动光标到指定位置
     679                 g.RotateTransform(angle);
     680 
     681                 //设置渐变画刷  
     682                 Rectangle myretang = new Rectangle(0, 1, Convert.ToInt32(textFont.Size), Convert.ToInt32(textFont.Size));
     683                 Color c = GetRandomDeepColor();
     684                 LinearGradientBrush mybrush2 = new LinearGradientBrush(myretang, c, GetLightColor(c, 120), random.Next(180));
     685 
     686                 g.DrawString(chars[i].ToString(), textFont, mybrush2, 1, 1, format);
     687 
     688                 g.RotateTransform(-angle);//转回去
     689                 g.TranslateTransform(-point.X, -point.Y);//移动光标到指定位置,每个字符紧凑显示,避免被软件识别
     690 
     691                 strPoint[i] = point;
     692 
     693                 textFont.Dispose();
     694                 mybrush2.Dispose();
     695             }
     696             return b;
     697         }
     698         #endregion
     699 
     700         #region 画干扰背景文字
     701         /// <summary>
     702         /// 画背景干扰文字
     703         /// </summary>
     704         /// <returns></returns>
     705         private Bitmap DrawRandBgString()
     706         {
     707             Bitmap b = new Bitmap(bgWidth, bgHeight);
     708             String[] randStr = { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" };
     709             b.MakeTransparent();
     710             Graphics g = Graphics.FromImage(b);
     711 
     712             g.Clear(Color.Transparent);
     713             g.PixelOffsetMode = PixelOffsetMode.HighQuality;
     714             g.SmoothingMode = SmoothingMode.HighQuality;
     715             g.TextRenderingHint = TextRenderingHint.AntiAlias;
     716             g.InterpolationMode = InterpolationMode.HighQualityBilinear;
     717 
     718             //设置字体显示格式
     719             StringFormat format = new StringFormat(StringFormatFlags.NoClip);
     720             format.Alignment = StringAlignment.Center;
     721             format.LineAlignment = StringAlignment.Center;
     722 
     723             FontFamily f = new FontFamily(GenericFontFamilies.Serif);
     724             Font textFont = new Font(f, randomStringFontSize, FontStyle.Underline);
     725 
     726             int randAngle = 60; //随机转动角度
     727 
     728             for (int i = 0; i < RandomStringCount; i++)
     729             {
     730 
     731                 Brush brush = new System.Drawing.SolidBrush(GetRandomLightColor());
     732                 Point pot = new Point(random.Next(5, bgWidth - 5), random.Next(5, bgHeight - 5));
     733                 //随机转动的度数
     734                 float angle = random.Next(-randAngle, randAngle);
     735 
     736                 //转动画布
     737                 g.RotateTransform(angle);
     738                 g.DrawString(randStr[random.Next(randStr.Length)], textFont, brush, pot, format);
     739                 //转回去,为下一个字符做准备
     740                 g.RotateTransform(-angle);
     741                 //释放资源
     742                 brush.Dispose();
     743             }
     744             textFont.Dispose();
     745             format.Dispose();
     746             f.Dispose();
     747 
     748             return b;
     749         }
     750         #endregion
     751 
     752         #region 生成随机字符串
     753         /// <summary>
     754         /// 生成随机字符串    
     755         /// </summary>
     756         /// <returns></returns>
     757         private string GetRandomString(Int32 textLength)
     758         {
     759             string[] randomArray = charCollection.Split(','); //将字符串生成数组     
     760             int arrayLength = randomArray.Length;
     761             string randomString = "";
     762             for (int i = 0; i < textLength; i++)
     763             {
     764                 randomString += randomArray[random.Next(0, arrayLength)];
     765             }
     766             return randomString; //长度是textLength +1
     767         }
     768         #endregion
     769 
     770         #region 内部方法:绘制验证码背景
     771         private void DrawBackground(HatchStyle hatchStyle)
     772         {
     773             //设置填充背景时用的笔刷
     774             HatchBrush hBrush = new HatchBrush(hatchStyle, backColor);
     775 
     776             //填充背景图片
     777             dc.FillRectangle(hBrush, 0, 0, this.bgWidth, this.bgHeight);
     778         }
     779         #endregion
     780 
     781         #region 根据指定长度,返回随机验证码
     782         /// <summary>
     783         /// 根据指定长度,返回随机验证码
     784         /// </summary>
     785         /// <param >制定长度</param>
     786         /// <returns>随即验证码</returns>
     787         public string Next(int length)
     788         {
     789             this.validationCode = GetRandomCode(length);
     790             return this.validationCode;
     791         }
     792         #endregion
     793 
     794         #region 内部方法:返回指定长度的随机验证码字符串
     795         /// <summary>
     796         /// 根据指定大小返回随机验证码
     797         /// </summary>
     798         /// <param >字符串长度</param>
     799         /// <returns>随机字符串</returns>
     800         private string GetRandomCode(int length)
     801         {
     802             StringBuilder sb = new StringBuilder(6);
     803 
     804             for (int i = 0; i < length; i++)
     805             {
     806                 sb.Append(Char.ConvertFromUtf32(RandomAZ09()));
     807             }
     808 
     809             return sb.ToString();
     810         }
     811         #endregion
     812 
     813         #region 内部方法:产生随机数和随机点
     814 
     815         /// <summary>
     816         /// 产生0-9A-Z的随机字符代码
     817         /// </summary>
     818         /// <returns>字符代码</returns>
     819         private int RandomAZ09()
     820         {
     821             int result = 48;
     822             Random ram = new Random();
     823             int i = ram.Next(2);
     824 
     825             switch (i)
     826             {
     827                 case 0:
     828                     result = ram.Next(48, 58);
     829                     break;
     830                 case 1:
     831                     result = ram.Next(65, 91);
     832                     break;
     833             }
     834 
     835             return result;
     836         }
     837 
     838         /// <summary>
     839         /// 返回一个随机点,该随机点范围在验证码背景大小范围内
     840         /// </summary>
     841         /// <returns>Point对象</returns>
     842         private Point RandomPoint()
     843         {
     844             Random ram = new Random();
     845             Point point = new Point(ram.Next(this.bgWidth), ram.Next(this.bgHeight));
     846             return point;
     847         }
     848         #endregion
     849 
     850         #region 随机生成颜色值
     851         /// <summary>
     852         /// 生成随机深颜色
     853         /// </summary>
     854         /// <returns></returns>
     855         public Color GetRandomDeepColor()
     856         {
     857             int nRed, nGreen, nBlue;    // nBlue,nRed  nGreen 相差大一点 nGreen 小一些
     858             //int high = 255;       
     859             int redLow = 160;
     860             int greenLow = 100;
     861             int blueLow = 160;
     862             nRed = random.Next(redLow);
     863             nGreen = random.Next(greenLow);
     864             nBlue = random.Next(blueLow);
     865             Color color = Color.FromArgb(nRed, nGreen, nBlue);
     866             return color;
     867         }
     868 
     869         /// <summary>
     870         /// 生成随机浅颜色
     871         /// </summary>
     872         /// <returns>randomColor</returns>
     873         public Color GetRandomLightColor()
     874         {
     875             int nRed, nGreen, nBlue;    //越大颜色越浅
     876             int low = 180;           //色彩的下限
     877             int high = 255;          //色彩的上限      
     878             nRed = random.Next(high) % (high - low) + low;
     879             nGreen = random.Next(high) % (high - low) + low;
     880             nBlue = random.Next(high) % (high - low) + low;
     881             Color color = Color.FromArgb(nRed, nGreen, nBlue);
     882             return color;
     883         }
     884         /// <summary>
     885         /// 生成随机颜色值
     886         /// </summary>
     887         /// <returns></returns>
     888         public Color GetRandomColor()
     889         {
     890             int nRed, nGreen, nBlue;    //越大颜色越浅
     891             int low = 10;           //色彩的下限
     892             int high = 255;          //色彩的上限    
     893             nRed = random.Next(high) % (high - low) + low;
     894             nGreen = random.Next(high) % (high - low) + low;
     895             nBlue = random.Next(high) % (high - low) + low;
     896             Color color = Color.FromArgb(nRed, nGreen, nBlue);
     897             return color;
     898         }
     899         /// <summary>
     900         /// 获取与当前颜色值相加后的颜色
     901         /// </summary>
     902         /// <param name="c"></param>
     903         /// <returns></returns>
     904         public Color GetLightColor(Color c, Int32 value)
     905         {
     906             int nRed = c.R, nGreen = c.G, nBlue = c.B;    //越大颜色越浅
     907             if (nRed + value < 255 && nRed + value > 0)
     908             {
     909                 nRed = c.R + 40;
     910             }
     911             if (nGreen + value < 255 && nGreen + value > 0)
     912             {
     913                 nGreen = c.G + 40;
     914             }
     915             if (nBlue + value < 255 && nBlue + value > 0)
     916             {
     917                 nBlue = c.B + 40;
     918             }
     919             Color color = Color.FromArgb(nRed, nGreen, nBlue);
     920             return color;
     921         }
     922         #endregion
     923 
     924         #region 合并图片
     925         /// <summary>       
     926         /// 合并图片        
     927         /// </summary>        
     928         /// <param name="maps"></param>        
     929         /// <returns></returns>        
     930         private Bitmap MergerImg(params Bitmap[] maps)
     931         {
     932             int i = maps.Length;
     933             if (i == 0)
     934                 throw new Exception("图片数不能够为0");
     935             //创建要显示的图片对象,根据参数的个数设置宽度            
     936             Bitmap backgroudImg = new Bitmap(i * 12, 16);
     937             Graphics g = Graphics.FromImage(backgroudImg);
     938             //清除画布,背景设置为白色            
     939             g.Clear(System.Drawing.Color.White);
     940             for (int j = 0; j < i; j++)
     941             {
     942                 //g.DrawImage(maps[j], j * 11, 0, maps[j].Width, maps[j].Height);
     943                 g.DrawImageUnscaled(maps[j], 0, 0);
     944             }
     945             g.Dispose();
     946             return backgroudImg;
     947         }
     948         #endregion
     949 
     950         #region 生成不重复的随机数,该函数会消耗大量系统资源
     951         /// <summary>
     952         /// 生成不重复的随机数,该函数会消耗大量系统资源
     953         /// </summary>
     954         /// <returns></returns>
     955         private static int GetRandomSeed()
     956         {
     957             byte[] bytes = new byte[4];
     958             System.Security.Cryptography.RNGCryptoServiceProvider rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
     959             rng.GetBytes(bytes);
     960             return BitConverter.ToInt32(bytes, 0);
     961         }
     962         #endregion
     963 
     964         #region 缩放图片
     965         /// <summary>
     966         /// 缩放图片
     967         /// </summary>
     968         /// <param name="bmp">原始Bitmap</param>
     969         /// <param name="newW">新的宽度</param>
     970         /// <param name="newH">新的高度</param>
     971         /// <param name="Mode">缩放质量</param>
     972         /// <returns>处理以后的图片</returns>
     973         public static Bitmap KiResizeImage(Bitmap bmp, int newW, int newH, InterpolationMode Mode)
     974         {
     975             try
     976             {
     977                 Bitmap b = new Bitmap(newW, newH);
     978                 Graphics g = Graphics.FromImage(b);
     979                 // 插值算法的质量
     980                 g.InterpolationMode = Mode;
     981                 g.DrawImage(bmp, new Rectangle(0, 0, newW, newH), new Rectangle(0, 0, bmp.Width, bmp.Height), GraphicsUnit.Pixel);
     982                 g.Dispose();
     983                 return b;
     984             }
     985             catch
     986             {
     987                 return null;
     988             }
     989         }
     990         #endregion
     991 
     992         #region 绘制圆角矩形
     993         /// <summary>
     994         /// C# GDI+ 绘制圆角矩形
     995         /// </summary>
     996         /// <param name="g">Graphics 对象</param>
     997         /// <param name="rectangle">Rectangle 对象,圆角矩形区域</param>
     998         /// <param name="borderColor">边框颜色</param>
     999         /// <param name="borderWidth">边框宽度</param>
    1000         /// <param name="r">圆角半径</param>
    1001         private static void DrawRoundRectangle(Graphics g, Rectangle rectangle, Color borderColor, float borderWidth, int r)
    1002         {
    1003             // 如要使边缘平滑,请取消下行的注释
    1004             g.SmoothingMode = SmoothingMode.HighQuality;
    1005 
    1006             // 由于边框也需要一定宽度,需要对矩形进行修正
    1007             //rectangle = new Rectangle(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
    1008             Pen p = new Pen(borderColor, borderWidth);
    1009             // 调用 getRoundRectangle 得到圆角矩形的路径,然后再进行绘制
    1010             g.DrawPath(p, getRoundRectangle(rectangle, r));
    1011         }
    1012         #endregion
    1013 
    1014         #region 根据普通矩形得到圆角矩形的路径
    1015         /// <summary>
    1016         /// 根据普通矩形得到圆角矩形的路径
    1017         /// </summary>
    1018         /// <param name="rectangle">原始矩形</param>
    1019         /// <param name="r">半径</param>
    1020         /// <returns>图形路径</returns>
    1021         private static GraphicsPath getRoundRectangle(Rectangle rectangle, int r)
    1022         {
    1023             int l = 2 * r;
    1024             // 把圆角矩形分成八段直线、弧的组合,依次加到路径中
    1025             GraphicsPath gp = new GraphicsPath();
    1026             gp.AddLine(new Point(rectangle.X + r, rectangle.Y), new Point(rectangle.Right - r, rectangle.Y));
    1027             gp.AddArc(new Rectangle(rectangle.Right - l, rectangle.Y, l, l), 270F, 90F);
    1028 
    1029             gp.AddLine(new Point(rectangle.Right, rectangle.Y + r), new Point(rectangle.Right, rectangle.Bottom - r));
    1030             gp.AddArc(new Rectangle(rectangle.Right - l, rectangle.Bottom - l, l, l), 0F, 90F);
    1031 
    1032             gp.AddLine(new Point(rectangle.Right - r, rectangle.Bottom), new Point(rectangle.X + r, rectangle.Bottom));
    1033             gp.AddArc(new Rectangle(rectangle.X, rectangle.Bottom - l, l, l), 90F, 90F);
    1034 
    1035             gp.AddLine(new Point(rectangle.X, rectangle.Bottom - r), new Point(rectangle.X, rectangle.Y + r));
    1036             gp.AddArc(new Rectangle(rectangle.X, rectangle.Y, l, l), 180F, 90F);
    1037             return gp;
    1038         }
    1039         #endregion
    1040 
    1041         #region 柔化
    1042         ///<summary>
    1043         /// 柔化
    1044         /// </summary>
    1045         /// <param name="b">原始图</param>
    1046         /// <returns>输出图</returns>
    1047         public static Bitmap KiBlur(Bitmap b)
    1048         {
    1049 
    1050             if (b == null)
    1051             {
    1052                 return null;
    1053             }
    1054 
    1055             int w = b.Width;
    1056             int h = b.Height;
    1057 
    1058             try
    1059             {
    1060 
    1061                 Bitmap bmpRtn = new Bitmap(w, h, PixelFormat.Format24bppRgb);
    1062 
    1063                 BitmapData srcData = b.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
    1064                 BitmapData dstData = bmpRtn.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
    1065 
    1066                 unsafe
    1067                 {
    1068                     byte* pIn = (byte*)srcData.Scan0.ToPointer();
    1069                     byte* pOut = (byte*)dstData.Scan0.ToPointer();
    1070                     int stride = srcData.Stride;
    1071                     byte* p;
    1072 
    1073                     for (int y = 0; y < h; y++)
    1074                     {
    1075                         for (int x = 0; x < w; x++)
    1076                         {
    1077                             //取周围9点的值
    1078                             if (x == 0 || x == w - 1 || y == 0 || y == h - 1)
    1079                             {
    1080                                 //不做
    1081                                 pOut[0] = pIn[0];
    1082                                 pOut[1] = pIn[1];
    1083                                 pOut[2] = pIn[2];
    1084                             }
    1085                             else
    1086                             {
    1087                                 int r1, r2, r3, r4, r5, r6, r7, r8, r9;
    1088                                 int g1, g2, g3, g4, g5, g6, g7, g8, g9;
    1089                                 int b1, b2, b3, b4, b5, b6, b7, b8, b9;
    1090 
    1091                                 float vR, vG, vB;
    1092 
    1093                                 //左上
    1094                                 p = pIn - stride - 3;
    1095                                 r1 = p[2];
    1096                                 g1 = p[1];
    1097                                 b1 = p[0];
    1098 
    1099                                 //正上
    1100                                 p = pIn - stride;
    1101                                 r2 = p[2];
    1102                                 g2 = p[1];
    1103                                 b2 = p[0];
    1104 
    1105                                 //右上
    1106                                 p = pIn - stride + 3;
    1107                                 r3 = p[2];
    1108                                 g3 = p[1];
    1109                                 b3 = p[0];
    1110 
    1111                                 //左侧
    1112                                 p = pIn - 3;
    1113                                 r4 = p[2];
    1114                                 g4 = p[1];
    1115                                 b4 = p[0];
    1116 
    1117                                 //右侧
    1118                                 p = pIn + 3;
    1119                                 r5 = p[2];
    1120                                 g5 = p[1];
    1121                                 b5 = p[0];
    1122 
    1123                                 //右下
    1124                                 p = pIn + stride - 3;
    1125                                 r6 = p[2];
    1126                                 g6 = p[1];
    1127                                 b6 = p[0];
    1128 
    1129                                 //正下
    1130                                 p = pIn + stride;
    1131                                 r7 = p[2];
    1132                                 g7 = p[1];
    1133                                 b7 = p[0];
    1134 
    1135                                 //右下
    1136                                 p = pIn + stride + 3;
    1137                                 r8 = p[2];
    1138                                 g8 = p[1];
    1139                                 b8 = p[0];
    1140 
    1141                                 //自己
    1142                                 p = pIn;
    1143                                 r9 = p[2];
    1144                                 g9 = p[1];
    1145                                 b9 = p[0];
    1146 
    1147                                 vR = (float)(r1 + r2 + r3 + r4 + r5 + r6 + r7 + r8 + r9);
    1148                                 vG = (float)(g1 + g2 + g3 + g4 + g5 + g6 + g7 + g8 + g9);
    1149                                 vB = (float)(b1 + b2 + b3 + b4 + b5 + b6 + b7 + b8 + b9);
    1150 
    1151                                 vR /= 9;
    1152                                 vG /= 9;
    1153                                 vB /= 9;
    1154 
    1155                                 pOut[0] = (byte)vB;
    1156                                 pOut[1] = (byte)vG;
    1157                                 pOut[2] = (byte)vR;
    1158 
    1159                             }
    1160 
    1161                             pIn += 3;
    1162                             pOut += 3;
    1163                         }// end of x
    1164 
    1165                         pIn += srcData.Stride - w * 3;
    1166                         pOut += srcData.Stride - w * 3;
    1167                     } // end of y
    1168                 }
    1169 
    1170                 b.UnlockBits(srcData);
    1171                 bmpRtn.UnlockBits(dstData);
    1172 
    1173                 return bmpRtn;
    1174             }
    1175             catch
    1176             {
    1177                 return null;
    1178             }
    1179 
    1180         } // end of KiBlur
    1181         #endregion
    1182 
    1183         #region 滤镜
    1184         /// <summary>
    1185         /// 红色滤镜
    1186         /// </summary>
    1187         /// <param name="bitmap">Bitmap</param>
    1188         /// <param name="threshold">阀值 -255~255</param>
    1189         /// <returns></returns>
    1190         public System.Drawing.Bitmap AdjustToRed(System.Drawing.Bitmap bitmap, int threshold)
    1191         {
    1192             for (int y = 0; y < bitmap.Height; y++)
    1193             {
    1194                 for (int x = 0; x < bitmap.Width; x++)
    1195                 {
    1196                     // 取得每一個 pixel
    1197                     var pixel = bitmap.GetPixel(x, y);
    1198                     var pR = pixel.R + threshold;
    1199                     pR = Math.Max(pR, 0);
    1200                     pR = Math.Min(255, pR);
    1201                     // 將改過的 RGB 寫回
    1202                     // 只寫入紅色的值 , G B 都放零
    1203                     System.Drawing.Color newColor = System.Drawing.Color.FromArgb(pixel.A, pR, 0, 0);
    1204                     bitmap.SetPixel(x, y, newColor);
    1205                 }
    1206             }
    1207             // 回傳結果
    1208             return bitmap;
    1209         }
    1210 
    1211         /// <summary>
    1212         /// 绿色滤镜
    1213         /// </summary>
    1214         /// <param name="bitmap">一个图片实例</param>
    1215         /// <param name="threshold">阀值 -255~+255</param>
    1216         /// <returns></returns>
    1217         public System.Drawing.Bitmap AdjustToGreen(System.Drawing.Bitmap bitmap, int threshold)
    1218         {
    1219             for (int y = 0; y < bitmap.Height; y++)
    1220             {
    1221                 for (int x = 0; x < bitmap.Width; x++)
    1222                 {
    1223                     // 取得每一個 pixel
    1224                     var pixel = bitmap.GetPixel(x, y);
    1225                     //判斷是否超過255 如果超過就是255 
    1226                     var pG = pixel.G + threshold;
    1227                     //如果小於0就為0
    1228                     if (pG > 255) pG = 255;
    1229                     if (pG < 0) pG = 0;
    1230                     // 將改過的 RGB 寫回
    1231                     // 只寫入綠色的值 , R B 都放零
    1232                     System.Drawing.Color newColor = System.Drawing.Color.FromArgb(pixel.A, 0, pG, 0);
    1233                     bitmap.SetPixel(x, y, newColor);
    1234                 }
    1235             }
    1236             // 回傳結果
    1237             return bitmap;
    1238         }
    1239         /// <summary>
    1240         /// 蓝色滤镜
    1241         /// </summary>
    1242         /// <param name="bitmap">一个图片实例</param>
    1243         /// <param name="threshold">阀值 -255~255</param>
    1244         /// <returns></returns>
    1245         public System.Drawing.Bitmap AdjustToBlue(System.Drawing.Bitmap bitmap, int threshold)
    1246         {
    1247             for (int y = 0; y < bitmap.Height; y++)
    1248             {
    1249                 for (int x = 0; x < bitmap.Width; x++)
    1250                 {
    1251                     // 取得每一個 pixel
    1252                     var pixel = bitmap.GetPixel(x, y);
    1253                     //判斷是否超過255 如果超過就是255 
    1254                     var pB = pixel.B + threshold;
    1255                     //如果小於0就為0
    1256                     if (pB > 255) pB = 255;
    1257                     if (pB < 0) pB = 0;
    1258                     // 將改過的 RGB 寫回
    1259                     // 只寫入藍色的值 , R G 都放零
    1260                     System.Drawing.Color newColor = System.Drawing.Color.FromArgb(pixel.A, 0, 0, pB);
    1261                     bitmap.SetPixel(x, y, newColor);
    1262                 }
    1263             }
    1264             // 回傳結果
    1265             return bitmap;
    1266         }
    1267         /// <summary>
    1268         /// 调整 RGB 色调
    1269         /// </summary>
    1270         /// <param name="bitmap"></param>
    1271         /// <param name="thresholdRed">红色阀值</param>
    1272         /// <param name="thresholdBlue">蓝色阀值</param>
    1273         /// <param name="thresholdGreen">绿色阀值</param>
    1274         /// <returns></returns>
    1275         public System.Drawing.Bitmap AdjustToCustomColor(System.Drawing.Bitmap bitmap, int thresholdRed, int thresholdGreen, int thresholdBlue)
    1276         {
    1277             for (int y = 0; y < bitmap.Height; y++)
    1278             {
    1279                 for (int x = 0; x < bitmap.Width; x++)
    1280                 {
    1281                     // 取得每一個 pixel
    1282                     var pixel = bitmap.GetPixel(x, y);
    1283                     //判斷是否超過255 如果超過就是255 
    1284                     var pG = pixel.G + thresholdGreen;
    1285                     //如果小於0就為0
    1286                     if (pG > 255) pG = 255;
    1287                     if (pG < 0) pG = 0;
    1288                     //判斷是否超過255 如果超過就是255 
    1289                     var pR = pixel.R + thresholdRed;
    1290                     //如果小於0就為0
    1291                     if (pR > 255) pR = 255;
    1292                     if (pR < 0) pR = 0;
    1293                     //判斷是否超過255 如果超過就是255 
    1294                     var pB = pixel.B + thresholdBlue;
    1295                     //如果小於0就為0
    1296                     if (pB > 255) pB = 255;
    1297                     if (pB < 0) pB = 0;
    1298                     // 將改過的 RGB 寫回
    1299                     // 只寫入綠色的值 , R B 都放零
    1300                     System.Drawing.Color newColor = System.Drawing.Color.FromArgb(pixel.A, pR, pG, pB);
    1301                     bitmap.SetPixel(x, y, newColor);
    1302                 }
    1303             }
    1304             return bitmap;
    1305         }
    1306         #endregion
    1307 
    1308         #region 图片去色(图片黑白化)
    1309         /// <summary>
    1310         /// 图片去色(图片黑白化)
    1311         /// </summary>
    1312         /// <param name="original">一个需要处理的图片</param>
    1313         /// <returns></returns>
    1314         public static Bitmap MakeGrayscale(Bitmap original)
    1315         {
    1316             //create a blank bitmap the same size as original
    1317             Bitmap newBitmap = new Bitmap(original.Width, original.Height);
    1318 
    1319             //get a graphics object from the new image
    1320             Graphics g = Graphics.FromImage(newBitmap);
    1321             g.SmoothingMode = SmoothingMode.HighQuality;
    1322             //create the grayscale ColorMatrix
    1323             ColorMatrix colorMatrix = new ColorMatrix(new float[][] 
    1324                           {
    1325                              new float[] {.3f, .3f, .3f, 0, 0},
    1326                              new float[] {.59f, .59f, .59f, 0, 0},
    1327                              new float[] {.11f, .11f, .11f, 0, 0},
    1328                              new float[] {0, 0, 0, 1, 0},
    1329                              new float[] {0, 0, 0, 0, 1}
    1330                           });
    1331 
    1332             //create some image attributes
    1333             ImageAttributes attributes = new ImageAttributes();
    1334 
    1335             //set the color matrix attribute
    1336             attributes.SetColorMatrix(colorMatrix);
    1337 
    1338             //draw the original image on the new image
    1339             //using the grayscale color matrix
    1340             g.DrawImage(original, new Rectangle(0, 0, original.Width, original.Height),
    1341                0, 0, original.Width, original.Height, GraphicsUnit.Pixel, attributes);
    1342 
    1343             //dispose the Graphics object
    1344             g.Dispose();
    1345             return newBitmap;
    1346         }
    1347         #endregion
    1348 
    1349         #region 增加或減少亮度
    1350         /// <summary>
    1351         /// 增加或減少亮度
    1352         /// </summary>
    1353         /// <param name="img">System.Drawing.Image Source </param>
    1354         /// <param name="valBrightness">0~255</param>
    1355         /// <returns></returns>
    1356         public System.Drawing.Bitmap AdjustBrightness(System.Drawing.Image img, int valBrightness)
    1357         {
    1358             // 讀入欲轉換的圖片並轉成為 Bitmap
    1359             System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(img);
    1360 
    1361             for (int y = 0; y < bitmap.Height; y++)
    1362             {
    1363                 for (int x = 0; x < bitmap.Width; x++)
    1364                 {
    1365                     // 取得每一個 pixel
    1366                     var pixel = bitmap.GetPixel(x, y);
    1367 
    1368                     // 判斷 如果處理過後 255 就設定為 255 如果小於則設定為 0
    1369                     var pR = ((pixel.R + valBrightness > 255) ? 255 : pixel.R + valBrightness) < 0 ? 0 : ((pixel.R + valBrightness > 255) ? 255 : pixel.R + valBrightness);
    1370                     var pG = ((pixel.G + valBrightness > 255) ? 255 : pixel.G + valBrightness) < 0 ? 0 : ((pixel.G + valBrightness > 255) ? 255 : pixel.G + valBrightness);
    1371                     var pB = ((pixel.B + valBrightness > 255) ? 255 : pixel.B + valBrightness) < 0 ? 0 : ((pixel.B + valBrightness > 255) ? 255 : pixel.B + valBrightness);
    1372 
    1373                     // 將改過的 RGB 寫回
    1374                     System.Drawing.Color newColor = System.Drawing.Color.FromArgb(pixel.A, pR, pG, pB);
    1375 
    1376                     bitmap.SetPixel(x, y, newColor);
    1377 
    1378                 }
    1379             }
    1380             // 回傳結果
    1381             return bitmap;
    1382         }
    1383         #endregion
    1384 
    1385         #region 浮雕效果
    1386         /// <summary>
    1387         /// 浮雕效果
    1388         /// </summary>
    1389         /// <param name="src">一个图片实例</param>
    1390         /// <returns></returns>
    1391         public Bitmap AdjustToStone(Bitmap src)
    1392         {
    1393             // 依照 Format24bppRgb 每三个表示一 Pixel 0: 蓝 1: 绿 2: 红
    1394             BitmapData bitmapData = src.LockBits(new Rectangle(0, 0, src.Width, src.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
    1395 
    1396             unsafe
    1397             {
    1398                 // 抓住第一个 Pixel 第一个数值
    1399                 byte* p = (byte*)(void*)bitmapData.Scan0;
    1400 
    1401                 // 跨步值 - 宽度 *3 可以算出畸零地 之后跳到下一行
    1402                 int nOffset = bitmapData.Stride - src.Width * 3;
    1403 
    1404                 for (int y = 0; y < src.Height; ++y)
    1405                 {
    1406                     for (int x = 0; x < src.Width; ++x)
    1407                     {
    1408                         // 为了理解方便 所以特地在命名
    1409                         int r, g, b;
    1410                         // 先取得下一个 Pixel
    1411                         var q = p + 3;
    1412                         r = Math.Abs(p[2] - q[2] + 128);
    1413                         r = r < 0 ? 0 : r;
    1414                         r = r > 255 ? 255 : r;
    1415                         p[2] = (byte)r;
    1416 
    1417                         g = Math.Abs(p[1] - q[1] + 128);
    1418                         g = g < 0 ? 0 : g;
    1419                         g = g > 255 ? 255 : g;
    1420                         p[1] = (byte)g;
    1421 
    1422                         b = Math.Abs(p[0] - q[0] + 128);
    1423                         b = b < 0 ? 0 : b;
    1424                         b = b > 255 ? 255 : b;
    1425                         p[0] = (byte)b;
    1426 
    1427                         // 跳去下一个 Pixel
    1428                         p += 3;
    1429 
    1430                     }
    1431                     // 跨越畸零地
    1432                     p += nOffset;
    1433                 }
    1434             }
    1435             src.UnlockBits(bitmapData);
    1436             return src;
    1437         }
    1438         #endregion
    1439 
    1440         #region 水波纹效果
    1441         /// <summary>
    1442         /// 水波纹效果
    1443         /// </summary>
    1444         /// <param name="src"></param>
    1445         /// <param name="nWave">坡度</param>
    1446         /// www.it165.net
    1447         /// <returns></returns>
    1448         public Bitmap AdjustRippleEffect(Bitmap src, short nWave)
    1449         {
    1450 
    1451             int nWidth = src.Width;
    1452             int nHeight = src.Height;
    1453 
    1454             // 透过公式进行水波纹的採样
    1455 
    1456             PointF[,] fp = new PointF[nWidth, nHeight];
    1457             
    1458             Point[,] pt = new Point[nWidth, nHeight];
    1459 
    1460             Point mid = new Point();
    1461             mid.X = nWidth / 2;
    1462             mid.Y = nHeight / 2;
    1463 
    1464             double newX, newY;
    1465             double xo, yo;
    1466 
    1467             //先取样将水波纹座标跟RGB取出
    1468             for (int x = 0; x < nWidth; ++x)
    1469                 for (int y = 0; y < nHeight; ++y)
    1470                 {
    1471                     xo = ((double)nWave * Math.Sin(2.0 * 3.1415 * (float)y / 128.0));
    1472                     yo = ((double)nWave * Math.Cos(2.0 * 3.1415 * (float)x / 128.0));
    1473 
    1474                     newX = (x + xo);
    1475                     newY = (y + yo);
    1476 
    1477                     if (newX > 0 && newX < nWidth)
    1478                     {
    1479                         fp[x, y].X = (float)newX;
    1480                         pt[x, y].X = (int)newX;
    1481                     }
    1482                     else
    1483                     {
    1484                         fp[x, y].X = (float)0.0;
    1485                         pt[x, y].X = 0;
    1486                     }
    1487 
    1488 
    1489                     if (newY > 0 && newY < nHeight)
    1490                     {
    1491                         fp[x, y].Y = (float)newY;
    1492                         pt[x, y].Y = (int)newY;
    1493                     }
    1494                     else
    1495                     {
    1496                         fp[x, y].Y = (float)0.0;
    1497                         pt[x, y].Y = 0;
    1498                     }
    1499                 }
    1500 
    1501 
    1502             //进行合成
    1503             Bitmap bSrc = (Bitmap)src.Clone();
    1504 
    1505             // 依照 Format24bppRgb 每三个表示一 Pixel 0: 蓝 1: 绿 2: 红
    1506             BitmapData bitmapData = src.LockBits(new Rectangle(0, 0, src.Width, src.Height), ImageLockMode.ReadWrite,
    1507                                            PixelFormat.Format24bppRgb);
    1508             BitmapData bmSrc = bSrc.LockBits(new Rectangle(0, 0, bSrc.Width, bSrc.Height), ImageLockMode.ReadWrite,
    1509                                              PixelFormat.Format24bppRgb);
    1510 
    1511             int scanline = bitmapData.Stride;
    1512 
    1513             IntPtr Scan0 = bitmapData.Scan0;
    1514             IntPtr SrcScan0 = bmSrc.Scan0;
    1515 
    1516             unsafe
    1517             {
    1518                 byte* p = (byte*)(void*)Scan0;
    1519                 byte* pSrc = (byte*)(void*)SrcScan0;
    1520 
    1521                 int nOffset = bitmapData.Stride - src.Width * 3;
    1522 
    1523                 int xOffset, yOffset;
    1524 
    1525                 for (int y = 0; y < nHeight; ++y)
    1526                 {
    1527                     for (int x = 0; x < nWidth; ++x)
    1528                     {
    1529                         xOffset = pt[x, y].X;
    1530                         yOffset = pt[x, y].Y;
    1531 
    1532                         if (yOffset >= 0 && yOffset < nHeight && xOffset >= 0 && xOffset < nWidth)
    1533                         {
    1534                             p[0] = pSrc[(yOffset * scanline) + (xOffset * 3)];
    1535                             p[1] = pSrc[(yOffset * scanline) + (xOffset * 3) + 1];
    1536                             p[2] = pSrc[(yOffset * scanline) + (xOffset * 3) + 2];
    1537                         }
    1538 
    1539                         p += 3;
    1540                     }
    1541                     p += nOffset;
    1542                 }
    1543             }
    1544 
    1545             src.UnlockBits(bitmapData);
    1546             bSrc.UnlockBits(bmSrc);
    1547 
    1548             return src;
    1549         }
    1550         #endregion
    1551 
    1552         #region 调整曝光度值
    1553         /// <summary>
    1554         /// 调整曝光度值
    1555         /// </summary>
    1556         /// <param name="src">原图</param>
    1557         /// <param name="r"></param>
    1558         /// <param name="g"></param>
    1559         /// <param name="b"></param>
    1560         /// <returns></returns>
    1561         public Bitmap AdjustGamma(Bitmap src, double r, double g, double b)
    1562         {
    1563             // 判断是不是在0.2~5 之间
    1564             r = Math.Min(Math.Max(0.2, r), 5);
    1565             g = Math.Min(Math.Max(0.2, g), 5);
    1566             b = Math.Min(Math.Max(0.2, b), 5);
    1567 
    1568             // 依照 Format24bppRgb 每三个表示一 Pixel 0: 蓝 1: 绿 2: 红
    1569             BitmapData bitmapData = src.LockBits(new Rectangle(0, 0, src.Width, src.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
    1570 
    1571             unsafe
    1572             {
    1573                 // 抓住第一个 Pixel 第一个数值
    1574                 byte* p = (byte*)(void*)bitmapData.Scan0;
    1575 
    1576                 // 跨步值 - 宽度 *3 可以算出畸零地 之后跳到下一行
    1577                 int nOffset = bitmapData.Stride - src.Width * 3;
    1578 
    1579                 for (int y = 0; y < src.Height; y++)
    1580                 {
    1581                     for (int x = 0; x < src.Width; x++)
    1582                     {
    1583                         p[2] = (byte)Math.Min(255, (int)((255.0 * Math.Pow(p[2] / 255.0, 1.0 / r)) + 0.5));
    1584                         p[1] = (byte)Math.Min(255, (int)((255.0 * Math.Pow(p[1] / 255.0, 1.0 / g)) + 0.5));
    1585                         p[0] = (byte)Math.Min(255, (int)((255.0 * Math.Pow(p[0] / 255.0, 1.0 / b)) + 0.5));
    1586 
    1587 
    1588                         // 跳去下一个 Pixel
    1589                         p += 3;
    1590 
    1591                     }
    1592                     // 跨越畸零地
    1593                     p += nOffset;
    1594                 }
    1595             }
    1596             src.UnlockBits(bitmapData);
    1597             return src;
    1598 
    1599         }
    1600         #endregion
    1601 
    1602         #region 高对比,对过深的颜色调浅,过浅的颜色调深。
    1603         /// <summary>
    1604         /// 高对比,对过深的颜色调浅,过浅的颜色调深。
    1605         /// </summary>
    1606         /// <param name="src"></param>
    1607         /// <param name="effectThreshold"> 高对比程度 -100~100</param>
    1608         /// <returns></returns>
    1609         public Bitmap Contrast(Bitmap src, float effectThreshold)
    1610         {
    1611 
    1612             // 依照 Format24bppRgb 每三个表示一 Pixel 0: 蓝 1: 绿 2: 红
    1613             BitmapData bitmapData = src.LockBits(new Rectangle(0, 0, src.Width, src.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
    1614 
    1615             // 判断是否在 -100~100
    1616             effectThreshold = effectThreshold < -100 ? -100 : effectThreshold;
    1617             effectThreshold = effectThreshold > 100 ? 100 : effectThreshold;
    1618 
    1619             effectThreshold = (float)((100.0 + effectThreshold) / 100.0);
    1620             effectThreshold *= effectThreshold;
    1621 
    1622             unsafe
    1623             {
    1624                 // 抓住第一个 Pixel 第一个数值 www.it165.net
    1625                 byte* p = (byte*)(void*)bitmapData.Scan0;
    1626 
    1627                 // 跨步值 - 宽度 *3 可以算出畸零地 之后跳到下一行
    1628                 int nOffset = bitmapData.Stride - src.Width * 3;
    1629 
    1630 
    1631 
    1632                 for (int y = 0; y < src.Height; y++)
    1633                 {
    1634                     for (int x = 0; x < src.Width; x++)
    1635                     {
    1636                         double buffer = 0;
    1637 
    1638 
    1639                         // 公式  (Red/255)-0.5= 偏离中间值程度
    1640                         // ((偏离中间值程度 * 影响范围)+0.4 ) * 255
    1641                         buffer = ((((p[2] / 255.0) - 0.5) * effectThreshold) + 0.5) * 255.0;
    1642                         buffer = buffer > 255 ? 255 : buffer;
    1643                         buffer = buffer < 0 ? 0 : buffer;
    1644                         p[2] = (byte)buffer;
    1645 
    1646                         buffer = ((((p[1] / 255.0) - 0.5) * effectThreshold) + 0.5) * 255.0;
    1647                         buffer = buffer > 255 ? 255 : buffer;
    1648                         buffer = buffer < 0 ? 0 : buffer;
    1649                         p[1] = (byte)buffer;
    1650 
    1651 
    1652                         buffer = ((((p[0] / 255.0) - 0.5) * effectThreshold) + 0.5) * 255.0;
    1653                         buffer = buffer > 255 ? 255 : buffer;
    1654                         buffer = buffer < 0 ? 0 : buffer;
    1655                         p[0] = (byte)buffer;
    1656 
    1657 
    1658 
    1659 
    1660                         // 跳去下一个 Pixel
    1661                         p += 3;
    1662 
    1663                     }
    1664                     // 跨越畸零地
    1665                     p += nOffset;
    1666                 }
    1667             }
    1668             src.UnlockBits(bitmapData);
    1669             return src;
    1670 
    1671 
    1672         }
    1673         #endregion
    1674 
    1675         #region 对图片进行雾化效果
    1676         /// <summary>
    1677         /// 对图片进行雾化效果
    1678         /// </summary>
    1679         /// <param name="bmp"></param>
    1680         /// <returns></returns>
    1681         public Bitmap Atomization(Bitmap bmp)
    1682         {
    1683 
    1684             int Height = bmp.Height;
    1685             int Width = bmp.Width;
    1686             Bitmap newBitmap = new Bitmap(Width, Height);
    1687             Bitmap oldBitmap = bmp;
    1688             Color pixel;
    1689             for (int x = 1; x < Width - 1; x++)
    1690             {
    1691                 for (int y = 1; y < Height - 1; y++)
    1692                 {
    1693                     Random MyRandom = new Random( Guid.NewGuid().GetHashCode());
    1694                     int k = MyRandom.Next(123456);
    1695                     //像素块大小
    1696                     int dx = x + k % 19;
    1697                     int dy = y + k % 19;
    1698                     if (dx >= Width)
    1699                         dx = Width - 1;
    1700                     if (dy >= Height)
    1701                         dy = Height - 1;
    1702                     pixel = oldBitmap.GetPixel(dx, dy);
    1703                     newBitmap.SetPixel(x, y, pixel);
    1704                 }
    1705             }
    1706             return newBitmap;
    1707         }
    1708         #endregion
    1709 
    1710     } //END Class DrawValidationCode
    1711     #endregion
    1712 
    1713     #region 高斯模糊算法
    1714     /// <summary>
    1715     /// 高斯模糊算法
    1716     /// </summary>
    1717     public class Gaussian
    1718     {
    1719         public static double[,] Calculate1DSampleKernel(double deviation, int size)
    1720         {
    1721             double[,] ret = new double[size, 1];
    1722             double sum = 0;
    1723             int half = size / 2;
    1724             for (int i = 0; i < size; i++)
    1725             {
    1726                 ret[i, 0] = 1 / (Math.Sqrt(2 * Math.PI) * deviation) * Math.Exp(-(i - half) * (i - half) / (2 * deviation * deviation));
    1727                 sum += ret[i, 0];
    1728             }
    1729             return ret;
    1730         }
    1731         public static double[,] Calculate1DSampleKernel(double deviation)
    1732         {
    1733             int size = (int)Math.Ceiling(deviation * 3) * 2 + 1;
    1734             return Calculate1DSampleKernel(deviation, size);
    1735         }
    1736         public static double[,] CalculateNormalized1DSampleKernel(double deviation)
    1737         {
    1738             return NormalizeMatrix(Calculate1DSampleKernel(deviation));
    1739         }
    1740         public static double[,] NormalizeMatrix(double[,] matrix)
    1741         {
    1742             double[,] ret = new double[matrix.GetLength(0), matrix.GetLength(1)];
    1743             double sum = 0;
    1744             for (int i = 0; i < ret.GetLength(0); i++)
    1745             {
    1746                 for (int j = 0; j < ret.GetLength(1); j++)
    1747                     sum += matrix[i, j];
    1748             }
    1749             if (sum != 0)
    1750             {
    1751                 for (int i = 0; i < ret.GetLength(0); i++)
    1752                 {
    1753                     for (int j = 0; j < ret.GetLength(1); j++)
    1754                         ret[i, j] = matrix[i, j] / sum;
    1755                 }
    1756             }
    1757             return ret;
    1758         }
    1759         public static double[,] GaussianConvolution(double[,] matrix, double deviation)
    1760         {
    1761             double[,] kernel = CalculateNormalized1DSampleKernel(deviation);
    1762             double[,] res1 = new double[matrix.GetLength(0), matrix.GetLength(1)];
    1763             double[,] res2 = new double[matrix.GetLength(0), matrix.GetLength(1)];
    1764             //x-direction
    1765             for (int i = 0; i < matrix.GetLength(0); i++)
    1766             {
    1767                 for (int j = 0; j < matrix.GetLength(1); j++)
    1768                     res1[i, j] = processPoint(matrix, i, j, kernel, 0);
    1769             }
    1770             //y-direction
    1771             for (int i = 0; i < matrix.GetLength(0); i++)
    1772             {
    1773                 for (int j = 0; j < matrix.GetLength(1); j++)
    1774                     res2[i, j] = processPoint(res1, i, j, kernel, 1);
    1775             }
    1776             return res2;
    1777         }
    1778         private static double processPoint(double[,] matrix, int x, int y, double[,] kernel, int direction)
    1779         {
    1780             double res = 0;
    1781             int half = kernel.GetLength(0) / 2;
    1782             for (int i = 0; i < kernel.GetLength(0); i++)
    1783             {
    1784                 int cox = direction == 0 ? x + i - half : x;
    1785                 int coy = direction == 1 ? y + i - half : y;
    1786                 if (cox >= 0 && cox < matrix.GetLength(0) && coy >= 0 && coy < matrix.GetLength(1))
    1787                 {
    1788                     res += matrix[cox, coy] * kernel[i, 0];
    1789                 }
    1790             }
    1791             return res;
    1792         }
    1793         /// <summary>
    1794         /// 对颜色值进行灰色处理
    1795         /// </summary>
    1796         /// <param name="cr"></param>
    1797         /// <returns></returns>
    1798         private Color grayscale(Color cr)
    1799         {
    1800             return Color.FromArgb(cr.A, (int)(cr.R * .3 + cr.G * .59 + cr.B * 0.11),
    1801                (int)(cr.R * .3 + cr.G * .59 + cr.B * 0.11),
    1802               (int)(cr.R * .3 + cr.G * .59 + cr.B * 0.11));
    1803         }
    1804         /// <summary>
    1805         /// 对图片进行高斯模糊
    1806         /// </summary>
    1807         /// <param name="d">模糊数值,数值越大模糊越很</param>
    1808         /// <param name="image">一个需要处理的图片</param>
    1809         /// <returns></returns>
    1810         public Bitmap FilterProcessImage(double d, Bitmap image)
    1811         {
    1812             Bitmap ret = new Bitmap(image.Width, image.Height);
    1813             Double[,] matrixR = new Double[image.Width, image.Height];
    1814             Double[,] matrixG = new Double[image.Width, image.Height];
    1815             Double[,] matrixB = new Double[image.Width, image.Height];
    1816             for (int i = 0; i < image.Width; i++)
    1817             {
    1818                 for (int j = 0; j < image.Height; j++)
    1819                 {
    1820                     //matrix[i, j] = grayscale(image.GetPixel(i, j)).R;
    1821                     matrixR[i, j] = image.GetPixel(i, j).R;
    1822                     matrixG[i, j] = image.GetPixel(i, j).G;
    1823                     matrixB[i, j] = image.GetPixel(i, j).B;
    1824                 }
    1825             }
    1826             matrixR = Gaussian.GaussianConvolution(matrixR, d);
    1827             matrixG = Gaussian.GaussianConvolution(matrixG, d);
    1828             matrixB = Gaussian.GaussianConvolution(matrixB, d);
    1829             for (int i = 0; i < image.Width; i++)
    1830             {
    1831                 for (int j = 0; j < image.Height; j++)
    1832                 {
    1833                     Int32 R = (int)Math.Min(255, matrixR[i, j]);
    1834                     Int32 G = (int)Math.Min(255, matrixG[i, j]);
    1835                     Int32 B = (int)Math.Min(255, matrixB[i, j]);
    1836                     ret.SetPixel(i, j, Color.FromArgb(R, G, B));
    1837                 }
    1838             }
    1839             return ret;
    1840         }
    1841 
    1842     }
    1843     #endregion
    1844 }
    验证码生成类
  • 相关阅读:
    Mac上使用Charles抓取https
    使用react-navigation 报错isMounted
    create-react-app创建出来项目,如何设置CSS模块化?
    Markdown 常用语法整理
    Git安装和使用
    页面重定向跳转
    AntDesign 踩坑大全
    js实现数组、对象深度克隆的两种办法
    wamp中mysql安装时能启动,重启后无法启动的解决办法
    前端开发工具收藏
  • 原文地址:https://www.cnblogs.com/knightyj/p/3585806.html
Copyright © 2020-2023  润新知