Python PIL: как записать изображение PNG в строку - PullRequest
84 голосов
/ 14 марта 2009

Я сгенерировал изображение, используя PIL . Как я могу сохранить его в строку в памяти? Для метода Image.save() требуется файл.

Я бы хотел, чтобы в словаре было несколько таких изображений.

Ответы [ 6 ]

169 голосов
/ 14 марта 2009

Вы можете использовать класс BytesIO, чтобы получить оболочку для строк, которая ведет себя как файл. Объект BytesIO предоставляет тот же интерфейс, что и файл, но сохраняет содержимое только в памяти:

import io

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

Вы должны явно указать формат вывода с параметром format, в противном случае PIL выдаст ошибку при попытке его автоматического определения.

Если вы загрузили изображение из файла, оно имеет параметр format, который содержит исходный формат файла, поэтому в этом случае вы можете использовать format=image.format.

В старых версиях Python 2 до появления модуля io вы бы использовали модуль StringIO.

26 голосов
/ 30 апреля 2015

Для 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

24 голосов
/ 31 марта 2011

STH решение не работает для меня
потому что в ...

Imaging / PIL / Image.pyc строка 1423 -> поднять 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()
13 голосов
/ 14 марта 2009

save () может принимать как файловый объект, так и путь, поэтому вы можете использовать буфер в памяти, такой как StringIO:

buf= StringIO.StringIO()
im.save(buf, format= 'JPEG')
jpeg= buf.getvalue()
10 голосов
/ 23 августа 2017

С современными (по состоянию на середину 2017 года Python 3.5 и Pillow 4.0):

StringIO больше не работает, как раньше. Класс BytesIO - правильный способ справиться с этим. Функция сохранения подушки ожидает строку в качестве первого аргумента и неожиданно не видит StringIO как таковой. Следующее похоже на более старые решения StringIO, но на его месте стоит BytesIO.

from io import BytesIO
from PIL import Image

image = Image.open("a_file.png")
faux_file = BytesIO()
image_data = faux_file.getvalue()
image.save(faux_file, 'png')
8 голосов
/ 14 марта 2009

Когда вы говорите: «Я хотел бы, чтобы количество таких изображений сохранялось в словаре», неясно, является ли это структурой в памяти или нет.

Вам не нужно ничего делать, чтобы смирить изображение в памяти. Просто сохраните объект image в своем словаре.

Если вы собираетесь записать свой словарь в файл, вам может понадобиться метод im.tostring() и функция Image.fromstring()

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

im.tostring () => строка

Возвращает строку, содержащую пиксель данные, используя стандарт «сырой» кодировщик.

Image.fromstring (режим, размер, данные) => изображение

Создает память изображения из пикселя данные в строке, используя стандарт «сырой» декодер.

«Формат» (.jpeg, .png и т. Д.) Имеет значение только на диске, когда вы обмениваетесь файлами. Если вы не обмениваетесь файлами, формат не имеет значения.

...