分类
Web编程

谈谈C#验证码识别的方法集合

前段一直没有时间维护博客,还是因为太懒了只当它是一个wordpress的文具,其实工作生活记录一下没有什么不好。

个人项目中需要验证码识别,所以研究了一阵子,图像识别是c#的弱项。到互联网飞速发展的今天,验证码识别已经没当初那么简单了。

使用c#有以下几种识别方式:

tesseract-ocr

这是一个开源项目,项目地址:https://code.google.com/p/tesseract-ocr/。现在已经被google接手。当前最新的是3.02版,支持多个平台。需要注意的是安装了之后还需要下载与版本对应的语言包放到安装目录,默认设置下的识别能力一般,但是可以通过学习训练来得到最优的配置,具体设置方法请参阅wiki

windows平台下面可以通过cmd调用

执行识别图像的命令格式为:
tesseract .exe [-l lang]
Imagename: 需要识别的图片文件名
outputname: 输出结果txt文件名,用来存放识别出来的文字结果
lang: 使用的文字字库,根据要识别的文字类型来选择。
例如:输入命令:tesseract.exe 6.jpg 6 –l chi_sim

遗憾的是web用户调用cmd需要特殊权限,对于安全性是不好的

2 Asprise OCR

最新的是Asprise OCR v4.0 for C# [C Sharp] .NET,官网在http://asprise.com/product/ocr/index.php?lang=csharp。这不是一个开源项目,好在伟大的天朝到处都是破解版可以下载。没有繁琐的学习和训练,dll是由c++编译的,c#调用方便。如果是web项目甚至可以不用把dll放在项目里面。数字和字母的识别率挺高的。

调用方式:

[DllImport("AspriseOCR.dll")]
static extern string craboOCR(string file, int type);

private void GetVeryfyCode()
{
   if(File.Exists(_imgPath))//ok now?
   {
    try
    {
        this.picbVeryfyCode.Image = System.Drawing.Bitmap.FromFile(_imgPath);
        _veryfyCode = craboOCR(_imgPath,-1);   //将返回string,并以"\r\n"结尾!!
        _veryfyCode = _veryfyCode.Substring(0,4);
        this.txtVeryfyCode.Text = _veryfyCode;
    }
    catch(Exception e)
    {
       this.lblResult.Text += e.Message;
    }
   }
}

需要注意的是代码里虽然只调用了一个AspriseOCR.dll,但是同一目录下还需要放另外2dll个哦。我在win7+vs2012+iisexpress环境测试成功,server上失败,也许是dll版本和系统不匹配

3 Tessnet2

Tessnet2 a .NET 2.0 Open Source OCR assembly using Tesseract engine 项目地址:http://www.pixel-technology.com/freeware/tessnet2/ 。其实就是前面说的tesseract-ocr 旧版本2.0的。net版。可以直接集成到framework2.0的web项目,同样需要下载语言包,语言包也在tesseract-ocr地址里下载,但是版本号一定要对应,也就是说只能使用tesseract-ocr 2的语言包。

4 自己写代码处理验证码图像,这个不详细讲了,通用性不高。也可以把图片简单处理后采用前面的方式来识别,提高成功率。


 

总结:不管使用什么识别工具,都存在一个识别率的问题,一句话没有百分之百的识别。还是要具体情况具体分析:

如果你想做一个qq空间游戏外挂,个人建议还是把验证码request下来给用户输吧,我相信没有人会为了少输一个验证码而容忍连续失败10次的登录(这个可是经常会有);

如果你想做的是自动化暴力的http post,比如自动注册机,不在乎失败反正挂在那循环。。。你应该采用验证码识别技术。

分享经验只为节省大家的时间:)

C#操作压缩文件(rar,zip,gzip,winform/asp.net)

 

 

从.NET 2.0开始,微软提供了一个 System.IO.Compression 的NameSpace,下含有 GZipStream 和 DeflateStream,都具有压缩和解压功能,但是,确不支持 zip 和 rar等常用的压缩文件。因为rar是有版权的,不支持有情可原,但zip是开源的,也不支持就有点自私了(估计微软是为了自己的cab格式)

对于 rar 格式,我们可以直接利用WinRAR提供的rar.exe/unrar.exe(此文件在winrar的安装目录下,是一个console程序),这种情况,只能用于 winform 或者 在提权 的情况下,才能用于 asp.net ;

