我正在使用PIL(Python影像庫)。我想繪製透明的多邊形。看起來,指定包含alpha級別的填充顏色不起作用。他們的解決方法是什麼?如何用Python繪製透明多邊形?
如果使用PIL無法完成,我願意使用別的東西。
如果有多個解決方案,則應考慮性能。繪圖需要儘可能快。
我正在使用PIL(Python影像庫)。我想繪製透明的多邊形。看起來,指定包含alpha級別的填充顏色不起作用。他們的解決方法是什麼?如何用Python繪製透明多邊形?
如果使用PIL無法完成,我願意使用別的東西。
如果有多個解決方案,則應考慮性能。繪圖需要儘可能快。
我爲此使用cairo + pycairo,而且效果很好。 如果在pil中有無法在cairo中完成的操作,則可以使用python緩衝區接口在PIL和cairo之間共享圖像數據。
PIL的圖像模塊提供了一種混合方法。
創建與您的第一張相同尺寸的第二張圖像,並帶有黑色背景。繪製您的多邊形(全綵)。然後調用Image.blend傳遞兩個圖像和一個alpha級別。它返回第三個圖像,它應該有一個半透明的多邊形。
我還沒有測量性能(嘿,我甚至沒有嘗試過!),所以我不能評論它的適用性。我建議你計算一下你的性能預算,然後測量它,看它是否足夠快達到你的目的。
什麼我已經使用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數組表示的多邊形。
我不得不畫外部多邊形的輪廓,並減去內部多邊形(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
從我發現它不能直接用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()
這是枕頭,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')
這將繪製兩個三角形與兩種顏色混合重疊。這要比爲每個多邊形合成多個「圖層」快得多。
謝謝,這非常有用。我不知道你從哪裏得到這些信息 - 我沒有看到它的記錄。當使用RGB/RGBA組合以外的其他組合時,我得到了一些奇怪的行爲...... – jwd 2015-09-24 01:45:59
這與透明度無關。 – Junuxx 2012-05-20 23:10:22