PHP - 给PNG图片添加水印并保留透明度/Alpha通道

5

我知道这个问题已经被反复讨论了很多次,但是我一直在尝试不同的脚本并修改我已有的脚本,但我仍然无法使我的PNG-24 watermark.png透明地覆盖在父级图像上。

这是我目前拥有的:

<?

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);

?>

我刚刚阅读了另一个Stack Overflow的问题,其中一个答案建议如果您不添加以下两行代码,则不会透明:

imagealphablending($image, false);
imagesavealpha($image, true);

我已经添加了它们,但仍然没有效果。我尝试设置头信息并将输出设为PNG格式,但仍然没有运气。 我在浏览器中加载了水印(原始文件),确实是透明的,但是在图片上不起作用。这肯定不可能那么难吧?有什么想法我做错了什么吗?

1个回答

17

这不是应用程序代码的问题,而是水印图像(PNG)本身的问题。

许多水印示例/教程都建议使用PNG-24作为水印,但根据我刚读到的一篇博客,他们称imagecopymerge不能很好地处理PNG-24文件,因此需要使用PNG-8和一些特殊的“另存为Web”设置。我按照这样做后,它现在运行良好。

以下是该博客中关于PNG类型的相关部分:

水印图像应该采用以下推荐格式之一:

  • PNG-8(推荐)
    颜色: 256或更少
    透明度: 开/关
  • GIF
    颜色: 256或更少
    透明度: 开/关
  • JPEG
    颜色: 真彩色
    透明度: 无

imagecopymerge函数不能正确处理PNG-24图像,因此不建议使用。

如果您使用Adobe Photoshop创建水印图像,则建议使用“另存为Web”命令,并采用以下设置:

File Format: PNG-8, non-interlaced
Color Reduction: Selective, 256 colors
Dithering: Diffusion, 88%
Transparency: On, Matte: None
Transparency Dither: Diffusion Transparency Dither, 100%
为了其他人的好处,这是我拥有且可用的水印代码:
<?
$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);
?>

经过更多阅读(这篇文章的评论),我发现您可以使用PNG-24水印,但是要使用imagecopy而不是imagecopymerge。 您可以将此行替换为:

imagecopymerge($image, $watermark, $dest_x, $dest_y, 0, 0, $watermark_width, $watermark_height, 100);
这个:
imagecopy($image, $watermark, $dest_x, $dest_y, 0, 0, $watermark_width, $watermark_height);

使用 imagecopymerge 对 PNG-8 水印进行处理非常好,因为水印文件很小,适用于“即时”水印。如果您在“后台”对水印进行处理,文件大小并不重要,您可以使用 imagecopy 从 PNG-24 水印获得更高的质量。

希望这可以帮助困惑的水印制作者们。


1
请勿包含文本截图。 - user229044
2
@meagar:为什么?如果它让你如此困扰,那就重写它! - TheCarver
6
我做了,但我本不应该这么做。不要截屏文字。它对网络、网站和用户都是有害的。 - user229044
值得注意的是:(i) RGBA PNG比基于调色板的PNG更好,因为它们提供了完整的颜色范围;(ii)由于alpha透明度,边缘与背景混合得更加平滑;(iii)整个图像可以被部分透明,以便背景图像部分地显示出来。 - Salman A

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接