对于 zip 格式,我们这里推荐是用原生的C#类库,这种方式,可以适用于asp.net(要有目录的写权限),我推荐大家使用开源免费的 SharpZipLib 。

对于 rar.exe 的解压和压缩,下面先给出它的 命令行格式对照表,便于了解:

rar命令行的使用方法:

rar <命令> -<开关 1> -<开关 N> <压缩文件> <文件…> <@列表文件…> <解压路径\>

rar的命令列表:

 

rar 的开关列表:


rar使用的例子:

 

1、rar a file file.ext 

如果file.rar不存在将创建file.rar文件;如果file.rar压缩包中已有file.ext,将更新压缩包中的file.ext

2、rar a file d:\*.ext

将d盘下所有ext文件(不包括自文件夹)添加到压缩包中

3、rar x Fonts *.ttf 

从压缩文件中解压 *.ttf 字体文件到当前文件夹

4、rar x Fonts *.ttf NewFonts\

从压缩文件中解压 *.ttf 字体文件到 NewFonts 目录下

5、rar e -p密码 test.rar

将有密码test.rar文件,解压到当前文件夹


C#调用rar.exe解压一个rar文件到系统的临时目录:

//取得系统临时目录
string sysTempDir = Path.GetTempPath();

//要解压的文件路径,请自行设置
string rarFilePath = @"d:\test.rar";

//确定要解压到的目录,是系统临时文件夹下,与原压缩文件同名的目录里
string unrarDestPath = Path.Combine(sysTempDir,
    Path.GetFileNameWithoutExtension(rarFilePath));

//组合出需要shell的完整格式
string shellArguments = string.Format("x -o+ \"{0}\" \"{1}\\\"",
    rarFilePath, unrarDestPath);

//用Process调用
using (Process unrar = new Process())
{
    unrar.StartInfo.FileName = "rar.exe";
    unrar.StartInfo.Arguments = shellArguments;
    //隐藏rar本身的窗口
    unrar.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
    unrar.Start();
    //等待解压完成
    unrar.WaitForExit();
    unrar.Close();
}

//统计解压后的目录和文件数
DirectoryInfo di = new DirectoryInfo(unrarDestPath);

MessageBox.Show(string.Format("解压完成,共解压出:{0}个目录,{1}个文件",
    di.GetDirectories().Length, di.GetFiles().Length));

例子代码下载

C#中文转拼音代码

c#代码,自动生成简码,可以根据输入的商品名称等信息自动取其中文拼音首字母作为简码-c# code automatically generated Jane code, based on the importation of trade names and other information automatically choose the first letter of Chinese phonetic code as Jane

 

using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions; 

public static class Chs2Spell
{  

    #region 编码定义,不支持全角字符 

