(self, ctx: PipelineContext)
| 466 | ctx.update_buffer(buffer).save_buffer(self.name()).success() |
| 467 | |
| 468 | def process2(self, ctx: PipelineContext): |
| 469 | shadow_color = ctx.getcolor("shadow_color", (0, 0, 0, 255)) |
| 470 | # 即使radius设为30,为了视觉效果彻底消失,建议不要设太小 |
| 471 | shadow_radius = ctx.getint("shadow_radius", 30) |
| 472 | buffer = [] |
| 473 | for img in ctx.get_buffer(): |
| 474 | if img.mode != 'RGBA': |
| 475 | original_img = img.convert('RGBA') |
| 476 | else: |
| 477 | original_img = img |
| 478 | |
| 479 | w, h = original_img.size |
| 480 | if shadow_radius <= 0: |
| 481 | buffer.append(img) |
| 482 | continue |
| 483 | # --- 优化点 1: 扩大画布范围 (3-Sigma 原则) --- |
| 484 | # 高斯模糊的尾部很长,只有预留 3倍半径 的空间,边缘像素才能自然衰减到 0 (完全透明) |
| 485 | # 如果只留 1倍,最外圈一定会被切断,留下一圈灰色的“硬边” |
| 486 | padding = shadow_radius * 3 |
| 487 | |
| 488 | full_width = w + padding * 2 |
| 489 | full_height = h + padding * 2 |
| 490 | |
| 491 | # 创建底图 |
| 492 | background = Image.new('RGBA', (full_width, full_height), (0, 0, 0, 0)) |
| 493 | # --- 优化点 2: 制作纯色剪影 --- |
| 494 | shadow_layer = Image.new('RGBA', (w, h), shadow_color) |
| 495 | shadow_layer.putalpha(original_img.getchannel('A')) |
| 496 | |
| 497 | # 将剪影贴入底图中心 |
| 498 | background.paste(shadow_layer, (padding, padding)) |
| 499 | # --- 优化点 3: 高斯模糊 --- |
| 500 | shadow_in_process = background.filter(ImageFilter.GaussianBlur(shadow_radius)) |
| 501 | # --- 优化点 4: Alpha 通道非线性衰减 (缓动关键) --- |
| 502 | # 这一步是为了解决“灰色残留”并让阴影更有层次感。 |
| 503 | # 我们提取阴影的 Alpha 通道,对其进行 指数运算。 |
| 504 | # 作用:让原本很淡的边缘(如 alpha=10)迅速变成 0,而原本浓的地方保持保留。 |
| 505 | # 这是清理 "脏边缘" 最有效的手段。 |
| 506 | r, g, b, a = shadow_in_process.split() |
| 507 | |
| 508 | # lambda x: int(x * ((x / 255.0) ** 0.5)) -> 这种会让阴影更丰满 |
| 509 | # lambda x: int(x * ((x / 255.0) ** 2)) -> 这种会让边缘收得更快(Fade Out),彻底消除灰边 |
| 510 | |
| 511 | # 这里使用平方级衰减 (Quad Ease In),强力清洗边缘 |
| 512 | a = a.point(lambda p: int(p * (p / 255.0) * 1.2)) |
| 513 | |
| 514 | shadow_in_process.putalpha(a) |
| 515 | # 组合原图 |
| 516 | shadow_in_process.paste(original_img, (padding, padding), mask=original_img) |
| 517 | |
| 518 | # (可选) 如果你不希望图片尺寸暴增,可以在这里 crop 回去, |
| 519 | # 但既然要阴影,通常就需要保留扩大的尺寸。 |
| 520 | buffer.append(shadow_in_process) |
| 521 | ctx.update_buffer(buffer).save_buffer(self.name()).success() |
| 522 | |
| 523 | def process3(self, ctx: PipelineContext): |
| 524 | # 阴影颜色(固定灰色) |
no test coverage detected