diff --git a/etiquette/helpers.py b/etiquette/helpers.py index 807b732..269ca0f 100644 --- a/etiquette/helpers.py +++ b/etiquette/helpers.py @@ -213,7 +213,7 @@ def dotdot_range(s) -> tuple: return (low, high) -def generate_image_thumbnail(filepath, width, height) -> PIL.Image: +def _generate_image_thumbnail(filepath, max_width, max_height) -> PIL.Image: if not os.path.isfile(filepath): raise FileNotFoundError(filepath) image = PIL.Image.open(filepath) @@ -222,8 +222,8 @@ def generate_image_thumbnail(filepath, width, height) -> PIL.Image: (new_width, new_height) = imagetools.fit_into_bounds( image_width=image_width, image_height=image_height, - frame_width=width, - frame_height=height, + frame_width=max_width, + frame_height=max_height, only_shrink=True, ) if (new_width, new_height) != (image_width, image_height): @@ -244,6 +244,15 @@ def generate_image_thumbnail(filepath, width, height) -> PIL.Image: image = image.convert('RGB') return image +def generate_image_thumbnail(*args, trusted_file=False, **kwargs) -> PIL.Image: + _max_pixels = PIL.Image.MAX_IMAGE_PIXELS + if trusted_file: + PIL.Image.MAX_IMAGE_PIXELS = None + try: + return _generate_image_thumbnail(*args, **kwargs) + finally: + PIL.Image.MAX_IMAGE_PIXELS = _max_pixels + def generate_video_thumbnail(filepath, outfile, width, height, **special) -> PIL.Image: if not os.path.isfile(filepath): raise FileNotFoundError(filepath) diff --git a/etiquette/objects.py b/etiquette/objects.py index fcd847c..7917bbb 100644 --- a/etiquette/objects.py +++ b/etiquette/objects.py @@ -1060,9 +1060,11 @@ class Photo(ObjectBase): @decorators.required_feature('photo.generate_thumbnail') @worms.atomic - def generate_thumbnail(self, **special) -> pathclass.Path: + def generate_thumbnail(self, trusted_file=False, **special) -> pathclass.Path: ''' special: + For images, you can provide `max_width` and/or `max_height` to + override the config file. For videos, you can provide a `timestamp` to take the thumbnail at. ''' hopeful_filepath = self.make_thumbnail_filepath() @@ -1073,8 +1075,9 @@ class Photo(ObjectBase): try: image = helpers.generate_image_thumbnail( self.real_path.absolute_path, - width=self.photodb.config['thumbnail_width'], - height=self.photodb.config['thumbnail_height'], + max_width=special.get('max_width', self.photodb.config['thumbnail_width']), + max_height=special.get('max_height', self.photodb.config['thumbnail_height']), + trusted_file=trusted_file, ) except (OSError, ValueError): traceback.print_exc() diff --git a/etiquette/photodb.py b/etiquette/photodb.py index 6d52731..5297f86 100644 --- a/etiquette/photodb.py +++ b/etiquette/photodb.py @@ -319,6 +319,7 @@ class PDBPhotoMixin: known_hash=None, searchhidden=False, tags=None, + trusted_file=False, ) -> objects.Photo: ''' Given a filepath, determine its attributes and create a new Photo object @@ -377,9 +378,9 @@ class PDBPhotoMixin: if do_metadata: hash_kwargs = hash_kwargs or {} - photo.reload_metadata(hash_kwargs=hash_kwargs) + photo.reload_metadata(hash_kwargs=hash_kwargs, trusted_file=trusted_file) if do_thumbnail: - photo.generate_thumbnail() + photo.generate_thumbnail(trusted_file=trusted_file) tags = tags or [] tags = [self.get_tag(name=tag) for tag in tags]