    private static int[] pyvalue = new int[]
    {
          -20319, -20317, -20304, -20295, -20292, -20283, -20265, -20257, -20242, -20230, -20051, -20036, -20032,
                -20026,
                -20002, -19990, -19986, -19982, -19976, -19805, -19784, -19775, -19774, -19763, -19756, -19751, -19746,
                -19741, -19739, -19728,
                -19725, -19715, -19540, -19531, -19525, -19515, -19500, -19484, -19479, -19467, -19289, -19288, -19281,
                -19275, -19270, -19263,
                -19261, -19249, -19243, -19242, -19238, -19235, -19227, -19224, -19218, -19212, -19038, -19023, -19018,
                -19006, -19003, -18996,
                -18977, -18961, -18952, -18783, -18774, -18773, -18763, -18756, -18741, -18735, -18731, -18722, -18710,
                -18697, -18696, -18526,
                -18518, -18501, -18490, -18478, -18463, -18448, -18447, -18446, -18239, -18237, -18231, -18220, -18211,
                -18201, -18184, -18183,
                -18181, -18012, -17997, -17988, -17970, -17964, -17961, -17950, -17947, -17931, -17928, -17922, -17759,
                -17752, -17733, -17730,
                -17721, -17703, -17701, -17697, -17692, -17683, -17676, -17496, -17487, -17482, -17468, -17454, -17433,
                -17427, -17417, -17202,
                -17185, -16983, -16970, -16942, -16915, -16733, -16708, -16706, -16689, -16664, -16657, -16647, -16474,
                -16470, -16465, -16459,
                -16452, -16448, -16433, -16429, -16427, -16423, -16419, -16412, -16407, -16403, -16401, -16393, -16220,
                -16216, -16212, -16205,
                -16202, -16187, -16180, -16171, -16169, -16158, -16155, -15959, -15958, -15944, -15933, -15920, -15915,
                -15903, -15889, -15878,
                -15707, -15701, -15681, -15667, -15661, -15659, -15652, -15640, -15631, -15625, -15454, -15448, -15436,
                -15435, -15419, -15416,
                -15408, -15394, -15385, -15377, -15375, -15369, -15363, -15362, -15183, -15180, -15165, -15158, -15153,
                -15150, -15149, -15144,
                -15143, -15141, -15140, -15139, -15128, -15121, -15119, -15117, -15110, -15109, -14941, -14937, -14933,
                -14930, -14929, -14928,
                -14926, -14922, -14921, -14914, -14908, -14902, -14894, -14889, -14882, -14873, -14871, -14857, -14678,
                -14674, -14670, -14668,
                -14663, -14654, -14645, -14630, -14594, -14429, -14407, -14399, -14384, -14379, -14368, -14355, -14353,
                -14345, -14170, -14159,
                -14151, -14149, -14145, -14140, -14137, -14135, -14125, -14123, -14122, -14112, -14109, -14099, -14097,
                -14094, -14092, -14090,
                -14087, -14083, -13917, -13914, -13910, -13907, -13906, -13905, -13896, -13894, -13878, -13870, -13859,
                -13847, -13831, -13658,
                -13611, -13601, -13406, -13404, -13400, -13398, -13395, -13391, -13387, -13383, -13367, -13359, -13356,
                -13343, -13340, -13329,
                -13326, -13318, -13147, -13138, -13120, -13107, -13096, -13095, -13091, -13076, -13068, -13063, -13060,
                -12888, -12875, -12871,
                -12860, -12858, -12852, -12849, -12838, -12831, -12829, -12812, -12802, -12607, -12597, -12594, -12585,
                -12556, -12359, -12346,
                -12320, -12300, -12120, -12099, -12089, -12074, -12067, -12058, -12039, -11867, -11861, -11847, -11831,
                -11798, -11781, -11604,
                -11589, -11536, -11358, -11340, -11339, -11324, -11303, -11097, -11077, -11067, -11055, -11052, -11045,
                -11041, -11038, -11024,
                -11020, -11019, -11018, -11014, -10838, -10832, -10815, -10800, -10790, -10780, -10764, -10587, -10544,
                -10533, -10519, -10331,
                -10329, -10328, -10322, -10315, -10309, -10307, -10296, -10281, -10274, -10270, -10262, -10260, -10256,
                -10254
            }; 

