You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1758 lines
64 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
namespace BookingWeb.Helper
{
/// <summary>
/// 验证码生成类
/// </summary>
public class DrawCaptchaHelper
{
#region 定义和初始化配置字段
//用户存取验证码字符串
private string captchaStr = String.Empty;
/// <summary>
/// 获取系统生成的随机验证码
/// </summary>
public String CaptchaStr
{
get { return captchaStr; }
}
private Int32 captchaLength = 4;
/// <summary>
/// 获取和设置验证码字符串的长度
/// </summary>
public Int32 CaptchaLength
{
get { return captchaLength; }
set { captchaLength = value; }
}
Graphics dc = null;
private int bgWidth = 130;
/// <summary>
/// 验证码的宽度默认为130
/// </summary>
public Int32 Width
{
get { return bgWidth; }
set { bgWidth = value; }
}
private int bgHeight = 40;
/// <summary>
/// 验证码的高度默认为40
/// </summary>
public Int32 Height
{
get { return bgHeight; }
set { bgHeight = value; }
}
private int fontMinSize = 15;
/// <summary>
/// 验证码字体的最小值默认为15,建议不小于15像素
/// </summary>
public Int32 FontMinSize
{
get { return fontMinSize; }
set { fontMinSize = value; }
}
private Int32 fontMaxSize = 20;
/// <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(243, 255, 255);
/// <summary>
/// 验证码的背景色默认为Color.FromArgb(243, 251, 254)
/// </summary>
public Color BackgroundColor
{
get { return backColor; }
set { backColor = value; }
}
private Int32 bezierCount = 3;
/// <summary>
/// 贝塞尔曲线的条数,默认为3条
/// </summary>
public Int32 BezierCount
{
get { return bezierCount; }
set { bezierCount = value; }
}
private Int32 lineCount = 3;
/// <summary>
/// 直线条数默认为3条
/// </summary>
public Int32 LineCount
{
get { return lineCount; }
set { lineCount = value; }
}
Random random;
//定义验证码字符及出现频次 ,避免出现 0 o j i l 1 x;
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";
/// <summary>
/// 随机字符串列表,请使用英文状态下的逗号分隔。
/// </summary>
public String CharCollection
{
get { return charCollection; }
set { charCollection = value; }
}
private Int32 intCount = 4;
/// <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; }
}
/// <summary>
/// 随机背景字符串的个数
/// </summary>
public Int32 RandomStringCount { get; set; }
private Int32 randomStringFontSize = 10;
/// <summary>
/// 随机背景字符串的大小
/// </summary>
public Int32 RandomStringFontSize
{
get { return randomStringFontSize; }
set { randomStringFontSize = value; }
}
/// <summary>
/// 边框样式
/// </summary>
public enum BorderStyle
{
/// <summary>
/// 无边框
/// </summary>
None,
/// <summary>
/// 矩形边框
/// </summary>
Rectangle,
/// <summary>
/// 圆角边框
/// </summary>
RoundRectangle
}
/// <summary>
/// 设置或获取边框样式
/// </summary>
public BorderStyle Border { get; set; }
private Int32 rotationAngle = 40;
/// <summary>
/// 验证码字符串随机转动的角度的最大值
/// </summary>
public Int32 RotationAngle
{
get { return rotationAngle; }
set { rotationAngle = value; }
}
private Point[] strPoint = null;
private Double gaussianDeviation = 0;
/// <summary>
/// 对验证码图片进行高斯模糊的阀值如果设置为0则不对图片进行高斯模糊该设置可能会对图片处理的性能有较大影响
/// </summary>
public Double GaussianDeviation
{
get { return gaussianDeviation; }
set { gaussianDeviation = value; }
}
private Int32 brightnessValue = 0;
/// <summary>
/// 对图片进行暗度和亮度的调整如果该值为0则不调整。该设置会对图片处理性能有较大影响
/// </summary>
public Int32 BrightnessValue
{
get { return brightnessValue; }
set { brightnessValue = value; }
}
#endregion
#region wq 新增 边框补(默认1像素)
int padding = 2;
public int Padding
{
get { return padding; }
set { padding = value; }
}
#endregion
/// <summary>
/// 构造函数,用于初始化常用变量
/// </summary>
public DrawCaptchaHelper()
{
random = new Random(Guid.NewGuid().GetHashCode());
strPoint = new Point[captchaLength + 1];
if (gaussianDeviation < 0) gaussianDeviation = 0;
}
/// <summary>
/// 生成验证码
/// </summary>
/// <param name="target">用于存储图片的一般字节序列</param>
public MemoryStream CreateImage(MemoryStream target)
{
//新增 wq ,否则后面报错
if (strPoint.Length != captchaLength)
{
strPoint = new Point[captchaLength + 1];//wq 新增原因是构造函数默认初始化5个元素假如new后又改了validationCodeCount的数值则该数字需要重新初始化
}
//新增 wq ,否则图片的画布太小
if (fontMaxSize >= (bgHeight / 5) * 4)
{
//throw new ArgumentException("字体最大值参数FontMaxSize与验证码高度相近这会导致描绘验证码字符串时出错请重新设置参数");
AdjustBitmapSize();
}
Bitmap bit = new Bitmap(bgWidth + 1, bgHeight + 1);
//写字符串
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(), 0, 0);
//绘制验证码
Bitmap validatecodeImg = DrawRandomString();
//对随机码图像上的文字进行波形扭曲扭曲文字方式1
validatecodeImg = TwistImage(validatecodeImg, true, 3, 4);
dc.DrawImageUnscaled(validatecodeImg, 0, 0);
//水波纹效果 文字进行波形扭曲 扭曲文字方式2
//bit = AdjustRippleEffect(bit, 5);
//对图片进行高斯模糊
if (gaussianDeviation > 0)
{
GaussianHelper gau = new GaussianHelper();
bit = gau.FilterProcessImage(gaussianDeviation, bit);
}
//进行暗度和亮度处理
if (brightnessValue != 0)
{
//对图片进行调暗处理
bit = AdjustBrightness(bit, brightnessValue);
}
bit.Save(target, ImageFormat.Gif);
//brush.Dispose();
bit.Dispose();
dc.Dispose();
return target;
}
#region 画验证码背景,例如,增加早点,添加曲线和直线等
/// <summary>
/// 画验证码背景,例如,增加早点,添加曲线和直线等
/// </summary>
/// <returns></returns>
private Bitmap DrawBackground()
{
Bitmap bit = new Bitmap(bgWidth + 1, bgHeight + 1);
Graphics g = Graphics.FromImage(bit);
g.SmoothingMode = SmoothingMode.HighQuality;
g.Clear(Color.White);
Rectangle rectangle = new Rectangle(0, 0, bgWidth, bgHeight);
Brush brush = new SolidBrush(backColor);
g.FillRectangle(brush, rectangle);
//画噪点
if (isPixel)
{
g.DrawImageUnscaled(DrawRandomPixel(30), 0, 0);
}
//画干扰字符
g.DrawImageUnscaled(DrawRandBgString(), 0, 0);
//画曲线
g.DrawImageUnscaled(DrawRandomBezier(bezierCount), 0, 0);
//画直线
g.DrawImageUnscaled(DrawRandomLine(lineCount), 0, 0);
//画字符连接线
//dc.DrawImageUnscaled(DrawStringline(), 0, 0);
if (Border == BorderStyle.Rectangle)
{
//绘制边框
g.DrawRectangle(new Pen(Color.FromArgb(90, 87, 46)), 0, 0, bgWidth, bgHeight);
}
else if (Border == BorderStyle.RoundRectangle)
{
//画圆角
DrawRoundRectangle(g, rectangle, Color.FromArgb(90, 87, 46), 1, 3);
}
else
{
//没有边框
}
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 = 2;
float temp = 0.0f;
//把画布下移100。为什么要这样做只要你把这一句给注释掉运行一下代码
//你就会明白是为什么?
graphics.TranslateTransform(0, 100);
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
for (int i = 0; i < size; i++)
{
//改变tWidth实现正弦曲线宽度的变化。
//改tHeight实现正弦曲线高度的变化。
x[i] = Math.Sin(2 * Math.PI * i / tWidth) * tHeight;
graphics.DrawLine(pen, i * val, temp, i * val + val / 2, (float)x[i]);
temp = (float)x[i];
}
graphics.RotateTransform(60, 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), 0, 0, destBmp.Width, destBmp.Height);
graph.Dispose();
double dBaseAxisLen = bXDir ? (double)destBmp.Height : (double)destBmp.Width;
for (int i = 0; i < destBmp.Width; i++)
{
for (int j = 0; j < destBmp.Height; j++)
{
double dx = 0;
dx = bXDir ? (PI2 * (double)j) / dBaseAxisLen : (PI2 * (double)i) / dBaseAxisLen;
dx += dPhase;
double dy = Math.Sin(dx);
// 取得当前点的颜色
int nOldX = 0, nOldY = 0;
nOldX = bXDir ? i + (int)(dy * dMultValue) : i;
nOldY = bXDir ? j : j + (int)(dy * dMultValue);
System.Drawing.Color color = srcBmp.GetPixel(i, j);
if (nOldX >= 0 && nOldX < destBmp.Width
&& nOldY >= 0 && 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, 1, 1);
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, 0, 0);
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 = 0; i < (lineNum - lineRandNum); i++)
{
Pen p = new Pen(GetRandomDeepColor(), 3f); //wq,增加贝塞尔曲线的线宽参数
Point[] point = {
new Point(random.Next(1, (b.Width / 10)), random.Next(1, (b.Height))),
new Point(random.Next((b.Width / 10) * 2, (b.Width / 10) * 4), random.Next(1, (b.Height))),
new Point(random.Next((b.Width / 10) * 4, (b.Width / 10) * 6), random.Next(1, (b.Height))),
new Point(random.Next((b.Width / 10) * 8, b.Width), random.Next(1, (b.Height)))
};
gPath1.AddBeziers(point);
g.DrawPath(p, gPath1);
p.Dispose();
}
for (int i = 0; i < lineRandNum; i++)
{
Pen p = new Pen(GetRandomDeepColor());
Point[] point = {
new Point(random.Next(1, b.Width), random.Next(1, b.Height)),
new Point(random.Next((b.Width / 10) * 2, b.Width), random.Next(1, b.Height)),
new Point(random.Next((b.Width / 10) * 4, b.Width), random.Next(1, b.Height)),
new Point(random.Next(1, b.Width), random.Next(1, 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 < 0) 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 = 0; i < lineNum; i++)
{
Pen p = new Pen(GetRandomDeepColor());
Point pt1 = new Point(random.Next(1, (b.Width / 5) * 2), random.Next(b.Height));
Point pt2 = new Point(random.Next((b.Width / 5) * 3, 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 = 0; i < (bgHeight * bgWidth) / pixNum; i++)
{
int x = random.Next(b.Width);
int y = random.Next(b.Height);
b.SetPixel(x, y, GetRandomDeepColor());
//下移坐标重新画点
if ((x + 1) < b.Width && (y + 1) < b.Height)
{
//画图片的前景噪音点
graph.DrawRectangle(new Pen(Color.Silver), random.Next(b.Width), random.Next(b.Height), 1, 1);
}
}
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[captchaLength];
for (int i = 0; i < captchaLength; 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(), 1), strPoint);
return b;
}
#endregion
#region 写入验证码的字符串
/// <summary>
/// 写入验证码的字符串
/// </summary>
private Bitmap DrawRandomString()
{
if (fontMaxSize >= (bgHeight / 5) * 4)
{
//throw new ArgumentException("字体最大值参数FontMaxSize与验证码高度相近这会导致描绘验证码字符串时出错请重新设置参数");
AdjustBitmapSize();
}
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(captchaLength).ToCharArray();//拆散字符串成单字符数组
captchaStr = new string(chars); //这个类的外部,也可以通过这个参数,获取到本次的验证码字符串值。
//设置字体显示格式
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 = 9;
for (int i = 0; i < captchaLength; i++)
{
int findex = random.Next(captchaLength + 1);// random.Next(5);
//定义字体
Font textFont = new Font(f, random.Next(fontMinSize, fontMaxSize), FontStyle.Bold);
//定义画刷,用于写字符串
//Brush brush = new SolidBrush(GetRandomDeepColor());
Int32 textFontSize = Convert.ToInt32(textFont.Size);
fontSize = textFontSize;
var t = (bgWidth / charNum) / 2;
Point point = new Point(random.Next((bgWidth / charNum) * (i) + t - 2, (bgWidth / charNum) * (i + 1) - t + 2), random.Next(bgHeight / 5 + textFontSize / 2, bgHeight - textFontSize / 2));
//如果当前字符X坐标小于字体的二分之一大小
if (point.X < textFontSize / 2)
{
point.X = point.X + textFontSize / 2;
}
//防止文字叠加
if (i > 0 && (point.X - sPoint.X < (textFontSize / 2 + textFontSize / 2)))
{
point.X = point.X + textFontSize;
}
//如果当前字符X坐标大于图片宽度就减去字体的宽度
if (point.X > (bgWidth - textFontSize / 2))
{
point.X = bgWidth - textFontSize / 2;
}
sPoint = point;
float angle = random.Next(-rotationAngle, rotationAngle);//转动的度数
g.TranslateTransform(point.X, point.Y);//移动光标到指定位置
g.RotateTransform(angle);
//设置渐变画刷
Rectangle myretang = new Rectangle(0, 1, Convert.ToInt32(textFont.Size), Convert.ToInt32(textFont.Size));
Color c = GetRandomDeepColor();
LinearGradientBrush mybrush2 = new LinearGradientBrush(myretang, c, GetLightColor(c, 120), random.Next(180));
g.DrawString(chars[i].ToString(), textFont, mybrush2, 1, 1, format);
g.RotateTransform(-angle);//转回去
g.TranslateTransform(-point.X, -point.Y);//移动光标到指定位置,每个字符紧凑显示,避免被软件识别
strPoint[i] = point;
textFont.Dispose();
mybrush2.Dispose();
}
return b;
}
#endregion
#region 新增的矫正验证码的宽高
private void AdjustBitmapSize()
{
int fSize = fontMaxSize;
int fWidth = fSize + Padding;
int imageWidth = (int)(captchaLength * fWidth) + 4 + Padding * 2;
int imageHeight = fSize * 2 + Padding;
bgWidth = imageWidth;
bgHeight = imageHeight;
}
#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 = 60; //随机转动角度
for (int i = 0; i < RandomStringCount; i++)
{
Brush brush = new System.Drawing.SolidBrush(GetRandomLightColor());
Point pot = new Point(random.Next(randomStringFontSize / 2, bgWidth - randomStringFontSize / 2),
random.Next(randomStringFontSize / 2, bgHeight - randomStringFontSize / 2));
//随机转动的度数
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 = 0; i < textLength; i++)
{
randomString += randomArray[random.Next(0, arrayLength)];
}
//Session["CheckCode"] = randomString;
return randomString; //长度是textLength +1
}
#endregion
#region 内部方法:绘制验证码背景
private void DrawBackground(HatchStyle hatchStyle)
{
//设置填充背景时用的笔刷
HatchBrush hBrush = new HatchBrush(hatchStyle, backColor);
//填充背景图片
dc.FillRectangle(hBrush, 0, 0, this.bgWidth, this.bgHeight);
}
#endregion
#region 根据指定长度,返回随机验证码
/// <summary>
/// 根据指定长度,返回随机验证码
/// </summary>
/// <param >制定长度</param>
/// <returns>随即验证码</returns>
public string Next(int length)
{
this.captchaStr = GetRandomCode(length);
return this.captchaStr;
}
#endregion
#region 内部方法:返回指定长度的随机验证码字符串
/// <summary>
/// 根据指定大小返回随机验证码
/// </summary>
/// <param >字符串长度</param>
/// <returns>随机字符串</returns>
private string GetRandomCode(int length)
{
StringBuilder sb = new StringBuilder(6);
for (int i = 0; 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 = 48;
Random ram = new Random();
int i = ram.Next(2);
switch (i)
{
case 0:
result = ram.Next(48, 58);
break;
case 1:
result = ram.Next(65, 91);
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 = 160;
int greenLow = 100;
int blueLow = 160;
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 = 180; //色彩的下限
int high = 255; //色彩的上限
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 = 10; //色彩的下限
int high = 255; //色彩的上限
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 < 255 && nRed + value > 0)
{
nRed = c.R + 40;
}
if (nGreen + value < 255 && nGreen + value > 0)
{
nGreen = c.G + 40;
}
if (nBlue + value < 255 && nBlue + value > 0)
{
nBlue = c.B + 40;
}
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 == 0)
throw new Exception("图片数不能够为0");
//创建要显示的图片对象,根据参数的个数设置宽度
Bitmap backgroudImg = new Bitmap(i * 12, 16);
Graphics g = Graphics.FromImage(backgroudImg);
//清除画布,背景设置为白色
g.Clear(System.Drawing.Color.White);
for (int j = 0; j < i; j++)
{
//g.DrawImage(maps[j], j * 11, 0, maps[j].Width, maps[j].Height);
g.DrawImageUnscaled(maps[j], 0, 0);
}
g.Dispose();
return backgroudImg;
}
#endregion
#region 生成不重复的随机数,该函数会消耗大量系统资源
/// <summary>
/// 生成不重复的随机数,该函数会消耗大量系统资源
/// </summary>
/// <returns></returns>
private static int GetRandomSeed()
{
byte[] bytes = new byte[4];
System.Security.Cryptography.RNGCryptoServiceProvider rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
rng.GetBytes(bytes);
return BitConverter.ToInt32(bytes, 0);
}
#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(0, 0, newW, newH), new Rectangle(0, 0, 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 = 2 * 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(0, 0, w, h), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
BitmapData dstData = bmpRtn.LockBits(new Rectangle(0, 0, 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 = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
//取周围9点的值
if (x == 0 || x == w - 1 || y == 0 || y == h - 1)
{
//不做
pOut[0] = pIn[0];
pOut[1] = pIn[1];
pOut[2] = pIn[2];
}
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 - 3;
r1 = p[2];
g1 = p[1];
b1 = p[0];
//正上
p = pIn - stride;
r2 = p[2];
g2 = p[1];
b2 = p[0];
//右上
p = pIn - stride + 3;
r3 = p[2];
g3 = p[1];
b3 = p[0];
//左侧
p = pIn - 3;
r4 = p[2];
g4 = p[1];
b4 = p[0];
//右侧
p = pIn + 3;
r5 = p[2];
g5 = p[1];
b5 = p[0];
//右下
p = pIn + stride - 3;
r6 = p[2];
g6 = p[1];
b6 = p[0];
//正下
p = pIn + stride;
r7 = p[2];
g7 = p[1];
b7 = p[0];
//右下
p = pIn + stride + 3;
r8 = p[2];
g8 = p[1];
b8 = p[0];
//自己
p = pIn;
r9 = p[2];
g9 = p[1];
b9 = p[0];
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 /= 9;
vG /= 9;
vB /= 9;
pOut[0] = (byte)vB;
pOut[1] = (byte)vG;
pOut[2] = (byte)vR;
}
pIn += 3;
pOut += 3;
}// end of x
pIn += srcData.Stride - w * 3;
pOut += srcData.Stride - w * 3;
} // 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 = 0; y < bitmap.Height; y++)
{
for (int x = 0; x < bitmap.Width; x++)
{
// 取得每一個 pixel
var pixel = bitmap.GetPixel(x, y);
var pR = pixel.R + threshold;
pR = Math.Max(pR, 0);
pR = Math.Min(255, pR);
// 將改過的 RGB 寫回
// 只寫入紅色的值 , G B 都放零
System.Drawing.Color newColor = System.Drawing.Color.FromArgb(pixel.A, pR, 0, 0);
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 = 0; y < bitmap.Height; y++)
{
for (int x = 0; x < bitmap.Width; x++)
{
// 取得每一個 pixel
var pixel = bitmap.GetPixel(x, y);
//判斷是否超過255 如果超過就是255
var pG = pixel.G + threshold;
//如果小於0就為0
if (pG > 255) pG = 255;
if (pG < 0) pG = 0;
// 將改過的 RGB 寫回
// 只寫入綠色的值 , R B 都放零
System.Drawing.Color newColor = System.Drawing.Color.FromArgb(pixel.A, 0, pG, 0);
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 = 0; y < bitmap.Height; y++)
{
for (int x = 0; x < bitmap.Width; x++)
{
// 取得每一個 pixel
var pixel = bitmap.GetPixel(x, y);
//判斷是否超過255 如果超過就是255
var pB = pixel.B + threshold;
//如果小於0就為0
if (pB > 255) pB = 255;
if (pB < 0) pB = 0;
// 將改過的 RGB 寫回
// 只寫入藍色的值 , R G 都放零
System.Drawing.Color newColor = System.Drawing.Color.FromArgb(pixel.A, 0, 0, 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 = 0; y < bitmap.Height; y++)
{
for (int x = 0; x < bitmap.Width; x++)
{
// 取得每一個 pixel
var pixel = bitmap.GetPixel(x, y);
//判斷是否超過255 如果超過就是255
var pG = pixel.G + thresholdGreen;
//如果小於0就為0
if (pG > 255) pG = 255;
if (pG < 0) pG = 0;
//判斷是否超過255 如果超過就是255
var pR = pixel.R + thresholdRed;
//如果小於0就為0
if (pR > 255) pR = 255;
if (pR < 0) pR = 0;
//判斷是否超過255 如果超過就是255
var pB = pixel.B + thresholdBlue;
//如果小於0就為0
if (pB > 255) pB = 255;
if (pB < 0) pB = 0;
// 將改過的 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, 0, 0},
new float[] {.59f, .59f, .59f, 0, 0},
new float[] {.11f, .11f, .11f, 0, 0},
new float[] {0, 0, 0, 1, 0},
new float[] {0, 0, 0, 0, 1}
});
//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(0, 0, original.Width, original.Height),
0, 0, 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 = 0; y < bitmap.Height; y++)
{
for (int x = 0; x < bitmap.Width; x++)
{
// 取得每一個 pixel
var pixel = bitmap.GetPixel(x, y);
// 判斷 如果處理過後 255 就設定為 255 如果小於則設定為 0
var pR = ((pixel.R + valBrightness > 255) ? 255 : pixel.R + valBrightness) < 0 ? 0 : ((pixel.R + valBrightness > 255) ? 255 : pixel.R + valBrightness);
var pG = ((pixel.G + valBrightness > 255) ? 255 : pixel.G + valBrightness) < 0 ? 0 : ((pixel.G + valBrightness > 255) ? 255 : pixel.G + valBrightness);
var pB = ((pixel.B + valBrightness > 255) ? 255 : pixel.B + valBrightness) < 0 ? 0 : ((pixel.B + valBrightness > 255) ? 255 : 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(0, 0, src.Width, src.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
unsafe
{
// 抓住第一个 Pixel 第一个数值
byte* p = (byte*)(void*)bitmapData.Scan0;
// 跨步值 - 宽度 *3 可以算出畸零地 之后跳到下一行
int nOffset = bitmapData.Stride - src.Width * 3;
for (int y = 0; y < src.Height; ++y)
{
for (int x = 0; x < src.Width; ++x)
{
// 为了理解方便 所以特地在命名
int r, g, b;
// 先取得下一个 Pixel
var q = p + 3;
r = Math.Abs(p[2] - q[2] + 128);
r = r < 0 ? 0 : r;
r = r > 255 ? 255 : r;
p[2] = (byte)r;
g = Math.Abs(p[1] - q[1] + 128);
g = g < 0 ? 0 : g;
g = g > 255 ? 255 : g;
p[1] = (byte)g;
b = Math.Abs(p[0] - q[0] + 128);
b = b < 0 ? 0 : b;
b = b > 255 ? 255 : b;
p[0] = (byte)b;
// 跳去下一个 Pixel
p += 3;
}
// 跨越畸零地
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 / 2;
mid.Y = nHeight / 2;
double newX, newY;
double xo, yo;
//先取样将水波纹座标跟RGB取出
for (int x = 0; x < nWidth; ++x)
for (int y = 0; 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 > 0 && 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 = 0;
}
if (newY > 0 && 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 = 0;
}
}
//进行合成
Bitmap bSrc = (Bitmap)src.Clone();
// 依照 Format24bppRgb 每三个表示一 Pixel 0: 蓝 1: 绿 2: 红
BitmapData bitmapData = src.LockBits(new Rectangle(0, 0, src.Width, src.Height), ImageLockMode.ReadWrite,
PixelFormat.Format24bppRgb);
BitmapData bmSrc = bSrc.LockBits(new Rectangle(0, 0, 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 * 3;
int xOffset, yOffset;
for (int y = 0; y < nHeight; ++y)
{
for (int x = 0; x < nWidth; ++x)
{
xOffset = pt[x, y].X;
yOffset = pt[x, y].Y;
if (yOffset >= 0 && yOffset < nHeight && xOffset >= 0 && xOffset < nWidth)
{
p[0] = pSrc[(yOffset * scanline) + (xOffset * 3)];
p[1] = pSrc[(yOffset * scanline) + (xOffset * 3) + 1];
p[2] = pSrc[(yOffset * scanline) + (xOffset * 3) + 2];
}
p += 3;
}
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), 5);
g = Math.Min(Math.Max(0.2, g), 5);
b = Math.Min(Math.Max(0.2, b), 5);
// 依照 Format24bppRgb 每三个表示一 Pixel 0: 蓝 1: 绿 2: 红
BitmapData bitmapData = src.LockBits(new Rectangle(0, 0, src.Width, src.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
unsafe
{
// 抓住第一个 Pixel 第一个数值
byte* p = (byte*)(void*)bitmapData.Scan0;
// 跨步值 - 宽度 *3 可以算出畸零地 之后跳到下一行
int nOffset = bitmapData.Stride - src.Width * 3;
for (int y = 0; y < src.Height; y++)
{
for (int x = 0; x < src.Width; x++)
{
p[2] = (byte)Math.Min(255, (int)((255.0 * Math.Pow(p[2] / 255.0, 1.0 / r)) + 0.5));
p[1] = (byte)Math.Min(255, (int)((255.0 * Math.Pow(p[1] / 255.0, 1.0 / g)) + 0.5));
p[0] = (byte)Math.Min(255, (int)((255.0 * Math.Pow(p[0] / 255.0, 1.0 / b)) + 0.5));
// 跳去下一个 Pixel
p += 3;
}
// 跨越畸零地
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(0, 0, src.Width, src.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
// 判断是否在 -100~100
effectThreshold = effectThreshold < -100 ? -100 : effectThreshold;
effectThreshold = effectThreshold > 100 ? 100 : 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 * 3;
for (int y = 0; y < src.Height; y++)
{
for (int x = 0; x < src.Width; x++)
{
double buffer = 0;
// 公式 (Red/255)-0.5= 偏离中间值程度
// ((偏离中间值程度 * 影响范围)+0.4 ) * 255
buffer = ((((p[2] / 255.0) - 0.5) * effectThreshold) + 0.5) * 255.0;
buffer = buffer > 255 ? 255 : buffer;
buffer = buffer < 0 ? 0 : buffer;
p[2] = (byte)buffer;
buffer = ((((p[1] / 255.0) - 0.5) * effectThreshold) + 0.5) * 255.0;
buffer = buffer > 255 ? 255 : buffer;
buffer = buffer < 0 ? 0 : buffer;
p[1] = (byte)buffer;
buffer = ((((p[0] / 255.0) - 0.5) * effectThreshold) + 0.5) * 255.0;
buffer = buffer > 255 ? 255 : buffer;
buffer = buffer < 0 ? 0 : buffer;
p[0] = (byte)buffer;
// 跳去下一个 Pixel
p += 3;
}
// 跨越畸零地
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 = 1; x < Width - 1; x++)
{
for (int y = 1; y < Height - 1; y++)
{
Random MyRandom = new Random(Guid.NewGuid().GetHashCode());
int k = MyRandom.Next(123456);
//像素块大小
int dx = x + k % 19;
int dy = y + k % 19;
if (dx >= Width)
dx = Width - 1;
if (dy >= Height)
dy = Height - 1;
pixel = oldBitmap.GetPixel(dx, dy);
newBitmap.SetPixel(x, y, pixel);
}
}
return newBitmap;
}
#endregion
public MemoryStream test(MemoryStream target)
{
Graphics dc = null;
Bitmap bit = new Bitmap(200, 200);
//写字符串
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(), 0, 0);
bit.Save(target, ImageFormat.Gif);
//brush.Dispose();
bit.Dispose();
dc.Dispose();
return target;
}
}
}