首页 > 解决方案 > pycairo 中不支持灰度图像的透明度

问题描述

我正在尝试将重叠的透明圆圈绘制到 2d numpy 数组:

img = np.zeros((256, 256), dtype=np.uint8)
surface = cairo.ImageSurface.create_for_data(
    img, cairo.FORMAT_A8, 256, 256
)
ctx = cairo.Context(surface)

ctx.arc(128, 128, 22, 0, 2 * math.pi)
ctx.set_source_rgba(1, 1, 1, 1)
ctx.fill()

ctx.arc(128, 102, 22, 0, 2 * math.pi)
ctx.set_source_rgba(0, 0, 0, 0.5)
ctx.fill()

输出应如下所示: 在此处输入图像描述

相反,它看起来像这样:

在此处输入图像描述 .

为什么会这样?我想要的只是绘制相互叠加的透明灰度圆圈,但它似乎没有检测颜色,它只使用 alpha 值。

标签: pythoncairopycairo

解决方案


img = np.zeros((256, 256), dtype=np.uint8)
surface = cairo.ImageSurface.create_for_data(
    img, cairo.FORMAT_A8, 256, 256
)
ctx = cairo.Context(surface)

此时表面完全透明,保存为全黑PNG。

ctx.arc(128, 128, 22, 0, 2 * math.pi)
ctx.set_source_rgba(1, 1, 1, 1)
ctx.fill()

现在你用“完全不透明”填充一个圆圈(颜色分量被忽略)。这最终成为一个白色圆圈

ctx.arc(128, 102, 22, 0, 2 * math.pi)
ctx.set_source_rgba(0, 0, 0, 0.5)
ctx.fill()

在这里,您使用“半透明”绘制第二个圆圈。这最终变成黑色。已经绘制了另一个圆圈的部分是“半透明”而不是“完全不透明”,最终成为“完全不透明”,保存为 PNG 时为白色。

输出应如下所示:

因此,您不希望在第一个圆圈之外绘制第二个圆圈。为此,您需要ctx.clip().

这是一些Lua代码......

local cairo = require("lgi").cairo
local surface = cairo.ImageSurface.create(cairo.Format.A8, 256, 256)
local ctx = cairo.Context(surface)

ctx:arc(128, 128, 22, 0, 2 * math.pi)
ctx:set_source_rgba(1, 1, 1, 1)
-- Fill the circle, but do not clear the current path
ctx:fill_preserve()
-- Use the circle as a clip
ctx:clip()

ctx:arc(128, 102, 22, 0, 2 * math.pi)
ctx:set_source_rgba(0, 0, 0, 0.5)
-- Replace the default operator OVER with SOURCE:
-- Instead of drawing "ontop", just copy the source to the target
ctx:set_operator(cairo.Operator.SOURCE)
ctx:fill()

surface:write_to_png("out.png")

...产生此输出(我使用的坐标与您的代码使用的坐标相同,不知道您如何最终输出带有 X/Y 翻转的图像):

程序的输出


推荐阅读