Por que o bitmapsource.create joga uma argumentação?
-
22-09-2019 - |
Pergunta
Estou tentando criar um bitmap a partir de dados brutos para mostrar no WPF, usando uma imagem e um 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;
No entanto, a chamada para o bitmapsource.create lança uma argumentação, dizendo "o valor não se enquadra no intervalo esperado". Não é essa a maneira de fazer isso? Não estou fazendo essa chamada corretamente?
Solução
Seu passo está incorreto. STRIDE é o número de bytes alocados para uma linha de varredura do bitmap. Assim, use o seguinte:
int stride = ((RenderWidth * 32 + 31) & ~31) / 8;
e substitua o último parâmetro (atualmente 0
) com stride
conforme definido acima.
Aqui está uma explicação para a fórmula misteriosa do passo:
Fato: as linhas de varredura devem estar alinhadas em limites de 32 bits (referência).
A fórmula ingênua para o número de bytes por scanline seria:
(width * bpp) / 8
Mas isso pode não nos dar um bitmap alinhado em um limite de 32 bits e (largura * bpp) pode nem ter sido divisível por 8.
Então, o que fazemos é forçar nosso bitmap a ter pelo menos 32 bits seguidos (assumimos que width > 0
):
width * bpp + 31
E então dizemos que não nos importamos com os bits de ordem baixa (bits 0--4) porque estamos tentando alinhar-se nos limites de 32 bits:
(width * bpp + 31) & ~31
e depois divida por 8 para voltar aos bytes:
((width * bpp + 31) & ~31) / 8
O preenchimento pode ser calculado por
int padding = stride - (((width * bpp) + 7) / 8)
A fórmula ingênua seria
stride - ((width * bpp) / 8)
Mas width * bpp
pode não se alinhar em um limite de byte e, quando não, essa fórmula contaria demais o preenchimento por um byte. (Pense em um bitmap largo de 1 pixels usando 1 bpp. O passo é 4 e a fórmula ingênua diria que o preenchimento é 4, mas na realidade é 3.) Por isso, adicionamos um pouco para cobrir o caso que width * bpp
não é um limite de byte e, em seguida, obtemos a fórmula correta dada acima.