PHP Captcha Image can not be displayed because of errors - php

This is my static function in class 'image_utils.php'
public static function getCaptcha()
{
try {
$width = 200;
$height = 30;
$font = 'fonts/arial.ttf';
//
if (!file_exists($font)) {
throw new Exception('Error Font not found');
}
//
$image = imagecreatetruecolor($width, $height);
$white = imagecolorallocate($image, 255, 255, 255);
$grey = imagecolorallocate($image, 180, 180, 180);
$black = imagecolorallocate($image, 0, 0, 0);
//
for ($sq = 1; $sq <= 10; $sq++) {
$cx = (int)rand(0, $width / 2);
$cy = (int)rand(0, $height);
$h = $cy + (int)rand(0, $height / 5);
$w = $cx + (int)rand($width / 3, $width);
if (!imagefilledrectangle($image, $cx, $cy, $w, $h, $white)) {
throw new Exception('Error in White Fill');
}
}
//
$ellipse_count = 5;
for ($i = 0; $i < $ellipse_count; $i++) {
$cx = (int)rand(-1 * ($width / 2), $width + ($width / 2));
$cy = (int)rand(-1 * ($height / 2), $height + ($height / 2));
$h = (int)rand($height / 2, 2 * $height);
$w = (int)rand($width / 2, 2 * $width);
if (!imageellipse($image, $cx, $cy, $w, $h, $grey)) {
throw new Exception('Error in Grey Fill');
}
}
//
imagefttext($image, 20, 0, 10, 20, $black, $font, 'Captcha');
header('Content-type: image/png');
if (!imagepng($image)) {
throw new Exception('Error in ImagePng');
}
} catch (Exception $ex) {
echo $ex->getMessage();
}
}
Calling it in 'log.php' in img tag:
<img src='<?php image_utils::getCaptcha() ?>'/>
Gives an error 'The image cannot be displayed because it contains errors'. I have create a check for font file as shown in code so the font file is in inclusion. Please throw some light.
Thanks in Advance.

Related

Make sure imagepng has written the file on the server

I have a function which adds text under a existing qr-code image.
In some cases the return is faster than the server has written the image on the filesystem, so that other function got issues.
How can I make sure that everything is done before I return the path to the image?
At the moment I am trying to use a while-loop, but I am also really unhappy with it. That causes also timeouts and crashes on my server (no idea why).
function addTextToQrCode($oldImage, $text)
{
$newImage = $oldImage;
$newImage = str_replace(".png", "_original.png", $newImage);
copy($oldImage, $newImage);
$image = imagecreatefrompng($oldImage);
$black = imagecolorallocate($image, 0, 0, 0);
$fontSize = 20;
$textWidth = imagefontwidth($fontSize) * strlen($text);
$textHeight = imagefontheight($fontSize);
$x = imagesx($image) / 2 - $textWidth / 2;
$y = imagesy($image) - $textHeight - 3;
imagestring($image, 5, $x, $y, $text, $black);
$filePath = "/qrCodes/qrcode".$text.'.png';
imagepng($image, $filePath);
while(!$this->checkIfNewQrCodeIsOnFileSystem($filePath)){
$this->checkIfNewQrCodeIsOnFileSystem($filePath);
}
return $filePath;
}
function checkIfNewQrCodeIsOnFileSystem($filePath) {
if (file_exists($filePath)) {
return true;
} else {
return false;
}
}
Check only imagepng(). The solution i would prefer.
function addTextToQrCode($oldImage, $text)
{
$newImage = $oldImage;
$newImage = str_replace(".png", "_original.png", $newImage);
copy($oldImage, $newImage);
$image = imagecreatefrompng($oldImage);
$black = imagecolorallocate($image, 0, 0, 0);
$fontSize = 20;
$textWidth = imagefontwidth($fontSize) * strlen($text);
$textHeight = imagefontheight($fontSize);
$x = imagesx($image) / 2 - $textWidth / 2;
$y = imagesy($image) - $textHeight - 3;
imagestring($image, 5, $x, $y, $text, $black);
$filePath = "/qrCodes/qrcode".$text.'.png';
if (imagepng($image, $filePath) === true) {
return $filePath;
}
}

How to crop image like with object-fit:cover by php?

Could you help please, I crop image for thumbnail with php code below.
But some pictures crops with black frames at top and bottom. How to do it properly?
$w = 265;
$h = 198;
if (empty($w)) {
$w = ceil($h / ($height / $width));
}
if (empty($h)) {
$h = ceil($w / ($width / $height));
}
$tmp = imageCreateTrueColor($w, $h);
$tw = ceil($h / ($height / $width));
$th = ceil($w / ($width / $height));
if ($tw < $w) {
imageCopyResampled($tmp, $img, ceil(($w - $tw) / 2), 0, 0, 0, $tw, $h, $width, $height);
} else {
imageCopyResampled($tmp, $img, 0, ceil(($h - $th) / 2), 0, 0, $w, $th, $width, $height);
}
$img = $tmp;
Links to origninal photo and with black frames:

