扭曲的验证码

来源:互联网 发布:定位蜂窝移动网络搜索 编辑:程序博客网 时间:2024/05/01 10:02

http://www.cnblogs.com/wcfl/p/3795478.html

  当初学习一般处理程序的时候,写过一个验证码,不过是后台程序向前台输出了一张图片,图片上是几个随机写上去的字符。虽然也惊讶于许多网站上那些“扭曲”的验证码,却琢磨不透人家是怎么实现的,后来逐渐把这事遗忘了。今天在网上碰巧看到有人用php实现的案例,忍不住想着用C#来一把。当然,在此先感谢网上那位仁兄提供的思路,在下只是比着葫芦画瓢。

  这里所说的“扭曲”的验证码,只是字符扭曲。由于时间仓促,我也没给顾得上添加图片噪点。先说思路:创建图片A做为背景,其次创建图片B,在图片B画上验证码文字,然后将图片B拆分成若干部分画到图片A上。打个比方,好比是把一张画纵向平均裁成若干份,然后再上下交错着粘到另一张白纸上。如果随意的上下交错排列,看到的八成就是一片乱七八糟的玩意儿,这里不妨按照一个曲线变化的规律来排列,我选择的是正弦曲线。

  步骤:

  1、新建一般处理程序TestCodeHandler.ashx,先定义一个随机生成验证码文字的方法,如下:

复制代码
        /// <summary>        /// 随机生成验证码        /// </summary>        /// <returns></returns>        public string GetTestCode()        {            Random r = new Random();            StringBuilder sb = new StringBuilder();            for (int i = 0; i < 5; i++)            {                int n = r.Next(65, 91);                sb.Append((char)n);            }            return sb.ToString();        }    
复制代码

  2、在ProcessRequest方法中,确定输出文件的类型。  

1
context.Response.ContentType = "image/jpeg";

  3、引用命名空间System.Drawing和using System.Drawing.Imaging生成验证码图片。

 

复制代码
            using (Image img = new Bitmap(85, 40))//背景图片            {                using (Image fontImg = new Bitmap(84, 38))//预先画验证码的临时图片                {                    //先将验证码画到临时图片fontImg上                    using (Graphics fontGraphic = Graphics.FromImage(fontImg))                    {                        fontGraphic.Clear(Color.White);//将画布涂白                        //画验证吗                        fontGraphic.DrawString(GetTestCode(), new Font("宋体", 18, FontStyle.Italic | FontStyle.Bold), Brushes.Black, new PointF(4, 4));                    }                    //将临时验证码图片fontImg分成若干份画到背景图片img上                    using (Graphics g = Graphics.FromImage(img))                    {                        g.Clear(Color.White);//将画布涂白                                               int sum = 60;//分成60份                        int niu = 6;//上下最多偏移10像素                        float x = 0, y = 1;//从临时图片fontImg选取矩形区域的起始坐标                        //从临时图片fontImg选取矩形区域的宽度,由于有背景图片映衬,这里只确定宽度                                                float width = ((float)fontImg.Width) / sum;                        //依次把临时图片fontImg各部分画到背景图片上                                               for (int i = 0; i < sum; i++)                        {                                                        //获取当前部分的正弦值,计算上下偏移量。但这样会使验证码的扭曲单一                            float rate = (float)Math.Sin(360 * 1.0 / sum * i / 180 * Math.PI) * niu;                            //如果使用随机数,会有不同的变化                            //Random r = new Random(DateTime.Now.Millisecond);                            //float rate = (float)Math.Sin(360 * 1.0 / sum * i / 180 * Math.PI) * r.Next(1,niu);                            //把临时图片fontImg当前部分画到背景图片上                            g.DrawImage(fontImg, new Rectangle(x==0?1:(int)x, (int)y, img.Width, img.Height - 2), x, y * rate, width, fontImg.Height, GraphicsUnit.Pixel);                            //依次改变横坐标的下一个位置                            x += width;                                                                               }                        //为背景图片画边框                        g.DrawRectangle(new Pen(Brushes.Black), new Rectangle(0, 0, img.Width - 1, img.Height - 1));                    }                }                //将背景图片保存到输出流                img.Save(context.Response.OutputStream, ImageFormat.Jpeg);
复制代码

 

  4、测试。新建html页面,添加<img>标签,令src属性指向TestCodeHandler.ashx,并为它的onclick事件注册方法,实现点击切换图片的效果。如下:

 

复制代码
<!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head>    <title></title>    <script type="text/javascript">        function change() {            document.getElementById("img").src = "TestCodeHandler.ashx?id=" + new Date().getTime();        }    </script></head><body>    <img id="img" src="TestCodeHandler.ashx"  onclick="change()"/></body></html>
复制代码

 

  5、效果如下: 

     

  恕在下能力一般,水平有限,也只能实现上面的效果。若有高人看到此文,发现有不到之处,还望不吝赐教。

0 0