    private static string[] pystr = new string[]
    {
         "a", "ai", "an", "ang", "ao", "ba", "bai", "ban", "bang", "bao", "bei", "ben", "beng", "bi", "bian",
                "biao",
                "bie", "bin", "bing", "bo", "bu", "ca", "cai", "can", "cang", "cao", "ce", "ceng", "cha", "chai", "chan"
                , "chang", "chao", "che", "chen",
                "cheng", "chi", "chong", "chou", "chu", "chuai", "chuan", "chuang", "chui", "chun", "chuo", "ci", "cong"
                , "cou", "cu", "cuan", "cui",
                "cun", "cuo", "da", "dai", "dan", "dang", "dao", "de", "deng", "di", "dian", "diao", "die", "ding",
                "diu", "dong", "dou", "du", "duan",
                "dui", "dun", "duo", "e", "en", "er", "fa", "fan", "fang", "fei", "fen", "feng", "fo", "fou", "fu", "ga"
                , "gai", "gan", "gang", "gao",
                "ge", "gei", "gen", "geng", "gong", "gou", "gu", "gua", "guai", "guan", "guang", "gui", "gun", "guo",
                "ha", "hai", "han", "hang",
                "hao", "he", "hei", "hen", "heng", "hong", "hou", "hu", "hua", "huai", "huan", "huang", "hui", "hun",
                "huo", "ji", "jia", "jian",
                "jiang", "jiao", "jie", "jin", "jing", "jiong", "jiu", "ju", "juan", "jue", "jun", "ka", "kai", "kan",
                "kang", "kao", "ke", "ken",
                "keng", "kong", "kou", "ku", "kua", "kuai", "kuan", "kuang", "kui", "kun", "kuo", "la", "lai", "lan",
                "lang", "lao", "le", "lei",
                "leng", "li", "lia", "lian", "liang", "liao", "lie", "lin", "ling", "liu", "long", "lou", "lu", "lv",
                "luan", "lue", "lun", "luo",
                "ma", "mai", "man", "mang", "mao", "me", "mei", "men", "meng", "mi", "mian", "miao", "mie", "min",
                "ming", "miu", "mo", "mou", "mu",
                "na", "nai", "nan", "nang", "nao", "ne", "nei", "nen", "neng", "ni", "nian", "niang", "niao", "nie",
                "nin", "ning", "niu", "nong",
                "nu", "nv", "nuan", "nue", "nuo", "o", "ou", "pa", "pai", "pan", "pang", "pao", "pei", "pen", "peng",
                "pi", "pian", "piao", "pie",
                "pin", "ping", "po", "pu", "qi", "qia", "qian", "qiang", "qiao", "qie", "qin", "qing", "qiong", "qiu",
                "qu", "quan", "que", "qun",
                "ran", "rang", "rao", "re", "ren", "reng", "ri", "rong", "rou", "ru", "ruan", "rui", "run", "ruo", "sa",
                "sai", "san", "sang",
                "sao", "se", "sen", "seng", "sha", "shai", "shan", "shang", "shao", "she", "shen", "sheng", "shi",
                "shou", "shu", "shua",
                "shuai", "shuan", "shuang", "shui", "shun", "shuo", "si", "song", "sou", "su", "suan", "sui", "sun",
                "suo", "ta", "tai",
                "tan", "tang", "tao", "te", "teng", "ti", "tian", "tiao", "tie", "ting", "tong", "tou", "tu", "tuan",
                "tui", "tun", "tuo",
                "wa", "wai", "wan", "wang", "wei", "wen", "weng", "wo", "wu", "xi", "xia", "xian", "xiang", "xiao",
                "xie", "xin", "xing",
                "xiong", "xiu", "xu", "xuan", "xue", "xun", "ya", "yan", "yang", "yao", "ye", "yi", "yin", "ying", "yo",
                "yong", "you",
                "yu", "yuan", "yue", "yun", "za", "zai", "zan", "zang", "zao", "ze", "zei", "zen", "zeng", "zha", "zhai"
                , "zhan", "zhang",
                "zhao", "zhe", "zhen", "zheng", "zhi", "zhong", "zhou", "zhu", "zhua", "zhuai", "zhuan", "zhuang",
                "zhui", "zhun", "zhuo",
                "zi", "zong", "zou", "zu", "zuan", "zui", "zun", "zuo"
            }; 

    #endregion 

    /**/
    /// <summary>
    /// 将中文转换为拼音
    /// 如果给定的字符为非中文汉字将不执行转化,直接返回原字符;
    /// </summary>
    /// <param name="chsstr">指定汉字字符串</param>
    /// <returns>拼音字符串</returns>
    public static string ChsString2Spell(string chsstr)
    {
        string strRet = string.Empty; 

        char[] ArrChar = chsstr.ToCharArray(); 

        foreach (char c in ArrChar)
        {
            if (c == '孢') //"孢"系统转换有问题
            {
                strRet += "Bao ";
            }
            else
            {
                strRet += SingleChs2Spell(c.ToString());
            } 

        }
        return strRet;
    } 

     /**//// <summary>
        /// 取出一行字符首字母(大写)
        /// </summary>
        /// <param name="chsstr">指定汉字字符串</param>
        /// <returns>拼音首字母</returns>
        public static string GetHeadOfChs(string chsstr)
        {
            string strRet = string.Empty; 

            char[] ArrChar = chsstr.ToCharArray(); 

            foreach (char c in ArrChar)
             {
                 if (c == '孢')
                 {
                     strRet += "B";
                 }
                 else
                 {
                     strRet += GetHeadOfSingleChs(c.ToString());
                 } 

             } 

            return strRet;
        } 

    /**/
    /// <summary>
    /// 单个汉字字符转化为拼音字符串
    /// </summary>
    /// <param name="SingleChs">单个汉字字符</param>
    /// <returns>拼音字符串</returns>
     public static string SingleChs2Spell(string SingleChs)
     {
         byte[] array;
            int iAsc;
            string strRtn = string.Empty; 

            array = Encoding.Default.GetBytes(SingleChs); 

            try
            {
                iAsc = (short) (array[0]) * 256 + (short) (array[1]) - 65536;
            }
            catch
            {
                iAsc = 1;
            }
         if (iAsc > 0 && iAsc < 160)
                return SingleChs; 

            for (int i = (pyvalue.Length - 1); i >= 0; i--)
            {
                if (pyvalue[i] <= iAsc)
                {
                    strRtn = pystr[i];
                    break;
                }
            } 

            //将首字母转为大写
            if (strRtn.Length >= 1)
            {
                strRtn = strRtn.Substring(0, 1).ToUpper() + strRtn.Substring(1)+" ";
            } 

            return strRtn;
        } 

