Search code examples
phpcaptcha

Changes in captcha image through coding


I use the following captcha code which works correctly:

<?php
session_start();
//You can customize your captcha settings here

$captcha_code = '';
$captcha_image_height = 50;
$captcha_image_width = 130;
$total_characters_on_image = 6;

//The characters that can be used in the CAPTCHA code.
//avoid all confusing characters and numbers (For example: l, 1 and i)
$possible_captcha_letters = 'bcdfghjkmnpqrstvwxyz23456789';
$captcha_font = './monofont.ttf';

$random_captcha_dots = 45;
$random_captcha_lines = 20;
$captcha_text_color = "0x021f64";
$captcha_noise_color = "0x021f64";


$count = 0;
while ($count < $total_characters_on_image) { 
$captcha_code .= substr(
    $possible_captcha_letters,
    mt_rand(0, strlen($possible_captcha_letters)-1),
    1);
$count++;
}

$captcha_font_size = $captcha_image_height * 0.65;
$captcha_image = @imagecreate(
    $captcha_image_width,
    $captcha_image_height
    );

/* setting the background, text and noise colours here */
$background_color = imagecolorallocate(
    $captcha_image,
    255,
    255,
    255
    );

$array_text_color = hextorgb($captcha_text_color);
$captcha_text_color = imagecolorallocate(
    $captcha_image,
    $array_text_color['red'],
    $array_text_color['green'],
    $array_text_color['blue']
    );

$array_noise_color = hextorgb($captcha_noise_color);
$image_noise_color = imagecolorallocate(
    $captcha_image,
    $array_noise_color['red'],
    $array_noise_color['green'],
    $array_noise_color['blue']
    );

/* Generate random dots in background of the captcha image */
for( $count=0; $count<$random_captcha_dots; $count++ ) {
imagefilledellipse(
    $captcha_image,
    mt_rand(0,$captcha_image_width),
    mt_rand(0,$captcha_image_height),
    2,
    3,
    $image_noise_color
    );
}

/* Generate random lines in background of the captcha image */
for( $count=0; $count<$random_captcha_lines; $count++ ) {
imageline(
    $captcha_image,
    mt_rand(0,$captcha_image_width),
    mt_rand(0,$captcha_image_height),
    mt_rand(0,$captcha_image_width),
    mt_rand(0,$captcha_image_height),
    $image_noise_color
    );
}

/* Create a text box and add 6 captcha letters code in it */
$text_box = imagettfbbox(
    $captcha_font_size,
    0,
    $captcha_font,
    $captcha_code
    ); 
$x = ($captcha_image_width - $text_box[4])/2;
$y = ($captcha_image_height - $text_box[5])/2;
imagettftext(
    $captcha_image,
    $captcha_font_size,
    0,
    $x,
    $y,
    $captcha_text_color,
    $captcha_font,
    $captcha_code
    );

/* Show captcha image in the html page */
// defining the image type to be shown in browser widow
header('Content-Type: image/jpeg'); 
imagejpeg($captcha_image); //showing the image
imagedestroy($captcha_image); //destroying the image instance
$_SESSION['captcha'] = $captcha_code;

function hextorgb ($hexstring){
  $integar = hexdec($hexstring);
  return array("red" => 0xFF & ($integar >> 0x10),
               "green" => 0xFF & ($integar >> 0x8),
               "blue" => 0xFF & $integar);
               }
?>

Result of above code: Generated captcha image

As you can see in the image, the generated image for captcha has only one color, which is very annoying.

I want each part of the generated captcha image to have different colors so that it looks beautiful in addition to making it harder for robots to guess it.

What I'm looking for is to generate the captcha image as follows: My desired captcha image

Is there a need for a separate library to generate such a captcha image or can it be implemented with a few changes in the code?


Solution

  • You don't need a separate library for this, but you need to update the way you allocate colors and draw elements on the image.

    • Modify the colors for text, dots, and lines to be random for each element.
    • Update the code for drawing the captcha text, dots, and lines with random colors.
    • Adjust the color allocation within the loops for dots and lines to ensure random colors are generated.

    You can try following code::

    <?php
    session_start();
    
    // You can customize your captcha settings here
    $captcha_code = '';
    $captcha_image_height = 50;
    $captcha_image_width = 130;
    $total_characters_on_image = 6;
    
    // The characters that can be used in the CAPTCHA code.
    // Avoid all confusing characters and numbers (For example: l, 1, and i)
    $possible_captcha_letters = 'bcdfghjkmnpqrstvwxyz23456789';
    $captcha_font = './monofont.ttf';
    
    $random_captcha_dots = 45;
    $random_captcha_lines = 20;
    
    $count = 0;
    while ($count < $total_characters_on_image) { 
        $captcha_code .= substr(
            $possible_captcha_letters,
            mt_rand(0, strlen($possible_captcha_letters)-1),
            1
        );
        $count++;
    }
    
    $captcha_font_size = $captcha_image_height * 0.65;
    $captcha_image = @imagecreate(
        $captcha_image_width,
        $captcha_image_height
    );
    
    /* Generate random dots and lines in the background of the captcha image */
    for ($count = 0; $count < $random_captcha_dots; $count++) {
        $image_noise_color = imagecolorallocate(
            $captcha_image,
            mt_rand(0, 255),
            mt_rand(0, 255),
            mt_rand(0, 255)
        );
    
        imagefilledellipse(
            $captcha_image,
            mt_rand(0, $captcha_image_width),
            mt_rand(0, $captcha_image_height),
            2,
            3,
            $image_noise_color
        );
    }
    
    for ($count = 0; $count < $random_captcha_lines; $count++) {
        $image_noise_color = imagecolorallocate(
            $captcha_image,
            mt_rand(0, 255),
            mt_rand(0, 255),
            mt_rand(0, 255)
        );
    
        imageline(
            $captcha_image,
            mt_rand(0, $captcha_image_width),
            mt_rand(0, $captcha_image_height),
            mt_rand(0, $captcha_image_width),
            mt_rand(0, $captcha_image_height),
            $image_noise_color
        );
    }
    
    /* Create a text box and add 6 captcha letters code in it */
    $text_box = imagettfbbox(
        $captcha_font_size,
        0,
        $captcha_font,
        $captcha_code
    ); 
    $x = ($captcha_image_width - $text_box[4]) / 2;
    $y = ($captcha_image_height - $text_box[5]) / 2;
    
    /* Show captcha image in the HTML page */
    // Defining the image type to be shown in the browser window
    header('Content-Type: image/jpeg');
    
    // Loop through each character and assign a random color
    for ($i = 0; $i < strlen($captcha_code); $i++) {
        $character_color = imagecolorallocate(
            $captcha_image,
            mt_rand(0, 255),
            mt_rand(0, 255),
            mt_rand(0, 255)
        );
    
        imagettftext(
            $captcha_image,
            $captcha_font_size,
            0,
            $x + $i * $captcha_font_size * 0.7, // Adjust character spacing
            $y,
            $character_color, // Use the randomly allocated color
            $captcha_font,
            $captcha_code[$i] // Render each character individually
        );
    }
    
    imagedestroy($captcha_image); // Destroying the image instance
    $_SESSION['captcha'] = $captcha_code;
    
    ?>