imagecopyresampled after rotating the image

I am trying to copy image (to $img) after rotating image (many images $im) but I get weird behavior. Once I un-comment the line //$img = I only get the rotated image on my final output. Can I rotate the inner $im and copy it to final image$img?
<?php
$height = 80;
$width = 300;
$img = imagecreate($width, $height);
$c = imagecolorallocate ($img , 135, 135, 135);
imagefill($img, 0, 0, imagecolorallocate($img, 255, 255, 255));
for($i=0; $i<=5; $i++){
$im = imagecreatetruecolor(35, 35);
$gry = imagecolorallocate($im, 135, 135, 135);
$wht = imagecolorallocate($im, 255, 255, 255);
$j = mt_rand(0, 1);
$ch = mt_rand(0,1)?chr(rand(65, 90)):chr(rand(97, 122));
if($j == 0){
imagefill($im, 0, 0, $wht);
imagefttext($im, 20, 0, 3, 21, $gry, 'AHGBold.ttf', $ch);
//$img = imagerotate($im, mt_rand(0,10)-5, $wht);
}else{
imagefill($im, 0, 0, $gry);
imagefttext($im, 20, 0, 3, 21, $wht, 'AHGBold.ttf', $ch);
//$img = imagerotate($im, mt_rand(0,10)-5, $gry);
}
imagecopyresampled($img, $im, 5 + $i*42, $height/2 - 12, 0, 0, 40, 40, 25, 25);
}
header('Content-type: image/png');
imagepng($img);
change
$img = imagerotate($im, mt_rand(0,10)-5, $wht);
and
$img = imagerotate($im, mt_rand(0,10)-5, $gry);
to
$im = imagerotate($im, mt_rand(0,10)-5, $wht);
and
$im = imagerotate($im, mt_rand(0,10)-5, $gry);
in cases that imagerotes does not work you can use the following function to rotate an image:
function imagerotateEquivalent(&$srcImg, $angle, $bgcolor, $ignore_transparent = 0)
{
$srcw = imagesx($srcImg);
$srch = imagesy($srcImg);
if($angle == 0) return $srcImg;
// Convert the angle to radians
$theta = deg2rad ($angle);
// Calculate the width of the destination image.
$temp = array ( rotateX(0, 0, 0-$theta),
rotateX($srcw, 0, 0-$theta),
rotateX(0, $srch, 0-$theta),
rotateX($srcw, $srch, 0-$theta)
);
$minX = floor(min($temp));
$maxX = ceil(max($temp));
$width = $maxX - $minX;
// Calculate the height of the destination image.
$temp = array ( rotateY(0, 0, 0-$theta),
rotateY($srcw, 0, 0-$theta),
rotateY(0, $srch, 0-$theta),
rotateY($srcw, $srch, 0-$theta)
);
$minY = floor(min($temp));
$maxY = ceil(max($temp));
$height = $maxY - $minY;
$destimg = imagecreatetruecolor($width, $height);
imagefill($destimg, 0, 0, imagecolorallocate($destimg, 0,255, 0));
// sets all pixels in the new image
for($x=$minX;$x<$maxX;$x++) {
for($y=$minY;$y<$maxY;$y++)
{
// fetch corresponding pixel from the source image
$srcX = round(rotateX($x, $y, $theta));
$srcY = round(rotateY($x, $y, $theta));
if($srcX >= 0 && $srcX < $srcw && $srcY >= 0 && $srcY < $srch)
{
$color = imagecolorat($srcImg, $srcX, $srcY );
}
else
{
$color = $bgcolor;
}
imagesetpixel($destimg, $x-$minX, $y-$minY, $color);
}
}
return $destimg;
}
function rotateX($x, $y, $theta){
return $x * cos($theta) - $y * sin($theta);
}
function rotateY($x, $y, $theta){
return $x * sin($theta) + $y * cos($theta);
}
I got the above code from a note in php.net

imagecopyresampled lossing quality an image php

