2010-04-30 31 views
0

我有一個C++程序,其中創建了一個gdk-pixbuf。我想輸出它作爲一個圖像,所以我打電話gdk_pixbuf_save_to_stream(pixbuf,stream,type,NULL,&err,NULL)。當「type」是png或tiff時,這可以正常工作,但使用jpeg或bmp只會產生黑色方塊。原pixbuf由黑透明(和gdk_pixbuf_get_has_alpha返回true),所以我猜測問題是與alpha蒙版。如何刪除(或應用)gdk-pixbuf上的透明度?

GdkPixbuf有一個函數來添加一個alpha通道,但我看不到一個再次移除它,或者(它可能是一樣好)來反轉它。

有沒有簡單的方法讓jpeg和bmp格式正常工作?

(我應該說我很新,像這樣適當的編程。)

+0

不能確定'GDK-pixbuf',但你可能想嘗試'libcairo ',這通常基於'gdk-pixbuf',並具有所有這些jpeg,bmp,...相關的東西例程。 – 2010-04-30 14:16:13

+0

謝謝,但通過文檔掃描不會顯示_saving_到jpeg&c的任何函數,僅用於從它們導入。 – 2010-04-30 20:02:21

回答

2

JPEG沒有alpha通道的任何概念或透明度可言。在轉換爲JPEG期間,alpha通道被剝離。 BMP有相同的限制。

由於透明度對您很重要,您的程序應堅持生成PNG。

只要你在標題中提出的問題,刪除一個alpha通道可以手動完成。訣竅是瞭解GdkPixbuf中的數據是如何存儲的。當具有alpha通道(也稱爲RGBA)的RGB pixbuf時,像素將存儲爲32位值:4個字節,每種顏色一個字節,第四個爲alpha通道。 RGB pixbufs存儲爲24位值,每種顏色一個字節。

因此,如果您創建一個臨時字節緩衝區並複製每個RGBA像素的前三個字節並丟棄第四個像素,則該臨時緩衝區將爲純RGB。爲了說明它:

[R] [G] [B] [A] [R] [G] [B] [A] ... => [R] [G] [B] [R ] [G] [B] ...

請注意,您必須打包臨時緩衝區;在[B]字節和下一個[R]字節之間沒有備用字節。

然後,您通過將此RGB緩衝區交給您創建一個新的GdkPixbuf,並刪除了Alpha通道。

請參閱gdk_pixbuf_get_pixels()來訪問RGBA緩衝區和gdk_pixbuf_new_from_data()來創建RGB pixbuf。有關如何將打包數據存儲在GdkPixbuf中的更多討論,請參閱here

+0

你要去考古徽章!我完全忘記了這個問題。謝謝你的回答 - 非常清楚。當我回到這個項目時,我會記住這一點。 – 2012-05-23 07:32:35

-1

這是(相當低效和醜陋)的Vala應用程序,從圖像中刪除透明度並將其保存爲指定的格式。注意:在gdk_pixbuf_new_from_data()的vala綁定中存在一個小錯誤,導致生成的圖像損壞。我會盡快解決這個問題,但這是卑賤的演示目的,現在(除了問題是關於C++):

public static int main (string[] args) { 
     if (args.length < 4) { 
      print ("Usage: %s SOURCE DESTINATION FORMAT\n", args[0]); 
      return -1; 
     } 

     var src_path = args[1]; 
     var destination_path = args[2]; 
     var dest_type = args[3]; 

     var pixbuf = new Gdk.Pixbuf.from_file_at_scale (src_path, 48, 48, false); 

     // Remove alpha channel 
     if (pixbuf.get_has_alpha() && pixbuf.get_n_channels() == 4 && pixbuf.get_bits_per_sample() == 8) { 
      var width = pixbuf.get_width(); 
      var height = pixbuf.get_height(); 
      var rowstride = pixbuf.get_rowstride(); 
      unowned uint8[] orig_pixels = pixbuf.get_pixels(); 
      var pixels = new uint8[rowstride * height]; 

      for (var i = 0; i < height; i++) { 
       for (var j = 0, k = 0; j < width * 4; j += 4, k += 3) { 
        var orig_index = rowstride * i + j; 
        var index = rowstride * i + k; 

        if (orig_pixels[orig_index] == 0 && 
         orig_pixels[orig_index + 1] == 0 && 
         orig_pixels[orig_index + 2] == 0 && 
         orig_pixels[orig_index + 3] == 0) { 
         pixels[index] = 0xFF; 
         pixels[index + 1] = 0xFF; 
         pixels[index + 2] = 0xFF; 
        } else { 
         pixels[index] = orig_pixels[orig_index]; 
         pixels[index + 1] = orig_pixels[orig_index + 1]; 
         pixels[index + 2] = orig_pixels[orig_index + 2]; 
        } 
       } 
      } 

      pixbuf = new Gdk.Pixbuf.from_data (pixels, 
               pixbuf.get_colorspace(), 
               false, 
               8, 
               width, 
               height, 
               rowstride, 
               null); 
     } 

     pixbuf.save (destination_path, dest_type); 

     return 0; 
    } 
+0

問題是關於C++! – alestanis 2012-10-20 09:58:38