Bagaimana cara menulis gambar PNG ke string dengan PIL?

100

Saya telah membuat gambar menggunakan PIL . Bagaimana cara menyimpannya ke string di memori? The Image.save()Metode membutuhkan sebuah file.

Saya ingin menyimpan beberapa gambar seperti itu di kamus.

maks
sumber

Jawaban:

194

Anda bisa menggunakan BytesIOkelas untuk mendapatkan pembungkus di sekitar string yang berperilaku seperti file. The BytesIOobjek menyediakan antarmuka yang sama sebagai file, tapi menghemat isi hanya dalam memori:

import io

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

Anda harus secara eksplisit menentukan format keluaran dengan formatparameter, jika tidak PIL akan memunculkan kesalahan saat mencoba mendeteksinya secara otomatis.

Jika Anda memuat gambar dari sebuah file, ia memiliki formatparameter yang berisi format file asli, jadi dalam hal ini Anda dapat menggunakan format=image.format.

Dalam versi Python 2 lama sebelum pengenalan iomodul, Anda akan menggunakan StringIOmodul sebagai gantinya.

sth
sumber
1
Iya! Inilah yang saya cari. Saya mencari di Google setiap kombinasi python, string, reader, writer, buffer dan tidak menemukan apa pun. Terima kasih!
rik.the.vik
2
Tidak berfungsi untuk saya :( Saya mendapatkan KeyError ini di baris Imaging / PIL / Image.pyc 1423 -> naikkan KeyError (ext) # ekstensi tidak dikenal
Radian
6
@Radian, Dokumentasi PIL pada metode save () mengatakan: You can use a file object instead of a filename. In this case, you must always specify the format.Jadi jika argumen pertama adalah objek file, Anda harus meneruskan argumen kedua, yang merupakan formatnya (misalnya 'PNG').
Su Zhang
1
Dalam versi Python saat ini, StringIO ada dalam paket io, Anda harus menulis:from io import StringIO
Spoutnik16
4
Anda dapat menggunakan lebih baikimage.save(output, format=image.format)
reetesh11
29

Untuk Python3, diperlukan penggunaan 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')

Baca lebih lanjut: http://fadeit.dk/blog/post/python3-flask-pil-in-memory-image

ozooner
sumber
24

solusi sth tidak berhasil untuk saya
karena di ...

Imaging / PIL / Image.pyc baris 1423 -> naikkan KeyError (ext) # ekstensi tidak dikenal

Itu mencoba mendeteksi format dari ekstensi di nama file, yang tidak ada dalam kasus StringIO

Anda dapat melewati deteksi format dengan mengatur format sendiri dalam parameter

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

save()dapat mengambil objek seperti file serta jalur, sehingga Anda dapat menggunakan buffer dalam memori seperti StringIO:

buf = StringIO.StringIO()
im.save(buf, format='JPEG')
jpeg = buf.getvalue()
bobince
sumber
Terima kasih. StringIO - itulah yang saya butuhkan.
maks.
Antarmuka save () jauh lebih bersih daripada antarmuka tostring () dalam hal mendapatkan format file PNG, JPEG, atau sebenarnya.
Kekoa
13

Dengan modern (mulai pertengahan 2017 Python 3.5 dan Pillow 4.0):

StringIO sepertinya tidak lagi berfungsi seperti dulu. Kelas BytesIO adalah cara yang tepat untuk menangani ini. Fungsi penyimpanan Pillow mengharapkan string sebagai argumen pertama, dan secara mengejutkan tidak melihat StringIO seperti itu. Berikut ini adalah serupa dengan solusi StringIO yang lebih lama, tetapi dengan BytesIO sebagai gantinya.

from io import BytesIO
from PIL import Image

image = Image.open("a_file.png")
faux_file = BytesIO()
image.save(faux_file, 'png')
mayypile
sumber
2
apa tujuan dari, image_data = faux_file.getvalue ()?
Ryan
@ Ryan Tangkapan bagus, tidak ada tujuan sama sekali. Itu tersisa dari pengujian dan akhirnya dihapus.
mightypile
9

Saat Anda mengatakan "Saya ingin menyimpan sejumlah gambar seperti itu di kamus", tidak jelas apakah ini adalah struktur dalam memori atau bukan.

Anda tidak perlu melakukan semua ini untuk melemahkan gambar dalam memori. Simpan saja imageobjek tersebut di kamus Anda.

Jika Anda akan menulis kamus Anda ke sebuah file, Anda mungkin ingin melihat im.tostring()metode dan Image.fromstring()fungsinya

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

im.tostring () => string

Menampilkan string yang berisi data piksel, menggunakan pembuat enkode "mentah" standar.

Image.fromstring (mode, size, data) => image

Membuat memori gambar dari data piksel dalam sebuah string, menggunakan dekoder "mentah" standar.

"Format" (.jpeg, .png, dll.) Hanya penting pada disk saat Anda menukar file. Jika Anda tidak bertukar file, format tidak masalah.

S. Lott
sumber
2
Sepertinya dia ingin mempertahankan format PNG, bukan menguranginya menjadi data piksel mentah.
Ben Blank