web-dev-qa-db-fra.com

Python PIL: comment écrire une image PNG dans une chaîne

J'ai généré une image en utilisant PIL . Comment puis-je l'enregistrer dans une chaîne en mémoire? La méthode Image.save() nécessite un fichier.

Je voudrais avoir plusieurs de ces images stockées dans un dictionnaire.

87
maxp

Vous pouvez utiliser la classe BytesIO pour obtenir un wrapper autour de chaînes qui se comportent comme un fichier. L'objet BytesIO fournit la même interface qu'un fichier, mais enregistre le contenu juste en mémoire:

import io

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

Vous devez spécifier explicitement le format de sortie avec le paramètre format, sinon PIL générera une erreur en essayant de le détecter automatiquement.

Si vous avez chargé l'image à partir d'un fichier, le paramètre format contient le format de fichier d'origine. Dans ce cas, vous pouvez utiliser format=image.format.

Dans les anciennes Python 2 versions avant l'introduction du module io, vous auriez utilisé le module StringIO .

178
sth

Pour Python3, il est nécessaire d’utiliser 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')

En savoir plus: http://fadeit.dk/blog/post/python3-flask-pil-in-memory-image

26
ozooner

la solution de qn n'a pas fonctionné pour moi
parce que dans ...

Imaging/PIL/Image.pyc line 1423 -> augmenter KeyError (ext) # extension inconnue

Il essayait de détecter le format de l'extension dans le nom du fichier, ce qui n'existe pas dans le cas StringIO

Vous pouvez ignorer la détection du format en définissant vous-même le format dans un paramètre.

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

save () peut prendre un objet de type fichier ainsi qu'un chemin, vous pouvez donc utiliser un tampon en mémoire comme un StringIO:

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

Avec moderne (à partir de mi-2017 Python 3.5 et Pillow 4.0):

StringIO ne semble plus fonctionner comme avant. La classe BytesIO est le moyen approprié de gérer cela. La fonction save de Pillow attend une chaîne comme premier argument et, étonnamment, ne voit pas StringIO en tant que tel. Ce qui suit est similaire aux anciennes solutions StringIO, mais avec BytesIO à la place.

from io import BytesIO
from PIL import Image

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

Lorsque vous dites "j'aimerais avoir le nombre d'images de ce type stockées dans un dictionnaire", il n'est pas clair s'il s'agit d'une structure en mémoire ou non.

Vous n'avez pas besoin de faire cela pour atténuer une image en mémoire. Il suffit de garder l’objet image dans votre dictionnaire.

Si vous voulez écrire votre dictionnaire dans un fichier, vous voudrez peut-être regarder la méthode im.tostring() et la fonction Image.fromstring()

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

im.tostring () => chaîne

Retourne une chaîne contenant des données de pixels, en utilisant l'encodeur standard "brut".

Image.fromstring (mode, taille, données) => image

Crée une mémoire d'images à partir de données de pixels d'une chaîne, à l'aide du décodeur "brut" standard.

Le "format" (.jpeg, .png, etc.) n’a d’importance que sur le disque lorsque vous échangez des fichiers. Si vous n'échangez pas de fichiers, le format n'a pas d'importance.

8
S.Lott