En este tutorial, el objetivo es hacer un «click» en el captcha para validar que el formulario no haya sido rellenado por un robot.

Vamos a necesitar dos imágenes:

La Imagen de seguridad:

La imagen de la máscara de Captcha:

A continuación pondre el codigo explicado:

  1. <?php
  2.  
  3.   // iniciamos la session
  4.   session_start();
  5.  
  6.   // declaramos nuestras variables
  7.   $width = 180;
  8.   $height = 90;
  9.   $blob_width = 40;
  10.   $blob_height = 40;
  11.  
  12.   // creamos nuestra imagen
  13.   $image = imagecreatetruecolor($width, $height);
  14.  
  15.   //color background de la imagen
  16.   $white = imagecolorallocate($image, 230, 230, 230);
  17.   $red  = imagecolorallocate($image, 255, 0, 0);
  18.   $blue  = imagecolorallocate($image, 0, 0, 230);
  19.  
  20.   // llenamos el contenedor de la imagen
  21.   imagefilledrectangle($image, 0, 0, $width, $height ,$white);
  22.  
  23.  
  24.   // creamos el background de espirales para nuestra imagen
  25.  
  26.   $theta    = 1;
  27.   $thetac   = 7;
  28.   $radius   = 16;
  29.   $circles  = 20;
  30.   $points   = 32;
  31.  
  32.   for ($i = 0; $i < ($circles * $points) - 1; $i++)
  33.   {
  34.     $theta = $theta + $thetac;
  35.     $rad = $radius * ($i / $points );
  36.     $x = ($rad * cos($theta)) + $x_axis;
  37.     $y = ($rad * sin($theta)) + $y_axis;
  38.     $theta = $theta + $thetac;
  39.     $rad1 = $radius * (($i + 1) / $points);
  40.     $x1 = ($rad1 * cos($theta)) + $x_axis;
  41.     $y1 = ($rad1 * sin($theta )) + $y_axis;
  42.     imageline($image, $x, $y, $x1, $y1, $blue);
  43.     $theta = $theta - $thetac;
  44.   }
  45.  
  46.   // obtenemos la posicion de nuestro circulo aleatoriamente
  47.   $x_axis = rand($blob_width, $width) - ($blob_width / 2);
  48.   $y_axis = rand($blob_height, $height)  - ($blob_height / 2);
  49.  
  50.   // dibujamos el circulo
  51.   imagefilledellipse ($image, $x_axis, $y_axis, $blob_width, $blob_height, $red);
  52.  
  53.   // creamos la imagen de mascara
  54.   $mask_image = imagecreatetruecolor($width, $height);
  55.  
  56.   // escogemos el color de nuestro background y color de circulo para nuestra mascara
  57.   $mask_white = imagecolorallocate($mask_image, 255, 255, 255);
  58.   $mask_red  = imagecolorallocate($mask_image, 255, 0, 0);
  59.  
  60.   // llenamos la imagen mascara con nuestro background
  61.   imagefilledrectangle($mask_image, 0, 0, $width, $height ,$mask_white);
  62.  
  63.   // dibujamos el circulo en nuestra mascara
  64.   imagefilledellipse ($mask_image, $x_axis, $y_axis, $blob_width, $blob_height, $mask_red);
  65.  
  66.   // escribimos la imagen en el buffer
  67.   ob_start();
  68.   imagepng($mask_image);
  69.   $mask_image_data = ob_get_contents();  // recibimos los datos y limpiamos el buffer
  70.   ob_end_clean();
  71.  
  72.   // convertimos la imagen a Base64
  73.   $mask_image_data_b64 =  base64_encode($mask_image_data);
  74.  
  75.   // guardamos los datos en nuestra variable del servidor
  76.  $_SESSION&#91;'captcha_image_code'] = $mask_image_data_b64;
  77.  
  78.  
  79.   // Enviamos las cabeceras del contenido
  80.   header('Content-type: image/jpeg');
  81.   header('Cache-control: no-cache');
  82.  
  83.   // lanzamos la imagen al navegador
  84.   imagejpeg($image);
  85.  
  86.   imagedestroy($image);
  87.  
  88.   ?>

Ahora el formulario:

  1. <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" enctype="multipart/form-data">  
  2.       <p>Name<br/><input type="text" name="name" /></p>  
  3.       <p>Comment<br/><textarea name="message"></textarea></p>
  4.       <p>
  5.         Click the Red Circle to continue:<br/>
  6.         <input type='image' name='submit' src='captcha.php' alt='Captcha Security'  />
  7.       </p>
  8.   </form>

