| 92 | |
| 93 | |
| 94 | def compose_frame( |
| 95 | image: Image.Image | None, |
| 96 | frame_size: int, |
| 97 | scale: float, |
| 98 | ) -> Image.Image: |
| 99 | canvas = Image.new("RGBA", (frame_size, frame_size), (0, 0, 0, 0)) |
| 100 | if image is None: |
| 101 | return canvas |
| 102 | |
| 103 | width = max(1, int(round(image.width * scale))) |
| 104 | height = max(1, int(round(image.height * scale))) |
| 105 | resized = image.resize((width, height), Image.Resampling.NEAREST) |
| 106 | offset_x = (frame_size - width) // 2 |
| 107 | offset_y = frame_size - height |
| 108 | canvas.alpha_composite(resized, (offset_x, offset_y)) |
| 109 | return canvas |
| 110 | |
| 111 | |
| 112 | def load_anchor(path: str | None, alpha_threshold: int) -> tuple[Image.Image | None, Image.Image | None]: |