6

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.

Brian Burns
  • 20,575
  • 8
  • 83
  • 77
Bruce
  • 1,380
  • 2
  • 13
  • 17
  • Possible duplicate of http://stackoverflow.com/questions/5324647/how-to-merge-a-transparent-png-image-with-another-image-using-pil – Charles Merriam Aug 24 '15 at 01:29

2 Answers2

11

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]

background mask foreground composite

(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.)

sngjuk
  • 927
  • 1
  • 10
  • 24
Gareth Rees
  • 64,967
  • 9
  • 133
  • 163
0

I had trouble getting the above examples to work well. Instead, this worked for me:

import numpy as np
import Image
import ImageDraw

def add_craters(image, craterization=20.0, width=256, height=256):

    foreground = Image.new('RGBA', (width, height), (0, 0, 0, 0))
    draw = ImageDraw.Draw(foreground)

    for c in range(0, craterization):
        x = np.random.randint(10, width-10)
        y = np.random.randint(10, height-10)
        radius = np.random.randint(2, 10)
        dark_color = (0, 0, 0, 128)
        draw.ellipse((x-radius, y-radius, x+radius, y+radius), fill=dark_color)

    image_new = Image.composite(foreground, image, foreground)
    return image_new
JayCrossler
  • 2,079
  • 2
  • 22
  • 22