2011-06-27 73 views
4

我有一個應用程序,允許用戶創建不超過帶有所需背景色的文本的簡單圖像。用戶可以從System.Windows.Forms.ColorDialog中選擇一種顏色,並用它來設置文本顏色和背景顏色。如何保存帶有透明背景的gif?

背景顏色可以設置爲透明(我使用Color.Transparent作爲透明度的參考),選擇之後,我更新預覽圖像,以正確顯示文本和透明度。但是,當我去保存圖像時,我無法獲得用圖像作爲gif保存的透明度。

我發現this article其中規定我應該使用MakeTransparent方法來設置透明度顏色。

在我調用保存操作之前,我將內存中的圖像作爲背景/透明顏色使用黑色重新繪製,然後在保存圖像之前,在內存圖像上調用MakeTransperent方法。儘管如此,圖像仍以黑色作爲背景進行保存。

我會做什麼錯?


編輯:這裏是相關的代碼。

這是創建圖像的方法。 overrideBG變量用於指定是否應將透明度顏色設置爲gif的非alpha顏色。

void ReDrawImage(bool overrideBG = false) //My method that draws the image in memory. 
{ 
    //My In Memory Image creation 
    img = new Bitmap(sz.Width, sz.Height); 
    Graphics gfx = Graphics.FromImage(img); 

    ... 

    //This portion of code sets the BG color to what should be the transparency color, if the BG is transparent 
    if (overrideBG) 
     { 
      gfx.Clear(TransparentColor); //TransparentColor = Black, unless Text Color is Black. If so, it equals White. 
     } 
     else 
     { 
      gfx.Clear(BackColorPreview.BackColor); 
     } 

    //Followed by code that writes the text. 
} 

//This is the save method (Assume we are always drawing a transparent background.) 
Save() 
{ 
    ReDrawImage(true); 
    img.MakeTransparent(TransparentColor); //I've also tried moving this line before the ReDrawImage call 
    img.Save(SaveFile.FileName, ImageFormat.Gif); 
    ReDrawImage(); 
} 
+0

發佈您的代碼。 – lincolnk

回答

3

顯然有MakeTransparent和gif問題。我發現this post它提供並通過修改內存中的圖像字節的方式替代。這是來自帖子的代碼示例,其中修復了語法錯誤。

/// <summary> 
/// Returns a transparent background GIF image from the specified Bitmap. 
/// </summary> 
/// <param name="bitmap">The Bitmap to make transparent.</param> 
/// <param name="color">The Color to make transparent.</param> 
/// <returns>New Bitmap containing a transparent background gif.</returns> 
public static Bitmap MakeTransparentGif(Bitmap bitmap, Color color) 
{ 
    byte R = color.R; 
    byte G = color.G; 
    byte B = color.B; 
    MemoryStream fin = new MemoryStream(); 
    bitmap.Save(fin, System.Drawing.Imaging.ImageFormat.Gif); 
    MemoryStream fout = new MemoryStream((int)fin.Length); 
    int count = 0; 
    byte[] buf = new byte[256]; 
    byte transparentIdx = 0; 
    fin.Seek(0, SeekOrigin.Begin); 
    //header 
    count = fin.Read(buf, 0, 13); 
    if ((buf[0] != 71) || (buf[1] != 73) || (buf[2] != 70)) return null; //GIF 
    fout.Write(buf, 0, 13); 
    int i = 0; 
    if ((buf[10] & 0x80) > 0) 
    { 
     i = 1 << ((buf[10] & 7) + 1) == 256 ? 256 : 0; 
    } 
    for (; i != 0; i--) 
    { 
     fin.Read(buf, 0, 3); 
     if ((buf[0] == R) && (buf[1] == G) && (buf[2] == B)) 
     { 
      transparentIdx = (byte)(256 - i); 
     } 
     fout.Write(buf, 0, 3); 
    } 
    bool gcePresent = false; 
    while (true) 
    { 
     fin.Read(buf, 0, 1); 
     fout.Write(buf, 0, 1); 
     if (buf[0] != 0x21) break; 
     fin.Read(buf, 0, 1); 
     fout.Write(buf, 0, 1); 
     gcePresent = (buf[0] == 0xf9); 
     while (true) 
     { 
      fin.Read(buf, 0, 1); 
      fout.Write(buf, 0, 1); 
      if (buf[0] == 0) break; 
      count = buf[0]; 
      if (fin.Read(buf, 0, count) != count) return null; 
      if (gcePresent) 
      { 
       if (count == 4) 
       { 
        buf[0] |= 0x01; 
        buf[3] = transparentIdx; 
       } 
      } 
      fout.Write(buf, 0, count); 
     } 
    } 
    while (count > 0) 
    { 
     count = fin.Read(buf, 0, 1); 
     fout.Write(buf, 0, 1); 
    } 
    fin.Close(); 
    fout.Flush(); 
    return new Bitmap(fout); 
} 

我試過用漢斯的樣品​​(取代gif零件),它適用於我。

您的代碼看起來像

img = MakeTransparent(img, TransparentColor); 
img.Save(SaveFile.FileName, ImageFormat.Gif); 
+0

這不是我希望的答案,但它是一個工作的。謝謝。 – RLH

+0

它不在我身邊工作:( – Nofuzy

2

GDI版本1.10支持存儲透明度顏色的屬性,屬性ID 20740.我看到它習慣用GIF編碼器在Windows 7上使用此測試代碼:

 var bmp = new Bitmap(100, 100, System.Drawing.Imaging.PixelFormat.Format32bppArgb); 
     using (var gr = Graphics.FromImage(bmp)) { 
      gr.Clear(Color.Blue); 
      gr.FillRectangle(Brushes.Red, new Rectangle(10, 10, 80, 80)); 
     } 
     bmp.MakeTransparent(Color.Red); 
     bmp.Save(@"c:\temp\test.gif", System.Drawing.Imaging.ImageFormat.Gif); 

此代碼正確恢復位圖:

private static Bitmap LoadGif(string path) { 
     var bmp = new Bitmap(path); 
     bool found = false; 
     foreach (System.Drawing.Imaging.PropertyItem item in bmp.PropertyItems) { 
      if (item.Id == 20740) { 
       int paletteIndex = item.Value[0]; 
       Color backGround = bmp.Palette.Entries[paletteIndex]; 
       bmp.MakeTransparent(backGround); 
       found = true; 
       break; 
      } 
     } 
     // Property missing, punt at the color of the lower-left pixel 
     //if (!found) bmp.MakeTransparent(); 
     return bmp; 
    } 

不知道這是否適用於早期版本的GDI +,我沒有XP了。 SDK明確提到版本1.10,首先隨Vista發貨。

+0

這實際上就是我在做的,只是我的過程被分割到多個方法中。另外,我不需要將圖像恢復到應用程序。 – RLH

+1

我不知道這是什麼意思。無論你用什麼程序來查看圖像似乎都不使用屬性項。嘗試另一個或寫你自己的。 –

+0

我創建的圖像存儲在顯示在PictureBox中的內存中。當用戶保存圖像時,我將內存中的圖像(img)寫入gif文件。我的過程與第一個代碼示例中所述的完全相同,不同之處在於我在ReDrawImage方法中操縱圖像,並將該文件保存在Save方法中。 – RLH