0

I'm trying to add a watermark to images right after uploading them to my website, but it seems the watermark keeps coming out as a black object with no details. I believe the script is working a little bit because if it wasn't, I probably wouldn't see any kind of watermark or the script would fail.

This is my script so far:

$watermark = imagecreatefrompng('preview-watermark.png');  
$watermark_width = imagesx($watermark);  
$watermark_height = imagesy($watermark);        
$image = imagecreatetruecolor($watermark_width, $watermark_height);  
$image = imagecreatefromjpeg($portfolio_preview_dir.'/'.$file);  
$size = getimagesize($portfolio_preview_dir.'/'.$file);  
$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, $portfolio_preview_dir.'/'.$file);  
imagedestroy($image); 
imagedestroy($watermark);

This is what it's producing. The shape of the watermark is correct, as the watermark is 325x37 pixels:

enter image description here

I have tried playing with the watermark image itself. My first attempt was to save the photoshop watermark (with transparent bg) using 'save for web' and selected 'PNG-24'. This didn't work, so I then saved it as a normal PNG (without 'save for web') and it still fails.

I'm not sure whether it's the script or the image! Can somebody please share some knowledge with me and help fix this issue?

TheCarver
  • 19,391
  • 25
  • 99
  • 149
  • I remember reading [somewhere](http://stackoverflow.com/questions/11680734/php-watermark-png-transparency-alpha) there are some GD issues with PNG-24 and PNG-8 would be preferable with regards to wattermarks. – Mihai Stancu Aug 07 '13 at 17:10

2 Answers2

1
$watermark = imagecreatefrompng('preview-watermark.png');
imagealphablending($watermark , false);
imagesavealpha($watermark , true);
$watermark_width = imagesx($watermark);  
$watermark_height = imagesy($watermark);        
$image = imagecreatetruecolor($watermark_width, $watermark_height);  
$image = imagecreatefromjpeg($portfolio_preview_dir.'/'.$file);  
$size = getimagesize($portfolio_preview_dir.'/'.$file);  
$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, $portfolio_preview_dir.'/'.$file);  
imagedestroy($image); 
imagedestroy($watermark);

There are things:

  1. imagecopymerge does not allow transparency for PNG-24

(Source: https://drupal.org/node/80369)

  1. imagesavealpha + imagealphablending allow to save transparency

(Source: http://php.net/manual/en/function.imagesavealpha.php)

I hope it fixes your problem.

Also you output a JPEG, why? Stay with PNG and your image will support transparent watermarks, right now it does not!

D. Schalla
  • 655
  • 4
  • 9
  • With actually trying it, I know you're right. After posting the question, a related article popped up and somebody said the same thing. I just tested a PNG-8 watermark and it worked okay, although looked very rough around the edges. I will have a go at changing 'imagecopymerge' to except PNG-24's. Thanks. – TheCarver Aug 07 '13 at 17:14
  • Great to hear, I added something additional to the answer, why you use imagejpeg instead imagepng? – D. Schalla Aug 07 '13 at 17:15
  • My user uploads a JPEG file and the upload script saves it as a JPEG file, so I suppose I was just trying to keep it all the same. I'd have to change a fair bit of code in the rest of the app if I were to use PNG's. – TheCarver Aug 07 '13 at 17:18
  • No, you just have to change imagejpeg() to imagepng() normnally, but alright. You just can't use transparency then. – D. Schalla Aug 07 '13 at 17:25
  • Decided the mods to the rest of the site (for using png's instead of jpg's) were worth it. I've got the script working now. Thanks. – TheCarver Aug 07 '13 at 17:47
0

There are many solution on SO and php.net as well. This is one (without creating new image itself)

// Load the stamp and the photo to apply the watermark to
$stamp = imagecreatefrompng('stamp.png');
$im = imagecreatefromjpeg('photo.jpeg');

// Set the margins for the stamp and get the height/width of the stamp image
$marge_right = 10;
$marge_bottom = 10;
$sx = imagesx($stamp);
$sy = imagesy($stamp);

// Copy the stamp image onto our photo using the margin offsets and the photo 
// width to calculate positioning of the stamp. 
imagecopy($im, $stamp, imagesx($im) - $sx - $marge_right, imagesy($im) - $sy - $marge_bottom, 0, 0, imagesx($stamp), imagesy($stamp));

// Output and free memory
header('Content-type: image/png');
imagepng($im);
imagedestroy($im);

edit

Watermark should be saved with alpha channek (transparency). Photoshop since CS2 (save for web) should do the thing, also GIMP works great.

kwarunek
  • 12,141
  • 4
  • 43
  • 48
  • Thanks for your time but I'm not really looking for a new script, I just want to find out why this is happening and fix the script I have. – TheCarver Aug 07 '13 at 17:05
  • You wrote `I'm not sure whether it's the script or the image` so I presume that your script (without further analysis) its not working correctly. We cannot test if image is ok, because you haven't attached it. – kwarunek Aug 07 '13 at 17:07