Jak napisać obraz PNG do łańcucha za pomocą PIL?


100

Wygenerowałem obraz za pomocą PIL . Jak mogę zapisać go do ciągu w pamięci? Image.save()Metoda wymaga pliku.

Chciałbym mieć kilka takich obrazków zapisanych w słowniku.

Odpowiedzi:


194

Możesz użyć BytesIOklasy, aby uzyskać opakowanie wokół łańcuchów, które zachowuje się jak plik. BytesIOObiekt zapewnia ten sam interfejs jako plik, ale zapisuje zawartość tylko w pamięci:

import io

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

Musisz wyraźnie określić format wyjściowy za pomocą formatparametru, w przeciwnym razie PIL zgłosi błąd podczas próby automatycznego wykrycia go.

Jeśli wczytałeś obraz z pliku, ma on formatparametr zawierający oryginalny format pliku, więc w tym przypadku możesz użyć format=image.format.

W starszych wersjach Pythona 2 przed wprowadzeniem modułu zamiast iotego używałbyś StringIOmodułu.


1
Tak! To jest dokładnie to, czego szukałem. Wyszukałem w Google każdą kombinację Pythona, stringów, czytnika, pisarza, bufora i niczego nie wymyśliłem. Dzięki!
rik.the.vik

2
Nie działa dla mnie :( Otrzymałem ten KeyError w Imaging / PIL / Image.pyc line 1423 -> podnieś KeyError (ext) # nieznane rozszerzenie
Radian

6
@Radian, Dokumentacja PIL dotycząca metody save () mówi: You can use a file object instead of a filename. In this case, you must always specify the format.Więc jeśli pierwszym argumentem jest obiekt plikowy, musisz przekazać drugi argument, którym jest format (np 'PNG'.).
Su Zhang

1
W obecnej wersji Pythona StringIO jest w pakiecie io, musisz napisać:from io import StringIO
Spoutnik16

4
możesz lepiej wykorzystaćimage.save(output, format=image.format)
reetesh11


24

rozwiązanie czegoś nie zadziałało,
ponieważ w ...

Imaging / PIL / Image.pyc line 1423 -> podnieś KeyError (ext) # nieznane rozszerzenie

Próbował wykryć format z rozszerzenia w nazwie pliku, które nie istnieje w przypadku StringIO

Możesz ominąć wykrywanie formatu, ustawiając format samodzielnie w parametrze

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

14

save()może wziąć obiekt podobny do pliku, jak również ścieżkę, więc możesz użyć bufora w pamięci, takiego jak StringIO:

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

Dziękuję Ci. StringIO - tego potrzebuję.
maxp

Interfejs save () jest znacznie bardziej przejrzysty niż interfejs tostring (), jeśli chodzi o pobieranie formatu PNG, JPEG lub faktycznego formatu pliku.
Kekoa

13

Z nowoczesnym (od połowy 2017 Python 3.5 i Pillow 4.0):

Wygląda na to, że StringIO nie działa już tak, jak kiedyś. Klasa BytesIO jest właściwym sposobem radzenia sobie z tym. Funkcja save Pillow oczekuje łańcucha jako pierwszego argumentu i, co zaskakujące, nie widzi StringIO jako takiego. Poniższe jest podobne do starszych rozwiązań StringIO, ale z BytesIO na swoim miejscu.

from io import BytesIO
from PIL import Image

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

2
jaki jest cel, image_data = faux_file.getvalue ()?
Ryan

@Ryan Dobry chwyt, bez celu. Został po testach i ostatecznie usunięty.
mightypile

9

Kiedy mówisz „Chciałbym mieć pewną liczbę takich obrazów przechowywanych w słowniku”, nie jest jasne, czy jest to struktura w pamięci, czy nie.

Nie musisz tego robić, aby potulny obraz w pamięci. Po prostu zachowaj imageobiekt w swoim słowniku.

Jeśli masz zamiar zapisywać słownik do pliku, możesz przyjrzeć się im.tostring()metodzie i Image.fromstring()funkcji

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

im.tostring () => string

Zwraca ciąg zawierający dane pikseli przy użyciu standardowego kodera „surowego”.

Image.fromstring (tryb, rozmiar, dane) => obraz

Tworzy pamięć obrazu z danych pikseli w ciągu przy użyciu standardowego dekodera „surowego”.

„Format” (.jpeg, .png itp.) Ma znaczenie tylko na dysku podczas wymiany plików. Jeśli nie wymieniasz plików, format nie ma znaczenia.


2
Wygląda na to, że chce zachować format PNG, a nie zredukować go do surowych danych pikseli.
Ben Blank,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.