Codierung einer Bilddatei mit base64

161

Ich möchte ein Bild mit dem base64-Modul in eine Zeichenfolge codieren. Ich bin jedoch auf ein Problem gestoßen. Wie gebe ich das Bild an, das codiert werden soll? Ich habe versucht, das Verzeichnis für das Image zu verwenden, aber das führt einfach dazu, dass das Verzeichnis codiert wird. Ich möchte, dass die eigentliche Bilddatei verschlüsselt wird.

BEARBEITEN

Ich habe dieses Snippet ausprobiert:

with open("C:\Python26\seriph1.BMP", "rb") as f:
    data12 = f.read()
    UU = data12.encode("base64")
    UUU = base64.b64decode(UU)

    print UUU

    self.image = ImageTk.PhotoImage(Image.open(UUU))

aber ich bekomme folgenden Fehler:

Traceback (most recent call last):
  File "<string>", line 245, in run_nodebug
  File "C:\Python26\GUI1.2.9.py", line 473, in <module>
    app = simpleapp_tk(None)
  File "C:\Python26\GUI1.2.9.py", line 14, in __init__
    self.initialize()
  File "C:\Python26\GUI1.2.9.py", line 431, in initialize
    self.image = ImageTk.PhotoImage(Image.open(UUU))
  File "C:\Python26\lib\site-packages\PIL\Image.py", line 1952, in open
    fp = __builtin__.open(fp, "rb")
TypeError: file() argument 1 must be encoded string without NULL bytes, not str

Was mache ich falsch?

Rechteck
quelle

Antworten:

298

Ich bin mir nicht sicher, ob ich deine Frage verstehe. Ich gehe davon aus, dass Sie etwas in der Art tun:

import base64

with open("yourfile.ext", "rb") as image_file:
    encoded_string = base64.b64encode(image_file.read())

Sie müssen die Datei natürlich zuerst öffnen und ihren Inhalt lesen - Sie können den Pfad nicht einfach an die Codierungsfunktion übergeben.

Bearbeiten: Ok, hier ist ein Update, nachdem Sie Ihre ursprüngliche Frage bearbeitet haben.

Denken Sie zunächst daran, bei der Verwendung von Pfadtrennzeichen unter Windows unformatierte Zeichenfolgen zu verwenden (stellen Sie der Zeichenfolge 'r' voran), um zu verhindern, dass versehentlich ein Escape-Zeichen getroffen wird. Zweitens akzeptiert Image.open von PIL entweder einen Dateinamen oder einen dateiähnlichen Namen (dh das Objekt muss Lese-, Such- und Tell-Methoden bereitstellen).

Davon abgesehen können Sie mit cStringIO ein solches Objekt aus einem Speicherpuffer erstellen:

import cStringIO
import PIL.Image

# assume data contains your decoded image
file_like = cStringIO.StringIO(data)

img = PIL.Image.open(file_like)
img.show()
Jim Brissom
quelle
1
Vielen Dank, ein weiteres Problem beim Drucken des dekodierten Bildes ist die Zeichenfolge 'ÿØÿà'. Wenn ich dies jedoch alleine als Ersatz für Daten ausführe, wird eine Fehlermeldung angezeigt. Die codierte Zeichenfolge ist zum Vergleich viel länger. Ich denke also, dass das wahrscheinlich die Bilddaten speichert. Verweist die decodierte Zeichenfolge einfach auf die codierte Zeichenfolge oder etwas anderes? Es scheint viel zu kurz für die Datenspeicherung.
Rechteck
Die gedruckte Ausgabe entspricht nicht unbedingt dem tatsächlichen Inhalt - es hängt davon ab, wie und wo Sie sie drucken.
Jim Brissom
8
In meinem Fall muss ich dekodieren: base64.b64encode(fh.read()).decode()um eine Zeichenfolge zu erhalten, die in HTML-Dateien verwendet werden soll.
Qed
1
base64.b64encode (fh.read ()). decode () ist subtil, aber ich brauchte das auch @qed, danke. Der Unterschied ist, dass man Bytes und andere Zeichenfolgen zurückgibt ... und mein SOAP-Server würde es einfach nicht schlucken, ohne es zu dekodieren!
Zzart
57

Mit Python 2.x können Sie mit .encode trivial codieren:

with open("path/to/file.png", "rb") as f:
    data = f.read()
    print data.encode("base64")
Ivo van der Wijk
quelle
12

