Source code for betty.image
"""
Manipulate images.
"""
from typing import TypeAlias
import math
from PIL.Image import Image
OneDimensionalSize: TypeAlias = tuple[int, None] | tuple[None, int]
TwoDimensionalSize: TypeAlias = tuple[int, int]
Size: TypeAlias = OneDimensionalSize | TwoDimensionalSize
[docs]
def resize_cover(original_image: Image, cover_size: Size) -> Image:
"""
Resize an image to cover an area.
"""
cover_width, cover_height = cover_size
ratio = max(
cover_width / original_image.width if cover_width is not None else 0,
cover_height / original_image.height if cover_height is not None else 0,
)
resize_width = (
math.ceil(original_image.width * ratio) if cover_width else original_image.width
)
resize_height = (
math.ceil(original_image.height * ratio)
if cover_height
else original_image.height
)
cover_image = original_image.resize((resize_width, resize_height))
if cover_width is not None and cover_height is not None:
cover_image = resize_crop(cover_image, (cover_width, cover_height))
cover_image.format = original_image.format
return cover_image
[docs]
def resize_crop(original_image: Image, crop_size: TwoDimensionalSize) -> Image:
"""
Resize an image by cropping it.
"""
crop_width, crop_height = crop_size
left = math.ceil((original_image.width - crop_width) / 2)
top = math.ceil((original_image.height - crop_height) / 2)
right = left + crop_width
bottom = top + crop_height
crop_image = original_image.crop((left - 1, top - 1, right - 1, bottom - 1))
crop_image.format = original_image.format
return crop_image