You are here

function _image_captcha_generate_image in CAPTCHA 7

Same name and namespace in other branches
  1. 5.3 image_captcha/image_captcha.user.inc \_image_captcha_generate_image()
  2. 6.2 image_captcha/image_captcha.user.inc \_image_captcha_generate_image()
  3. 6 image_captcha/image_captcha.user.inc \_image_captcha_generate_image()

Base function for generating a image CAPTCHA.

1 call to _image_captcha_generate_image()
image_captcha_image in image_captcha/image_captcha.user.inc
Menu callback function that generates the CAPTCHA image.

File

image_captcha/image_captcha.user.inc, line 79
Functions for the generation of the CAPTCHA image.

Code

function _image_captcha_generate_image($code) {

  // Get font.
  $fonts = _image_captcha_get_enabled_fonts();

  // Get other settings.
  $font_size = (int) variable_get('image_captcha_font_size', 30);
  list($width, $height) = _image_captcha_image_size($code);

  // Create image resource.
  $image = imagecreatetruecolor($width, $height);
  if (!$image) {
    return FALSE;
  }

  // Get the background color and paint the background.
  $background_rgb = _image_captcha_hex_to_rgb(variable_get('image_captcha_background_color', '#ffffff'));
  $background_color = imagecolorallocate($image, $background_rgb[0], $background_rgb[1], $background_rgb[2]);

  // Set transparency if needed.
  $file_format = variable_get('image_captcha_file_format', IMAGE_CAPTCHA_FILE_FORMAT_JPG);
  if ($file_format == IMAGE_CAPTCHA_FILE_FORMAT_TRANSPARENT_PNG) {
    imagecolortransparent($image, $background_color);
  }
  imagefilledrectangle($image, 0, 0, $width, $height, $background_color);

  // Do we need to draw in RTL mode?
  global $language;
  $rtl = $language->direction && (bool) variable_get('image_captcha_rtl_support', 0);

  // Draw text.
  $result = _image_captcha_image_generator_print_string($image, $width, $height, $fonts, $font_size, $code, $rtl);
  if (!$result) {
    return FALSE;
  }

  // Add noise.
  $noise_colors = array();
  for ($i = 0; $i < 20; $i++) {
    $noise_colors[] = imagecolorallocate($image, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));
  }

  // Add additional noise.
  if (variable_get('image_captcha_dot_noise', 0)) {
    _image_captcha_image_generator_add_dots($image, $width, $height, $noise_colors);
  }
  if (variable_get('image_captcha_line_noise', 0)) {
    _image_captcha_image_generator_add_lines($image, $width, $height, $noise_colors);
  }

  // Distort the image.
  $distortion_amplitude = 0.25 * $font_size * variable_get('image_captcha_distortion_amplitude', 0) / 10.0;
  if ($distortion_amplitude > 1) {

    // Distortion parameters.
    $wavelength_xr = (2 + 3 * mt_rand(0, 1000) / 1000) * $font_size;
    $wavelength_yr = (2 + 3 * mt_rand(0, 1000) / 1000) * $font_size;
    $freq_xr = 2 * 3.141592 / $wavelength_xr;
    $freq_yr = 2 * 3.141592 / $wavelength_yr;
    $wavelength_xt = (2 + 3 * mt_rand(0, 1000) / 1000) * $font_size;
    $wavelength_yt = (2 + 3 * mt_rand(0, 1000) / 1000) * $font_size;
    $freq_xt = 2 * 3.141592 / $wavelength_xt;
    $freq_yt = 2 * 3.141592 / $wavelength_yt;
    $distorted_image = imagecreatetruecolor($width, $height);
    if ($file_format == IMAGE_CAPTCHA_FILE_FORMAT_TRANSPARENT_PNG) {
      imagecolortransparent($distorted_image, $background_color);
    }
    if (!$distorted_image) {
      return FALSE;
    }
    if (variable_get('image_captcha_bilinear_interpolation', FALSE)) {

      // Distortion with bilinear interpolation.
      for ($x = 0; $x < $width; $x++) {
        for ($y = 0; $y < $height; $y++) {

          // Get distorted sample point in source image.
          $r = $distortion_amplitude * sin($x * $freq_xr + $y * $freq_yr);
          $theta = $x * $freq_xt + $y * $freq_yt;
          $sx = $x + $r * cos($theta);
          $sy = $y + $r * sin($theta);
          $sxf = (int) floor($sx);
          $syf = (int) floor($sy);
          if ($sxf < 0 || $syf < 0 || $sxf >= $width - 1 || $syf >= $height - 1) {
            $color = $background_color;
          }
          else {

            // Bilinear interpolation: sample at four corners.
            $color_00 = imagecolorat($image, $sxf, $syf);
            $color_00_r = $color_00 >> 16 & 0xff;
            $color_00_g = $color_00 >> 8 & 0xff;
            $color_00_b = $color_00 & 0xff;
            $color_10 = imagecolorat($image, $sxf + 1, $syf);
            $color_10_r = $color_10 >> 16 & 0xff;
            $color_10_g = $color_10 >> 8 & 0xff;
            $color_10_b = $color_10 & 0xff;
            $color_01 = imagecolorat($image, $sxf, $syf + 1);
            $color_01_r = $color_01 >> 16 & 0xff;
            $color_01_g = $color_01 >> 8 & 0xff;
            $color_01_b = $color_01 & 0xff;
            $color_11 = imagecolorat($image, $sxf + 1, $syf + 1);
            $color_11_r = $color_11 >> 16 & 0xff;
            $color_11_g = $color_11 >> 8 & 0xff;
            $color_11_b = $color_11 & 0xff;

            // Interpolation factors.
            $u = $sx - $sxf;
            $v = $sy - $syf;

            // Interpolate.
            $r = (int) ((1 - $v) * ((1 - $u) * $color_00_r + $u * $color_10_r) + $v * ((1 - $u) * $color_01_r + $u * $color_11_r));
            $g = (int) ((1 - $v) * ((1 - $u) * $color_00_g + $u * $color_10_g) + $v * ((1 - $u) * $color_01_g + $u * $color_11_g));
            $b = (int) ((1 - $v) * ((1 - $u) * $color_00_b + $u * $color_10_b) + $v * ((1 - $u) * $color_01_b + $u * $color_11_b));

            // Build color.
            $color = ($r << 16) + ($g << 8) + $b;
          }
          imagesetpixel($distorted_image, $x, $y, $color);
        }
      }
    }
    else {

      // Distortion with nearest neighbor interpolation.
      for ($x = 0; $x < $width; $x++) {
        for ($y = 0; $y < $height; $y++) {

          // Get distorted sample point in source image.
          $r = $distortion_amplitude * sin($x * $freq_xr + $y * $freq_yr);
          $theta = $x * $freq_xt + $y * $freq_yt;
          $sx = $x + $r * cos($theta);
          $sy = $y + $r * sin($theta);
          $sxf = (int) floor($sx);
          $syf = (int) floor($sy);
          if ($sxf < 0 || $syf < 0 || $sxf >= $width - 1 || $syf >= $height - 1) {
            $color = $background_color;
          }
          else {
            $color = imagecolorat($image, $sxf, $syf);
          }
          imagesetpixel($distorted_image, $x, $y, $color);
        }
      }
    }

    // Release undistorted image.
    imagedestroy($image);

    // Return distorted image.
    return $distorted_image;
  }
  else {
    return $image;
  }
}