2010-12-05 44 views
4

我試圖在C#中將一組8位PNG圖像組合成更大的PNG圖像。奇怪的是,這似乎特別困難。在.NET中組合多個PNG8圖像的最簡單方法

因爲Graphics不支持索引顏色,所以我不能使用它,所以我嘗試構建一個非索引位圖(使用圖形)並將其轉換爲索引顏色位圖。轉換很好,但我無法弄清楚如何設置輸出圖像的調色板。它默認使用一些預定義的調色板,這與我正在尋找的內容無關。

所以:

有沒有辦法來控制位圖調色板?還是有另一種方法(例如System.Windows.Media.Imaging.WriteableBitmap)可以支持這個?

Re:WriteableBitmap:我似乎無法在網上找到任何關於如何將PNG合併到此上下文中的示例,或者即使它嘗試使用它也沒有任何意義。

+0

儘管專門提到GIF,但相同的顏色表主要可能適用於... http://support.microsoft.com/kb/319061只有在做一些非常相似的事情時纔會嘗試使用代碼。 – 2010-12-05 03:08:05

回答

0

事實證明,我能夠打造出一個非索引位圖和使用轉換PngBitmapEncoder像這樣:

byte[] ConvertTo8bpp(Bitmap sourceBitmap) 
    { 
     // generate a custom palette for the bitmap (I already had a list of colors 
     // from a previous operation 
     Dictionary<System.Drawing.Color, byte> colorDict = new Dictionary<System.Drawing.Color, byte>(); // lookup table for conversion to indexed color 
     List<System.Windows.Media.Color> colorList = new List<System.Windows.Media.Color>(); // list for palette creation 
     byte index = 0; 
     unchecked 
     { 
      foreach (var cc in ColorsFromPreviousOperation) 
      { 
       colorDict[cc] = index++; 
       colorList.Add(cc.ToMediaColor()); 
      } 
     } 
     System.Windows.Media.Imaging.BitmapPalette bmpPal = new System.Windows.Media.Imaging.BitmapPalette(colorList); 

     // create the byte array of raw image data 
     int width = sourceBitmap.Width; 
     int height = sourceBitmap.Height; 
     int stride = sourceBitmap.Width; 
     byte[] imageData = new byte[width * height]; 

     for (int x = 0; x < width; ++x) 
      for (int y = 0; y < height; ++y) 
      { 
       var pixelColor = sourceBitmap.GetPixel(x, y); 
       imageData[x + (stride * y)] = colorDict[pixelColor]; 
      } 

     // generate the image source 
     var bsource = BitmapSource.Create(width, height, 96, 96, PixelFormats.Indexed8, bmpPal, imageData, stride); 

     // encode the image 
     PngBitmapEncoder encoder = new PngBitmapEncoder(); 
     encoder.Interlace = PngInterlaceOption.Off; 
     encoder.Frames.Add(BitmapFrame.Create(bsource)); 

     MemoryStream outputStream = new MemoryStream(); 
     encoder.Save(outputStream); 

     return outputStream.ToArray(); 
    } 

加上輔助擴展方法:

public static System.Windows.Media.Color ToMediaColor(this System.Drawing.Color color) 
    { 
     return new System.Windows.Media.Color() 
     { 
      A = color.A, 
      R = color.R, 
      G = color.G, 
      B = color.B 
     }; 
    } 

注意的警惕:PngBitmapEncoder實際上似乎可以將bpp計數從8減少到4。例如,當我使用6種顏色進行測試時,輸出PNG只有4位。當我使用更色彩豐富的圖像時,它是8位的。看起來像一個功能到目前爲止...雖然它會很好,如果我有明確的控制權。

0

聲明,我爲Atalasoft工作。

我們的產品DotImage Photo是免費的,可以做到這一點。

要讀取PNG

AtalaImage img = new AtalaImage("image.png"); 

要轉換爲24 BPP

img = img.GetChangedPixelFormat(newPixelFormat); 

創建大小的圖像,你要

AtalaImage img2 = new AtalaImage(width, height, color); 

使用OverlayCommand疊加的img到IMG2

OverlayCommand cmd = new OverlayCommand(img); 
cmd.Apply(img2, point); 

爲了節省

img2.Save("new.png", new PngEncoder(), null); 

如果您需要幫助這個答案無論是評論還是一個論壇條目。

相關問題