|
Posted on 2006-08-22 03:00 大大毛 閱讀(755) 評論(0) 編輯 收藏 所屬分類: ASP.NET
???網頁中需要用到這樣的功能,參照網上的介紹,做了一個放在這里備查。 ???效果圖:
???為了方便調用,寫成了一個類(RandomCodeImage.cs)。
using
?System;
using
?System.Drawing;


/**/
///
?
<summary>
///
?隨機檢驗碼圖像模糊度
///
?
</summary>
public
?
enum
?RandomCodeImageMistily?
{
????None?
=
?
0
,
????General,
????Deep
}
/**/
///
?
<summary>
///
?生成隨機校驗碼圖象
///
?ddm,2006-8-22
///
?
</summary>
public
?
class
?RandomCodeImage?
{
????
//
隨機數
????Random?random?
=
?
null
;
????
//
字體
????
private
?
string
?fontName?
=
?
null
;
????
//
字體大小
????
private
?
int
?fontSize?
=
?
0
;
????
//
校驗碼長度
????
private
?
int
?codeLength?
=
?
0
;
????
//
間距
????
private
?
int
?codeSpace?
=
?
0
;
????
//
校驗碼
????
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>
????
///
?設置/獲取字體
????
///
?
</summary>
????
public
?
string
?FontName?
{
 ????????
get
?
{
????????????
return
?
this
.fontName;
????????}
????????
set
?
{
????????????
this
.fontName?
=
?value;
????????}
????}
????
/**/
///
?
<summary>
????
///
?設置/獲取字體大小
????
///
?
</summary>
????
public
?
int
?FontSize?
{
 ????????
get
?
{
????????????
return
?
this
.fontSize;
????????}
????????
set
?
{
????????????
this
.fontSize?
=
?value;
????????}
????}
????
/**/
///
?
<summary>
????
///
?設置/獲取校驗碼的長度
????
///
?
</summary>
????
public
?
int
?CodeLength?
{
 ????????
get
?
{
????????????
return
?
this
.codeLength;
????????}
????????
set
?
{
????????????
this
.codeLength?
=
?value;
????????}
????}
????
/**/
///
?
<summary>
????
///
?設置/獲取檢驗碼的間距
????
///
?
</summary>
????
public
?
int
?CodeSpace?
{
 ????????
get
?
{
????????????
return
?
this
.codeSpace;
????????}
????????
set
?
{
????????????
this
.codeSpace?
=
?value;
????????}
????}
????
/**/
///
?
<summary>
????
///
?設置/獲取檢驗碼
????
///
?
</summary>
????
public
?
string
?Code?
{
 ????????
get
?
{
 ????????????
if
?(
this
.code?
==
?
null
)?
{
????????????????
//
生成檢驗碼
????????????????
this
.code?
=
?
this
.createRandomCode();
????????????}
????????????
return
?
this
.code;
????????}
????????
set
?
{
????????????
this
.code?
=
?value;
????????}
????}
????
public
?RandomCodeImageMistily?Mistily?
{
 ????????
set
?
{
????????????
this
.mistily?
=
?value;
????????}
????}
????
/**/
///
?
<summary>
????
///
?獲取檢驗碼生成的圖像
????
///
?
</summary>
????
public
?System.Drawing.Bitmap?getCodeImage()?
{

 ????????
if
?(
this
.code?
==
?
null
)?
{
????????????
//
生成檢驗碼
????????????
this
.code?
=
?
this
.createRandomCode();
????????}
????????
return
?
this
.createCodeImage();
????}
????
/**/
///
?
<summary>
????
///
?獲取檢驗碼生成的圖像
????
///
?
</summary>
????
///
?
<param?name="mistily">
輸出圖像的模糊度
</param>
????
public
?System.Drawing.Bitmap?getCodeImage(RandomCodeImageMistily?mistily)?
{
????????
this
.mistily?
=
?mistily;
????????
return
?
this
.getCodeImage();
????}
????
/**/
///
?
<summary>
????
///
?創建隨機檢驗碼
????
///
?
</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
)?
{
????????????????
//
數字
????????????????ascii?
+=
?
48
;
 ????????????}
?
else
?
{
????????????????
//
大寫字母
????????????????ascii?
+=
?
55
;
????????????}
????????????codeBuilder.Append((
char
)ascii);
????????}
????????
return
?codeBuilder.ToString();
????}
????
/**/
///
?
<summary>
????
///
?創建代碼圖像
????
///
?
</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);
????????
//
畫刷,線性顏色漸變畫刷,渲染區域是整個圖片,從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
++
)?
{
????????????????
//
隨機坐標
????????????????
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);
????????????}
????????????
//
畫背景噪音點
????????????
for
?(
int
?i?
=
?
0
;?i?
<
?noiseNum?
*
?
20
;?i
++
)?
{
????????????????
//
隨機坐標
????????????????
int
?x?
=
?random.Next(resultImage.Width);
????????????????
int
?y?
=
?random.Next(resultImage.Height);
????????????????
//
畫噪音點
????????????????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坐標
????????????????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;
????}
}
???該類實現功能: ??????能夠返回一個隨機碼檢驗圖片(Image對象),這樣可以進行第2次處理。 ??????屬性: ??????FontName,字體; ??????FontSize,字體大小(point); ??????CodeLength,隨機生成的檢驗碼長度; ??????CodeSpace,字間距; ??????Code,校驗碼,如果通過setter設置了該屬性,則類不會隨機生成新的檢驗碼; ??????Mistily,模糊度,效果不是很好。
???在ASP頁面中(例ShowCodeImage.aspx)調用類:
????protected?void?Page_Load(object?sender,?EventArgs?e) ????{ ????????//初始化類 ????????RandomCodeImage?r?=?new?RandomCodeImage(); ????????//設置字體大小 ????????r.FontSize?=?10; ????????//r.FontName?=?"Times?Now?Roman"; ????????//設置字間距 ????????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用于提交檢驗 ????????Session.Add("ddm",?r.Code); ????}
???最后在最終需要顯示的ASP頁面中加以引用:
<img?src="ShowCodeImage.aspx"?alt="驗證圖片"/> ???后記: ??????在計算字符輸出寬度時遇到了麻煩,輸出時經常不對頭,直到逐步的拆解代碼才找到原因。MS在輸出字符時,由于各個字符是不等寬的(比如 I 就比較窄),因此在輸出時必須先用 Graphics.MeasureString() 方法來計算寬度,但是實際上采用不同的輸出方式得到的結果是不同的。如:1.在輸出時采用一次性輸出整個字符串;2.逐個字符的輸出。可以發現各字符的輸出寬度之和 要遠大于 整個字符串的輸出寬度,如果沒有考慮到這點就容易產生輸出無法定位的情況。
|