wpf 计算 WriteableBitmap.WritePixels 方法所需的缓冲区大小

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13953735/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 06:41:15  来源:igfitidea点击:

Calculating the required buffer size for the WriteableBitmap.WritePixels method

c#wpfbufferwriteablebitmap

提问by JMK

How do I calculate the required buffer size for the WriteableBitmap.WritePixels method?

如何计算 WriteableBitmap.WritePixels 方法所需的缓冲区大小?

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

我正在使用带有四个参数的重载,第一个是 Int32Rect,下一个是包含颜色的 RGBA 数字的字节数组,第三个是步幅(这是我的可写位图的宽度乘以每像素的位数除以8),最后一个是缓冲区(在Intellisense中称为偏移量)。

I am getting the Buffer size is not sufficientruntime error in the below code:

我在以下代码中收到Buffer size is not enough运行时错误:

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?

我需要使用什么公式来计算上述代码中所需的缓冲区值?

采纳答案by Clemens

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 strideas 8 and bufferSize as 16.

假设您有一个 2x2 的写入矩形和一个 32 位/像素的格式,例如PixelFormats.Pbgra32,您将获得stride8 和 bufferSize 为 16。

回答by Geerten

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.

步幅只是输入缓冲区的宽度(以字节为单位)。之所以称为stride,是因为有时在图像的每一行后面都有额外的内存,这使得无法使用图像的宽度来读取图像的每一行。

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.

所以在你的例子中,这是 2。你不需要用位图的每像素位数计算任何东西,WritePixels 方法知道所有这些信息。您需要提供有关输入数据结构的信息。

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.

但是,如另一个答案中所述,如果位图也是 2x2,则您的示例将不起作用。那么起始坐标将为 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:

当我仔细观察你的例子时,我看到了错误。你说 colourData 是输入color。但这是每像素输入。因此,如果要更改 2x2 的矩形,则需要以下输入数据:

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.

然后每像素的字节数等于位图的字节数,即 4,乘以每行 (2) 的宽度,总共为 8。

回答by Luke Puplett

Here's Microsoft's reflected code that performs the check within CopyPixels

这是 Microsoft 的反射代码,用于在其中执行检查 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 }));
        }

回答by Philm

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.

尽管用户 Clemens 回答了有关缓冲区大小的问题,但提问者并不知道他计算的缓冲区大小已经正确,问题出在其他地方。

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

虽然在评论中给出和讨论了细节,但缺少一个全面的片段(以及 .WritePixels(没有 .CopyPixels)的完整使用示例)。这是(我扫描了类似的问题,但这是最好的地方):

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

回答by tinkl

I am work with this. 60z fs

我正在处理这个。60z fs

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

回答by Prasad

I am not sure but try this works for 24 bit rgb

我不确定,但试试这个适用于 24 位 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));

   }