Encoding an image file with base64
Asked Answered
B

6

251

I want to encode an image into a string using the base64 module. I've ran into a problem though. How do I specify the image I want to be encoded? I tried using the directory to the image, but that simply leads to the directory being encoded. I want the actual image file to be encoded.

EDIT

I tried this snippet:

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

but I get the following error:

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

What am I doing wrong?

Burt answered 15/9, 2010 at 7:24 Comment(0)
L
449

I'm not sure I understand your question. I assume you are doing something along the lines of:

import base64

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

You have to open the file first of course, and read its contents - you cannot simply pass the path to the encode function.

Edit: Ok, here is an update after you have edited your original question.

First of all, remember to use raw strings (prefix the string with 'r') when using path delimiters on Windows, to prevent accidentally hitting an escape character. Second, PIL's Image.open either accepts a filename, or a file-like (that is, the object has to provide read, seek and tell methods).

That being said, you can use cStringIO to create such an object from a memory buffer:

import cStringIO
import PIL.Image

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

img = PIL.Image.open(file_like)
img.show()
Lanyard answered 15/9, 2010 at 7:31 Comment(4)
Thanks, one more problem when I print the decoded image I get the string 'ÿØÿà'. However, when I run this alone as a substitute for data I get an error. The encoded string is much longer for comparison. So I think that likely stores the image data. does the decoded string simply reference the encoded string or something? It seems far too short for data storage.Burt
The printed output is not necessarily equal to the actual contents - it depends on how and where you print it.Lanyard
In my case, I need to decode: base64.b64encode(fh.read()).decode() to get a string to be used in html files.Sowell
base64.b64encode(fh.read()).decode() is subtle but I needed this as well @Sowell , thanks. Difference is one returns bytes and other string ... and my SOAP server would just not swallow it without decoding!Janitor
C
67
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')

Cyanine answered 19/9, 2019 at 6:55 Comment(1)
this answer really should be at the top... best one -- thanks!Homeopathy
A
59

Just using base64.b64encode(img_file.read()) will return bytes. That means your result will look like b'your_string'. To solve this issue, you need to decode it like so:

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

I have experienced this while converting Image to Base64 string. You can take a look at how I removed that from there also. Link is here Image to base64 string and fix 'b from prefix

Atheism answered 26/4, 2019 at 21:20 Comment(4)
This looks like a good answer, but please refrain from posting if the purpose is to promote your website. You are welcome to add links into your profile, however.Jeraldinejeralee
(Incidentally, answer order cannot be relied on here, so it is worth avoiding comments like "the first answer". The one that appears first may change over time.:-))Jeraldinejeralee
In your original version of this answer, it looks like you linked to your own site or a site you're affiliated with. If you do link to such a site, you must disclose that it's your site. If you don't disclose affiliation, it's considered spam. See: What signifies "Good" self promotion? and the help center on self-promotion. Disclosure must be explicit, but doesn't need to be formal. When it's your own personal content, it can just be something like "on my site…", "on my blog…", etc.Randell
Thanks for the suggestion @Randell I am going to disclose that it's my site. Will it be legal to edit the answer now to disclose that it is my site? Or I should not edit it.Atheism
D
11

As I said in your previous question, there is no need to base64 encode the string, it will only make the program slower. Just use the 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))
...

Now the image is stored as a variable called image_data in a file called image.py Start a fresh interpreter and import the image_data

>>> from image import image_data
>>>
Deeply answered 15/9, 2010 at 7:36 Comment(3)
I don't really see how repr() can be of any use here.Lomeli
@Ivo, Anteater wants to be able to store images in python files. I am pointing out that using base64 is counterproductive because the data needs to be decoded every time the module is loaded. Using repr instead means the literal string is stored ready for immediate use in the .pyc file with no furthur processingDeeply
@JohnLaRooy Thanks a lot. I got that TypeError: a bytes-like object is required, not 'str' at the line ` fout.write("image_data="+repr(image_data))`. How can I fix that?Salivation
C
11

Borrowing from what Ivo van der Wijk and gnibbler have developed earlier, this is a dynamic solution

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

You can then decide to compile the output image file with Cython to make it cool. With this method, you can bundle all your graphics into one module.

Clare answered 3/10, 2013 at 15:22 Comment(0)
C
7

Its work for me

import base64
import requests

# Getting image in bytes
response = requests.get("image_url") 

# image encoding
encoded_image = base64.b64encode(response.content)

# image decoding and without it's won't work due to some '\xff' error
decoded_image= base64.b64decode(encoded_image)

Cyanide answered 7/4, 2021 at 10:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.