Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

CAPTCHA Graphic in ASP.NET

4.82/5 (20 votes)
30 Oct 2009CPOL1 min read 70.6K   5.6K  
Generate CAPTCHA graphics that you can use on websites to help authenticate users.

Image 1

Introduction

What is CAPTCHA?

CAPTCHA is an abbreviation for Completely Automated Public Turing test to tell Computers and Humans Apart.

This method uses images of words or numbers that are, in theory, distorted and jumbled enough so that an optical character recognition program can’t read them but a human should be able to do so easily.

Failed.JPG

Help.JPG

Success.JPG

Background

This class is a simple one that builds:

  1. Six characters (using numerics 0-9, capital letters A-Z, and small letters a-z).
  2. Is case sensitive.
  3. Has dynamic font color and position.
  4. Provides help (can be seen clearly in the message box).

Using the Constructor

Create a CAPTCHA image using the Captcha class. It has two constructors, with argument (defined by the user) and without (set by the system).

The following example describes how to create a captcha image with/without an argument:

VB
Private Sub DisplayCaptcha()
    'Save the generated CAPTCHA on phisical drive 
    'with the name of "CAPTCHA.jpg"
    'if you want to save with different name ("mycaptcha.jpg") 
    'instead of "CAPTCHA.jpg" 
    Dim strFile As String = "CAPTCHA.jpg"

    'There are two methods of CAPTCHA
    '1. Without argument (Default width:180, height:40,
    '                     fontstyle: [Name:Georgia,Size:30,Style:Bold])
    'Dim captcha = New Captcha() 

    '2. With argument (CAPTCHA width,CAPTCHA height,CAPTCHA font style)
    'Dim captcha = New Captcha(180, 55, fnt)

    'Set CAPTCHA font style
    Dim fnt As Font = New System.Drawing.Font("Calibri", 30.0!, _
        System.Drawing.FontStyle.Bold, _
        System.Drawing.GraphicsUnit.Point, CType(0, Byte))
    'Create CAPTCHA object with custom width, height and fontstyle
    Dim captcha = New Captcha(180, 55, fnt)
    'Start CAPTCHA generation
    captcha.GenerateCaptcha()
    'Save generated CAPTCHA (image) on target folder (CAPTCHAImage) 
    'located at your application root folder.
    captcha.CaptchaImage.Save(Server.MapPath("CAPTCHAImage/") & _
                              strFile, Drawing.Imaging.ImageFormat.Jpeg)
    'Display CAPTCHA (image) on your webpage
    imgCaptcha.ImageUrl = "CAPTCHAImage/" & strFile
    imgCaptcha.ToolTip = "Add this code into Verify textbox"
    'Store CAPTCHA (image) value into Session, becuse that will be
    'used for validating a CAPTCHA (image) with Session
    Session("CAPTCHA") = captcha.CaptchaValue
End Sub

Using the Class

  1. Display the captcha and verify the user input against the value stored in the class.
  2. Save the generated bitmap to disk in order to display it to a web user in an ASP.NET application.
  3. You can also regenerate the value if the user requests it.
VB
#Region "Captcha Generation Code"
 '' <summary>
