Blank pages when trying to do captcha - php

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'

Related

Displaying generated PNG in PHP?

So I'm trying to get a generated UPC bar code to display on an index page. but all it does is output the PNG contents instead of displaying the PNG itself.
I'm not quite sure why its doing this. I'm guessing its some silly little thing i need to add but I have no clue what it would be. So any help would be appreciated.
INDEX CODE
<form method="POST">
<head>UPC Barcode and QRcode Generator</head><br>
<label for="">Type 11 Didgits Here => </label>
<input type="text" class="form-control" name="text_code">
<button type="submit" class="btn btn-primary" name="generate">Generate</button>
<hr>
<?php
//QR CODE
if(isset($_POST['generate'])){
$code = $_POST['text_code'];
echo "<img src='https://chart.googleapis.com/chart?chs=300x300&cht=qr&chl=$code&choe=UTF-8'>";}
//Barcode
include "generate.php";
$upc = new BC(null,4);
$number = $_POST['text_code'];
$upc->build($number);
echo "*".substr($code, 0,6)."#".substr($code, 6,6)."*";
?>
GENERATE CODE
<?php
class BC{//
private $height;
private $width;
private $barheight;
private $barwidth;
private $lable;
private $border;
private $padding;
private $mapcode;
private $rightmap;
private $code;
function __construct($lable=null,$barwidth=2) {//
$this->set_width($barwidth);
$this->set_lable($lable);
$this->padding = $barwidth*5;
$this->border =2;
$this->mapcode = array
('0' => '0001101', '1' => '0011001', '2' => '0010011', '3' => '0111101', '4' => '0100011',
'5' => '0110001', '6' => '0101111', '7' => '0111011', '8' => '0110111', '9' => '0001011',
'#' => '01010', '*' => '101');
$this->rightmap = array
('0' => '1110010', '1' => '1100110', '2' => '1101100', '3' => '1000010', '4' => '1011100',
'5' => '1001110', '6' => '1010000', '7' => '1000100', '8' => '1001000', '9' => '1110100',
'#' => '01010', '*' => '101');
}
public function set_width($barwidth) {//
if(is_int($barwidth)) {//
$this->barwidth = $barwidth;
}
else{//
$this->barwidth = 2;
}
}
public function set_lable($lable) {//
if(is_null($lable)) {//
$this->lable = "none";
}
else{//
$this->lable = $lable;
}
}
public function build($code = null) {//
if(is_null($code)) {//
$this->code = "00000000000";
}
else{//
$this->code = $code;
}
$this-> code = substr($code, 0, 11);
if(is_numeric($code)){//
$checksum = 0;
for($digit = 0; $digit < strlen($code); $digit++) {
if($digit%2 == 0) {//
$checksum += (int)$code[$digit] * 3;
}
else{//
$checksum += (int) $code[$digit];
}
}
$checkdigit = 10 - $checksum % 10;
$code .= $checkdigit;
$code_disp = $code;
$code = "*".substr($code, 0,6)."#".substr($code, 6,6)."*";
$this->width = $this-> barwidth*95 + $this->padding*2;
$this->barheight = $this->barwidth*95*0.75;
$this->height = $this->barwidth*95*0.75 + $this->padding*2;
$barcode = imagecreatetruecolor($this->width, $this->barheight);
$black = imagecolorallocate($barcode, 0, 0, 0);
$white = imagecolorallocate($barcode, 255, 255, 255);
imagefill($barcode, 0, 0, $black);
imagefilledrectangle($barcode, $this->border, $this->width - $this->border, -1, $this->barheight - $this->border - 1, $white);
$bar_pos = $this->padding;
for($count = 0; $count < 15; $count++) {
$character = $code [$count];
for($subcount = 0; $subcount < strlen($this->mapcode[$character]); $subcount++) {//
if($count < 7) {
$color = ($this->mapcode[$character][$subcount] == 0) ? $white : $black;
}
else{
$color = ($this->rightmap[$character][$subcount] == 0) ? $white : $black;
}
if(strlen($this->mapcode[$character]) == 7) {
$height_offset = $this->height * 0.05;
}
else {
$height_offset = 0;
}
imagefilledrectangle($barcode, $bar_pos, $this->padding, $bar_pos+$this->barwidth - 1, $this->barheight - $height_offset - $this->padding, $color);
$bar_pos += $this->barwidth;
}
imagepng($barcode);
}
}
}
}
?>
So this is the output
after adding the new code
To display an image in an HTML page, you need to use an <img /> tag. To display image contents in an <img /> tag, you need to use a Data URI Scheme.
You'll end up with something like this:
echo '<img src="data:image/png;base64,', base64_encode($the_png_contents), '" />';
I checked out your Q and in the comments you said it still is not working so I decided to have a look with you. I used your code as you posted in and used it on my own little environment to make it work. What I did is the following:
Changed I made in your index.php:
// Check if request method is post
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Check if both Generate and Text_code have been set
if(isset($_POST['generate']) && isset($_POST['text_code'])) {
// Set code used through the if statement
$code = $_POST['text_code'];
echo '<img src="https://chart.googleapis.com/chart?chs=300x300&cht=qr&chl='. $code . '&choe=UTF-8">';
// Include file; generate.php
include "generate.php";
// New instance of class; BC
$upc = new BC(null, 4);
// Set barcode base64 to variable and display
$barcodeBase64 = $upc->build($code);
echo '<img src="data:image/png;base64,' . base64_encode($barcodeBase64) . '" />';
}
}
Furthermore your generate.php needed a little change in the function build:
public function build($code = null) {
$this->code = is_null($code) ? "00000000000" : $code;
$code = substr($code, 0, 11);
$code = str_pad($code, 11, "00000000000");
if(is_numeric($code)){//
$checksum = 0;
for($digit = 0; $digit < strlen($code); $digit++) {
if($digit%2 == 0) {//
$checksum += (int)$code[$digit] * 3;
}
else{//
$checksum += (int) $code[$digit];
}
}
$checkdigit = 10 - $checksum % 10;
$code .= $checkdigit;
$code_disp = $code;
$code = "*".substr($code, 0,6)."#".substr($code, 6,6)."*";
$this->width = $this-> barwidth*95 + $this->padding*2;
$this->barheight = $this->barwidth*95*0.75;
$this->height = $this->barwidth*95*0.75 + $this->padding*2;
$barcode = imagecreatetruecolor($this->width, $this->barheight);
$black = imagecolorallocate($barcode, 0, 0, 0);
$white = imagecolorallocate($barcode, 255, 255, 255);
imagefill($barcode, 0, 0, $black);
imagefilledrectangle($barcode, $this->border, $this->width - $this->border, -1, $this->barheight - $this->border - 1, $white);
$bar_pos = $this->padding;
for($count = 0; $count < 15; $count++) {
$character = $code[$count];
for($subcount = 0; $subcount < strlen($this->mapcode[$character]); $subcount++) {//
if($count < 7) {
$color = ($this->mapcode[$character][$subcount] == 0) ? $white : $black;
}
else{
$color = ($this->rightmap[$character][$subcount] == 0) ? $white : $black;
}
if(strlen($this->mapcode[$character]) == 7) {
$height_offset = $this->height * 0.05;
}
else {
$height_offset = 0;
}
imagefilledrectangle($barcode, $bar_pos, $this->padding, $bar_pos+$this->barwidth - 1, $this->barheight - $height_offset - $this->padding, $color);
$bar_pos += $this->barwidth;
}
}
ob_start();
imagepng($barcode);
$barcodeImage = ob_get_contents();
ob_clean();
return $barcodeImage;
}
}
I also see that you filled the image with black which normally is filled with white as the code is a black on white image. To change this simply replace:
imagefill($barcode, 0, 0, $black); > imagefill($barcode, 0, 0, $white);

