PHP - Watermark PNG Transparency/Alpha - php

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?

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.

Related

How to add watermark to an image at the bottom right in PHP?

I am trying to add watermark to an image in PHP. I am using the below code that works fine. But I am facing challenges in the following ways.
<?php
function watermark_image($target, $wtrmrk_file, $newcopy) {
$watermark = imagecreatefrompng($wtrmrk_file);
imagealphablending($watermark, false);
imagesavealpha($watermark, true);
$img = imagecreatefromjpeg($target);
$img_w = imagesx($img);
$img_h = imagesy($img);
$wtrmrk_w = imagesx($watermark);
$wtrmrk_h = imagesy($watermark);
imagecopy($img, $watermark, 500, 200, 0, 0, 100, 100);
imagejpeg($img, $newcopy, 100);
imagedestroy($img);
imagedestroy($watermark);
}
watermark_image('1.jpg','assets/images/watermark.png', 'new_image_name.jpg');
exit();
?>
I am trying to achieve a code in which I can apply a watermark to any image on the bottom right side. with a fixed height and width of 150x150. I am trying from past 2 hours but no success in getting it accurately placed.
Does anybody has an idea? how to achieve it? It would be really very helpful.
You are placing the watermark image in the wrong location. It needs to be relative to the width and height of the source image, as well as the dimensions of the watermark image. This solves your problem:
imagecopy($img, $watermark, $img_w - $wtrmrk_w, $img_h - $wtrmrk_h, 0, 0, $wtrmrk_w, $wtrmrk_h);

PHP imagecopy & imagecopymerge changing background from transparent to black

I am copying one image and placing over second image, second image is transparent in background. While copying background of second image is converted to black. Even if i display image just after initializing image from file, it gives me black background. Please help..
<?php
header('Content-type:image/png');
$watermark = imagecreatefrompng('eye.png');
$watermark_width = imagesx($watermark);
$watermark_height = imagesy($watermark);
$image = imagecreatetruecolor($watermark_width, $watermark_height);
$image = imagecreatefrompng('img.png');
$size = getimagesize('img.png');
$dest_x = $size[0] - $watermark_width - 5;
$dest_y = $size[1] - $watermark_height - 5;
imagecopyresampled($image, $watermark, 5, 5, 0,0,55 ,55, $watermark_width, $watermark_height);
//imagecopymerge($image, $watermark, 5, 5, 0, 0, $watermark_width, $watermark_height, 50);
imagejpeg($image);
imagedestroy($image);
imagedestroy($watermark);
?>
remove the function
imagejpeg($image);
and add
imagealphablending($image, false);
imagesavealpha($image,true);
imagepng($image);

Merging and resizing an image

I'm attempting to expand my function from simply resizing an image, to also adding a watermark. The problem is the watermark is not being added. I've confirmed the path is correct. Why is it not working?
$image = imagecreatefromjpeg($this->getFile());
$size = getimagesize($this->getFile());
$watermark = imagecreatefrompng('../watermark.png');
$watermark_width = imagesx($watermark);
$watermark_height = imagesy($watermark);
$dest_x = $size[0] - $watermark_width - 10;
$dest_y = $size[1] - $watermark_height - 5;
//die($watermark_width);
$thumb_image = imagecreatetruecolor($this->getThumbWidth(), $this->getThumbHeight());
imagecopymerge($image, $watermark, $dest_x, $dest_y, 0, 0, $watermark_width, $watermark_height, 100);
imagecopyresampled( $thumb_image, $image, 0, 0, 0, 0, $this->getThumbResizeWidth(), $this->getThumbResizeHeight(), $this->getWidth(), $this->getHeight() );
imagejpeg( $thumb_image, $this->getThumbDestination(), $this->getThumbQuality() );
imagedestroy($thumb_image);
imagedestroy($image);
After posting the code I found a couple of errors, the major one being, contrary to my belief, an incorrect file path for the watermark.png. The is updated and does work for me. There is still an issue with alpha transparency, however.

Transparency of PHP merged image not working

