Image Cropping Tool (Python)

Macca picture Macca · Sep 7, 2014 · Viewed 9.2k times · Source

I'm a film photographer who deals a lot with cropping/image resizing. Because I shoot film, I have to scan my negatives and crop each frame out of the batch scan. My scanner scans four strips of six images each (24 frames/crops per scan).

A friend of mine wrote me a script for Python that automatically crops images based on inputted coordinates. The script works well but it has problems in the file format of the exported images.

From the scan, each frame should produce a 37mb TIFF at 240 DPI (when I crop and export in Adobe Lightroom). Instead, the Cropper outputs a 13mb 72 DPI TIFF.

Terminal (I'm on Mac) warns me about a "Decompression Bomb" whenever I run the Cropper. My friend is stumped and suggested I ask Stack Overflow.

I've no Python experience. I can provide the code he wrote and the commands Terminal gives me.

Thoughts? This would be greatly appreciated and a huge HUGE timesaver. THANK YOU!

ERROR MESSAGE: /Library/Python/2.7/site-packages/PIL/Image.py:2192: DecompressionBombWarning: Image size (208560540 pixels) exceeds limit of 89478485 pixels, could be decompression bomb DOS attack.

Answer

Martijn Pieters picture Martijn Pieters · Sep 7, 2014

PIL is merely trying to protect you. It'll not open larger images, as that could be a vector of attack for a malicious user to give you a large image that'll expand to use up all memory. Quoting from the PIL.Image.open() documentation:

Warning: To protect against potential DOS attacks caused by “decompression bombs” (i.e. malicious files which decompress into a huge amount of data and are designed to crash or cause disruption by using up a lot of memory), Pillow will issue a DecompressionBombWarning if the image is over a certain limit.

Since you are not a malicious user and are not accepting images from anyone else, you can simply disable the limit:

from PIL import Image

Image.MAX_IMAGE_PIXELS = None

Setting Image.MAX_IMAGE_PIXELS disables the check altogether. You can also set it to a (high) integer value; the default is 1024 * 1024 * 1024 // 4 // 3, nearly 90 million pixels or about a 250MB uncompressed data for a 3-channel image.

Note that for PIL versions up to 4.3.0, by default, all that happens is that a warning is issued. You could also disable the warning:

import warnings
from PIL import Image

warnings.simplefilter('ignore', Image.DecompressionBombWarning)

Inversely, if you want to prevent such images from being loaded altogether, turn the warning into an exception:

import warnings
from PIL import Image

warnings.simplefilter('error', Image.DecompressionBombWarning)

and you can then expect the Image.DecompressionBombWarning object to be raised as an exception whenever you pass an image in that would otherwise demand a lot of memory.

As of PIL v5.0.0 (released Jan 2018), images that use twice the number of pixels as the MAX_IMAGE_PIXELS value will result in a PIL.Image.DecompressionBombError exception.

Note that these checks also apply to the Image.crop() operation (you can create a larger image by cropping), and you need to use PIL version 6.2.0 or newer (released in October 2019) if you want to benefit from this protection when working with GIF or ICO files.