Watermarking images - no transparency

Been at this for hours and it’s driving me nuts. I am using the original code published here a while back with some changes for my application. What is happening is the PNG (which has a transparent background) is showing up as a white square on the larger images … can’t for the life of me figure it out. Here’s the function:

function add_watermark($image_name, $watermark_file, $gallery_id, $photographer_id)	{

	$system = explode(".", $watermark_file);

	if (preg_match("/jpg|jpeg|jpe|JPG|JPEG|JPE/", $watermark_file))	{
		$watermark = imagecreatefromjpeg($_SERVER['DOCUMENT_ROOT'] . "/images/galleries/{$photographer_id}/{$watermark_file}");
		}
	else if (preg_match("/png|PNG/", $system[1]))	{
		$watermark = imagecreatefrompng($_SERVER['DOCUMENT_ROOT'] . "/images/galleries/{$photographer_id}/{$watermark_file}");
		}
	else if (preg_match("/gif|giff|GIF|GIFF/", $system[1]))	{
		$watermark = imagecreatefromgif($_SERVER['DOCUMENT_ROOT'] . "/images/galleries/{$photographer_id}/{$watermark_file}");
		}	

	$watermark_width = imagesx($watermark);  
	$watermark_height = imagesy($watermark);  

	$image = imagecreatetruecolor($watermark_width, $watermark_height);  
		
	$image = imagecreatefromjpeg($_SERVER['DOCUMENT_ROOT'] . "/images/galleries/{$photographer_id}/{$gallery_id}/{$image_name}");  

	$size = getimagesize($_SERVER['DOCUMENT_ROOT'] . "/images/galleries/{$photographer_id}/{$gallery_id}/{$image_name}");  

	$dest_x = $size[0] - $watermark_width - 5;  
	$dest_y = $size[1] - $watermark_height - 5;  

	imagecopymerge($image, $watermark, $dest_x, $dest_y, 0, 0, $watermark_width, $watermark_height, 100);  
	imagejpeg($image, $_SERVER['DOCUMENT_ROOT'] . "/images/galleries/{$photographer_id}/{$gallery_id}/{$image_name}");  
		
	imagedestroy($image);  
	imagedestroy($watermark);  
		
	}

I also played around with setting the alpha blending on the watermark image and the newly created image:


imagealphablending($image, true);
imagealphablending($watermark, true);

as I found in a couple of blogs but still I get nothing but a white background square.

What the heck am I doing wrong here?


$image = imagecreatetruecolor($watermark_width, $watermark_height);  
$image = imagecreatefromjpeg($_SERVER['DOCUMENT_ROOT'] . "/images/galleries/{$photographer_id}/{$gallery_id}/{$image_name}");

uh… okay, what’s the purpose of the first line? Creates an image file that never gets used?

You’re copying a PNG onto a JPEG (The second line makes it a JPEG), which destroys alpha information…

Both images are loaded so they are actually gd2 resources, not jpeg or png anymore. When you copy a gd2 image onto a gd2 image the transparency is preserved.

That being said, replace


imagecopymerge($image, $watermark, $dest_x, $dest_y, 0, 0, $watermark_width, $watermark_height, 100);

with


imagecopy($image, $watermark, $dest_x, $dest_y, 0, 0, $watermark_width, $watermark_height);

and it works. At least it does when I test it here :slight_smile:

Also, the regex at the start of your function is way too complex, and you don’t need $system=explode($watermark_file);


if (preg_match("/jpe?g$/i", $watermark_file)) {
	$watermark = imagecreatefromjpeg($watermark_file);
}
else if (preg_match("/png$/i", $watermark_file))   {
	$watermark = imagecreatefrompng($watermark_file);
}
else if (preg_match("/gif$/i", $watermark_file)) {
	$watermark = imagecreatefromgif($watermark_file);
}

:slight_smile:

