Как объединить два объекта ImageSurface в один - PullRequest
0 голосов
/ 27 апреля 2020

На основании этого ответа у меня есть два cairo.ImageSurface объекта, сгенерированных во время выполнения. Оба RGBA одинаковых размеров. Я хотел бы объединить / сложить их перед сохранением на диск:

new_surface = surface1 + surface2 # pseudo-code

(Как) это работает?

Ответы [ 3 ]

1 голос
/ 29 апреля 2020

(Как) это работает?

Вы создаете новую поверхность изображения Каира большего размера и рисуете свои исходные изображения на этой поверхности.

Непроверенное псевдо -код (используя 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);
1 голос
/ 27 апреля 2020

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 () (выберите интересную сумму) c для вашего случая)

0 голосов
/ 07 мая 2020

Прохождение PIL (подушки) на самом деле дает довольно приличные и относительно эффективные результаты. У меня работает следующее:

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