php ob ocr,CaptchaBuilder.php

namespace Gregwar\Captcha;

use \Exception;

/**

* Builds a new captcha image

* Uses the fingerprint parameter, if one is passed, to generate the same image

*

* @author Gregwar

* @author Jeremy Livingston

*/

class CaptchaBuilder implements CaptchaBuilderInterface

{

/**

* @var array

*/

protected $fingerprint = array();

/**

* @var bool

*/

protected $useFingerprint = false;

/**

* @var array

*/

protected $textColor = null;

/**

* @var array

*/

protected $backgroundColor = null;

/**

* @var array

*/

protected $backgroundImages = array();

/**

* @var resource

*/

protected $contents = null;

/**

* @var string

*/

protected $phrase = null;

/**

* @var PhraseBuilderInterface

*/

protected $builder;

/**

* @var bool

*/

protected $distortion = true;

/**

* The maximum number of lines to draw in front of

* the image. null - use default algorithm

*/

protected $maxFrontLines = null;

/**

* The maximum number of lines to draw behind

* the image. null - use default algorithm

*/

protected $maxBehindLines = null;

/**

* The maximum angle of char

*/

protected $maxAngle = 8;

/**

* The maximum offset of char

*/

protected $maxOffset = 5;

/**

* Is the interpolation enabled ?

*

* @var bool

*/

protected $interpolation = true;

/**

* Ignore all effects

*

* @var bool

*/

protected $ignoreAllEffects = false;

/**

* Allowed image types for the background images

*

* @var array

*/

protected $allowedBackgroundImageTypes = array('image/png', 'image/jpeg', 'image/gif');

/**

* The image contents

*/

public function getContents()

{

return $this->contents;

}

/**

* Enable/Disables the interpolation

*

* @param $interpolate bool True to enable, false to disable

*

* @return CaptchaBuilder

*/

public function setInterpolation($interpolate = true)

{

$this->interpolation = $interpolate;

return $this;

}

/**

* Temporary dir, for OCR check

*/

public $tempDir = 'temp/';

public function __construct($phrase = null, PhraseBuilderInterface $builder = null)

{

if ($builder === null) {

$this->builder = new PhraseBuilder;

} else {

$this->builder = $builder;

}

if ($phrase === null) {

$phrase = $this->builder->build();

}

$this->phrase = $phrase;

}

/**

* Setting the phrase

*/

public function setPhrase($phrase)

{

$this->phrase = (string) $phrase;

}

/**

* Enables/disable distortion

*/

public function setDistortion($distortion)

{

$this->distortion = (bool) $distortion;

return $this;

}

public function setMaxBehindLines($maxBehindLines)

{

$this->maxBehindLines = $maxBehindLines;

return $this;

}

public function setMaxFrontLines($maxFrontLines)

{

$this->maxFrontLines = $maxFrontLines;

return $this;

}

public function setMaxAngle($maxAngle)

{

$this->maxAngle = $maxAngle;

return $this;

}

public function setMaxOffset($maxOffset)

{

$this->maxOffset = $maxOffset;

return $this;

}

/**

* Gets the captcha phrase

*/

public function getPhrase()

{

return $this->phrase;

}

/**

* Returns true if the given phrase is good

*/

public function testPhrase($phrase)

{

return ($this->builder->niceize($phrase) == $this->builder->niceize($this->getPhrase()));

}

/**

* Instantiation

*/

public static function create($phrase = null)

{

return new self($phrase);

}

/**

* Sets the text color to use

*/

public function setTextColor($r, $g, $b)

{

$this->textColor = array($r, $g, $b);

return $this;

}

/**

* Sets the background color to use

*/

public function setBackgroundColor($r, $g, $b)

{

$this->backgroundColor = array($r, $g, $b);

return $this;

}

/**

* Sets the ignoreAllEffects value

*

* @param bool $ignoreAllEffects

* @return CaptchaBuilder

*/

public function setIgnoreAllEffects($ignoreAllEffects)

{

$this->ignoreAllEffects = $ignoreAllEffects;

return $this;

}

/**

* Sets the list of background images to use (one image is randomly selected)

*/

public function setBackgroundImages(array $backgroundImages)

{

$this->backgroundImages = $backgroundImages;

return $this;

}

/**

* Draw lines over the image

*/

protected function drawLine($image, $width, $height, $tcol = null)

{

if ($tcol === null) {

$tcol = imagecolorallocate($image, $this->rand(100, 255), $this->rand(100, 255), $this->rand(100, 255));

}

if ($this->rand(0, 1)) { // Horizontal

$Xa = $this->rand(0, $width/2);

$Ya = $this->rand(0, $height);

$Xb = $this->rand($width/2, $width);

$Yb = $this->rand(0, $height);

} else { // Vertical

$Xa = $this->rand(0, $width);

$Ya = $this->rand(0, $height/2);

$Xb = $this->rand(0, $width);

$Yb = $this->rand($height/2, $height);

}

imagesetthickness($image, $this->rand(1, 3));

imageline($image, $Xa, $Ya, $Xb, $Yb, $tcol);

}

/**

* Apply some post effects

*/

protected function postEffect($image)

{

if (!function_exists('imagefilter')) {

return;

}

if ($this->backgroundColor != null || $this->textColor != null) {

return;

}

// Negate ?

if ($this->rand(0, 1) == 0) {

imagefilter($image, IMG_FILTER_NEGATE);

}

// Edge ?

if ($this->rand(0, 10) == 0) {

imagefilter($image, IMG_FILTER_EDGEDETECT);

}

// Contrast

imagefilter($image, IMG_FILTER_CONTRAST, $this->rand(-50, 10));

// Colorize

if ($this->rand(0, 5) == 0) {

imagefilter($image, IMG_FILTER_COLORIZE, $this->rand(-80, 50), $this->rand(-80, 50), $this->rand(-80, 50));

}

}

/**

* Writes the phrase on the image

*/

protected function writePhrase($image, $phrase, $font, $width, $height)

{

$length = strlen($phrase);

if ($length === 0) {

return imagecolorallocate($image, 0, 0, 0);

}

// Gets the text size and start position

$size = $width / $length - $this->rand(0, 3) - 1;

$box = imagettfbbox($size, 0, $font, $phrase);

$textWidth = $box[2] - $box[0];

$textHeight = $box[1] - $box[7];

$x = ($width - $textWidth) / 2;

$y = ($height - $textHeight) / 2 + $size;

if (!count($this->textColor)) {

$textColor = array($this->rand(0, 150), $this->rand(0, 150), $this->rand(0, 150));

} else {

$textColor = $this->textColor;

}

$col = imagecolorallocate($image, $textColor[0], $textColor[1], $textColor[2]);

// Write the letters one by one, with random angle

for ($i=0; $i

$box = imagettfbbox($size, 0, $font, $phrase[$i]);

$w = $box[2] - $box[0];

$angle = $this->rand(-$this->maxAngle, $this->maxAngle);

$offset = $this->rand(-$this->maxOffset, $this->maxOffset);

imagettftext($image, $size, $angle, $x, $y + $offset, $col, $font, $phrase[$i]);

$x += $w;

}

return $col;

}

/**

* Try to read the code against an OCR

*/

public function isOCRReadable()

{

if (!is_dir($this->tempDir)) {

@mkdir($this->tempDir, 0755, true);

}

$tempj = $this->tempDir . uniqid('captcha', true) . '.jpg';

$tempp = $this->tempDir . uniqid('captcha', true) . '.pgm';

$this->save($tempj);

shell_exec("convert $tempj $tempp");

$value = trim(strtolower(shell_exec("ocrad $tempp")));

@unlink($tempj);

@unlink($tempp);

return $this->testPhrase($value);

}

/**

* Builds while the code is readable against an OCR

*/

public function buildAgainstOCR($width = 150, $height = 40, $font = null, $fingerprint = null)

{

do {

$this->build($width, $height, $font, $fingerprint);

} while ($this->isOCRReadable());

}

/**

* Generate the image

*/

public function build($width = 150, $height = 40, $font = null, $fingerprint = null)

{

if (null !== $fingerprint) {

$this->fingerprint = $fingerprint;

$this->useFingerprint = true;

} else {

$this->fingerprint = array();

$this->useFingerprint = false;

}

if ($font === null) {

$font = __DIR__ . '/Font/captcha'.$this->rand(0, 5).'.ttf';

}

if (empty($this->backgroundImages)) {

// if background images list is not set, use a color fill as a background

$image = imagecreatetruecolor($width, $height);

if ($this->backgroundColor == null) {

$bg = imagecolorallocate($image, $this->rand(200, 255), $this->rand(200, 255), $this->rand(200, 255));

} else {

$color = $this->backgroundColor;

$bg = imagecolorallocate($image, $color[0], $color[1], $color[2]);

}

$this->background = $bg;

imagefill($image, 0, 0, $bg);

} else {

// use a random background image

$randomBackgroundImage = $this->backgroundImages[rand(0, count($this->backgroundImages)-1)];

$imageType = $this->validateBackgroundImage($randomBackgroundImage);

$image = $this->createBackgroundImageFromType($randomBackgroundImage, $imageType);

}

// Apply effects

if (!$this->ignoreAllEffects) {

$square = $width * $height;

$effects = $this->rand($square/3000, $square/2000);

// set the maximum number of lines to draw in front of the text

if ($this->maxBehindLines != null && $this->maxBehindLines > 0) {

$effects = min($this->maxBehindLines, $effects);

}

if ($this->maxBehindLines !== 0) {

for ($e = 0; $e < $effects; $e++) {

$this->drawLine($image, $width, $height);

}

}

}

// Write CAPTCHA text

$color = $this->writePhrase($image, $this->phrase, $font, $width, $height);

// Apply effects

if (!$this->ignoreAllEffects) {

$square = $width * $height;

$effects = $this->rand($square/3000, $square/2000);

// set the maximum number of lines to draw in front of the text

if ($this->maxFrontLines != null && $this->maxFrontLines > 0) {

$effects = min($this->maxFrontLines, $effects);

}

if ($this->maxFrontLines !== 0) {

for ($e = 0; $e < $effects; $e++) {

$this->drawLine($image, $width, $height, $color);

}

}

}

// Distort the image

if ($this->distortion && !$this->ignoreAllEffects) {

$image = $this->distort($image, $width, $height, $bg);

}

// Post effects

if (!$this->ignoreAllEffects) {

$this->postEffect($image);

}

$this->contents = $image;

return $this;

}

/**

* Distorts the image

*/

public function distort($image, $width, $height, $bg)

{

$contents = imagecreatetruecolor($width, $height);

$X = $this->rand(0, $width);

$Y = $this->rand(0, $height);

$phase = $this->rand(0, 10);

$scale = 1.1 + $this->rand(0, 10000) / 30000;

for ($x = 0; $x < $width; $x++) {

for ($y = 0; $y < $height; $y++) {

$Vx = $x - $X;

$Vy = $y - $Y;

$Vn = sqrt($Vx * $Vx + $Vy * $Vy);

if ($Vn != 0) {

$Vn2 = $Vn + 4 * sin($Vn / 30);

$nX = $X + ($Vx * $Vn2 / $Vn);

$nY = $Y + ($Vy * $Vn2 / $Vn);

} else {

$nX = $X;

$nY = $Y;

}

$nY = $nY + $scale * sin($phase + $nX * 0.2);

if ($this->interpolation) {

$p = $this->interpolate(

$nX - floor($nX),

$nY - floor($nY),

$this->getCol($image, floor($nX), floor($nY), $bg),

$this->getCol($image, ceil($nX), floor($nY), $bg),

$this->getCol($image, floor($nX), ceil($nY), $bg),

$this->getCol($image, ceil($nX), ceil($nY), $bg)

);

} else {

$p = $this->getCol($image, round($nX), round($nY), $bg);

}

if ($p == 0) {

$p = $bg;

}

imagesetpixel($contents, $x, $y, $p);

}

}

return $contents;

}

/**

* Saves the Captcha to a jpeg file

*/

public function save($filename, $quality = 90)

{

imagejpeg($this->contents, $filename, $quality);

}

/**

* Gets the image GD

*/

public function getGd()

{

return $this->contents;

}

/**

* Gets the image contents

*/

public function get($quality = 90)

{

ob_start();

$this->output($quality);

return ob_get_clean();

}

/**

* Gets the HTML inline base64

*/

public function inline($quality = 90)

{

return 'data:image/jpeg;base64,' . base64_encode($this->get($quality));

}

/**

* Outputs the image

*/

public function output($quality = 90)

{

imagejpeg($this->contents, null, $quality);

}

/**

* @return array

*/

public function getFingerprint()

{

return $this->fingerprint;

}

/**

* Returns a random number or the next number in the

* fingerprint

*/

protected function rand($min, $max)

{

if (!is_array($this->fingerprint)) {

$this->fingerprint = array();

}

if ($this->useFingerprint) {

$value = current($this->fingerprint);

next($this->fingerprint);

} else {

$value = mt_rand($min, $max);

$this->fingerprint[] = $value;

}

return $value;

}

/**

* @param $x

* @param $y

* @param $nw

* @param $ne

* @param $sw

* @param $se

*

* @return int

*/

protected function interpolate($x, $y, $nw, $ne, $sw, $se)

{

list($r0, $g0, $b0) = $this->getRGB($nw);

list($r1, $g1, $b1) = $this->getRGB($ne);

list($r2, $g2, $b2) = $this->getRGB($sw);

list($r3, $g3, $b3) = $this->getRGB($se);

$cx = 1.0 - $x;

$cy = 1.0 - $y;

$m0 = $cx * $r0 + $x * $r1;

$m1 = $cx * $r2 + $x * $r3;

$r = (int) ($cy * $m0 + $y * $m1);

$m0 = $cx * $g0 + $x * $g1;

$m1 = $cx * $g2 + $x * $g3;

$g = (int) ($cy * $m0 + $y * $m1);

$m0 = $cx * $b0 + $x * $b1;

$m1 = $cx * $b2 + $x * $b3;

$b = (int) ($cy * $m0 + $y * $m1);

return ($r << 16) | ($g << 8) | $b;

}

/**

* @param $image

* @param $x

* @param $y

*

* @return int

*/

protected function getCol($image, $x, $y, $background)

{

$L = imagesx($image);

$H = imagesy($image);

if ($x < 0 || $x >= $L || $y < 0 || $y >= $H) {

return $background;

}

return imagecolorat($image, $x, $y);

}

/**

* @param $col

*

* @return array

*/

protected function getRGB($col)

{

return array(

(int) ($col >> 16) & 0xff,

(int) ($col >> 8) & 0xff,

(int) ($col) & 0xff,

);

}

/**

* Validate the background image path. Return the image type if valid

*

* @param string $backgroundImage

* @return string

* @throws Exception

*/

protected function validateBackgroundImage($backgroundImage)

{

// check if file exists

if (!file_exists($backgroundImage)) {

$backgroundImageExploded = explode('/', $backgroundImage);

$imageFileName = count($backgroundImageExploded) > 1? $backgroundImageExploded[count($backgroundImageExploded)-1] : $backgroundImage;

throw new Exception('Invalid background image: ' . $imageFileName);

}

// check image type

$finfo = finfo_open(FILEINFO_MIME_TYPE); // return mime type ala mimetype extension

$imageType = finfo_file($finfo, $backgroundImage);

finfo_close($finfo);

if (!in_array ($imageType, $this->allowedBackgroundImageTypes)) {

throw new Exception('Invalid background image type! Allowed types are: ' . join(', ', $this->allowedBackgroundImageTypes));

}

return $imageType;

}

/**

* Create background image from type

*

* @param string $backgroundImage

* @param string $imageType

* @return resource

* @throws Exception

*/

protected function createBackgroundImageFromType($backgroundImage, $imageType)

{

switch ($imageType) {

case 'image/jpeg':

$image = imagecreatefromjpeg($backgroundImage);

break;

case 'image/png':

$image = imagecreatefrompng($backgroundImage);

break;

case 'image/gif':

$image = imagecreatefromgif($backgroundImage);

break;

default:

throw new Exception('Not supported file type for background image!');

break;

}

return $image;

}

}

一键复制

编辑

Web IDE

原始数据

按行查看

历史

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值