Click here to Skip to main content
Click here to Skip to main content

Captcha Image using C# in ASP.NET

By , 22 Mar 2011
 

Download CaptchaImage.zip - 131.44 KB

What is Captcha Image? 

Source:DotNet Stuff   

done.JPG 

If both match then displays above message 

notvalid.JPG

If both doesn't match then display above message 

In the web, whenever you register on any site, normally they ask at the end of page for entering Image code/Challenge Image/Image verification code, etc. This type of image is called Captcha Image.

What is the Use of Captcha?

(Source: http://en.wikipedia.org/wiki/Captcha)

Captcha is a type of challenge-response test used in computing to ensure that the response is not generated by a computer. The process usually involves one computer (a server) asking a user to complete a simple test which the computer is able to generate and grade. Because other computers are unable to solve the CAPTCHA, any user entering a correct solution is presumed to be human.

A best technique to restrict automatic form submissions when developing a web page is to add some kind of verification. As per my knowledge, image verification is the best way, it’s also called Captcha image. In this process, dynamically we are creating an image with random string either string, number or alphanumeric and displaying it on the web page. After that, at the time of form submission, the user is asked to enter the same code in the text box as shown in that image. Once the form is submitted, then we can compare both auto generated value and entered by user because there is no other good way to protect your webworms from spammers (auto submission).

How Can We Do That?

Here is the detailed explanation with code snippets.

This is the default.aspx (partially):

<asp:Label ID="lblmsg" runat="server" Font-Bold="True" 
	ForeColor="Red" Text=""></asp:Label>
         <br />
    </div>
    <asp:TextBox ID="txtimgcode" runat="server"></asp:TextBox>
    <br />
    <asp:Image ID="Image1" runat="server" ImageUrl="~/CImage.aspx"/>
    <br />
    <asp:Button ID="Button1" runat="server" onclick="Button1_Click" Text="Button" />

In the above code, there are three control Label controls to display message whether entered code is matched or not, TextBox to take input from user and Image box to hold an image autogenerated by CImage.aspx page. Before that, we will see default.aspx.cs page code:

protected void Button1_Click(object sender, EventArgs e)
    {
        if (this.txtimgcode.Text == this.Session["CaptchaImageText"].ToString())
        {
            lblmsg.Text = "Excellent.......";
        }
        else
        {
            lblmsg.Text = "image code is not valid.";
        }
        this.txtimgcode.Text = "";
    }

In button’s click event, we are just checking entered value with stored value in session. And we display the appropriate message on the screen.

CImage.aspx Page

Remove all the code except the first line.

The main code is here which is calling a method to generate random number string and passes it to the class file which will generate image with the same string and return it as a JPEG format.

Here are the details of the code:

using System.Drawing.Imaging;
public partial class CImage : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        // Create a random code and store it in the Session object.
        this.Session["CaptchaImageText"] = GenerateRandomCode();
        // Create a CAPTCHA image using the text stored in the Session object.
        RandomImage ci = new RandomImage(this.Session
			["CaptchaImageText"].ToString(), 300, 75);
        // 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();
    }
   
    // Function to generate random string with Random class.
    private string GenerateRandomCode()
    {
        Random r = new Random();
        string s = "";
        for (int j = 0; j < 5;j++)
        {
            int i = r.Next(3);
            int ch;
            switch (i)
            {
                case 1:
                    ch = r.Next(0, 9);
                    s = s + ch.ToString();
                    break;
                case 2:
                    ch = r.Next(65, 90);
                    s = s + Convert.ToChar(ch).ToString();
                    break;
                case 3:
                    ch = r.Next(97, 122);
                    s = s + Convert.ToChar(ch).ToString();
                    break;
                default:
                    ch = r.Next(97, 122);
                    s = s + Convert.ToChar(ch).ToString();
                    break;
            }
            r.NextDouble();
            r.Next(100, 1999);
        }
        return s;
    }
}

And finally, the code for RandomImage class which generates Image with the help of BitMap class.

//Extra name space
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Drawing.Text;
public class RandomImage
{
//Default Constructor 
      public RandomImage(){}
//property
      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; }
    }
