imagecopyresampled lossing quality an image php - 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;
}

Related

Resizing font size and padding using gd to create a dynamic bar chart

Inspired by this code, I am trying to create a simple bar chart able to dynamically create, resize both bars and texts depends on the the $data, $height and $weight:
<?php
$width = 300;
$height = 200;
$font_path = getenv('WINDIR') . DIRECTORY_SEPARATOR . "Fonts" . DIRECTORY_SEPARATOR;
$font = 'arial.ttf';
$data = ['jan'=>30,'fev'=>40,'mar'=>90,'apr'=>77,
'mai'=>33, 'jun'=>44, 'bigggggggg' => 80];
$columns = count($data);
$padding = ($width+$height)/100;
$column_width = $width / $columns;
$image = imagecreate($width, $height);
$gray = imagecolorallocate($image, 0xcc, 0xcc, 0xcc);
$black = imagecolorallocate($image, 0, 0, 0);
$gray_lite = imagecolorallocate($image, 0xee, 0xee, 0xee);
$gray_dark = imagecolorallocate($image, 0x7f, 0x7f, 0x7f);
$white = imagecolorallocate($image, 0xff, 0xff, 0xff);
imagefilledrectangle($image, 0, 0, $width, $height, $white);
$maxv = max($data);
$array_values = array_values($data);
$array_keys = array_keys($data);
for ($i = 0; $i < $columns; $i++) {
$font_size = ($height / 100) * $padding;
$column_height = ($height / 100) * (( $array_values[$i] / $maxv) * 100);
$string = $array_keys[$i];
$x1 = $i * $column_width;
$y1 = $height - $column_height;
$x2 = (($i + 1) * $column_width) - $padding;
$y2 = $height - ($padding*4);
$maxChars = ($font_size * 2) / $padding;
if (strlen($string) > ($maxChars)) {
$string = substr($string, 0, $maxChars) . '...';
}
imagefilledrectangle($image, $x1, $y1, $x2, $y2, $gray);
imagettftext($image, $font_size, 0, $x1, $y2+$font_size+$padding, $black, $font_path.$font,
$string);
imageline($image, $x1, $y1, $x1, $y2, $gray_lite);
imageline($image, $x1, $y2, $x2, $y2, $gray_lite);
imageline($image, $x2, $y1, $x2, $y2, $gray_dark);
}
header("Content-type: image/png");
imagepng($image);
imagedestroy($image);
Using 300x200 its okay:
But using 600x400:
What Can I do to fix that?
There is only Font Size Calculations Which can be fixed earlier code:
$font_size = ($height / 100) * $padding; //Changing this line
$column_height = ($height / 100) * (( $array_values[$i] / $maxv) * 100);
$string = $array_keys[$i];
$x1 = $i * $column_width;
$y1 = $height - $column_height;
$x2 = (($i + 1) * $column_width) - $padding;
$y2 = $height - ($padding*4);
$maxChars = ($font_size * 2) / $padding;
after changing it dynamic it would be as under:
$column_height = ($height / 100) * (( $array_values[$i] / $maxv) * 100);
$string = $array_keys[$i];
$x1 = $i * $column_width;
$y1 = $height - $column_height;
$x2 = (($i + 1) * $column_width) - $padding;
$y2 = $height - ($padding*4);
$font_size = ($x2 - $x1) / 4; //Changed line and location
$maxChars = ($font_size * 2) / $padding;
Except this change nothing is required.
You create the $font_size base on $padding, the $font_size will grow fast in the case size of chart grow
Instead of it, make the $font_size depend on the $height and Y position of the bars, it should work fine, please try this script instead
<?php
$width = 600;
$height = 400;
$font_path = getenv('WINDIR') . DIRECTORY_SEPARATOR . "Fonts" . DIRECTORY_SEPARATOR;
$font = 'arial.ttf';
$data = ['jan'=>30,'fev'=>40,'mar'=>90,'apr'=>77,
'mai'=>33, 'jun'=>44, 'bigggggggg' => 80];
$columns = count($data);
$padding = ($width+$height)/100;
$column_width = $width / $columns;
$image = imagecreate($width, $height);
$gray = imagecolorallocate($image, 0xcc, 0xcc, 0xcc);
$black = imagecolorallocate($image, 0, 0, 0);
$gray_lite = imagecolorallocate($image, 0xee, 0xee, 0xee);
$gray_dark = imagecolorallocate($image, 0x7f, 0x7f, 0x7f);
$white = imagecolorallocate($image, 0xff, 0xff, 0xff);
imagefilledrectangle($image, 0, 0, $width, $height, $white);
$maxv = max($data);
$array_values = array_values($data);
$array_keys = array_keys($data);
for ($i = 0; $i < $columns; $i++) {
$column_height = ($height / 100) * (( $array_values[$i] / $maxv) * 100);
$string = $array_keys[$i];
$x1 = $i * $column_width;
$y1 = $height - $column_height;
$x2 = (($i + 1) * $column_width) - $padding;
$y2 = $height - ($padding*4);
$maxChars = ($font_size * 2) / $padding;
if (strlen($string) > ($maxChars)) {
$string = substr($string, 0, $maxChars) . '...';
}
$font_size = ($height - $y2) / 2.5;
imagefilledrectangle($image, $x1, $y1, $x2, $y2, $gray);
imagettftext($image, $font_size, 0, $x1, $y2+$font_size+$padding, $black, $font_path.$font,
$string);
imageline($image, $x1, $y1, $x1, $y2, $gray_lite);
imageline($image, $x1, $y2, $x2, $y2, $gray_lite);
imageline($image, $x2, $y1, $x2, $y2, $gray_dark);
}
header("Content-type: image/png");
imagepng($image);
imagedestroy($image);
Just small change on $font_size = ($height - $y2) / 2.5;
Try if this works.
Basically your font size was height/100 which was working when height was 200, but when you have doubled the height, we need to change the font size to match it as well.
See if this is the desired result MaxInfo.Tech
<?php
$width = 600;
$height = 400;
$font_path = getenv('WINDIR') . DIRECTORY_SEPARATOR . "Fonts" . DIRECTORY_SEPARATOR;
$font = 'arial.ttf';
$data = ['jan'=>30,'fev'=>40,'mar'=>90,'apr'=>77,
'mai'=>33, 'jun'=>44, 'bigggggggg' => 80];
$columns = count($data);
$padding = ($width+$height)/100;
$column_width = $width / $columns;
$image = imagecreate($width, $height);
$gray = imagecolorallocate($image, 0xcc, 0xcc, 0xcc);
$black = imagecolorallocate($image, 0, 0, 0);
$gray_lite = imagecolorallocate($image, 0xee, 0xee, 0xee);
$gray_dark = imagecolorallocate($image, 0x7f, 0x7f, 0x7f);
$white = imagecolorallocate($image, 0xff, 0xff, 0xff);
imagefilledrectangle($image, 0, 0, $width, $height, $white);
$maxv = max($data);
$array_values = array_values($data);
$array_keys = array_keys($data);
for ($i = 0; $i < $columns; $i++) {
$font_size = ($height / 200) * $padding;
$column_height = ($height / 100) * (( $array_values[$i] / $maxv) * 100);
$string = $array_keys[$i];
$x1 = $i * $column_width;
$y1 = $height - $column_height;
$x2 = (($i + 1) * $column_width) - $padding;
$y2 = $height - ($padding*4);
$maxChars = ($font_size * 2) / $padding;
if (strlen($string) > ($maxChars)) {
$string = substr($string, 0, $maxChars) . '...';
}
imagefilledrectangle($image, $x1, $y1, $x2, $y2, $gray);
imagettftext($image, $font_size, 0, $x1, $y2+$font_size+$padding, $black, $font_path.$font,
$string);
imageline($image, $x1, $y1, $x1, $y2, $gray_lite);
imageline($image, $x1, $y2, $x2, $y2, $gray_lite);
imageline($image, $x2, $y1, $x2, $y2, $gray_dark);
}
header("Content-type: image/png");
imagepng($image);
imagedestroy($image);
Also Please note to format it better you can change other variables also which are based on height or width, to something more dynamic than a static divider of 100.

