使用Python图像库创建超大图像
我正在尝试通过拼接很多小图片来创建一张非常大的图片(25000x25000)。但是当我用这么大的尺寸调用Image.new()时,Python就会因为内存不够而报错,显示MemoryError。
有没有办法可以逐步写出这样一张图片,而不需要把整个图片都放在内存里呢?
编辑:使用ImageMagick的montage
命令,似乎可以创建任意大小的图片。看起来它并不是把最终的图片加载到内存中(在这个过程中使用的内存非常少),而是直接把它写到硬盘上,这样的做法非常理想。
6 个回答
2
这其实就是理解二进制文件格式的问题。压缩格式会更复杂一些。
假设你想要一个位图/DIB,这段代码:
#incremental_write_bmp.py
import binascii
data='''
0h -2 -42 4D -"BM" -Magic Number (unsigned integer 66, 77)
2h -4 -46 00 00 00 -70 Bytes -Size of the BMP file
6h -2 -00 00 -Unused -Application Specific
8h -2 -00 00 -Unused -Application Specific
Ah -4 -36 00 00 00 -54 bytes -The offset where the bitmap data (pixels) can be found.
Eh -4 -28 00 00 00 -40 bytes -The number of bytes in the header (from this point).
12h -4 -02 00 00 00 -2 pixels -The width of the bitmap in pixels
16h -4 -02 00 00 00 -2 pixels -The height of the bitmap in pixels
1Ah -2 -01 00 -1 plane -Number of color planes being used.
1Ch -2 -18 00 -24 bits -The number of bits/pixel.
1Eh -4 -00 00 00 00 -0 -BI_RGB, No compression used
22h -4 -10 00 00 00 -16 bytes -The size of the raw BMP data (after this header)
26h -4 -13 0B 00 00 -2,835 pixels/meter -The horizontal resolution of the image
2Ah -4 -13 0B 00 00 -2,835 pixels/meter -The vertical resolution of the image
2Eh -4 -00 00 00 00 -0 colors -Number of colors in the palette
32h -4 -00 00 00 00 -0 important colors -Means all colors are important
36h -3 -00 00 FF -0 0 255 -Red, Pixel (1,0)
39h -3 -FF FF FF -255 255 255 -White, Pixel (1,1)
3Ch -2 -00 00 -0 0 -Padding for 4 byte alignment (Could be a value other than zero)
3Eh -3 -FF 00 00 -255 0 0 -Blue, Pixel (0,0)
41h -3 -00 FF 00 -0 255 0 -Green, Pixel (0,1)
44h -2 -00 00 -0 0 -Padding for 4 byte alignment (Could be a value other than zero)
'''.strip().split('\n')
open('test.bmp','wb')
for l in data:
b = l.split('-')[2].strip()
d = ''.join(b.split())
x = binascii.a2b_hex(d)
# this re-opens the file and appends each iteration
open('test.bmp','ab').write(x)
...会逐步写入一个2x2的位图,具体的例子可以在这里找到。现在只需要设置好头部信息,调整到你想要的大小,然后按照正确的顺序读取(有时候还需要重新读取)你的图块。我用一个非常大的文件试过,没看到Python的内存使用量激增。我猜操作系统可以在不读取整个文件的情况下,直接在文件末尾添加内容。
2
你内存不够用也不奇怪;那张图片在内存中会占用超过2GB的空间,而根据你使用的系统,你的操作系统可能无法给Python分配足够的虚拟内存来运行它,这和你实际的RAM大小无关。
你肯定需要逐步写入数据。如果你使用的是原始格式,可能可以按行处理这些图片,只要它们的尺寸都一样。然后你可以把这些文件合并在一起,否则你就得更小心地处理数据编码了。