Beispiel #1
0
 /**
  * Base function for generating a image CAPTCHA.
  *
  * @param string $code
  *   String code to be presented on image.
  *
  * @return resource
  *   Image to be outputted contained $code string.
  */
 protected function generateImage($code)
 {
     $fonts = _image_captcha_get_enabled_fonts();
     $font_size = $this->config->get('image_captcha_font_size');
     list($width, $height) = _image_captcha_image_size($code);
     $image = imagecreatetruecolor($width, $height);
     if (!$image) {
         return FALSE;
     }
     // Get the background color and paint the background.
     $background_rgb = $this->hexToRGB($this->config->get('image_captcha_background_color'));
     $background_color = imagecolorallocate($image, $background_rgb[0], $background_rgb[1], $background_rgb[2]);
     // Set transparency if needed.
     $file_format = $this->config->get('image_captcha_file_format');
     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) $this->config->get('image_captcha_rtl_support');
     $result = $this->printString($image, $width, $height, $fonts, $font_size, $code);
     if (!$result) {
         return FALSE;
     }
     $noise_colors = [];
     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 ($this->config->get('image_captcha_dot_noise')) {
         $this->addDots($image, $width, $height, $noise_colors);
     }
     if ($this->config->get('image_captcha_line_noise')) {
         $this->addLines($image, $width, $height, $noise_colors);
     }
     $distortion_amplitude = 0.25 * $font_size * $this->config->get('image_captcha_distortion_amplitude') / 10.0;
     if ($distortion_amplitude > 1) {
         $wavelength_xr = (2 + 3 * lcg_value()) * $font_size;
         $wavelength_yr = (2 + 3 * lcg_value()) * $font_size;
         $freq_xr = 2 * 3.141592 / $wavelength_xr;
         $freq_yr = 2 * 3.141592 / $wavelength_yr;
         $wavelength_xt = (2 + 3 * lcg_value()) * $font_size;
         $wavelength_yt = (2 + 3 * lcg_value()) * $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 ($this->config->get('image_captcha_bilinear_interpolation')) {
             // 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;
                         $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));
                         $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);
                 }
             }
         }
         imagedestroy($image);
         return $distorted_image;
     } else {
         return $image;
     }
 }
Beispiel #2
0
 /**
  * Form elements for the font specific setting.
  *
  * This is refactored to a separate function to avoid polluting the
  * general form function image_captcha_settings_form with some
  * specific logic.
  *
  * @return array $form
  *   The font settings specific form elements.
  */
 protected function settingsDotSection()
 {
     $config = $this->config('image_captcha.settings');
     // Put it all in a details element.
     $form = ['#type' => 'details', '#title' => t('Font settings')];
     // First check if there is TrueType support.
     $setup_status = _image_captcha_check_setup(FALSE);
     if ($setup_status & IMAGE_CAPTCHA_ERROR_NO_TTF_SUPPORT) {
         // Show a warning that there is no TrueType support.
         $form['no_ttf_support'] = ['#type' => 'item', '#title' => t('No TrueType support'), '#markup' => t('The Image CAPTCHA module can not use TrueType fonts because your PHP setup does not support it. You can only use a PHP built-in bitmap font of fixed size.')];
     } else {
         // Build a list of  all available fonts.
         $available_fonts = [];
         // List of folders to search through for TrueType fonts.
         $fonts = $this->getAvailableFontsFromDirectories();
         // Cache the list of previewable fonts. All the previews are done
         // in separate requests, and we don't want to rescan the filesystem
         // every time, so we cache the result.
         $config->get('image_captcha_fonts_preview_map_cache', $fonts);
         // Put these fonts with preview image in the list.
         foreach ($fonts as $token => $font) {
             $img_src = check_url(url('admin/config/people/captcha/image_captcha/font_preview/' . $token));
             $title = t('Font preview of @font (@file)', ['@font' => $font->name, '@file' => $font->uri]);
             $available_fonts[$font->uri] = '<img src="' . $img_src . '" alt="' . $title . '" title="' . $title . '" />';
         }
         // Append the PHP built-in font at the end.
         $img_src = check_url(url('admin/config/people/captcha/image_captcha/font_preview/BUILTIN'));
         $title = t('Preview of built-in font');
         $available_fonts['BUILTIN'] = t('PHP built-in font: !font_preview', ['!font_preview' => '<img src="' . $img_src . '" alt="' . $title . '" title="' . $title . '" />']);
         $default_fonts = _image_captcha_get_enabled_fonts();
         $form['image_captcha_fonts'] = ['#type' => 'checkboxes', '#title' => t('Fonts'), '#default_value' => $default_fonts, '#description' => t('Select the fonts to use for the text in the image CAPTCHA. Apart from the provided defaults, you can also use your own TrueType fonts (filename extension .ttf) by putting them in %fonts_library_general or %fonts_library_specific.', ['%fonts_library_general' => 'sites/all/libraries/fonts', '%fonts_library_specific' => conf_path() . '/libraries/fonts']), '#options' => $available_fonts, '#attributes' => ['class' => ['image_captcha_admin_fonts_selection']], '#process' => ['form_process_checkboxes']];
         $form['image_captcha_font_size'] = ['#type' => 'select', '#title' => t('Font size'), '#options' => [9 => '9 pt - ' . t('tiny'), 12 => '12 pt - ' . t('small'), 18 => '18 pt', 24 => '24 pt - ' . t('normal'), 30 => '30 pt', 36 => '36 pt - ' . t('large'), 48 => '48 pt', 64 => '64 pt - ' . t('extra large')], '#default_value' => (int) $config->get('image_captcha_font_size'), '#description' => t('The font size influences the size of the image. Note that larger values make the image generation more CPU intensive.')];
     }
     // Character spacing (available for both the TrueType
     // fonts and the builtin font.
     $form['image_captcha_font_settings']['image_captcha_character_spacing'] = ['#type' => 'select', '#title' => t('Character spacing'), '#description' => t('Define the average spacing between characters. Note that larger values make the image generation more CPU intensive.'), '#default_value' => $config->get('image_captcha_character_spacing'), '#options' => ['0.75' => t('tight'), '1' => t('normal'), '1.2' => t('wide'), '1.5' => t('extra wide')]];
     return $form;
 }