【困惑】生成验证码图片,怎么才能做到只扭曲验证码字符而不扭曲背景呢?

云想慕尘 2008-09-24 09:48:58
由于帖子内容长度限制不能贴出具体请到本人博客

验证码字符个数、生成图片宽度、高度自定均可由构造方法自定,无参构造生成默认字符个数和默认大小的Image,方法 GetImgWithValidateCode()返回生成的验证码图片,方法 IsRight(string inputValCode) 判断用户输入的验证码 inputValCode与图片显示的字符是否一致,不区分大小写
出问题了,在调用方法TwistImage(Bitmap srcBmp, bool bXDir, double dMultValue, double dPhase)后,整个图片都扭曲了,从而导致图片边缘出现黑色区域,怎么才能做到只扭曲验证码字符而不扭曲背景呢?我知道要先扭曲字符所在图片,然后再和背景叠加,具体怎么才能做到呢?

namespace DrawValidateImageLib
{
public class DrawValImg
{


/// <summary>
/// 由随机字符串,随即颜色背景,和随机线条产生的Image
/// </summary>
/// <returns>Image</returns>
public Image GetImgWithValidateCode()//返回 Image
{
//产生随机字符串
GetValidateCode();

//声明一个位图对象
Bitmap bitMap = null;
//声明一个绘图画面
Graphics gph = null;
//创建内存流
MemoryStream memStream = new MemoryStream();

Random random = new Random();

//由给定的需要生成字符串中字符个数 CharNum, 图片宽度 Width 和高度 Height 确定字号 FontSize,
//确保不因字号过大而不能全部显示在图片上
int fontWidth=(int)Math.Round(width/(charNum+2)/1.3);
int fontHeight=(int)Math.Round(height/1.5);
//字号取二者中小者,以确保所有字符能够显示,并且字符的下半部分也能显示
fontSize = fontWidth <= fontHeight ? fontWidth : fontHeight;

//创建位图对象
bitMap = new Bitmap(width+FontSize,height);
//根据上面创建的位图对象创建绘图图面
gph = Graphics.FromImage(bitMap);

//设定验证码图片背景色
gph.Clear(GetControllableColor(200));
//产生随机干扰线条
for (int i = 0; i < 10; i++)
{
Pen backPen = new Pen(GetControllableColor(100), 2);
//线条起点
int x = random.Next(width);
int y = random.Next(height);
//线条终点
int x2 = random.Next(width);
int y2 = random.Next(height);
//划线
gph.DrawLine(backPen, x, y, x2, y2);
}

//定义一个含10种字体的数组
String[] fontFamily ={ "Arial", "Verdana", "Comic Sans MS", "Impact", "Haettenschweiler",
"Lucida Sans Unicode", "Garamond", "Courier New", "Book Antiqua", "Arial Narrow" };
SolidBrush sb = new SolidBrush(GetControllableColor(0));
//通过循环,绘制每个字符,
for (int i = 0; i < validStr.Length; i++)
{
Font textFont = new Font(fontFamily[random.Next(10)], fontSize, FontStyle.Bold);//字体随机,字号大小30,加粗

//每次循环绘制一个字符,设置字体格式,画笔颜色,字符相对画布的X坐标,字符相对画布的Y坐标
int space = (int)Math.Round((double)((width - fontSize * (CharNum + 2)) / CharNum));
//纵坐标
int y = (int)Math.Round((double)((height - fontSize)/3));
gph.DrawString(validStr.Substring(i, 1), textFont, sb, fontSize + i * (fontSize + space), y);
}
[color=#FF6600]//扭曲图片
bitMap=TwistImage(bitMap, true, random.Next(3,5),random.Next(3));


try
{

bitMap.Save(memStream, ImageFormat.Gif);

}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message);
}
//gph.Dispose();
bitMap.Dispose();

Image img = Image.FromStream(memStream);
gph.DrawImage(img, 50, 20, width, 10);

return img;
}
/// <summary>
/// 产生一种 R,G,B 均大于 colorBase 随机颜色,以确保颜色不会过深
/// </summary>
/// <returns>背景色</returns>
Color GetControllableColor(int colorBase)
{
Color color=Color.Black;
if (colorBase > 200)
{
System.Windows.Forms.MessageBox.Show("可控制颜色参数大于200,颜色默认位黑色");
}
Random random = new Random();
//确保 R,G,B 均大于 colorBase,这样才能保证背景色较浅
color= Color.FromArgb(random.Next(56) + colorBase, random.Next(56) + colorBase, random.Next(56) + colorBase);
return color;
}

/// <summary>
/// 扭曲图片
/// </summary>
/// <param name="srcBmp"></param>
/// <param name="bXDir"></param>
/// <param name="dMultValue"></param>
/// <param name="dPhase"></param>
/// <returns></returns>
Bitmap TwistImage(Bitmap srcBmp, bool bXDir, double dMultValue, double dPhase)
{
int leftMargin = 0;
int rightMargin = 0;
int topMargin = 0;
int bottomMargin = 0;
//float PI = 3.14159265358979f;
float PI2 = 6.28318530717959f;
Bitmap destBmp = new Bitmap(srcBmp.Width, srcBmp.Height);
double dBaseAxisLen = bXDir ? Convert.ToDouble(destBmp.Height) : Convert.ToDouble(destBmp.Width);
for (int i = 0; i < destBmp.Width; i++)
{
for (int j = 0; j < destBmp.Height; j++)
{
double dx = 0;
dx = bXDir ? PI2 * Convert.ToDouble(j) / dBaseAxisLen : PI2 * Convert.ToDouble(i) / dBaseAxisLen;
dx += dPhase;
double dy = Math.Sin(dx);

//取得当前点的颜色
int nOldX = 0;
int nOldY = 0;
nOldX = bXDir ? i + Convert.ToInt32(dy * dMultValue) : i;
nOldY = bXDir ? j : j + Convert.ToInt32(dy * dMultValue);
System.Drawing.Color color = srcBmp.GetPixel(i, j);
if (nOldX >= leftMargin && nOldX < destBmp.Width - rightMargin && nOldY >= bottomMargin && nOldY < destBmp.Height - topMargin)
{
destBmp.SetPixel(nOldX, nOldY, color);
}
}
}
return destBmp;
}

/// <summary>
/// 判断验证码是否正确
/// </summary>
/// <param name="inputValCode">待判断的验证码</param>
/// <returns>正确返回 true,错误返回 false</returns>
public bool IsRight(string inputValCode)
{

if (validStr.ToUpper().Equals(inputValCode.ToUpper()))//无论输入大小写都转换为大些判断
{
return true;
}
else
{
return false;
}
}

}
}
...全文
459 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
云想慕尘 2008-09-30
  • 打赏
  • 举报
