Search code examples
c#imagebinarypictureboxgrayscale

Grayscale image from binary data


I'm working on some simple viewer app for CT images. Let's say I have array of 262144 Int16 values.

Each value represents one pixel in 512x512 image. Each pixel has value from 0 to 4096 where 0 is black and 4096 is white.

Is there any elegant, simple solution to display this image in Visual Studio Picture Box? Maybe some kind of MemoryReader or Stream?

I've tried to search for some solution but found only topic about retrieving binary data from databases.


Solution

  • A good way and with a good performance is to use LockBits function to access image data, using the LockBits you can create a Bitmap image using each byte of image, the lockBit lock the image data in memory to change each pixel data of the Bitmap Image. See this example:

      Bitmap bm = new Bitmap(512, 512);
      BitmapData bmd=bm.LockBits(new Rectangle(0, 0, 10, 10), System.Drawing.Imaging.ImageLockMode.ReadOnly, bm.PixelFormat);
      int PixelSize=4;
    
      for(int y=0; y<bmd.Height; y++)
      {
        byte* row=(byte *)bmd.Scan0+(y*bmd.Stride);
        for(int x=0; x<bmd.Width; x++)
        {
          // Here you change your pixel data
          row[x*PixelSize]=255;
        }
      }
      bm.UnlockBits(bmd)
    

    to draw in pictureBox you can just concatenate the member Image of pictureBox, or draw of a manually way. See these examples:

    // concatenate 
    pict1.Image = bmp;
    

    or

    // Draw using CreateGraphics
    Graphics g = Graphics.FromHwnd(pictureBox1.Handle);
    g.DrawImage(bmp, new Point(10, 10));
    

    About the grayscale you can get a grayscale just using the value of one channel of image or getting an average value between RGB values and use the same value to these three channels, see this example:

    // Average value between channels
    Color oc = bmp.GetPixel(i, x);
    int grayScale = (int)((oc.R * 0.3) + (oc.G * 0.59) + (oc.B * 0.11));
    Color nc = Color.FromArgb(oc.A, grayScale, grayScale, grayScale);
    d.SetPixel(x, y, nc); // if you are using bitmap
    

    or

    // value from one channel
    Color pixelColor = c.GetPixel(x, y);
    Color newColor = Color.FromArgb(pixelColor.R, pixelColor.R, pixelColor.R);
    c.SetPixel(x, y, newColor); // Now greyscale
    

    See more about the lockBits in this link: https://web.archive.org/web/20141229164101/http://bobpowell.net/lockingbits.aspx

    and about grayscale: https://en.wikipedia.org/wiki/Grayscale