如何使用Python中的PIL将一张图片合成到另一张图片上?

115

我需要将一张图片放置在新生成的白色背景上,以便将其转换为可下载的桌面壁纸。因此,该过程如下:

  1. 生成新的全白色图像,尺寸为1440x900
  2. 将现有图像居中放置在上方
  3. 保存为单个图像

在PIL中,我看到了ImageDraw对象,但没有任何指示表明它可以将现有图像数据绘制到另一个图像上。有什么建议或链接可以推荐吗?


请注意,Pillow 中 Image.blend、paste、composite 和 alpha_composite 的区别,请参考以下链接:[https://dev59.com/JXUOtIcB2Jgan1znqwm1] - Simba
6个回答

189

使用Image实例的paste方法可以实现此操作:

from PIL import Image
img = Image.open('/path/to/file', 'r')
img_w, img_h = img.size
background = Image.new('RGBA', (1440, 900), (255, 255, 255, 255))
bg_w, bg_h = background.size
offset = ((bg_w - img_w) // 2, (bg_h - img_h) // 2)
background.paste(img, offset)
background.save('out.png')

您可以在Nadia Alramli的PIL教程上学习这个以及许多其他的PIL技巧。


1
根据你的模块/系统/版本,你可能需要导入以下内容: from PIL import Image - Nuno Aniceto
3
谢谢 @NunoAniceto,我已经将代码更改为 from PIL import Image,以使其更加兼容Pillow - unutbu
如果您正在使用Python 3.x,可以查看https://dev59.com/JHTYa4cB1Zd3GeqPsDYB#17530159来解决“offset”元组整数错误。 - LucSpan

9

根据unutbus的答案:

#!/usr/bin/env python

from PIL import Image
import math


def resize_canvas(old_image_path="314.jpg", new_image_path="save.jpg",
                  canvas_width=500, canvas_height=500):
    """
    Place one image on another image.

    Resize the canvas of old_image_path and store the new image in
    new_image_path. Center the image on the new canvas.
    """
    im = Image.open(old_image_path)
    old_width, old_height = im.size

    # Center the image
    x1 = int(math.floor((canvas_width - old_width) / 2))
    y1 = int(math.floor((canvas_height - old_height) / 2))

    mode = im.mode
    if len(mode) == 1:  # L, 1
        new_background = (255)
    if len(mode) == 3:  # RGB
        new_background = (255, 255, 255)
    if len(mode) == 4:  # RGBA, CMYK
        new_background = (255, 255, 255, 255)

    newImage = Image.new(mode, (canvas_width, canvas_height), new_background)
    newImage.paste(im, (x1, y1, x1 + old_width, y1 + old_height))
    newImage.save(new_image_path)

resize_canvas()

请记住使用Pillow (文档, GitHub, PyPI)代替python-imaging,因为Pillow可以使用于Python 2.X和Python 3.X。


5

这是要做类似某事的事情

我开始时在Photoshop中生成了“白色背景”,并将其导出为PNG文件。这就是我得到的im1(图像1)。然后使用粘贴功能,因为它更容易。

from PIL import Image

im1 = Image.open('image/path/1.png')
im2 = Image.open('image/path/2.png')
area = (40, 1345, 551, 1625)  
im1.paste(im2, area)
                   l>(511+40) l>(280+1345)
         |    l> From 0 (move, 1345px down) 
          -> From 0 (top left, move 40 pixels right)

这些数字是从哪里来的呢? (40, 1345, 551, 1625) im2的尺寸 (511, 280) 因为我向右添加了40个像素,向下添加了1345个像素(40, 1345, 511, 280),所以我必须将它们加到原始图像的尺寸上,即(40, 1345, 551, 1625)。

im1.show() 

展示你的新形象

0

Image.blend()?[link]

或者,更好的选择是使用Image.paste(),同样的链接。


通过使用恒定的 alpha 在给定的图像之间进行插值,创建一个新的图像。两个图像必须具有相同的大小和模式。从文档中可以看出,它们不能是不同的尺寸。 - Sebastian
我也注意到了Image.paste(),最终这是解决方案。 - Felix
2
链接已过期。 - Phani Rithvij

0
或许有点晚了,但对于这样的图像操作,我们在模型中使用{{link1:ImageSpecField}}来处理原始图像。

0

尝试下面的代码

from PIL import Image

# Load the existing image
existing_image = Image.open("existing_image.png")

# Create a new white image with 1440x900 dimensions
new_image = Image.new("RGB", (1440, 900), (255, 255, 255))

# Calculate the center position for the existing image
x = (new_image.width - existing_image.width) // 2
y = (new_image.height - existing_image.height) // 2

# Paste the existing image onto the new white image at the center position
new_image.paste(existing_image, (x, y))

# Save the new image as a PNG file
new_image.save("new_wallpaper.png")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接