Як написати зображення PNG до рядка з PIL?


100

Я створив зображення за допомогою PIL . Як я можу зберегти його до рядка в пам'яті? Image.save()Метод вимагає файл.

Я хотів би, щоб у словнику було збережено кілька таких зображень.

Відповіді:


194

Ви можете використовувати 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
Так! Це саме те, що я шукав. Я гуглив кожну комбінацію пітона, рядка, читача, автора, буфера і нічого не придумав. Дякую!
rik.the.vik

2
Не працює для мене :( я отримав цей KeyError в Imaging / PIL / Image.pyc рядок 1423 -> підвищити KeyError (ext) # невідоме розширення
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


24

рішення для мене не спрацювало,
тому що в ...

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 або фактичного формату файлу.
Кекоа

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 ()?
Райан

@Ryan Добрий лов, взагалі ніякої мети. Він був залишений від тестування та остаточно вилучений.
могучий

9

Коли ви говорите "Я хотів би, щоб кількість таких зображень зберігалася у словнику", не ясно, чи це структура пам'яті чи ні.

Вам не потрібно нічого з цього робити, щоб пом'якшити зображення в пам'яті. Просто зберігайте imageоб’єкт у своєму словнику.

Якщо ви збираєтеся написати свій словник у файл, можливо, ви захочете переглянути im.tostring()спосіб та Image.fromstring()функцію

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

im.tostring () => рядок

Повертає рядок, що містить дані пікселів, використовуючи стандартний "необроблений" кодер.

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

Створює пам'ять зображення з піксельних даних у рядку, використовуючи стандартний "необроблений" декодер.

"Формат" (.jpeg, .png тощо) має значення на диску лише під час обміну файлами. Якщо ви не обмінюєтесь файлами, формат не має значення.


2
Це здається, що він хоче зберегти формат PNG, а не зводити його до необроблених даних пікселів.
Бен Бланк
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.