<?
/**
* CaptchaV2 File
* Generates CAPTCHA Numbers and Chars Image
* @author Albert Demeter <borex8@hotmail.com>
* @version 2.3
* GNU General Public License (Version 2.3, March 14th, 2019)
*
* based on Hadar Porat's Captcha Numbers class v.1.5 <hpman28@gmail.com>
*
* This program is free software; you can redistribute
* it and/or modify it under the terms of the GNU
* General Public License as published by the Free
* Software Foundation; either version 2 of the License,
* or (at your option) any later version.
*
* This program is distributed in the hope that it will
* be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/**
* CaptchaNumbersV2 Class
* @access public
* @author Albert Demeter <borex8@hotmail.com>
* @version 2.0
*/
class CaptchaNumbersV2 {
var $length = 6;
var $type = 'png';
var $height = 60;
var $width = 160;
var $string = '';
var $captchaType = 'mixed';
// automatically calculated based on the percent in the constructor
var $dotsCount = 0;
// background colors RED, GREEN and BLUE values (provide it as a number between 0-255)
var $bgColorRed = 240;
var $bgColorGreen = 240;
var $bgColorBlue = 240;
// if true then grid is drawn
var $drawGrid = true;
// if true then every grid line will have a different color
var $randomGridColor = true;
// min number of grid lines to draw
var $min_number_of_grid_lines = 2;
// max number of grid lines to draw
var $max_number_of_grid_lines = 7;
// if true then every letter will have a different color
var $randomLetterColor = true;
// array of TTF fonts (path/filename)
// fonts array to use for random char fonts
var $fonts = [
//'fonts/arial.ttf',
//'fonts/vera.ttf',
];
// fonts are loaded automatically from this folder
var $fonts_folder = 'fonts/';
// the range of font size of each letter displayed as pixels.
var $font_size_min = 16;
var $font_size_max = 20;
// font angles are for placing the fonts at a random angle. high values of angles might have unexpected results.
var $font_angle_min = -15;
var $font_angle_max = 15;
/**
* @return void
* @param int $length string length
* @param String $type image type
* @param String $captchaType text contain digits, chars or mixed
* @param int $dotsPercent random pixels generated in image
* @desc generate the main image
*/
function __construct($length = '', $type = '', $captchaType = '', $dotsPercent = 10, $fonts_folder = '') {
if ($length!='') $this -> length = $length;
if ($type!='') $this -> type = $type;
if ($captchaType!='') $this -> captchaType = $captchaType;
if ($fonts_folder!='') $this -> fonts_folder = $fonts_folder;
$newWidth = $this -> length * $this -> font_size_max;
$newHeight = $this -> font_size_max;
if ($newWidth > $this -> width)
$this -> width = $newWidth;
if ($newHeight > $this -> height)
$this -> height = $newHeight;
if (!empty($this->fonts_folder) && file_exists($this->fonts_folder)) {
foreach (glob($this->fonts_folder . "*.ttf") as $file) {
if (!in_array($file, $this->fonts))
$this->fonts[] = $file;
}
}
// dots count equals #% of all points in the image
$this -> dotsCount = round(($this -> width * $this -> height) * $dotsPercent / 100);
$this -> generateString();
}
/**
* @return void
* @desc display captcha image
*/
function display() {
$this -> sendHeader();
$image = $this -> generate();
switch ($this-> type) {
case 'jpeg': imagejpeg($image); break;
case 'png': imagepng($image); break;
case 'gif': imagegif($image); break;
default: imagepng($image); break;
}
}
// function picks a random font for each letter each time
function random_font() {
$font = null;
if (count($this->fonts) > 0) {
$rand = mt_rand(0, count($this->fonts)-1);
$font = $this->fonts[$rand];
}
if (file_exists($font))
return $font;
else
return null;
}
// the font size would be determined randomly within the limits defined above.
function random_font_size() {
if ($this->font_size_min == $this->font_size_max)
return $this->font_size_min;
return mt_rand($this->font_size_min, $this->font_size_max);
}
// the angle would be determined randomly within the limits defined above.
function random_font_angle() {
if ($this->font_angle_min == $this->font_angle_max)
return $this->font_angle_min;
return mt_rand($this->font_angle_min, $this->font_angle_max);
}
/**
* @return Image
* @desc generate the image
*/
function generate() {
$image = ImageCreate($this -> width, $this -> height) or die("Cannot Initialize new GD image stream");
// colors
$background_color = ImageColorAllocate($image, $this -> bgColorRed, $this -> bgColorGreen, $this -> bgColorBlue);
if (!$this -> randomLetterColor)
{
$net_color_1 = ImageColorAllocate($image, 10, 200, 10);
$net_color_2 = ImageColorAllocate($image, 200, 10, 10);
}
if (!$this -> randomLetterColor)
{
$stringcolor_1 = ImageColorAllocate($image, 150, 150, 150);
$stringcolor_2 = ImageColorAllocate($image, 120, 120, 250);
}
if ($this -> drawGrid) {
$count = mt_rand($this->min_number_of_grid_lines, $this->max_number_of_grid_lines);
for ($i = 0; $i < $count; $i++) {
if ($this -> randomGridColor) {
$net_color_1 = ImageColorAllocate($image, mt_rand(0,255), mt_rand(0,250), mt_rand(0,250));
$net_color_2 = ImageColorAllocate($image, mt_rand(0,255), mt_rand(0,250), mt_rand(0,250));
}
if ($i%2) imageline($image, 0, mt_rand(0, $this->height), $this->width, mt_rand(0, $this->height), $net_color_1);
else imageline($image, mt_rand(0, $this->width), 0, mt_rand(0, $this->width), $this->height, $net_color_2);
}
}
// make the text
$str = $this -> getString();
$x = 0;
for($i = 0, $n = strlen($str); $i < $n; $i++)
{
if ($this -> randomLetterColor)
{
$stringcolor_1 = ImageColorAllocate($image, mt_rand(0,255), mt_rand(0,250), mt_rand(0,250));
$stringcolor_2 = ImageColorAllocate($image, mt_rand(0,255), mt_rand(0,250), mt_rand(0,250));
}
$font = $this->random_font();
$fontSize = $this->random_font_size();
$fontAngle = $this->random_font_angle();
$spacing = $this->width / $fontSize * $i;
if (is_callable('imagettftext') && $font != null) {
$y = ($this->height / 2) + ($fontSize / 2);
$y += mt_rand(-1 * $y / 2, $y / 2);
if ($i%2) imagettftext($image, $fontSize, $fontAngle, $x + $spacing, $y, $stringcolor_1, $font, $str{$i} );
else imagettftext($image, $fontSize, $fontAngle, $x + $spacing, $y, $stringcolor_2, $font, $str{$i} );
} else {
$y = ($this->height / 2);
if ($i%2) imagechar($image, $fontSize, $x + $spacing, $y, $str{$i}, $stringcolor_1 );
else imagechar($image, $fontSize, $x + $spacing, $y, $str{$i}, $stringcolor_2 );
}
$x = $x + $fontSize;
}
for ($i = 0; $i < $this -> dotsCount; $i++)
{
$x = rand(0, $this -> width - 1);
$y = rand(0, $this -> height - 1);
$rgbIndex = imagecolorat($image, $x, $y);
$rgb = imagecolorsforindex($image, $rgbIndex);
//print $x . ' x ' . $y . ' : ' . $rgbIndex . '(' . $rgb['red'] . '-' . $rgb['green'] . '-' . $rgb['blue'] . ')<br>';
// if background color create random pixel color
if ($rgb['red'] == $this -> bgColorRed
&& $rgb['green'] == $this -> bgColorGreen
&& $rgb['blue'] == $this -> bgColorBlue)
{
$dotColor = ImageColorAllocate($image, mt_rand(0,255), mt_rand(0,255), mt_rand(0,255));
}
else
{
// not background color then generate a close shade color
$rgb['red'] = $rgb['red'] + ((mt_rand(0,100) % 2) == 1 ? 1 : -1) * mt_rand(0, 255 - $rgb['red']);
if ($rgb['red'] < 0 || $rgb['red'] > 255) $rgb['red'] = mt_rand(0, 255);
$rgb['green'] = $rgb['green'] + ((mt_rand(0,100) % 2) == 1 ? 1 : -1) * mt_rand(0, 255 - $rgb['green']);
if ($rgb['green'] < 0 || $rgb['green'] > 255) $rgb['green'] = mt_rand(0, 255);
$rgb['blue'] = $rgb['blue'] + ((mt_rand(0,100) % 2) == 1 ? 1 : -1) * mt_rand(0, 255 - $rgb['blue']);
if ($rgb['blue'] < 0 || $rgb['blue'] > 255) $rgb['blue'] = mt_rand(0, 255);
$dotColor = ImageColorAllocate($image, $rgb['red'], $rgb['green'], $rgb['blue']);
}
ImageSetPixel($image, $x, $y, $dotColor);
}
return $image;
}
/**
* @return String
* @desc generate the string
*/
function generateString() {
$string = $this->create_random_value($this -> length, $this -> captchaType);
$this -> string = $string;
return true;
}
/**
* @return void
* @desc send image header
*/
function sendHeader() {
header('Content-type: image/' . $this -> type);
}
/**
* @return String
* @desc return the string
*/
function getString() {
return $this -> string;
}
function create_random_value($length, $type = 'mixed') {
if ( ($type != 'mixed') && ($type != 'chars') && ($type != 'digits')) return false;
$rand_value = '';
while (strlen($rand_value) < $length) {
if ($type == 'digits') {
$char = mt_rand(0,9);
} else {
$char = chr(mt_rand(0,255));
}
if ($type == 'mixed') {
if (preg_match('/^[a-z0-9]$/i', $char)) $rand_value .= $char;
} elseif ($type == 'chars') {
if (preg_match('/^[a-z]$/i', $char)) $rand_value .= $char;
} elseif ($type == 'digits') {
if (preg_match('/^[0-9]$/i', $char)) $rand_value .= $char;
}
}
return $rand_value;
}
}
|