Por ultimo la validacion:

  1. session_start();
  2.  
  3.   if(isset($_POST['submit_x']) && isset($_POST['submit_y'])) {  
  4.  
  5.       if(!empty($_POST['name']) && !empty($_POST['message'])) {  
  6.  
  7.         // retrive the image captcha data
  8.         $data = base64_decode($_SESSION['captcha_image_code']);
  9.  
  10.         $captcha_image = imagecreatefromstring($data);
  11.         $x = $_POST['submit_x'];
  12.         $y = $_POST['submit_y'];
  13.  
  14.         // get the pixel color of the clicked x and y coordinate
  15.         $rgb = imagecolorat($captcha_image, $x, $y);
  16.         $color_tran = imagecolorsforindex($captcha_image, $rgb);
  17.  
  18.         // check if the color is red and red only
  19.         $captcha_ok = ($color_tran['red'] == 255 && $color_tran['green'] == 0 && $color_tran['blue'] == 0 && $color_tran['alpha'] == 0) ;
  20.  
  21.         if($captcha_ok) {  
  22.  
  23.           $result = "Thank you for submitting your comment.";            
  24.  
  25.         } else {  
  26.  
  27.           $result = "Please make sure you click the red circle!";  
  28.  
  29.         }  
  30.  
  31.       } else {  
  32.  
  33.           $result = "Please fill out the entire form.";  
  34.  
  35.       }  
  36.  
  37.   }

Un cambio adicional aquí es recuperar la imagen de la máscara de la sesión y volver a poner esa imagen de un objeto y luego obtener el color del píxel de X e Y.

Para ello, primero tenemos que recuperar la imagen de la máscara de la sesión y luego descifrar como se muestra a continuación:

  1. // retrive the image captcha data
  2.   $data = base64_decode($_SESSION['captcha_image_code']);

A continuación, convertirlo de nuevo en una imagen del objeto utilizando la funcion ImageCreateFromString().

  1. $captcha_image = imagecreatefromstring($data);

Luego recuperar la coordenadas X e Y desde el primer clic que el usuario envía, junto con el color del píxel usando imagecolorsforindex (). Nos aseguramos de que sólo se obtiene un color rojo y nada más.

  1. // obtenemos el  color del pixel que fue clickeado con las coordenas "x" y "y"
  2.   $rgb = imagecolorat($captcha_image, $x, $y);
  3.   $color_tran = imagecolorsforindex($captcha_image, $rgb);
  4.  
  5.   // verificamos que el color sea solo rojo
  6.   $captcha_ok = ($color_tran['red'] == 255 && $color_tran['green'] == 0 && $color_tran['blue'] == 0 && $color_tran['alpha'] == 0) ;

Despues de todo esto el formulario nos quedaria asi:

  1. <?php  
  2. session_start();
  3.  
  4. if(isset($_POST&#91;'submit_x'&#93;) && isset($_POST&#91;'submit_y'&#93;)) {  
  5.  
  6.    if(!empty($_POST&#91;'name'&#93;) && !empty($_POST&#91;'message'&#93;)) {  
  7.  
  8.      // retrive the image captcha data
  9.      $data = base64_decode($_SESSION&#91;'captcha_image_code'&#93;);
  10.  
  11.      $captcha_image = imagecreatefromstring($data);
  12.      $x = $_POST&#91;'submit_x'&#93;;
  13.      $y = $_POST&#91;'submit_y'&#93;;
  14.  
  15.      // get the pixel color of the clicked x and y coordinate
  16.      $rgb = imagecolorat($captcha_image, $x, $y);
  17.      $color_tran = imagecolorsforindex($captcha_image, $rgb);
  18.  
  19.      // check if the color is red and red only
  20.      $captcha_ok = ($color_tran&#91;'red'&#93; == 255 && $color_tran&#91;'green'&#93; == 0 && $color_tran&#91;'blue'&#93; == 0 && $color_tran&#91;'alpha'&#93; == 0) ;
  21.  
  22.      if($captcha_ok) {  
  23.  
  24.        $result = "Thank you for submitting your comment.";            
  25.  
  26.      } else {  
  27.  
  28.        $result = "Please make sure you click the red circle!";  
  29.  
  30.      }  
  31.  
  32.    } else {  
  33.  
  34.        $result = "Please fill out the entire form.";  
  35.  
  36.    }  
  37.  
  38. }  
  39. ?>
  40.  
  41. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
  42. <html xmlns="http://www.w3.org/1999/xhtml">  
  43. <head>  
  44. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  
  45. <title>Captcha Demo</title>  
  46. </head>  
  47.  
  48. <body>  
  49.  
  50. <?php if(!empty($result)) echo "<div style='color:#990000; margin-bottom: 20px;'>" . $result . "</div>"; ?>  
  51.  
  52. <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" enctype="multipart/form-data">  
  53.     <p>Name<br/><input type="text" name="name" /></p>  
  54.     <p>Comment<br/><textarea name="message"></textarea></p>
  55.     <p>
  56.       Click the Red Circle to continue:<br/>
  57.       <input type='image' name='submit' src='captcha.php' alt='Captcha Security'  />
  58.     </p>
  59. </form>  
  60.  
  61. </body>  
  62. </html>

Ahora puedes implementarlo en tu web, puedes cambiar los colores y jugar un poco con esta validacion, veras que no es muy dificil.