PHP Captcha Image can not be displayed because of errors

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.

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

PHP Captcha-generator does not generate transparent PNG. Why?

I have set imagealphablending on every image I create, still there is a black background. What could be the problem?
$systemSettings = array(
'captcha' => array(
'colors' => array(array(30, 80, 180), array(20, 160, 40), array(220, 40, 10)),
'fonts' => array('AntykwaBold.ttf', 'Candice.ttf', 'Carbon.ttf', 'Duality.ttf', 'Heineken.ttf', 'Jura.ttf', 'StayPuft.ttf', 'TimesNewRomanBold.ttf', 'VeraSansBold.ttf'),
'size' => array('width' => '200', 'height' => '50')
)
);
function generateCaptcha() {
global $systemSettings;
$randomLetters = "abcdef";
$scale = 3;
$width = $systemSettings['captcha']['size']['width'];
$height = $systemSettings['captcha']['size']['height'];
$im = imagecreatetruecolor($width * $scale, $height * $scale);
imagealphablending($im, true);
//$GdBgColor = imagecolorallocate($im, 250, 250, 250);
//imagefilledrectangle($im, 0, 0, $width * $scale, $height * $scale, $GdBgColor);
$color = $systemSettings['captcha']['colors'][mt_rand(0, sizeof($systemSettings['captcha']['colors']) - 1)];
$GdFgColor = imagecolorallocate($im, $color[0], $color[1], $color[2]);
$fontfile = 'visual/fonts/' . $systemSettings['captcha']['fonts'][array_rand($systemSettings['captcha']['fonts'])];
$x = 20 * $scale;
$y = round(($height * 0.75) * $scale);
$length = strlen($randomLetters);
for ($i = 0; $i < $length; $i++) {
$degree = rand(-10, 10);
$fontsize = rand(20, 25) * $scale;
$letter = substr($randomLetters, $i, 1);
$coords = imagettftext($im, $fontsize, $degree, $x, $y, $GdFgColor, $fontfile, $letter);
$x += ($coords[2] - $x);
}
$k = rand(0, 100);
$xp = $scale * 12 * rand(1, 3);
for ($i = 0; $i < ($width * $scale); $i++)
imagecopy($im, $im, $i - 1, sin($k + $i / $xp) * ($scale * 5), $i, 0, 1, $height * $scale);
$k = rand(0, 100);
$yp = $scale * 12 * rand(1, 3);
for ($i = 0; $i < ($height * $scale); $i++)
imagecopy($im, $im, sin($k + $i / $yp) * ($scale * 14), $i - 1, 0, $i, $width * $scale, 1);
imagefilter($im, IMG_FILTER_GAUSSIAN_BLUR);
$imResampled = imagecreatetruecolor($width, $height);
imagecopyresampled($imResampled, $im, 0, 0, 0, 0, $width, $height, $width * $scale, $height * $scale);
imagealphablending($imResampled, true);
header("Content-type: image/png");
imagepng($imResampled);
imagedestroy($im);
imagedestroy($imResampled);
}
try this
$systemSettings = array(
'captcha' => array(
'colors' => array(array(30, 80, 180), array(20, 160, 40), array(220, 40, 10)),
'fonts' => array('AntykwaBold.ttf', 'Candice.ttf', 'Carbon.ttf', 'Duality.ttf', 'Heineken.ttf', 'Jura.ttf', 'StayPuft.ttf', 'TimesNewRomanBold.ttf', 'VeraSansBold.ttf'),
'size' => array('width' => '200', 'height' => '50')
)
);
function generateCaptcha() {
global $systemSettings;
$randomLetters = "abcdef";
$scale = 3;
$width = $systemSettings['captcha']['size']['width'];
$height = $systemSettings['captcha']['size']['height'];
$im = imagecreatetruecolor($width * $scale, $height * $scale);
// enable alpha blending on the destination image.
imagealphablending($im, true);
// Allocate a transparent color and fill the new image with it.
// Without this the image will have a black background instead of being transparent.
$transparent = imagecolorallocatealpha( $im, 0, 0, 0, 127 );
imagefill( $im, 0, 0, $transparent );
// disable alpha blending on the destination image.
imagealphablending($im, false);
// save the alpha
imagesavealpha($im,true);
//$GdBgColor = imagecolorallocate($im, 250, 250, 250);
//imagefilledrectangle($im, 0, 0, $width * $scale, $height * $scale, $GdBgColor);
$color = $systemSettings['captcha']['colors'][mt_rand(0, sizeof($systemSettings['captcha']['colors']) - 1)];
$GdFgColor = imagecolorallocate($im, $color[0], $color[1], $color[2]);
$fontfile = 'visual/fonts/' . $systemSettings['captcha']['fonts'][array_rand($systemSettings['captcha']['fonts'])];
$x = 20 * $scale;
$y = round(($height * 0.75) * $scale);
$length = strlen($randomLetters);
for ($i = 0; $i < $length; $i++) {
$degree = rand(-10, 10);
$fontsize = rand(20, 25) * $scale;
$letter = substr($randomLetters, $i, 1);
$coords = imagettftext($im, $fontsize, $degree, $x, $y, $GdFgColor, $fontfile, $letter);
$x += ($coords[2] - $x);
}
$k = rand(0, 100);
$xp = $scale * 12 * rand(1, 3);
for ($i = 0; $i < ($width * $scale); $i++)
imagecopy($im, $im, $i - 1, sin($k + $i / $xp) * ($scale * 5), $i, 0, 1, $height * $scale);
$k = rand(0, 100);
$yp = $scale * 12 * rand(1, 3);
for ($i = 0; $i < ($height * $scale); $i++)
imagecopy($im, $im, sin($k + $i / $yp) * ($scale * 14), $i - 1, 0, $i, $width * $scale, 1);
imagefilter($im, IMG_FILTER_GAUSSIAN_BLUR);
$imResampled = imagecreatetruecolor($width, $height);
// enable alpha blending on the destination image.
imagealphablending($imResampled, true);
// Allocate a transparent color and fill the new image with it.
// Without this the image will have a black background instead of being transparent.
$transparent = imagecolorallocatealpha( $imResampled, 0, 0, 0, 127 );
imagefill( $imResampled, 0, 0, $transparent );
// disable alpha blending on the destination image.
imagealphablending($imResampled, false);
// save the alpha
imagesavealpha($imResampled,true);
imagecopyresampled($imResampled, $im, 0, 0, 0, 0, $width, $height, $width * $scale, $height * $scale);
header("Content-type: image/png");
imagepng($imResampled);
imagedestroy($im);
imagedestroy($imResampled);
}

