(src: Path, settings: ConvertSettings)
| 75 | |
| 76 | |
| 77 | def load_source_frames(src: Path, settings: ConvertSettings) -> tuple[list[Image.Image], list[int], int]: |
| 78 | img = Image.open(src) |
| 79 | all_frames = [frame.copy() for frame in ImageSequence.Iterator(img)] |
| 80 | total_frames = len(all_frames) |
| 81 | if not all_frames: |
| 82 | raise ValueError("No image frames found.") |
| 83 | |
| 84 | start = clamp(settings.frame_start, 0, total_frames - 1) |
| 85 | end = settings.frame_end if settings.frame_end > 0 else total_frames - 1 |
| 86 | end = clamp(end, start, total_frames - 1) |
| 87 | skip = max(1, settings.frame_skip) |
| 88 | |
| 89 | selected = all_frames[start : end + 1 : skip][: max(1, settings.max_gif_frames)] |
| 90 | frames: list[Image.Image] = [] |
| 91 | durations: list[int] = [] |
| 92 | for frame in selected: |
| 93 | durations.append(max(settings.min_frame_ms, int(frame.info.get("duration", 100)))) |
| 94 | frames.append(frame.convert("RGBA").copy()) |
| 95 | return frames, durations, total_frames |
| 96 | |
| 97 | |
| 98 | def reduce_points_evenly(points: list[tuple[int, int, int]], max_points: int) -> list[tuple[int, int, int]]: |
no test coverage detected