pythoncairogdkgdkpixbufgobject-introspection

How to render text on a GdkPixbuf.Pixbuf


I'm trying to add text to a Pixbuf, using Python and Gdk 3.

I've been searching the web for info about this topic for hours, and it looks like I'll need to create a cairo context from the pixbuf. Unfortunately, I have zero experience with cairo, but I've been able to put together this piece of code:

from gi.repository import Gdk

def put_text(pixbuf, text, x, y):
    #create a Gdk.Window
    window_attr= Gdk.WindowAttr()
    window_attr.width= pixbuf.get_width()
    window_attr.height= pixbuf.get_height()
    window_attr.window_type= Gdk.WindowType.OFFSCREEN
    #~ window_attr.window_type= Gdk.WindowType.TEMP
    window_attr.redirect= True
    #~ window_attr.redirect= False
    window= Gdk.Window(None, window_attr, Gdk.WindowAttributesType(0))

    #make a cairo context from the window
    context= Gdk.cairo_create(window)
    Gdk.cairo_set_source_pixbuf(context, pixbuf, 0, 0)

    #render text
    context.move_to(x, y)
    context.set_font_size(15)
    context.show_text(text)

    #get the resulting pixbuf
    surface= context.get_target()
    result= Gdk.pixbuf_get_from_surface(surface, 0, 0, surface.get_width(), surface.get_height())

    #~ window.destroy()
    return result

Which at least doesn't cause my program to crash. However, the pixbuf it produces is entirely transparent. Can anyone tell me what I'm doing wrong or if there's a better way to do this?


Solution

  • I finally managed to produce working code. Apparently using from gi.repository import cairo was a big mistake.

    from gi.repository import Gdk
    import cairo
    
    def put_text(pixbuf, text, x, y):
        surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, pixbuf.get_width(), pixbuf.get_height())
        context = cairo.Context(surface)
    
        Gdk.cairo_set_source_pixbuf(context, pixbuf, 0, 0)
        context.paint() #paint the pixbuf
    
        #add the text
        fontsize= 20
        context.move_to(x, y+fontsize)
        context.set_font_size(fontsize)
        context.set_source_rgba(0,0,0,1)
        context.show_text(text)
    
        #get the resulting pixbuf
        surface= context.get_target()
        pixbuf= Gdk.pixbuf_get_from_surface(surface, 0, 0, surface.get_width(), surface.get_height())
    
        return pixbuf