Grayscale image from binary data
Asked Answered
R

2

1

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.

Regenerative answered 29/12, 2014 at 13:21 Comment(0)
S
1

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

Splenetic answered 29/12, 2014 at 13:57 Comment(0)
R
0

Thanks for a really helpful informations. I've managed to do it by myself

my code:

// stworzenie obrazu i przeskalowanie
    public Bitmap GetBitmap(double scalingFactor)
    {
        Bitmap image = new Bitmap(_width, _height, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);

        // konwersja palety idexed na skale szarosci
        ColorPalette grayPalette = image.Palette;
        Color[] entries = grayPalette.Entries;
        for (int i = 0; i < 256; i++)
        {
            Color grayC = new Color();
            grayC = Color.FromArgb((byte)i, (byte)i, (byte)i);
            entries[i] = grayC;
        }
        image.Palette = grayPalette;

        // wrzut binary data do bitmapy
        BitmapData dataR = image.LockBits(new Rectangle(Point.Empty, image.Size), ImageLockMode.WriteOnly, image.PixelFormat);
        Marshal.Copy(_rawDataPresented, 0, dataR.Scan0, _rawDataPresented.Length);
        image.UnlockBits(dataR);

        // skalowanie wielkosci
        Size newSize = new Size((int)(image.Width * scalingFactor), (int)(image.Height * scalingFactor));
        Bitmap scaledImage = new Bitmap(image, newSize);

        return scaledImage;
    }
Regenerative answered 8/1, 2015 at 10:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.