[cairo] Color-Tinting a surface with alpha channel

Simon Schneegans code at simonschneegans.de
Tue Dec 22 06:18:26 UTC 2020


Dear all!

I want to use Cairo to colorize / tint a RGBA Pixbuf with a given RGB 
(potentially RGBA) color. It would be great if this could be achieved 
with normal operators since rolling my own loop over all pixels is too 
slow as I am writing a GNOME Shell extension and am therefore bound to 
GJS. As Cairo.Operator.MULTIPLY uses normal OVER-alpha-blending, the 
code below does not really multiply the image with the given color. E.g. 
black semi-transparent areas will actually become tinted as well!

         // We first draw the image in normal colors with 
Cairo.Operator.OVER.
         ctx.setOperator(Cairo.Operator.OVER);
         Gdk.cairo_set_source_pixbuf(ctx, image, 0, 0);
         ctx.paint();

         const pattern = ctx.getSource();

         // Then we use Cairo.Operator.MULTIPLY to colorize the image. 
We use ctx.mask()
         // in order to maintain the alpha channel of the original image.
         ctx.setSourceRGBA(color.red / 255, color.green / 255, 
color.blue / 255, color.alpha / 255);
         ctx.setOperator(Cairo.Operator.MULTIPLY);
         ctx.mask(pattern);

If anybody knows how to do a simple result.rgba = first.rgba * 
second.rgba in Cairo, please let me know I think the difficulty boils 
down to the fact that Cairo uses pre-multiplied alpha but the use-case 
of colorizing a RGBA image seems quite common to me. I hope that ther is 
a solution I am simply not aware of.

Thank you!

Simon



More information about the cairo mailing list