3

I've a two-dimensional double[,] rawImage array representing a gray level image with each element in the array has a rational value from 0 ~ 1 , and I need to convert it to Bitmap image, I've used the following code:

private Bitmap ToBitmap(double[,] rawImage)
{
     int width  = rawImage.GetLength(1);
     int height = rawImage.GetLength(0);

     Bitmap Image= new Bitmap(width, height);

     for (int i = 0; i < height; i++)
         for (int j = 0; j < YSize; j++)
              {
               double color = rawImage[j, i];
               int rgb = color * 255;
               Image.SetPixel(i, j, rgb , rgb , rgb);
              }

     return Image;
}

but it seems to be so slow. I don't know if there is a way to do the above work using pointers of short data type.

How can I write a faster code using pointers to handle this function ?

Sameh K. Mohamed
  • 2,323
  • 4
  • 29
  • 55
  • [`bitMap.LockBits`](http://msdn.microsoft.com/en-us/library/5ey6h79d.aspx) – L.B Nov 22 '12 at 11:26
  • SetPixel locks the entire image for every pixel. If you lock the entire image you can use unsafe code to write every value in the image. http://stackoverflow.com/questions/7768711/setpixel-is-too-slow-is-there-a-faster-way-to-draw-to-bitmap – MrFox Nov 22 '12 at 11:37

1 Answers1

6

This should be enough for you. The example is written according to this source code.

private unsafe Bitmap ToBitmap(double[,] rawImage)
{
    int width = rawImage.GetLength(1);
    int height = rawImage.GetLength(0);

    Bitmap Image = new Bitmap(width, height);
    BitmapData bitmapData = Image.LockBits(
        new Rectangle(0, 0, width, height),
        ImageLockMode.ReadWrite,
        PixelFormat.Format32bppArgb
    );
    ColorARGB* startingPosition = (ColorARGB*) bitmapData.Scan0;


    for (int i = 0; i < height; i++)
        for (int j = 0; j < width; j++)
        {
            double color = rawImage[i, j];
            byte rgb = (byte)(color * 255);

            ColorARGB* position = startingPosition + j + i * width;
            position->A = 255;
            position->R = rgb;
            position->G = rgb;
            position->B = rgb;
        }

    Image.UnlockBits(bitmapData);
    return Image;
}

public struct ColorARGB
{
    public byte B;
    public byte G;
    public byte R;
    public byte A;

    public ColorARGB(Color color)
    {
        A = color.A;
        R = color.R;
        G = color.G;
        B = color.B;
    }

    public ColorARGB(byte a, byte r, byte g, byte b)
    {
        A = a;
        R = r;
        G = g;
        B = b;
    }

    public Color ToColor()
    {
        return Color.FromArgb(A, R, G, B);
    }
}
Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321
Nikola Davidovic
  • 8,556
  • 1
  • 27
  • 33
  • I'm testing this code and I will accept it as soon as it work fine. – Sameh K. Mohamed Nov 22 '12 at 12:11
  • You should exchange indecies "i,j" in the line "double color = rawImage[j, i]; " because in this form in causes "index out of range exception" – Sameh K. Mohamed Nov 22 '12 at 12:15
  • @SamehKamal Yes sorry, it's because of copy paste. I'll change. Is the code helpful? – Nikola Davidovic Nov 22 '12 at 12:18
  • yes, the image is now converted in less than a second, after taking about 20 seconds, as I am working on very high resolution images, Thanks a lot. – Sameh K. Mohamed Nov 22 '12 at 12:23
  • Can you deploy unsafe code anywhere? Or are there restrictions on certain platforms or use by certain .Net frameworks? – toddmo Oct 01 '17 at 19:03
  • I am, unfortunately, not aware of such limitations. I have usually used such code on mobile devices or when making desktop apps. Did you try to google the answer? Maybe this could help: https://stackoverflow.com/questions/706495/what-are-the-implications-of-using-unsafe-code – Nikola Davidovic Oct 09 '17 at 16:10