Die erste Antwort gibt eine Zeichenfolge mit dem Präfix b 'aus. Das bedeutet, dass Ihre Zeichenfolge wie folgt aussieht: b'your_string 'Um dieses Problem zu beheben, fügen Sie bitte die folgende Codezeile hinzu.

encoded_string= base64.b64encode(img_file.read())
print(encoded_string.decode('utf-8'))
CodeSpeedy
quelle
2
Dies scheint eine gute Antwort zu sein, aber bitte veröffentlichen Sie nichts, wenn der Zweck darin besteht, Ihre Website zu bewerben. Sie können jedoch gerne Links zu Ihrem Profil hinzufügen.
halfer
1
(Übrigens kann man sich hier nicht auf die Antwortreihenfolge verlassen, daher lohnt es sich, Kommentare wie "die erste Antwort" zu vermeiden. Die erste Antwort kann sich im Laufe der Zeit ändern. :-))
halfer
In Ihrer Originalversion dieser Antwort sieht es so aus, als ob Sie mit Ihrer eigenen Site oder einer Site, mit der Sie verbunden sind, verlinkt sind. Wenn Sie auf eine solche Site verlinken, müssen Sie angeben, dass es sich um Ihre Site handelt . Wenn Sie keine Zugehörigkeit offenlegen, wird dies als Spam betrachtet. Siehe: Was bedeutet "gute" Eigenwerbung? und das Hilfezentrum zur Eigenwerbung . Die Offenlegung muss explizit erfolgen, muss jedoch nicht formal sein. Wenn es Ihr persönlicher Inhalt ist, kann es einfach so etwas wie "auf meiner Website ...", "auf meinem Blog ..." usw. sein
Makyen
Vielen Dank für den Vorschlag @Makyen Ich werde offenlegen, dass es meine Website ist. Ist es legal, die Antwort jetzt zu bearbeiten, um anzugeben, dass es sich um meine Website handelt? Oder ich sollte es nicht bearbeiten.
CodeSpeedy
9

Wie ich in Ihrer vorherigen Frage gesagt habe, muss die Zeichenfolge nicht mit base64 codiert werden, sondern das Programm wird nur langsamer. Verwenden Sie einfach den Repr

>>> with open("images/image.gif", "rb") as fin:
...  image_data=fin.read()
...
>>> with open("image.py","wb") as fout:
...  fout.write("image_data="+repr(image_data))
...

Jetzt wird das Bild als Variable gespeichert, die image_datain einer Datei namens image.py Starten Sie einen neuen Interpreter aufgerufen und importieren Sie die image_data

>>> from image import image_data
>>>
John La Rooy
quelle
Ich sehe nicht wirklich, wie repr () hier von Nutzen sein kann.
Ivo van der Wijk
6
@Ivo, Anteater möchte Bilder in Python-Dateien speichern können. Ich weise darauf hin, dass die Verwendung von base64 kontraproduktiv ist, da die Daten bei jedem Laden des Moduls dekodiert werden müssen. Die Verwendung von repr bedeutet stattdessen, dass die Literalzeichenfolge zur weiteren Verwendung in der .pyc-Datei ohne weitere Verarbeitung gespeichert wird
John La Rooy
7

In Anlehnung an das, was Ivo van der Wijk und Gnibbler zuvor entwickelt haben, ist dies eine dynamische Lösung

import cStringIO
import PIL.Image

image_data = None

def imagetopy(image, output_file):
    with open(image, 'rb') as fin:
        image_data = fin.read()

    with open(output_file, 'w') as fout:
        fout.write('image_data = '+ repr(image_data))

def pytoimage(pyfile):
    pymodule = __import__(pyfile)
    img = PIL.Image.open(cStringIO.StringIO(pymodule.image_data))
    img.show()

if __name__ == '__main__':
    imagetopy('spot.png', 'wishes.py')
    pytoimage('wishes')

Sie können dann entscheiden, die Ausgabebilddatei mit Cython zu kompilieren , um sie cool zu machen. Mit dieser Methode können Sie alle Ihre Grafiken in einem Modul bündeln.

iChux
quelle
6
import base64
from PIL import Image
from io import BytesIO

with open("image.jpg", "rb") as image_file:
    data = base64.b64encode(image_file.read())

im = Image.open(BytesIO(base64.b64decode(data)))
im.save('image1.png', 'PNG')
DooDle-Softwarelösungen
quelle
Diese Antwort sollte wirklich ganz oben stehen ... am besten - danke!
Luther