Слияние фона с прозрачным изображением в PIL - PullRequest
6 голосов
/ 31 марта 2012

У меня есть фоновое изображение png, и я хочу добавить прозрачную сетку к этому фону, но это не работает, как ожидалось.Фоновое изображение преобразуется в прозрачный в местах, где я применяю прозрачную сетку.

Я делаю:

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)

Но результат:

enter image description here

Вы можете увидеть шахматную доску, если внимательно посмотрите (используется в графических программах без фона).Прозрачные линии делают фоновый слой прозрачным в местах, где встречаются оба слоя.Но я хочу, чтобы прозрачная линия была добавлена ​​поверх фона.

Я могу решить ее с помощью:

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

, но, поскольку я использую разные цвета для разных линий, я бысделать для каждого цвета этот процесс.Если у меня было 100 цветов, мне нужно 100 слоев, что не очень хорошее решение.

Ответы [ 2 ]

11 голосов
/ 31 марта 2012

То, что вы пытаетесь сделать, это объединить сетку с фоном, и для этого вам нужно использовать Image.blend или Image.composite. Вот пример использования последнего для компоновки красных линий со случайными альфа-значениями на белом фоне:

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)

Слева направо:
[фон] [маска] [На первый план] [результат]

background mask foreground composite

(Если вы счастливы записать результат обратно на фоновое изображение, тогда вы можете использовать одну из замаскированных версий Image.paste, на что указывает Пауло Скардин в удаленном ответе.)

0 голосов
/ 26 декабря 2013

У меня были проблемы с тем, чтобы приведенные выше примеры работали хорошо. Вместо этого это сработало для меня:

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