How to convert bitmap to byte [,] faster?

I wrote a 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] = cR; result[i, j, 1] = cG; result[i, j, 2] = cB; } } return result; } 

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

EDIT:
Ok, I found this: http://msdn.microsoft.com/en-us/library/system.drawing.imaging.bitmapdata.aspx
Good example. My question is only about Marshal.Copy . Can I copy data directly to byte[,,] ?

EDIT 2: OK, sometimes I get weird pixel values ​​and they don't seem to follow the rule r0 g0 b0 r1 g1 b1. Why? Nothing. It revealed.

EDIT 3: Do it. 0.13s vs 5.35s :)

+4
source share
3 answers

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

GetPixel painfully, painfully slow, which makes it (ironically) completely unsuitable for manipulating individual pixels.

+17
source

I’m interested in this for a while.

In .NET 4.0, Microsoft introduced a parallel library. Basically what it is, there is the Parallel.For method, which automatically generates many threads to help with the job. For example, if you originally had For (int i = 0; i <3; i ++) {code ...}, the parallel.For loop would probably create 3 threads, and each thread would have a different value for i , internal code. Therefore, the best thing I can offer is a Parallel.For loop with

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

upon receipt of the pixel.

If you need more explanation on parallelism, I cannot help you before you take some time to study it, since this is a huge area of ​​study.

+1
source

I just tried parallel to For .
This does not work without SyncLock on the bitmap.
He says the object is being used.
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 are interested, this is a kinect depth map -> bitmap conversion.
The Kinect depth range is between 11 bits (0-2047) and represents the distance without color.

0
source

Source: https://habr.com/ru/post/1335312/


All Articles