python - 如何使用 PIL 在半透明背景上创建重叠的半透明形状
问题描述
我正在尝试创建在透明背景上绘制的半透明形状的图像。由于某种原因,这些形状并没有保持透明,而是完全覆盖了它们下面的形状。我的代码:
from PIL import Image, ImageDraw
img = Image.new("RGBA", (256, 256), (255,0,0,127))
drawing = ImageDraw.Draw(img, "RGBA")
drawing.ellipse((127-79, 127 - 63, 127 + 47, 127 + 63), fill=(0, 255, 0, 63), outline=(0, 255, 0, 255))
drawing.ellipse((127-47, 127 - 63, 127 + 79, 127 + 63), fill=(0, 0, 255, 63), outline=(0, 0, 255, 255))
img.save("foo.png", "png")
我希望结果看起来像(除了背景不透明):
但它看起来像:
当我尝试将其保存为 GIF 时img.save("foo.gif", "gif")
,结果更糟。圆圈是实心的,轮廓和填充之间没有区别。
解决方案
正如我在评论中提到的,ImageDraw.Draw
不进行混合——无论绘制什么都会替换之前存在的任何像素。要获得您想要的效果,需要分两步进行绘制。椭圆必须首先在空白透明背景上绘制,然后必须与当前图像 ( ) 进行alpha 合成bg_img
以保持透明度。
在下面的代码中,这已在可重用功能中实现:
from PIL import Image, ImageDraw
def draw_transp_ellipse(img, xy, **kwargs):
""" Draws an ellipse inside the given bounding box onto given image.
Supports transparent colors
"""
transp = Image.new('RGBA', img.size, (0,0,0,0)) # Temp drawing image.
draw = ImageDraw.Draw(transp, "RGBA")
draw.ellipse(xy, **kwargs)
# Alpha composite two images together and replace first with result.
img.paste(Image.alpha_composite(img, transp))
bg_img = Image.new("RGBA", (256, 256), (255, 0, 0, 127)) # Semitransparent background.
draw_transp_ellipse(bg_img, (127-79, 127-63, 127+47, 127+63),
fill=(0, 255, 0, 63), outline=(0, 255, 0, 255))
draw_transp_ellipse(bg_img, (127-47, 127-63, 127+79, 127+63),
fill=(0, 0, 255, 63), outline=(0, 0, 255, 255))
bg_img.save("foo.png")
这是它在我的图像文件编辑器应用程序中创建的图像,它使用棋盘图案呈现图像的半透明部分。正如您所看到的,不透明的轮廓是唯一不是的部分。
推荐阅读
- angular5 - 用于创建和编辑数据 Angular4 示例的相同模板驱动表单
- jpa - 主键自动生成
- apache-spark - 将 SQL 查询转换为 Spark Dataframe 结构化数据处理
- haskell - 是否有类似 `fromNewtype 之类的操作的简写。F 。toNewtype`?
- mysql - 自动装配时sqlSession为空(mybatis3,Spring5)
- pac - 滤波脑电时如何设置低带通滤波器的长度(秒)?
- kubernetes - Kubernetes 无法在集群范围内创建命名空间
- android - 如何在android中快速响应接收来自socket的数据[关闭]
- c# - 表单面板调整大小
- python - 意外影响结果的执行顺序