diff --git a/kodak/manipulations.py b/kodak/manipulations.py index e0b7777..2689bdb 100644 --- a/kodak/manipulations.py +++ b/kodak/manipulations.py @@ -7,7 +7,36 @@ from kodak import constants def scale(image: Image.Image, config: configuration.ManipConfig) -> Image.Image: - pass + """Scale an image to new dimensions""" + + if config.scale.strategy == constants.ScaleStrategy.ABSOLUTE: + width = config.scale.horizontal or image.width + height = config.scale.vertical or image.height + elif config.scale.strategy == constants.ScaleStrategy.RELATIVE: + width = ( + (config.scale.horizontal * image.width) + if config.scale.vertical + else image.width + ) + height = ( + (config.scale.horizontal * image.height) + if config.scale.vertical + else image.height + ) + else: + raise ValueError("Here there be dragons") + + logging.getLogger(__name__).debug( + f"Scaling image: old {image.width}x{image.height}; new {width}x{height})" + ) + + if config.scale.horizontal is None or config.scale.vertical is None: + image = image.copy() + image.thumbnail((width, height), Image.ANTIALIAS) + else: + image.resize((width, height)) + + return image def crop(image: Image.Image, config: configuration.ManipConfig) -> Image.Image: @@ -18,56 +47,51 @@ def crop(image: Image.Image, config: configuration.ManipConfig) -> Image.Image: width = config.crop.horizontal or image.width height = config.crop.vertical or image.height - top = 0 - left = 0 - bottom = image.height - right = image.width - if config.crop.anchor == constants.CropAnchor.TL: - x_1 = left - y_1 = top + x_1 = 0 + y_1 = 0 x_2 = width y_2 = height elif config.crop.anchor == constants.CropAnchor.TC: - x_1 = (right / 2) - (width / 2) - y_1 = top - x_2 = (right / 2) + (width / 2) + x_1 = (image.width / 2) - (width / 2) + y_1 = 0 + x_2 = (image.width / 2) + (width / 2) y_2 = height elif config.crop.anchor == constants.CropAnchor.TR: - x_1 = right - width - y_1 = top - x_2 = right + x_1 = image.width - width + y_1 = 0 + x_2 = image.width y_2 = height elif config.crop.anchor == constants.CropAnchor.CL: - x_1 = left - y_1 = (bottom / 2) - (height / 2) + x_1 = 0 + y_1 = (image.height / 2) - (height / 2) x_2 = width - y_2 = (bottom / 2) + (height / 2) + y_2 = (image.height / 2) + (height / 2) elif config.crop.anchor == constants.CropAnchor.C: - x_1 = (right / 2) - (width / 2) - y_1 = (bottom / 2) - (height / 2) - x_2 = (right / 2) + (width / 2) - y_2 = (bottom / 2) + (height / 2) + x_1 = (image.width / 2) - (width / 2) + y_1 = (image.height / 2) - (height / 2) + x_2 = (image.width / 2) + (width / 2) + y_2 = (image.height / 2) + (height / 2) elif config.crop.anchor == constants.CropAnchor.BL: - x_1 = left - y_1 = bottom - height + x_1 = 0 + y_1 = image.height - height x_2 = width - y_2 = bottom + y_2 = image.height elif config.crop.anchor == constants.CropAnchor.BC: - x_1 = (right / 2) - (width / 2) - y_1 = bottom - height - x_2 = (right / 2) + (width / 2) - y_2 = bottom + x_1 = (image.width / 2) - (width / 2) + y_1 = image.height - height + x_2 = (image.width / 2) + (width / 2) + y_2 = image.height elif config.crop.anchor == constants.CropAnchor.BR: - x_1 = right - width - y_1 = bottom - height - x_2 = right - y_2 = bottom + x_1 = image.width - width + y_1 = image.height - height + x_2 = image.width + y_2 = image.height else: raise ValueError("Ye gadds! This codepath is impossible!") logging.getLogger(__name__).debug( - f"Cropping image {image.filename}: old {right}x{bottom}; new {width}x{height}; upper-left anchor ({x_1}, {y_1}); lower-right anchor ({x_2}, {y_2})" + f"Cropping image: old {image.width}x{image.height}; new {width}x{height}; upper-0 anchor ({x_1}, {y_1}); lower-image.width anchor ({x_2}, {y_2})" ) return image.crop((x_1, y_1, x_2, y_2)) @@ -78,5 +102,5 @@ def black_and_white( ) -> Image.Image: """Convert an image to full-depth black and white""" logger = logging.getLogger(__name__) - logger.debug(f"Converting image {image.filename} to black and white") + logger.debug("Converting image to black and white") return image.convert("L")