Pourquoi BitmapSource.Create jeter un ArgumentException?
-
22-09-2019 - |
Question
Je suis en train d'obtenir un bitmap créé à partir des données brutes à afficher dans WPF, à l'aide d'une image et un 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;
Cependant, l'appel à BitmapSource.Create lance une ArgumentException, disant: « La valeur ne tombe pas dans la plage attendue ». Est-ce pas la façon de le faire? Est-ce que je ne fais cet appel correctement?
La solution
Votre foulée est incorrect. Enjambée est le nombre d'octets affectés à une ligne de balayage de la bitmap. Ainsi, utilisez ce qui suit:
int stride = ((RenderWidth * 32 + 31) & ~31) / 8;
et remplacer le dernier paramètre (actuellement 0
) avec stride
tel que défini ci-dessus.
Voici une explication de la formule mystérieuse foulée:
Fait: Scanlines doivent être alignées sur des limites de 32 bits ( de référence) .
La formule naïf pour le nombre d'octets par ligne de balayage serait:
(width * bpp) / 8
Mais cela pourrait ne pas nous donner une image bitmap aligné sur une limite de 32 bits et (largeur * BPP) aurait même pu pas divisible par 8.
Alors, ce que nous faisons est que nous forcer notre bitmap d'avoir au moins 32 bits dans une rangée (nous supposons que width > 0
):
width * bpp + 31
et alors nous disons que nous ne nous soucions pas les bits de poids faible (bits 0 à -4) parce que nous essayons d'aligner sur les limites 32 bits:
(width * bpp + 31) & ~31
puis diviser par 8 pour revenir à octets:
((width * bpp + 31) & ~31) / 8
Le rembourrage peut être calculée par
int padding = stride - (((width * bpp) + 7) / 8)
La formule naïve serait
stride - ((width * bpp) / 8)
Mais width * bpp
pourrait ne pas aligner sur une limite d'octet et quand il n'a pas cette formule plus compter le rembourrage par un octet. (Pensez à un bitmap large de 1 pixel en utilisant 1 BPP. La foulée est 4 et la formule naïve dirait que le rembourrage est 4, mais en réalité il est 3.) Donc, nous ajoutons un peu pour couvrir le cas où width * bpp
est pas limite d'octet, puis nous obtenons la bonne formule donnée ci-dessus.