php如何合并PNG图片

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了php如何合并PNG图片相关的知识,希望对你有一定的参考价值。

我知道的gd函数imagecopy,imagecopyresized等这些函数都只是间单的把两张回片叠在一起,而且叠着合并一起后,整个图片背景颜色都变了.不是我要的效果.
我要实现的举个例子,我有一张大背景图,格式当然是PNG的,而这张PNG图片中间是被PS抠出来的一个形状,空白区域的没任何东西,这个区域的尺寸大概是100px*100px无规则的形状,然后有另外一张小图片300*300的图片,我要把这张小图片放在这张大背景图的后面这个无规则这个区域里,当然这张小的图片形状是不允许改变的,把它放在大背景图后面然后只显示无规则区域内的小图片.不知我描述是否清晰,请问哪位大侠能指点一下?先谢了

参考技术A 自认为两种可以实现:
用css,图片作为网页背景,大图片可以作为表格等的背景,这样表格背景遮挡网页背景,只要位置设置对了,应该就没有问题了
另一种,你直接把两个图片作为层,去图像处理软件上处理一下就好了。

如何使用 PIL 将透明 png 图像与另一个图像合并

【中文标题】如何使用 PIL 将透明 png 图像与另一个图像合并【英文标题】:How to merge a transparent png image with another image using PIL 【发布时间】:2011-07-16 12:41:48 【问题描述】:

我有一个透明的 png 图像“foo.png” 我用

打开了另一张图片
im = Image.open("foo2.png");

现在我需要将 foo.png 与 foo2.png 合并。

( foo.png 包含一些文本,我想在 foo2.png 上打印该文本)

【问题讨论】:

不要在 python 中的命令末尾使用;:这很难看... 我会记住的,谢谢!! 【参考方案1】:
from PIL import Image

background = Image.open("test1.png")
foreground = Image.open("test2.png")

background.paste(foreground, (0, 0), foreground)
background.show()

.paste() 的第一个参数是要粘贴的图像。第二个是坐标,秘诀是第三个参数。它表示将用于粘贴图像的掩码。如果您传递具有透明度的图像,则 Alpha 通道将用作遮罩。

检查docs。

【讨论】:

要确保前景在所有情况下都包含透明度,请使用 foreground.convert('RGBA') 作为掩码参数。 谢谢。我太少了第三个参数。 我收到ValueError: bad transparency mask 秘制酱汁很好吃 @DenizOzger 修复 ValueError: bad transparency mask 使用 bg.paste(fg, (0, 0), fg.convert('RGBA'))【参考方案2】:

当背景图像也包含透明度时,Image.paste 无法按预期工作。您需要使用真实的Alpha Compositing。

Pillow 2.0 包含一个执行此操作的 alpha_composite 函数。

background = Image.open("test1.png")
foreground = Image.open("test2.png")

Image.alpha_composite(background, foreground).save("test3.png")

编辑:两个图像都需要是 RGBA 类型。所以你需要调用convert('RGBA')如果他们是调色板等等。如果背景没有alpha通道,那么你可以使用常规粘贴方法(应该更快)。

【讨论】:

我只是使用 paste() 将一个半透明图像覆盖在另一个上,使用 PIL,它按我的预期工作。它在哪些方面没有按您的预期工作? @PeterHansen,“当背景图像也包含透明度”时,paste() 无法按预期工作。 @PeterHansen 有例子:github.com/python-pillow/Pillow/issues/… @homm 谢谢。那是很久以前的事了,我不记得我尝试了什么。看来我确实错过了您引用的关于背景图像也具有透明度的部分。 我得到ValueError: image has wrong made 以及@DenizOzger【参考方案3】:

正如 olt 已经指出的那样,Image.paste 在源 目标都包含 alpha 时无法正常工作。

考虑以下场景:

两个测试图像,都包含 alpha:

layer1 = Image.open("layer1.png")
layer2 = Image.open("layer2.png")

像这样使用Image.paste合成图像:

final1 = Image.new("RGBA", layer1.size)
final1.paste(layer1, (0,0), layer1)
final1.paste(layer2, (0,0), layer2)

生成以下图像(覆盖的红色像素的 alpha 部分完全取自第 2 层。像素未正确混合):

像这样使用Image.alpha_composite合成图像:

final2 = Image.new("RGBA", layer1.size)
final2 = Image.alpha_composite(final2, layer1)
final2 = Image.alpha_composite(final2, layer2)

