分类: LINUX
2009-08-23 08:23:55
文章出处:http://www.limodev.cn/blog
作者联系方式:李先静
GdkPixmap 是GdkDrawable的子类。GdkDrawable和Win32下的DC(DeviceContext)有点类似,你可以在上面画直线、画圆或者在 上面贴图片。DC有很多不同的子类,最常见的有内存DC,打印机DC,屏幕DC。同样,GdkDrawable也有很多子类,非要和Win32对应起来的 话,GdkPixmap的地位和内存DC差不多。
GdkPixbuf的功能近似于位图(bitmap),但一般仅限于在内存使用中,没有定义特定的存储格式。可以把任意格式的图片文件加裁到一个 GdkPixbuf中; 可以把GdkPixbuf贴到GdkDrawable任意子类的对象上; 也可以把GdkDrawable任意子类的对象转换成GdkPixbuf对象,然后把GdkPixbuf对象存为指定格式的图片文件。
GTK+提供了几个函数在这两者之间转换:
gdk_draw_pixbuf 把GdkPixbuf对象贴到GdkDrawable对象上。
gdk_pixbuf_get_from_drawable 从GdkDrawable对象中得到GdkPixbuf对象。
GdkPixbuf是GdkDrawable的子类,这两个函数自然也适用于GdkPixmap。
最近遇到一个问题,尽管我指明要透明的GdkPixbuf,通过gdk_pixbuf_get_from_drawable得到的GdkPixbuf仍然是不透明的。
GdkPixbuf有一个has_alpha属性,它是控制GdkPixbuf透明与否的第一关。只能在创建时设置它(gdk_pixbuf_new),对于已经存在的GdkPixbuf对象,不能再修改它的has_alpha属性。
对于透明的GdkPixbuf,每个像素在内存中占四个字节,也即R(红)、G(绿)、B(蓝)三基色各占一个字节,alpha占一个字节。利用 alpha的值可以实现(半)透明效果,alpha的值为0则完全透明,alpha的值为255则完全不透明,中间的值为半透明。
我发现通过gdk_pixbuf_get_from_drawable得到的GdkPixbuf是完全不透明的,从内存中的值可以看到每个像素的 alpha值都为255,而且没有任何参数可以控制gdk_pixbuf_get_from_drawable处理透明问题的行为。
把GTK+提供的相关函数翻了个遍,也没有找到把GdkPixbuf转换为透明效果GdkPixbuf的函数,最后只好自己写了一个,它的缺点是只能指定一种透明色,所有为这种透明色的pixel都是作透明处理。不过,这对正常应用没有什么影响。
void
gdk_pixbuf_transparent (GdkPixbuf *pixbuf, guint32 pixel)
{
guchar *pixels;
guint r, g, b, a;
guchar *p;
guint w, h;
g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
if (pixbuf->width == 0 || pixbuf->height == 0)
return;
pixels = pixbuf->pixels;
r = (pixel & 0xff000000) >> 24;
g = (pixel & 0x00ff0000) >> 16;
b = (pixel & 0x0000ff00) >> 8;
a = (pixel & 0x000000ff);
h = pixbuf->height;
while (h--)
{
w = pixbuf->width;
p = pixels;
switch (pixbuf->n_channels)
{
case 4:
while (w--)
{
if(p[0] == r && p[1] == g && p[2] == b)
{
p[3] = a;
}
p += 4;
}
break;
default:
break;
}
pixels += pixbuf->rowstride;
}
return;
}
使用方法:
把黑色设置为透明色:gdk_pixbuf_transparent(pixbuf, 0×00000000);
把白色设置为透明色:gdk_pixbuf_transparent(pixbuf, 0xFFFFFF00);
把红色设置为透明色:gdk_pixbuf_transparent(pixbuf, 0xFF000000);
把绿色设置为透明色:gdk_pixbuf_transparent(pixbuf, 0×00FF0000);
把蓝色设置为透明色:gdk_pixbuf_transparent(pixbuf, 0×0000FF00);