默之's profile个人随笔PhotosBlogListsMore ![]() | Help |
|
March 16 .NET学习,生成图片验证码(二) 上一篇,我已经实现了简单的图片验证码。但是该图片验证码看上去比较简单没有什么特效,不像其他网站上的验证码具有扭曲,和图片背景有噪音点的功能,这次我就准备实现这个功能。
一、图片背景噪音点的实现
实现思路:就是在内存图片上通过setPixel方法,设置指定像素点的颜色。
//字符串数组,存放颜色
private static string[] BrushName = new string[]{"OliveDrab","ForestGreen", "DarkCyan", "LightSlateGray", "RoyalBlue",
"SlateBlue", "DarkViolet","MediumVioletRed","IndianRed","Firebrick",
"Chocolate", "Peru","Goldenrod", "Teal", "DarkGreen",
"MediumBlue", "Black" }; /// <summary>
/// 绘制图片噪音点 /// </summary> /// <param name="image">图片对象</param> public void stainImage(Bitmap image) { Random rnd = new Random(); //随机选择颜色
int index = rnd.Next(BrushName.Length); //在图形上画20个点数字可以进行修改 for (int n = 0; n < 20; n++) { int x = rnd.Next(image.Width-2); int y = rnd.Next(image.Height-2); image.SetPixel(x, y, Color.FromName(BrushName[index])); } } 二、扭曲图片实现
实现思路:按列循环整张图片,获取每个像素点的颜色,并通过正弦曲线获取另一个像素点的位置,用原始像素点的颜色替换正弦像素点的颜色,就可以得到一张扭曲的图片。余弦以此类推。
/// <summary>
/// 正弦曲线Wave扭曲图片 /// </summary> /// <param name="srcBmp"></param> /// <param name="bXDir">true左右波动,false上下波动</param> /// <param name="nMultValue">波形的幅度倍数</param> /// <returns></returns> public System.Drawing.Bitmap twistImage(Bitmap srcBmp, bool bXDir, double dMultValue) { Random rnd = new Random(); double dPhase = rnd.Next(0, 6); System.Drawing.Bitmap destBmp = new Bitmap(srcBmp.Width, srcBmp.Height); // 将位图背景填充为白色
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 ? (Math.PI * 2 * (double)j) / dBaseAxisLen : (Math.PI * 2 * (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; } 总结:在图片处理时,我们大量使用了setpixel和getpixel方法,这仅仅适用于处理小图片,因为这2个方法处理十分缓慢,如果是大图片的话,推荐使用unsafe代码使用指针来进行操作。
LockBits();在内存中锁定
Scan0//获取首地址指针
UnlockBits();在内存中解锁
March 11 .NET学习,生成图片验证码(一)最近,在做一个登录界面,界面上想有一个生成随机验证码的功能,就自己实现了一个,主要是使用了GDI+。思路如下:
1、在内存中生成一张Bitmap图片;
2、生成随机数字;
3、Graphics.FromImage()方法获取DC(设备上下文);
4、Graphics.DrawString();
5、将图片写入内存流,将内存流通过http传输给网页;
代码如下:
一、生成图片的网页
/// <summary>
/// 生成随机字符串 /// </summary> /// <param name="codeLength">需要生成随机字符串的长度</param> /// <returns>生成的字符串</returns> private string GenerateCode(int codeLength) { //存放生成随机数据的字符数组共62个 char[] charArray = { '0','1','2','3','4','5','6','7','8','9', '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' }; int arrayLength = charArray.Length; string returnValue = "";
int flag = 0; Random rand = new Random(); //生成制定数字的字符串 for (int i = 0; i < codeLength; i++) { while (flag != -1) { int pos = rand.Next(0, arrayLength); flag = returnValue.IndexOf(charArray[pos]); if (flag == -1) { returnValue += charArray[pos]; flag = 0; break; } } } return returnValue; } /// <summary>
/// 生成验证码图片 /// </summary> /// <param name="ImageWidth">图片宽度</param> /// <param name="ImageHeight">图片高度</param> /// <param name="font">内容字体</param> /// <param name="brush">画刷</param> /// <param name="backgroundColor">图片背景色</param> /// <param name="codeLength">生成验证码的长度</param> /// <returns></returns> private MemoryStream GenerateMemoryImage(int ImageWidth, int ImageHeight, Font font, Brush brush, Color backgroundColor, int codeLength) { MemoryStream ms = new MemoryStream(); Bitmap image = new Bitmap(ImageWidth, ImageHeight); Graphics g = Graphics.FromImage(image); g.Clear(backgroundColor); string code = GenerateCode(codeLength); SizeF size = g.MeasureString(code, font); g.DrawString(code, font, brush, (ImageWidth - (int)size.Width) / 2, (ImageHeight - (int)size.Height) / 2); image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); return ms; } //网页调用生成图片方法,并将内存流转换为byte[]通过http传输
protected void Page_Load(object sender, EventArgs e)
{ Font font = new Font("Arial", 20f); MemoryStream ms = GenerateMemoryImage(150, 30, font, new SolidBrush(Color.Black), Color.WhiteSmoke, 4); Response.ClearContent(); Response.ContentType = "image/jpeg"; Response.BinaryWrite(ms.ToArray()); Response.End(); } 二、调用图片的网页
<img id="code" alt="" onclick="this.src='Default.aspx?'+Math.random();" src="Default.aspx" style="padding-left: 10px;
vertical-align: middle; cursor: pointer" /> 只要在需要使用图片的网页上调用该标记即可,之所以="this.src='Default.aspx?'+Math.random();" 要加上Math.random()是因为防止缓存。
生成图片时可以对图片写入的文字,对每个字符/汉字随机使用字体、字号、颜色等等。
下一讲,更深入说明如何对验证码进行图片的效果处理。
|
|
|