Resize image size according to size of text

The PHP code below generates text as a dynamically created image, how would I be able to get the image to only be as large as the text? Thanks.
<?php
header('Content-Type: image/jpeg');
$text='Test';
$img = imageCreate(200,200);
imagecolorallocate($img, 255, 255, 255);
$textColor = imagecolorallocate($img, 0, 0, 0);
imagefttext($img, 15, 0, 0, 55, $textColor, 'bgtbt.ttf', $text);
imagejpeg($img);
imagedestroy($img);
?>
UPDATE 1: I found the answer here with the example of the original poster - Creating IMage from Text in PHP - how can I make multiline?
UPDATE 2: Martin Geisler's version also works well
When using a TrueType font, you use the imageftbbox function to obtain the bounding box for a string typeset with your font. The bounding box gives the offsets from the base-point to the four corners in the rectangle occupied by the text. So if you store the bounding box in $bb and use imagefttext to put text at ($x, $y), then the corners will have these coordinates:
($x + $bb[6], $y + $bb[7]) ($x + $bb[4], $y + $bb[5])
+-------+
| Hello |
+-------+
($x + $bb[0], $y + $bb[1]) ($x + $bb[2], $y + $bb[3])
That tells us that we want an image width of ($x + $bb[2]) - ($x + $bb[6]) = $bb[2] - $bb[6] and similarly an image height of $bb[3] - $bb[7]. The text should then be rendered at coordinates (-$bb[6], -$bb[7]) inside that picture since we want to have
(0, 0) = ($x + $bb[6], $y + $bb[7]) ==> $x = -$bb[6] and $y = -$bb[7]
You can try it out with this code. Put it into a file called img.php and browse to img.php?q=Hello to test:
<?php
header("Content-type: image/png");
$q = $_REQUEST['q'];
$font = "Impact.ttf";
$size = 30;
$bbox = imageftbbox($size, 0, $font, $q);
$width = $bbox[2] - $bbox[6];
$height = $bbox[3] - $bbox[7];
$im = imagecreatetruecolor($width, $height);
$green = imagecolorallocate($im, 60, 240, 60);
imagefttext($im, $size, 0, -$bbox[6], -$bbox[7], $green, $font, $q);
imagepng($im);
imagedestroy($im);
?>
If you use the bitmap fonts instead, then look at the imagefontwidth and imagefontheight functions.
#Martin Geisler's answer is almost correct, but I couldn't get my text to fit completely inside the image. I tried this instead, which works perfectly!
From the PHP Manual's User Contributed Notes:
$text = "<?php echo \"hello, world\"; ?>";
$font = "./arial.ttf";
$size = "60";
$bbox = imagettfbbox($size, 0, $font, $text);
$width = abs($bbox[2] - $bbox[0]);
$height = abs($bbox[7] - $bbox[1]);
$image = imagecreatetruecolor($width, $height);
$bgcolor = imagecolorallocate($image, 255, 255, 255);
$color = imagecolorallocate($image, 0, 0, 0);
$x = $bbox[0] + ($width / 2) - ($bbox[4] / 2);
$y = $bbox[1] + ($height / 2) - ($bbox[5] / 2);
imagefilledrectangle($image, 0, 0, $width - 1, $height - 1, $bgcolor);
imagettftext($image, $size, 0, $x, $y, $color, $font, $text);
$last_pixel= imagecolorat($image, 0, 0);
for ($j = 0; $j < $height; $j++)
{
for ($i = 0; $i < $width; $i++)
{
if (isset($blank_left) && $i >= $blank_left)
{
break;
}
if (imagecolorat($image, $i, $j) !== $last_pixel)
{
if (!isset($blank_top))
{
$blank_top = $j;
}
$blank_left = $i;
break;
}
$last_pixel = imagecolorat($image, $i, $j);
}
}
$x -= $blank_left;
$y -= $blank_top;
imagefilledrectangle($image, 0, 0, $width - 1, $height - 1, $bgcolor);
imagettftext($image, $size, 0, $x, $y, $color, $font, $text);
header('Content-type: image/png');
imagepng($image);
imagedestroy($image);

Categories