I'm creating an image with imagecopymerge, but the image being overlaid on top, is a PNG but the transparent part is pure white. How do I enable transparency?
$image = imagecreatefromjpeg($this->getFile());
$size = getimagesize($this->getFile());
$watermark = imagecreatefrompng('../watermark.png');
$watermark_width = imagesx($watermark);
$watermark_height = imagesy($watermark);
$dest_x = $size[0] - $watermark_width - 10;
$dest_y = $size[1] - $watermark_height - 5;
//die($watermark_width);
$thumb_image = imagecreatetruecolor($this->getThumbWidth(), $this->getThumbHeight());
imagealphablending($thumb_image,true);
imagealphablending($image,true);
imagecopymerge($image, $watermark, $dest_x, $dest_y, 0, 0, $watermark_width, $watermark_height, 100);
imagecopyresampled( $thumb_image, $image, 0, 0, 0, 0, $this->getThumbResizeWidth(), $this->getThumbResizeHeight(), $this->getWidth(), $this->getHeight() );
imagejpeg( $thumb_image, $this->getThumbDestination(), $this->getThumbQuality() );
imagedestroy($thumb_image);
imagedestroy($image);
So I FINALLY found a solution. It's using imagecopy().
Here is the article that nudged me in the right direction.
That took quite a few hours of research!
Use imagecolortransparent()
Read more here
EDIT:
A better solution is here:
https://stackoverflow.com/a/313103/1533203

Scaling a watermark to fit parent image

My photo sizes vary, they are either landscape, portrait or square, and I need to make a watermark the best fit for each photo - so I need to resize just the width of the watermark (without Imagick), as it's a long rectangle shape, so height doesn't matter.
I found the PHP function, imagecopyresized, but I'll be honest, I can't work out what parameters are needed for my situation, even after looking at PHP documentation! I'm also not sure if after using imagecopyresized, the rest of my function will work where it gets the watermark width and height.
Can somebody help me get over the finish line. This is how far I got, all it needs is the right parameters added to the imagecopyresized part:
<?php
header('content-type: image/jpeg');
$image = imagecreatefromjpeg('https://.....jpg');
$imageSize = getimagesize('https://.....jpg');
$newWatermarkWidth = $imageSize[0]-50; // width of image minus 50px
$watermark = imagecreatefrompng('watermark.png');
// resize watermark to newWatermarkWidth here with imagecopyresize
$watermark = imagecopyresized(?,?,?,?);
$watermark_width = imagesx($watermark);
$watermark_height = imagesy($watermark);
$dest_x = ($imageSize[0]/2) - ($watermark_width/2) ;
$dest_y = ($imageSize[1]/2) - ($watermark_height/2);
imagecopy($image, $watermark, round($dest_x,0), round($dest_y,0), 0, 0, $watermark_width, $watermark_height);
imagejpeg($image);
imagedestroy($image);
imagedestroy($watermark);
?>
THIS IS WHAT I ENDED WITH & WORKS PERFECTLY
A script that adjusts the width of a watermark to fit across the whole parent image, centered and proportional.
<?php
header('content-type: image/jpeg');
$image = imagecreatefromjpeg('http://mydomain.com/myPhoto.jpg');
$imageSize = getimagesize('http://mydomain.com/myPhoto.jpg');
$watermark = imagecreatefrompng('http://mydomain.com/myWatermark.png');
$watermark_o_width = imagesx($watermark);
$watermark_o_height = imagesy($watermark);
$newWatermarkWidth = $imageSize[0]-20;
$newWatermarkHeight = $watermark_o_height * $newWatermarkWidth / $watermark_o_width;
imagecopyresized($image, $watermark, $imageSize[0]/2 - $newWatermarkWidth/2, $imageSize[1]/2 - $newWatermarkHeight/2, 0, 0, $newWatermarkWidth, $newWatermarkHeight, imagesx($watermark), imagesy($watermark));
imagejpeg($image);
imagedestroy($image);
imagedestroy($watermark);
This resizes the watermark and copies directly to the image.
You don't need the existing imagecopy line anymore.
$success = imagecopyresized($image, // Destination image
$watermark, // Source image
$imageSize[0]/2 - $newWatermarkWidth/2, // Destination X
$imageSize[1]/2 - imagesy($watermark)/2, // Destination Y
0, // Source X
0, // Source Y
$newWatermarkWidth, // Destination W
imagesy($watermark), // Destination H
imagesx($watermark), // Source W
imagesy($watermark)); // Source H

Categories