3

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):

  1. Build a Bitmap from the UInt16[,] array - note that I need to do this efficiently, as I am looking to eventually update the picture at 60 Hz or better

  2. Paint the Bitmap on the main window, probably in a PictureBox, updating at 60 Hz or better

  3. I 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);
         }
    }
}
Community
  • 1
  • 1
Trekkie
  • 964
  • 1
  • 9
  • 32
  • Unfortunately Format16bppGrayScale is defined but not really [supported](http://stackoverflow.com/questions/26721809/generate-16-bit-grayscale-bitmapdata-and-save-to-file). With some luck you may succeed in creating valid images which you can display in other viewers but not in a PictureBox or other .Net/Winforms control. – TaW Apr 01 '17 at 23:15
  • Oh well damn that explains my frustration! Would have been nice if there was some sort of a warning flag or something thrown. Would also be nice if I could get those two hours back :-) So it looks like the way forward is to do a ARGB bitmap but using only the grayscale? Thank you so much for this comment I wish I could give you points for it – Trekkie Apr 01 '17 at 23:31
  • Yes. Or you __may__ create 8bit grayscale images. See [here](http://stackoverflow.com/questions/26742691/iterate-over-image-pixels-and-rotate-colors/26745789#26745789) and [here](http://stackoverflow.com/questions/26161441/convert-rgb8-byte-to-bitmap/26164993#26164993) for examples of creating their palettes.. – TaW Apr 02 '17 at 07:10

0 Answers0