diff options
Diffstat (limited to 'src/hircine/thumbnailer.py')
-rw-r--r-- | src/hircine/thumbnailer.py | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/src/hircine/thumbnailer.py b/src/hircine/thumbnailer.py new file mode 100644 index 0000000..ed565d5 --- /dev/null +++ b/src/hircine/thumbnailer.py @@ -0,0 +1,75 @@ +import os +from typing import NamedTuple + +from PIL import Image + +pillow_extensions = { + ext for ext, f in Image.registered_extensions().items() if f in Image.OPEN +} + + +class ThumbnailParameters(NamedTuple): + bounds: tuple[int, int] + options: dict + + +def params_from(config): + return { + "full": ThumbnailParameters( + bounds=( + config.getint("import.scale.full", "width", fallback=4200), + config.getint("import.scale.full", "height", fallback=2000), + ), + options={"quality": 82, "method": 5}, + ), + "thumb": ThumbnailParameters( + bounds=( + config.getint("import.scale.thumb", "width", fallback=1680), + config.getint("import.scale.thumb", "height", fallback=800), + ), + options={"quality": 75, "method": 5}, + ), + } + + +def object_path(directory, hash, suffix): + return os.path.join(directory, hash[:2], f"{hash[2:]}_{suffix}.webp") + + +class Thumbnailer: + def __init__(self, directory, params): + self.directory = directory + self.params = params + + @classmethod + def can_process(cls, extension): + return extension in pillow_extensions + + def object(self, hash, suffix): + return object_path(self.directory, hash, suffix) + + def process(self, handle, hash, reprocess=False): + size = None + + for suffix, parameters in self.params.items(): + source = Image.open(handle, mode="r") + + if not size: + size = source.size + + output = self.object(hash, suffix) + + if os.path.exists(output) and not reprocess: + continue + else: + os.makedirs(os.path.dirname(output), exist_ok=True) + + if source.mode != "RGB": + target = source.convert() + else: + target = source + + target.thumbnail(parameters.bounds, resample=Image.Resampling.LANCZOS) + target.save(output, **parameters.options) + + return size |