[英]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,我该如何执行以下操作之一:
Bitmap
类型,以直接在 Winforms 中显示,无需读取文件。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.