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

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

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

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

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Drawing.Imaging; /**********************
* 验证码生成类
* 作者:李飞麟
* URL:http://www.xuehuwang.com
* Email:lifei6671@163.com
*
* *********************/
namespace NS.DrawValidationCode
{
#region 验证码生成类
/// <summary>
/// 验证码生成类
/// </summary>
public class DrawValidationCode
{
#region 定义和初始化配置字段
//用户存取验证码字符串
private string validationCode = String.Empty;
/// <summary>
/// 获取系统生成的随机验证码
/// </summary>
public String ValidationCode
{
get { return validationCode; }
}
private Int32 validationCodeCount = ;
/// <summary>
/// 获取和设置验证码字符串的长度
/// </summary>
public Int32 ValidationCodeCount
{
get { return validationCodeCount; }
set { validationCodeCount = value; }
}
Graphics dc = null;
private int bgWidth = ;
/// <summary>
/// 验证码的宽度,默认为80
/// </summary>
public Int32 Width
{
get { return bgWidth; }
set { bgWidth = value; }
} private int bgHeight = ;
/// <summary>
/// 验证码的高度,默认为40
/// </summary>
public Int32 Height
{
get { return bgHeight; }
set { bgHeight = value; }
}
/* private string[] fontFace = { "Verdana", "Microsoft Sans Serif", "Comic Sans MS", "Arial", "宋体" };
/// <summary>
/// 验证码字体列表,默认为{ "Verdana", "Microsoft Sans Serif", "Comic Sans MS", "Arial", "宋体" }
/// </summary>
public String[] FontFace
{
get { return fontFace; }
set { fontFace = value; }
}*/ private int fontMinSize = ;
/// <summary>
/// 验证码字体的最小值,默认为15,建议不小于15像素
/// </summary>
public Int32 FontMinSize
{
get { return fontMinSize; }
set { fontMinSize = value; }
}
private Int32 fontMaxSize = ;
/// <summary>
/// 验证码字体的最大值,默认为20
/// </summary>
public Int32 FontMaxSize
{
get { return fontMaxSize; }
set { fontMaxSize = value; }
}
private Color[] fontColor = { };
/// <summary>
/// 验证码字体的颜色,默认为系统自动生成字体颜色
/// </summary>
public Color[] FontColor
{
get { return fontColor; }
set { fontColor = value; }
}
private Color backColor = Color.FromArgb(, , );
/// <summary>
/// 验证码的背景色,默认为Color.FromArgb(243, 251, 254)
/// </summary>
public Color BackgroundColor
{
get { return backColor; }
set { backColor = value; }
}
private Int32 bezierCount = ;
/// <summary>
/// 贝塞尔曲线的条数,默认为3条
/// </summary>
public Int32 BezierCount
{
get { return bezierCount; }
set { bezierCount = value; }
}
private Int32 lineCount = ;
/// <summary>
/// 直线条数,默认为3条
/// </summary>
public Int32 LineCount
{
get { return lineCount; }
set { lineCount = value; }
}
Random random; 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;
/// <summary>
/// 随机字符串列表,请使用英文状态下的逗号分隔。
/// </summary>
public String CharCollection
{
get { return charCollection; }
set { charCollection = value; }
}
private Int32 intCount = ;
/// <summary>
/// 验证码字符串个数,默认为4个字符
/// </summary>
public Int32 IntCount
{
get { return intCount; }
set { intCount = value; }
}
private Boolean isPixel = true;
/// <summary>
/// 是否添加噪点,默认添加,噪点颜色为系统随机生成。
/// </summary>
public Boolean IsPixel
{
get { return isPixel; }
set { isPixel = value; }
}
private Boolean isRandString = true;
/// <summary>
/// 是否添加随机噪点字符串,默认添加
/// </summary>
public Boolean IsRandString
{
get { return isRandString; }
set { isRandString = value; }
}
/// <summary>
/// 随机背景字符串的个数
/// </summary>
public Int32 RandomStringCount
{
get;
set;
}
private Int32 randomStringFontSize = ;
/// <summary>
/// 随机背景字符串的大小
/// </summary>
public Int32 RandomStringFontSize
{
get { return randomStringFontSize; }
set { randomStringFontSize = value; }
}
/// <summary>
/// 是否对图片进行扭曲
/// </summary>
public Boolean IsTwist
{
get;
set;
}
/// <summary>
/// 边框样式
/// </summary>
public enum BorderStyle
{
/// <summary>
/// 无边框
/// </summary>
None,
/// <summary>
/// 矩形边框
/// </summary>
Rectangle,
/// <summary>
/// 圆角边框
/// </summary>
RoundRectangle
}
private Int32 rotationAngle = ;
/// <summary>
/// 验证码字符串随机转动的角度的最大值
/// </summary>
public Int32 RotationAngle
{
get { return rotationAngle; }
set { rotationAngle = value; }
}
/// <summary>
/// 设置或获取边框样式
/// </summary>
public BorderStyle Border
{
get;
set;
}
private Point[] strPoint = null; private Double gaussianDeviation = ;
/// <summary>
/// 对验证码图片进行高斯模糊的阀值,如果设置为0,则不对图片进行高斯模糊,该设置可能会对图片处理的性能有较大影响
/// </summary>
public Double GaussianDeviation
{
get { return gaussianDeviation; }
set { gaussianDeviation = value; }
}
private Int32 brightnessValue = ;
/// <summary>
/// 对图片进行暗度和亮度的调整,如果该值为0,则不调整。该设置会对图片处理性能有较大影响
/// </summary>
public Int32 BrightnessValue
{
get { return brightnessValue; }
set { brightnessValue = value; }
}
#endregion
/// <summary>
/// 构造函数,用于初始化常用变量
/// </summary>
public DrawValidationCode()
{
random = new Random(Guid.NewGuid().GetHashCode());
strPoint = new Point[validationCodeCount + ];
if (gaussianDeviation < ) gaussianDeviation = ;
} /// <summary>
/// 生成验证码
/// </summary>
/// <param name="target">用于存储图片的一般字节序列</param>
public void CreateImage(Stream target)
{
Bitmap bit = new Bitmap(bgWidth + , bgHeight + );
//写字符串
dc = Graphics.FromImage(bit);
dc.SmoothingMode = SmoothingMode.HighQuality;
dc.TextRenderingHint = TextRenderingHint.ClearTypeGridFit; ;
dc.InterpolationMode = InterpolationMode.HighQualityBilinear;
dc.CompositingQuality = CompositingQuality.HighQuality; dc.Clear(Color.White);
dc.DrawImageUnscaled(DrawBackground(), , );
dc.DrawImageUnscaled(DrawRandomString(), , );
//对图片文字进行扭曲
bit = AdjustRippleEffect(bit, );
//对图片进行高斯模糊
if (gaussianDeviation > )
{
Gaussian gau = new Gaussian();
bit = gau.FilterProcessImage(gaussianDeviation, bit);
}
//进行暗度和亮度处理
if (brightnessValue != )
{
//对图片进行调暗处理
bit = AdjustBrightness(bit, brightnessValue);
}
bit.Save(target, ImageFormat.Gif);
//brush.Dispose();
bit.Dispose();
dc.Dispose();
} #region 画验证码背景,例如,增加早点,添加曲线和直线等
/// <summary>
/// 画验证码背景,例如,增加早点,添加曲线和直线等
/// </summary>
/// <returns></returns>
private Bitmap DrawBackground()
{
Bitmap bit = new Bitmap(bgWidth + , bgHeight + );
Graphics g = Graphics.FromImage(bit);
g.SmoothingMode = SmoothingMode.HighQuality; g.Clear(Color.White);
Rectangle rectangle = new Rectangle(, , bgWidth, bgHeight);
Brush brush = new SolidBrush(backColor);
g.FillRectangle(brush, rectangle); //画噪点
if (isPixel)
{
g.DrawImageUnscaled(DrawRandomPixel(), , );
}
g.DrawImageUnscaled(DrawRandBgString(), , ); //画曲线
g.DrawImageUnscaled(DrawRandomBezier(bezierCount), , );
//画直线
g.DrawImageUnscaled(DrawRandomLine(lineCount), , ); //dc.DrawImageUnscaled(DrawStringline(), 0, 0);
if (Border == BorderStyle.Rectangle)
{
//绘制边框
g.DrawRectangle(new Pen(Color.FromArgb(, , )), , , bgWidth, bgHeight);
}
else if (Border == BorderStyle.RoundRectangle)
{
//画圆角
DrawRoundRectangle(g, rectangle, Color.FromArgb(, , ), , );
} return bit; }
#endregion #region 画正弦曲线
private Bitmap DrawTwist(Bitmap bmp, Int32 tWidth, Int32 tHeight, float angle, Color color)
{
//为了方便查看效果,在这里我定义了一个常量。
//它在定义数组的长度和for循环中都要用到。
int size = bgWidth; double[] x = new double[size];
Bitmap b = new Bitmap(bmp.Width, bmp.Height);
b.MakeTransparent();
Graphics graphics = Graphics.FromImage(b);
Pen pen = new Pen(color); //画正弦曲线的横轴间距参数。建议所用的值应该是 正数且是2的倍数。
//在这里采用2。
int val = ; float temp = 0.0f; //把画布下移100。为什么要这样做,只要你把这一句给注释掉,运行一下代码,
//你就会明白是为什么?
graphics.TranslateTransform(, );
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
for (int i = ; i < size; i++)
{
//改变tWidth,实现正弦曲线宽度的变化。
//改tHeight,实现正弦曲线高度的变化。
x[i] = Math.Sin( * Math.PI * i / tWidth) * tHeight; graphics.DrawLine(pen, i * val, temp, i * val + val / , (float)x[i]);
temp = (float)x[i];
}
graphics.RotateTransform(, MatrixOrder.Prepend); //旋转图片
// b = KiRotate(b, angle, Color.Transparent);
return b;
}
#endregion #region 正弦曲线Wave扭曲图片
/// <summary>
/// 正弦曲线Wave扭曲图片
/// </summary>
/// <param name="srcBmp">图片路径</param>
/// <param name="bXDir">如果扭曲则选择为True</param>
/// <param name="dMultValue">波形的幅度倍数,越大扭曲的程度越高,一般为3</param>
/// <param name="dPhase">波形的起始相位,取值区间[0-2*PI)</param>
/// <returns></returns>
public Bitmap TwistImage(Bitmap srcBmp, bool bXDir, double dMultValue, double dPhase)
{
System.Drawing.Bitmap destBmp = new Bitmap(srcBmp.Width, srcBmp.Height);
double PI2 = 6.283185307179586476925286766559;
// 将位图背景填充为白色
System.Drawing.Graphics graph = System.Drawing.Graphics.FromImage(destBmp);
graph.FillRectangle(new SolidBrush(System.Drawing.Color.White), , , destBmp.Width, destBmp.Height);
graph.Dispose(); double dBaseAxisLen = bXDir ? (double)destBmp.Height : (double)destBmp.Width; for (int i = ; i < destBmp.Width; i++)
{
for (int j = ; j < destBmp.Height; j++)
{
double dx = ;
dx = bXDir ? (PI2 * (double)j) / dBaseAxisLen : (PI2 * (double)i) / dBaseAxisLen;
dx += dPhase;
double dy = Math.Sin(dx); // 取得当前点的颜色
int nOldX = , nOldY = ;
nOldX = bXDir ? i + (int)(dy * dMultValue) : i;
nOldY = bXDir ? j : j + (int)(dy * dMultValue); System.Drawing.Color color = srcBmp.GetPixel(i, j);
if (nOldX >= && nOldX < destBmp.Width
&& nOldY >= && nOldY < destBmp.Height)
{
destBmp.SetPixel(nOldX, nOldY, color);
}
}
}
return destBmp;
}
#endregion #region 图片任意角度旋转
/// <summary>
/// 图片任意角度旋转
/// </summary>
/// <param name="bmp">原始图Bitmap</param>
/// <param name="angle">旋转角度</param>
/// <param name="bkColor">背景色</param>
/// <returns>输出Bitmap</returns>
public static Bitmap KiRotate(Bitmap bmp, float angle, Color bkColor)
{
int w = bmp.Width;
int h = bmp.Height; PixelFormat pf; if (bkColor == Color.Transparent)
{
pf = PixelFormat.Format32bppArgb;
}
else
{
pf = bmp.PixelFormat;
} Bitmap tmp = new Bitmap(w, h, pf);
Graphics g = Graphics.FromImage(tmp);
g.Clear(bkColor);
g.DrawImageUnscaled(bmp, , );
g.Dispose(); GraphicsPath path = new GraphicsPath();
path.AddRectangle(new RectangleF(0f, 0f, w, h));
Matrix mtrx = new Matrix();
mtrx.Rotate(angle);
RectangleF rct = path.GetBounds(mtrx); Bitmap dst = new Bitmap((int)rct.Width, (int)rct.Height, pf);
g = Graphics.FromImage(dst);
g.Clear(bkColor);
g.TranslateTransform(-rct.X, -rct.Y);
g.RotateTransform(angle);
g.InterpolationMode = InterpolationMode.HighQualityBilinear;
g.DrawImageUnscaled(tmp, , );
g.Dispose();
tmp.Dispose(); return dst;
}
#endregion #region 随机生成贝塞尔曲线
/// <summary>
/// 随机生成贝塞尔曲线
/// </summary>
/// <param name="bmp">一个图片的实例</param>
/// <param name="lineNum">线条数量</param>
/// <returns></returns>
public Bitmap DrawRandomBezier(Int32 lineNum)
{
Bitmap b = new Bitmap(bgWidth, bgHeight);
b.MakeTransparent();
Graphics g = Graphics.FromImage(b);
g.Clear(Color.Transparent);
g.SmoothingMode = SmoothingMode.HighQuality;
g.PixelOffsetMode = PixelOffsetMode.HighQuality; GraphicsPath gPath1 = new GraphicsPath();
Int32 lineRandNum = random.Next(lineNum); for (int i = ; i < (lineNum - lineRandNum); i++)
{
Pen p = new Pen(GetRandomDeepColor());
Point[] point = {
new Point(random.Next(, (b.Width / )), random.Next(, (b.Height))),
new Point(random.Next((b.Width / ) * , (b.Width / ) * ), random.Next(, (b.Height))),
new Point(random.Next((b.Width / ) * , (b.Width / ) * ), random.Next(, (b.Height))),
new Point(random.Next((b.Width / ) * , b.Width), random.Next(, (b.Height)))
}; gPath1.AddBeziers(point);
g.DrawPath(p, gPath1);
p.Dispose();
}
for (int i = ; i < lineRandNum; i++)
{
Pen p = new Pen(GetRandomDeepColor());
Point[] point = {
new Point(random.Next(, b.Width), random.Next(, b.Height)),
new Point(random.Next((b.Width / ) * , b.Width), random.Next(, b.Height)),
new Point(random.Next((b.Width / ) * , b.Width), random.Next(, b.Height)),
new Point(random.Next(, b.Width), random.Next(, b.Height))
};
gPath1.AddBeziers(point);
g.DrawPath(p, gPath1);
p.Dispose();
}
return b;
}
#endregion #region 画直线
/// <summary>
/// 画直线
/// </summary>
/// <param name="bmp">一个bmp实例</param>
/// <param name="lineNum">线条个数</param>
/// <returns></returns>
public Bitmap DrawRandomLine(Int32 lineNum)
{
if (lineNum < ) throw new ArgumentNullException("参数bmp为空!");
Bitmap b = new Bitmap(bgWidth, bgHeight);
b.MakeTransparent();
Graphics g = Graphics.FromImage(b);
g.Clear(Color.Transparent);
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.SmoothingMode = SmoothingMode.HighQuality;
for (int i = ; i < lineNum; i++)
{
Pen p = new Pen(GetRandomDeepColor());
Point pt1 = new Point(random.Next(, (b.Width / ) * ), random.Next(b.Height));
Point pt2 = new Point(random.Next((b.Width / ) * , b.Width), random.Next(b.Height));
g.DrawLine(p, pt1, pt2);
p.Dispose();
} return b;
}
#endregion #region 画随机噪点
/// <summary>
/// 画随机噪点
/// </summary>
/// <param name="pixNum">噪点的百分比</param>
/// <returns></returns>
public Bitmap DrawRandomPixel(Int32 pixNum)
{
Bitmap b = new Bitmap(bgWidth, bgHeight);
b.MakeTransparent();
Graphics graph = Graphics.FromImage(b);
graph.SmoothingMode = SmoothingMode.HighQuality;
graph.InterpolationMode = InterpolationMode.HighQualityBilinear; //画噪点
for (int i = ; i < (bgHeight * bgWidth) / pixNum; i++)
{
int x = random.Next(b.Width);
int y = random.Next(b.Height);
b.SetPixel(x, y, GetRandomDeepColor());
//下移坐标重新画点
if ((x + ) < b.Width && (y + ) < b.Height)
{
//画图片的前景噪音点
graph.DrawRectangle(new Pen(Color.Silver), random.Next(b.Width), random.Next(b.Height), , );
} } return b;
}
#endregion #region 画随机字符串中间连线
/// <summary>
/// 画随机字符串中间连线
/// </summary>
/// <returns></returns>
private Bitmap DrawStringline()
{
Bitmap b = new Bitmap(bgWidth, bgHeight);
b.MakeTransparent();
Graphics g = Graphics.FromImage(b);
g.SmoothingMode = SmoothingMode.AntiAlias; Point[] p = new Point[validationCodeCount];
for (int i = ; i < validationCodeCount; i++)
{
p[i] = strPoint[i];
//throw new Exception(strPoint.Length.ToString());
}
// g.DrawBezier(new Pen(GetRandomDeepColor()), strPoint);
//g.DrawClosedCurve(new Pen(GetRandomDeepColor()), strPoint);
g.DrawCurve(new Pen(GetRandomDeepColor(), ), strPoint); return b;
}
#endregion #region 写入验证码的字符串
/// <summary>
/// 写入验证码的字符串
/// </summary>
private Bitmap DrawRandomString()
{
if (fontMaxSize >= (bgHeight / ) * ) throw new ArgumentException("字体最大值参数FontMaxSize与验证码高度相近,这会导致描绘验证码字符串时出错,请重新设置参数!");
Bitmap b = new Bitmap(bgWidth, bgHeight);
b.MakeTransparent();
Graphics g = Graphics.FromImage(b); g.Clear(Color.Transparent);
g.PixelOffsetMode = PixelOffsetMode.Half;
g.SmoothingMode = SmoothingMode.HighQuality;
g.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit;
g.InterpolationMode = InterpolationMode.HighQualityBilinear; char[] chars = GetRandomString(validationCodeCount).ToCharArray();//拆散字符串成单字符数组
validationCode = chars.ToString(); //设置字体显示格式
StringFormat format = new StringFormat(StringFormatFlags.NoClip);
format.Alignment = StringAlignment.Center;
format.LineAlignment = StringAlignment.Center;
FontFamily f = new FontFamily(GenericFontFamilies.Monospace); Int32 charNum = chars.Length; Point sPoint = new Point();
Int32 fontSize = ;
for (int i = ; i < validationCodeCount; i++)
{
int findex = random.Next();
//定义字体
Font textFont = new Font(f, random.Next(fontMinSize, fontMaxSize), FontStyle.Bold);
//定义画刷,用于写字符串
//Brush brush = new SolidBrush(GetRandomDeepColor());
Int32 textFontSize = Convert.ToInt32(textFont.Size);
fontSize = textFontSize;
Point point = new Point(random.Next((bgWidth / charNum) * i + , (bgWidth / charNum) * (i + )), random.Next(bgHeight / + textFontSize / , bgHeight - textFontSize / )); //如果当前字符X坐标小于字体的二分之一大小
if (point.X < textFontSize / )
{
point.X = point.X + textFontSize / ;
}
//防止文字叠加
if (i > && (point.X - sPoint.X < (textFontSize / + textFontSize / )))
{
point.X = point.X + textFontSize;
}
//如果当前字符X坐标大于图片宽度,就减去字体的宽度
if (point.X > (bgWidth - textFontSize / ))
{
point.X = bgWidth - textFontSize / ;
} sPoint = point; float angle = random.Next(-rotationAngle, rotationAngle);//转动的度数
g.TranslateTransform(point.X, point.Y);//移动光标到指定位置
g.RotateTransform(angle); //设置渐变画刷
Rectangle myretang = new Rectangle(, , Convert.ToInt32(textFont.Size), Convert.ToInt32(textFont.Size));
Color c = GetRandomDeepColor();
LinearGradientBrush mybrush2 = new LinearGradientBrush(myretang, c, GetLightColor(c, ), random.Next()); g.DrawString(chars[i].ToString(), textFont, mybrush2, , , format); g.RotateTransform(-angle);//转回去
g.TranslateTransform(-point.X, -point.Y);//移动光标到指定位置,每个字符紧凑显示,避免被软件识别 strPoint[i] = point; textFont.Dispose();
mybrush2.Dispose();
}
return b;
}
#endregion #region 画干扰背景文字
/// <summary>
/// 画背景干扰文字
/// </summary>
/// <returns></returns>
private Bitmap DrawRandBgString()
{
Bitmap b = new Bitmap(bgWidth, bgHeight);
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" };
b.MakeTransparent();
Graphics g = Graphics.FromImage(b); g.Clear(Color.Transparent);
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.SmoothingMode = SmoothingMode.HighQuality;
g.TextRenderingHint = TextRenderingHint.AntiAlias;
g.InterpolationMode = InterpolationMode.HighQualityBilinear; //设置字体显示格式
StringFormat format = new StringFormat(StringFormatFlags.NoClip);
format.Alignment = StringAlignment.Center;
format.LineAlignment = StringAlignment.Center; FontFamily f = new FontFamily(GenericFontFamilies.Serif);
Font textFont = new Font(f, randomStringFontSize, FontStyle.Underline); int randAngle = ; //随机转动角度 for (int i = ; i < RandomStringCount; i++)
{ Brush brush = new System.Drawing.SolidBrush(GetRandomLightColor());
Point pot = new Point(random.Next(, bgWidth - ), random.Next(, bgHeight - ));
//随机转动的度数
float angle = random.Next(-randAngle, randAngle); //转动画布
g.RotateTransform(angle);
g.DrawString(randStr[random.Next(randStr.Length)], textFont, brush, pot, format);
//转回去,为下一个字符做准备
g.RotateTransform(-angle);
//释放资源
brush.Dispose();
}
textFont.Dispose();
format.Dispose();
f.Dispose(); return b;
}
#endregion #region 生成随机字符串
/// <summary>
/// 生成随机字符串
/// </summary>
/// <returns></returns>
private string GetRandomString(Int32 textLength)
{
string[] randomArray = charCollection.Split(','); //将字符串生成数组
int arrayLength = randomArray.Length;
string randomString = "";
for (int i = ; i < textLength; i++)
{
randomString += randomArray[random.Next(, arrayLength)];
}
return randomString; //长度是textLength +1
}
#endregion #region 内部方法:绘制验证码背景
private void DrawBackground(HatchStyle hatchStyle)
{
//设置填充背景时用的笔刷
HatchBrush hBrush = new HatchBrush(hatchStyle, backColor); //填充背景图片
dc.FillRectangle(hBrush, , , this.bgWidth, this.bgHeight);
}
#endregion #region 根据指定长度,返回随机验证码
/// <summary>
/// 根据指定长度,返回随机验证码
/// </summary>
/// <param >制定长度</param>
/// <returns>随即验证码</returns>
public string Next(int length)
{
this.validationCode = GetRandomCode(length);
return this.validationCode;
}
#endregion #region 内部方法:返回指定长度的随机验证码字符串
/// <summary>
/// 根据指定大小返回随机验证码
/// </summary>
/// <param >字符串长度</param>
/// <returns>随机字符串</returns>
private string GetRandomCode(int length)
{
StringBuilder sb = new StringBuilder(); for (int i = ; i < length; i++)
{
sb.Append(Char.ConvertFromUtf32(RandomAZ09()));
} return sb.ToString();
}
#endregion #region 内部方法:产生随机数和随机点 /// <summary>
/// 产生0-9A-Z的随机字符代码
/// </summary>
/// <returns>字符代码</returns>
private int RandomAZ09()
{
int result = ;
Random ram = new Random();
int i = ram.Next(); switch (i)
{
case :
result = ram.Next(, );
break;
case :
result = ram.Next(, );
break;
} return result;
} /// <summary>
/// 返回一个随机点,该随机点范围在验证码背景大小范围内
/// </summary>
/// <returns>Point对象</returns>
private Point RandomPoint()
{
Random ram = new Random();
Point point = new Point(ram.Next(this.bgWidth), ram.Next(this.bgHeight));
return point;
}
#endregion #region 随机生成颜色值
/// <summary>
/// 生成随机深颜色
/// </summary>
/// <returns></returns>
public Color GetRandomDeepColor()
{
int nRed, nGreen, nBlue; // nBlue,nRed nGreen 相差大一点 nGreen 小一些
//int high = 255;
int redLow = ;
int greenLow = ;
int blueLow = ;
nRed = random.Next(redLow);
nGreen = random.Next(greenLow);
nBlue = random.Next(blueLow);
Color color = Color.FromArgb(nRed, nGreen, nBlue);
return color;
} /// <summary>
/// 生成随机浅颜色
/// </summary>
/// <returns>randomColor</returns>
public Color GetRandomLightColor()
{
int nRed, nGreen, nBlue; //越大颜色越浅
int low = ; //色彩的下限
int high = ; //色彩的上限
nRed = random.Next(high) % (high - low) + low;
nGreen = random.Next(high) % (high - low) + low;
nBlue = random.Next(high) % (high - low) + low;
Color color = Color.FromArgb(nRed, nGreen, nBlue);
return color;
}
/// <summary>
/// 生成随机颜色值
/// </summary>
/// <returns></returns>
public Color GetRandomColor()
{
int nRed, nGreen, nBlue; //越大颜色越浅
int low = ; //色彩的下限
int high = ; //色彩的上限
nRed = random.Next(high) % (high - low) + low;
nGreen = random.Next(high) % (high - low) + low;
nBlue = random.Next(high) % (high - low) + low;
Color color = Color.FromArgb(nRed, nGreen, nBlue);
return color;
}
/// <summary>
/// 获取与当前颜色值相加后的颜色
/// </summary>
/// <param name="c"></param>
/// <returns></returns>
public Color GetLightColor(Color c, Int32 value)
{
int nRed = c.R, nGreen = c.G, nBlue = c.B; //越大颜色越浅
if (nRed + value < && nRed + value > )
{
nRed = c.R + ;
}
if (nGreen + value < && nGreen + value > )
{
nGreen = c.G + ;
}
if (nBlue + value < && nBlue + value > )
{
nBlue = c.B + ;
}
Color color = Color.FromArgb(nRed, nGreen, nBlue);
return color;
}
#endregion #region 合并图片
/// <summary>
/// 合并图片
/// </summary>
/// <param name="maps"></param>
/// <returns></returns>
private Bitmap MergerImg(params Bitmap[] maps)
{
int i = maps.Length;
if (i == )
throw new Exception("图片数不能够为0");
//创建要显示的图片对象,根据参数的个数设置宽度
Bitmap backgroudImg = new Bitmap(i * , );
Graphics g = Graphics.FromImage(backgroudImg);
//清除画布,背景设置为白色
g.Clear(System.Drawing.Color.White);
for (int j = ; j < i; j++)
{
//g.DrawImage(maps[j], j * 11, 0, maps[j].Width, maps[j].Height);
g.DrawImageUnscaled(maps[j], , );
}
g.Dispose();
return backgroudImg;
}
#endregion #region 生成不重复的随机数,该函数会消耗大量系统资源
/// <summary>
/// 生成不重复的随机数,该函数会消耗大量系统资源
/// </summary>
/// <returns></returns>
private static int GetRandomSeed()
{
byte[] bytes = new byte[];
System.Security.Cryptography.RNGCryptoServiceProvider rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
rng.GetBytes(bytes);
return BitConverter.ToInt32(bytes, );
}
#endregion #region 缩放图片
/// <summary>
/// 缩放图片
/// </summary>
/// <param name="bmp">原始Bitmap</param>
/// <param name="newW">新的宽度</param>
/// <param name="newH">新的高度</param>
/// <param name="Mode">缩放质量</param>
/// <returns>处理以后的图片</returns>
public static Bitmap KiResizeImage(Bitmap bmp, int newW, int newH, InterpolationMode Mode)
{
try
{
Bitmap b = new Bitmap(newW, newH);
Graphics g = Graphics.FromImage(b);
// 插值算法的质量
g.InterpolationMode = Mode;
g.DrawImage(bmp, new Rectangle(, , newW, newH), new Rectangle(, , bmp.Width, bmp.Height), GraphicsUnit.Pixel);
g.Dispose();
return b;
}
catch
{
return null;
}
}
#endregion #region 绘制圆角矩形
/// <summary>
/// C# GDI+ 绘制圆角矩形
/// </summary>
/// <param name="g">Graphics 对象</param>
/// <param name="rectangle">Rectangle 对象,圆角矩形区域</param>
/// <param name="borderColor">边框颜色</param>
/// <param name="borderWidth">边框宽度</param>
/// <param name="r">圆角半径</param>
private static void DrawRoundRectangle(Graphics g, Rectangle rectangle, Color borderColor, float borderWidth, int r)
{
// 如要使边缘平滑,请取消下行的注释
g.SmoothingMode = SmoothingMode.HighQuality; // 由于边框也需要一定宽度,需要对矩形进行修正
//rectangle = new Rectangle(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
Pen p = new Pen(borderColor, borderWidth);
// 调用 getRoundRectangle 得到圆角矩形的路径,然后再进行绘制
g.DrawPath(p, getRoundRectangle(rectangle, r));
}
#endregion #region 根据普通矩形得到圆角矩形的路径
/// <summary>
/// 根据普通矩形得到圆角矩形的路径
/// </summary>
/// <param name="rectangle">原始矩形</param>
/// <param name="r">半径</param>
/// <returns>图形路径</returns>
private static GraphicsPath getRoundRectangle(Rectangle rectangle, int r)
{
int l = * r;
// 把圆角矩形分成八段直线、弧的组合,依次加到路径中
GraphicsPath gp = new GraphicsPath();
gp.AddLine(new Point(rectangle.X + r, rectangle.Y), new Point(rectangle.Right - r, rectangle.Y));
gp.AddArc(new Rectangle(rectangle.Right - l, rectangle.Y, l, l), 270F, 90F); gp.AddLine(new Point(rectangle.Right, rectangle.Y + r), new Point(rectangle.Right, rectangle.Bottom - r));
gp.AddArc(new Rectangle(rectangle.Right - l, rectangle.Bottom - l, l, l), 0F, 90F); gp.AddLine(new Point(rectangle.Right - r, rectangle.Bottom), new Point(rectangle.X + r, rectangle.Bottom));
gp.AddArc(new Rectangle(rectangle.X, rectangle.Bottom - l, l, l), 90F, 90F); gp.AddLine(new Point(rectangle.X, rectangle.Bottom - r), new Point(rectangle.X, rectangle.Y + r));
gp.AddArc(new Rectangle(rectangle.X, rectangle.Y, l, l), 180F, 90F);
return gp;
}
#endregion #region 柔化
///<summary>
/// 柔化
/// </summary>
/// <param name="b">原始图</param>
/// <returns>输出图</returns>
public static Bitmap KiBlur(Bitmap b)
{ if (b == null)
{
return null;
} int w = b.Width;
int h = b.Height; try
{ Bitmap bmpRtn = new Bitmap(w, h, PixelFormat.Format24bppRgb); BitmapData srcData = b.LockBits(new Rectangle(, , w, h), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
BitmapData dstData = bmpRtn.LockBits(new Rectangle(, , w, h), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); unsafe
{
byte* pIn = (byte*)srcData.Scan0.ToPointer();
byte* pOut = (byte*)dstData.Scan0.ToPointer();
int stride = srcData.Stride;
byte* p; for (int y = ; y < h; y++)
{
for (int x = ; x < w; x++)
{
//取周围9点的值
if (x == || x == w - || y == || y == h - )
{
//不做
pOut[] = pIn[];
pOut[] = pIn[];
pOut[] = pIn[];
}
else
{
int r1, r2, r3, r4, r5, r6, r7, r8, r9;
int g1, g2, g3, g4, g5, g6, g7, g8, g9;
int b1, b2, b3, b4, b5, b6, b7, b8, b9; float vR, vG, vB; //左上
p = pIn - stride - ;
r1 = p[];
g1 = p[];
b1 = p[]; //正上
p = pIn - stride;
r2 = p[];
g2 = p[];
b2 = p[]; //右上
p = pIn - stride + ;
r3 = p[];
g3 = p[];
b3 = p[]; //左侧
p = pIn - ;
r4 = p[];
g4 = p[];
b4 = p[]; //右侧
p = pIn + ;
r5 = p[];
g5 = p[];
b5 = p[]; //右下
p = pIn + stride - ;
r6 = p[];
g6 = p[];
b6 = p[]; //正下
p = pIn + stride;
r7 = p[];
g7 = p[];
b7 = p[]; //右下
p = pIn + stride + ;
r8 = p[];
g8 = p[];
b8 = p[]; //自己
p = pIn;
r9 = p[];
g9 = p[];
b9 = p[]; vR = (float)(r1 + r2 + r3 + r4 + r5 + r6 + r7 + r8 + r9);
vG = (float)(g1 + g2 + g3 + g4 + g5 + g6 + g7 + g8 + g9);
vB = (float)(b1 + b2 + b3 + b4 + b5 + b6 + b7 + b8 + b9); vR /= ;
vG /= ;
vB /= ; pOut[] = (byte)vB;
pOut[] = (byte)vG;
pOut[] = (byte)vR; } pIn += ;
pOut += ;
}// end of x pIn += srcData.Stride - w * ;
pOut += srcData.Stride - w * ;
} // end of y
} b.UnlockBits(srcData);
bmpRtn.UnlockBits(dstData); return bmpRtn;
}
catch
{
return null;
} } // end of KiBlur
#endregion #region 滤镜
/// <summary>
/// 红色滤镜
/// </summary>
/// <param name="bitmap">Bitmap</param>
/// <param name="threshold">阀值 -255~255</param>
/// <returns></returns>
public System.Drawing.Bitmap AdjustToRed(System.Drawing.Bitmap bitmap, int threshold)
{
for (int y = ; y < bitmap.Height; y++)
{
for (int x = ; x < bitmap.Width; x++)
{
// 取得每一個 pixel
var pixel = bitmap.GetPixel(x, y);
var pR = pixel.R + threshold;
pR = Math.Max(pR, );
pR = Math.Min(, pR);
// 將改過的 RGB 寫回
// 只寫入紅色的值 , G B 都放零
System.Drawing.Color newColor = System.Drawing.Color.FromArgb(pixel.A, pR, , );
bitmap.SetPixel(x, y, newColor);
}
}
// 回傳結果
return bitmap;
} /// <summary>
/// 绿色滤镜
/// </summary>
/// <param name="bitmap">一个图片实例</param>
/// <param name="threshold">阀值 -255~+255</param>
/// <returns></returns>
public System.Drawing.Bitmap AdjustToGreen(System.Drawing.Bitmap bitmap, int threshold)
{
for (int y = ; y < bitmap.Height; y++)
{
for (int x = ; x < bitmap.Width; x++)
{
// 取得每一個 pixel
var pixel = bitmap.GetPixel(x, y);
//判斷是否超過255 如果超過就是255
var pG = pixel.G + threshold;
//如果小於0就為0
if (pG > ) pG = ;
if (pG < ) pG = ;
// 將改過的 RGB 寫回
// 只寫入綠色的值 , R B 都放零
System.Drawing.Color newColor = System.Drawing.Color.FromArgb(pixel.A, , pG, );
bitmap.SetPixel(x, y, newColor);
}
}
// 回傳結果
return bitmap;
}
/// <summary>
/// 蓝色滤镜
/// </summary>
/// <param name="bitmap">一个图片实例</param>
/// <param name="threshold">阀值 -255~255</param>
/// <returns></returns>
public System.Drawing.Bitmap AdjustToBlue(System.Drawing.Bitmap bitmap, int threshold)
{
for (int y = ; y < bitmap.Height; y++)
{
for (int x = ; x < bitmap.Width; x++)
{
// 取得每一個 pixel
var pixel = bitmap.GetPixel(x, y);
//判斷是否超過255 如果超過就是255
var pB = pixel.B + threshold;
//如果小於0就為0
if (pB > ) pB = ;
if (pB < ) pB = ;
// 將改過的 RGB 寫回
// 只寫入藍色的值 , R G 都放零
System.Drawing.Color newColor = System.Drawing.Color.FromArgb(pixel.A, , , pB);
bitmap.SetPixel(x, y, newColor);
}
}
// 回傳結果
return bitmap;
}
/// <summary>
/// 调整 RGB 色调
/// </summary>
/// <param name="bitmap"></param>
/// <param name="thresholdRed">红色阀值</param>
/// <param name="thresholdBlue">蓝色阀值</param>
/// <param name="thresholdGreen">绿色阀值</param>
/// <returns></returns>
public System.Drawing.Bitmap AdjustToCustomColor(System.Drawing.Bitmap bitmap, int thresholdRed, int thresholdGreen, int thresholdBlue)
{
for (int y = ; y < bitmap.Height; y++)
{
for (int x = ; x < bitmap.Width; x++)
{
// 取得每一個 pixel
var pixel = bitmap.GetPixel(x, y);
//判斷是否超過255 如果超過就是255
var pG = pixel.G + thresholdGreen;
//如果小於0就為0
if (pG > ) pG = ;
if (pG < ) pG = ;
//判斷是否超過255 如果超過就是255
var pR = pixel.R + thresholdRed;
//如果小於0就為0
if (pR > ) pR = ;
if (pR < ) pR = ;
//判斷是否超過255 如果超過就是255
var pB = pixel.B + thresholdBlue;
//如果小於0就為0
if (pB > ) pB = ;
if (pB < ) pB = ;
// 將改過的 RGB 寫回
// 只寫入綠色的值 , R B 都放零
System.Drawing.Color newColor = System.Drawing.Color.FromArgb(pixel.A, pR, pG, pB);
bitmap.SetPixel(x, y, newColor);
}
}
return bitmap;
}
#endregion #region 图片去色(图片黑白化)
/// <summary>
/// 图片去色(图片黑白化)
/// </summary>
/// <param name="original">一个需要处理的图片</param>
/// <returns></returns>
public static Bitmap MakeGrayscale(Bitmap original)
{
//create a blank bitmap the same size as original
Bitmap newBitmap = new Bitmap(original.Width, original.Height); //get a graphics object from the new image
Graphics g = Graphics.FromImage(newBitmap);
g.SmoothingMode = SmoothingMode.HighQuality;
//create the grayscale ColorMatrix
ColorMatrix colorMatrix = new ColorMatrix(new float[][]
{
new float[] {.3f, .3f, .3f, , },
new float[] {.59f, .59f, .59f, , },
new float[] {.11f, .11f, .11f, , },
new float[] {, , , , },
new float[] {, , , , }
}); //create some image attributes
ImageAttributes attributes = new ImageAttributes(); //set the color matrix attribute
attributes.SetColorMatrix(colorMatrix); //draw the original image on the new image
//using the grayscale color matrix
g.DrawImage(original, new Rectangle(, , original.Width, original.Height),
, , original.Width, original.Height, GraphicsUnit.Pixel, attributes); //dispose the Graphics object
g.Dispose();
return newBitmap;
}
#endregion #region 增加或減少亮度
/// <summary>
/// 增加或減少亮度
/// </summary>
/// <param name="img">System.Drawing.Image Source </param>
/// <param name="valBrightness">0~255</param>
/// <returns></returns>
public System.Drawing.Bitmap AdjustBrightness(System.Drawing.Image img, int valBrightness)
{
// 讀入欲轉換的圖片並轉成為 Bitmap
System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(img); for (int y = ; y < bitmap.Height; y++)
{
for (int x = ; x < bitmap.Width; x++)
{
// 取得每一個 pixel
var pixel = bitmap.GetPixel(x, y); // 判斷 如果處理過後 255 就設定為 255 如果小於則設定為 0
var pR = ((pixel.R + valBrightness > ) ? : pixel.R + valBrightness) < ? : ((pixel.R + valBrightness > ) ? : pixel.R + valBrightness);
var pG = ((pixel.G + valBrightness > ) ? : pixel.G + valBrightness) < ? : ((pixel.G + valBrightness > ) ? : pixel.G + valBrightness);
var pB = ((pixel.B + valBrightness > ) ? : pixel.B + valBrightness) < ? : ((pixel.B + valBrightness > ) ? : pixel.B + valBrightness); // 將改過的 RGB 寫回
System.Drawing.Color newColor = System.Drawing.Color.FromArgb(pixel.A, pR, pG, pB); bitmap.SetPixel(x, y, newColor); }
}
// 回傳結果
return bitmap;
}
#endregion #region 浮雕效果
/// <summary>
/// 浮雕效果
/// </summary>
/// <param name="src">一个图片实例</param>
/// <returns></returns>
public Bitmap AdjustToStone(Bitmap src)
{
// 依照 Format24bppRgb 每三个表示一 Pixel 0: 蓝 1: 绿 2: 红
BitmapData bitmapData = src.LockBits(new Rectangle(, , src.Width, src.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); unsafe
{
// 抓住第一个 Pixel 第一个数值
byte* p = (byte*)(void*)bitmapData.Scan0; // 跨步值 - 宽度 *3 可以算出畸零地 之后跳到下一行
int nOffset = bitmapData.Stride - src.Width * ; for (int y = ; y < src.Height; ++y)
{
for (int x = ; x < src.Width; ++x)
{
// 为了理解方便 所以特地在命名
int r, g, b;
// 先取得下一个 Pixel
var q = p + ;
r = Math.Abs(p[] - q[] + );
r = r < ? : r;
r = r > ? : r;
p[] = (byte)r; g = Math.Abs(p[] - q[] + );
g = g < ? : g;
g = g > ? : g;
p[] = (byte)g; b = Math.Abs(p[] - q[] + );
b = b < ? : b;
b = b > ? : b;
p[] = (byte)b; // 跳去下一个 Pixel
p += ; }
// 跨越畸零地
p += nOffset;
}
}
src.UnlockBits(bitmapData);
return src;
}
#endregion #region 水波纹效果
/// <summary>
/// 水波纹效果
/// </summary>
/// <param name="src"></param>
/// <param name="nWave">坡度</param>
/// www.it165.net
/// <returns></returns>
public Bitmap AdjustRippleEffect(Bitmap src, short nWave)
{ int nWidth = src.Width;
int nHeight = src.Height; // 透过公式进行水波纹的採样 PointF[,] fp = new PointF[nWidth, nHeight]; Point[,] pt = new Point[nWidth, nHeight]; Point mid = new Point();
mid.X = nWidth / ;
mid.Y = nHeight / ; double newX, newY;
double xo, yo; //先取样将水波纹座标跟RGB取出
for (int x = ; x < nWidth; ++x)
for (int y = ; y < nHeight; ++y)
{
xo = ((double)nWave * Math.Sin(2.0 * 3.1415 * (float)y / 128.0));
yo = ((double)nWave * Math.Cos(2.0 * 3.1415 * (float)x / 128.0)); newX = (x + xo);
newY = (y + yo); if (newX > && newX < nWidth)
{
fp[x, y].X = (float)newX;
pt[x, y].X = (int)newX;
}
else
{
fp[x, y].X = (float)0.0;
pt[x, y].X = ;
} if (newY > && newY < nHeight)
{
fp[x, y].Y = (float)newY;
pt[x, y].Y = (int)newY;
}
else
{
fp[x, y].Y = (float)0.0;
pt[x, y].Y = ;
}
} //进行合成
Bitmap bSrc = (Bitmap)src.Clone(); // 依照 Format24bppRgb 每三个表示一 Pixel 0: 蓝 1: 绿 2: 红
BitmapData bitmapData = src.LockBits(new Rectangle(, , src.Width, src.Height), ImageLockMode.ReadWrite,
PixelFormat.Format24bppRgb);
BitmapData bmSrc = bSrc.LockBits(new Rectangle(, , bSrc.Width, bSrc.Height), ImageLockMode.ReadWrite,
PixelFormat.Format24bppRgb); int scanline = bitmapData.Stride; IntPtr Scan0 = bitmapData.Scan0;
IntPtr SrcScan0 = bmSrc.Scan0; unsafe
{
byte* p = (byte*)(void*)Scan0;
byte* pSrc = (byte*)(void*)SrcScan0; int nOffset = bitmapData.Stride - src.Width * ; int xOffset, yOffset; for (int y = ; y < nHeight; ++y)
{
for (int x = ; x < nWidth; ++x)
{
xOffset = pt[x, y].X;
yOffset = pt[x, y].Y; if (yOffset >= && yOffset < nHeight && xOffset >= && xOffset < nWidth)
{
p[] = pSrc[(yOffset * scanline) + (xOffset * )];
p[] = pSrc[(yOffset * scanline) + (xOffset * ) + ];
p[] = pSrc[(yOffset * scanline) + (xOffset * ) + ];
} p += ;
}
p += nOffset;
}
} src.UnlockBits(bitmapData);
bSrc.UnlockBits(bmSrc); return src;
}
#endregion #region 调整曝光度值
/// <summary>
/// 调整曝光度值
/// </summary>
/// <param name="src">原图</param>
/// <param name="r"></param>
/// <param name="g"></param>
/// <param name="b"></param>
/// <returns></returns>
public Bitmap AdjustGamma(Bitmap src, double r, double g, double b)
{
// 判断是不是在0.2~5 之间
r = Math.Min(Math.Max(0.2, r), );
g = Math.Min(Math.Max(0.2, g), );
b = Math.Min(Math.Max(0.2, b), ); // 依照 Format24bppRgb 每三个表示一 Pixel 0: 蓝 1: 绿 2: 红
BitmapData bitmapData = src.LockBits(new Rectangle(, , src.Width, src.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); unsafe
{
// 抓住第一个 Pixel 第一个数值
byte* p = (byte*)(void*)bitmapData.Scan0; // 跨步值 - 宽度 *3 可以算出畸零地 之后跳到下一行
int nOffset = bitmapData.Stride - src.Width * ; for (int y = ; y < src.Height; y++)
{
for (int x = ; x < src.Width; x++)
{
p[] = (byte)Math.Min(, (int)((255.0 * Math.Pow(p[] / 255.0, 1.0 / r)) + 0.5));
p[] = (byte)Math.Min(, (int)((255.0 * Math.Pow(p[] / 255.0, 1.0 / g)) + 0.5));
p[] = (byte)Math.Min(, (int)((255.0 * Math.Pow(p[] / 255.0, 1.0 / b)) + 0.5)); // 跳去下一个 Pixel
p += ; }
// 跨越畸零地
p += nOffset;
}
}
src.UnlockBits(bitmapData);
return src; }
#endregion #region 高对比,对过深的颜色调浅,过浅的颜色调深。
/// <summary>
/// 高对比,对过深的颜色调浅,过浅的颜色调深。
/// </summary>
/// <param name="src"></param>
/// <param name="effectThreshold"> 高对比程度 -100~100</param>
/// <returns></returns>
public Bitmap Contrast(Bitmap src, float effectThreshold)
{ // 依照 Format24bppRgb 每三个表示一 Pixel 0: 蓝 1: 绿 2: 红
BitmapData bitmapData = src.LockBits(new Rectangle(, , src.Width, src.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); // 判断是否在 -100~100
effectThreshold = effectThreshold < - ? - : effectThreshold;
effectThreshold = effectThreshold > ? : effectThreshold; effectThreshold = (float)((100.0 + effectThreshold) / 100.0);
effectThreshold *= effectThreshold; unsafe
{
// 抓住第一个 Pixel 第一个数值 www.it165.net
byte* p = (byte*)(void*)bitmapData.Scan0; // 跨步值 - 宽度 *3 可以算出畸零地 之后跳到下一行
int nOffset = bitmapData.Stride - src.Width * ; for (int y = ; y < src.Height; y++)
{
for (int x = ; x < src.Width; x++)
{
double buffer = ; // 公式 (Red/255)-0.5= 偏离中间值程度
// ((偏离中间值程度 * 影响范围)+0.4 ) * 255
buffer = ((((p[] / 255.0) - 0.5) * effectThreshold) + 0.5) * 255.0;
buffer = buffer > ? : buffer;
buffer = buffer < ? : buffer;
p[] = (byte)buffer; buffer = ((((p[] / 255.0) - 0.5) * effectThreshold) + 0.5) * 255.0;
buffer = buffer > ? : buffer;
buffer = buffer < ? : buffer;
p[] = (byte)buffer; buffer = ((((p[] / 255.0) - 0.5) * effectThreshold) + 0.5) * 255.0;
buffer = buffer > ? : buffer;
buffer = buffer < ? : buffer;
p[] = (byte)buffer; // 跳去下一个 Pixel
p += ; }
// 跨越畸零地
p += nOffset;
}
}
src.UnlockBits(bitmapData);
return src; }
#endregion #region 对图片进行雾化效果
/// <summary>
/// 对图片进行雾化效果
/// </summary>
/// <param name="bmp"></param>
/// <returns></returns>
public Bitmap Atomization(Bitmap bmp)
{ int Height = bmp.Height;
int Width = bmp.Width;
Bitmap newBitmap = new Bitmap(Width, Height);
Bitmap oldBitmap = bmp;
Color pixel;
for (int x = ; x < Width - ; x++)
{
for (int y = ; y < Height - ; y++)
{
Random MyRandom = new Random( Guid.NewGuid().GetHashCode());
int k = MyRandom.Next();
//像素块大小
int dx = x + k % ;
int dy = y + k % ;
if (dx >= Width)
dx = Width - ;
if (dy >= Height)
dy = Height - ;
pixel = oldBitmap.GetPixel(dx, dy);
newBitmap.SetPixel(x, y, pixel);
}
}
return newBitmap;
}
#endregion } //END Class DrawValidationCode
#endregion #region 高斯模糊算法
/// <summary>
/// 高斯模糊算法
/// </summary>
public class Gaussian
{
public static double[,] Calculate1DSampleKernel(double deviation, int size)
{
double[,] ret = new double[size, ];
double sum = ;
int half = size / ;
for (int i = ; i < size; i++)
{
ret[i, ] = / (Math.Sqrt( * Math.PI) * deviation) * Math.Exp(-(i - half) * (i - half) / ( * deviation * deviation));
sum += ret[i, ];
}
return ret;
}
public static double[,] Calculate1DSampleKernel(double deviation)
{
int size = (int)Math.Ceiling(deviation * ) * + ;
return Calculate1DSampleKernel(deviation, size);
}
public static double[,] CalculateNormalized1DSampleKernel(double deviation)
{
return NormalizeMatrix(Calculate1DSampleKernel(deviation));
}
public static double[,] NormalizeMatrix(double[,] matrix)
{
double[,] ret = new double[matrix.GetLength(), matrix.GetLength()];
double sum = ;
for (int i = ; i < ret.GetLength(); i++)
{
for (int j = ; j < ret.GetLength(); j++)
sum += matrix[i, j];
}
if (sum != )
{
for (int i = ; i < ret.GetLength(); i++)
{
for (int j = ; j < ret.GetLength(); j++)
ret[i, j] = matrix[i, j] / sum;
}
}
return ret;
}
public static double[,] GaussianConvolution(double[,] matrix, double deviation)
{
double[,] kernel = CalculateNormalized1DSampleKernel(deviation);
double[,] res1 = new double[matrix.GetLength(), matrix.GetLength()];
double[,] res2 = new double[matrix.GetLength(), matrix.GetLength()];
//x-direction
for (int i = ; i < matrix.GetLength(); i++)
{
for (int j = ; j < matrix.GetLength(); j++)
res1[i, j] = processPoint(matrix, i, j, kernel, );
}
//y-direction
for (int i = ; i < matrix.GetLength(); i++)
{
for (int j = ; j < matrix.GetLength(); j++)
res2[i, j] = processPoint(res1, i, j, kernel, );
}
return res2;
}
private static double processPoint(double[,] matrix, int x, int y, double[,] kernel, int direction)
{
double res = ;
int half = kernel.GetLength() / ;
for (int i = ; i < kernel.GetLength(); i++)
{
int cox = direction == ? x + i - half : x;
int coy = direction == ? y + i - half : y;
if (cox >= && cox < matrix.GetLength() && coy >= && coy < matrix.GetLength())
{
res += matrix[cox, coy] * kernel[i, ];
}
}
return res;
}
/// <summary>
/// 对颜色值进行灰色处理
/// </summary>
/// <param name="cr"></param>
/// <returns></returns>
private Color grayscale(Color cr)
{
return Color.FromArgb(cr.A, (int)(cr.R * . + cr.G * . + cr.B * 0.11),
(int)(cr.R * . + cr.G * . + cr.B * 0.11),
(int)(cr.R * . + cr.G * . + cr.B * 0.11));
}
/// <summary>
/// 对图片进行高斯模糊
/// </summary>
/// <param name="d">模糊数值,数值越大模糊越很</param>
/// <param name="image">一个需要处理的图片</param>
/// <returns></returns>
public Bitmap FilterProcessImage(double d, Bitmap image)
{
Bitmap ret = new Bitmap(image.Width, image.Height);
Double[,] matrixR = new Double[image.Width, image.Height];
Double[,] matrixG = new Double[image.Width, image.Height];
Double[,] matrixB = new Double[image.Width, image.Height];
for (int i = ; i < image.Width; i++)
{
for (int j = ; j < image.Height; j++)
{
//matrix[i, j] = grayscale(image.GetPixel(i, j)).R;
matrixR[i, j] = image.GetPixel(i, j).R;
matrixG[i, j] = image.GetPixel(i, j).G;
matrixB[i, j] = image.GetPixel(i, j).B;
}
}
matrixR = Gaussian.GaussianConvolution(matrixR, d);
matrixG = Gaussian.GaussianConvolution(matrixG, d);
matrixB = Gaussian.GaussianConvolution(matrixB, d);
for (int i = ; i < image.Width; i++)
{
for (int j = ; j < image.Height; j++)
{
Int32 R = (int)Math.Min(, matrixR[i, j]);
Int32 G = (int)Math.Min(, matrixG[i, j]);
Int32 B = (int)Math.Min(, matrixB[i, j]);
ret.SetPixel(i, j, Color.FromArgb(R, G, B));
}
}
return ret;
} }
#endregion
}

C# :GDI+技术生成复杂型彩色验证码(转载)的更多相关文章

  1. MVC的验证(模型注解和非侵入式脚本的结合使用) .Net中初探Redis .net通过代码发送邮件 Log4net (Log for .net) 使用GDI技术创建ASP.NET验证码 Razor模板引擎 (RazorEngine) .Net程序员应该掌握的正则表达式

    MVC的验证(模型注解和非侵入式脚本的结合使用)   @HtmlHrlper方式创建的标签,会自动生成一些属性,其中一些属性就是关于验证 如图示例: 模型注解 通过模型注解后,MVC的验证,包括前台客 ...

  2. 编写生成彩色验证码的Servlet

    利用Ajax实现无刷新的彩色验证码时,也需要编写一个名称为PictureCheckCode.java的Servlet,该类继承HttpServlet,主要通过service()方法生成验证码. 下面将 ...

  3. 字符型图片验证码识别完整过程及Python实现

    字符型图片验证码识别完整过程及Python实现 1   摘要 验证码是目前互联网上非常常见也是非常重要的一个事物,充当着很多系统的 防火墙 功能,但是随时OCR技术的发展,验证码暴露出来的安全问题也越 ...

  4. 用C#生成随机中文汉字验证码的基本原理

    前几天去申请免费QQ号码,突然发现申请表单中的验证码内容换成了中文,这叫真叫我大跌眼镜感到好笑,Moper上的猫儿们都大骂腾讯采用中文验证码.^_^  我不得不佩服腾讯为了防止目前网络上横行的QQ号码 ...

  5. JSP实例:彩色验证码

    本例使用一个JavaBean,名为Image.java,包com.zempty.bean下; 三个JSP文件,分别为image.jsp.login.jsp.check.jsp.其中login.jsp是 ...

  6. Java中动态代理技术生成的类与原始类的区别 (转)

    用动态代理的时候,对它新生成的类长什么样子感到好奇.有幸通过一些资料消除了心里的疑惑. 平时工作使用的Spring框架里面有一个AOP(面向切面)的机制,只知道它是把类重新生成了一遍,在切面上加上了后 ...

  7. Java中动态代理技术生成的类与原始类的区别

    用动态代理的时候,对它新生成的类长什么样子感到好奇.有幸通过一些资料消除了心里的疑惑. 平时工作使用的Spring框架里面有一个AOP(面向切面)的机制,只知道它是把类重新生成了一遍,在切面上加上了后 ...

  8. C# GDI+技术

    C# GDI+技术 GDI+概述         GDI+是GDI(即Windows早期版本号中附带的Graphics Device Interface)的后继者.它是一种构成Windows XP操作 ...

  9. 字符型图片验证码,使用tensorflow实现卷积神经网络,进行验证码识别CNN

    本项目使用卷积神经网络识别字符型图片验证码,其基于 TensorFlow 框架.它封装了非常通用的校验.训练.验证.识别和调用 API,极大地减低了识别字符型验证码花费的时间和精力. 项目地址: ht ...

随机推荐

  1. c c++怎么判断一个字符串中是否含有汉字

    c c++怎么判断一个字符串中是否含有汉字 (2013-02-05 10:44:23) 转载▼     #include  #include  int main() { char sztext[] = ...

  2. java length属性 length()方法 size()方法

    length是属性,一般用来说明数组的长度 length()是方法,针对字符串String说的,用来求数组中某个元素的字符串长度 String str={"adfasf",&quo ...

  3. 测试nfs和cifs

    losetup /dev/loop1 file1.img losetup /dev/loop2 file2.img losetup /dev/loop3 file3.img mkfs -t ext4 ...

  4. iOS开发Swift篇—(九)属性

    iOS开发Swift篇—(九)属性 一.类的定义 Swift与Objective-C定义类的区别 Objective-C:一般需要2个文件,1个.h声明文件和1个.m实现文件 Swift:只需要1个. ...

  5. Winform TreeList递归绑定树节点

    /// <summary> /// 绑定树目录 /// </summary> /// <param name="parentId">父ID< ...

  6. TreeSet和Comparator 对TreeSet排序

    使用TreeSet和Comparator,编写TreeSetTestInner类,要求对TreeSet中的元素"HashSet"."ArrayList".&qu ...

  7. Android 源码下载

    一直想尝试android源码的编译,这两天正好海思代码的编译也需要ubuntu环境,于是安装了ubuntu 12.04,安装时选了语言为中文,因此下面很多状态及错误报告都是中文了,另外分配了4G sw ...

  8. MySQL数据库忘记root密码解决办法

    MySQL数据库忘记root密码解决办法 1.在运行输入services.msc打开服务窗体,找到MYSQL服务.右键停止将其关闭.如图:

  9. jQuery 实现菜单

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  10. C++指针比较的问题

    在C++里面,指针的比较是要保障type-safe的,也就是说,这两个指针必须是convertible的:从一个指针能够直接转换到另一个指针(有中间路径不算,不然都往void*转没完没了),顺序不限 ...