2012-12-19 7 views
14

Wie berechne ich die erforderliche Puffergröße für die WriteableBitmap.WritePixels-Methode?Berechnen der erforderlichen Puffergröße für die WriteableBitmap.WritePixels-Methode

Ich verwende die Überladung unter vier Parameter, der erste ist ein Int32Rect, der nächste ist ein Byte-Array mit den RGBA-Zahlen für die Farbe, der dritte ist der Schritt (das ist die Breite meiner beschreibbaren Bitmap mit dem multipliziert Bits pro Pixel dividiert durch 8), und der letzte ist der Puffer (in Intellisense als Offset bezeichnet).

Ich erhalte die Puffergröße nicht ausreichend ist Laufzeitfehler in dem folgenden Code:

byte[] colourData = { 0, 0, 0, 0 }; 

var xCoordinate = 1; 
var yCoordinate = 1; 

var width = 2; 
var height = 2; 

var rect = new Int32Rect(xCoordinate, yCoordinate, width, height); 

var writeableBitmap = new WriteableBitmap(MyImage.Source as BitmapSource); 

var stride = width*writeableBitmap.Format.BitsPerPixel/8; 

writeableBitmap.WritePixels(rect, colourData, stride,0); 

Was die Formel ich brauche, ist zu verwenden, um den Pufferwert in dem obigen Code erforderlich zu berechnen?

+0

Wenn Sie RGBA sagen, Sie haben sicherlich 32 Bit pro Pixel. Das macht 4 Bytes pro Pixel. In einem 2x2-Rect beträgt die Summe 16 Bytes (4 Pixel * 4 Bytes/pro Pixel). Deine 'coulorData' sind offensichtlich zu klein. – Clemens

+0

@Clemens Meinst du, mein Schritt ist zu klein? Wenn nicht, könntest du erklären, wie die colorData zu klein ist, wie ich es nicht verstehe. Danke – JMK

+0

Stride ist einfach die Anzahl der Bytes pro Zeile im Puffer. Sie haben 4 Bytes pro Pixel bei 2 Pixeln pro Zeile (d. H. Die Breite des Schreibrechtecks), was einen Schritt von 8 ergibt. – Clemens

Antwort

11

Der Schrittwert wird als die Anzahl der Bytes berechnet, pro „Pixelzeile“ in dem Schreib Rechteck:

var stride = (rect.Width * bitmap.Format.BitsPerPixel + 7)/8; 

Die erforderliche Puffergröße ist die Anzahl der Bytes pro Zeile durch die Anzahl von Zeilen multipliziert:

var bufferSize = rect.Height * stride; 

Vorausgesetzt, Sie haben ein 2x2-Rechteck schreiben und ein 32-Bit-pro-Pixel-Format, z PixelFormats.Pbgra32, erhalten Sie stride als 8 und buffer als 16.

+0

hmm, jetzt bekomme ich einen Index Outside of Array error, hätten Sie einen Einblick in warum? – JMK

+0

"Now" bedeutet, dass Ihr Puffer tatsächlich 16 Bytes lang ist? – Clemens

+0

Das stimmt ja ja – JMK

0

Ich bin nicht sicher, aber versuchen Sie dies für 24-Bit-RGB arbeitet

{ 
    //your code 
     var stride = width * 3; 
     WriteableBitmap bmp = new WriteableBitmap(width, height, 96, 96, PixelFormats.Bgr24, null); 
     bmp.WritePixels(new System.Windows.Int32Rect(0, 0, width , height),byte[],stride,0)); 

    } 
+1

Die Frage ist, wie man die Puffergröße berechnet. – Clemens

+0

Und dieser Code wird nicht kompiliert, da Sie 'byte []' für den 'Pixel' Parameter schreiben. – Clemens

3

Der Schritt einfach die Breite in Bytes des Eingangspuffers ist. Es wird als Schrittweite bezeichnet, da manchmal hinter jeder Zeile eines Bildes zusätzlicher Speicher vorhanden ist, was es unmöglich macht, die Breite des Bildes zum Lesen jeder Zeile eines Bildes zu verwenden.

Also in Ihrem Beispiel ist dies 2. Sie müssen nichts mit den Bits pro Pixel der Bitmap berechnen, die WritePixels-Methode kennt alle diese Informationen. Sie müssen Informationen zur Struktur Ihrer Eingabedaten bereitstellen.

Allerdings, wie in der anderen Antwort erwähnt, wird Ihr Beispiel nicht funktionieren, wenn die Bitmap auch 2x2 ist. Dann wäre die Startkoordinate 0,0.

