默之's profile个人随笔PhotosBlogListsMore Tools Help

Blog


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

    天目湖、南山竹海二日游2(2008年03月23日)

          第二天我们来到了南山竹海的大门口,宋代苏轼在《于潜僧绿筠轩》中曾写到,“宁可食无肉,不可居无竹。 无肉令人瘦,无竹令人俗。 人瘦尚可肥,士俗不可医”。在竹海的大门上就写了这首诗。但是门上缺了几个字,当地的导游就读不完整了。非常可惜。 

    y1pIg70ykvoZ-pi139i2H2njmOuuasMo9rN4je3x1wtgRLzkM-QWIJeruaswzn125x5ug_3LXWp88U(南山竹海大门)  y1pIg70ykvoZ-o8vW1AXGrDyXEBNK7brCBrccrW50mu6Tc9ah6_YdT-rFeUrwdkLzRu3f5KJ-hIUNQ(余风琴、我、汪彼得、阳昭星,从左到右)

    y1pIg70ykvoZ-rCyvQ2xs_C4Q6vkYlD0NLvVG7bBTM9xkgkwQIps0LKgjK6E8nvpOXdPaGLETGltbI(余风琴、汪彼得,从左到右)y1pIg70ykvoZ-quwBMwzPRLY-FARrR5NtU5c8vvl_IoDKiQMrgolIzyng2jDGgR8FNZ6VK0YZiTzbc(余风琴、阳昭星、汪彼得、我)

          虽然昨天在天目湖景区还在下雨,但是今天游览南山竹海,运气非常的好,艳阳高照,大家在“静湖”边合影留念后,乘旅游车到达寿星广场。

    y1pIg70ykvoZ-poGvkawH81HdP4_Yzi9YFWr5tMAPF8ggZFGZcEg9JK4tboS0qMUHHnNjC5dg4dA8s(静湖,吴波、阳昭星、余风琴、汪彼得,从左到右)y1pIg70ykvoZ-rwV15SlCZgO7lqj4mLgPMbFr-_RVk9DSM8lggG-zkHDgQmj9I7e8tFiPF4mzwmn4c(寿星广场)

            从寿星广场乘缆车登上吴越第一峰,登山顶瞭望古官道,看三省交汇(安徽省、江苏省、浙江省)。我和阳昭星一起、吴波和余风琴一起,汪彼得独自一辆车。乘了大概20分钟,坐到半山的时候风很大,缆车呈45度的摇晃,当时我手心汉都出来了。向下看实在是太高了。 

    y1pIg70ykvoZ-pSlmBVTSacir_QjBqMcSdZLGAq4RNScE_ZfPJh3y3lFsfQmrw7k_pcb-3-LbmbtRM(缆车下的风景)y1pVvXAG_G2WmVJqTcaw1-VCVXRNtcjxKbrvF25aCOnICovXeNRQciBggaA-9ljQEWGguL6kFf9dtpaHAT-3N-oLpaOZL8t5MPo(阳昭星和我在缆车上)

    y1pIg70ykvoZ-rRuHamr4-dxagVE5NvNVtnuGxqrtAIVwCBAsA2aU_PLgDrGkK-y8yfLiKmhc8xVlo(吴越第一峰,吴波、余风琴、阳昭星、汪彼得、我)

    y1pIg70ykvoZ-rPm_S4tOldvvRwleAPKEU1tyV9Dl93FulbGzxU6lQX55JxskUdGKKnyRY1i6a6jIo(吴波、阳昭星、汪彼得、余风琴、我,看古官道、三省交汇)y1pIg70ykvoZ-qK4rDObcqt_1Hofo7nbNDsG49FhP3deA4ZJTKc3eCf9j6cAzggHUa2bv2E6vIaTdg(余风琴)

          登上吴越第一峰之后(海拔1200米),缆车因为风大所以停运了,我们大家步行下山(本来也是这个打算)。很久不运动了,下个山都有些气喘。真不好意思。

     y1pIg70ykvoZ-prZ-kGU_xxLQZAepL3URgerqitbDnfAHz8HdmBH5sdf9w_gRYRTCgmtO3nEwOB8do(下山的路)y1pIg70ykvoZ-r_Zk1T4xISwZTgJlNFbFRTdTSJTuc2PRLkig94iYdldRNmQ0J_MAfZArkkZXkg4Mo(下山经过南山寿泉)

    y1pIg70ykvoZ-p_UUd2QA8x9I6uc1EWgpBWSD3xwL5fB4Iw-g7SEbDhEybMFPhYXzIMSpiepyjIHls(小鸟天堂,散养了很多小鸟)

        下山之后,大家在南山人家用完了午餐,开始启程回上海。在17:00左右到达上体馆,我觉得我们应该自发多组织一些这样的活动,使紧张的心情可以得到缓解。使人与自然更加和谐。

    天目湖、南山竹海二日游1(2008年03月22日)

          从天目湖旅游回来已经有半个月了,由于期间发生了一些事情,所以直到今天我才有兴趣来写一写关于这次我组织的公司部分人员天目湖、南山竹海二日游的文章。
          天目湖位于江苏省溧阳市,是天目湖鱼头砂锅的发祥地,天目湖景区是国家4A级景区,说到天目鱼头砂锅的来历,还非常有趣,听导游说在3年自然灾害时,天目湖附近的居民靠山吃山、靠水吃水,就靠吃天目湖的鱼度过了这次灾害,但是当时居民名吃鱼都不吃鱼头,将鱼头随意丢弃,当地的老村长看到了觉得非常可惜。就将鱼头捡回去烧汤,由于天目湖的水质很好,而起湖底含沙量很少,鱼又是一种名叫大头灰鲢的鱼,烧出来的汤味道鲜美,没有土腥味。有一次上级领导来村视察,村里没有什么准备,老村长就让厨师朱顺才师傅制作了鱼头砂锅,上级领导吃了连声叫好。以后只要领导到江苏视察,都要点这道鱼头砂锅。值得一提的是,一九八五年,“鱼头大师”朱顺才曾受命特为邓小平煨砂锅鱼头汤,邓小平喝后连声称好,并请夫人卓琳为朱顺才敬酒。此后,砂锅鱼头汤更是声名大振,现已被誉为江苏最佳传统名菜,成为中国美食天地的一枝奇葩。著名社会学家费孝通老先生品尝过砂锅鱼头后,欣然题词:“溧阳天目湖砂锅鱼头,朱顺才手艺誉满全球”。
         2008年3月22日余风琴、汪彼德、阳昭星、吴波、我一行五人,早上8:30在上体馆上了上海旅游集散中心的天目湖、南山竹海二日游的旅行车,开始了天目湖、南山竹海二日游。在开车4小时之后(大约12点左右),我们到达了 天目湖景区。
    y1pIg70ykvoZ-rO7jiLdFas0nsmcV9hXaM3cSGDc9I4PbcstXz-E0glxs2hNt0Oj3HaL5x8Kgv-ysc(天目湖景区大门,汪彼得、阳昭星、吴波、余风琴,从左到右)
    y1pIg70ykvoZ-omIhk4rcIKFUpk0t_QOIFyRDepIMdMKAzW20vRy6FnkJYXKB9ovNetO9nxG0dLSKg(下山,吴波、汪彼得,阳昭星、余风琴)y1pIg70ykvoZ-rV0-i9ZmdNpbzgHPSTkcubg73U0VulKNfMzS1k1gTPgcuZQ2i1ahRL5x7Q68iHRcI(汪彼得、我、余风琴、阳昭星)
    用完午餐之后。首先搭乘“龙兴号”游艇畅游天目湖,并登上了天目湖的生态氧吧龙兴岛,参观蝴蝶谷,游览林间小道,当天下着朦朦细雨,道路比较湿滑,但是这种烟雨朦胧的感觉真实不错,空气特别的清醒,是上海所不能比较的。之后再次登船,去了天目湖的第二大岛乡村田园,在乡村田园岛上,我们参观农家的小屋,亲手推磨,磨制豆浆,走过了逍遥索桥,并看到了路边的茶树,茶树正在出嫩芽。在夕照湾酒店大家草草的用完了晚餐。因为晚上大伙准备去别的饭店好好品尝天目湖的鱼头砂锅和天目湖的啤酒。
    y1pIg70ykvoZ-oDkQWRlpAnD0V0O-0oh1L-xSUsGdLJgqNm2cnmBAA67I_ZDkLYFA7T0cohbur0pdY(逍遥桥)y1pIg70ykvoZ-pL92ZtG07vCOeNc_2o_37AZ4JyZbWRa5JJ-kTRoMyX5DBQjR--Gji2B8wyWpNpvIo(夕照湾酒店)
     
          晚上大约19:00点左右我们入住了汤臣花园商务酒店,酒店就位于溧阳市的美食街旁边。值得一提的是我们住的房间,有电脑可以提供上网,同时还有一个大的桌子可以供大家打牌。我们办好了房卡之后就马上冲出了房间,去品尝那传说中的“天目砂锅鱼头”,随便找了家饭店,大概时间在19:30左右,饭店都要打烊了,在这里不得不说一句,上海饭店的生意应该刚刚到达高峰。还好有“天目砂锅鱼头”,要等60分钟,没关系慢工出细活,点了一些家常小炒,叫上了几瓶天目湖啤酒(据说该啤酒上海麦德龙有售),大家开始聊了起来。等砂锅鱼头上了,我们也吃的很饱了,砂锅很大,鱼头大概有3斤左右,尝了尝味道还真不错,没有普通鱼头的腥味,就连我不太喜欢吃鱼的人,都吃了很多。回酒店后,大家打了几局牌,由于明天还要去南山竹海,所以在12点左右都休息了。
     
     
    March 01

    感谢

    感谢
    感激伤害你的人,因为他(她)磨练了你的心志;
    感激绊倒你的人,因为他(她)强化了你的双腿;
    感激欺骗你的人,因为他(她)增进了你的智慧;
    感激蔑视你的人,因为他(她)唤醒了你的自尊;
    感激遗弃你的人,因为他(她)教会了你该独立。
     
    感言:
    有了“因为”,所以“感谢”。
    July 04

    .NET 2005中自定义代码段的使用

    按照Microsoft的snippetFormat.xsd的schema文件编写代码段文件,文件类型为.snippet
    <?xml version="1.0" encoding="UTF-8"?>
    <CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
      <CodeSnippet Format="1.0.0">
      <Header>
      <Title>c#header</Title>
        <Shortcut>c#header</Shortcut>
      <Author>Developer.com</Author>
      <SnippetTypes>
       <SnippetType>Expansion</SnippetType>
      </SnippetTypes>
     </Header>
     <Snippet>
      <Declarations>
       <Literal>
        <ID>classname</ID>
        <ToolTip>The class name of the file</ToolTip>
        <Function>ClassName()</Function>
        <Default>ClassNamePlaceholder</Default>
       </Literal>
       <Literal>
        <ID>author</ID>
        <ToolTip>The developer who created the file.</ToolTip>
        <Default>hmeooran</Default>
       </Literal>
       <Literal>
        <ID>date</ID>
        <ToolTip>The date the file was created.</ToolTip>
        <Default>Now</Default>
       </Literal>   
       <Literal>
        <ID>company</ID>
        <ToolTip>The company who owns the class</ToolTip>
        <Default>YiTong.com</Default>
       </Literal>
      </Declarations>
      <Code Language="csharp">
       <![CDATA[
       //==============================
       //File:  $classname$.cs
       //Date:  $date$
       //Author: $author$
       //------------------------------
       //Description: This is a_u116?est file used to
       //    demonstrate Code Snippets
       //CopyRight:` (c)$company$
       //All Rights Reserved
       //History:  $date$ Created 
       //==============================
       ]]>
      </Code>
     </Snippet>
     </CodeSnippet>
    </CodeSnippets>
    编写完用visual studio8.0的代码段管理器将header.snippet加入My snippet code中,就可以在文件中使用了。