天天看點

由GdkPixmap得到透明的GdkPixbuf

由GdkPixmap得到透明的GdkPixbuf

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:

                }

                pixels += pixbuf->rowstride;

        }

        return;

}

使用方法:

把黑色設定為透明色:gdk_pixbuf_transparent(pixbuf, 0x00000000); 把白色設定為透明色:gdk_pixbuf_transparent(pixbuf, 0xFFFFFF00); 把紅色設定為透明色:gdk_pixbuf_transparent(pixbuf, 0xFF000000); 把綠色設定為透明色:gdk_pixbuf_transparent(pixbuf, 0x00FF0000); 把藍色設定為透明色:gdk_pixbuf_transparent(pixbuf, 0x0000FF00);