PHP - Watermark PNG Transparency/Alpha
php, watermark
Solution
It's not an issue with the application code, it's with the watermark image (PNG) itself.
A lot of watermark examples/tutorials say to use a PNG-24 watermark, but according to a blog I've just read, they say that `imagecopymerge` does not deal with PNG-24 files very well, therefore, use PNG-8 and some special 'Save for Web' settings. I did this and it works fine now.
Here is the relevant section about PNG types from this blog:
The watermark image should be in one of the following recommended formats:
- PNG-8 (recommended) Colors: 256 or less Transparency: On/Off
- GIF Colors: 256 or less Transparency: On/Off
- JPEG Colors: True color Transparency: n/a
The imagecopymerge function does not properly handle the PNG-24 images; it is therefore not recommended.
If you are using Adobe Photoshop to create watermark images, it is recommended that you use "Save for Web" command with the following settings:
File Format: PNG-8, non-interlaced
Color Reduction: Selective, 256 colors
Dithering: Diffusion, 88%
Transparency: On, Matte: None
Transparency Dither: Diffusion Transparency Dither, 100%
And for other's benefits, this is the watermark code I have that works:
<?
$masterURL = 'mydomain.com/myImage.jpg';
header('content-type: image/jpeg');
$watermark = imagecreatefrompng('watermark.png');
$watermark_width = imagesx($watermark);
$watermark_height = imagesy($watermark);
$image = imagecreatetruecolor($watermark_width, $watermark_height);
$image = imagecreatefromjpeg($masterURL);
$size = getimagesize($masterURL);
$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);
imagedestroy($image);
imagedestroy($watermark);
?>
After a bit more reading (this comment on the same article), I found out that you CAN use PNG-24 watermarks but with `imagecopy` instead of `imagecopymerge`. You can replace this line:
imagecopymerge($image, $watermark, $dest_x, $dest_y, 0, 0, $watermark_width, $watermark_height, 100);
with this one:
imagecopy($image, $watermark, $dest_x, $dest_y, 0, 0, $watermark_width, $watermark_height);
Using `imagecopymerge` with PNG-8 watermarks is quite good for 'on-the-fly' watermarking, as the watermark file is tiny. If you do watermarking 'behind-the-scenes', it doesn't really matter about file size and you can get much better quality from the PNG-24 watermark, using `imagecopy`.
I hope this helps the confused watermarkers out there.
Problem
I know this has been covered PLENTY of times but I keep trying different scripts and modifying the one I have, and I still can't get my PNG-24 watermark.png to be transparent over the top of my parent image. This is what I have currently: ``` <? header('content-type: image/jpeg'); $watermark = imagecreatefrompng('watermark.png'); $watermark_width = imagesx($watermark); $watermark_height = imagesy($watermark); $image = imagecreatefromjpeg($imageURL); $image = imagecreatetruecolor($watermark_width, $watermark_height); $size = getimagesize($imageURL); imagealphablending($image, false); imagesavealpha($image, true); $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); imagedestroy($image); imagedestroy($watermark); ?> ``` I've just read another SO question and one of the answers advised that it won't be transparent if you don't add these two lines: ``` imagealphablending($image, false); imagesavealpha($image, true); ``` I added them and still not. I tried setting headers and output to PNG instead but still no luck. I loaded the watermark in my browser (raw) and it's definitely transparent but just not on the image. Surely this can't be that difficult? Any ideas what I'm doing wrong?