繁体   English   中英

用GD PHP水印PNG图像时的局部黑色背景

[英]Partial black background when watermarking PNG image with GD PHP

我已经拼凑了一个PHP类,使用PHP的GD函数执行各种与图像相关的函数。

它适用于所有图像类型。 旋转,翻转,调整大小,裁剪以及较小程度的水印。

除了后者之外的所有工作都完美 例如,经过一些更改后,旋转的PNG图像保持其透明度,而在它们丢失之前,背景变黑。 看来常见的问题。 但现在一切正常。

我仍然卡住的地方是用另一个PNG图像为PNG图像添加水印。 它似乎与JPG和其他图像一起使用。 这是代码(简化):

public function writeWatermarkSimple()
{
    $watermarkFile = 'watermark.png';
    $watermarkImage = imagecreatefrompng($watermarkFile);

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

    $imageFile = 'image.png';
    $baseImage = imagecreatefrompng($imageFile);

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

    $marginH = imagesx($baseImage) - imagesx($watermarkImage);
    $marginV = imagesy($baseImage) - imagesy($watermarkImage);

    $cut = imagecreatetruecolor(imagesx($watermarkImage), imagesy($watermarkImage));
    imagecopy($cut, $baseImage, 0, 0, $marginH, $marginV, imagesx($watermarkImage), imagesy($watermarkImage));
    imagecopy($cut, $watermarkImage, 0, 0, 0, 0, imagesx($watermarkImage), imagesy($watermarkImage));

    imagecopymerge($baseImage, $cut, $marginH, $marginV, 0, 0, imagesx($watermarkImage), imagesy($watermarkImage), 80);

    if (!imagepng($baseImage, 'watermarked_image.png'))
    {
        return false;
    }

    return true;
}

这已经与人们基于类似问题给出的各种指南和建议拼凑在一起。 再次,完美地与JPG图像和PNG水印,但不是PNG和PNG。

一些示例图片:

http://i.imgur.com/hHRWinj.png - 这是我正在使用的水印。 http://i.imgur.com/6sy8Ncs.png - 这是我正在应用水印的图像。 http://i.imgur.com/ghovYLm.png - 这是最终结果。

我觉得有趣的是,覆盖在图像的非透明部分上的水印的任何部分都能正常工作。 其余部分都是黑色背景。

这让我相信自己很亲近,我希望你这些优秀人才的专业知识可以引导我找到解决方案。

非常感谢您的阅读。

所以,我并没有放弃使用GD来找到正确的答案。 但是,我非常高兴地发现,使用ImageMagick可以使用更少的代码来实现GD需要多达30行的代码:

    $image = new Imagick();
    $image->readimage($this->_image);

    $watermark = new Imagick();
    $watermark->readimage($this->_watermark->_getImage());
    $watermark->evaluateImage(Imagick::EVALUATE_DIVIDE, 2, Imagick::CHANNEL_ALPHA);

    $image->compositeImage($watermark, imagick::COMPOSITE_OVER, $marginH, $marginV);

所以这是之前(使用GD): http//i.imgur.com/AlS0TcO.png

之后(使用ImageMagick和上面的代码): http//i.imgur.com/zBxlC3R.png

如果有人的答案纯粹是GD,那么我会非常感激。

最近遇到了一些类似的问题,虽然这可能无法解决你的问题,但这些都是我做的一些有用的发现。

就我而言,我有一个原始的.jpg图像和一个水印.png图像。 水印图像具有完全透明的背景。 我想在我的脚本中指定不透明度,并在将其置于原始图像顶部之前更改水印不透明度。 关于PHP水印的大多数帖子假设原始水印.png文件已经将实心水印部分设置为正确的不透明度而不是通过脚本更改它。

  1. gd不喜欢24位.png并引起了一些愚蠢的问题。 切换到8位用gd解决了这个问题。 另一方面, imagick与24位.png效果非常好,最终结果似乎更好。
  2. 对我来说,如果我打开原始水印.png并使用imagecopymerge()设置水印透明度,使用gd工作得很好。 但是,如果我首先尝试缩放原始水印.png (具有透明背景),那么我会得到与水印图像所在的黑色或白色背景部分类似的结果。 请参阅如何在PHP中使用透明度调整png的大小? 通过首先用透明矩形填充新的wm图像来获得部分解决方案。 对我来说,无论我尝试什么,这仍然会在最终结果上产生不透明的白色背景。
  3. 我切换到imagick并使用setImageOpacity()来改变我的水印.png的透明度,然后将其应用到原始图像之上,我仍然在黑色背景下获得相同的效果。 最后在PHP文档中读取setImageOpacity() ,如果原始.png具有任何透明像素并且您尝试降低不透明度,那么这些像素将变为不透明(黑色)并应用新的透明度。 相反,需要使用evaluateImage()函数。 这将仅改为评估每个像素的alpha通道并除以特定的数字。
  4. 我认为gd的黑/白背景问题很可能是因为与imagick相比,它在缩放/组合时处理alpha通道的方式相似,如果你想在gd完成所有这些,你只需要找到一些类似的方法来评估和操纵每像素的alpha通道,因为“简单”的方式似乎采用已经透明的背景并使其不透明。

所以,解决方案:

假设您想以45%的不透明度应用水印并且您正在使用imagick ,那么请改为:

$watermark->setImageOpacity(.45);

做这个

$watermark->evaluateImage(Imagick::EVALUATE_DIVIDE, (1/.45), Imagick::CHANNEL_ALPHA);

您需要将1除以不透明度以获得幻化器,函数将为每个像素划分Alpha通道值。 在这种情况下, 1/.45 = 2.2222 ,那么函数将每个像素的alpha通道除以2.2222 这意味着实心像素(alpha为1 )在完成时会产生1/2.2222.45 alpha或透明度。 任何已经透明的像素(alpha 0 )都会保持透明,因为0除以任何东西总是如此? 零!

更改水印透明度后,您可以使用compositeImage()将水印合并到原始图像上。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM