簡體   English   中英

將 16 (12) 位灰度 png 加載並顯示到 PictureBox 中

[英]Loading and displaying a 16 (12) bit grayscale png into a PictureBox

我正在使用一個名為 IDS Peak 的相機硬件框架,我們從框架接收 16 位灰度圖像,框架本身可以將文件作為 PNG 寫入磁盤,這一切都很好,但是我如何顯示它們在 Winforms 的PictureBox中?

Windows Bitmap 不支持 16 位灰度,因此以下代碼會拋出“參數無效”。 System.ArgumentException

var image = new Bitmap(width, height, stride, System.Drawing.Imaging.PixelFormat.Format16bppGrayScale, iplImg.Data());

這里的iplImg.Data()是框架的定制圖像格式的 IntPtr。

考慮到 Windows Bitmap 不支持該格式,我可以使用框架將文件寫入 PNG,我該如何執行以下操作之一:

  1. 轉換為 Bitmap 以外的其他Bitmap類型,以直接在 Winforms 中顯示,無需讀取文件。
  2. 將 16 位灰度 PNG 文件加載到PictureBox控件(或任何其他控件類型,它不必是PictureBox )。

(1)是可取的,因為它不需要文件 IO 但如果(2)是唯一完全沒問題的可能性,因為無論如何我都需要保存和顯示它們但是(1)只需要寫入操作而不是二次讀取。

寫入磁盤之前的文件實際上是單色的,每像素 12 位,打包。

雖然可以顯示 16 位圖像,例如通過在 winforms 中托管 wpf 控件,但您可能希望應用窗口 function 以在顯示前將圖像縮小到 8 位。

因此,讓我們使用不安全的代碼和指針來提高速度:

            var bitmapData = myBitmap.LockBits(
                new Rectangle(0, 0, myBitmap.Width, myBitmap.Height),
                ImageLockMode.ReadWrite,
                myBitmap.PixelFormat);

            try
            {
                 var ptr= (byte*)bitmapData.Scan0;
                 var stride = bitmapData.Stride;
                 var width = bitmapData.Width;
                 var height= bitmapData.Height;
                 // Conversion Code
            }
            finally
            {
                myBitmap.UnlockBits(bitmapData);
            }

或使用 wpf 圖像類,通常具有更好的 16 位支持:

var myBitmap= new WriteableBitmap(new BitmapImage(new Uri("myBitmap.jpg", UriKind.Relative)));
writeableBitmap.Lock();
try{
     var ptr = (byte*)myBitmap.BackBuffer;
     ...
}
finally
{
      myBitmap.Unlock();
}

要遍歷所有像素,您將使用雙循環:

for (int y = 0; y < height; y++)
{
    var row = (ushort*)(ptr+ y * stride);
    for (int x = 0; x < width; x++)
    {
        var pixelValue = row[x];
        // Scaling code
    }
}

並且要縮放該值,您可以使用最小值和最大值之間的線性縮放到一個字節的 0-255 范圍

var slope = (byte.MaxValue + 1f) / (maxUshortValyue - minUshortValue);
var scaled = (int)(((pixelValue + 0.5f - minUshortValue) * slope)) ;
scaled = scaled > byte.MaxValue ? byte.MaxValue: scaled;
scaled = scaled < 0 ? 0: scaled;
var byteValue = (byte)scaled;

maxUshortValyue / minUshortValue可以根據圖像的最大/最小值計算,或者由用戶配置。 您還需要創建一個目標圖像,以便將結果寫入要顯示的目標 8 位灰度 bitmap,或者為彩色圖像中的每個顏色通道寫下相同的值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM