4

the following code is throwing an error Error with file: string argument expected, got 'bytes'

I also tried using BytesIO but it threw an error about needed a format of string and not bytes. Very confusing.

def im_2_b64(image):
    buffer = StringIO()
    image.save(buffer, format="JPEG")
    img_str = base64.b64encode(buffer.getvalue())
    return img_str

How can I convert an image to base64 using python 2.7?

UPDATE

Error with file: Object of type bytes is not JSON serializable
Error with file: single positional indexer is out-of-bounds

using BytesIO

Jeff Voss
  • 3,637
  • 8
  • 46
  • 71
  • Is the `image` arg a PIL `Image` object? – PM 2Ring Sep 19 '18 at 17:52
  • @PM 2Ring, Yes it is – Jeff Voss Sep 19 '18 at 17:53
  • 2
    In that case, that code works fine for me once I change `StringIO()` to `BytesIO()`. Are you sure you're running it on Python 2? :) Actually, it works fine in Python 3 as well. – PM 2Ring Sep 19 '18 at 17:54
  • 2
    BTW, `buffer` isn't a great variable name in Python 2, since it clashes with the built-in `buffer` type. – PM 2Ring Sep 19 '18 at 17:56
  • Well, I'm not sure what the exact problem is, but you can decode your `buffer.getvalue()` byte-string to a normal string and I think it should work---just replace it with `buffer.getvalue().decode()`. – alkasm Sep 19 '18 at 18:02
  • 2
    Regarding your edit, where is that error occurring?I don't believe it is occurring in the code you've shown us – ubadub Sep 19 '18 at 18:06
  • 1
    You didn't say anything about JSON before! And that error message *definitely* indicates you're using Python 3. – PM 2Ring Sep 19 '18 at 18:09
  • JSON does not accept `bytes` objects. But that's not a problem. Simply decode the bytes to a string, eg `img_str.decode('ascii')` – PM 2Ring Sep 19 '18 at 18:10

2 Answers2

14

Here's a short but complete demo of your code using a ByteIO instead of StringIO. I've also added a function to do the reverse conversion. It runs correctly on Python 2.6 and 3.6. The only difference is that in Python 3 the Base64 output is a b string.

from PIL import Image
from io import BytesIO
import base64

# Convert Image to Base64 
def im_2_b64(image):
    buff = BytesIO()
    image.save(buff, format="JPEG")
    img_str = base64.b64encode(buff.getvalue())
    return img_str

# Convert Base64 to Image
def b64_2_img(data):
    buff = BytesIO(base64.b64decode(data))
    return Image.open(buff)

# Test

img = Image.new('RGB', (120, 90), 'red')
img.show()

img_b64 = im_2_b64(img)
print(img_b64)

new_img = b64_2_img(img_b64)
new_img.show()

Python 3 output

b'/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCABaAHgDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDi6KKK+ZP3EKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigD/9k='
PM 2Ring
  • 54,345
  • 6
  • 82
  • 182
0

You can use this function to convert an image to base64 string.

import base64

def image_to_base64(image_path):
    with open(image_path, "rb") as image_file:
        encoded_string = base64.b64encode(image_file.read()).decode("utf-8")
        return encoded_string

base64String = image_to_base64('image.jpg')