回复
还是不行呀老兄,能不能再我源码里面帮着改改!
云想慕尘 2008-09-26
  • 打赏
  • 举报
回复
[COLOR=#FF0000]哪位老兄能搞定呀,帮着看看呀,急用!![/COLOR]
danjiewu 2008-09-26
  • 打赏
  • 举报
回复

Bitmap image = new Bitmap(pictureBox1.Width, pictureBox1.Height, pictureBox1.CreateGraphics());
Graphics.FromImage(image).DrawString("验证码", xx, xx, xx, xx);
image = TwistImage(image , xx, xx, xx)
pictureBox1.Refresh();
pictureBox1.CreateGraphics().DrawImage(image, 0, 0);
//Graphics.FromImage(pictureBox1.BackgroundImage).DrawImage(image, 0, 0);看你自己需要
云想慕尘 2008-09-25
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 danjiewu 的回复:]
先DrawString到一个空白图片中,然后扭曲
然后把扭曲的图片DrawImage到背景图片中

[/Quote]


还是没能解决,老兄有时间的话帮这搞搞吧!谢啦先
danjiewu 2008-09-25
  • 打赏
  • 举报
回复
先DrawString到一个空白图片中,然后扭曲
然后把扭曲的图片DrawImage到背景图片中
云想慕尘 2008-09-25
  • 打赏
  • 举报
回复
忙了一天累死了,刚上来,我试试去!多谢了先
云想慕尘 2008-09-24
  • 打赏
  • 举报
回复
谢谢,最好帮解决小问题!O(∩_∩)O哈哈~
Zoonware 2008-09-24
  • 打赏
  • 举报
回复
帮顶了....

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