Skip to content

Commit

Permalink
Merge pull request loris-imageserver#506 from jamieparkinson/configur…
Browse files Browse the repository at this point in the history
…able-pil-max-image-size

Configurable PIL.Image.MAX_IMAGE_PIXELS
  • Loading branch information
alexwlchan authored Jun 1, 2020
2 parents b7abd38 + 0a1c020 commit 01df4d4
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 3 deletions.
4 changes: 4 additions & 0 deletions doc/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ Any options you add here will be passed through to the resolver you implement. F

Probably safe to leave these as-is unless you care about something very specific. See the [Developer Notes](develop.md#image-transformations) for when this may not be the case. The exceptions are `kdu_expand` and `kdu_libs` in the `[transforms.jp2]` (see [Installing Dependencies](dependencies.md) step 2) or if you're not concerned about color profiles (see next).

If you are seeing `DecompressionBombError`s thrown for very large source images, try setting the `pil_max_image_pixels` property here. This error occurs for images that are larger than **2x** PIL's MAX_IMAGE_PIXELS property, which is `1024 * 1024 * 1024 // 4 // 3 = 89478485` by default (and so the error is thrown for images larger than `2 * 89478485 = 178956970` pixels). Note that PIL will still log a `DecompressionBombWarning` will still be logged if the image is bigger than **1x** the configured value.

If `pil_max_image_pixels` is set to `0`, `PIL.Image.MAX_IMAGE_PIXELS` is set to `None` and there is no limit on image size.

### map_profile_to_srgb

You can tell Loris to map embedded color profiles to sRGB with the following settings in your transformer:
Expand Down
6 changes: 6 additions & 0 deletions etc/loris2.conf
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,12 @@ dither_bitonal_images = False
# To enable TIFF output, add "tif" here:
target_formats = ['jpg','png','gif','webp']

# By default PIL throws a DecompressionBombError for images that are larger than
# 2x its MAX_IMAGE_PIXELS property (this limit is 2 * 89478485 = 178956970px).
# This property can be overridden by this config value. If set to 0, MAX_IMAGE_PIXELS
# is set to `None` and there is no limit on image size.
# pil_max_image_pixels = 250000000

[[jpg]]
impl = 'JPG_Transformer'

Expand Down
15 changes: 12 additions & 3 deletions loris/webapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
sys.path.append('.')

from configobj import ConfigObj
from PIL import Image
from werkzeug.http import parse_date, http_date

from werkzeug.wrappers import (
Expand Down Expand Up @@ -379,13 +380,21 @@ def _load_transformers(self):
tforms = self.app_configs['transforms']
source_formats = [k for k in tforms if isinstance(tforms[k], dict)]
self.logger.debug('Source formats: %r', source_formats)
global_tranform_options = dict((k, v) for k, v in tforms.items() if not isinstance(v, dict))
self.logger.debug('Global transform options: %r', global_tranform_options)
global_transform_options = dict((k, v) for k, v in tforms.items() if not isinstance(v, dict))
self.logger.debug('Global transform options: %r', global_transform_options)

pil_max_image_pixels = tforms.get('pil_max_image_pixels', Image.MAX_IMAGE_PIXELS)
if pil_max_image_pixels != 0:
Image.MAX_IMAGE_PIXELS = pil_max_image_pixels
self.logger.debug('PIL maximum image pixels set to: %d', pil_max_image_pixels)
else:
Image.MAX_IMAGE_PIXELS = None
self.logger.debug('PIL maximum image pixels limit removed.')

transformers = {}
for sf in source_formats:
# merge [transforms] options and [transforms][source_format]] options
config = dict(list(self.app_configs['transforms'][sf].items()) + list(global_tranform_options.items()))
config = dict(list(self.app_configs['transforms'][sf].items()) + list(global_transform_options.items()))
transformers[sf] = self._load_transformer(config)
return transformers

Expand Down
15 changes: 15 additions & 0 deletions tests/transforms_t.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import operator

import pytest
from PIL import Image

from loris import transforms
from loris.loris_exception import ConfigError
Expand Down Expand Up @@ -344,3 +345,17 @@ def test_can_transform_transparent_png_as_nontransparent_format(self):
ident = 'png_with_transparency.png'
request_path = '/%s/full/full/0/default.jpg' % ident
self.request_image_from_client(request_path)

def test_respects_pil_max_image_pixels(self):
default_max_pixels = Image.MAX_IMAGE_PIXELS
try:
config = get_debug_config('kdu')
config['transforms']['pil_max_image_pixels'] = 1
self.build_client_from_config(config)
with pytest.raises(Image.DecompressionBombError):
request_path = '/%s/full/300,300/0/default.jpg' % self.ident
self.request_image_from_client(request_path)
finally:
# Because we have to mutate a value in an external library
# it must be reset at the end of this test
Image.MAX_IMAGE_PIXELS = default_max_pixels

0 comments on commit 01df4d4

Please sign in to comment.