问题
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.
回答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
回答2:
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;
}
来源:https://stackoverflow.com/questions/27689739/grayscale-image-from-binary-data