Wie schreibe ich ein PNG-Bild in einen String mit dem PIL?


99

Ich habe ein Bild mit PIL generiert . Wie kann ich es in einer Zeichenfolge im Speicher speichern? Die Image.save()Methode erfordert eine Datei.

Ich möchte mehrere solcher Bilder im Wörterbuch speichern.

Antworten:


194

Mit der BytesIOKlasse können Sie einen Wrapper um Zeichenfolgen erstellen, der sich wie eine Datei verhält. Das BytesIOObjekt bietet dieselbe Schnittstelle wie eine Datei, speichert den Inhalt jedoch nur im Speicher:

import io

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

Sie müssen das Ausgabeformat explizit mit dem formatParameter angeben , da sonst PIL einen Fehler auslöst, wenn versucht wird, ihn automatisch zu erkennen.

Wenn Sie das Bild aus einer Datei geladen haben format, enthält es einen Parameter, der das ursprüngliche Dateiformat enthält. In diesem Fall können Sie es verwenden format=image.format.

In alten Python 2-Versionen hätten Sie vor der Einführung des Moduls stattdessen iodas StringIOModul verwendet.


1
Ja! Genau das habe ich gesucht. Ich habe jede Kombination aus Python, String, Reader, Writer, Buffer gegoogelt und mir nichts ausgedacht. Vielen Dank!
rik.the.vik

2
Funktioniert bei mir nicht :( Ich habe diesen KeyError in Imaging / PIL / Image.pyc Zeile 1423 -> KeyError (ext) # unbekannte Erweiterung erhöhen
Radian

6
@Radian, In der PIL-Dokumentation zur save () -Methode heißt es: You can use a file object instead of a filename. In this case, you must always specify the format.Wenn das erste Argument ein Dateiobjekt ist, müssen Sie das zweite Argument übergeben, das das Format ist (z 'PNG'. B. ).
Su Zhang

1
In der aktuellen Python-Version befindet sich StringIO im io-Paket. Sie müssen from io import StringIO
Folgendes

4
Sie können besser verwendenimage.save(output, format=image.format)
reetesh11


24

Die Lösung von etw hat bei mir nicht funktioniert,
weil in ...

Imaging / PIL / Image.pyc Zeile 1423 -> KeyError (ext) # unbekannte Erweiterung auslösen

Es wurde versucht, das Format anhand der Erweiterung im Dateinamen zu ermitteln, die im StringIO-Fall nicht vorhanden ist

Sie können die Formaterkennung umgehen, indem Sie das Format selbst in einem Parameter festlegen

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

14

save()Sie können sowohl ein dateiähnliches Objekt als auch einen Pfad verwenden, sodass Sie einen speicherinternen Puffer wie den folgenden verwenden können StringIO:

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

Danke dir. StringIO - das brauche ich.
maxp

Die save () -Schnittstelle ist viel sauberer als die tostring () -Schnittstelle, wenn es darum geht, ein PNG-, JPEG- oder tatsächliches Dateiformat zu erhalten.
Kekoa

13

Mit modern (ab Mitte 2017 Python 3.5 und Pillow 4.0):

StringIO scheint nicht mehr so ​​zu funktionieren wie früher. Die BytesIO-Klasse ist der richtige Weg, um damit umzugehen. Die Speicherfunktion von Pillow erwartet einen String als erstes Argument und sieht StringIO überraschenderweise nicht als solches. Das Folgende ähnelt älteren StringIO-Lösungen, jedoch mit BytesIO an seiner Stelle.

from io import BytesIO
from PIL import Image

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

2
Was ist der Zweck von, image_data = faux_file.getvalue ()?
Ryan

@ Ryan Guter Fang, überhaupt kein Zweck. Es wurde vom Testen übrig gelassen und schließlich entfernt.
mächtiger

9

Wenn Sie sagen "Ich möchte, dass die Anzahl solcher Bilder im Wörterbuch gespeichert wird", ist nicht klar, ob es sich um eine In-Memory-Struktur handelt oder nicht.

Sie müssen nichts davon tun, um ein Bild in Erinnerung zu behalten. Behalten Sie das imageObjekt einfach in Ihrem Wörterbuch.

Wenn Sie Ihr Wörterbuch in eine Datei schreiben möchten, sollten Sie sich die im.tostring()Methode und die Image.fromstring()Funktion ansehen

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

im.tostring () => string

Gibt eine Zeichenfolge zurück, die Pixeldaten enthält, wobei der Standard-Rohcodierer verwendet wird.

Image.fromstring (Modus, Größe, Daten) => Bild

Erstellt einen Bildspeicher aus Pixeldaten in einer Zeichenfolge unter Verwendung des Standarddecoders "roh".

Das "Format" (.jpeg, .png usw.) spielt auf der Festplatte nur eine Rolle, wenn Sie die Dateien austauschen. Wenn Sie keine Dateien austauschen, spielt das Format keine Rolle.


2
Es hört sich so an, als ob er das PNG-Format beibehalten und nicht auf Rohpixeldaten reduzieren möchte.
Ben Blank
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.