''' Generates a new captcha value and graphic for the class
''' </summary>
''' <remarks>
Public Sub GenerateCaptcha()
    '//1. CAPTCHA default property
    '------------------------------------------------------------
    'If you could not set the Font,Height and Width property 
    'of CAPTCHA, it will not be generate any images
    If _captchaFont Is Nothing OrElse _captchaHeight = 0 _
                    OrElse _captchaWidth = 0 Then
        Exit Sub
    End If

    Dim strValue As String = ""
    Dim captchaDigit As String = ""
    'This following line is used to decide whether alphabet 
    '(character that includes A-Z, a-z)
    'should be displayed or not
    Dim strAlphaDisplay As String = "0100110100"

    '//2. Digit character in CAPTCHA graphic
    '------------------------------------------------------------
    'RandomValue.Next(10000, 1000000).ToString will be return 
    '6 characters string between (10000 to 1000000) randomly.
    captchaDigit = RandomValue.Next(10000, 1000000).ToString

    '//3. Create Bitmap object
    '------------------------------------------------------------
    'We must create a Bitmap object on witch we draw a CAPTCHA graphic.
    'New Bitmap(_captchaWidth, _captchaHeight)         
    'The parameters represent the height and weight of the bitmap. 
    'They are not important right now, we will modify them later
    _captchaImage = New Bitmap(_captchaWidth, _captchaHeight)

    Using CaptchaGraphics As Graphics = Graphics.FromImage(CaptchaImage)
        '//4. Alphabets character in CAPTCHA graphic
        '--------------------------------------------------------
        'Allows you to select from a large variety of preset 
        'patterns to paint with, rather than a solid color.
        'The following code to create a HatchBrush that 
        'paints with a "SmallGrid" pattern,
        'using "DimGray" as the forecolor 
        'and "WhiteSmoke" as the backcolor. 
        Using BackgroundBrush As New Drawing2D.HatchBrush(_
              Drawing2D.HatchStyle.SmallGrid, Color.DimGray, Color.WhiteSmoke)
            CaptchaGraphics.FillRectangle(BackgroundBrush, 0, 0, _
                            _captchaWidth, _captchaHeight)
        End Using

        'Calculate horizontal space between each Character.
        Dim CharacterSpacing As Integer = (_captchaWidth \ captchaDigit.Length) - 1
        'Variable declaration that will be used later
        Dim HorizontalPosition As Integer
        Dim MaxVerticalPosition As Integer
        Dim rndbBrush As New Random
        Dim rndAlphabet As New Random
        Dim rndAlphaDisplay As New Random

        For Each CharValue As Char In captchaDigit.ToCharArray

            '//5. Alphabets character in CAPTCHA graphic
            '----------------------------------------------------
            'rndAlphaDisplay.Next(0, 9) will be return one digit between 0-9
            Dim intAlphaDisplay As Integer = rndAlphaDisplay.Next(0, 9)
            'Now compared return digit with static value ("0100110100")index, 
            'if it will return "1" then i generate random number between (0 to 51)
            'the length of Capital Letters (A-Z) = 26 
            'and Small  Letters (a-z) = 26 (26+26=52)
            If strAlphaDisplay.ToCharArray(intAlphaDisplay, 1) = "1" Then
                CharValue = alphabets(rndAlphabet.Next(0, 51))
            End If

            '//6. Stored generated CAPTCHA characters
            '----------------------------------------------------
            strValue = strValue & CharValue

            'rndbBrush.Next(0, 139) will return a color index 
            '(which is stored in "colors" ArrayList).
            'All the colors (140 colors starting from 
            '"AliceBlue" to "YellowGreen")
            '----------------------------------------------------
            Dim intRand As Integer = rndbBrush.Next(0, 139)

            '//7. Set the font color of Character.
            '----------------------------------------------------
            'The color of the brush would be the color of the character .
            'get the drawing brush and where we're going to draw.
            Dim brush As Brush = _
              New SolidBrush(ColorTranslator.FromHtml(colors(intRand)))

            '//8. Set the position of Character.
            '----------------------------------------------------
            MaxVerticalPosition = _captchaHeight - Convert.ToInt32(_
               CaptchaGraphics.MeasureString(CharValue, _captchaFont).Height)
            'Draw the Character.
            CaptchaGraphics.DrawString(CharValue, _captchaFont, brush, _
               HorizontalPosition, RandomValue.Next(0, MaxVerticalPosition))
            'Now set the horizontal position of next upcoming Character.
            HorizontalPosition += CharacterSpacing + RandomValue.Next(-1, 1)

            'Clear brush
            brush.Dispose()
        Next

        '//9. Set noise in CAPTCHA graphic.
        '--------------------------------------------------------
        'Image noise is the random variation of colors
        'like (Red, Blue, Green and Yellow)
        'information in images produced by following method
        'Just it is used for increasing complexity 
        'and readability of the image.
        Dim RndmValue As New Random
        Dim start As Integer = RndmValue.Next(1, 4)
        For Counter As Integer = 0 To 24
            CaptchaGraphics.FillEllipse(Brushes.Red, _
                RandomValue.Next(start, _captchaWidth), _
                RandomValue.Next(1, _captchaHeight), _
                RandomValue.Next(1, 4), RandomValue.Next(2, 5))
            start = RndmValue.Next(1, 4)
            CaptchaGraphics.FillEllipse(Brushes.Blue, _
                RandomValue.Next(start, _captchaWidth), _
                RandomValue.Next(1, _captchaHeight), _
                RandomValue.Next(1, 6), RandomValue.Next(2, 7))
            start = RndmValue.Next(1, 4)
            CaptchaGraphics.FillEllipse(Brushes.Green, _
                RandomValue.Next(start, _captchaWidth), _
                RandomValue.Next(1, _captchaHeight), _
                RandomValue.Next(1, 4), RandomValue.Next(2, 6))
            start = RndmValue.Next(1, 4)
            CaptchaGraphics.FillEllipse(Brushes.Yellow, _
                RandomValue.Next(start, _captchaWidth), _
                RandomValue.Next(1, _captchaHeight), _
                RandomValue.Next(1, 5), RandomValue.Next(2, 6))
        Next

            '//10. Clear pending CAPTCHA graphics.
            '----------------------------------------------------
            ' Finally, the Flush method forces all pending 
            ' operations on the Graphics object to finish.
            CaptchaGraphics.Flush()
            _captchaFont.Dispose()
        End Using

        'Set the CAPTCHA graphic answer and image 
        'to CaptchaValue and CaptchaImage
        CaptchaValue = strValue
        CaptchaImage = _captchaImage
    End Sub
#End Region

Points of Interest

Let’s look at some of the details of this routine.

  • The HatchBrush object is used to draw the grid background.
  • The characters from the randomly generated number are drawn onto the graphic one character at a time, and are randomly placed along the vertical axis and slightly off kilter on the horizontal one.
  • The FillEllipse method of the Graphics object is used to create noise at 50 different random points on the graphic.

Let me know if you have any questions or observations in this example by leaving me a comment.

License

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