问题
I have an array which consists in PixelData extracted from a Dicom Image.
Here's the code:
byte[] bytes = img.PixelData.GetFrame(0).Data; // img is the Dicom Image
int count = bytes.Length / 2;
ushort[] words = new ushort[count];
for (int i = 0, p = 0; i < count; i++, p += 2)
{
words[i] = BitConverter.ToUInt16(bytes, p);
}
pixels16 = words.ToList(); //pixels16 contains now the PixelData for the Grayscale image
Now, here's my question, how do I render that into a Picturebox??
回答1:
My code for converting Bitmaps from Format16bppGrayScale to Format8bppIndexed format. PictureBox can easy show this format. (If you want, you can use different palette).
public Bitmap Gray16To8bppIndexed(Bitmap BmpIn)
{
if (BmpIn.PixelFormat != PixelFormat.Format16bppGrayScale)
throw new BadImageFormatException();
byte[] ImageData = new byte[BmpIn.Width * BmpIn.Height * 2];
Rectangle Re = new Rectangle(0, 0, BmpIn.Width, BmpIn.Height);
BitmapData BmpData = BmpIn.LockBits(Re, ImageLockMode.ReadOnly, BmpIn.PixelFormat);
Marshal.Copy(BmpData.Scan0, ImageData, 0, ImageData.Length);
BmpIn.UnlockBits(BmpData);
byte[] ImageData2 = new byte[BmpIn.Width * BmpIn.Height];
for (long i = 0; i < ImageData2.LongLength; i++)
ImageData2[i] = ImageData[i * 2 + 1];
ImageData = null;
Bitmap BmpOut = new Bitmap(BmpIn.Width, BmpIn.Height, PixelFormat.Format8bppIndexed);
BmpData = BmpOut.LockBits(Re, ImageLockMode.WriteOnly, BmpOut.PixelFormat);
Marshal.Copy(ImageData2, 0, BmpData.Scan0, ImageData2.Length);
BmpOut.UnlockBits(BmpData);
ImageData2 = null;
BmpData = null;
ColorPalette GrayPalette = BmpOut.Palette;
Color[] GrayColors = GrayPalette.Entries;
for (int i = 0; i < GrayColors.Length; i++)
GrayColors[GrayColors.Length - 1 - i] = Color.FromArgb(i, i, i);
BmpOut.Palette = GrayPalette;
return BmpOut;
}
回答2:
Well, I don't know the specifics, because it depends on how you really want to go about it (if performance is important, you need to create your own subclass of Bitmap, but otherwise, Bitmap.SetPixel would work fine).
But essentially, you need to shove those pixels into a Bitmap, then set the picture box's image to that bitmap, like:
Bitmap bitmap = new Bitmap(width, height);
for(int y = 0;y < height;y++)
for(int x = 0;x < width;x++)
bitmap.SetPixel(x,y, Color.fromRGB(/* unpack your R,G,B channel of your pixel here */);
pictureBox.Image = bitmap;
回答3:
You can utilize the AForge .NET Framework, which is a great .NET library for image processing. The built-in .NET Picturebox could not nativley display images with System.Drawing.Imaging.PixelFormat.Format16bppGrayScale, but the AForge library has its own Picturebox control, check this out. It expects a .NET Image.
You can include AForge to your project easily with NuGet:
Install-Package AForge.Controls
Install-Package AForge.Imaging
Or just
Install-Package AForge
Example code below:
//SOME BYTES
//Load here the DICOM image
int width=640, height=480;
int numberOfPixels = width*height;
byte[] source = new byte[2*numberOfPixels];
//With AFORGE
var image = AForge.Imaging.UnmanagedImage.Create(width, height, System.Drawing.Imaging.PixelFormat.Format16bppGrayScale);
IntPtr ptrToImage = image.ImageData;
//Copies the bytes from source to the image
//System.Runtime.InteropServices
Marshal.Copy(source, 0, ptrToImage,numberOfPixels);
//WITH .NET
System.Drawing.Bitmap bitmapImage = new System.Drawing.Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format16bppGrayScale);
var imageData = bitmapImage.LockBits(new System.Drawing.Rectangle(0, 0, width, height), System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format16bppGrayScale);
Marshal.Copy(source, 0, imageData.Scan0, numberOfPixels);
bitmapImage.UnlockBits(imageData);
回答4:
Got this idea from a friend. The inputImage.ImageSource property is a 2D array with grayscale pixel values.
Bitmap grayscaleImage = new Bitmap(inputImage.ImageSource);
for (int x = 0; x < grayscaleImage.Width; x++)
{
for (int y = 0; y < grayscaleImage.Height; y++)
{
byte[,] tempMatrix = inputImage.ImageGrayscale;
byte temp = tempMatrix[x, y];
Color tempColor = Color.FromArgb(255, temp, temp, temp);
grayscaleImage.SetPixel(x, y, tempColor);
}
}
picboxDisplay.Image = grayscaleImage;
来源:https://stackoverflow.com/questions/18217583/render-16-bits-image-in-picturebox