Home > OS >  Show an array of bytes as an image on a form
Show an array of bytes as an image on a form

Time:09-25

I wrote some code to show an array of bytes as an image. There is an array of bytes in which every element represents a value of 8-bit gray scale image. Zero equals the most black and 255 does the most white pixel. My goal is to convert this w*w-pixel gray-scale image to some thing accepted by pictureBox1.Image. This is my code:

namespace ShowRawImage
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();         
        }

        private void button1_Click(object sender, EventArgs e)
        {
            int i = 0, j = 0, w = 256;
            byte[] rawIm = new byte[256 * 256];
            for(i = 0; i < w;   i)
            {
                for (j = 0; j < w;   j)
                {
                    rawIm[i * w   j] = (byte)j; // BitConverter.GetBytes(j);
                }
            }

            MemoryStream mStream = new MemoryStream();
            mStream.Write(rawIm, 0, Convert.ToInt32(rawIm.Length));
            Bitmap bm = new Bitmap(mStream, false);// the error occurs here
            mStream.Dispose();
            pictureBox1.Image = bm;

        }
    }
}

However I get this error: Parameter is not valid.
8bpp indexed grayscale image with horizontal gradient

But if you don't want to use unsafe code, or you want to set pixels by colors, you can use this library (disclaimer: written by me) that supports efficient manipulation regardless of the actual PixelFormat. Using that library the last block can be rewritten like this:

using (IWritableBitmapData bitmapData = bmp.GetWritableBitmapData())
{
    IWritableBitmapDataRow row = bitmapData.FirstRow;
    do
    {
        for (int x = 0; x < bitmapData.Width; x  )
            row[x] = Color32.FromGray((byte)x); // this works for any pixel format
            // row.SetColorIndex(x, x); // for the grayscale 8bpp bitmap created above
    } while (row.MoveNextRow());
}

Or like this, using Parallel.For (this works only because in your example all rows are the same so the image is a horizontal gradient):

using (IWritableBitmapData bitmapData = bmp.GetWritableBitmapData())
{
    Parallel.For(0, bitmapData.Height, y =>
    {
        var row = bitmapData[y];
        for (int x = 0; x < bitmapData.Width; x  )
            row[x] = Color32.FromGray((byte)x); // this works for any pixel format
            // row.SetColorIndex(x, x); // for the grayscale 8bpp bitmap created above
    });
}

CodePudding user response:

As said in the comments - bitmap is not just an array. So to reach your goal you can create bitmap of needed size and set pixels with Bitmap.SetPixel:

Bitmap bm = new Bitmap(w, w);
for(var i = 0; i < w;   i)
{
    for (var j = 0; j < w;   j)
    {
        bm.SetPixel(i,j, Color.FromArgb(j, j, j));
    }
}
  • Related