EDIT:

Wenn ich an Ihrem Beispiel näher betrachten, ich den Fehler zu sehen. Sie sagen, die colorData ist die Eingabe Farbe. Aber das ist Eingabe pro Pixel. Wenn Sie also eine rect von 2x2 ändern möchten, müssen Sie die folgenden Eingangsdaten:

byte[] colourData = { 0, 0, 0, 0, 0, 0, 0, 0, 
         0, 0, 0, 0, 0, 0, 0, 0 }; 

Und dann pro Pixel die Bytes an, dass der Bitmap gleich ist, so dass 4, mal die Breite jeder Linie (2), macht insgesamt 8.

+0

"Also in Ihrem Beispiel ist dies 2" ist falsch. Der Schritt ist stattdessen 2 (Pixel) * 4 (Bytes pro Pixel) == 8 (Bytes). – Clemens

+0

"Sie müssen nichts mit den Bits pro Pixel der Bitmap berechnen" ist auch falsch. Um den Schritt aus der Breite des Schreibrechtecks ​​zu berechnen, benötigen Sie die Anzahl der Bytes pro Pixel. – Clemens

+0

In seinem Beispiel sehe ich deutlich, dass er 4 Bytes in seinen Eingabedaten hat, also 1 Byte pro Pixel. Es handelt sich nicht um die Bytes pro Pixel der Bitmap, sondern um die Bytes pro Pixel der Eingabedaten. – Geerten

1

Ich arbeite mit diesem. 60z fs

this.playerOpacityMaskImage.WritePixels(
       new Int32Rect(0, 0, this.depthWidth, this.depthHeight), 
       this.greenScreenPixelData, 
       this.depthWidth * ((this.playerOpacityMaskImage.Format.BitsPerPixel + 7)/8), 
       0); 
3

Code Hier ist Microsofts reflektiert, die die Prüfung durchführt, innerhalb CopyPixels

 int num = ((sourceRect.Width * this.Format.BitsPerPixel) + 7)/8; 
     if (stride < num) 
     { 
      throw new ArgumentOutOfRangeException("stride", MS.Internal.PresentationCore.SR.Get("ParameterCannotBeLessThan", new object[] { num })); 
     } 
     int num2 = (stride * (sourceRect.Height - 1)) + num; 
     if (bufferSize < num2) 
     { 
      throw new ArgumentOutOfRangeException("buffer", MS.Internal.PresentationCore.SR.Get("ParameterCannotBeLessThan", new object[] { num2 })); 
     } 
1

Obwohl Benutzer Clemens die Frage nach der Puffergröße beantwortet, war der Fragesteller nicht bewusst, dass er die Puffergröße bereits berechnet richtig und das Problem war woanders.

Während Details in Kommentaren gegeben und diskutiert werden, fehlt ein umfassendes Snippet (und vollständiges Verwendungsbeispiel von .WritePixels (auch ohne .CopyPixels)). Hier ist es (ich ähnliche Fragen gescannt, aber dies ist der beste Ort gewesen):

var dpiX = 96; 

var writeableBitmap = new WriteableBitmap(width, height, dpiX, dpiX, PixelFormats.Bgra32, null); // Pixelformat of Bgra32 results always in 4 bytes per pixel 
int bytesPerPixel = (writeableBitmap.Format.BitsPerPixel + 7)/8; // general formula 
int stride = bytesPerPixel * width; // general formula valid for all PixelFormats 

byte[] pixelByteArrayOfColors = new byte[stride * height]; // General calculation of buffer size 

// The numbers in the array are indices to the used BitmapPalette, 
//  since we initialized it with null in the writeableBitmap init, they refer directly to RGBA, but only in this case. 
// Choose a light green color for whole bitmap (for not easy to find commented MSDN example with random colors, see https://msdn.microsoft.com/en-us/library/system.windows.media.imaging.writeablebitmap(VS.85).aspx 
for (int pixel = 0; pixel < pixelByteArrayOfColors.Length; pixel += bytesPerPixel) 
{ 
    pixelByteArrayOfColors[pixel] = 0;  // blue (depends normally on BitmapPalette) 
    pixelByteArrayOfColors[pixel + 1] = 255; // green (depends normally on BitmapPalette) 
    pixelByteArrayOfColors[pixel + 2] = 0; // red (depends normally on BitmapPalette) 
    pixelByteArrayOfColors[pixel + 3] = 50; // alpha (depends normally on BitmapPalette) 
} 

writeableBitmap.WritePixels(new Int32Rect(0, 0, width, height), pixelByteArrayOfColors, stride, 0);