简体   繁体   中英

Render 16 bits image in picturebox

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??

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;
}

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;

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);   

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;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM