【问题标题】:Partial black background when watermarking PNG image with GD PHP使用GD PHP为PNG图像加水印时部分黑色背景
【发布时间】:2014-01-10 14:30:03
【问题描述】:

我已经拼凑了一个 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 - 这是最终结果。

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

这让我相信我已经很接近了,我希望你们这些优秀人士的专业知识可以引导我找到解决方案。

非常感谢您的阅读。

【问题讨论】:

  • 只是一个注释。 ImageMagick 已经取代了 GD 函数。
  • 当然有。不幸的是,我的应用程序故意有非常低的最低要求。诚然,考虑到此功能是唯一存在部分问题的功能,我一直在考虑将该功能设为 ImageMagick 独有,但是......您曾经遇到过其中一个您必须深入了解的问题,即使它会在这个过程中杀死你吗? :-)
  • imagecopymerge - 在这个函数中,最后一个值为 80。这与 alhpa 通道有关,我猜这是问题所在,所以也许可以尝试更改这个值。
  • 这是应用于基础图像的水印的不透明度。 i.imgur.com/lWsgc0X.png - 不透明度为 0。i.imgur.com/DxvKmOX.png - 不透明度为 100。
  • 是否有可以删除的与可以删除的水印相关的行?尝试缩小问题范围?抱歉,我不知道 GD。

标签: php image gd


【解决方案1】:

所以,我不会放弃使用 GD 找到正确答案。然而,我欣喜若狂地发现,使用 GD 需要多达 30 行代码,而 ImageMagick 使用更少的代码就可以实现:

    $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 的答案,我将非常感激。

【讨论】:

    【解决方案2】:

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

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

    1. gd 不喜欢 24 位 .png 并导致了一些愚蠢的问题。切换到 8 位使用 gd 解决了这个问题。另一方面,imagick 与 24 位 .png 配合得非常好,最终结果似乎更好。
    2. 对我来说,如果我打开原始水印.png 并使用imagecopymerge() 设置水印透明度,则使用gd 效果很好。但是,如果我首先尝试缩放原始水印.png(具有透明背景),那么我会得到与水印图像所在的黑色或白色背景部分相似的结果。请参阅How do I resize pngs with transparency in PHP? 获取部分解决方案,首先使用透明矩形填充新的 wm 图像。对我来说,无论我尝试什么,最终结果仍然会产生不透明的白色背景。
    3. 我切换到imagick 并使用setImageOpacity() 来更改我的水印.png 的透明度,然后再将它应用到我的原始图像之上,我仍然得到与黑色背景相同的效果。最后在PHP doc 中读取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。这意味着一个实心像素(1 的 alpha 值)在完成时会产生 1/2.2222.45 alpha 或透明度。任何已经透明的像素(alpha 0)都会保持透明,因为0 除以任何东西总是什么?零!

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

    【讨论】:

      猜你喜欢
      • 2015-04-20
      • 1970-01-01
      • 1970-01-01
      • 2019-07-19
      • 2014-10-17
      • 1970-01-01
      • 2013-03-17
      • 2018-03-15
      • 1970-01-01
      相关资源
      最近更新 更多