如何使用 PIL 将 PNG 图像写入字符串?

Posted

技术标签:

【中文标题】如何使用 PIL 将 PNG 图像写入字符串?【英文标题】:How to write PNG image to string with the PIL? 【发布时间】:2010-10-13 09:01:06 【问题描述】:

我使用PIL 生成了一张图片。如何将其保存到内存中的字符串? Image.save() 方法需要一个文件。

我想在字典中存储几张这样的图像。

【问题讨论】:

【参考方案1】:

您可以使用BytesIO 类来获取行为类似于文件的字符串的包装器。 BytesIO 对象提供与文件相同的接口,但只是将内容保存在内存中:

import io

with io.BytesIO() as output:
    image.save(output, format="GIF")
    contents = output.getvalue()

您必须使用format 参数明确指定输出格式,否则PIL 在尝试自动检测时会引发错误。

如果您从一个文件加载图像,它有一个包含原始文件格式的format 参数,因此在这种情况下您可以使用format=image.format

在引入 io 模块之前的旧 Python 2 版本中,您将改用 StringIO 模块。

【讨论】:

是的!这正是我一直在寻找的。我用谷歌搜索了 python、string、reader、writer、buffer 的每一个组合,但没有想出任何东西。谢谢! 对我不起作用 :( 我在 Imaging/PIL/Image.pyc 第 1423 行得到了这个 KeyError -> raise KeyError(ext) # unknown extension @Radian,关于 save() 方法的 PIL 文档说:You can use a file object instead of a filename. In this case, you must always specify the format. 因此,如果第一个参数是文件对象,则必须传入第二个参数,即格式(例如'PNG'). 当前Python版本中,StringIO在io包中,必须写:from io import StringIO 你可以更好地使用image.save(output, format=image.format)【参考方案2】:

当你说“我想在字典中存储一些这样的图像”时,不清楚这是否是内存结构。

您无需执行任何这些操作即可在内存中恢复图像。只需将 image 对象保存在您的字典中即可。

如果您要将字典写入文件,您可能需要查看 im.tostring() 方法和 Image.fromstring() 函数

http://effbot.org/imagingbook/image.htm

im.tostring() => 字符串

返回一个包含像素的字符串 数据,使用标准的“原始” 编码器。

Image.fromstring(模式、大小、数据) => 图片

从像素创建图像内存 字符串中的数据,使用标准 “原始”解码器。

“格式”(.jpeg、.png 等)仅在您交换文件时在磁盘上很重要。如果您不交换文件,格式无关紧要。

【讨论】:

听起来他想保留PNG格式,而不是将其还原为原始像素数据。【参考方案3】:

save() 可以采用类似文件的对象以及路径,因此您可以使用像 StringIO 这样的内存缓冲区:

buf = StringIO.StringIO()
im.save(buf, format='JPEG')
jpeg = buf.getvalue()

【讨论】:

谢谢。 StringIO - 这就是我需要的。 在获取 PNG、JPEG 或实际文件格式时,save() 接口比 tostring() 接口干净得多。【参考方案4】:

某事的解决方案对我不起作用 因为在...

成像/PIL/Image.pyc 第 1423 行 -> raise KeyError(ext) # 未知 扩展

它试图从文件名中的扩展名中检测格式,这在 StringIO 案例中不存在

您可以通过在参数中自己设置格式来绕过格式检测

import StringIO
output = StringIO.StringIO()
format = 'PNG' # or 'JPEG' or whatever you want
image.save(output, format)
contents = output.getvalue()
output.close()

【讨论】:

【参考方案5】:

对于 Python3,需要使用 BytesIO:

from io import BytesIO
from PIL import Image, ImageDraw

image = Image.new("RGB", (300, 50))
draw = ImageDraw.Draw(image)
draw.text((0, 0), "This text is drawn on image")

byte_io = BytesIO()

image.save(byte_io, 'PNG')

阅读更多:http://fadeit.dk/blog/post/python3-flask-pil-in-memory-image

【讨论】:

【参考方案6】:

使用现代(截至 2017 年中期 Python 3.5 和 Pillow 4.0):

StringIO 似乎不再像以前那样工作了。 BytesIO 类是处理这个问题的正确方法。 Pillow 的保存函数需要一个字符串作为第一个参数,但令人惊讶的是,它并没有看到 StringIO 是这样的。以下类似于旧的 StringIO 解决方案,但使用了 BytesIO。

from io import BytesIO
from PIL import Image

image = Image.open("a_file.png")
faux_file = BytesIO()
image.save(faux_file, 'png')

【讨论】:

image_data = faux_file.getvalue() 的目的是什么? @Ryan 很好,完全没有目的。它是从测试中遗留下来的,最后被删除了。

以上是关于如何使用 PIL 将 PNG 图像写入字符串?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 PIL 将透明 png 图像与另一个图像合并

Python - 如何使用Open-cv或PIL将24位PNG图像转换为32位

如何使用 PIL 减小图像文件大小

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

将 Numpy 数组保存为图像

使用 PIL 在另一个图像之上的图像上写入文本