C # Эффективное получение данных пикселей из System.Drawing.Bitmap - PullRequest
12 голосов
/ 10 сентября 2011

У меня есть несколько (~ 2 ГБ) сырых 24-битных RGB-файлов на жестком диске. Теперь я хочу извлечь его часть и масштабировать до нужного размера.
(Допустимы только 1, 1/2, 1/4, 1/8, ..., 1/256)

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

В качестве следующего шага я создаю растровое изображение из вновь созданного массива.
Это делается с помощью указателя, поэтому копирование данных не требуется.
Затем я вызываю GetThumbnailImage для растрового изображения, которое создает новое растровое изображение с правильными размерами.

Теперь я хочу вернуть необработанные данные пикселей (в виде байтового массива) недавно созданного растрового изображения. Но для этого я сейчас копирую данные с помощью LockBits в новый массив.

Итак, мой вопрос: Есть ли способ получить данные пикселей из растрового изображения в байтовый массив, не копируя его?

Что-то вроде:

var bitmapData = scaledBitmap.LockBits(...)
byte[] rawBitmapData = (byte[])bitmapData.Scan0.ToPointer()
scaledBitmap.UnlockBits(bitmapData)
return rawBitmapData 

Я хорошо знаю, что это не работает, это всего лишь пример того, чего я в основном хочу достичь.

1 Ответ

18 голосов
/ 10 сентября 2011

Я думаю, что это ваша лучшая ставка.

var bitmapData = scaledBitmap.LockBits(...);
var length = bitmapData.Stride * bitmapData.Height;

byte[] bytes = new byte[length];

// Copy bitmap to byte[]
Marshal.Copy(bitmapData.Scan0, bytes, 0, length);
scaledBitmap.UnlockBits(bitmapData);

Вы должны скопировать ее, если хотите получить пропуск байта [].

Вам не нужно удалятьбайты, которые были выделены, вам просто нужно избавиться от исходного объекта Bitmap, когда это будет сделано, поскольку он реализует IDisposable.

...