每个字符旋转随机角度的图象验证码 V2.0

根据jeff377 的话,竹子将这验证码改进了一下,请大家讨论看看。
-------jeff377--------------------------------------------
我研究所的论文就是在做类神经网络处理文字辨识,以你的例子而言,旋转随意角度对辨识来说并不会有太大影响,只要抓字的重心,360度旋转抓取特微值,还是可以辨识的出来。
通常文字辨识的有一个重要的动作,就是要把个别文字分割,你只要把文字弄的难分割就有不错的安全性。
---------------------------------------------------

代码比较粗糙,而且比较菜,其中遇到一个问题,未对 Graphics 填充底色,那么文字的 ClearType 效果没有了,文字毛边比较明显,不知道为什么,谁能告诉竹子?

代码相对粗糙,没有考虑更多的情况,在测试过程中,以20px 字体呈现,效果感觉还不错,只是 ClearType 效果没有了。

帖几张看看

------------

------------

------------

------------
有一些随机的不好,象下面这张


相关链接:
查看 V1.0

.NET 2.0 代码如下:
using System;
using System.Drawing;
using System.Web;


namespace Oran.Image
{
    
/// <summary>
    
/// 旋转的可视验证码图象
    
/// </summary>
    public class RotatedVlidationCode
    {
        
public enum RandomStringMode
        {
            
/// <summary>
            
/// 小写字母
            
/// </summary>
            LowerLetter,
            
/// <summary>
            
/// 大写字母
            
/// </summary>
            UpperLetter,
            
/// <summary>
            
/// 混合大小写字母
            
/// </summary>
            Letter,
            
/// <summary>
            
/// 数字
            
/// </summary>
            Digital,
            
/// <summary>
            
/// 混合数字与大小字母
            
/// </summary>
            Mix
        }

        
public static string GenerateRandomString(int length, RandomStringMode mode)
        {
            
string rndStr = string.Empty;
            
if (length == 0)
                
return rndStr;

            
//以数组方式候选字符,可以更方便的剔除不要的字符,如数字 0 与字母 o
            char[] digitals = new char[10] { '0''1''2''3''4''5''6''7''8''9' };
            
char[] lowerLetters = new char[26] {
                
'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' };
            
char[] upperLetters = new char[26] {
                
'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' };
            
char[] letters = new char[52]{
                
'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' };
            
char[] mix = new char[62]{
                
'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[] range = new int[2] { 00 };
            Random random 
= new Random();

            
switch (mode)
            {
                
case RandomStringMode.Digital:
                    
for (int i = 0; i < length; ++i)
                        rndStr 
+= digitals[random.Next(0, digitals.Length)];
                    
break;

                
case RandomStringMode.LowerLetter:
                    
for (int i = 0; i < length; ++i)
                        rndStr 
+= lowerLetters[random.Next(0, lowerLetters.Length)];
                    
break;

                
case RandomStringMode.UpperLetter:
                    
for (int i = 0; i < length; ++i)
                        rndStr 
+= upperLetters[random.Next(0, upperLetters.Length)];
                    
break;

                
case RandomStringMode.Letter:
                    
for (int i = 0; i < length; ++i)
                        rndStr 
+= letters[random.Next(0, letters.Length)];
                    
break;

                
default:
                    
for (int i = 0; i < length; ++i)
                        rndStr 
+= mix[random.Next(0, mix.Length)];
                    
break;
            }

            
return rndStr;
        }

        
/// <summary>
        
/// 显示验证码
        
/// </summary>
        
/// <param name="seed">随机数辅助种子</param>
        
/// <param name="strLen">验证码字符长度</param>
        
/// <param name="fontSize">字体大小</param>
        
/// <param name="mode">随机字符模式</param>
        
/// <param name="clrFont">字体颜色</param>
        
/// <param name="clrBg">背景颜色</param>
        public static void ShowValidationCode(ref int seed, int strLen, int fontSize, RandomStringMode mode, Color clrFont, Color clrBg)
        {
            
int tmpSeed;
            
unchecked
            {
                tmpSeed 
= (int)(seed * DateTime.Now.Ticks);
                
++seed;
            }
            Random rnd 
= new Random(tmpSeed);

            
string text = GenerateRandomString(strLen, mode);
            
int height = fontSize * 2;
            
// 因为字体旋转后每个字体所占宽度会所有加大,所以要加一点补偿宽度
            int width = fontSize * text.Length + fontSize / (text.Length - 2);
            Bitmap bmp 
= new Bitmap(width, height);

            Graphics graphics 
= Graphics.FromImage(bmp);
            Font font 
= new Font("Courier New", fontSize, FontStyle.Bold);
            Brush brush 
= new SolidBrush(clrFont);
            Brush brushBg 
= new SolidBrush(clrBg);
            graphics.FillRectangle(brushBg, 
00, width, height);
            Bitmap tmpBmp 
= new Bitmap(height, height);
            Graphics tmpGph 
= null;
            
int degree = 40;
            Point tmpPoint 
= new Point();
            
for (int i = 0; i < text.Length; i++)
            {
                tmpBmp 
= new Bitmap(height, height);
                tmpGph 
= Graphics.FromImage(tmpBmp);
               
// tmpGph.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit;
               
// 不填充底色,文字 ClearType 效果不见了,why?!
               
// tmpGph.FillRectangle(brushBg, 0, 0, tmpBmp.Width, tmpBmp.Height);
                degree = rnd.Next(2051); // [20, 50]随机角度
                if (rnd.Next(02== 0)
                {
                    tmpPoint.X 
= 12// 调整文本坐标以适应旋转后的图象
                    tmpPoint.Y = -6;
                }
                
else
                {
                    degree 
= ~degree + 1// 逆时针旋转
                    tmpPoint.X = -10;
                    tmpPoint.Y 
= 6;
                }

                tmpGph.RotateTransform(degree);
                tmpGph.DrawString(text[i].ToString(), font, brush, tmpPoint);
                graphics.DrawImage(tmpBmp, i 
* fontSize, 0); // 拼接图象
            }
            
            
//输出图象
            System.IO.MemoryStream memoryStream = new System.IO.MemoryStream();
            bmp.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Gif);
            HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
            HttpContext.Current.Response.ClearContent();
            HttpContext.Current.Response.ContentType 
= "image/gif";
            HttpContext.Current.Response.BinaryWrite(memoryStream.ToArray());
            HttpContext.Current.Response.End();

            
//释放资源
            font.Dispose();
            brush.Dispose();
            brushBg.Dispose();
            tmpGph.Dispose();
            tmpBmp.Dispose();
            graphics.Dispose();
            bmp.Dispose();
            memoryStream.Dispose();
        }
    }
}


posted on 2008-06-22 16:40  iTonyDay  阅读(2452)  评论(15编辑  收藏  举报