大大毛 的筆記

            DDM's Note

          哪怕沒有辦法一定有說法,
          就算沒有鴿子一定有烏鴉,
          固執(zhí)無罪 夢想有價,
          讓他們驚訝.

          posts - 14, comments - 23, trackbacks - 0, articles - 58
             :: 首頁 ::  :: 聯(lián)系 ::  :: 管理

          生成隨機(jī)碼檢驗(yàn)圖片

          Posted on 2006-08-22 03:00 大大毛 閱讀(756) 評論(0)  編輯  收藏 所屬分類: ASP.NET

          ???網(wǎng)頁中需要用到這樣的功能,參照網(wǎng)上的介紹,做了一個放在這里備查。
          ???效果圖:t_Default7.JPG

          ???為了方便調(diào)用,寫成了一個類(RandomCodeImage.cs)。

          using ?System;
          using ?System.Drawing;

          /// ? <summary>
          /// ?隨機(jī)檢驗(yàn)碼圖像模糊度
          /// ? </summary>

          public ? enum ?RandomCodeImageMistily? {
          ????None?
          = ? 0 ,
          ????General,
          ????Deep
          }


          /// ? <summary>
          /// ?生成隨機(jī)校驗(yàn)碼圖象
          /// ?ddm,2006-8-22
          /// ? </summary>

          public ? class ?RandomCodeImage? {
          ????
          // 隨機(jī)數(shù)
          ????Random?random? = ? null ;
          ????
          // 字體
          ???? private ? string ?fontName? = ? null ;
          ????
          // 字體大小
          ???? private ? int ?fontSize? = ? 0 ;
          ????
          // 校驗(yàn)碼長度
          ???? private ? int ?codeLength? = ? 0 ;
          ????
          // 間距
          ???? private ? int ?codeSpace? = ? 0 ;
          ????
          // 校驗(yàn)碼
          ???? private ? string ?code? = ? null ;
          ????
          // 字體
          ???? private ?Font?font? = ? null ;
          ????
          // 模糊度
          ???? private ?RandomCodeImageMistily?mistily? = ?RandomCodeImageMistily.General;

          ????
          public ?RandomCodeImage()? {
          ????????
          this .random? = ? new ?Random();
          ????????
          this .fontName? = ? " Arial " ;
          ????????
          this .fontSize? = ? 12 ;
          ????????
          this .codeLength? = ? 4 ;
          ????????
          this .codeSpace? = ? 0 ;
          ????}

          ????
          /// ? <summary>
          ????
          /// ?設(shè)置/獲取字體
          ????
          /// ? </summary>

          ???? public ? string ?FontName? {
          ????????
          get ? {
          ????????????
          return ? this .fontName;
          ????????}

          ????????
          set ? {
          ????????????
          this .fontName? = ?value;
          ????????}

          ????}

          ????
          /// ? <summary>
          ????
          /// ?設(shè)置/獲取字體大小
          ????
          /// ? </summary>

          ???? public ? int ?FontSize? {
          ????????
          get ? {
          ????????????
          return ? this .fontSize;
          ????????}

          ????????
          set ? {
          ????????????
          this .fontSize? = ?value;
          ????????}

          ????}

          ????
          /// ? <summary>
          ????
          /// ?設(shè)置/獲取校驗(yàn)碼的長度
          ????
          /// ? </summary>

          ???? public ? int ?CodeLength? {
          ????????
          get ? {
          ????????????
          return ? this .codeLength;
          ????????}

          ????????
          set ? {
          ????????????
          this .codeLength? = ?value;
          ????????}

          ????}

          ????
          /// ? <summary>
          ????
          /// ?設(shè)置/獲取檢驗(yàn)碼的間距
          ????
          /// ? </summary>

          ???? public ? int ?CodeSpace? {
          ????????
          get ? {
          ????????????
          return ? this .codeSpace;
          ????????}

          ????????
          set ? {
          ????????????
          this .codeSpace? = ?value;
          ????????}

          ????}

          ????
          /// ? <summary>
          ????
          /// ?設(shè)置/獲取檢驗(yàn)碼
          ????
          /// ? </summary>

          ???? public ? string ?Code? {
          ????????
          get ? {
          ????????????
          if ?( this .code? == ? null )? {
          ????????????????
          // 生成檢驗(yàn)碼
          ???????????????? this .code? = ? this .createRandomCode();
          ????????????}

          ????????????
          return ? this .code;
          ????????}

          ????????
          set ? {
          ????????????
          this .code? = ?value;
          ????????}

          ????}

          ????
          public ?RandomCodeImageMistily?Mistily? {
          ????????
          set ? {
          ????????????
          this .mistily? = ?value;
          ????????}

          ????}


          ????
          /// ? <summary>
          ????
          /// ?獲取檢驗(yàn)碼生成的圖像
          ????
          /// ? </summary>

          ???? public ?System.Drawing.Bitmap?getCodeImage()? {

          ????????
          if ?( this .code? == ? null )? {
          ????????????
          // 生成檢驗(yàn)碼
          ???????????? this .code? = ? this .createRandomCode();
          ????????}



          ????????
          return ? this .createCodeImage();
          ????}

          ????
          /// ? <summary>
          ????
          /// ?獲取檢驗(yàn)碼生成的圖像
          ????
          /// ? </summary>
          ????
          /// ? <param?name="mistily"> 輸出圖像的模糊度 </param>

          ???? public ?System.Drawing.Bitmap?getCodeImage(RandomCodeImageMistily?mistily)? {
          ????????
          this .mistily? = ?mistily;
          ????????
          return ? this .getCodeImage();
          ????}


          ????
          /// ? <summary>
          ????
          /// ?創(chuàng)建隨機(jī)檢驗(yàn)碼
          ????
          /// ? </summary>

          ???? protected ? string ?createRandomCode()? {
          ????????System.Text.StringBuilder?codeBuilder?
          = ? new ?System.Text.StringBuilder();

          ????????
          int ?ascii? = ? 0 ;
          ????????
          for ?( int ?i? = ? 0 ;?i? < ? this .codeLength;?i ++ )? {
          ????????????
          // 0-9,A-Z一共36個
          ????????????ascii? = ? this .random.Next()? % ? 36 ;

          ????????????
          if ?(ascii? < ? 10 )? {
          ????????????????
          // 數(shù)字
          ????????????????ascii? += ? 48 ;
          ????????????}
          ? else ? {
          ????????????????
          // 大寫字母
          ????????????????ascii? += ? 55 ;
          ????????????}


          ????????????codeBuilder.Append((
          char )ascii);
          ????????}

          ????????
          return ?codeBuilder.ToString();
          ????}

          ????
          /// ? <summary>
          ????
          /// ?創(chuàng)建代碼圖像
          ????
          /// ? </summary>

          ???? private ?System.Drawing.Bitmap?createCodeImage()? {
          ????????Bitmap?tmpImage?
          = ? null ,?resultImage? = ? null ;
          ????????Graphics?tmpG?
          = ? null ,?resultG? = ? null ;
          ????????
          float ?charWidth? = ?0f,?charHeight? = ?0f;
          ????????
          int ?imageWidth? = ? 0 ,?imageHeight? = ? 0 ;
          ????????SizeF?size?
          = ?SizeF.Empty;
          ????????
          // 噪音
          ???????? int ?noiseNum? = ? 0 ;

          ????????
          // 生成字體
          ???????? this .font? = ? new ?Font( this .fontName,? this .fontSize,?(FontStyle.Bold? | ?FontStyle.Italic),?GraphicsUnit.Point);

          ????????
          using ?(tmpImage? = ? new ?Bitmap( 1 ,? 1 ))? {
          ????????????
          using ?(tmpG? = ?Graphics.FromImage(tmpImage))? {
          ????????????????
          // 獲得code的輸出寬度
          ???????????????? for ?( int ?i? = ? 0 ;?i? < ? this .code.Length;?i ++ )? {

          ????????????????????size?
          = ?tmpG.MeasureString(code.Substring(i,? 1 ),?font);
          ????????????????????charWidth?
          += ?size.Width;
          ????????????????????charHeight?
          = ?Math.Max(charHeight,?size.Height);

          ????????????????}

          ????????????}

          ????????}

          ????????
          // 輸出字符的大小
          ????????imageWidth? = ?( int )Math.Ceiling(charWidth);
          ????????imageHeight?
          = ?( int )Math.Ceiling(charHeight);
          ????????
          // 加入間距
          ????????imageWidth? = ?imageWidth? + ? this .code.Length? * ? this .codeSpace? + ? this .codeSpace;
          ????????imageHeight?
          = ?imageHeight? + ? 2 ? * ? this .codeSpace;
          ????????
          // 生成輸出圖像
          ????????resultImage? = ? new ?Bitmap(imageWidth,?imageHeight);
          ????????
          // 畫刷,線性顏色漸變畫刷,渲染區(qū)域是整個圖片,從Blue漸變到Pruple,從X軸方面1.2弧度,漸變受角度影響
          ????????Brush?brush? = ? new ?System.Drawing.Drawing2D.LinearGradientBrush( new ?Rectangle( 0 ,? 0 ,?resultImage.Width,?resultImage.Height),?Color.Blue,?Color.Purple,? 1.2f ,? true );
          ????????
          using ?(resultG? = ?Graphics.FromImage(resultImage))? {
          ????????????
          // 填充背景色
          ????????????resultG.Clear(Color.White);
          ????????????
          // resultG.TextRenderingHint?=?System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;

          ????????????
          switch ?( this .mistily)? {
          ????????????????
          case ?RandomCodeImageMistily.Deep:
          ????????????????????noiseNum?
          = ?resultImage.Width? * ?resultImage.Height? / ? 30 ;
          ????????????????????
          break ;
          ????????????????
          case ?RandomCodeImageMistily.General:
          ????????????????????noiseNum?
          = ?resultImage.Width? * ?resultImage.Height? / ? 50 ;
          ????????????????????
          break ;
          ????????????????
          default :
          ????????????????????noiseNum?
          = ? 0 ;
          ????????????????????
          break ;
          ????????????}


          ????????????
          // 畫背景噪音線
          ???????????? for ?( int ?i? = ? 0 ;?i? < ?noiseNum;?i ++ )? {
          ????????????????
          // 隨機(jī)坐標(biāo)
          ???????????????? int ?x1? = ?random.Next(resultImage.Width);
          ????????????????
          int ?x2? = ?random.Next(resultImage.Width);
          ????????????????
          int ?y1? = ?random.Next(resultImage.Height);
          ????????????????
          int ?y2? = ?random.Next(resultImage.Height);
          ????????????????
          // 畫噪音線
          ????????????????resultG.DrawLine( new ?Pen(Color.Silver),?x1,?y1,?x2,?y2);
          ????????????}


          ????????????
          // 畫背景噪音點(diǎn)
          ???????????? for ?( int ?i? = ? 0 ;?i? < ?noiseNum? * ? 20 ;?i ++ )? {
          ????????????????
          // 隨機(jī)坐標(biāo)
          ???????????????? int ?x? = ?random.Next(resultImage.Width);
          ????????????????
          int ?y? = ?random.Next(resultImage.Height);
          ????????????????
          // 畫噪音點(diǎn)
          ????????????????resultG.DrawEllipse( new ?Pen(Color.FromArgb(random.Next())),?x,?y,? 1 ,? 1 );
          ????????????}

          ????????????
          // 輸出字符
          ????????????charWidth? = ?charHeight? = ? this .codeSpace;
          ????????????
          for ?( int ?i? = ? 0 ;?i? < ? this .code.Length;?i ++ )? {
          ????????????????resultG.DrawString(
          this .code.Substring(i,? 1 ),?font,?brush,?charWidth,?charHeight);
          ????????????????
          // 起始X坐標(biāo)
          ????????????????charWidth? = ?charWidth? + ?resultG.MeasureString( this .code.Substring(i,? 1 ),?font).Width? + ? this .codeSpace;
          ????????????}


          ????????????
          // 畫圖片邊框
          ????????????resultG.DrawRectangle( new ?Pen(Color.SaddleBrown),? 0 ,? 0 ,?resultImage.Width? - ? 1 ,?resultImage.Height? - ? 1 );
          ????????}

          ????????
          return ?resultImage;
          ????}

          }


          ???該類實(shí)現(xiàn)功能
          ??????能夠返回一個隨機(jī)碼檢驗(yàn)圖片(Image對象),這樣可以進(jìn)行第2次處理。
          ??????屬性
          ??????FontName,字體;
          ??????FontSize,字體大小(point);
          ??????CodeLength,隨機(jī)生成的檢驗(yàn)碼長度;
          ??????CodeSpace,字間距;
          ??????Code,校驗(yàn)碼,如果通過setter設(shè)置了該屬性,則類不會隨機(jī)生成新的檢驗(yàn)碼;
          ??????Mistily,模糊度,效果不是很好。

          ???在ASP頁面中(例ShowCodeImage.aspx)調(diào)用類:
          ????protected?void?Page_Load(object?sender,?EventArgs?e)
          ????{
          ????????
          //初始化類
          ????????RandomCodeImage?r?=?new?RandomCodeImage();
          ????????
          //設(shè)置字體大小
          ????????r.FontSize?=?10;
          ????????
          //r.FontName?=?"Times?Now?Roman";
          ????????
          //設(shè)置字間距
          ????????r.CodeSpace?=?2;
          ????????
          //獲取圖像
          ????????System.Drawing.Image?image?=?r.getCodeImage();
          ????????
          //輸出圖像
          ????????System.IO.MemoryStream?ms?=?new?System.IO.MemoryStream();
          ????????image.Save(ms,?System.Drawing.Imaging.ImageFormat.Png);
          ????????image.Dispose();
          ????????Response.ContentType?
          =?"image/Png";
          ????????Response.BinaryWrite(ms.ToArray());

          ????????
          //將code放入Session或Cokie用于提交檢驗(yàn)
          ????????Session.Add("ddm",?r.Code);
          ????}

          ???最后在最終需要顯示的ASP頁面中加以引用:
          <img?src="ShowCodeImage.aspx"?alt="驗(yàn)證圖片"/>

          ???后記:
          ??????在計(jì)算字符輸出寬度時遇到了麻煩,輸出時經(jīng)常不對頭,直到逐步的拆解代碼才找到原因。MS在輸出字符時,由于各個字符是不等寬的(比如 I 就比較窄),因此在輸出時必須先用 Graphics.MeasureString() 方法來計(jì)算寬度,但是實(shí)際上采用不同的輸出方式得到的結(jié)果是不同的。如:1.在輸出時采用一次性輸出整個字符串;2.逐個字符的輸出。可以發(fā)現(xiàn)各字符的輸出寬度之和 要遠(yuǎn)大于 整個字符串的輸出寬度,如果沒有考慮到這點(diǎn)就容易產(chǎn)生輸出無法定位的情況。

          i am ddm

          主站蜘蛛池模板: 宜春市| 阜平县| 栖霞市| 白水县| 乐昌市| 定日县| 洮南市| 平顶山市| 云安县| 四会市| 双流县| 托克逊县| 伊吾县| 东光县| 仲巴县| 菏泽市| 屯留县| 千阳县| 萍乡市| 北辰区| 阳朔县| 昌黎县| 炎陵县| 卓资县| 泸溪县| 武安市| 田林县| 吴忠市| 团风县| 会泽县| 盘山县| 蚌埠市| 佛山市| 青铜峡市| 昌黎县| 库伦旗| 徐州市| 梅河口市| 华容县| 竹溪县| 广州市|