Search code examples
phptransparencygdimagettftext

PHP GD Imagettftext transparent


I am trying to write a transparent text using imagettftext but I can't (using imagestring works but it's not possible to select your own font and sizes). The final image should be a grey rectangle with transparent text, so that if I put the image over a new background that background is visible in the text.

My code is:

$font = "./Verdana.ttf";
$fontSize = 12;
$img = imagecreatetruecolor(600, 600);
imagealphablending($img, false);
imagesavealpha($img, true);
$transparent = imagecolorallocatealpha($img, 255, 255, 255, 127);
$grey = imagecolorallocate($img, 127, 127, 127);
imagefilledrectangle($img, 0, 0, $imageX, $imageY, $grey);
imagettftext($img, $fontSize, 0, $text_posX, $text_posY, $transparent, $font, "This is a transparent text");
imagepng($img);

Solution

  • The solution here should be simple; switch to non-blending mode (via imagealphablending($img, false);) and add the text with a fully transparent colour. But there appears to be a bug in PHP (tested in 7.0.7, latest at time of writing) where this results in the text rendering as a series of rectangles instead of letters.

    A very quick and simple fix for this is to negate the colour index of $transparent to disable anti-aliasing:

    imagettftext($img, $fontSize, 0, $text_posX, $text_posY, -$transparent, $font, 'TEST');
    

    But, if you would prefer the text to be anti-aliased you can:

    • create your image at double the required size (width×2, height×2)
    • add the aliased text using the negation method, above
    • resize the image (width÷2, height÷2) via imagecopyresampled() to fake a basic anti-aliased effect.

    So, basically, this:

    $font = "./Verdana.ttf";
    $fontSize = 24; // note: double your original value.
    $img = imagecreatetruecolor(1200, 1200); // note: double your original values.
    imagealphablending($img, false);
    imagesavealpha($img, true);
    $transparent = imagecolorallocatealpha($img, 255, 255, 255, 127);
    $grey = imagecolorallocate($img, 127, 127, 127);
    imagefilledrectangle($img, 0, 0, $imageX, $imageY, $grey);
    imagettftext($img, $fontSize, 0, $text_posX, $text_posY, -$transparent, $font, "This is a transparent text");
    
    $dest = imagecreatetruecolor(600, 600);
    imagealphablending($dest, false);
    imagesavealpha($dest, true);
    imagecopyresampled($dest, $img, 0, 0, 0, 0, 600, 600, 1200, 1200);
    
    header('Content-Type: image/png');
    imagepng($dest);