You've probably encountered such tests when signing up for an online email or forum account. The form might include an image of distorted text, like that seen above, which you are required to type into a text field.
The idea is to prevent spammers from using web bots to automatically post form data in order to create email accounts (for sending spam) or to submit feedback comments or guestbook entries containing spam messages. The text in the image is usually distorted to prevent the use of OCR (optical character reader) software to defeat the process. Hotmail, PayPal, Yahoo and a number of blog sites have employed this technique.
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Drawing.Text;
namespace CaptchaImage
{
/// <summary>
/// Summary description for CaptchaImage.
/// </summary>
public class CaptchaImage
{
// Public properties (all read-only).
public string Text
{
get { return this.text; }
}
public Bitmap Image
{
get { return this.image; }
}
public int Width
{
get { return this.width; }
}
public int Height
{
get { return this.height; }
}
// Internal properties.
private string text;
private int width;
private int height;
private string familyName;
private Bitmap image;
// For generating random numbers.
private Random random = new Random();
// =============================================================
// Initializes a new instance of the CaptchaImage class using the
// specified text, width and height.
//==============================================================
public CaptchaImage(string s, int width, int height)
{
this.text = s;
this.SetDimensions(width, height);
this.GenerateImage();
}
//===============================================================
// Initializes a new instance of the CaptchaImage class using the
// specified text, width, height and font family.
//===============================================================
public CaptchaImage(string s, int width, int height, string familyName)
{
this.text = s;
this.SetDimensions(width,height);
this.SetFamilyName(familyName);
this.GenerateImage();
}
//==============================================================
// This member overrides Object.Finalize.
//==============================================================
~CaptchaImage()
{
Dispose(false);
}
//============================================================
// Releases all resources used by this object.
//============================================================
public void Dispose()
{
GC.SuppressFinalize(this);
this.Dispose(true);
}
//===============================================================
// Custom Dispose method to clean up unmanaged resources.
//===============================================================
protected virtual void Dispose(bool disposing)
if (disposing)
// Dispose of the bitmap.
this.image.Dispose();
}
//=============================================================
// Sets the image width and height.
//=============================================================
private void SetDimensions(int width, int height)
{
// Check the width and height.
if (width <= 0)
throw new ArgumentOutOfRangeException("width",
width, "Argument out of range, must be greater than zero.");
if (width <= 0)
throw new ArgumentOutOfRangeException("height",
height, "Argument out of range, must be greater than zero.");
this.width = width;
this.height = height;
}
//=============================================================
// Sets the font used for the image text.
//=============================================================
private void SetFamilyName(string familyName)
{
// If the named font is not installed, default to a system font.
try
{
Font font = new
Font(this.familyName, 12F);
this.familyName = familyName;
font.Dispose();
}
catch (Exception ex)
{
this.familyName = System.Drawing.FontFamily.GenericSerif.Name;
}
}
//============================================================
// Creates the bitmap image.
//============================================================
private void GenerateImage()
{
// Create a new 32-bit bitmap image.
Bitmap bitmap = new
Bitmap(this.width, this.height, PixelFormat.Format32bppArgb);
// Create a graphics object for drawing.
Graphics g = Graphics.FromImage(bitmap);
g.SmoothingMode = SmoothingMode.AntiAlias;
Rectangle rect = new Rectangle(0, 0, this.width, this.height);
// Fill in the background.
//HatchStyle hs = (HatchStyle)Enum.Parse(typeof(HatchStyle), "0", true);
//HatchBrush hatchBrush = new HatchBrush(hs, Color.White, Color.White);
//HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti,
Color.LightGray, Color.White);
HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti,
Color.White, Color.White);
g.FillRectangle(hatchBrush, rect);
// Set up the text font.
SizeF size;
float fontSize = rect.Height + 2;
Font font;
// Adjust the font size until the text fits within the image.
do
{
fontSize--;
font = new Font(this.familyName, fontSize, FontStyle.Bold);
size = g.MeasureString(this.text, font);
} while (size.Width > rect.Width);
// Set up the text format.
StringFormat format = new StringFormat();
format.Alignment = StringAlignment.Center;
format.LineAlignment = StringAlignment.Center;
// Create a path using the text and warp it randomly.
GraphicsPath path = new GraphicsPath();
path.AddString(this.text, font.FontFamily, (int)font.Style,
font.Size, rect, format);
float v = 4F;
PointF[] points =
{
new PointF(this.random.Next(rect.Width) / v, this.random.Next(rect.Height) / v),new PointF(rect.Width - this.random.Next(rect.Width) / v, this.random.Next(rect.Height) / v),new PointF(this.random.Next(rect.Width) / v, rect.Height - this.random.Next(rect.Height) / v),new PointF(rect.Width - this.random.Next(rect.Width) / v, rect.Height - this.random.Next(rect.Height) / v)
};
Matrix matrix = new Matrix();
matrix.Translate(0F, 0F);
path.Warp(points, rect, matrix, WarpMode.Perspective, 0F);
// Draw the text.
hatchBrush = new HatchBrush(HatchStyle.Shingle,Color.Black,Color.Black);
g.FillPath(hatchBrush, path);
// Add some random noise.
int m = Math.Max(rect.Width, rect.Height);
for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++)
{
int x = this.random.Next(rect.Width);
int y = this.random.Next(rect.Height);
int w = this.random.Next(m / 50);
int h = this.random.Next(m / 50);
g.FillEllipse(hatchBrush, x, y, w, h);
}
// Clean up.
font.Dispose();
hatchBrush.Dispose();
g.Dispose();
// Set the image.
this.image = bitmap;
}
}
}
JpegImage.aspx
<%@ Page Language="C#" AutoEventWireup="false" Codebehind="JpegImage.aspx.cs" Inherits="CaptchaImage.JpegImage"
%>
"-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Jpeg Captcha Image</title>
<meta name="GENERATOR" content="Microsoft Visual
Studio 7.0" />
<meta name="CODE_LANGUAGE" content="C#" />
<meta name="vs_defaultClientScript" content="JavaScript"
/>
<meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5"
/>
</head>
<body>
<form id="JpegImage" method="post" runat="server">
</form>
</body>
</html>
JpegImage.aspx.cs
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Imaging;
using System.Web.SessionState;
namespace CaptchaImage
{
public partial class JpegImage : BasePage
{
protected void Page_Load(object sender, EventArgs e)
{
if (this.Session["CaptchaImageText"] != null)
{
// Create a CAPTCHA image using the text stored in the Session object.
CaptchaImage ci =
new CaptchaImage(this.Session["CaptchaImageText"].ToString(), 150, 20);//,"Century Schoolbook");
// Change the response headers to output a JPEG image.
this.Response.Clear();
this.Response.ContentType = "image/jpeg";
// Write the image to the response stream in JPEG format.
ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg);
// Dispose of the CAPTCHA image object.
ci.Dispose();
}
}
#region Web Form Designer generated code
override protected void OnInit(EventArgs e)
{
// CODEGEN: This call is required by the ASP.NET Web Form Designer.
InitializeComponent();
base.OnInit(e);
}
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.Load += new System.EventHandler(this.Page_Load);
}
#endregion
}
}
Default.aspx
<asp:Image ID="imgAntiSpam" runat="server" Width="100px" Height="20px" BorderWidth="1px" BorderColor="#7F9DB9" />
<asp:TextBox ID="txtAntiSpam" runat="server" ToolTip="Anti-Spam" Width="47px" AutoCompleteType="disabled"></asp:TextBox>
protected void Page_Load(object sender, EventArgs e)
{
this.Session["CaptchaImageText"] = GenerateRandomCode();
imgAntiSpam.ImageUrl = "~/jpegImage.aspx";
}
private string GenerateRandomCode()
{
#region Random 1
Random objRandom = new Random();
StringBuilder returnStr = new StringBuilder();
string key = "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789";
char[] keylist = key.ToCharArray();
for (int intcnt = 0; intcnt < 4; intcnt++)//Numher of character
{
returnStr.Append(keylist[objRandom.Next(keylist.Length)]);
//temppwd += objRandom.Next(keylist.Length);
}
//return returnStr;
#endregion
#region Random 1
//string s1 = string.Empty;
//string s2 = string.Empty;
//for (int i = 0; i < 1; i++)
//{
// s1 = String.Concat(s1, this.random.Next(10).ToString());
// s2 = String.Concat(s2, this.random.Next(10).ToString());
//}
//int Sum = (int.Parse(s1) + int.Parse(s2));
//string returnStr = string.Empty;
//if (Sum % 2 == 0)
//{
// Sum = (int.Parse(s1) * int.Parse(s2));
// returnStr = s1 + " X " + s2 + " = ";
//}
//else
//{
// Sum = (int.Parse(s1) + int.Parse(s2));
// returnStr = s1 + " + " + s2 + " = ";
//}
//Session["CaptchaImageTextSum"] = Sum.ToString();
//return returnStr;
#endregion
Session["CaptchaImageTextSum"] = returnStr.ToString();
imgAntiSpam.ToolTip = returnStr.ToString();
returnStr.ToString();
}
Any Event
if (txtAntiSpam.Text.ToString().Equals(Session["CaptchaImageTextSum"].ToString()))
{
//true
}
For more http://www.codeproject.com/KB/aspnet/CaptchaImage.aspx