I want to copy re-size merge an image using imagecopyresampled in php. It is resizing properly but loosing it's quality or i can say its edges getting destroyed why?
Below is my code please view it and give solution.PHP GD-Library.
<?php
$percent = 1.0;
$filename ='filepath.png';
$image_source = imagecreatefrompng($filename);
list($old_width, $old_height) = getimagesize($filename );
$width=$old_width;
$height=$old_height;
$new_width = $old_width * $percent;
$new_height = $old_height * $percent;
$transColor=imagecolorallocatealpha($image_source, 0, 0, 0, 0);
imagecolortransparent($image_source, $transColor);
$image_p = imagecreatetruecolor($new_width, $new_height);
imagecopyresampled($image_p, $image_source, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
header('Content-Type: image/png');
imagepng($image_p);
imagedestroy($image_p);
?>
Try using this code
<?php
$percent = 1.0;
$filename ='filepath.png';
$image_source = imagecreatefrompng($filename);
list($old_width, $old_height) = getimagesize($filename );
$width=$old_width;
$height=$old_height;
$new_width = $old_width * $percent;
$new_height = $old_height * $percent;
$transColor=imagecolorallocatealpha($image_source, 0, 0, 0, 0);
imagecolortransparent($image_source, $transColor);
$image_p = imagecreatetruecolor($new_width, $new_height);
imagealphablending($image_p, false);
imagesavealpha($image_p, true);
imagecopyresampled($image_p, $image_source, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
header('Content-Type: image/png');
imagepng($image_p);
imagedestroy($image_p);
?>
Below code work for me you can customize by your requirement :
function textOutWithStroke($textSize, $textAngle, $x, $y, $textColor, $textFont, $text, $strokeColor = null, $borderSize = 1, $spacing = 0) {
if ($this->isImageCreated()){
imagealphablending($this->handle, true);
$textColor = imagecolorallocatealpha($this->handle, $textColor[0], $textColor[1], $textColor[2], $textColor[3]);
if($strokeColor === null)
$strokeColor = $textColor;
else
$strokeColor = imagecolorallocatealpha($this->handle, $strokeColor[0], $strokeColor[1], $strokeColor[2], $strokeColor[3]);
if ($borderSize < 1){
if ($spacing == 0)
imagettftext($this->handle, $textSize, $textAngle, $x, $y, $textColor, $textFont, $text);
else{
for ($i = 0; $i < strlen($text); $i++) {
$letterBox = imagettftext($this->handle, $textSize, $textAngle, $x, $y, $textColor, $textFont, $text[$i]);
$x += $spacing + ($letterBox[2] - $letterBox[0]);
}
}
}
else{
if ($spacing == 0) {
for ($c1 = $x - $borderSize; $c1 <= $x + $borderSize; $c1++)
for ($c2 = $y - $borderSize; $c2 <= $y + $borderSize; $c2++)
imagettftext($this->handle, $textSize, $textAngle, $c1, $c2, $strokeColor, $textFont, $text);
imagettftext($this->handle, $textSize, $textAngle, $x, $y, $textColor, $textFont, $text);
}
else{
for ($i = 0; $i < strlen($text); $i++) {
for ($c1 = $x - $borderSize; $c1 <= $x + $borderSize; $c1++)
for ($c2 = $y - $borderSize; $c2 <= $y + $borderSize; $c2++)
imagettftext($this->handle, $textSize, $textAngle, $c1, $c2, $strokeColor, $textFont, $text[$i]);
$letterBox = imagettftext($this->handle, $textSize, $textAngle, $x, $y, $textColor, $textFont, $text[$i]);
$x += $spacing + ($letterBox[2] - $letterBox[0]) + (2 * $borderSize);
}
}
}
imagealphablending($this->handle, $this->alphaBlending);
return true;
}
else
return false;
}

Image border using GD

This is my captcha image script
$width = 100;
$height = 40;
$im = #ImageCreate((int)$width, (int)$height);
$bg = ImageColorAllocate($im, 255, 255, 255);
$border = ImageColorAllocate($im, 100, 120, 180);
$text = base64_decode($_GET["key"]);
$textcolor = ImageColorAllocate($im,20,40,75);
for( $i=0; $i<($width*$height)/5; $i++ ) {
imagefilledellipse($im, mt_rand(0,$width), mt_rand(0,$height), 1, 1, $border);
}
for( $i=0; $i<($width*$height)/1000; $i++ ) {
imageline($im, mt_rand(0,$width), mt_rand(0,$height), mt_rand(0,$width), mt_rand(0,$height), $border);
}
// $font = 10;
$font = $height * 0.28;
$font_width = ImageFontWidth($font);
$font_height = ImageFontHeight($font);
$text_width = $font_width * strlen($text);
$position_center = ceil(($width - $text_width) / 2);
$text_height = $font_height;
$position_middle = ceil(($height - $text_height) / 2);
$textbox = imagettfbbox($font, 0, $font_fam, $text) or die('Error in imagettfbbox function');
$x = ($width - $textbox[4])/2;
$y = ($height - $textbox[5])/2;
imagettftext($im, $font, 0, $x, $y, $textcolor, $font_fam , $text) or die('Error in imagettftext function');
// ImageString($im, $font, $position_center, $position_middle, $text, $textcolor);
Imagepng($im);
header("Content-type: image/png");
imagedestroy($im);
The image displays successfully and I need to display border for this image.
You can add ImageRectangle($im, 0, 0, $width - 1, $height - 1, $color); after the variable $textcolor. I think this may help you.

Categories