nobody
nobody

Reputation: 521

Python PIL image Verify returns None

I am developing a tool which retrieves a JPG from an API and processes it. The source of the image cannot be trusted and I want to test if the image is a valid JPG (which is the only image type allowed).

I encountered an error with PIL that I am unable to fix. Below is my code:

image = StringIO(base64.b64decode(download['file']))
img = Image.open(image)
if img.verify():
    print 'Valid image'
else:
    print 'Invalid image'

However, it seems that img.verify() returns None. I can call other functions on the open image like img.size() which returns the size. I get the following output when I try to debug the code:

img = Image.open(image)
print img
print img.size()
print img.verify()

[2018-01-09 20:56:43,715: WARNING/Worker-1] <PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=2577x1715 at 0x7F16E17DC9D0>
[2018-01-09 20:56:43,716: WARNING/Worker-1] (2577, 1715)
[2018-01-09 20:56:43,716: WARNING/Worker-1] None

Has someone encountered the same issue?

Upvotes: 9

Views: 24634

Answers (2)

supersam654
supersam654

Reputation: 3234

According to the docs, Image#verify (or the PIL docs for verify) raises an exception if there is a problem with the image and does nothing otherwise.

To use #verify, you probably want something like this:

image = StringIO(base64.b64decode(download['file']))
img = Image.open(image)
try:
    img.verify()
    print('Valid image')
except Exception:
    print('Invalid image')

Additionally, you might want to also check that the image is actually a JPG by looking at the image format:

if img.format == 'JPEG':
     print('JPEG image')
else:
     print('Invalid image type')

Upvotes: 15

Finlay McWalter
Finlay McWalter

Reputation: 1342

In addition to verify and checking the .format field, if you're loading images from untrustworthy (and possibly genuinely malicious) sources over the web, you should worry about zip bombs.

Pillow (but not, I think, original PIL) has a DecompressionBombWarning which is triggered when an image tries to exceed Image.MAX_IMAGE_PIXELS (a value you can set yourself, prior to attempting to load an image). The default value of that, on my install, is a very generous 85 Mpixels.

A fuller discussion about this Pillow feature is at this discussion.

Upvotes: 5

Related Questions