yes - i think it’s a bug with imagecopymerge() - the documentation says it supports alpha, but it doesn’t. Use imagecopyresized() or imagecopy() as scallio suggested

Well color me fixed :slight_smile:

Funny, 90% of the tutorials I saw on the web used the merge including the original I got from an article here…

As far as the regex . yeah I know, sloppy. I had copied and pasted it from some ancient code I had lying around and had gotten so tied up with this I hadn’t bothered with any ‘cleaning’

Thanks man, my throbbing head just started feeling a whole lot better

Well I hate to be a pain in the butt but something weird happened today, the code I had working last night (after I got the fix here) is now not working, throwing errors that the image is not a valid JPEG.

I tested using the exact images I used yesterday just to be safe but I am getting this:

[15-Apr-2011 15:47:34] PHP Warning: imagecreatefromjpeg() [<a href=‘function.imagecreatefromjpeg’>function.imagecreatefromjpeg</a>]: gd-jpeg: JPEG library reports unrecoverable error: in D:\xampplite\htdocs\photographers\functions\Thumbnailer.php on line 110
[15-Apr-2011 15:47:34] PHP Warning: imagecreatefromjpeg() [<a href=‘function.imagecreatefromjpeg’>function.imagecreatefromjpeg</a>]: ‘D:/xampplite/htdocs/images/galleries/75/530/DSCF4009.JPG’ is not a valid JPEG file in D:\xampplite\htdocs\photographers\functions\Thumbnailer.php on line 110
[15-Apr-2011 15:47:34] PHP Warning: imagecopy(): supplied argument is not a valid Image resource in D:\xampplite\htdocs\photographers\functions\Thumbnailer.php on line 117
[15-Apr-2011 15:47:34] PHP Warning: imagejpeg(): supplied argument is not a valid Image resource in D:\xampplite\htdocs\photographers\functions\Thumbnailer.php on line 119
[15-Apr-2011 15:47:34] PHP Warning: imagedestroy(): supplied argument is not a valid Image resource in D:\xampplite\htdocs\photographers\functions\Thumbnailer.php on line 121

and the function is this:

function add_watermark($image_name, $watermark_file, $gallery_id, $photographer_id) {
	 
	$system = explode(".", $watermark_file);
	 
	if (preg_match("/jpg|jpeg|jpe|JPG|JPEG|JPE/", $watermark_file)) {
		$watermark = imagecreatefromjpeg($_SERVER['DOCUMENT_ROOT'] . "/images/galleries/{$photographer_id}/{$watermark_file}");
		}
	else if (preg_match("/png|PNG/", $system[1]))   {
		$watermark = imagecreatefrompng($_SERVER['DOCUMENT_ROOT'] . "/images/galleries/{$photographer_id}/{$watermark_file}");
		}
	else if (preg_match("/gif|giff|GIF|GIFF/", $system[1])) {
		$watermark = imagecreatefromgif($_SERVER['DOCUMENT_ROOT'] . "/images/galleries/{$photographer_id}/{$watermark_file}");
		}   
	 
	$watermark_width = imagesx($watermark); 
	$watermark_height = imagesy($watermark); 
	 
	$image = imagecreatetruecolor($watermark_width, $watermark_height); 
		   
	$image = imagecreatefromjpeg($_SERVER['DOCUMENT_ROOT'] . "/images/galleries/{$photographer_id}/{$gallery_id}/{$image_name}"); 
	 
	$size = getimagesize($_SERVER['DOCUMENT_ROOT'] . "/images/galleries/{$photographer_id}/{$gallery_id}/{$image_name}"); 
	 
	$dest_x = $size[0] - $watermark_width - 5; 
	$dest_y = $size[1] - $watermark_height - 5; 
	 
	imagecopy($image, $watermark, $dest_x, $dest_y, 0, 0, $watermark_width, $watermark_height);

	imagejpeg($image, $_SERVER['DOCUMENT_ROOT'] . "/images/galleries/{$photographer_id}/{$gallery_id}/{$image_name}"); 
		   
	imagedestroy($image); 
	imagedestroy($watermark); 
		   
	}

