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

2025-02-18 09:24:00
admin
原创
32
摘要:问题描述:我有一张透明的 png 图像foo.png,并且使用以下命令打开了另一张图像:im = Image.open("foo2.png") 现在我需要的是foo.png与合并foo2.png。(foo.png包含一些文本,我想打印该文本foo2.png)解决方案 1:from PIL ...

问题描述:

我有一张透明的 png 图像foo.png,并且使用以下命令打开了另一张图像:

im = Image.open("foo2.png")

现在我需要的是foo.png与合并foo2.png

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


解决方案 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 通道将用作蒙版。

检查文档。

解决方案 2:

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

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 通道,那么您可以使用常规粘贴方法(应该更快)。

解决方案 3:

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

请考虑以下情形:

两张测试图像均包含 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 部分完全取自第二层。像素未正确混合):

在此处输入图片描述

Image.alpha_composite使用如下方法合成图像​​:

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

产生以下(正确)图像:

在此处输入图片描述

解决方案 4:

也可以使用混合:

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

解决方案 5:

下面是合并两张不同大小图像的代码,每张图像都有透明度和偏移量:

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

此代码片段是前面答案的混合,将元素与偏移混合,同时处理具有不同尺寸且每个具有透明度的图像。

解决方案 6:

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

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

解决方案 7:

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

解决方案 8:

关键代码是:

_, _, _, 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)

  • 自动调整图像元素的大小为 (w, h)

  • 旋转 image_element 但不进行裁剪

  • 水平翻转

解决方案 9:

这是所有当前答案的综合,也是一个可立即使用的代码。

主要答案实际上不起作用,如另一个答案的示例所示:混合方法不正确并且没有产生良好的结果。

正如在另一个答案中所解释的,关键是使用Image.alpha_composite,但这并不直接允许我们为粘贴的图层设置(x,y)偏移量。

以下是可立即使用的代码:

from PIL import Image

def paste(dest, src, pos):
    new_layer = Image.new("RGBA", dest.size)
    new_layer.paste(src, pos)
    return Image.alpha_composite(dest, new_layer)

layer1 = Image.open("layer1.png").convert("RGBA")
layer2 = Image.open("layer2.png").convert("RGBA")   # smaller image, to be pasted 
                                                    # at position (123, 123)

# layer1.paste(layer2, (123, 123))             # not good
# layer1.save("out1.png")

# layer1.paste(layer2, (123, 123), layer2)     # not good either 
# layer1.save("out2.png")                      # (from accepted answer)

out = paste(layer1, layer2, (123, 123))        # works
out.save("out3.png")
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1325  
  IPD(Integrated Product Development)流程作为一种先进的产品开发管理模式,在众多企业中得到了广泛应用。它涵盖了从产品概念产生到产品退市的整个生命周期,通过整合跨部门团队、优化流程等方式,显著提升产品开发的效率和质量,进而为项目的成功奠定坚实基础。深入探究IPD流程的五个阶段与项目成功之间...
IPD流程分为几个阶段   4  
  华为作为全球知名的科技企业,其成功背后的管理体系备受关注。IPD(集成产品开发)流程作为华为核心的产品开发管理模式,其中的创新管理与实践更是蕴含着丰富的经验和深刻的智慧,对众多企业具有重要的借鉴意义。IPD流程的核心架构IPD流程旨在打破部门墙,实现跨部门的高效协作,将产品开发视为一个整体的流程。它涵盖了从市场需求分析...
华为IPD是什么   3  
  IPD(Integrated Product Development)研发管理体系作为一种先进的产品开发模式,在众多企业的发展历程中发挥了至关重要的作用。它不仅仅是一套流程,更是一种理念,一种能够全方位提升企业竞争力,推动企业持续发展的有效工具。深入探究IPD研发管理体系如何助力企业持续发展,对于众多渴望在市场中立足并...
IPD管理流程   3  
  IPD(Integrated Product Development)流程管理旨在通过整合产品开发流程、团队和资源,实现产品的快速、高质量交付。在这一过程中,有效降低成本是企业提升竞争力的关键。通过优化IPD流程管理中的各个环节,可以在不牺牲产品质量和性能的前提下,实现成本的显著降低,为企业创造更大的价值。优化产品规划...
IPD流程分为几个阶段   4  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用