Calculating the required buffer size for the WriteableBitmap.WritePixels method

匿名 (未验证) 提交于 2019-12-03 02:23:02

问题:

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, the next is a byte array containing the RGBA numbers for the colour, the third is the stride (which is the width of my writeable bitmap multiplied by the bits per pixel divided by 8), and the last is the buffer (referred to as the offset in Intellisense).

I am getting the Buffer size is not sufficient runtime error in the below 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); 

What is the formula I need to use to calculate the buffer value needed in the above code?

回答1:

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.



回答2:

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.



回答3:

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


回答4:

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


回答5:

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


回答6:

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


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!