3

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.

SBB
  • 8,560
  • 30
  • 108
  • 223
  • anything from error reporting? – Funk Forty Niner Dec 30 '17 at 21:52
  • @FunkFortyNiner Not that I am seeing. On some of the images that dont open (that become corrupt), I open them in a editor and they say `Resource #6` before the contents of the HTML. – SBB Dec 30 '17 at 22:00
  • That "Resource #6" is a database error. You're using a database for this somewhere? This could also be related to your html form after seeing this q&a https://stackoverflow.com/q/9618604/1415724 and a few more. It could also be related to cURL. – Funk Forty Niner Dec 30 '17 at 22:04
  • Nope, nothing database related in here :/ – SBB Dec 30 '17 at 22:04
  • Now that makes this really odd. – Funk Forty Niner Dec 30 '17 at 22:05
  • A `Resource` isn't only a database connection. To quote the [manual page](http://php.net/manual/en/language.types.resource.php), "A resource is a special variable, holding a reference to an external resource.". For example, `var_dump(imagecreate(100,100));` returns `resource(4) of type (gd)`. – timclutton Jan 02 '18 at 10:21

1 Answers1

1
// 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.

timclutton
  • 12,682
  • 3
  • 33
  • 43