I need to display a 2D array (UInt16[,]
) as a 16 bit grayscale image within a Winforms application.
The steps I need to take are (roughly):
Build a
Bitmap
from theUInt16[,]
array - note that I need to do this efficiently, as I am looking to eventually update the picture at 60 Hz or betterPaint the
Bitmap
on the main window, probably in aPictureBox
, updating at 60 Hz or betterI would like to re-size the image from full to thumbnail size as well, based on the size of the
PictureBox
From this question, I got efficient (but unsafe) code that builds the Bitmap
from the array.
Also, I checked to make sure I could at least paint a pre-made image without issue, and that worked just fine.
When I tried to display the Bitmap
made from the UInt16[,]
, however, I was either met with the big red box of doom or (running on a different machine) met with a System.ArgumentException
, "Parameter is not valid."
After I met with failure, I got code to determine if the Bitmap
was empty from this question. That isn't the problem.
Here is some sample code to illustrate, using a dummy array.
Main Form Code
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
namespace IntArrViewer
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
int sz = 256;
UInt16[,] raw = new UInt16[sz, sz];
// Assign values to pixels
for (int i = 0; i < sz; i++)
for (int j = 0; j < sz; j++)
raw[i, j] = (UInt16)(i * sz + j);
// Get Bitmap from 2D array of UInt16
Bitmap intBmp= UInt16toBmp(raw, sz, sz);
// Get Bitmap from premade JPG
Bitmap preMadeBmp= new Bitmap(@"premade_pic.jpg");
// Verify that neither BMP is empty
bool emptyIntBmp= BmpIsEmpty(intBmp);
bool emptyPreMadeBmp= BmpIsEmpty(preMadeBmp);
// Set main picture box to premade image
mainPic.Image = preMadeBmp;
// Setting to array image raises an exception
// mainPic.Image = intBmp
}
public unsafe Bitmap UInt16toBmp(UInt16[,] frame, int width, int height)
{
int stride = width * 2;
Bitmap bitmap;
fixed (UInt16* intPtr = &frame[0, 0])
{
bitmap = new Bitmap(width, height, stride,
PixelFormat.Format16bppGrayScale,
new IntPtr(intPtr));
}
return bitmap;
}
public bool BmpIsEmpty(Bitmap bmp)
{
var data = bmp.LockBits(new Rectangle(0, 0, bmp.Width,
bmp.Height),
ImageLockMode.ReadOnly,
bmp.PixelFormat);
var bytes = new byte[data.Height * data.Stride];
Marshal.Copy(data.Scan0, bytes, 0, bytes.Length);
bmp.UnlockBits(data);
return bytes.All(x => x == 0);
}
}
}