开发者

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


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.


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.


I just tried parallel For.
It doesn't work without SyncLock on the bitmap.
It says the object is in use.
So it pretty much just works, in serial lol... what a mess.

    For xx As Integer = 0 To 319
        pq.ForAll(Sub(yy)
                      Dim Depth = getDepthValue(Image, xx, yy) / 2047
                      Dim NewColor = Depth * 128
                      Dim Pixel = Color.FromArgb(NewColor, NewColor, NewColor)
                      SyncLock Bmp2
                          Bmp2.SetPixel(xx, yy, Pixel)
                      End SyncLock
                  End Sub)
    Next

In case you're wondering, this is converting kinect's depth map -> bitmap.
Kinect's depth range is from 11bit(0-2047) and represents distance not color.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