现在的位置: 首页 > 综合 > 正文

.NET学习,生成图片验证码

2018年05月04日 ⁄ 综合 ⁄ 共 5916字 ⁄ 字号 评论关闭

 http://blog.csdn.net/humozhi/archive/2009/03/29/4034568.aspx

  .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()是因为防止缓存。
 
生成图片时可以对图片写入的文字,对每个字符/汉字随机使用字体、字号、颜色等等。
 
下一讲,更深入说明如何对验证码进行图片的效果处理。

http://blog.csdn.net/humozhi/archive/2009/03/29/4034573.aspx

上一篇,我已经实现了简单的图片验证码。但是该图片验证码看上去比较简单没有什么特效,不像其他网站上的验证码具有扭曲,和图片背景有噪音点的功能,这次我就准备实现这个功能。

    一、图片背景噪音点的实现
    实现思路:就是在内存图片上通过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();在内存中解锁

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/humozhi/archive/2009/03/29/4034573.aspx

抱歉!评论已关闭.