Page 1 of 1

PHP generated image as an overlay?

Posted: Wed Feb 28, 2007 3:35 am
by Zu
I have hit a bit of a snag. I have 2 PHP files, portion.php and template.php. Template uses a default image as a template and uses Portion to overlay an image onto it.

Portion works fine, when you go to the page it will create the image I need, everything okay there.

When I go to Template uses the imagecreatefrompng() function to create a PNG image from the Portion class, this is where the snag is.

The problem comes when I try and make the overlay image PHP generated. If I reference it to a standard PNG file, it works perfectly. I am guessing that the Portion class isn't making a true PNG image for the imagecreatefrompng() function.

Here are the two files I am using:

Code: Select all

<?php
// Header mime type
header('Content-type: image/png');

// Only get a small part of the image
$image = imagecreatefromgif('overlay.gif');
$crop = imagecreatetruecolor(75, 20);

// Make the small part of the image smaller
imagecopy($crop, $image, 0, 0, 40, 13, 75, 20);
imagecopyresampled($crop, $crop, 0, 0, 0, 0, 55, 20, imagesx($crop), imagesy($crop));

// Only get what we need from the new smaller image
$crop2 = imagecreatetruecolor(55, 20);
imagecopy($crop2, $crop, 0, 0, 0, 0, 55, 20);

// Create the PNG graphic
imagepng($crop2);

Code: Select all

<?php
// Header mime type
header('Content-type: image/png');

// The overlay image
$overlay = 'portion.php';
$overlay = imagecreatefrompng($overlay);
$overlayX = imagesx($overlay);
$overlayY = imagesy($overlay);

// The template image
$template = imagecreatefromgif('template.gif');
$templateX = imagesx($template);
$templateY = imagesy($template);

// The dimentions of the final graphic
$imageX = 90;
$imageY = 50;

// Where to place the overlay
$offsetX = 30;
$offsetY = 12;

// Create the basic graphic holder
$image = imagecreatetruecolor($imageX, $imageY);

// Put the template in the image
imagecopyresampled($image, $template, 0, 0, 0, 0, $imageX, $imageY, $templateX, $templateY);

// Overlay the overlay graphic onto the template
imagecopymerge($image, $overlay, $offsetX, $offsetY, 0, 0, $overlayX, $overlayY, 99);

// Create the PNG graphic
imagepng($image);
If I change the line

Code: Select all

$overlay = 'portion.php';
to

Code: Select all

$overlay = 'portion.png';
it works fine, so here is my question to you PHP guru's, is there another header I need in the portion.php file???

Thanks :)

Posted: Wed Feb 28, 2007 3:44 am
by onion2k
You've not said what the problem is.

Posted: Wed Feb 28, 2007 3:52 am
by Zu
In essence, the imagecreatefrompng() function in the template.php file does not like the source as portion.php, but works fine if I save the output of the portion.php file as portion.php.png.

The error is that is says imagesx() and imagesy() contain invalid arguments (off the top of my head, at work at the moment).

Posted: Wed Feb 28, 2007 3:57 am
by onion2k
Right.

Code: Select all

$overlay = 'portion.php';
$overlay = imagecreatefrompng($overlay);
portion.php is not a PNG file, it's a text file containing PHP. If you access it locally on the fileserver your script will try to open it as if it's a PNG and fail, then imagesx() and imagesy() will fail because $overlay isn't a valid image resource. You need to rewrite the script so that portion.php creates $crop2 but doesn't generate a PNG file from it, then include() it and use $crop2 in template.php. Better yet, rewrite portion.php as a function or an object and call it in template.php.

Posted: Wed Feb 28, 2007 4:14 am
by Zu
Thanks, will have a go at it in a while.

And I was going to make in into a class, was just getting the barebones done first. The GD lib unfortunatly isn't my speciality.

Posted: Wed Feb 28, 2007 5:01 am
by onion2k
Zu wrote:The GD lib unfortunatly isn't my speciality.
Feel free to ask any questions because it is mine. :)

