PIL 将大图像保存为静态

Posted

技术标签:

【中文标题】PIL 将大图像保存为静态【英文标题】:PIL saves large images as static 【发布时间】:2013-06-05 22:32:18 【问题描述】:

我正在使用 PIL(Python 图像库)将数百张 512x512 图像拼接在一起。生成的图像约为 300 MB。它非常适合大约 50 - 150 MB 的结果,但在一些未知的边界之后,它们开始变成巨大的静态。它们如下图所示。

我已尝试确保内存超过 300 MB。我现在有大约 4 GB 的可用空间,但仍然存在这个问题。我认为这是 PIL 的问题。我猜它不应该处理大文件。

请帮忙。

edit: img.show() 实际上显示了图片(在预览中,因为我有一台 Mac)。不过,我认为它在显示时会被压缩,因为我可以通过比较较小的文件来看到压缩情况,并且它说它是一个 .jpeg

【问题讨论】:

300MB 是图像的未压缩大小,还是 PNG 或 JPG 的大小? (跨越 2GB 或 4GB 的错误比跨越 300MB 的错误更有意义……但它也可能类似于跨越 64Kpix 宽度。) 另外,您使用的是哪个版本的 PIL(或 Pillow)?您可能遇到了已经修复的错误…… 最后,您确定这些文件实际上是坏的,而且不仅仅是您用来查看它们的任何东西吗?因为我刚刚创建了一个尺寸为 2Mx60 的 PNG(未压缩超过 300MB,压缩后不到 1MB)并在我的 Mac 上的各种程序中打开它。 Preview 和 Firefox 都会立即给我错误; QuickLook 将其显示为 0x0 图像; Chrome 会旋转 3 分钟,然后显示损坏的图像标签;一个简单的 CoreImage 查看器将其显示为正确的尺寸(或至少非常宽)但纯黑色......没有正确显示它。 LibreOffice Draw 终于打开了它……我有一个非常错误的形状(比宽度高得多……但尺寸声称它是 0 像素高)奇怪的红色条带。 终于找到了可以处理它的东西:ImageMagick。因此,您可以使用它来裁剪最右边的 512x512,然后在另一个程序中查看它,看看它是否真的是静态的,或者只是您的查看器。但是在 PIL 本身中进行测试可能更简单:重新打开巨型文件,裁剪最右边的 512x512,然后保存并查看它,或者只是 getpixel 并检查值...... 【参考方案1】:

很可能您的实际问题不在于 PIL,而在于您用于显示图像的任何内容。

您的问题也可能出在 PIL 上,它已由 Pillow 2.0 修复,或者它只发生在 32 位或其他任何情况下,但我无法重现它。

无论如何,这是我从一堆 512x60 PNG 副本中生成 2Mx60 PNG 文件的代码,该文件未压缩超过 300MB(但压缩后小于 1MB):

>>> src = PIL.Image.open('strip-512x60.png')
>>> dst = PIL.Image.new('RGBA', (4096*512, 60))
>>> for i in range(4096):
...    dst.paste(src, (4096*i, 0))
>>> dst.save('strip-3Mx60.png')

我检查了文件;它有一个有效的 PNG 块结构和 IHDR 中的所有正确信息。

我可以在PIL中重新打开,像素明显有效:

>>> dst = PIL.Image.open('strip-3Mx60.png')
>>> src.getpixel((0, 30))
(115, 67, 19)
>>> dst.getpixel((0, 30))
(115, 67, 19)
>>> dst.getpixel((4000*512, 30))
(115, 67, 19)

ImageMagick 的命令行工具也可以很好地读取文件;将倒数第二个 512x512 裁剪成一个新文件并打开它给了我原始图像(或者至少足够接近以通过快速目视检查的图像)。

但是,我尝试打开它的几乎所有其他程序或高级库都失败了,或者给了我垃圾:

QuickLook 系统日志“ImageIO: PNG Invalid IHDR Data”然后返回 0x0 图像。 一个简单的 CoreImage 测试程序 syslog 显示“ImageIO: PNG Invalid IHDR Data”然后返回一个纯黑色图像,我猜这是默认大小(大约 600x600)。 预览版出现有关无效文件类型的错误。 Firefox 给出关于无效图像内容的错误。 Chrome 和 Safari 显示损坏的图像标签。这需要几分钟。 LibreOffice Draw 为我提供了一个类似于 600x64K 的图像,由红色、白色和黑色的奇异条纹组成。它比 WebKit 需要更长的时间。 一个简单的 .NET 图像查看器(在 Mono 中运行)会吐出大量错误,然后显示传统的模拟电视风格的静态图像。它需要的时间甚至比 LibreOffice 还要长。

据推测,Apple 的库(WebKit 除外)和 Gecko 只是在进行某种健全性检查,并确定任何声称为 2M 像素宽的 IHDR 都是无效的,而其他一切都试图解释图像,然后溢出一些内部在中止之前缓冲,或者没有注意到并且只是返回垃圾。

【讨论】:

哈哈哈。我没有提到的另一件事是 img.show() 显示图像。我猜是因为它也压缩了一点。您可以在较小的图像中看到压缩(它变成了 .jpeg)。告诉我,如果你找到任何打开它的方法,我猜。 @wufufufu:嗯,这给了你一个简单的测试,以确保它实际上是Image.save 的罪魁祸首:保存图像,重新打开它,然后显示它。【参考方案2】:

只需在 Windows 上运行相同的代码。有效。实际图像在 Mac 上由 Python 保存时已损坏,我很确定。

我在 Windows 和 Mac

上运行 Python 2.5 和 PIL 1.1.7

【讨论】:

以上是关于PIL 将大图像保存为静态的主要内容,如果未能解决你的问题,请参考以下文章

在大图像上保存形状

保存时使用 Python PIL“质量”参数时,PNG 文件大小是不是应该保持静态?

如何将 Matplotlib 图形转换为 PIL Image 对象(不保存图像)

将 Numpy 数组保存为图像

如何使用 Python PIL 将图像保存到特定目录?

Python - 尝试使用 PIL 的 Image.fromarray 保存 numpy 数组时出现 TypeError