250 votes

Encodage d'un fichier image avec base64

Je veux encoder une image dans une chaîne de caractères en utilisant le module base64. Je me heurte cependant à un problème. Comment puis-je spécifier l'image que je veux encoder ? J'ai essayé d'utiliser le répertoire de l'image, mais cela conduit simplement à l'encodage du répertoire. Je veux que le fichier image réel soit encodé.

EDIT

J'ai essayé cet extrait :

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))

mais je reçois l'erreur suivante :

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

Qu'est-ce que je fais de mal ?

446voto

Jim Brissom Points 10282

Je ne suis pas sûr de comprendre votre question. Je suppose que vous faites quelque chose du genre :

import base64

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

Bien entendu, vous devez d'abord ouvrir le fichier et lire son contenu. Vous ne pouvez pas simplement transmettre le chemin d'accès à la fonction d'encodage.

Edita: Ok, voici une mise à jour après que vous ayez modifié votre question originale.

Tout d'abord, n'oubliez pas d'utiliser des chaînes brutes (préfixez la chaîne par 'r') lorsque vous utilisez des délimiteurs de chemin sous Windows, afin d'éviter de toucher accidentellement un caractère d'échappement. Deuxièmement, Image.open de PIL accepte soit un nom de fichier, soit un fichier similaire (c'est-à-dire que l'objet doit fournir des méthodes read, seek et tell).

Cela dit, vous pouvez utiliser cStringIO pour créer un tel objet à partir d'un tampon mémoire :

import cStringIO
import PIL.Image

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

img = PIL.Image.open(file_like)
img.show()

1 votes

Merci, mais il y a un autre problème : lorsque j'imprime l'image décodée, j'obtiens la chaîne 'ÿØÿà'. Cependant, lorsque je l'exécute seule en remplacement des données, j'obtiens une erreur. La chaîne encodée est beaucoup plus longue pour comparaison. La chaîne décodée fait-elle simplement référence à la chaîne encodée ? Elle semble beaucoup trop courte pour le stockage de données.

1 votes

La sortie imprimée n'est pas nécessairement égale au contenu réel - cela dépend de la façon dont vous l'imprimez et de l'endroit où vous l'imprimez.

21 votes

Dans mon cas, j'ai besoin de décoder : base64.b64encode(fh.read()).decode() pour obtenir une chaîne de caractères à utiliser dans les fichiers html.

66voto

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')

59voto

CodeSpeedy Points 411

La première réponse imprimera une chaîne de caractères avec le préfixe b'. Cela signifie que votre chaîne sera comme ceci b'votre_chaîne' Pour résoudre ce problème, veuillez ajouter la ligne de code suivante.

encoded_string= base64.b64encode(img_file.read())
print(encoded_string.decode('utf-8'))

J'ai rencontré ce problème lors de la conversion d'une image en chaîne de caractères Base64. Vous pouvez regarder comment je l'ai supprimé de là aussi. Le lien est ici Image en chaîne base64 et correction du préfixe "b".

56voto

Ivo van der Wijk Points 7239

Avec python 2.x, vous pouvez trivialement encoder en utilisant .encode :

with open("path/to/file.png", "rb") as f:
    data = f.read()
    print data.encode("base64")

11voto

gnibbler Points 103484

Comme je l'ai dit dans votre question précédente, il n'est pas nécessaire de coder la chaîne en base64, cela ne fera que ralentir le programme. Utilisez simplement la fonction 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))
...

L'image est maintenant stockée dans une variable appelée image_data dans un fichier appelé image.py Démarrer un nouvel interpréteur et importer l'image_data.

>>> from image import image_data
>>>

1 votes

Je ne vois pas vraiment comment repr() peut être d'une quelconque utilité ici.

6 votes

@Ivo, Anteater veut être capable de stocker des images dans des fichiers python. Je signale que l'utilisation de base64 est contre-productive car les données doivent être décodées à chaque fois que le module est chargé. En utilisant repr à la place, la chaîne littérale est stockée prête à être utilisée immédiatement dans le fichier .pyc sans traitement supplémentaire.

0 votes

@JohnLaRooy Merci beaucoup. J'ai compris que TypeError: a bytes-like object is required, not 'str' à la ligne ` fout.write("image_data="+repr(image_data))`. Comment puis-je corriger cela ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X