2012-12-19 28 views
14

Jak obliczyć wymagany rozmiar bufora dla metody WriteableBitmap.WritePixels?Obliczanie wymaganego rozmiaru bufora dla metody WriteableBitmap.WritePixels

Używam przeciążenia przyjmującego cztery parametry, pierwszy to Int32Rect, następny to tablica bajtów zawierająca liczby RGBA dla koloru, trzecia to krok (który jest szerokość mojej zapisywalnej mapy bitowej pomnożonej przez bity na piksel podzielone przez 8), a ostatni to bufor (określany jako przesunięcie w Intellisense).

Dostaję rozmiar bufora nie jest wystarczający błąd wykonawcze w poniższym kodzie:

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

Jaka jest formuła muszę użyć do obliczenia wartości bufora potrzebnego w powyższym kodzie?

+0

Kiedy mówisz RGBA, na pewno mają 32 bity na piksel. To sprawia, że ​​4 bajty na piksel. W 2x2 rect całkowity to 16 bajtów (4 piksele * 4 bajty/piksel). Twoja 'coulorData' jest oczywiście za mała. – Clemens

+0

@Clemens Czy masz na myśli mój krok jest za mały? Jeśli nie, to możesz wyjaśnić, jak colorData jest za mała, czego nie rozumiem. Thankyou – JMK

+0

Stride to po prostu liczba bajtów na linię w buforze. Masz 4 bajty na piksel przy 2 pikselach na linię (tj. Szerokość prostokąta zapisu), co skutkuje krokiem 8. – Clemens

Odpowiedz

11

wartość kroku oblicza się jako liczbę bajtów na „linii pikseli” w zapisu prostokąta:

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

Wymagany rozmiar bufora jest liczbą bajtów w linii pomnożona przez liczbę wierszy:

var bufferSize = rect.Height * stride; 

Pod warunkiem, że masz format zapisu 2x2 i format 32 bitów na piksel, np. PixelFormats.Pbgra32, masz stride jako 8 i BUFFERSIZE jako 16.

+0

hmm, teraz otrzymuję błąd wskaźnika poza tablicą, czy miałbyś wgląd w to, dlaczego? – JMK

+0

"Teraz" oznacza, że ​​twój bufor ma 16 bajtów długości? – Clemens

+0

Zgadza się tak – JMK

0

Nie jestem pewien, ale spróbuj to działa na 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

Pytanie dotyczy sposobu obliczania rozmiaru bufora. – Clemens

+0

Ten kod nie zostanie skompilowany, ponieważ wpisujesz 'byte []' dla parametru 'pixels'. – Clemens

3

kroczyć po prostu szerokość w bajtach swojego bufora wejściowego. Nazywa się to krokiem, ponieważ czasami za każdą linią obrazu znajduje się dodatkowa pamięć, co uniemożliwia wykorzystanie szerokości obrazu do odczytania każdej linii obrazu.

Tak więc w twoim przykładzie jest to 2. Nie musisz niczego obliczyć za pomocą bitów na piksel mapy bitowej, metoda WritePixels zna wszystkie te informacje. Musisz podać informacje o strukturze danych wejściowych.

Jednak, jak wspomniano w drugiej odpowiedzi, twój przykład nie zadziała, jeśli bitmapa jest również 2x2. Wtedy współrzędna początkowa wynosiłaby 0,0.

EDIT:

Kiedy przyjrzeć się bliżej na swoim przykładzie, widzę błąd. Mówisz, że colorData jest wejściem kolor. Ale jest to wejście na piksel. Więc jeśli chcesz zmienić rect z 2x2, trzeba następujące inputdata:

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

a następnie bajtów na piksel jest równy bitmapy, dzięki czemu jest 4 razy szerokość każdej linii (2), łącznie 8.

+0

"W twoim przykładzie jest to 2" jest błędne. Krok to 2 (piksele) * 4 (bajty na piksel) == 8 (bajty). – Clemens

+0

"Nie trzeba obliczyć niczego za pomocą bitów na piksel mapy bitowej" również jest błędne. Aby obliczyć krok z szerokości prostokąta zapisu, potrzebujesz liczby bajtów na piksel. – Clemens

+0

W jego przykładzie wyraźnie widzę, że ma 4 bajty w swoich danych wejściowych, więc 1 bajt na piksel. Nie dotyczy to bajtów na piksel mapy bitowej, ale bajtów na piksel danych wejściowych. – Geerten

1

Pracuję z tym. 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

Oto Microsoft kod, który wykonuje kontrolę w 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

Chociaż użytkownik Clemens odpowiedział na pytanie o rozmiar bufora odbicie, pytający nie był świadomy, że obliczony rozmiar bufora już poprawne, a problem był gdzie indziej.

Podczas gdy w komentarzach podano i omówiono szczegóły, brakuje jednego obszernego fragmentu (i pełnego przykładu użycia .WritePixels (bez rozszerzenia .CopyPixels)). Oto ona (I skanowane podobne pytania, ale to było najlepsze miejsce):

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