Как записать изображение PNG в строку с помощью PIL?

100

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

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

maxp
источник

Ответы:

195

Вы можете использовать этот 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вместо него.

что-то
источник
1
Да! Это именно то, что я искал. Я погуглил каждую комбинацию python, string, reader, writer, buffer и ничего не нашел. Спасибо!
rik.the.vik 07
2
У меня не работает :( Я получил KeyError в строке 1423 Imaging / PIL / Image.pyc -> raise KeyError (ext) # unknown extension
Radian
6
@Radian, Документация PIL по методу save () гласит: You can use a file object instead of a filename. In this case, you must always specify the format.Итак, если первый аргумент является файловым объектом, вы должны передать второй аргумент, который является форматом (например 'PNG').
Су Чжан
1
В текущей версии Python StringIO находится в пакете io, вы должны написать:from io import StringIO
Spoutnik16
4
Вы можете лучше использоватьimage.save(output, format=image.format)
reetesh11
29

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

Решение 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()
Радиан
источник
14

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

buf = StringIO.StringIO()
im.save(buf, format='JPEG')
jpeg = buf.getvalue()
бобинс
источник
Спасибо. StringIO - вот что мне нужно.
maxp
Интерфейс save () намного чище, чем интерфейс tostring (), когда дело доходит до получения PNG, JPEG или фактического формата файла.
Kekoa
13

С современными (по состоянию на середину 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.save(faux_file, 'png')
могучая куча
источник
2
какова цель image_data = faux_file.getvalue ()?
Райан
@ Райан Хороший улов, без всякой цели. Он остался после тестирования и окончательно удален.
mightypile
9

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

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

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

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

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

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

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

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

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

С.Лотт
источник
2
Похоже, он хочет сохранить формат PNG, а не сводить его к необработанным пиксельным данным.
Бен Бланк,