8 Stimmen

Warum löst BitmapSource.Create eine ArgumentException aus?

Ich versuche, eine Bitmap aus Rohdaten erstellt, um in WPF zu zeigen, indem Sie ein Bild und eine BitmapSource zu erhalten:

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;

Der Aufruf von BitmapSource.Create löst jedoch eine ArgumentException aus, die besagt, dass "der Wert nicht in den erwarteten Bereich fällt". Ist dies nicht der richtige Weg, dies zu tun? Mache ich diesen Aufruf nicht richtig?

40voto

jason Punkte 227577

Ihre Schrittlänge ist falsch. Stride ist die Anzahl der Bytes, die für eine Scanline der Datei Bitmap. Verwenden Sie also das Folgende:

int stride = ((RenderWidth * 32 + 31) & ~31) / 8;

und ersetzen den letzten Parameter (derzeit 0 ) mit stride wie oben definiert.

Hier ist eine Erklärung für die mysteriöse Schrittformel:

Tatsache: Scanlines müssen an 32-Bit-Grenzen ausgerichtet werden ( Referenz ).

Die naive Formel für die Anzahl der Bytes pro Scanzeile lautet:

(width * bpp) / 8

Dies führt jedoch möglicherweise nicht zu einer Bitmap, die an einer 32-Bit-Grenze ausgerichtet ist, und (Breite * bpp) ist möglicherweise nicht einmal durch 8 teilbar.

Wir zwingen also unsere Bitmap, mindestens 32 Bits in einer Reihe zu haben (wir nehmen an, dass width > 0 ):

width * bpp + 31

und dann sagen wir, dass wir uns nicht um die Bits niedriger Ordnung (Bits 0-4) kümmern, weil wir versuchen, uns an 32-Bit-Grenzen auszurichten:

(width * bpp + 31) & ~31

und dividieren Sie dann durch 8, um wieder auf Bytes zu kommen:

((width * bpp + 31) & ~31) / 8

Die Auffüllung kann wie folgt berechnet werden

int padding = stride - (((width * bpp) + 7) / 8)

Die naive Formel würde lauten

stride - ((width * bpp) / 8)

Aber width * bpp möglicherweise nicht an einer Byte-Grenze ausgerichtet, und wenn dies nicht der Fall ist, würde diese Formel das Auffüllen um ein Byte überzählen. (Man denke an eine 1 Pixel breite Bitmap mit 1 bpp. Der Stride ist 4 und die naive Formel würde sagen, dass das Padding 4 ist, aber in Wirklichkeit sind es 3.) Wir fügen also ein kleines Bit hinzu, um den Fall abzudecken, dass width * bpp keine Byte-Grenze ist, erhalten wir die oben angegebene korrekte Formel.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X