'Python - Opening a PNG fails with `cannot identify image file`

I'm trying to open a PNG file with Python. I do believe I have a properly encoded PNG.

Full text of file: https://ctxt.io/2/AABgnYYrEw

It starts with:

\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR 

And ends with:

\x00IEND\xaeB`\x82

My code so far:

import PIL.Image as Image
with open('./test_image_3.txt', 'rb') as f:
    b = f.read()
    b = base64.b64decode(b).decode("unicode_escape").encode("latin-1")
    b = b.decode('utf-16-le')
    img = Image.open(io.BytesIO(b))
    img.show()

    b = base64.b64decode(b).decode("unicode_escape").encode("latin-1")
    UnicodeDecodeError: 'unicodeescape' codec can't decode bytes in position 178-179: truncated \uXXXX escape


Solution 1:[1]

Unfortunately I can't read the file you've provided as the website butchered it massively. Either use pastebin or github (or something similar) where it'll be possible to retrieve text/plain e.g. via curl so I can attempt to reproduce the problem 1:1 for the contents.

However, the general approach would be this:

from PIL import Image

with Image.open("./test_image_3.txt") as im:
    im.show()

it's directly from Pillow's documentation and it does not care about the file's name or extension.

Alternatively, if you have open() call with a file handle:

from PIL import Image

with open("./test_image_3.txt", "rb") as file:
    with Image.open(file) as im:
        im.show()

And if you have it mangled somehow, then judging from your encode() and decode() calls it would be this:

from PIL  import Image
from io import BytesIO

data = <some raw PNG bytes, the original image>

# here I store it in that weird format and write as bytes
with open("img.txt", "wb") as file:
    file.write(data.decode("latin-1").encode("unicode_escape"))

# here I read it back as bytes, reverse the chain of calls and invert
# the call pairs for en/decoding so encode() -> decode() and vice-versa
with open("img.txt","rb") as file:
    content = BytesIO()
    content.write(
        file.read().decode("unicode_escape").encode("latin-1")
    )
    # seek back, so the BytesIO() can return back the full content
    content.seek(0)
    # then simply read as if using a file handle
    with Image.open(content) as img:
        img.show()

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1