您遇到了异常,因为您超出了 4GB Tiff 格式限制。
请参阅:What is the maximum size of TIFF metadata?。
您可以使用BigTIFF 格式。
您可以尝试使用Tifffile 来编写 BigTIFF 图像文件。
我更喜欢使用 JPEG 2000 图像格式。
我发现了this 的帖子,关于用枕头保存 JPEG 2000。
我知道的方法是使用 OpenCV 保存 JPEG 2000。
OpenCV 以 无损 格式保存 JP2 图像(与 Tiff 无损的方式相同)。
使用 OpenCV 保存的问题:
- 我们需要将枕头图像转换为 NumPy 数组。
- 我们需要从 RGB 转换为 BGR 颜色格式。
这是您的代码的修改版本,它使用 OpenCV 保存 JP2:
import sys
import PIL
from PIL import Image
import cv2
import numpy as np
PIL.Image.MAX_IMAGE_PIXELS = 9331200000
ListeImage=['test1.tif','test2.tif','test3.tif','test4.tif','test5.tif','test6.tif','test7.tif','test8.tif']
images = [Image.open(x) for x in ListeImage]
widths, heights = zip(*(i.size for i in images))
#total_width = sum(widths)
#max_height = max(heights)
#new_im = Image.new('RGB', (total_width, max_height))
new_im = Image.new('RGB', (max(widths), sum(heights)))
y_offset = 0
for im in images:
new_im.paste(im, (0,y_offset))
y_offset += im.size[1] #im.size[0]
# new_im.save('TOTAL'+str(y_offset)+'.tif')
cv2.imwrite('TOTAL'+str(y_offset)+'.jp2', cv2.cvtColor(np.array(new_im), cv2.COLOR_RGB2BGR))
注意事项:
- 您似乎在混合宽度和高度 - 我试图修复它。
- 我的系统中没有足够的 RAM 来测试具有如此大图像的代码 - 我使用较小的图像对其进行了测试。
- 我使用 Python 3.6 测试了代码,不知道它是否适用于 Python 2.7
- 我在没有中间变量的情况下实现了代码,希望它消耗更少的 RAM。
更新:
上述解决方案消耗了太多 RAM(超过 100GB)。
使用大页面文件(磁盘空间作为虚拟内存)可以,但是太慢了。
该解决方案(另存为 JPEG 2000)对于大多数系统来说并不实用。
以下解决方案使用 BigTIFF 格式。
该实现在 RAM 方面也更高效:
import sys
import PIL
from PIL import Image
import tifffile
import numpy as np
import gc
PIL.Image.MAX_IMAGE_PIXELS = 9331200000
ListeImage=['test1.tif','test2.tif','test3.tif','test4.tif','test5.tif','test6.tif','test7.tif','test8.tif']
images = [Image.open(x) for x in ListeImage]
widths, heights = zip(*(i.size for i in images))
# Free memory - release memory of all images.
del images
gc.collect() # Explicitly invoke the Garbage Collector https://stackoverflow.com/questions/1316767/how-can-i-explicitly-free-memory-in-python
#new_im = Image.new('RGB', (max(widths), sum(heights)))
new_im = np.zeros((sum(heights), max(widths), 3), np.uint8) # Use NumPy array instead of pillow image.
y_offset = 0
for x in ListeImage:
im = Image.open(x) # Read one input image at a time (for saving RAM).
#new_im.paste(im, (0,y_offset))
new_im[y_offset:y_offset+im.size[1], :, :] = np.array(im) # Copy im to NumPy array (instead of pasting to pillow image - saves RAM).
y_offset += im.size[1]
tifffile.imwrite('TOTAL'+str(y_offset)+'.tif', new_im, bigtiff=True) # Write new_im as BigTIFF.
del im
gc.collect() # Explicitly invoke the Garbage Collector