     /**//// <summary>
        /// 取单个汉字拼音的首字母
        /// </summary>
        /// <param name="SingleChs">单个汉字字符</param>
        /// <returns>拼音首字符</returns>
        public static string GetHeadOfSingleChs(string SingleChs)
        {
            return SingleChs2Spell(SingleChs).Substring(0, 1);
        } 

}

asp与aspx共享session

因为最近要把asp和aspx两个网站整合到一起,session自然就成了一个难题了,自己在这方面还没有接触过,所以没办法又到处找资料。微软的网站上提供的是用数据库实现的,总觉得太麻烦,速度又会下降,于是放弃.也有说直接使用的,但我试了下没成功,大部分人认为这样是不可能的。另外还有一种方法,就是通过几个页面转换,我最后选用也是这个方法,通过搜索到的资料,整理后编写了几个页面来转换。主要是通过隐藏的input来实现的。具体方法如下:

 

asp转asp.net

logincheck.asp

程序代码 程序代码
<%

Username=Request.Form("Username")
Password=Request.Form("Password")
Set Rs = Server.CreateObject("ADODB.Recordset")
sql="select * from teacher where Uname='"&Username&"' and Pwd='"&Password&"'"
rs.open sql,cn,1,1
if rs.bof or rs.eof then
    Response.write("<script>alert('用户名或密码错误!请返回重新输入');window.location.replace('default.asp');</script>")
    Response.End()
else
session("Username")=trim(Rs("Uname"))

    response.write("<form name=frm id=frm action=""asptoaspx.aspx"" method=post >")
     Response.Write "<input type=hidden name=uname value="&session("Username")&">"
     Response.Write "<input type=hidden name=flag value=1">"    //此处用来判断登陆还是退出
    response.write("</form>")
    response.write("<scr" + "ipt>frm.submit();</scr" + "ipt>")
%>

 

 

asptoaspx.aspx

程序代码 程序代码
<%@ Page Language="C#" ContentType="text/html" ResponseEncoding="gb2312" %>
<script runat="server">
     protected void Page_Load(object sender, EventArgs e)
    {

        string flag = Request.Form.Get("flag");
        if (flag == "1")
        {

             Session["teacher"] = Request.Form.Get("uname");

        }
        else
          {

             Session["teacher"] = "";
          }

                 Response.Redirect("http://127.0.0.1/show");
}

</script>

 

 

asp.net 转 asp 页面:

logincheck.aspx

程序代码 程序代码
<%@ Page language="c#"  %>
<script language=C# runat=server>
private void Page_Load(object sender, System.EventArgs e)
{

Session["teacher"] = uname.Text.Trim().ToString();
Response.Write("<form name=frm id=frm action=aspxtoasp.asp method=post>");
Response.Write("<input type=hidden name=username value='"+Session["teacher"]+"'>");
Response.Write("<input type=hidden name=flag value=1>");
Response.Write("</form>");
Response.Write("<scr"+"ipt language='javascript'>frm.submit();</scr"+"ipt>");
}
</script>

 

 

aspxtoasp.asp

程序代码 程序代码
<%

flag=request("flag")
if flag="1" then
session("teacher")=""
else
session("teacher")=request("username")
end if

Response.Redirect"xxx.aspx"

%>

 

 

 

 

 

C# 控制主板蜂鸣器发声

 

在C#中可以通过以下四种方式来实现蜂鸣或者报警,播放声音之类的功能.XP下对蜂鸣有用,win7下请接上扬声器.

1). Beep的报警实现

 

// 添加引用
   using System.Runtime.InteropServices;  

   [DllImport("user32.dll")]
   public static extern int MessageBeep(uint uType);
   uint beepI = 0x00000030;  

    //发出不同类型的声音的参数如下:
    //Ok = 0x00000000,
    //Error = 0x00000010,
    //Question = 0x00000020,
    //Warning = 0x00000030,
    //Information = 0x00000040  

    // 然后在程序中调用
    MessageBeep(beepI);

