2016-10-03 41 views
0

我有一些原始的傳感器數據是在一個單維的字節數組。數據實際上是IEEE單精度浮點格式。我知道X軸和Y軸的邊距,我想從我的數據創建Windows位圖(灰度 - 只有一個包含亮度數據的顏色平面)。如何在C#中從頭開始創建Windows位圖?

這裏就是我試圖至今:

 var bitmap = new Bitmap(xAxis, yAxis, PixelFormat.Format16bppGrayScale); 
     var pixelReader = GetPixelReader(hdu.MandatoryKeywords.BitsPerPixel); 
     using (var stream = new MemoryStream(hdu.RawData, writable: false)) 
      { 
      using (var reader = new BinaryReader(stream, Encoding.ASCII)) 
       { 
       for (var y = 0; y < yAxis; y++) 
        { 
        for (var x = 0; x < xAxis; x++) 
         { 
         var pixel = pixelReader(reader); 
         var argb = Color.FromArgb(pixel, pixel, pixel); 
         bitmap.SetPixel(x, y, argb); 
         } 
        } 
       } 
      } 
     return bitmap; 

pixelReader是一個委託並定義爲:

private static int ReadIeeeSinglePrecision(BinaryReader reader) 
     { 
     return (int) reader.ReadSingle(); 
     } 

當我運行這段代碼,我上線那裏得到一個異常InvalidArgumentException我嘗試設置像素值。我在調試器中加入了它,x = 0,y = 0,像素= 0。它沒有說哪個參數是無效的或爲什麼(謝謝微軟)。

很顯然,我做錯了事實上,我懷疑可能有更有效的方法來解決這個問題。我將不勝感激任何建議。由於我無法完全理解的原因,我發現這些代碼非常具有挑戰性。

+1

不要使用'SetPixel'進行批量操作,[改用'LockBits'](http://stackoverflow.com/questions/1563038/fast-work-with-bitmaps-in-c-sharp)。此外,請[獲取例外詳情](https://blogs.msdn.microsoft.com/saraford/2008/08/07/did-you-know-you-can-copy-the-exception-details-with-一鍵從異常助手-276 /)的InvalidArgumentException並將其包括在這裏。這將有助於大大發現問題所在。 –

+0

@ScottChamberlain是的,我已經閱讀過文檔中的內容,但我認爲這只是一個表現問題,不是嗎?我需要先解決問題,然後再優化它,或者永遠不要。說實話,LockBits的文檔對我來說更不明智。 –

+1

你在argb中獲得一個有效的顏色還是隻是得到一個null?我懷疑你的問題更早,但隱式類型變量模糊了這個問題。我強烈建議使用實際的類型,而不是將所有的代碼都定義爲變量,而這些代碼中的大部分/全部都不需要。 – AgapwIesu

回答

0

確定這裏是最後的工作。基於從馬克·道森的回答帶到這個問題代碼:https://social.msdn.microsoft.com/Forums/vstudio/en-US/10252c05-c4b6-49dc-b2a3-4c1396e2c3ab/writing-a-16bit-grayscale-image?forum=csharpgeneral

private static Bitmap CreateBitmapFromBytes(byte[] pixelValues, int width, int height) 
    { 
    //Create an image that will hold the image data 
    Bitmap pic = new Bitmap(width, height, PixelFormat.Format16bppGrayScale); 
    //Get a reference to the images pixel data 
    Rectangle dimension = new Rectangle(0, 0, pic.Width, pic.Height); 
    BitmapData picData = pic.LockBits(dimension, ImageLockMode.ReadWrite, pic.PixelFormat); 
    IntPtr pixelStartAddress = picData.Scan0; 
    //Copy the pixel data into the bitmap structure 
    System.Runtime.InteropServices.Marshal.Copy(pixelValues, 0, pixelStartAddress, pixelValues.Length); 
    pic.UnlockBits(picData); 
    return pic; 
    } 

於是我修改了我自己的代碼從IEEE浮點數據轉換成16個整數,然後直接從創建位圖,像這樣:

 var pixelReader = GetPixelReader(hdu.MandatoryKeywords.BitsPerPixel); 
     var imageBytes = new byte[xAxis * yAxis * sizeof(Int16)]; 
     using (var outStream = new MemoryStream(imageBytes, writable: true)) 
     using (var writer = new BinaryWriter(outStream)) 
     using (var inStream = new MemoryStream(hdu.RawData, writable: false)) 
     using (var reader = new BinaryReader(inStream, Encoding.ASCII)) 
      for (var y = 0; y < yAxis; y++) 
       { 
       for (var x = 0; x < xAxis; x++) 
        { 
        writer.Write(pixelReader(reader)); 
        } 
       } 
     var bitmap = CreateGreyscaleBitmapFromBytes(imageBytes, xAxis, yAxis); 
     return bitmap; 

這似乎也解決了評論中強調的效率問題。

+0

一旦我嘗試顯示我創建的圖像,那不起作用。所以我仍然有辦法解決這個問題。當我找到更好的解決方案時,我會更新我的答案。 –