Почему BitmapSource.Create выдает исключение ArgumentException?
-
22-09-2019 - |
Вопрос
Я пытаюсь получить растровое изображение, созданное из необработанных данных, для отображения в WPF, используя Image и BitmapSource:
Int32[] data = new Int32[RenderHeight * RenderWidth];
for (Int32 i = 0; i < RenderHeight; i++)
{
for (Int32 j = 0; j < RenderWidth; j++)
{
Int32 index = j + (i * RenderHeight);
if (i + j % 2 == 0)
data[index] = 0xFF0000;
else
data[index] = 0x00FF00;
}
}
BitmapSource source = BitmapSource.Create(RenderWidth, RenderHeight, 96.0, 96.0, PixelFormats.Bgr32, null, data, 0);
RenderImage.Source = source;
Однако вызов BitmapSource.Create выдает исключение ArgumentException, сообщающее "Значение не попадает в ожидаемый диапазон".Разве это не тот способ, которым нужно это сделать?Я что, неправильно делаю этот звонок?
Решение
Ваш шаг неверен.Шаг - это количество байтов, выделенных для одной строки сканирования растрового изображения.Таким образом, используйте следующее:
int stride = ((RenderWidth * 32 + 31) & ~31) / 8;
и замените последний параметр (в данный момент 0
) с stride
как определено выше.
Вот объяснение таинственной формулы шага:
Факт:Линии сканирования должны быть выровнены по 32-разрядным границам (ссылка).
Наивная формула для количества байтов в строке сканирования была бы следующей:
(width * bpp) / 8
Но это может не дать нам растровое изображение, выровненное по 32-битной границе, и (ширина * bpp), возможно, даже не была кратна 8.
Итак, что мы делаем, так это заставляем наше растровое изображение содержать не менее 32 бит подряд (мы предполагаем, что width > 0
):
width * bpp + 31
и затем мы говорим, что нас не волнуют биты младшего порядка (биты 0--4), потому что мы пытаемся выровнять 32-битные границы:
(width * bpp + 31) & ~31
а затем разделите на 8, чтобы вернуться к байтам:
((width * bpp + 31) & ~31) / 8
Заполнение может быть вычислено с помощью
int padding = stride - (((width * bpp) + 7) / 8)
Наивная формула была бы такой
stride - ((width * bpp) / 8)
Но width * bpp
может не выровняться по границе байта, и когда этого не произойдет, эта формула превысит количество заполнений на байт.(Представьте себе растровое изображение шириной в 1 пиксель с использованием 1 битов в секунду.Шаг равен 4, и наивная формула сказала бы, что отступ равен 4, но на самом деле это 3.) Итак, мы добавляем немного, чтобы охватить случай, когда width * bpp
не является границей байта, и тогда мы получаем правильную формулу, приведенную выше.