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

时间:2011-01-12 21:35:43

标签: c# winforms image-processing bitmap

我写了函数:

    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;
    }

但转换1800x1800图片需要将近6秒钟。我能更快地完成这件事吗?

修改
好的,我发现了这个:http://msdn.microsoft.com/en-us/library/system.drawing.imaging.bitmapdata.aspx
有很好的例子。我唯一的问题是关于Marshal.Copy。我可以将数据直接复制到byte[,,]吗?

编辑2: 好的,有时我得到奇怪的像素值,它们似乎没有遵循r0 g0 b0 r1 g1 b1规则。为什么?没关系。想出来了。

编辑3: 做好了。 0,13s vs 5,35s:)

3 个答案:

答案 0 :(得分:17)

使用从BitmapData返回的Bitmap.LockBits对象,可以大大提高速度。谷歌“C#Bitmap LockBits”就是一堆例子。

GetPixel痛苦,痛苦地缓慢,使(具有讽刺意味)完全不适合操纵单个像素。

答案 1 :(得分:1)

我一直想知道这件事。

在.NET 4.0中,Microsoft引入了并行库。基本上它的作用是有一个Parallel.For方法,它会自动产生许多线程来帮助完成工作。 例如,如果你最初有一个For(int i = 0; i&lt; 3; i ++){code ...},一个parallel.For循环可能会创建3个线程,每个线程将有一个不同的值,我穿过内码。所以我能建议的最好的东西是带有

的Parallel.For循环
Color c
 lock(obraz) 
{
  c =  obraz.GetPixel(..)
}
...
获取像素时

如果你需要更多关于并行性的解释,在你花一些时间研究它之前我无法真正帮助你,因为它是一个巨大的研究领域。

答案 2 :(得分:0)

我刚尝试并行For 如果位图没有SyncLock,它就无法工作 它说该物体正在使用中 所以它几乎只是工作,连续大声笑......真是一团糟。

    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

如果你想知道,这是转换kinect的depth map -> bitmap Kinect的深度范围是11位(0-2047),表示距离而不是颜色。