4

I tried encoding an image and decoding the same in python shell. The first time I open the decoded base64 string in PIL there is no error, if I repeat the Image.open() command I'm getting IOError: cannot identify image file.

>>> with open("/home/home/Desktop/gatherify/1.jpg", "rb") as image_file:
...     encoded_string = base64.b64encode(image_file.read())
>>> image_string = cStringIO.StringIO(base64.b64decode(encoded_string))
>>> img = Image.open(image_string)
>>> img
<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=576x353 at 0xA21F20C>
>>> img.show() <-- Image opened without any errors. 
>>> img = Image.open(image_string)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/usr/lib/python2.6/dist-packages/PIL/Image.py", line 1980, in open
    raise IOError("cannot identify image file")
IOError: cannot identify image file

Why is this happening?

Praveen
  • 2,400
  • 3
  • 23
  • 30

2 Answers2

4

When you create your image_string, you're creating a fake file-like object backed by a string. When you call Image.open, it reads this fake file, moving the file pointer to the end of the file. Attempting to use Image.open on it again just gives you an EOF.

You need to either re-create your StringIO object, or seek() to the beginning of the stream.

TkTech
  • 4,729
  • 1
  • 24
  • 32
  • 1
    FYI, `Image.open` does not read the entire file (does not move the file pointer to the end of the file). It only reads the file header. See [Image.open](http://effbot.org/imagingbook/image.htm#tag-`Image.open`). – falsetru Nov 11 '13 at 16:31
  • http://stackoverflow.com/questions/19908975/loading-base64-string-into-python-image-library see if you can solve this issue, it's related to this question – Praveen Nov 11 '13 at 16:33
  • I wasn't aware of that @falsetru, thank you. Makes sense to lazily load it, especially if you are working on large images (think 1GB+ NASA images) – TkTech Nov 11 '13 at 16:34
  • Sorry, added incorrect link in the previous comment. See [`Image.open`](http://effbot.org/imagingbook/image.htm#tag-Image.open). – falsetru Nov 11 '13 at 16:38
1

image_string is file-like object. File-like object has file position.

Once the file is read, the position is advanced.

Any subsequent is occurred at that position unless you explicitly position it using seek method.

So if you want to reopen the file:

...
image_string.seek(0) # reset file position to the beginning of the file.
img = Image.open(image_string)
falsetru
  • 357,413
  • 63
  • 732
  • 636