Как быстрее преобразовать растровое изображение в байт [,,]? - PullRequest
4 голосов
/ 13 января 2011

Я написал функцию:

    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: ОК, иногда я получаю странные значения пикселей, и они, кажется, не следуютправило g1 b1.Почему? Неважно.Разобрался.

РЕДАКТИРОВАТЬ 3: Сделано.0,13 с против 5,35 с:)

Ответы [ 3 ]

17 голосов
/ 13 января 2011

Вы можете значительно ускорить это, используя объект BitmapData, который возвращается из Bitmap.LockBits. Google "C # Bitmap LockBits" для нескольких примеров.

GetPixel мучительно, мучительно медленно, что делает его (по иронии судьбы) совершенно непригодным для манипулирования отдельными пикселями.

1 голос
/ 13 января 2011

Мне уже давно интересно это.

В .NET 4.0 Microsoft представила библиотеку Parallel.По сути, это метод Parallel.For, который автоматически порождает множество потоков, чтобы помочь с работой.Например, если у вас изначально был цикл For (int i = 0; i <3; i ++) {code ...}, параллельный. For, вероятно, создал бы 3 потока, и каждый поток имел бы свое значение для i, проходящего черезвнутренний кодПоэтому лучшее, что я могу предложить, это цикл Parallel.For с </p>

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

при получении пикселя.

Если вам нужно больше объяснений параллелизма, я не могу вам помочьпрежде чем вы потратите время на его изучение, так как это огромная область изучения.

0 голосов
/ 24 сентября 2011

Я только что попробовал параллель 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

Если вам интересно, это конвертирует depth map -> bitmap.
kinect. Диапазон глубины Kinect от 11 бит (0-2047) и представляет расстояние, а не цвет.

...