问题描述
我正在尝试创建具有在透明背景上绘制的半透明形状的图像.由于某种原因而不是保持透明,这些形状完全覆盖了它们下面的形状.我的代码:
I'm trying to create image with semitransparent shapes drawn on transparent background. For some reason instead of staying transparent, the shapes are completely covering those beneath them. My code:
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")
我希望结果看起来像(背景不是透明的除外):
,但看起来像:
I would expect the result to look something like (except for background not being transparent):
but it looks like:
当我尝试使用img.save("foo.gif", "gif")
将其另存为GIF时,结果甚至更糟.圆圈是实心的,轮廓和填充之间没有区别.
When I try to save it as GIF with img.save("foo.gif", "gif")
, result is even worse. Circles are solid, no difference between outline and fill.
推荐答案
正如我在评论中所提到的,ImageDraw.Draw
不会进行混合-绘制的内容将替换以前存在的任何像素.要获得所需的效果,需要分两步进行绘制.椭圆必须首先在空白的透明背景上绘制,然后必须为由alpha合成与当前图像(bg_img
)保持透明.
As I mentioned in a comment, ImageDraw.Draw
doesn't do blending—whatever is drawn replaces whatever pixels that were there previously. To get the effect you want requires drawing things in a two-step process. The ellipse must first be drawn on a blank transparent background, and then that must be alpha-composited with current image (bg_img
) to preserve transparency.
在下面的代码中,a已在可重用功能中实现:
In the code below this a has been implementing in re-usable function:
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")
这是在我的图像文件编辑器应用程序中查看的它创建的图像,该图像使用棋盘图案渲染图像的半透明部分.如您所见,不透明的轮廓不是唯一的部分.
This is the image it created viewed in my image file editor app which renders semi-transparent portions of images with a checker-board pattern. As you can see the opaque outlines are the only part that isn't.
这篇关于如何使用PIL在半透明背景上创建重叠的半透明形状的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!