Python 如何逐补丁写入png/tiff文件?

Python 如何逐补丁写入png/tiff文件?,python,python-imaging-library,pillow,Python,Python Imaging Library,Pillow,我想从一个非常大的h5py数据集创建一个png或tiff图像文件,该数据集不能一次加载到内存中。所以,我想知道python中是否有一种方法可以在补丁中写入png或tiff文件?(我可以将h5py数据集分片加载到numpy.ndarray)。 我尝试过使用枕头库,并使用PIL.Image.paste给出盒子坐标,但对于大图像,它会耗尽内存 基本上,我想知道是否有一种方法可以做到: for y in range(0, height, patch_size): for x in range(0

我想从一个非常大的h5py数据集创建一个png或tiff图像文件,该数据集不能一次加载到内存中。所以,我想知道python中是否有一种方法可以在补丁中写入png或tiff文件?(我可以将h5py数据集分片加载到
numpy.ndarray
)。 我尝试过使用枕头库,并使用
PIL.Image.paste
给出盒子坐标,但对于大图像,它会耗尽内存

基本上,我想知道是否有一种方法可以做到:

for y in range(0, height, patch_size):
    for x in range(0, width, patch_size):
        y2 = min(y + patch_size, height)
        x2 = min(x + patch_size, width)
        # image_arr is an h5py dataset that cannot be loaded completely
        # in memory, so load it in slices
        image_file.write(image_arr[y:y2, x:x2], box=(y, x, y2, x2))
我正在寻找一种方法来做到这一点,而不需要将整个图像加载到内存中。我试过枕头库,但它会将所有数据加载/保存在内存中

编辑:这个问题不是关于h5py,而是关于如何将超大图像(无法加载到内存中)写入修补程序中的文件-类似于如何通过逐行写入来构造大型文本文件。

简短回答“Python中是否有方法在修补程序中写入png或tiff文件?”。是的,只要有足够的时间和技能来实现,Python中的一切都是可能的。另一方面,不,没有现成的解决方案,因为它似乎不是很有用

我不知道TIFF,这里的评论说它限制在4GB,所以这种格式可能不是一个好的候选格式。PNG没有实际的限制,可以分块编写,因此在理论上是可行的——前提是生成的图像中至少有一条扫描线适合内存

如果您真的想继续,以下是您需要的信息: PNG文件由几个元数据块和一系列图像数据块组成。后者相互独立,因此您可以通过简单地将其图像数据块(IDAT)连接在一起并添加所需的元数据块,从几个较小的图像(每个图像包含整行,至少一行)构建一个大图像(您可以从第一个小图像中选择这些图像,IHDR块除外-需要构造该块以包含最终图像大小)

因此,如果有必要,我会这样做(注意,您需要了解Python的
字节
类型以及将字节序列转换为Python数据类型和从Python数据类型转换字节序列的方法,以实现这一点):

  • 找出我可以放入内存的行数,并将其作为“小图像块”的高度。宽度是整个最终图像的宽度。让我们称之为
    width
    small\u height

  • 每次查看一块h5py中的巨型数据集(
    width*small_height
    ),将其转换为PNG并将其保存到临时文件中的磁盘,或者如果图像转换库允许,则直接将其保存到内存中的
    bytes
    字符串中。然后按如下方式处理字节数据并在末尾将其删除:

    --在第一次迭代中:一次遍历一条记录的PNG数据(参见PNG规范:,它是长度标记值形式,并且非常容易编写代码来高效地逐个记录遍历文件),将所有记录保存到我的目标文件中,除了:修改IHDR使其具有最终图像大小并跳过IEND记录

    --在所有后续迭代中:扫描PNG数据并仅拾取IDAT记录,将这些记录写入输出文件

  • 将IEND记录附加到目标文件

全部完成-您现在应该有一个有效的巨大PNG。不过,我想知道谁或什么人可以阅读它。

试试:


这将创建一个带有一个条带的未压缩BigTIFF文件。尚未实现内存映射分片。不确定有多少库可以处理此类文件,但您始终可以使用TIFF标记中的元数据直接从条带读取。

提供存储在TIFF文件中的内存映射numpy数组。但没有压缩或分片。可以你创建了一组单独的相对较小的png/tiff图像,然后将它们合并成一个大图像?投票结束。刺客的可能副本:一个太大而无法放入内存的图像有什么用?不管怎样,我怀疑你可以通过尝试将一组图像组合到这两个压缩的图像中来实现这一点mats.If未压缩(或仅限于直线压缩,如RLE),在组合它们时,只需在任何给定时间打开包含最终图像相同行的行所需的编号,就可以最大限度地减少内存使用。这将允许将最终图像的行连接在一起,而无需一次将所有行都读入内存。我也不认为使用singl有什么意义太大而无法放入内存的图像。您将如何渲染它?对于概念上只有一个大图像的地图之类的东西,实际上它们会被分为块并按需提供服务。如果您的问题不是特定于HDF5,那么它似乎与此重复:@gohlke bigtiff=True在最新版本中似乎不起作用租赁
from tifffile import memmap

image_file = memmap('temp.tif', shape=(height, width), dtype=image_arr.dtype,
                    bigtiff=True)

for y in range(0, height, patch_size):
    for x in range(0, width, patch_size):
        y2 = min(y + patch_size, height)
        x2 = min(x + patch_size, width)
        image_file[y:y2, x:x2] = image_arr[y:y2, x:x2]

image_file.flush()