简体   繁体   English

如何将Bitmap转换为byte [,,]更快?

[英]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. 但转换1800x1800图像需要将近6秒钟。 Can I do this faster? 我能更快地做到吗?

EDIT: 编辑:
OK, I found this: http://msdn.microsoft.com/en-us/library/system.drawing.imaging.bitmapdata.aspx 好的,我发现了这个: http//msdn.microsoft.com/en-us/library/system.drawing.imaging.bitmapdata.aspx
There is nice example. 有很好的例子。 Only question I have is about Marshal.Copy . 我唯一的问题是关于Marshal.Copy Can I make it copy data directly into byte[,,] ? 我可以将数据直接复制到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. 编辑2: 好的,有时我得到奇怪的像素值,它们似乎没有遵循r0 g0 b0 r1 g1 b1规则。 Why? 为什么? Never mind. 没关系。 Figured it out. 弄清楚了。

EDIT 3: Made it. 编辑3:做到了。 0,13s vs 5,35s :) 0,13s vs 5,35s :)

You can speed this up considerably by using a BitmapData object which is returned from Bitmap.LockBits . 通过使用从Bitmap.LockBits返回的BitmapData对象,可以大大提高速度。 Google "C# Bitmap LockBits" for a bunch of examples. Google“C#Bitmap LockBits”提供了大量示例。

GetPixel is painfully, painfully slow, making it (ironically) completely unsuitable for the manipulation of individual pixels. GetPixel令人痛苦,痛苦地缓慢,使它(具有讽刺意味)完全不适合操纵单个像素。

I've been wondering this for a while. 我一直在想这个问题。

In .NET 4.0 Microsoft introduced the Parallel library. 在.NET 4.0中,Microsoft引入了并行库。 Basically what this does is there is a Parallel.For method that will automatically spawn off numerous threads to help with the work. 基本上它的作用是有一个Parallel.For方法,它会自动产生许多线程来帮助完成工作。 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. 例如,如果你最初有一个For(int i = 0; i <3; i ++){code ...},一个parallel.For循环可能会创建3个线程,每个线程将有一个不同的值,我穿过内码。 So the best thing i can suggest is a Parallel.For loop with a 所以我能建议的最好的东西是一个带有一个的Parallel.For循环

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 . 我刚试过并行For
It doesn't work without SyncLock on the bitmap. 如果没有位图上的SyncLock ,它就无法工作。
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的depth map -> bitmap
Kinect's depth range is from 11bit(0-2047) and represents distance not color. Kinect的深度范围是11位(0-2047),表示距离而不是颜色。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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