//Private variable
    private string text;
    private int width;
    private int height;
    private Bitmap image;
    private Random random = new Random();
    //Methods declaration
    public RandomImage(string s, int width, int height)
    {
          this.text = s;
          this.SetDimensions(width, height);
          this.GenerateImage();
    }
    public void Dispose()
    {
        GC.SuppressFinalize(this);
        this.Dispose(true);
    }
    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
            this.image.Dispose();
    }
    private void SetDimensions(int width, int height)
    {
          if (width <= 0)
                throw new ArgumentOutOfRangeException("width", width, 
                    "Argument out of range, must be greater than zero.");
          if (height <= 0)
                throw new ArgumentOutOfRangeException("height", height, 
                    "Argument out of range, must be greater than zero.");
          this.width = width;
          this.height = height;
    }
    private void GenerateImage()
    {
          Bitmap bitmap = new Bitmap
			(this.width, this.height, PixelFormat.Format32bppArgb);
          Graphics g = Graphics.FromImage(bitmap);
          g.SmoothingMode = SmoothingMode.AntiAlias;
          Rectangle rect = new Rectangle(0, 0, this.width, this.height);
          HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti,
              Color.LightGray, Color.White);
          g.FillRectangle(hatchBrush, rect);
          SizeF size;
          float fontSize = rect.Height + 1;
        Font font;
        
          do
          {
                fontSize--;
            font = new Font(FontFamily.GenericSansSerif, fontSize, FontStyle.Bold);
                size = g.MeasureString(this.text, font);
          } while (size.Width > rect.Width);
          StringFormat format = new StringFormat();
          format.Alignment = StringAlignment.Center;
          format.LineAlignment = StringAlignment.Center;
          GraphicsPath path = new GraphicsPath();
          //path.AddString(this.text, font.FontFamily, (int) font.Style, 
          //    font.Size, rect, format);
        path.AddString(this.text, font.FontFamily, (int)font.Style, 75, 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);
          hatchBrush = new HatchBrush(HatchStyle.Percent10, Color.Black, Color.SkyBlue);
          g.FillPath(hatchBrush, path);
          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);
          }
          font.Dispose();
          hatchBrush.Dispose();
          g.Dispose();
          this.image = bitmap;
    }
}

Happy Coding...

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Tarun Dudhatra
Software Developer Working in Ahmedabad, Gujarat, India
India India
Member

I am working as a Software Engineer in Ahmedabad, Gujrat, India.

I have 5+ Years of Experience in Microsoft Technology Like Asp.Net 2.0,Asp.Net 3.0,Asp.Net 4.0,
C#, Javascript, Crystal Reports, JQuery etc.

Find out more on :


Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 5memberOshtri Deka23 May '13 - 20:28 
Nice!
QuestionCaptcha GenerationmemberMember 983287831 Mar '13 - 0:06 
This is working well. Thanks a lot..!
GeneralExcellent articlememberHarini kanipakam22 Mar '13 - 12:41 
Smile | :) Works well, easy to understand.
GeneralMy vote of 5member3mara12 Feb '13 - 0:35 
Yes its an excellent article
QuestionRegenerate Capthamembergaga blues16 Sep '12 - 0:42 
Hello. I just want to ask, how am I going to regenerate the captha? If the client cant read the current captcha, there is a link for getting another captcha but I dont know the code for the link. Please help
GeneralMy vote of 5membergaga blues16 Sep '12 - 0:03 
Thank you so much!
Questionjust roksmemberomkarpardeshi12327 Aug '12 - 8:57 
thanks
Questiontnxmemberjiji266315 Aug '12 - 15:15 
Very Good
Excellent
Questioncan see image local not deployedmemberMember 875979726 Jul '12 - 4:19 
Is there some web.config change or some other code I need to add so I can see the
image after deployed. I am using vs2010. I do really like this program
Questiontank youmembermaryam madadi28 Jun '12 - 4:59 
tanck you very very very much
you resolve my great problem
QuestionRefresh imagemembermoranmono9 Apr '12 - 23:27 
I want to add a button that the user will be able to refresh the captcha how can I implement it on my application?
Thanks
GeneralChange font color in the randomimagememberEitan.Aviran26 Apr '11 - 22:01 
How to change the font color in the random image generated from this light blue to somthing else?
GeneralRe: Change font color in the randomimagememberTarun Dudhatra27 Apr '11 - 7:56 
Hi Eitan,

In private void GenerateImage()

Method there is a line with

HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti,
              Color.LightGray, Color.White);

Here change the Color.LightGray to available other colors it will change the accordingly.
If you need more assistance please let me know.

DotNet Stuff


QuestionI am still unable to see an imagemembermlbrown23 Mar '11 - 6:30 
I had attempted to fill in the missing code and make some slight changes, however the code did not produce and image. I have since downloaded your supplied source, and am still not able to generate an image? Am I the only one having this issue?
AnswerRe: I am still unable to see an imagememberTarun Dudhatra23 Mar '11 - 19:54 
Can you check this line
ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg);
in CImage.aspx.cs file here just try to save image on local drive and check weather image is generated or not?
 
As I have checked that Sample code and it's working fine.
DotNet Stuff
GeneralOK let me try to insert code to downloadmemberTarun Dudhatra22 Mar '11 - 2:30 
Hi,
Actually this entry is from my blog so there is no code, But let me try to provide code to download for full working example.
 
It will be available very soon.
QuestionCan you provide the Code or Project Download ?membermikelopilato22 Mar '11 - 1:27 
A Full Code or Project Download may provide the solution to missing code.
AnswerRe: Can you provide the Code or Project Download ?memberTarun Dudhatra22 Mar '11 - 3:24 
Full working code to download is available now. If you need more help just let me know.
 
-------------------------------------
DotNet Stuff
QuestionHellomemberaccount291221 Mar '11 - 21:20 
Some code is not complete.
May you fix it?
AnswerRe: HellomemberTarun Dudhatra22 Mar '11 - 3:22 
Yes I have fixed it just check it.
 
-------------------------------------
DotNet Stuff

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130523.1 | Last Updated 23 Mar 2011
Article Copyright 2011 by Tarun Dudhatra
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid