2012-12-19 15 views
14

Come si calcola la dimensione del buffer richiesta per il metodo WriteableBitmap.WritePixels?Calcolo della dimensione del buffer richiesta per il metodo WriteableBitmap.WritePixels

Sto utilizzando il sovraccarico con quattro parametri, il primo è un Int32Rect, il successivo è un array di byte contenente i numeri RGBA per il colore, il terzo è il passo (che è la larghezza della mia bitmap scrivibile moltiplicata per il bit per pixel diviso per 8) e l'ultimo è il buffer (indicato come offset in Intellisense).

sto ottenendo la dimensione buffer non è sufficiente errore runtime nel codice qui sotto:

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); 

Qual è la formula che ho bisogno di utilizzare per calcolare il valore del tampone necessario nel codice sopra?

+0

Quando si dice RGBA, certamente ha 32 bit per pixel. Questo rende 4 byte per pixel. In un 2x 2x il totale è di 16 byte (4 pixel * 4 byte/per pixel). Il tuo 'coulorData' è ovviamente troppo piccolo. – Clemens

+0

@Clemens Vuoi dire che il mio Stride è troppo piccolo? Se no, potresti spiegare come il coloreData sia troppo piccolo, come non capisco. Thankyou – JMK

+0

Stride è semplicemente il numero di byte per riga nel buffer. Hai 4 byte per pixel a 2 pixel per linea (cioè la larghezza del rettangolo di scrittura), risultando in un passo di 8. – Clemens

risposta

11

Il valore del passo viene calcolato come numero di byte per "linea pixel" nel rettangolo scrittura:

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

La dimensione di buffer richiesto è il numero di byte per linea moltiplicato per il numero di righe:

var bufferSize = rect.Height * stride; 

A condizione che si disponga di un rettangolo di scrittura 2x2 e un formato a 32 bit per pixel, ad es. PixelFormats.Pbgra32, si ottiene stride come 8 e bufferSize come 16.

+0

hmm, ora sto ottenendo un errore di Index Outside of Array, avresti qualche idea sul perché? – JMK

+0

"Ora" significa che il buffer è in realtà lungo 16 byte? – Clemens

+0

Questo è corretto sì – JMK

0

Non sono sicuro, ma provo questo funziona per 24 bit RGB

{ 
    //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

La domanda è su come calcolare la dimensione del buffer. – Clemens

+0

E quel codice non verrà compilato poiché si scrive 'byte []' per il parametro 'pixels'. – Clemens

3

Il passo è semplicemente la larghezza in byte del buffer di input. Si chiama falcata, perché a volte c'è una memoria extra dietro ogni linea di un'immagine, che rende impossibile usare la larghezza dell'immagine per leggere ogni riga di un'immagine.

Quindi nel vostro esempio, questo è 2. Non è necessario calcolare nulla con i bit per pixel della bitmap, il metodo WritePixels conosce tutte queste informazioni. È necessario fornire le informazioni su come sono strutturati i dati di input.

Tuttavia, come indicato nell'altra risposta, il tuo esempio non funzionerà se la bitmap è anch'essa 2x2. Quindi la coordinata di partenza sarebbe 0,0.

EDIT:

Quando guardo più da vicino il tuo esempio, vedo l'errore. Tu dici il coloreData è l'input color. Ma questo è input per pixel. Quindi, se si desidera modificare un rettangolo di 2x2, è necessario quanto segue InputData:

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

E poi il byte per pixel è uguale a quello della bitmap, in modo che sia 4, volte la larghezza di ogni riga (2), rende totale 8.

+0

"Quindi nel tuo esempio, questo è 2" è sbagliato. Il passo è 2 (pixel) * 4 (byte per pixel) == 8 (byte) invece. – Clemens

+0

"Non è necessario calcolare nulla con i bit per pixel della bitmap" è anche sbagliato. Per calcolare la falcata dalla larghezza del rettangolo di scrittura, è necessario il numero di byte per pixel. – Clemens

+0

Nel suo esempio vedo chiaramente che ha 4 byte nei suoi dati di input, quindi 1 byte per pixel. Non si tratta dei byte per pixel della bitmap, ma dei byte per pixel dei dati di input. – Geerten

1

Io lavoro con questo. 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

Ecco Microsoft del codice che esegue il controllo all'interno 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

Sebbene utente Clemens ha risposto alla domanda relativa alla dimensione del buffer riflessa, l'interrogante non era a conoscenza che egli calcolata la dimensione del buffer già corretto e il problema era da qualche altra parte.

Mentre i dettagli vengono forniti e discussi nei commenti, manca uno snippet completo (e completo esempio di utilizzo di .WritePixels (senza .CopyPixels)). Qui è (ho scansionato domande simili, ma questo è stato il posto migliore):

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); 
Problemi correlati