[转载]用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 }
验证码生成类

 

转载于:https://www.cnblogs.com/knightyj/p/3585806.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值