Python 图像库:如何将四张图片组合成 2 x 2 的网格?

29

我有四个文件夹,每个文件夹中都有一些图片用于制作动画。我想把这些图片按照2x2的网格排列,并生成一个包含四张图片的单一图片,用于动画的每一帧。

到目前为止,我的代码是:

import Image

fluid64 = "Fluid64_half_size/00"
fluid128 = "Fluid128_half_size/00"
fluid512 = "Fluid512_half_size/00" 
fluid1024 = "Fluid1024_half_size/00" 

out_image = "Fluid_all/00"

for pic in range(1, 26):
    blank_image = Image.open("blank.jpg")

    if pic < 10:
        image_num = "0"+str(pic)
    else:
        image_num = str(pic)

    image64 = Image.open(fluid64+image_num+".jpg")
    image128 = Image.open(fluid128+image_num+".jpg")
    image512 = Image.open(fluid512+image_num+".jpg")
    image1024 = Image.open(fluid1024+image_num+".jpg")
    out = out_image + image_num + ".jpg"

    blank_image.paste(image64, (0,0)).paste(fluid128, (400,0)).paste(fluid512, (0,300)).paste(fluid1024, (400,300)).save(out)

不确定为什么它不起作用。我收到了以下错误:

Traceback (most recent call last):
  File "C:\Users\Casey\Desktop\Image_composite.py", line 24, in <module>
    blank_image.paste(image64, (0,0)).paste(fluid128, (400,0)).paste(fluid512, (
ste(fluid1024, (400,300)).save(out)
AttributeError: 'NoneType' object has no attribute 'paste'
shell returned 1

希望能得到任何帮助。谢谢!

5个回答

42
唯一的问题是 "paste" 不会返回一个图像对象 - 它将直接就地修改“空白”图像。
因此,当第二个 paste 被调用(使用 fuild128 图像的那个),它试图被应用于 “None” - 这是第一个图像的返回值。
如果这是您遇到的唯一问题,只需每行进行一次 paste 调用,如下所示:
blank_image.paste(image64, (0,0))
blank_image.paste(fluid128, (400,0))
blank_image.paste(fluid512, (0,300))
blank_image.paste(fluid1024, (400,300))
blank_image.save(out)
虽然看起来你需要缩放每个图像以使它们的格式匹配。 而且你的“image_num”变量的代码是不必要的。Python在处理字符串方面非常出色 - 只需执行以下操作:
image64 = Image.open(fluid64 + "%02d.jpg" % pic)

12

你可能想要使用类似以下的内容:

blank_image = Image.new("RGB", (800, 600))

这将在内存中创建一个新区域,使您能够生成图像。然后,您就可以将图片粘贴到其中。

随后,您需要使用以下代码将其保存:

blank_image.save("blank.jpg")

1
这并不是代码中的“错误” - 尽管他也会从中受益。 - jsbueno
是的,我后来注意到了实际的“问题”。我查看了跟踪记录,发现 blank_image 没有被正确定义。所以我只是做出了一些假设。毕竟现在已经很晚了 :) - David Hewitt
1
我的使用情况是创建一个具有动态大小的新图像,将段连接到新的空白图像中,因此这非常有帮助。+1 - Clint Powell

4

阅读错误信息:

AttributeError: 'NoneType' object has no attribute 'paste'

这意味着您试图在NoneType类型的对象上调用.paste,即在None对象上调用。

Image.paste返回None。您不能像这样“链接”调用,除非函数专门设计支持它,并且Image.paste不支持。 (通过使函数return self来支持此类事情。如果未显式返回其他内容,则默认情况下Python中的所有内容都会返回None。)这被认为是Pythonic:方法要么返回新值,要么修改self并返回None。因此,所谓的“流畅接口”在函数具有副作用时不使用- Pythonistas认为这是有害的。返回None是函数具有副作用的警告。 :)

只需进行四个单独的.paste调用即可。


2
在一个 2x2 的网格中平铺图形可以通过这个回复中定义的 append_images 函数轻松实现。https://dev59.com/s10a5IYBdhLWcg3whJDW#46623632 例如:
img1 = append_images([image64, image128], direction='horizontal')
img2 = append_images([image512, image1024], direction='horizontal')
final = append_images([img1, img2], direction='vertical')
final.save("Fluid_all/00.jpg")

1
与PIL API的copy、crop、resize或rotate不同,它们返回一个Image对象,而paste返回None,这会阻止链式方法调用。这种API设计并不方便。请参见API

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