Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP/GD using imagecreatetruecolor() instead of imagecreate() renders black image

Tags:

php

gd

Using this 'somewhat' ugly class I am rendering text to images using .ttf font files. When using the ImageFlip() function I get a black completely black image (with the right size though). When I replace all occurences of imagecreatetruecolor() with imagecreate() though, everything works as expected.

rendering as JPEG instead of PNG makes no difference. I get no PHP errors.

<?php

define ( 'IMAGE_FLIP_HORIZONTAL', 1 );
define ( 'IMAGE_FLIP_VERTICAL', 2 );
define ( 'IMAGE_FLIP_BOTH', 3 );

/**
 * Renders text to an image using a TrueType font
 *
 * @author peterrus
 */
class ImageTTFRenderer {

    //defaults
    private $size = 60;
    private $rot = 0; // rotation in degrees. 
    private $pad = 10; // padding. 
    private $transparent = 0; // gives a black image in combination with flipping
    private $red = 0; // white text... 
    private $grn = 0;
    private $blu = 0;
    private $bg_red = 255; // on black background. 
    private $bg_grn = 255;
    private $bg_blu = 255;
    private $flipped = true;
    private $fontFile;

    function __construct($options) {
        if (isset($options['fontfile'])) {
            $this->fontFile = $options['fontfile'];
        } else {
            throw new Exception("No font selected");
            die();
        }
        if (isset($options['size'])) {
            $this->size = $options['size'];
        }
        if (isset($options['red'])) {
            $this->size = $options['red'];
        }
        if (isset($options['grn'])) {
            $this->size = $options['grn'];
        }
        if (isset($options['blu'])) {
            $this->size = $options['blu'];
        }
        if (isset($options['bg_red'])) {
            $this->size = $options['bg_red'];
        }
        if (isset($options['bg_grn'])) {
            $this->size = $options['bg_grn'];
        }
        if (isset($options['bg_blu'])) {
            $this->size = $options['bg_blu'];
        }
    }

function ImageFlip($imgsrc, $type)
{
    $width = imagesx($imgsrc);
    $height = imagesy($imgsrc);

    $imgdest = imagecreatetruecolor($width, $height);

    switch( $type )
        {
        case IMAGE_FLIP_HORIZONTAL:
            for( $y=0 ; $y<$height ; $y++ )
                imagecopy($imgdest, $imgsrc, 0, $height-$y-1, 0, $y, $width, 1);
            break;

        case IMAGE_FLIP_VERTICAL:
            for( $x=0 ; $x<$width ; $x++ )
                imagecopy($imgdest, $imgsrc, $width-$x-1, 0, $x, 0, 1, $height);
            break;

        case IMAGE_FLIP_BOTH:
            for( $x=0 ; $x<$width ; $x++ )
                imagecopy($imgdest, $imgsrc, $width-$x-1, 0, $x, 0, 1, $height);

            $rowBuffer = imagecreatetruecolor($width, 1);
            for( $y=0 ; $y<($height/2) ; $y++ )
                {
                imagecopy($rowBuffer, $imgdest  , 0, 0, 0, $height-$y-1, $width, 1);
                imagecopy($imgdest  , $imgdest  , 0, $height-$y-1, 0, $y, $width, 1);
                imagecopy($imgdest  , $rowBuffer, 0, $y, 0, 0, $width, 1);
                }

            imagedestroy( $rowBuffer );
            break;
        }

    return( $imgdest );
}

public function draw($message) {

// Set the enviroment variable for GD
putenv('GDFONTPATH=' . realpath('.'));

$width = 0;
$height = 0;
$offset_x = 0;
$offset_y = 0;
$bounds = array();
$image = "";

// determine font height. 
$bounds = ImageTTFBBox($this->size, $this->rot, $this->fontFile, "W");
if ($bounds == false) {
    throw new Exception("imagettfbbox() returned false");
    die();
}
if ($this->rot < 0) {
    $font_height = abs($bounds[7] - $bounds[1]);
} else if ($this->rot > 0) {
    $font_height = abs($bounds[1] - $bounds[7]);
} else {
    $font_height = abs($bounds[7] - $bounds[1]);
}

// determine bounding box. 
$bounds = ImageTTFBBox($this->size, $this->rot, $this->fontFile, $message);
if ($bounds == false) {
    throw new Exception("imagettfbbox() returned false");
    die();
}
if ($this->rot < 0) {
    $width = abs($bounds[4] - $bounds[0]);
    $height = abs($bounds[3] - $bounds[7]);
    $offset_y = $font_height;
    $offset_x = 0;
} else if ($this->rot > 0) {
    $width = abs($bounds[2] - $bounds[6]);
    $height = abs($bounds[1] - $bounds[5]);
    $offset_y = abs($bounds[7] - $bounds[5]) + $font_height;
    $offset_x = abs($bounds[0] - $bounds[6]);
} else {
    $width = abs($bounds[4] - $bounds[6]);
    $height = abs($bounds[7] - $bounds[1]);
    $offset_y = $font_height;
    $offset_x = 0;
}

$image = imagecreatetruecolor($width + ($this->pad * 2) + 1, $height + ($this->pad * 2) + 1);
if ($image == false) {
    throw new Exception("imagecreatetruecolor() returned false");
    die();
}

$background = imagecolorallocate($image, $this->bg_red, $this->bg_grn, $this->bg_blu);
$foreground = imagecolorallocate($image, $this->red, $this->grn, $this->blu);
if ($background === false || $foreground === false) {
    throw new Exception("imagecolorallocate() returned false");
    die();
}

if ($this->transparent)
    imagecolortransparent($image, $background);
imageinterlace($image, false);

// render it. 
imageTTFText($image, $this->size, $this->rot, $offset_x + $this->pad, $offset_y + $this->pad, $foreground, $this->fontFile, $message);

if($this->flipped) { $image = $this->ImageFlip($image, IMAGE_FLIP_VERTICAL); }

// output PNG object. 
imagePNG($image);
}

}

?>
like image 234
peterrus Avatar asked Dec 19 '25 20:12

peterrus


1 Answers

If you want to have a fully-transparent background, you could use the following right after imagecreatetruecolor.

imagesavealpha($image, true);
$trans_colour = imagecolorallocatealpha($image, 0, 0, 0, 127);
imagefill($image, 0, 0, $trans_colour);

What you do is create a true colour image, make sure that the alpha save-state is on, then fill the image with a colour that has had its alpha level set to fully transparent (127).

Also, be aware that the first call to imagecolorallocate fills the background with that color. Just thought you should pay attention to this too.

like image 194
imelgrat Avatar answered Dec 21 '25 12:12

imelgrat