Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Merging background with transparent image in PIL

I have a png image as background and I want to add a transparent mesh to this background but this doesn't work as expected. The background image is converted to transparent on places where I apply transparent mesh.

I am doing:

from PIL import Image, ImageDraw

map_background = Image.open(MAP_BACKGROUND_FILE).convert('RGBA')
map_mesh = Image.new('RGBA', (width, height), (0, 0, 0, 0))
draw = ImageDraw.Draw(map_mesh)

# Create mesh using: draw.line([...], fill=(255, 255, 255, 50), width=1)
...

map_background.paste(map_mesh, (0, 0), map_mesh)

But the result is:

enter image description here

You can see a chessboard pattern if you look carefully (used in graphics programs as no background). Transparent lines makes the background layer transparent too in places where both layers met. But I only want the transparent line to be added on top of the background.

I can solve it with:

map_background.paste((255,255,255), (0, 0), map_mesh)

but as I use different colors for different lines, I would have to make for every color this process. If I had 100 colors, then I need 100 layers what is not very good solution.

like image 580
Bruce Avatar asked Mar 30 '12 21:03

Bruce


1 Answers

What you are trying to do is to composite the grid onto the background, and for that you need to use Image.blend or Image.composite. Here's an example using the latter to composite red lines with random alpha values onto a white background:

import Image, ImageDraw, random
background = Image.new('RGB', (100, 100), (255, 255, 255))
foreground = Image.new('RGB', (100, 100), (255, 0, 0))
mask = Image.new('L', (100, 100), 0)
draw = ImageDraw.Draw(mask)
for i in range(5, 100, 10):
    draw.line((i, 0, i, 100), fill=random.randrange(256))
    draw.line((0, i, 100, i), fill=random.randrange(256))
result = Image.composite(background, foreground, mask)

From left to right:
  [background]        [mask]          [foreground]          [result]

backgroundmaskforegroundcomposite

(If you are happy to write the result back to the background image, then you can use one of the masked versions of Image.paste, as pointed out by Paulo Scardine in a deleted answer.)

like image 144
Gareth Rees Avatar answered Oct 17 '22 01:10

Gareth Rees