2) 调用Microsoft.ViualBase中的Beep():
1.先引入命名空间:using Microsoft.VisualBasic;
2.调用:Interaction.Beep();
在编译时注意要引用Microsoft.VisualBasic.dll程序集,否则编译不能通过。
另外,如果是Console应用,可以用Console.WriteLine(”\a”);来代替Beep()。

3) 通过主板蜂鸣器发出蜂鸣

 

[DllImport("kernel32.dll", EntryPoint = "Beep")]
// 第一个参数是指频率的高低,越大越高,第二个参数是指响的时间多长
public static extern int Beep(
int dwFreq,
int dwDuration
);

 

4) 调用PlaySound(string pszSound,int hmod,int fdwSound)来播放声音

 

using System.Runtime.InteropServices;
然后声明:
[DllImport("winmm.dll")]
public static extern bool PlaySound(String Filename, int Mod, int Flags);
播放:
PlaySound(@"e:\Music\login.wav", 0, 1);      //把1替换成9,可连续播放

 

分类
未分类

C#生成验证码图片代码

以下是本人整理的生成验证码图片的C#代码。不对,严格说应该是asp.net代码。。。

可以通过下面注释的部分采用cookie或session来验证!

protected void Page_Load(object sender, EventArgs e)
        {
            validateCode v = new validateCode();
            v.Length = this.length;
            v.FontSize = this.fontSize;
            v.Chaos = false;
            v.BackgroundColor = Color.Black;
            v.ChaosColor = this.chaosColor;
            v.CodeSerial = this.codeSerial;
            Color[] FontColors = { Color.White };
            v.Colors = FontColors;
            v.Fonts = this.fonts;
            v.FontSize = 14;
            v.Padding = this.padding;
            string code = v.CreateVerifyCode();                //取随机码
            v.CreateImageOnPage(code, this.Context);        // 输出图片
            //Response.Cookies.Add(new HttpCookie("CheckCode", code.ToLower()));// 使用Cookies取验证码的值
            Session["CheckCode"] = code;

        }

        #region 验证码长度(默认4个验证码的长度)
        int length = 4;
        /// <summary>
        /// 验证码长度(默认4个验证码的长度)
        /// </summary>
        public int Length
        {
            get { return length; }
            set { length = value; }
        }
        #endregion
        #region 验证码字体大小(为了显示扭曲效果,默认40像素,可以自行修改)
        int fontSize = 10;

        /// <summary>
        /// 验证码字体大小(为了显示扭曲效果,默认40像素,可以自行修改)
        /// </summary>
        public int FontSize
        {
            get { return fontSize; }
            set { fontSize = value; }
        }
        #endregion

        #region 边框补(默认1像素)
        int padding = 1;
        /// <summary>
        /// 边框补(默认1像素)
        /// </summary>
        public int Padding
        {
            get { return padding; }
            set { padding = value; }
        }
        #endregion
        #region 是否输出燥点(默认不输出)
        bool chaos = true;

        /// <summary>
        /// 是否输出燥点(默认不输出)
        /// </summary>
        public bool Chaos
        {
            get { return chaos; }
            set { chaos = value; }
        }
        #endregion

        #region 输出燥点的颜色(默认灰色)
        Color chaosColor = Color.LightGray;
        /// <summary>
        /// 输出燥点的颜色(默认灰色)
        /// </summary>
        public Color ChaosColor
        {
            get { return chaosColor; }
            set { chaosColor = value; }
        }
        #endregion
        #region 自定义背景色(默认白色)
        Color backgroundColor = Color.White;

        /// <summary>
        /// 自定义背景色(默认白色)
        /// </summary>
        public Color BackgroundColor
        {
            get { return backgroundColor; }
            set { backgroundColor = value; }
        }
        #endregion

        #region 自定义随机颜色数组
        Color[] colors = { Color.Black, Color.Red, Color.DarkBlue, Color.Green, Color.Orange, Color.Brown, Color.DarkCyan, Color.Purple };
        /// <summary>
        /// 自定义随机颜色数组
        /// </summary>
        public Color[] Colors
        {
            get { return colors; }
            set { colors = value; }
        }
        #endregion

        #region 自定义字体数组
        string[] fonts = { "Arial", "Georgia" };
        /// <summary>
        /// 自定义字体数组
        /// </summary>
        public string[] Fonts
        {
            get { return fonts; }
            set { fonts = value; }
        }
        #endregion
        #region 自定义随机码字符串序列(使用逗号分隔)
         //string codeSerial = "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";
        string codeSerial = "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";
        /// <summary>
        /// 自定义随机码字符串序列
        /// </summary>
        public string CodeSerial
        {
            get { return codeSerial; }
            set { codeSerial = value; }
        }
        #endregion
        #region 产生波形滤镜效果
        private const double PI = 3.1415926535897932384626433832795;
        private const double PI2 = 6.283185307179586476925286766559;

        /// <summary>
        /// 正弦曲线Wave扭曲图片
        /// </summary>
        /// <param name="srcBmp">图片路径</param>
        /// <param name="bXDir">如果扭曲则选择为True</param>
        /// <param name="nMultValue">波形的幅度倍数,越大扭曲的程度越高,一般为3</param>
        /// <param name="dPhase">波形的起始相位,取值区间[0-2*PI)</param>
        /// <returns></returns>
        public System.Drawing.Bitmap TwistImage(Bitmap srcBmp, bool bXDir, double dMultValue, double dPhase)
        {
            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 ? (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="code">校验码</param>
        /// <returns></returns>
        public Bitmap CreateImageCode(string code)
        {
            int fSize = FontSize;
            int fWidth = fSize + Padding;

            int imageWidth = (int)(code.Length * fWidth) + 4 + Padding * 2;
            int imageHeight = fSize * 2 + Padding;
            System.Drawing.Bitmap image = new System.Drawing.Bitmap(imageWidth, imageHeight);
            Graphics g = Graphics.FromImage(image);
            g.Clear(BackgroundColor);
            Random rand = new Random();
            //给背景添加随机生成的燥点
            if (this.Chaos)
            {
                Pen pen = new Pen(ChaosColor, 0);
                int c = Length * 10;

                for (int i = 0; i < c; i++)
                {
                    int x = rand.Next(image.Width);
                    int y = rand.Next(image.Height);
                    g.DrawRectangle(pen, x, y, 1, 1);
                }
            }
            int left = 0, top = 0, top1 = 1, top2 = 1;
            int n1 = (imageHeight - FontSize - Padding * 2);
            int n2 = n1 / 4;
            top1 = n2;
            top2 = n2 * 2;

            Font f;
            Brush b;
            int cindex, findex;
            //随机字体和颜色的验证码字符
            for (int i = 0; i < code.Length; i++)
            {
                cindex = rand.Next(Colors.Length - 1);
                findex = rand.Next(Fonts.Length - 1);
                f = new System.Drawing.Font(Fonts[findex], fSize, System.Drawing.FontStyle.Bold);
                b = new System.Drawing.SolidBrush(Colors[cindex]);

                if (i % 2 == 1)
                {
                    top = top2;
                }
                else
                {
                    top = top1;
                }
                left = i * fWidth;
                g.DrawString(code.Substring(i, 1), f, b, left, top);
            }

            //画一个边框 边框颜色为Color.Gainsboro
            g.DrawRectangle(new Pen(Color.Gainsboro, 0), 0, 0, image.Width - 1, image.Height - 1);
            g.Dispose();

            //产生波形(Add By 51aspx.com)
            image = TwistImage(image, false, 1, 10);
            return image;
        }
        #endregion
        #region 将创建好的图片输出到页面
        public void CreateImageOnPage(string code, HttpContext context)
        {
            System.IO.MemoryStream ms = new System.IO.MemoryStream();
            Bitmap image = this.CreateImageCode(code);
            image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
            context.Response.ClearContent();
            context.Response.ContentType = "image/Jpeg";
            context.Response.BinaryWrite(ms.GetBuffer());
            ms.Close();
            ms = null;
            image.Dispose();
            image = null;
        }
        #endregion

        #region 生成随机字符码
        public string CreateVerifyCode(int codeLen)
        {
            if (codeLen == 0)
            {
                codeLen = Length;
            }

            string[] arr = CodeSerial.Split(',');

            string code = "";

            int randValue = -1;

            Random rand = new Random(unchecked((int)DateTime.Now.Ticks));

            for (int i = 0; i < codeLen; i++)
            {
                randValue = rand.Next(0, arr.Length - 1);

                code += arr[randValue];
            }
            return code;
        }
        public string CreateVerifyCode()
        {
            return CreateVerifyCode(0);
        }
        #endregion