Getting an alpha channel from text rendering



Hello everyone,

I need to render text into a pixbuf, getting the alpha channel of the rendered
text as well as just the colour.

I can't see any way to do this simply, as pixmaps don't have an alpha channel.
You can blend into them, but they don't store alpha. When I render a Pango
layout into one I get the text blended onto the background colour.

Currently I'm rendering into one pixmap with colour, then rendering into
another with black and white and then copying those black and white values into
my pixbuf's alpha channel, and the colour I'm just copying straight across.

I've included my code below as it's very simple and I think quite readable.

Is there a better way to do this?

Ideally I'd like the same effect as if I'd rendered using SDL_ttf with the
blended function, if that means anything to anyone.

My results are a little messy due I think to sub pixel anti aliasing, and
rendering everything twice is not ideal. I don't want to go too low level with
Pango if that can be avoided.

Thanks for your time.

Chris

Texture::Texture(Glib::ustring text, Colour colour, int size)
{
    /*
        This is a little complicated because I can't see a way to render text
        with an alpha channel.

        We render twice, once in colour and then again in black and white. The
        latter is then used as the alpha channel when creating a finished
        pixbuf with alpha channel.
    */

    // Create Pango context and layout

    Glib::RefPtr<Pango::Context> context = Glib::wrap(gdk_pango_context_get());
    g_assert(context);

    Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
    g_assert(layout);

    // Measure

    Glib::ustring basic_text = "<span font_desc=\"sans 20\">" + text + "</span>";

    layout->set_markup(basic_text);

    int width;
    int height;

    layout->get_pixel_size(width, height);

    // Render the beauty pass

    layout->set_markup("<span foreground=\"black\" background=\"black\">" + basic_text + "</span>");

    Glib::RefPtr<Gdk::Pixmap> beauty_pass_pixmap = Gdk::Pixmap::create(Glib::RefPtr<Gdk::Drawable>(NULL), width, height, 24);
    g_assert(beauty_pass_pixmap);

    beauty_pass_pixmap->draw_layout(Gdk::GC::create(beauty_pass_pixmap), 0, 0, layout);

    Glib::RefPtr<Gdk::Pixbuf> beauty_pass_pixbuf = Gdk::Pixbuf::create(Glib::RefPtr<Gdk::Drawable>(beauty_pass_pixmap), beauty_pass_pixmap->get_colormap(), 0, 0, 0, 0, width, height);
    g_assert(beauty_pass_pixbuf);

    // Render the mask pass

    layout->set_markup("<span foreground=\"white\" background=\"black\">" + basic_text + "</span>");

    Glib::RefPtr<Gdk::Pixmap> mask_pass_pixmap = Gdk::Pixmap::create(Glib::RefPtr<Gdk::Drawable>(NULL), width, height, 24);
    g_assert(mask_pass_pixmap);

    mask_pass_pixmap->draw_layout(Gdk::GC::create(mask_pass_pixmap), 0, 0, layout);

    Glib::RefPtr<Gdk::Pixbuf> mask_pass_pixbuf = Gdk::Pixbuf::create(Glib::RefPtr<Gdk::Drawable>(mask_pass_pixmap), mask_pass_pixmap->get_colormap(), 0, 0, 0, 0, width, height);
    g_assert(mask_pass_pixbuf);

    // Create a pixbuf to contain the composite of the two passes

    Glib::RefPtr<Gdk::Pixbuf> pixbuf = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true, 8, width, height);
    g_assert(pixbuf);

    // Copy in colour from the beauty pass and alpha from the mask pass

    for (int y = 0; y < height; y++)
    {
        for (int x = 0; x < width; x++)
        {
            guint8 red;
            guint8 green;
            guint8 blue;

            get_pixel(beauty_pass_pixbuf, x, y, &red, &green, &blue, NULL);

            guint8 alpha_red;
            guint8 alpha_green;
            guint8 alpha_blue;

            get_pixel(mask_pass_pixbuf, x, y, &alpha_red, &alpha_green, &alpha_blue, NULL);

            guint8 alpha = (alpha_red + alpha_green + alpha_blue) / 3;

            set_pixel(pixbuf, x, y, red, green, blue, alpha);
        }
    }

    // Create the texture from that

    create(pixbuf);
}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]