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

时间:2013-12-22 01:56:41

标签: php image gd

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

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

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

非常感谢您阅读。

2 个答案:

答案 0 :(得分:1)

所以,我并没有放弃使用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,那么我会非常感激。

答案 1 :(得分:1)

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

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

  1. gd并不喜欢24位.png并导致一些愚蠢的问题。使用gd切换到8位解析。另一方面,imagick与24位.png的效果非常好,最终结果似乎更好。
  2. 对我来说,如果我打开原始水印gd并使用.png设置水印透明度,则使用imagecopymerge()工作正常。但是,如果我首先尝试缩放原始水印.png(具有透明背景),那么我会得到与水印图像所在的黑色或白色背景部分类似的结果。首先使用透明矩形填充新的wm图像,查看How do I resize pngs with transparency in PHP?的部分解决方案。对我来说,无论我尝试什么,这仍然会在最终结果上产生不透明的白色背景。
  3. 我切换到imagick并使用setImageOpacity()更改了我的水印.png的透明度,然后将其应用于我的原始图像之前,我仍然获得相同的效果黑色背景。最后请在setImageOpacity()中查看.png,如果原始evaluateImage()有任何透明像素,并且您尝试降低不透明度,那么这些像素将变为不透明(黑色)并应用新的透明度。相反,需要使用gd函数。这将仅改为评估每个像素的alpha通道并除以特定数字。
  4. 我认为imagick的黑/白背景问题可能是由于与gd相比,在缩放/合并时处理Alpha通道的方式类似,并且如果您想在alpha中执行此操作{1}}您只需要找到一些类似的方法来评估和操作每像素imagick频道,因为" easy"方式似乎采用已经透明的背景并使其不透明。
  5. 所以,解决方案:

    假设您要以45%的不透明度应用水印并且使用$watermark->setImageOpacity(.45);,那么请改为:

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

    这样做

    1

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

    更改水印透明度后,您可以使用df = df.replace({'diag_1' : {'(1-139)' : 0, '(140-239)' : 1}}) 将水印合并到原始图像上。