Come scrivere un'immagine PNG in stringa con il PIL?


100

Ho generato un'immagine utilizzando PIL . Come posso salvarlo in una stringa in memoria? Il Image.save()metodo richiede un file.

Mi piacerebbe avere molte di queste immagini memorizzate nel dizionario.

Risposte:


194

Puoi usare la BytesIOclasse per ottenere un wrapper attorno alle stringhe che si comporta come un file. L' BytesIOoggetto fornisce la stessa interfaccia di un file, ma salva il contenuto solo in memoria:

import io

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

Devi specificare esplicitamente il formato di output con il formatparametro, altrimenti PIL solleverà un errore quando tenterà di rilevarlo automaticamente.

Se hai caricato l'immagine da un file, ha un formatparametro che contiene il formato del file originale, quindi in questo caso puoi usare format=image.format.

Nelle vecchie versioni di Python 2 prima dell'introduzione del iomodulo avresti invece usato il StringIOmodulo.


1
Sì! Questo e 'esattamente quello che stavo cercando. Ho cercato su Google ogni combinazione di python, stringa, lettore, scrittore, buffer e non ho trovato nulla. Grazie!
rik.the.vik

2
Non funziona per me :( Ho ricevuto questo KeyError in Imaging / PIL / Image.pyc riga 1423 -> raise KeyError (ext) # unknown extension
Radian

6
@Radian, La documentazione PIL sul metodo save () dice: You can use a file object instead of a filename. In this case, you must always specify the format.Quindi se il primo argomento è un oggetto file, devi passare il secondo argomento, che è il formato (ad esempio 'PNG').
Su Zhang

1
Nella versione corrente di Python, StringIO è nel pacchetto io, devi scrivere:from io import StringIO
Spoutnik16

4
puoi usare meglioimage.save(output, format=image.format)
reetesh11


24

la soluzione di sth non ha funzionato per me
perché in ...

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

Stava cercando di rilevare il formato dall'estensione nel nome del file, che non esiste nel caso StringIO

È possibile bypassare il rilevamento del formato impostando il formato personalmente in un parametro

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

14

save()può prendere un oggetto simile a un file così come un percorso, quindi puoi usare un buffer in memoria come un StringIO:

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

Grazie. StringIO - questo è ciò di cui ho bisogno.
maxp

L'interfaccia save () è molto più pulita dell'interfaccia tostring () quando si tratta di ottenere un formato di file PNG, JPEG o effettivo.
Kekoa

13

Con Modern (a partire dalla metà del 2017 Python 3.5 e Pillow 4.0):

StringIO non sembra più funzionare come una volta. La classe BytesIO è il modo corretto per gestire questo. La funzione di salvataggio di Pillow si aspetta una stringa come primo argomento e sorprendentemente non vede StringIO come tale. Quanto segue è simile alle vecchie soluzioni StringIO, ma con BytesIO al suo posto.

from io import BytesIO
from PIL import Image

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

2
qual è lo scopo di, image_data = faux_file.getvalue ()?
Ryan

@ Ryan Buona cattura, per niente. Era rimasto dai test e infine rimosso.
mightypile

9

Quando dici "Mi piacerebbe avere il numero di tali immagini memorizzate nel dizionario", non è chiaro se si tratta di una struttura in memoria o meno.

Non è necessario fare nulla di tutto questo per umiliare un'immagine nella memoria. Tieni l' imageoggetto nel tuo dizionario.

Se hai intenzione di scrivere il tuo dizionario su un file, potresti voler guardare il im.tostring()metodo e la Image.fromstring()funzione

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

im.tostring () => stringa

Restituisce una stringa contenente dati pixel, utilizzando il codificatore "grezzo" standard.

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

Crea una memoria immagine dai dati dei pixel in una stringa, utilizzando il decodificatore "grezzo" standard.

Il "formato" (.jpeg, .png, ecc.) Conta solo sul disco quando si scambiano i file. Se non stai scambiando file, il formato non ha importanza.


2
Sembra che voglia mantenere il formato PNG, non ridurlo a dati pixel grezzi.
Ben Blank
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.