8

for the past few hours i've been trying to create a Base64 String of an Image, but it won't work.

ship_color = (0,100,100,255)
img = Image.new("RGBA", (100,100))
for i in range(20):
   for j in range(20):
       img.putpixel((40 + i, 40 + j), ship_color)
img.save("tmp.png", format = "PNG")
im = open("tmp.png", "rb").read()
print(im)
base = base64.b64encode(im)
print(base)

When i try to create an image from the String again i get an exception:

img2 = Image.frombytes("RGBA", (100, 100), base)
ValueError: not enough image data

Other online services for Base64 Decoding also give an error, so the base64 String itself does not seem to be correct.

example image String (from open().read()):

b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00d\x00\x00\x00d\x08\x02\x00\x00\x00\xff\x80\x02\x03\x00\x00\x00lIDATx\x9c\xed\xd0\xd1\t\x800\x10\x05\xc1h\xad)+\xc5Z\xc3\x8a\x10"3\xff\xc7;v\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x008\xc7\xb5my\xce\xf7\xb7k}\xf7GpoY=\x94X\x81X\x81X\x81X\x81X\x81X\x81X\x81X\x81X\x81X\x81X\x81X\x81X\x81X\x81X\x81X\x81X\x81X\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0S\x0fX\xb7\x02(\x90HP\xa2\x00\x00\x00\x00IEND\xaeB`\x82'

example base64 String:

b'iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAIAAAD/gAIDAAAAbElEQVR4nO3Q0QmAMBAFwWitKSvFWsOKECIz/8c7dgwAAAAAAAAAAAAAADjHtW15zve3a333R3BvWT2UWIFYgViBWIFYgViBWIFYgViBWIFYgViBWIFYgViBWIFYgVgAAAAAAAAAAAAAAPBTD1i3AiiQSFCiAAAAAElFTkSuQmCC'
Alastair McCormack
  • 26,573
  • 8
  • 77
  • 100
Vlad de Elstyr
  • 83
  • 1
  • 2
  • 6

2 Answers2

13

You need to base64 encode before you can decode.

You can achieve this without creating a temporary file by using an in memory file, with io.BytesIO()

in_mem_file = io.BytesIO()
img.save(in_mem_file, format = "PNG")
# reset file pointer to start
in_mem_file.seek(0)
img_bytes = in_mem_file.read()

base64_encoded_result_bytes = base64.b64encode(img_bytes)
base64_encoded_result_str = base64_encoded_result_bytes.decode('ascii')
Alastair McCormack
  • 26,573
  • 8
  • 77
  • 100
  • Thanks i got it working now. In the end the problem was the b'' prefix of a byte representation in python so i first had to convert it to a string and then slice off the first few characters. For anyone curious: `base = base64.b64encode(im) base.decode() base = str(base) base = base[2:len(base)- 1]` did it for me – Vlad de Elstyr Feb 28 '17 at 10:25
  • no, no. that's the wrong way to do it. You simply need to `decode()` the byte object as text using 'ascii'. The result is a str. See updated answer. – Alastair McCormack Feb 28 '17 at 11:22
  • Saved me tons of time. Thanks! – Hvitis Jul 04 '22 at 19:51
0

Image.frombytes() does not create an image from a base64 encoded string, see documentation.

If you want to reverse the encoding, use:

img2 = base64.b64decode(base)
Robert
  • 5,703
  • 2
  • 31
  • 32