i have following captcha code:
<?php
class CaptchaView extends View
{
private $fontsDir = 'captcha_resources/fonts/';
private $backgroundsDir = 'captcha_resources/backgrounds/';
private static $dirCache = array();
public function render($controller)
{
$code = $controller->viewVars["code"];
/**
* The next part is orginnaly written by ted from mastercode.nl and modified for using in this mod.
**/
header("content-type:image/png");
header('Cache-control: no-cache, no-store');
$width = 100;
$height = 30;
$img = imagecreatefrompng(self::backgroundImage());
// add noise
for ($i = 0; $i < 1; $i++) {
$horizontal_progress = 0;
$vertical_pos = rand(1, $height / 2);
do {
$horizontal_step_size = floor(rand(1, $width / 5));
imageline($img, $horizontal_progress, $vertical_pos, ($horizontal_progress += $horizontal_step_size), ($vertical_pos = rand(1, $height)), self::color("tekst"));
} while ($horizontal_progress < $width);
}
$background = imagecolorallocate($img, self::color("bg"), self::color("bg"), self::color("bg"));
for ($g = 0; $g < 30; $g++) {
$t = rand(10, 20);
$t = $t[0];
$ypos = rand(0, $height);
$xpos = rand(0, $width);
$kleur = imagecolorallocate($img, self::color("bgtekst"), self::color("bgtekst"), self::color("bgtekst"));
imagettftext($img, self::size(), self::move(), $xpos, $ypos, $kleur, self::font(), $t);
}
$stukje = $width / (strlen($code) + 3) + 5;
for ($j = 0; $j < strlen($code); $j++) {
$tek = $code[$j];
$ypos = rand(23, 27);
$xpos = $stukje * ($j + 1) - 5;
$color2 = imagecolorallocate($img, self::color("tekst"), self::color("tekst"), self::color("tekst"));
imagettftext($img, self::size(), self::move(), $xpos, $ypos, $color2, self::font(), $tek);
}
imagepng($img);
imagedestroy($img);
}
/**
* Some functions :)
* Also orginally written by mastercode.nl
**/
/**
* Function to create a random color
* #auteur mastercode.nl
* #param $type string Mode for the color
* #return int
**/
private static function color($type)
{
switch ($type) {
case "bg":
$color = rand(224, 255);
break;
case "tekst":
$color = rand(0, 127);
break;
case "bgtekst":
$color = rand(200, 224);
break;
default:
$color = rand(0, 255);
break;
}
return $color;
}
/**
* Function to ranom the size
* #auteur mastercode.nl
* #return int
**/
private static function size()
{
return rand(18, 22);
}
/**
* Function to random the posistion
* #auteur mastercode.nl
* #return int
**/
private static function move()
{
return rand(-22, 22);
}
/**
* Function to return a ttf file from fonts map
* #auteur mastercode.nl
* #return string
**/
function randomFileByExt($dir, $ext)
{
$f = opendir($dir);
if (empty(self::$dirCache[$dir])) {
$ar = array();
while (($file = #readdir($f)) !== false) {
if (!in_array($file, array('.', '..')) && substr_compare($file, $ext, -strlen($ext)) == 0) {
$ar[] = $file;
}
}
self::$dirCache[$dir] = $ar;
} else {
$ar = self::$dirCache[$dir];
}
if (count($ar)) {
$i = rand(0, (count($ar) - 1));
return $dir . $ar[$i];
}
}
private function backgroundImage()
{
return self::randomFileByExt(Config::get("VIEWS_PATH") . $this->backgroundsDir, ".png");
}
private function font()
{
return self::randomFileByExt(Config::get("VIEWS_PATH") . $this->fontsDir, ".ttf");
}
}
actually it display 4 letters with a disturbed background
i want block some spam bot them i think to modify code to increase security increasing number of letters
can you tell me how to modify it to display 6 letters instead of 4?
1) Best solution is to implement existing Captcha like reCaptcha or so..
docs : http://code.google.com/intl/en_EN/apis/recaptcha/intro.html
PHP : http://code.google.com/intl/en_EN/apis/recaptcha/docs/php.html
2) To modify your code to push 6 instead of 4 letters edit part of code like this:
$stukje = $width / (strlen($code) + 5) + 5; //instead of "+3) +5;"
should do the trick, but I can't test it, since I don't know in which mod it was used (what CMS, PHP Framework,...)
Related
Hello i am learning php now and developing website for my education. I am facing problem if i try to add captcha image. I don't know where is the problem but instead of working captcha i get blank page.
I even tried few already done captchas from github but get same problem i think the problem could be with fonts but i am not sure "ts probably my stupidity and i am doing something wrong :D" . Anyway if anyone can help me with it it would be great.
code i tried to use:
captcha.php
<?php
class captcha {
private static $captcha = "__captcha__";
public static $font;
private static $width = 70;
private static $height = 70;
private static $font_size = 40;
private static $character_width = 40;
private static function session_exists() {
return isset($_SESSION);
}
private static function set_font() {
self::$font = self::$captcha;
$AnonymousClippings ='there is inserted chars from font you can';
self::$font = tempnam(sys_get_temp_dir(), self::$captcha);
$handle = fopen(self::$font,"w+");
fwrite($handle,base64_decode($AnonymousClippings));
fclose($handle);
return self::$font;
}
private static function get_random() {
$type = rand(0,2);
switch($type) {
case 2:
$random = chr(rand(65,90));
break;
case 1:
$random = chr(rand(97,122));
break;
default:
$random = rand(0,9);
}
return $random;
}
private static function generate_code($length) {
$code = null;
for($i = 0; $i < $length; $i++) {
$code .= self::get_random();
}
if(self::session_exists()) {
$_SESSION[self::$captcha] = $code;
}
self::$width = $length * self::$character_width;
return $code;
}
private static function get_width() {
return self::$width;
}
private static function get_height() {
return self::$height;
}
public static function image() {
$length = 6;
$code = self::generate_code($length);
self::set_font();
ob_start();
$image = imagecreatetruecolor(self::get_width(),self::get_height());
$white = imagecolorallocate($image, 255, 255, 255);
imagefilledrectangle($image, 0, 0, self::get_width(), self::get_height(), $white);
for($dot = 0; $dot < 2000; $dot++) {
$r = rand(0,255);
$g = rand(0,255);
$b = rand(0,255);
$dot_color = imagecolorallocate($image, $r, $g, $b);
$x1 = rand(0, self::get_width());
$y1 = rand(0, self::get_height());
$x2 = $x1 + 1;
$y2 = $y1 + 1;
imageline($image, $x1, $y1, $x2, $y2, $dot_color);
}
for($start = - $length; $start < 0; $start++) {
$color = imagecolorallocate($image, rand(0,177), rand(0,177), rand(0,177));
$character = substr($code, $start, 1);
$x = ($start+6) * self::$character_width;
$y = rand(self::get_height() - 20, self::get_height() - 10);
imagettftext($image, self::$font_size, 0, $x, $y, $color, self::$font, $character);
}
imagepng($image);
imagedestroy($image);
$source = ob_get_contents();
ob_end_clean();
unlink(self::$font);
return "data:image/png;base64,".base64_encode($source);
}
public static function get_code() {
if(self::session_exists()) {
return $_SESSION[self::$captcha];
}
return rand();
}
}
index.php file
<?php
session_start();
require_once("captcha.php");
if(isset($_POST['rCaptcha'])) {
echo captcha::image();
exit;
}
else if(isset($_POST["code"])) {
if($_POST["code"] == captcha::get_code()) {
echo "Good";
}
else {
echo "Bad";
}
echo "<br/>";
}
?>
<script>
function refreshCaptcha(target) {
var req = new XMLHttpRequest();
req.open("POST", window.location, true);
req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
req.onreadystatechange = function() {
if(req.readyState == 4 && req.status == 200) {
target.src = req.responseText;
}
}
req.send("rCaptcha=true");
}
</script>
<form method="post" autocomplete="off">
<fieldset>
<legend>PHP Captcha</legend>
<input type="text" name="code" placeholder="Captcha Code" /><br/>
<img src="<?= captcha::image() ?>" onclick="refreshCaptcha(this)"
title="click to refresh" /><br/>
<input type="submit" value="Check" /><br/>
</fieldset>
</form>
For a start add those two lines in the beginning of your index.php file (after <?php):
error_reporting(-1);
ini_set('display_errors', 'On');
Then you will see the errors produced by php. It will be much more easy to debug your code!
In this case a semicolon is missing in line 16 in your captcha.php file:
$AnonymousClippings ='there is inserted chars from font you can'
I am using ImageMagic for a project, Since i use windows i installed wamp, i want to convert some text into images, insert effects and make an animated gif out of it, i tried various folder options finally ended up with this, which does not work as well. Can someone help? the code which i am using right now is "D:\Program Files\EasyPHP\data\localweb\imgmgk\convert" -background "" -fill "#000" -font Arial -pointsize 12 label:" hi casino" "D:\Program Files\EasyPHP\data\localweb\files\bum.jpg" a link to ImageMagick http://www.imagemagick.org/script/convert.php
Try Imagick,
Imagick is a native php extension to create and modify images using the ImageMagick API.
ImageMagick is a software suite to create, edit, and compose bitmap images.. It can read, convert and write images in a variety of formats (over 100) including DPX, EXR, GIF, JPEG, JPEG-2000, PDF, PhotoCD, PNG, Postscript, SVG, and TIFF.
By using this, we have an example.
whirlyGif
function lerp($t, $a, $b)
{
return $a + ($t * ($b - $a));
}
class Dot
{
public function __construct($color, $sequence, $numberDots, $imageWidth, $imageHeight)
{
$this->color = $color;
$this->sequence = $sequence;
$this->numberDots = $numberDots;
$this->imageWidth = $imageWidth;
$this->imageHeight = $imageHeight;
if ($this->numberDots < 0) {
$this->numberDots = 0;
}
}
public function calculateFraction($frame, $maxFrames, $timeOffset, $phaseMultiplier, $phaseDivider)
{
$frame = -$frame;
$totalAngle = 2 * $phaseMultiplier;
$fraction = ($frame / $maxFrames * 2);
$fraction += $totalAngle * ($this->sequence / $this->numberDots);
if ($phaseDivider != 0) {
$fraction += (($this->sequence)) / ($phaseDivider);
}
$fraction += $timeOffset;
while ($fraction < 0) {
//fmod does not work 'correctly' on negative numbers
$fraction += 64;
}
$fraction = fmod($fraction, 2);
if ($fraction > 1) {
$unitFraction = 2 - $fraction;
}
else {
$unitFraction = $fraction;
}
return $unitFraction * $unitFraction * (3 - 2 * $unitFraction);
}
public function render(\ImagickDraw $draw, $frame, $maxFrames, $phaseMultiplier, $phaseDivider)
{
$innerDistance = 40;
$outerDistance = 230;
$sequenceFraction = $this->sequence / $this->numberDots;
$angle = 2 * M_PI * $sequenceFraction;
$trailSteps = 5;
$trailLength = 0.1;
$offsets = [
100 => 0,
];
for ($i=0; $i<=$trailSteps; $i++) {
$key = intval(50 * $i / $trailSteps);
$offsets[$key] = $trailLength * ($trailSteps - $i) / $trailSteps;
}
//TODO - using a pattern would make the circles look more natural
//$draw->setFillPatternURL();
foreach ($offsets as $alpha => $offset) {
$distanceFraction = $this->calculateFraction($frame, $maxFrames, $offset, $phaseMultiplier, $phaseDivider);
$distance = lerp($distanceFraction, $innerDistance, $outerDistance);
$xOffset = $distance * sin($angle);
$yOffset = $distance * cos($angle);
$draw->setFillColor($this->color);
$draw->setFillAlpha($alpha / 100);
$xOffset = $xOffset * $this->imageWidth / 500;
$yOffset = $yOffset * $this->imageHeight / 500;
$xSize = 4 * $this->imageWidth / 500;
$ySize = 4 * $this->imageHeight / 500;
$draw->circle(
$xOffset,
$yOffset,
$xOffset + $xSize,
$yOffset + $ySize
);
}
}
}
function whirlyGif($numberDots, $numberFrames, $loopTime, $backgroundColor, $phaseMultiplier, $phaseDivider)
{
$aniGif = new \Imagick();
$aniGif->setFormat("gif");
$width = 500;
$height = $width;
$numberDots = intval($numberDots);
if ($numberDots < 1) {
$numberDots = 1;
}
$maxFrames = $numberFrames;
$frameDelay = ceil($loopTime / $maxFrames);
$scale = 1;
$startColor = new \ImagickPixel('red');
$dots = [];
for ($i=0; $i<$numberDots; $i++) {
$colorInfo = $startColor->getHSL();
//Rotate the hue by 180 degrees
$newHue = $colorInfo['hue'] + ($i / $numberDots);
if ($newHue > 1) {
$newHue = $newHue - 1;
}
//Set the ImagickPixel to the new color
$color = new \ImagickPixel('#ffffff');
$colorInfo['saturation'] *= 0.95;
$color->setHSL($newHue, $colorInfo['saturation'], $colorInfo['luminosity']);
$dots[] = new Dot($color, $i, $numberDots, $width, $height);
}
for ($frame = 0; $frame < $maxFrames; $frame++) {
$draw = new \ImagickDraw();
$draw->setStrokeColor('none');
$draw->setFillColor('none');
$draw->rectangle(0, 0, $width, $height);
$draw->translate($width / 2, $height / 2);
foreach ($dots as $dot) {
/** #var $dot Dot */
$dot->render($draw, $frame, $maxFrames, $phaseMultiplier, $phaseDivider);
}
//Create an image object which the draw commands can be rendered into
$imagick = new \Imagick();
$imagick->newImage($width * $scale, $height * $scale, $backgroundColor);
$imagick->setImageFormat("png");
$imagick->setImageDispose(\Imagick::DISPOSE_PREVIOUS);
//Render the draw commands in the ImagickDraw object
//into the image.
$imagick->drawImage($draw);
$imagick->setImageDelay($frameDelay);
$aniGif->addImage($imagick);
$imagick->destroy();
}
$aniGif->setImageFormat('gif');
$aniGif->setImageIterations(0); //loop forever
$aniGif->mergeImageLayers(\Imagick::LAYERMETHOD_OPTIMIZEPLUS);
header("Content-Type: image/gif");
echo $aniGif->getImagesBlob();
}
The output will be
You can find more examples here
Sorted! Thanks a lot for helping me out.
There was one file which i could not get from the tutorial url, here is the alternate link.
http://windows.php.net/downloads/pecl/releases/imagick/3.1.2/php_imagick-3.1.2-5.5-ts-vc11-x86.zip
I am trying to draw a hex using PHP. I have been trying to follow the manual from http://www.redblobgames.com/grids/hexagons/ supporting myself with leland hex generation class (https://github.com/pushcx/leland/blob/master/class_hex_image.php).
Unluckily my "hex" looks like this:
Can you please advice what am I doing wrong or tell me how can I create a proper hex?
It seems to me that function which grabs hex corners does not work correctly:
function hex_corners($center, $size)
{
$points = array();
for($i=0; $i <= 5; $i++)
{
$deg = 60 * $i; // Oblicz kąt, w którym znajduje sie róg hexu
$rad = pi() / 180 * $deg; // Przelicz kąt na radiany
$points[$i] = array_push($points, $center['x'] + $this->size / 2 * cos($rad), $center['y'] + $this->size / 2 * sin($rad));
}
return($points);
}
but I have tried to mimic the one described in http://www.redblobgames.com/grids/hexagons/ manual:
function hex_corner(center, size, i):
var angle_deg = 60 * i
var angle_rad = PI / 180 * angle_deg
return Point(center.x + size * cos(angle_rad),
center.y + size * sin(angle_rad))
I am using the following draw function:
public function hex_draw($x, $y)
{
$this->hex = imagecreatetruecolor ($this->size , $this->size);
$center['x'] = $this->size / 2;
$center['y'] = $this->size / 2;
$blue = imagecolorallocate($this->hex, 0, 0, 255);
// Get points
$points = $this->hex_corners($center, $this->size);
//die($print_r($points);
imagefilledpolygon($this->hex, $points, count($points)/2, $blue);
// flush image
header('Content-type: image/png');
imagepng($this->hex);
imagedestroy($this->hex);
}
My error was trivial.
In line
$points[$i] = array_push($points, $center['x'] + $this->size / 2 * cos($rad), $center['y'] + $this->size / 2 * sin($rad));
there was unneeded [$i] which caused problems.
Hex may be properly generated using the following code:
<?php
class hexmapimage
{
private $size = 100;
private $hex;
public function hex_draw($x, $y)
{
$this->hex = imagecreatetruecolor ($this->size , $this->size);
$center['x'] = $this->size / 2;
$center['y'] = $this->size / 2;
$black = imagecolorallocate($this->hex, 0, 0, 0);
$blue = imagecolorallocate($this->hex, 0, 0, 255);
$transparent = imagecolortransparent ($this->hex, $black);
// Get points
$points = $this->hex_corners($center, $this->size);
imagefilledrectangle($this->hex, 0, 0, $this->size, $this->size, $transparent);
imagefilledpolygon($this->hex, $points, count($points)/2, $blue);
// flush image
header('Content-type: image/png');
imagepng($this->hex);
imagedestroy($this->hex);
}
/*
* $center = array(x coordinate of center of hex, y coordinate of center of hex)
* $size = int (size of hex)
*/
function hex_corners($center, $size)
{
$points = array();
for($i=0; $i <= 5; $i++)
{
$deg = 60 * $i; // Oblicz kąt, w którym znajduje sie róg hexu
$rad = deg2rad($deg); // Przelicz kąt na radiany
array_push($points, $center['x'] + $this->size / 2 * cos($rad), $center['y'] + $this->size / 2 * sin($rad));
}
return($points);
}
}
$hex = new hexmapimage();
$hex->hex_draw(0, 0);
My objective with this script is to make smart thumbnails. In my demo package, I am using two scripts from different sources.
To crop thumbnails (Source) - It totally works like native wordpress thumbnails
Face Detection in PHP (Source)
I am using the Face Detection to get the desired coordinates (where the face is) and then feed the coordinates to the crop script to make a thumbnail.
The problem is, if the Face Detection script does not find a face, it'd just time-out with the time out error
Fatal error: Maximum execution time of 30 seconds exceeded in...
I do not know how to come around this issue.
Is there any way to limit the amount of time the face detector takes to detect? I mean, if not found in like 15 seconds, return null.
Here's the Face Detection code:
<?php
//
// 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.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// #Author Karthik Tharavaad
// karthik_tharavaad#yahoo.com
// #Contributor Maurice Svay
// maurice#svay.Com
namespace svay;
use Exception;
class FaceDetector
{
protected $detection_data;
protected $canvas;
protected $face;
private $reduced_canvas;
/**
* Creates a face-detector with the given configuration
*
* Configuration can be either passed as an array or as
* a filepath to a serialized array file-dump
*
* #param string|array $detection_data
*/
public function __construct($detection_data = 'detection.dat')
{
if (is_array($detection_data)) {
$this->detection_data = $detection_data;
return;
}
if (!is_file($detection_data)) {
// fallback to same file in this class's directory
$detection_data = dirname(__FILE__) . DIRECTORY_SEPARATOR . $detection_data;
if (!is_file($detection_data)) {
throw new \Exception("Couldn't load detection data");
}
}
$this->detection_data = unserialize(file_get_contents($detection_data));
}
public function faceDetect($file)
{
if (is_resource($file)) {
$this->canvas = $file;
} elseif (is_file($file)) {
//getting extension type (jpg, png, etc)
$type = explode(".", $file);
$ext = strtolower($type[sizeof($type)-1]);
$ext = (!in_array($ext, array("jpeg","png","gif"))) ? "jpeg" : $ext;
if ($ext == 'jpeg') {
$this->canvas = imagecreatefromjpeg($file);
} else if ($ext == 'png') {
$this->canvas = imagecreatefrompng($file);
} else if ($ext == 'gif') {
$this->canvas = imagecreatefromgif($file);
}
} else {
throw new Exception("Can not load $file");
}
$im_width = imagesx($this->canvas);
$im_height = imagesy($this->canvas);
//Resample before detection?
$diff_width = 320 - $im_width;
$diff_height = 240 - $im_height;
if ($diff_width > $diff_height) {
$ratio = $im_width / 320;
} else {
$ratio = $im_height / 240;
}
if ($ratio != 0) {
$this->reduced_canvas = imagecreatetruecolor($im_width / $ratio, $im_height / $ratio);
imagecopyresampled(
$this->reduced_canvas,
$this->canvas,
0,
0,
0,
0,
$im_width / $ratio,
$im_height / $ratio,
$im_width,
$im_height
);
$stats = $this->getImgStats($this->reduced_canvas);
$this->face = $this->doDetectGreedyBigToSmall(
$stats['ii'],
$stats['ii2'],
$stats['width'],
$stats['height']
);
if ($this->face['w'] > 0) {
$this->face['x'] *= $ratio;
$this->face['y'] *= $ratio;
$this->face['w'] *= $ratio;
}
} else {
$stats = $this->getImgStats($this->canvas);
$this->face = $this->doDetectGreedyBigToSmall(
$stats['ii'],
$stats['ii2'],
$stats['width'],
$stats['height']
);
}
return ($this->face['w'] > 0);
}
public function toJpeg()
{
$color = imagecolorallocate($this->canvas, 255, 0, 0); //red
imagerectangle(
$this->canvas,
$this->face['x'],
$this->face['y'],
$this->face['x']+$this->face['w'],
$this->face['y']+ $this->face['w'],
$color
);
header('Content-type: image/jpeg');
imagejpeg($this->canvas);
}
public function toJson()
{
return json_encode($this->face);
}
public function getFace()
{
return $this->face;
}
protected function getImgStats($canvas)
{
$image_width = imagesx($canvas);
$image_height = imagesy($canvas);
$iis = $this->computeII($canvas, $image_width, $image_height);
return array(
'width' => $image_width,
'height' => $image_height,
'ii' => $iis['ii'],
'ii2' => $iis['ii2']
);
}
protected function computeII($canvas, $image_width, $image_height)
{
$ii_w = $image_width+1;
$ii_h = $image_height+1;
$ii = array();
$ii2 = array();
for ($i=0; $i<$ii_w; $i++) {
$ii[$i] = 0;
$ii2[$i] = 0;
}
for ($i=1; $i<$ii_h-1; $i++) {
$ii[$i*$ii_w] = 0;
$ii2[$i*$ii_w] = 0;
$rowsum = 0;
$rowsum2 = 0;
for ($j=1; $j<$ii_w-1; $j++) {
$rgb = ImageColorAt($canvas, $j, $i);
$red = ($rgb >> 16) & 0xFF;
$green = ($rgb >> 8) & 0xFF;
$blue = $rgb & 0xFF;
$grey = (0.2989*$red + 0.587*$green + 0.114*$blue)>>0; // this is what matlab uses
$rowsum += $grey;
$rowsum2 += $grey*$grey;
$ii_above = ($i-1)*$ii_w + $j;
$ii_this = $i*$ii_w + $j;
$ii[$ii_this] = $ii[$ii_above] + $rowsum;
$ii2[$ii_this] = $ii2[$ii_above] + $rowsum2;
}
}
return array('ii'=>$ii, 'ii2' => $ii2);
}
protected function doDetectGreedyBigToSmall($ii, $ii2, $width, $height)
{
$s_w = $width/20.0;
$s_h = $height/20.0;
$start_scale = $s_h < $s_w ? $s_h : $s_w;
$scale_update = 1 / 1.2;
for ($scale = $start_scale; $scale > 1; $scale *= $scale_update) {
$w = (20*$scale) >> 0;
$endx = $width - $w - 1;
$endy = $height - $w - 1;
$step = max($scale, 2) >> 0;
$inv_area = 1 / ($w*$w);
for ($y = 0; $y < $endy; $y += $step) {
for ($x = 0; $x < $endx; $x += $step) {
$passed = $this->detectOnSubImage($x, $y, $scale, $ii, $ii2, $w, $width+1, $inv_area);
if ($passed) {
return array('x'=>$x, 'y'=>$y, 'w'=>$w);
}
} // end x
} // end y
} // end scale
return null;
}
protected function detectOnSubImage($x, $y, $scale, $ii, $ii2, $w, $iiw, $inv_area)
{
$mean = ($ii[($y+$w)*$iiw + $x + $w] + $ii[$y*$iiw+$x] - $ii[($y+$w)*$iiw+$x] - $ii[$y*$iiw+$x+$w])*$inv_area;
$vnorm = ($ii2[($y+$w)*$iiw + $x + $w]
+ $ii2[$y*$iiw+$x]
- $ii2[($y+$w)*$iiw+$x]
- $ii2[$y*$iiw+$x+$w])*$inv_area - ($mean*$mean);
$vnorm = $vnorm > 1 ? sqrt($vnorm) : 1;
$count_data = count($this->detection_data);
for ($i_stage = 0; $i_stage < $count_data; $i_stage++) {
$stage = $this->detection_data[$i_stage];
$trees = $stage[0];
$stage_thresh = $stage[1];
$stage_sum = 0;
$count_trees = count($trees);
for ($i_tree = 0; $i_tree < $count_trees; $i_tree++) {
$tree = $trees[$i_tree];
$current_node = $tree[0];
$tree_sum = 0;
while ($current_node != null) {
$vals = $current_node[0];
$node_thresh = $vals[0];
$leftval = $vals[1];
$rightval = $vals[2];
$leftidx = $vals[3];
$rightidx = $vals[4];
$rects = $current_node[1];
$rect_sum = 0;
$count_rects = count($rects);
for ($i_rect = 0; $i_rect < $count_rects; $i_rect++) {
$s = $scale;
$rect = $rects[$i_rect];
$rx = ($rect[0]*$s+$x)>>0;
$ry = ($rect[1]*$s+$y)>>0;
$rw = ($rect[2]*$s)>>0;
$rh = ($rect[3]*$s)>>0;
$wt = $rect[4];
$r_sum = ($ii[($ry+$rh)*$iiw + $rx + $rw]
+ $ii[$ry*$iiw+$rx]
- $ii[($ry+$rh)*$iiw+$rx]
- $ii[$ry*$iiw+$rx+$rw])*$wt;
$rect_sum += $r_sum;
}
$rect_sum *= $inv_area;
$current_node = null;
if ($rect_sum >= $node_thresh*$vnorm) {
if ($rightidx == -1) {
$tree_sum = $rightval;
} else {
$current_node = $tree[$rightidx];
}
} else {
if ($leftidx == -1) {
$tree_sum = $leftval;
} else {
$current_node = $tree[$leftidx];
}
}
}
$stage_sum += $tree_sum;
}
if ($stage_sum < $stage_thresh) {
return false;
}
}
return true;
}
}
Here's an example use:
include "facedetection/FaceDetector.php";
$detector = new svay\FaceDetector('detection.dat');
$detector->faceDetect($path);
$coord = $detector->getFace();
Any help or suggest other php thumbnails with face detection script.
Can you increase the time limit? You can use set_time_limit() or change your php.ini if you have access to it.
Also, how big is the detection.dat file? Loading the entire file in memory with file_get_contents() can take some time if the file is large.
Unless you mess up with the FaceDetection code (which is not recommended, unless you will never want to upgrade the library), you won't be able to stop the execution after 15 seconds. They don't provide any hooks where you could tell the script to stop.
I have an problem with PHP function imagettftext. I have code for generating card images from database with text informations. And with some cards I have problem - words are written over each other (like here).
My code looks like this (font size changes depending on the length of the text)
$length = strlen($cardInfo->description);
if ($length < 15) {
$divide = 15;
$fontSize = 16;
$lineHeight = 25;
$startPos = 220;
} else if ($length < 70) {
$divide = 25;
$fontSize = 12;
$lineHeight = 18;
$startPos = 210;
} else if ($length < 110) {
$divide = 28;
$fontSize = 10;
$lineHeight = 14;
$startPos = 210;
} else {
$divide = 38;
$fontSize = 8;
$lineHeight = 13;
$startPos = 210;
}
$description = wordwrap($cardInfo->description, $divide, ">>>");
$lines = explode(">>>", $description);
$count = 0;
foreach ($lines as $line) {
$position = $count * $lineHeight;
$count++;
imagettftext($image, $fontSize, 0, 28, ($startPos + $position), $black, $font, $line);
}
and the text in the database looks like this:
Oblehací stroj
Imunita vůči střelám /Tato jednotka je imunní vůči střeleckým zraněním/
Other problem is with the line wrapping: here. I don't know why the word "jídlo" is on the next line.
Thank you for any answers!
Long time ago, I have written a quite complex class to archive a similar task.
I don't have this code anymore, but the steps are fairly simple.
First: Don't rely on the calculations, php does on rare fonts.
Php's wordwrap-function is senseless here, because you deal with a charset-width (e.g. tracking) unknown to php. Wordwrap assumes, that all characters have the same char-width.
So, you have to build your own wordwrap-function using imagettfbbox. Then, you'll have to determine the size of the lowercase "x"-letter and the uppercase "X"-letter. These letters are the norm to calculate your own line-height/line-spacing. I also recommend you to manually separate words, since PHP does not always recognize the white-space-width correctly.
Hope this could help you...
This works for me. You need arial.ttf and http://dark-project.cz/CardDatabase/cards/lehky_katapult.png.
class Test_Canvas {
protected $res=null;
public function __construct($width, $height) {
$this->res = imagecreatetruecolor($width, $height);
imagealphablending($this->res, true);
imagesavealpha($this->res, true);
imagefill($this->res, 0, 0, imagecolorallocatealpha($this->res, 0, 0, 0, 127));
}
public function copyTo(Test_Canvas $canvas, $x, $y) {
imagecopyresampled($canvas->res, $this->res, $x, $y, 0, 0, $this->getWidth(), $this->getHeight(), $this->getWidth(), $this->getHeight());
}
public function getWidth() {
return imagesx($this->res);
}
public function getHeight() {
return imagesy($this->res);
}
public function saveAsPNG() {
imagepng($this->res);
}
}
class Test_Canvas_Image_PNG extends Test_Canvas {
public function __construct($filename) {
$res = imagecreatefrompng($filename);
$w = imagesx($res);
$h = imagesy($res);
parent::__construct($w, $h);
imagecopymerge($this->res, $res, 0, 0, 0, 0, $w, $h, 100);
}
}
class Test_Canvas_Textarea extends Test_Canvas {
private $text;
private $fontsize;
private $fontfile;
public function __construct($width, $height, $text, $fontsize, $fontfile) {
parent::__construct($width, $height);
$this->text = $text;
$this->fontsize = $fontsize;
$this->fontfile = $fontfile;
$this->removeDuplicateWhitespace();
$this->formatText();
$this->applyText();
}
private function removeDuplicateWhitespace() {
$this->text = preg_replace('/[ \t]+/', ' ', $this->text);
}
private function formatText() {
$lines = explode("\n", $this->text);
$res = array();
foreach ($lines as $line) {
$res[] = $this->insertAdditionalLinebreaks($line);
}
$this->text = join("\n", $res);
}
private function insertAdditionalLinebreaks($line) {
$words = $this->splitWords($line);
$res = array();
$line = "";
while(count($words)) {
$word = array_shift($words);
$testLine = "{$line} {$word}";
$width = $this->getTextWidth($testLine);
if($width > $this->getWidth()) {
$res[] = $line;
$line = $word;
} elseif(!count($words)) {
$res[] = $testLine;
} else {
$line = $testLine;
}
}
return join("\n", $res);
}
private function getTextWidth($text) {
$boundaries = imagettfbbox($this->fontsize, 0, $this->fontfile, $text);
$x1 = min($boundaries[0], $boundaries[6]);
$x2 = max($boundaries[2], $boundaries[4]);
return $x2 - $x1;
}
private function splitWords($text) {
return explode(' ', $text);
}
private function applyText() {
$lines = explode("\n", $this->text);
foreach($lines as $lineNo => $line) {
imagettftext($this->res, $this->fontsize, 0, 0, ($lineNo + 1) * ($this->fontsize + 5), imagecolorallocate($this->res, 0, 0, 0), $this->fontfile, $line);
}
}
}
$rootPath = dirname(__FILE__).'/';
$imageFilename = "{$rootPath}test.png";
$description = "Oblehací stroj\nImunita vuci strelám /Tato jednotka je imunní vuci streleckým zranením/ ";
$description .= $description;
$description .= $description;
header('Content-Type: image/png');
$canvas = new Test_Canvas_Image_PNG($imageFilename);
$text = new Test_Canvas_Textarea(179, 92, $description, 9, 'arial.ttf');
$text->copyTo($canvas, 25, 193);
$canvas->saveAsPNG();
You shouldn't use such estimates for the box you'll need.
The function imagettfbbox() can give you a definite answer to the box you'll need to display the text.
http://nl3.php.net/manual/en/function.imagettfbbox.php
Hope that helps.