I even did some testing using one image at a time (where yesterday I was doing 40 or 50) to see if it was a memory problem with the same results.

What’s really odd is I use similar code to resize the images in the same object (before I call this function) and there are no errors from that.

BTW, the error line first reported in the error (line 110) is this line in the function:

$image = imagecreatefromjpeg($_SERVER['DOCUMENT_ROOT'] . "/images/galleries/{$photographer_id}/{$gallery_id}/{$image_name}"); 

Thanks, I’m befuddled again! :confused:

From da manual –

If you get this error: “Warning: imagecreatefromjpeg(): gd-jpeg: JPEG library reports unrecoverable error” then check the JPEG files. If they are saved in CMYK format (instead of RGB) then GD will fail to load them (tested with GD 2.0.12)

PHP: imagecreatefromjpeg - Manual

Maybe that’s the problem?

As I said before I used the exact same source images I used yesterday when it worked fine.

Just now I moved everything over to my laptop ‘just in case’, created a test script and hard coded in the values on the function call and I’m getting the same thing:

<?php

	add_watermark('DSCF4009.JPG', 'watermark.png', '530', '75');

	function add_watermark($image_name, $watermark_file, $gallery_id, $photographer_id) {
	 
		$system = explode(".", $watermark_file);
	 
		if (preg_match("/jpg|jpeg|jpe|JPG|JPEG|JPE/", $watermark_file)) {
			$watermark = imagecreatefromjpeg($_SERVER['DOCUMENT_ROOT'] . "/images/galleries/{$photographer_id}/{$watermark_file}");
			}
		else if (preg_match("/png|PNG/", $system[1]))   {
			$watermark = imagecreatefrompng($_SERVER['DOCUMENT_ROOT'] . "/images/galleries/{$photographer_id}/{$watermark_file}");
			}
		else if (preg_match("/gif|giff|GIF|GIFF/", $system[1])) {
			$watermark = imagecreatefromgif($_SERVER['DOCUMENT_ROOT'] . "/images/galleries/{$photographer_id}/{$watermark_file}");
			}   
	 
		$watermark_width = imagesx($watermark); 
		$watermark_height = imagesy($watermark); 
	 
		$image = imagecreatetruecolor($watermark_width, $watermark_height); 
		   
		$image = imagecreatefromjpeg($_SERVER['DOCUMENT_ROOT'] . "/images/galleries/{$photographer_id}/{$gallery_id}/{$image_name}"); 
	 
		$size = getimagesize($_SERVER['DOCUMENT_ROOT'] . "/images/galleries/{$photographer_id}/{$gallery_id}/{$image_name}"); 
	 
		$dest_x = $size[0] - $watermark_width - 5; 
		$dest_y = $size[1] - $watermark_height - 5; 
	 
		imagecopy($image, $watermark, $dest_x, $dest_y, 0, 0, $watermark_width, $watermark_height);

		imagejpeg($image, $_SERVER['DOCUMENT_ROOT'] . "/images/galleries/{$photographer_id}/{$gallery_id}/{$image_name}"); 
		   
		imagedestroy($image); 
		imagedestroy($watermark); 
		   
		}

Even so I know these images, the were created from PSD files in Photoshop and saved as RGB jpgs

I found it … I’m an IDIOT! Will explain in a bit

So, I was redoing the regex’s last night, cleaning them up and I mistakenly copy and pasted the JPG regex into the block to create a PNG … so the code was taking the JPG, saving it as a PNG and then when it tried to reopen it later it blew up cause it wasn’t a JPG any more.

This is what happens when you work 14 hour days for 3 weeks straight and decide to * cough cough * fix things late one evening.

Sorry I missed that, but glad you figured it out! :slight_smile: