(self, ctx: PipelineContext)
| 28 | |
| 29 | class AlignmentMerger(Merger): |
| 30 | def process(self, ctx: PipelineContext): |
| 31 | buffer: List[Image] = ctx.get_buffer() |
| 32 | horizontal_alignment = ctx.getenum("horizontal_alignment", Alignment.CENTER, Alignment) |
| 33 | vertical_alignment = ctx.getenum("vertical_alignment", Alignment.CENTER, Alignment) |
| 34 | background: tuple = ctx.getcolor("background", (255, 255, 255, 0)) # 默认透明 |
| 35 | offsets = json.loads(ctx.get("offsets", "[]")) |
| 36 | weights = json.loads(ctx.get("weights", "[]")) |
| 37 | |
| 38 | if not buffer: |
| 39 | return |
| 40 | # 计算画布大小(所有图片的最大宽高) |
| 41 | max_width = max(img.width for img in buffer) |
| 42 | max_height = max(img.height for img in buffer) |
| 43 | # 创建画布 |
| 44 | canvas = Image.new("RGBA", (max_width, max_height), background) |
| 45 | # buffer 重排序 |
| 46 | if weights: |
| 47 | missing_count = len(buffer) - len(weights) |
| 48 | weights = weights + [0] * missing_count |
| 49 | combined = zip(weights, buffer) |
| 50 | sorted_combined = sorted(combined, key=lambda x: x[0], reverse=False) |
| 51 | buffer = [item for _, item in sorted_combined] |
| 52 | |
| 53 | # 遍历所有图片进行合并 |
| 54 | for i, img in enumerate(buffer): |
| 55 | # 获取偏移量,索引超出时默认为 (0, 0) |
| 56 | offset_x, offset_y = offsets[i] if i < len(offsets) else (0, 0) |
| 57 | offset_x, offset_y = -offset_x, -offset_y |
| 58 | # 处理水平对齐 |
| 59 | img_x = _calc_offset(img.width, max_width, horizontal_alignment) |
| 60 | # 处理垂直对齐 |
| 61 | img_y = _calc_offset(img.height, max_height, vertical_alignment) |
| 62 | # 处理偏移量 |
| 63 | img_x += offset_x |
| 64 | img_y += offset_y |
| 65 | # 确保图片是 RGBA 模式以正确处理透明度 |
| 66 | paste_img = img if img.mode == 'RGBA' else img.convert('RGBA') |
| 67 | # 粘贴图片到画布(使用 alpha 通道作为蒙版) |
| 68 | canvas.paste(paste_img, (img_x, img_y), paste_img) |
| 69 | ctx.update_buffer([canvas]).save_buffer(self.name()).success() |
| 70 | |
| 71 | def name(self) -> str: |
| 72 | return "alignment" |
nothing calls this directly
no test coverage detected