Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert Bitmap to byte[,,] faster?

I wrote function:

    public static byte[, ,] Bitmap2Byte(Bitmap image)
    {
        int h = image.Height;
        int w = image.Width;

        byte[, ,] result= new byte[w, h, 3];

        for (int i = 0; i < w; i++)
        {
            for (int j = 0; j < h; j++)
            {
                Color c= image.GetPixel(i, j);
                result[i, j, 0] = c.R;
                result[i, j, 1] = c.G;
                result[i, j, 2] = c.B;
            }
        }

        return result;
    }

But it takes almost 6 seconds to convert 1800x1800 image. Can I do this faster?

EDIT:
OK, I found this: http://msdn.microsoft.com/en-us/library/system.drawing.imaging.bitmapdata.aspx
There is nice example. Only question I have is about Marshal.Copy. Can I make it copy data directly into byte[,,] ?

EDIT 2: OK, sometimes I got strange values of pixels and they do not seem to follow r0 g0 b0 r1 g1 b1 rule. Why? Never mind. Figured it out.

EDIT 3: Made it. 0,13s vs 5,35s :)

like image 782
Miko Kronn Avatar asked Dec 03 '22 03:12

Miko Kronn


2 Answers

You can speed this up considerably by using a BitmapData object which is returned from Bitmap.LockBits. Google "C# Bitmap LockBits" for a bunch of examples.

GetPixel is painfully, painfully slow, making it (ironically) completely unsuitable for the manipulation of individual pixels.

like image 186
MusiGenesis Avatar answered Dec 04 '22 18:12

MusiGenesis


I've been wondering this for a while.

In .NET 4.0 Microsoft introduced the Parallel library. Basically what this does is there is a Parallel.For method that will automatically spawn off numerous threads to help with the work. For instance if you originally had a For(int i =0;i<3;i++){ code...}, A parallel.For loop would probably create 3 threads and each thread would have a different value for i running through the inner code. So the best thing i can suggest is a Parallel.For loop with a

Color c
 lock(obraz) 
{
  c =  obraz.GetPixel(..)
}
...

when getting the pixel.

If you need any more explanation on parallelism I can't really assist you before you take some time to study it as it is a huge area of study.

like image 43
dko Avatar answered Dec 04 '22 16:12

dko