Python PIL: comment écrire une image PNG en chaîne
-
22-07-2019 - |
Question
J'ai généré une image à l'aide de PIL . Comment puis-je l'enregistrer dans une chaîne en mémoire?
La méthode Image.save ()
nécessite un fichier.
J'aimerais que plusieurs de ces images soient stockées dans un dictionnaire.
La solution
Vous pouvez utiliser le BytesIO
. une classe pour obtenir un wrapper autour des 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 à l'aide du paramètre format
, sinon PIL générera une erreur lors de la tentative de détection automatique.
Si vous avez chargé l'image à partir d'un fichier, le fichier paramètre format
contenant le format de fichier d'origine. Dans ce cas, vous pouvez utiliser format = image.format
.
Dans les anciennes versions de Python 2, avant l'introduction du module io
, vous auriez utilisé le StringIO
à la place.
Autres conseils
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
sth n'a pas fonctionné pour moi
parce que dans ...
Imaging / PIL / Image.pyc, ligne 1423 - > soulève KeyError (ext) # inconnu extension
Il essayait de détecter le format à partir 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()
save () peut prendre un objet de type fichier ainsi qu'un chemin d'accès. Vous pouvez donc utiliser un tampon en mémoire tel qu'un StringIO:
buf= StringIO.StringIO()
im.save(buf, format= 'JPEG')
jpeg= buf.getvalue()
Avec les versions modernes (à compter de la 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')
Lorsque vous dites "j'aimerais avoir le nombre d'images de ce type dans le 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 envisagez d'écrire votre dictionnaire dans un fichier, consultez 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 pixels données, en utilisant la norme " raw " encodeur.
Image.fromstring (mode, taille, données) = > image
Crée une mémoire d'images à partir de pixels données dans une chaîne, en utilisant le standard " raw " décodeur.
Le " format " (.jpeg, .png, etc.) ne compte que sur le disque lorsque vous échangez des fichiers. Si vous n'échangez pas de fichiers, le format n'a pas d'importance.