Issue
I want to resize a GD image so that its contents fit inside the image.
Is this distinctly possible?
Solution
The biggest problem is to recover the size of the text. Imagettftext as well as imagettfbox returns an array of points that describe the position of the text in your image, but not the area that allow you to logically fit an image to it.
Here is what I mean :
function demo($text, $size, $angle, $font)
{
$gdh = imagecreatetruecolor(300, 300);
$white = imagecolorallocate($gdh, 255, 255, 255);
imagefill($gdh, 0, 0, $white);
$black = imagecolorallocate($gdh, 0, 0, 0);
$rect = imagettftext($gdh, $size, $angle, 50, 250, $black, $font, $text);
// Display a rectangle using the teturn of imagettftext
$red = imagecolorallocate($gdh, 255, 0, 0);
imageline($gdh, $rect[0], $rect[1], $rect[2], $rect[3], $red);
imageline($gdh, $rect[0], $rect[1], $rect[6], $rect[7], $red);
imageline($gdh, $rect[2], $rect[3], $rect[4], $rect[5], $red);
imageline($gdh, $rect[4], $rect[5], $rect[6], $rect[7], $red);
// Calculate and display the real area we need to fit our image
$blue = imagecolorallocate($gdh, 0, 0, 255);
$minX = min(array ($rect[0], $rect[2], $rect[4], $rect[6]));
$maxX = max(array ($rect[0], $rect[2], $rect[4], $rect[6]));
$minY = min(array ($rect[1], $rect[3], $rect[5], $rect[7]));
$maxY = max(array ($rect[1], $rect[3], $rect[5], $rect[7]));
imageline($gdh, $minX, $minY, $minX, $maxY, $blue);
imageline($gdh, $maxX, $minY, $maxX, $maxY, $blue);
imageline($gdh, $minX, $minY, $maxX, $minY, $blue);
imageline($gdh, $minX, $maxY, $maxX, $maxY, $blue);
header("Content-type: image/png");
imagepng($gdh);
die();
}
If we call :
demo("Cheers!", 48, 45, "font.ttf");
We'll get this image :
You can see in red the area given by imagettfbox, and in blue the calculated area that will allow us to define a new image size, fitted to the text.
Here is a solution to fit text to an image (replace font.ttf by your own font of course).
function fitImageToText($gdh, $text, $size, $angle, $font)
{
// Recover the box size where we will be able to put our text
// Took from the doc http://www.php.net/manual/en/function.imagettfbbox.php#105593
putenv('GDFONTPATH=' . realpath('.'));
$rect = imagettfbbox($size, $angle, $font, $text);
$minX = min(array ($rect[0], $rect[2], $rect[4], $rect[6]));
$maxX = max(array ($rect[0], $rect[2], $rect[4], $rect[6]));
$minY = min(array ($rect[1], $rect[3], $rect[5], $rect[7]));
$maxY = max(array ($rect[1], $rect[3], $rect[5], $rect[7]));
$targetWidth = $maxX - $minX;
$targetHeight = $maxY - $minY;
$srcWidth = imagesx($gdh);
$srcHeight = imagesy($gdh);
// Creating target image
$targetGdh = imagecreatetruecolor($targetWidth, $targetHeight);
imagealphablending($targetGdh, false);
imagesavealpha($targetGdh, true);
imagecopyresampled($targetGdh, $gdh, 0, 0, 0, 0, $targetWidth, $targetHeight, $srcWidth, $srcHeight);
// Writting text inside the new image
$red = imagecolorallocate($targetGdh, 255, 0, 0);
imagettftext($targetGdh, $size, $angle, abs($minX), abs($minY), $red, $font, $text);
return $targetGdh;
}
To call it :
$gdh = imagecreatefrompng("cheers.png");
$newGdh = fitImageToText($gdh, "Cheers!", 48, 45, "font.ttf");
imagedestroy($gdh);
// Outputs the image
header("Content-type: image/png");
imagepng($newGdh);
imagedestroy($newGdh);
die();
Original picture :
Resulting picture :
Note : aspect ratio of your source image will be fit to the text size without any logic. If you want to preserve aspect ratio of your image, you can use something like this :
function fitImageToText($gdh, $text, $size, $angle, $font)
{
// Recover the box size where we will be able to put our text
// Took from the doc http://www.php.net/manual/en/function.imagettfbbox.php#105593
putenv('GDFONTPATH=' . realpath('.'));
$rect = imagettfbbox($size, $angle, $font, $text);
$minX = min(array ($rect[0], $rect[2], $rect[4], $rect[6]));
$maxX = max(array ($rect[0], $rect[2], $rect[4], $rect[6]));
$minY = min(array ($rect[1], $rect[3], $rect[5], $rect[7]));
$maxY = max(array ($rect[1], $rect[3], $rect[5], $rect[7]));
$targetWidth = $maxX - $minX;
$targetHeight = $maxY - $minY;
$srcWidth = imagesx($gdh);
$srcHeight = imagesy($gdh);
// Recovering new source image size respecting its aspect ratio
$srcRatio = $srcWidth / $srcHeight;
$targetRatio = $targetWidth / $targetHeight;
if ($srcWidth <= $targetWidth && $srcHeight <= $targetHeight)
{
$imgTargetWidth = $srcWidth;
$imgTargetHeight = $srcHeight;
}
else if ($targetRatio > $srcRatio)
{
$imgTargetWidth = (int) ($targetHeight * $srcRatio);
$imgTargetHeight = $targetHeight;
}
else
{
$imgTargetWidth = $targetWidth;
$imgTargetHeight = (int) ($targetHeight / $srcRatio);
}
// Creating target image
$targetGdh = imagecreatetruecolor($targetWidth, $targetHeight);
imagealphablending($targetGdh, false);
imagesavealpha($targetGdh, true);
imagecopyresampled($targetGdh, $gdh, 0, 0, 0, 0, $imgTargetWidth, $imgTargetHeight, $srcWidth, $srcHeight);
// Writting text inside the new image
$red = imagecolorallocate($targetGdh, 255, 0, 0);
imagettftext($targetGdh, $size, $angle, abs($minX), abs($minY), $red, $font, $text);
return $targetGdh;
}
This will result in :
Answered By - Alain Tiemblo Answer Checked By - Marie Seifert (PHPFixing Admin)
0 Comments:
Post a Comment
Note: Only a member of this blog may post a comment.