Getting an alpha channel from text rendering
- From: Chris Seaton <chris chrisseaton com>
- To: gtk-list gnome org
- Subject: Getting an alpha channel from text rendering
- Date: Fri, 12 Aug 2005 00:40:28 +0100
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]