How do I calculate the required buffer size for the WriteableBitmap.WritePixels method?
I am using the overload taking four parameters, the first is an Int32Rect, th
Here's Microsoft's reflected code that performs the check within 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 }));
}
Although user Clemens answered the question concerning the buffer size, the questioner was not aware that he calculated the buffer size already correct and the problem was somewhere else.
While details are given and discussed in comments there is lacking one comprehensive snippet (and complete usage example of .WritePixels (without .CopyPixels) as well). Here it is (I scanned similar questions, but this has been the best place):
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);
I am work with this. 60z fs
this.playerOpacityMaskImage.WritePixels(
new Int32Rect(0, 0, this.depthWidth, this.depthHeight),
this.greenScreenPixelData,
this.depthWidth * ((this.playerOpacityMaskImage.Format.BitsPerPixel + 7) / 8),
0);
The stride value is calculated as the number of bytes per "pixel line" in the write rectangle:
var stride = (rect.Width * bitmap.Format.BitsPerPixel + 7) / 8;
The required buffer size is the number of bytes per line multiplied by the number of lines:
var bufferSize = rect.Height * stride;
Provided that you have a 2x2 write rectangle and a 32-bits-per-pixel format, e.g. PixelFormats.Pbgra32
, you get stride
as 8 and bufferSize as 16.
I am not sure but try this works for 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));
}
The stride is simply the width in bytes of your input buffer. It is called stride, because sometimes there is extra memory behind each line of an image, which makes it impossible to use the width of the image to read each line of an image.
So in your example, this is 2. You do not need to calculate anything with the bits per pixel of the bitmap, the WritePixels method knows all this information. You need to provide the information about how your input data is structured.
However, as mentioned in the other answer, your example won't work if the bitmap is also 2x2. Then the starting coordinate would be 0,0.
EDIT:
When I look closer at your example, I see the mistake. You say the colourData is the input color. But this is input per pixel. So if you want to change a rect of 2x2, you need the following inputdata:
byte[] colourData = { 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0 };
And then the bytes per pixel is equal to that of the bitmap, so that is 4, times the width of each line (2), makes total 8.