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:
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.
Advertisement
Answer
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.
In the code below this 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.