产生以下(正确的)图像:

【讨论】:

感谢截图!真的很有帮助! 但是alpha_composite不能设置偏移量,你介意举个例子来完全替换paste函数吗? 我猜你必须创建一个与 garget 图像大小相同的新空图像,将图层粘贴到适当的位置并使用 alpha_compositing 将新图像混合到目标图像上。跨度> 我得到:ValueError:图像不匹配 图片大小必须一致【参考方案4】:

也可以使用混合:

im1 = Image.open("im1.png")
im2 = Image.open("im2.png")
blended = Image.blend(im1, im2, alpha=0.5)
blended.save("blended.png")

【讨论】:

这个苦行僧为我工作。图像必须具有完全相同的大小,但没关系。粘贴功能并没有完全适合我... 'ValueError: 图片不匹配' 可能,它们的尺寸不同。您可能需要缩放或裁剪其中之一。 @Schütze 看到 nvd 的评论,因为他/她没有 ping(使用 @blahblah)你【参考方案5】:

有一个类似的问题,但很难找到答案。以下函数允许您将具有透明度参数的图像粘贴到另一个图像上的特定偏移处。

import Image

def trans_paste(fg_img,bg_img,alpha=1.0,box=(0,0)):
    fg_img_trans = Image.new("RGBA",fg_img.size)
    fg_img_trans = Image.blend(fg_img_trans,fg_img,alpha)
    bg_img.paste(fg_img_trans,box,fg_img_trans)
    return bg_img

bg_img = Image.open("bg.png")
fg_img = Image.open("fg.png")
p = trans_paste(fg_img,bg_img,.7,(250,100))
p.show()

【讨论】:

ValueError: images do not match【参考方案6】:
def trans_paste(bg_img,fg_img,box=(0,0)):
    fg_img_trans = Image.new("RGBA",bg_img.size)
    fg_img_trans.paste(fg_img,box,mask=fg_img)
    new_img = Image.alpha_composite(bg_img,fg_img_trans)
    return new_img

【讨论】:

嗨,您能否为您的答案添加更多上下文?否则,请求者不太可能了解其背后的“原因”。【参考方案7】:

关键代码是:

_, _, _, alpha = image_element_copy.split()
image_bg_copy.paste(image_element_copy, box=(x0, y0, x1, y1), mask=alpha)

完整的功能是:

def paste_image(image_bg, image_element, cx, cy, w, h, rotate=0, h_flip=False):
    image_bg_copy = image_bg.copy()
    image_element_copy = image_element.copy()

    image_element_copy = image_element_copy.resize(size=(w, h))
    if h_flip:
        image_element_copy = image_element_copy.transpose(Image.FLIP_LEFT_RIGHT)
    image_element_copy = image_element_copy.rotate(rotate, expand=True)
    _, _, _, alpha = image_element_copy.split()
    # image_element_copy's width and height will change after rotation
    w = image_element_copy.width
    h = image_element_copy.height
    x0 = cx - w // 2
    y0 = cy - h // 2
    x1 = x0 + w
    y1 = y0 + h
    image_bg_copy.paste(image_element_copy, box=(x0, y0, x1, y1), mask=alpha)
    return image_bg_copy

以上功能支持:

位置(cx, cy) 自动将 image_element 调整为 (w, h) 旋转 image_element 而不裁剪它 水平翻转

【讨论】:

【参考方案8】:

这是我合并 2 个不同大小的图像的代码,每个图像都具有透明度和偏移量:

from PIL import Image

background = Image.open('image1.png')
foreground = Image.open("image2.png")

x = background.size[0]//2
y = background.size[1]//2

background = Image.alpha_composite(
    Image.new("RGBA", background.size),
    background.convert('RGBA')
)

background.paste(
    foreground,
    (x, y),
    foreground
)

background.show()

这个 sn-p 是之前答案的混合,在处理不同大小的图像时混合元素和偏移量,每个图像都有透明度。

【讨论】:

以上是关于php如何合并PNG图片的主要内容,如果未能解决你的问题,请参考以下文章

php 将一张jpeg类型的图片复制到一个png图片上丢失色彩

把有透明区域的png图片和另外一个图片合并成一个,如何在web程序端实现,如php,python等

Imagemagick合并图片批处理

使用 PHP GD 库合并两个 PNG 图像

在 PHP GD 中调整 png 大小时将 jpg 与 png 合并(水印)

在 PHP 中将 2 个或更多 png 图像合并到基本图像上