如何将两个 ImageSurface 对象合并为一个
How to combine two ImageSurface objects into one
基于this answer,我在运行时生成了两个cairo.ImageSurface
对象。两者都是相同维度的 RGBA。我想在将它们保存到磁盘之前组合/堆叠它们:
new_surface = surface1 + surface2 # pseudo-code
(如何)这是有效的?
Cairo 允许您将 ImageSurface 转换为 Numpy 数组:
import numpy
import cairo
width, height = 255, 255
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
buf = surface.get_data()
data = numpy.ndarray(shape=(width, height),
dtype=numpy.uint32,
buffer=buf)
转换两个 ImageSurface 后,您可以使用“+”或 numpy.add() 对它们求和(根据您的情况选择求和函数)
(How) does this work?
您创建一个更大尺寸的新 cairo 图像表面并将您的原始图像绘制到该表面。
未经测试的伪代码(使用 C API 而不是 pycairo):
cairo_surface_t *merged = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height * 2);
cairo_t *cr = cairo_create(merged);
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
cairo_set_source_surface(cr, surface1, 0, 0);
cairo_paint(cr);
cairo_set_source_surface(cr, surface2, 0, height);
cairo_rectangle(cr, 0, height, width, height);
cairo_fill(cr);
cairo_destroy(cr);
通过 PIL(pillow)实际上给出了相当不错且相对高效的结果。以下对我有用:
import cairo
from PIL import Image
def surface_to_pil(surface):
return Image.frombuffer(
mode = 'RGBA',
size = (surface.get_width(), surface.get_height()),
data = surface.get_data(),
)
def pil_to_surface(image):
return cairo.ImageSurface.create_for_data(
bytearray(image.tobytes('raw', 'BGRa')),
cairo.FORMAT_ARGB32,
image.width,
image.height,
)
def add_surfaces(a, b):
assert a.get_width() == b.get_width() and a.get_height() == b.get_height()
result_pil = Image.new(
mode = 'RGBA',
size = (a.get_width(), a.get_height()),
color = (0.0, 0.0, 0.0, 0.0),
)
for surface in (a, b):
surface_pil = surface_to_pil(surface)
result_pil.paste(im = surface_pil, mask = surface_pil)
return pil_to_surface(result_pil)
new_surface = add_surfaces(surface1, surface2)
基于this answer,我在运行时生成了两个cairo.ImageSurface
对象。两者都是相同维度的 RGBA。我想在将它们保存到磁盘之前组合/堆叠它们:
new_surface = surface1 + surface2 # pseudo-code
(如何)这是有效的?
Cairo 允许您将 ImageSurface 转换为 Numpy 数组:
import numpy
import cairo
width, height = 255, 255
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
buf = surface.get_data()
data = numpy.ndarray(shape=(width, height),
dtype=numpy.uint32,
buffer=buf)
转换两个 ImageSurface 后,您可以使用“+”或 numpy.add() 对它们求和(根据您的情况选择求和函数)
(How) does this work?
您创建一个更大尺寸的新 cairo 图像表面并将您的原始图像绘制到该表面。
未经测试的伪代码(使用 C API 而不是 pycairo):
cairo_surface_t *merged = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height * 2);
cairo_t *cr = cairo_create(merged);
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
cairo_set_source_surface(cr, surface1, 0, 0);
cairo_paint(cr);
cairo_set_source_surface(cr, surface2, 0, height);
cairo_rectangle(cr, 0, height, width, height);
cairo_fill(cr);
cairo_destroy(cr);
通过 PIL(pillow)实际上给出了相当不错且相对高效的结果。以下对我有用:
import cairo
from PIL import Image
def surface_to_pil(surface):
return Image.frombuffer(
mode = 'RGBA',
size = (surface.get_width(), surface.get_height()),
data = surface.get_data(),
)
def pil_to_surface(image):
return cairo.ImageSurface.create_for_data(
bytearray(image.tobytes('raw', 'BGRa')),
cairo.FORMAT_ARGB32,
image.width,
image.height,
)
def add_surfaces(a, b):
assert a.get_width() == b.get_width() and a.get_height() == b.get_height()
result_pil = Image.new(
mode = 'RGBA',
size = (a.get_width(), a.get_height()),
color = (0.0, 0.0, 0.0, 0.0),
)
for surface in (a, b):
surface_pil = surface_to_pil(surface)
result_pil.paste(im = surface_pil, mask = surface_pil)
return pil_to_surface(result_pil)
new_surface = add_surfaces(surface1, surface2)