Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP GD Library Image on Image

Tags:

php

image

gd

I am working on some code that allows a users to generate a mock gift card for a company. They enter in a denomination, name, and upload a logo and it will use a base template image and put that information on top of it.

Up until the logo part, I had everything working as needed.

I created my template image using imagecreatefrompng("template.png") and use imagettftext() to place the text in the desired coordinates.

Now, when it comes to the logo, I am running into some issues.

I tried creating the base image first (template + text) and then using imagecopy in order to add the logo to the new image but all I appear to be getting each time is the base image and I never see the logo.

I have tried hardcoding the path to the image and I am still not getting the desired result.

  // If we have all of the post data
  if($denomination && $name && $pin && $defaultText){

    // Create our header to flush the image to browser
    header("Content-type: image/png");  
    header("Cache-Control: no-store, no-cache");  
    header('Content-Disposition: attachment; filename="GiftCard.png"');

    // Define our source image
    $image = imagecreatefrompng("card.png");

    // Preserve transparency
    imagealphablending($image, true);
    imagesavealpha($image, true);

    // Colors
    $backgroundColor = imagecolorallocate ($image, 255, 255, 255);
    $textColor = imagecolorallocate ($image, 255, 255,255);
    $font = 'arial.ttf';

    // Data
    $data = [
      'name' => [
        'x' => 30,
        'y' => 260,
        'size' => 12,
        'angle' => 0,
        'content' => $name,
      ],
      'pin' => [
        'x' => 175,
        'y' => 210,
        'size' => 18,
        'angle' => 0,
        'content' => $pin
      ],
      'denomination' => [
        'x' => 435,
        'y' => 45,
        'size' => 20,
        'angle' => 0,
        'content' => $denomination
      ],
      'defaultText' => [
        'x' => 30,
        'y' => 290,
        'size' => 12,
        'angle' => 0,
        'content' => $defaultText
      ]
    ];

    // Name
    imagettftext($image, $data['name']['size'], $data['name']['angle'], $data['name']['x'], $data['name']['y'], $textColor, $font, $data['name']['content']);
    // Pin
    imagettftext($image, $data['pin']['size'], $data['pin']['angle'], $data['pin']['x'], $data['pin']['y'], $textColor, $font, $data['pin']['content']);
    // Denomination
    imagettftext($image, $data['denomination']['size'], $data['denomination']['angle'], $data['denomination']['x'], $data['denomination']['y'], $textColor, $font, '$' . $data['denomination']['content']);
    // Default Text
    imagettftext($image, $data['defaultText']['size'], $data['defaultText']['angle'], $data['defaultText']['x'], $data['defaultText']['y'], $textColor, $font, $data['defaultText']['content']);

    // Create our base image with text
    $base = imagepng($image);

  // Do we need to place the logo?
  if($_FILES["logo"]["name"]){

      // Create our logo
      $logo = imagecreatefrompng($target_dir.$_FILES["logo"]["name"]);

      // Get current width/height of template
      list($top_width, $top_height) = getimagesize($base);

      // Get width/height of logo
      list($bottom_width, $bottom_height) = getimagesize($logo);

      // compute new width/height
      $new_width = ($top_width > $bottom_width) ? $top_width : $bottom_width;
      $new_height = $top_height + $bottom_height;

      // create new image and merge
      $new = imagecreate($new_width, $new_height);
      imagecopy($new, $base, 0, 0, 0, 0, $top_width, $top_height);
      imagecopy($new, $logo, 0, $top_height+1, 0, 0, $bottom_width, $bottom_height);

      // Send image to browser
      $final = imagepng($new);

      echo $final;

      // Free up memory
      imagedestroy($final);  

    }else{

      echo $base;

      // Free up memory
      imagedestroy($base); 
    }

  }

Anything stand out with what I am attempting? In short, I am trying to add both text and an image onto a "template" png image. Figured it would have been best to knock the text out first and then use that as the new template image for the logo.

like image 787
SBB Avatar asked Feb 26 '26 19:02

SBB


1 Answers

// Create our base image with text
$base = imagepng($image);

imagepng returns a boolean and outputs the image. So at this point you've sent your headers and a working PNG to the browser. You then try to perform image operations on a boolean. This will generate warning messages.

You repeat the error here:

    ...

    // Send image to browser
    $final = imagepng($new);

    echo $final;

    // Free up memory
    imagedestroy($final);  

} else {

    echo $base;

    // Free up memory
    imagedestroy($base); 
}

Now you've either output two PNGs and echoed a boolean, or output one PNG and echoed a boolean. Regardless, warning messages aplenty will be generated.

In summary:

  1. You don't need $base. Instead use $image.
  2. You don't need to create or echo $final, only call imagepng($new);.
  3. Don't echo $base; in your final else block, call imagepng($image);.

All of this should have been apparent from the PHP error log file.

like image 91
timclutton Avatar answered Feb 28 '26 16:02

timclutton