2008-12-11 77 views
14

我正在使用PIL(Python影像库)。我想绘制透明的多边形。看起来,指定包含alpha级别的填充颜色不起作用。他们的解决方法是什么?如何用Python绘制透明多边形?

如果使用PIL无法完成,我愿意使用别的东西。

如果有多个解决方案,则应考虑性能。绘图需要尽可能快。

回答

2

我为此使用cairo + pycairo,而且效果很好。 如果在pil中有无法在cairo中完成的操作,则可以使用python缓冲区接口在PIL和cairo之间共享图像数据。

2

PIL的图像模块提供了一种混合方法。

创建与您的第一张相同尺寸的第二张图像,并带有黑色背景。绘制您的多边形(全彩)。然后调用Image.blend传递两个图像和一个alpha级别。它返回第三个图像,它应该有一个半透明的多边形。

我还没有测量性能(嘿,我甚至没有尝试过!),所以我不能评论它的适用性。我建议你计算一下你的性能预算,然后测量它,看它是否足够快达到你的目的。

6

什么我已经使用PIL时绘制透明图像要做的就是创建一个颜色层,不透明层上所绘制的多边形,和与基础层,以便合成它们:

color_layer = Image.new('RGBA', base_layer.size, fill_rgb) 
alpha_mask = Image.new('L', base_layer.size, 0) 
alpha_mask_draw = ImageDraw.Draw(alpha_mask) 
alpha_mask_draw.polygon(self.outline, fill=fill_alpha) 
base_layer = Image.composite(color_layer, base_layer, alpha_mask) 

使用Image.Blend时,我遇到了绘制多边形上奇怪的大纲行为问题。

这种方法的唯一问题是,绘制大量合理大小的多边形时性能不佳。更快的解决方案就像“手动”绘制图像的numpy数组表示的多边形。

-1

我不得不画外部多边形的轮廓,并减去内部多边形(GIS中的常见操作)。像使用颜色(255,255,255,0)的魅力一样工作。

image = Image.new("RGBA", (100,100)) 
drawing = ImageDraw.Draw(i) 
for index, p in enumerate(polygons): 
    if index == 0: 
     options = { 'fill': "#AA5544", 
        'outline': "#993300"} 
    else: 
     options = {'fill': (255,255,255,0)} 
    drawing.polygon(p, **options) 

buf= StringIO.StringIO() 
i.save(buf, format= 'PNG') 
# do something with buf 
+1

这与透明度无关。 – Junuxx 2012-05-20 23:10:22

1

从我发现它不能直接用PIL完成。这是PyCairo的解决方案。 Mozilla,GTX +,Mono,Inkscape和WebKit也使用开罗,所以我认为这对未来的支持是安全的。它也可以使用aggdraw来完成,这是一个可选的PIL附件。有关更多详情,请参阅我列出的来源Python版本2.7.3被使用。

来源:http://livingcode.org/2008/12/14/drawing-with-opacity.1.html

辅助文件:random_polys_util.py

MIN_ALPHA = 50 
    MAX_ALPHA = 100 

    WIDTH = 500 
    HEIGHT = 250 

    # 
    # Utilities 
    # 
    def hex2tuple(hex_color): 
     return tuple([int(hex_color[i:i+2], 16) for i in range(1,9,2)]) 

    def tuple2hex(tuple_color): 
     return "#%0.2X%0.2X%0.2X%0.2X" % tuple_color 

    def ints2floats(tuple_color): 
     return tuple([c/255.0 for c in tuple_color]) 

    def inc_point(p, dp): 
     return (p[0] + dp[0]) % WIDTH, (p[1] + dp[1]) % HEIGHT 

    def inc_triangle(t, dt): 
     return tuple([inc_point(t[i], dt[i]) for i in range(3)]) 

    def inc_color(c, dc): 
     new_c = [(c[i] + dc[i]) % 256 for i in range(3)] 
     new_a = (c[3] + dc[3]) % MAX_ALPHA 
     if new_a < MIN_ALPHA: new_a += MIN_ALPHA 
     new_c.append(new_a) 
     return tuple(new_c) 

    def draw_all(draw_fn): 
     triangle = start_t 
     color = start_c 
     for i in range(50): 
      triangle = inc_triangle(triangle, dt) 
      color = inc_color(color, dc) 
      draw_fn(triangle, color) 

    # 
    # Starting and incrementing values 
    # 
    start_c = hex2tuple('E6A20644') 
    start_t = (127, 132), (341, 171), (434, 125) 
    dt = (107, 23), (47, 73), (13, 97) 
    dc = 61, 113, 109, 41 

主文件:random_polys.py

from random_polys_util import * 

def cairo_poly(pts, clr): 
    ctx.set_source_rgba(*ints2floats(clr)) 
    ctx.move_to(*pts[-1]) 
    for pt in pts: 
     ctx.line_to(*pt) 
    ctx.close_path() 
    ctx.fill() 

def cairo_main(): 
    # Setup Cairo 
    import cairo 
    global ctx 
    surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT) 
    ctx = cairo.Context(surface) 
    # fill background white 
    cairo_poly(((0,0),(WIDTH,0),(WIDTH,HEIGHT),(0,HEIGHT)),(255,255,255,255)) 
    draw_all(cairo_poly) 
    surface.write_to_png('cairo_example.png') 

def main(): 
    cairo_main() 

if __name__ == "__main__": 
    main() 
28

这是枕头,PIL的更维持叉。 http://pillow.readthedocs.org/

如果要绘制透明的多边形,相对于彼此,基本图像必须是RGB类型,而不是RGBA,并且ImageDraw必须是RGBA类型。例如:

from PIL import Image, ImageDraw 

img = Image.new('RGB', (100, 100)) 
drw = ImageDraw.Draw(img, 'RGBA') 
drw.polygon([(50, 0), (100, 100), (0, 100)], (255, 0, 0, 125)) 
drw.polygon([(50,100), (100, 0), (0, 0)], (0, 255, 0, 125)) 
del drw 

img.save('out.png', 'PNG') 

这将绘制两个三角形与两种颜色混合重叠。这要比为每个多边形合成多个“图层”快得多。

+0

谢谢,这非常有用。我不知道你从哪里得到这些信息 - 我没有看到它的记录。当使用RGB/RGBA组合以外的其他组合时,我得到了一些奇怪的行为...... – jwd 2015-09-24 01:45:59