繁体   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