Thumbnails with Face Detection in PHP

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.

Captcha image not showing

Ok...so...i'm trying the create my own Captcha to use on a webpage i'm working on.
Since i'm pretty much a noob on php i followed a youtube guide
i followed EVERY SINGLE STEP in this video, everything he did i did too, i dowloaded the same image lybrary(AnonymousClippings.tff btw) and etc BUT for some reason my captcha image is not showing.
I have to files, one for the captcha and one for the index(to call the image function so i can see the image) and use it in a form.
i'm sure the reason for not showing the image is pretty stupid but i just can't figure what's the problem.
if you know a easier way to create my own captcha i would apreciate.
captcha.php
<?php
class captcha{
private static $captcha = "__captcha__";
private static $font;
private static $width = 70;
private static $height = 70;
private static $font_size = 40;
private static $character_width = 40;
private static function session_start(){
if(!isset($_SESSION)){
session_start();
}
}
private static function set_font(){
self::$font = self::$captcha;
$AnonymousClippings = "HERE GOES ALL POSSIBLE CAHRS THAT THE CAPTCHA WILL BE ABLE TO SHOW FROM AnonymousClippings LYBRARY";
$handle = fopen(self::$font,"w+");
fwrite($handle, base64_encode($AnonymousClippings));
fclose($handle);
return self::$font;
}
public 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 = chr(rand(0,9));
break;
}
return $random;
}
private static function get_width(){
return self::$width;
}
private static function get_height(){
return self::$height;
}
private static function generate_code($length){
self::session_start();
$code=null;
for($i=0;$i<$length;$i++){
$code.=self::get_random();
}
$_SESSION[self::$captcha] = $code;
self::$width = $length * self::$character_width;
return $code;
}
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++){
$red = rand(0,255);
$green = rand(0,255);
$blue = rand(0,255);
$dot_color = imagecolorallocate($image, $red, $green, $blue);
$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*(-1); $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(){
self::session_start();
return $_SESSION[self::$captcha];
}
}
?>
index1.php
<?php
require_once("captcha.php");
if(isset($_POST["code"])){
if($_POST["code"]== captcha::get_code()){
echo "good";
}else{
echo "wrong";
}
}
?>
<form method="post">
<img src=" <?php captcha::image() ?>"/><br>
<input type="text" name="code"/><br>
<input type="submit" value="Check"/>
</form>
The methods end up returning the data but you never echo the output.
return "data:image/png;base64,".base64_encode($source);
Partially solved:
<img src="<?php echo captcha::image(); ?>"/><br>
Taken from the comments, next error is font path:
self::$font = self::$captcha;
Don't set em to the same value. $font must point to a font path (like ./arial.ttf).

Imagettftext - incorrect line spacing

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.

captcha modify six letters

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,...)

Categories