2013-03-26 87 views
2

我試圖用純色背景色創建一個8位圖像。它看起來應該是非常直接的,但文件中的細節列出它爲32位顏色深度。我錯過了什麼?創建8位圖像

public void CreateImage() 
    { 
     var bmpOut = new Bitmap(300, 300); 
     var g = Graphics.FromImage(bmpOut); 
     g.FillRectangle(new SolidBrush(Color.Gray), 0, 0, 300, 300); 

     var stream = new MemoryStream(); 
     bmpOut.Save(stream, GetPngCodecInfo(), GetEncoderParameters()); 

     bmpOut.Save(@"C:\image.png", GetPngCodecInfo(), GetEncoderParameters()); 
    } 

    public EncoderParameters GetEncoderParameters() 
    { 
     var parameters = new EncoderParameters(); 
     parameters.Param[0] = new EncoderParameter(Encoder.ColorDepth, 8); 

     return parameters; 
    } 

    public ImageCodecInfo GetPngCodecInfo() 
    { 
     var encoders = ImageCodecInfo.GetImageEncoders(); 

     ImageCodecInfo codecInfo = null; 

     foreach (var imageCodecInfo in encoders) 
     { 
      if (imageCodecInfo.FormatID != ImageFormat.Png.Guid) 
       continue; 

      codecInfo = imageCodecInfo; 
      break; 
     } 

     return codecInfo; 
    } 
+0

'「C:\ image.png」'是可能無效的路徑...假設你有前面的@(或只是隨機的字符串樣品)。 – 2013-03-26 03:08:09

+0

從我所看到的,你缺少的東西是一個調色板... – Nyerguds 2017-04-11 14:21:45

回答

1

使用此構造指定的像素格式:http://msdn.microsoft.com/en-us/library/3z132tat.aspx

因爲你不能在創建索引像素格式的圖形,你可以只寫原始像素的8位圖像。

Bitmap bitmap = new Bitmap(32, 32, PixelFormat.Format8bppIndexed); 
var bitmapData = bitmap.LockBits(new Rectangle(Point.Empty, bitmap.Size), ImageLockMode.ReadWrite, bitmap.PixelFormat); 
Random random=new Random(); 
byte[] buffer=new byte[bitmap.Width*bitmap.Height]; 
random.NextBytes(buffer); 
Marshal.Copy(buffer,0,bitmapData.Scan0,buffer.Length); 
bitmap.UnlockBits(bitmapData); 
bitmap.Save("test.bmp",ImageFormat.Bmp); 

您可以使用上的WinForms這樣的代碼:http://www.codeproject.com/Articles/17162/Fast-Color-Depth-Change-for-Bitmaps

或者,如果你可以從WPF引用此類就會容易得多: http://msdn.microsoft.com/en-us/library/system.windows.media.imaging.formatconvertedbitmap(v=vs.85).aspx

+2

但要小心。僅僅指定像素格式是不夠的,因爲創建8位索引圖像將在下一行失敗 - 從圖像創建一個「圖形」。 – DocMax 2013-03-26 06:21:44

+0

從索引格式創建圖形將引發異常:無法從具有索引像素格式的圖像創建Graphics對象。 – Aybe 2013-03-26 13:55:42

+1

究竟是在那裏做「Random」? – Nyerguds 2017-03-31 18:01:17

0
  • ImageExtensions.cs

    using System.Runtime.InteropServices; 
    using System.Linq; 
    
    using System.Drawing.Imaging; 
    using System.Drawing; 
    using System; 
    
    public static partial class ImageExtensions { 
        public static ColorPalette ToGrayScale(this ColorPalette palette) { 
         var entries=palette.Entries; 
    
         for(var i=entries.Length; i-->0; entries[i]=entries[i].ToGrayScale()) 
          ; 
    
         return palette; 
        } 
    
        public static Color ToGrayScale(this Color color, double[] luminance=null) { 
         var list=(luminance??new[] { 0.2989, 0.5870, 0.1140 }).ToList(); 
         var channel=new[] { color.R, color.G, color.B }; 
         var c=(byte)Math.Round(list.Sum(x => x*channel[list.IndexOf(x)])); 
         return Color.FromArgb(c, c, c); 
        } 
    
        public static Bitmap To8bppIndexed(this Bitmap original) { 
         var rect=new Rectangle(Point.Empty, original.Size); 
         var pixelFormat=PixelFormat.Format8bppIndexed; 
         var destination=new Bitmap(rect.Width, rect.Height, pixelFormat); 
    
         using(var source=original.Clone(rect, PixelFormat.Format32bppArgb)) { 
          var destinationData=destination.LockBits(rect, ImageLockMode.WriteOnly, pixelFormat); 
          var sourceData=source.LockBits(rect, ImageLockMode.ReadOnly, source.PixelFormat); 
    
          var destinationSize=destinationData.Stride*destinationData.Height; 
          var destinationBuffer=new byte[destinationSize]; 
    
          var sourceSize=sourceData.Stride*sourceData.Height; 
          var sourceBuffer=new byte[sourceSize]; 
    
          Marshal.Copy(sourceData.Scan0, sourceBuffer, 0, sourceSize); 
          source.UnlockBits(sourceData); 
    
          destination.Palette=destination.Palette.ToGrayScale(); 
          var list=destination.Palette.Entries.ToList(); 
    
          for(var y=destination.Height; y-->0;) { 
           for(var x=destination.Width; x-->0;) { 
            var pixelIndex=y*destination.Width+x; 
            var sourceIndex=4*pixelIndex; 
    
            var color= 
             Color.FromArgb(
              sourceBuffer[0+sourceIndex], 
              sourceBuffer[1+sourceIndex], 
              sourceBuffer[2+sourceIndex], 
              sourceBuffer[3+sourceIndex] 
              ).ToGrayScale(); 
    
            destinationBuffer[pixelIndex]=(byte)list.IndexOf(color); 
           } 
          } 
    
          Marshal.Copy(destinationBuffer, 0, destinationData.Scan0, destinationSize); 
          destination.UnlockBits(destinationData); 
         } 
    
         return destination; 
        } 
    } 
    

呼叫bmpOut=bmpOut.To8bppIndexed();你之前將其保存到文件中。

+0

有_no sense_在轉換調色板爲灰度爲新的圖像。只需使用顏色值從00,00,00到FF,FF,FF填充調色板。使用這樣的調色板,您可以100%確定具有所有灰度值,並且放置在最終像素上的8位值僅等於實際灰度像素顏色的三個顏色分量中的任何一個。沒有更多的查找需要。 – Nyerguds 2017-04-11 14:32:45