Posted: Thu Mar 01, 2007 9:31 am
by Zu
Right, I found a spare 5 mins and gave it another go.
You need to rewrite the script so that portion.php creates $crop2 but doesn't generate a PNG file from it, then include() it and use $crop2 in template.php.
I must be misreading you (or doing it wrong), as whenever I call the resource into imagecreatefrompng() it outputs errors saying it failed to open the file. It is expecting an actual image file rather than a resource.

Code: Select all

Warning: imagecreatefrompng(Resource id #5) [function.imagecreatefrompng]: failed to open stream: No such file or directory in F:\localhost\htdocs\GenerateImage.class.php on line 91

Warning: imagecopyresampled(): supplied argument is not a valid Image resource in F:\localhost\htdocs\GenerateImage.class.php on line 103

Warning: imagesx(): supplied argument is not a valid Image resource in F:\localhost\htdocs\GenerateImage.class.php on line 109

Warning: imagesy(): supplied argument is not a valid Image resource in F:\localhost\htdocs\GenerateImage.class.php on line 109

Warning: imagecopymerge(): supplied argument is not a valid Image resource in F:\localhost\htdocs\GenerateImage.class.php on line 110
This is the code I am using, I found time to put it into a class:

Code: Select all

<?php
/**
 * Generated an overlay onto a template
 * @author Zu
 * @version 0.2
 * @package ImageManipulation
 */
class GenerateOverlayImage
{
    /**
     * The URL of the original image
     * @access private
     * @var string 
     */
	private $originalLocation;
	
    /**
     * The URL of the template image
     * @access private
     * @var string 
     */
	private $templateLocation;
	
    /**
     * The overlay image
     * @access private
     * @var string 
     */
	private $overlay;
	
    /**
     * The template image
     * @access private
     * @var string 
     */
	private $template;
	
    /**
     * The final image
     * @access private
     * @var string 
     */
	private $image;

    /**
     * Class constructor
     * @access public
     */
	public function GenerateOverlayImage()
	{
		$this -> originalLocation = 'original.gif';
		$this -> originalLocation = 'template.gif';
		
		$this -> generateOverlay();
		$this -> generateTemplate();
	}
	
    /**
     * Generates the overlay image
     * @access private
     */
	private function generateOverlay()
	{
		// Get the image, then get a small part of it
		$tempImage = imagecreatefromgif($this -> originalLocation);
		$crop = imagecreatetruecolor(75, 20);

		// Shrink that small part of the image
		imagecopy($crop, $tempImage, 0, 0,
									 40, 13,
									 75, 20);
		imagecopyresampled($crop, $crop, 0, 0, 0, 0,
										 55, 20,
										 imagesx($crop),
										 imagesy($crop));
		
		// Remove the unessecary excess from the crop
		$this -> overlay = imagecreatetruecolor(55, 20);
		imagecopy($this -> overlay, $crop, 0, 0,
										   0, 0,
										   55, 20);
	}
	
    /**
     * Generates the template image
     * @access private
     */
	private function generateTemplate()
	{
		// The overlay image
		$this -> overlay = imagecreatefrompng($this -> overlay);
		
		// The template image
		$this -> template = imagecreatefromgif($this -> templateLocation);
		
		// Create the basic graphic holder
		$this -> image = imagecreatetruecolor(90, 50);
		
		// Put the template in the image
		imagecopyresampled($this -> image, $this -> template,
							0, 0, 0, 0,
							90, 50,
							30, 12);
		
		// Begin the overlaying
		imagecopymerge($this -> image, $this -> overlay,
						30, 12,
						0, 0,
						imagesx($this -> overlay), imagesy($this -> template),
						99);
	}

    /**
     * Returns the image
     * @access public
     * @return string overlayed template image
     */
	public function getImage()
	{
		return imagepng($this -> image);
	}
}

header('Content-type: image/png');
$image = new GenerateOverlayImage();
$image -> getImage();
One thing I thought about doing is saving the generated overlayed image to a file, and then calling that... would get round the problem, but I would prefer not to do that if at all possible.

Go easy on me, I'm fragile :\

Posted: Thu Mar 01, 2007 9:46 am
by feyd
$this->overlay is an image resource after calling generateOverlay().