18

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

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

我在下面的代码中收到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);

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

4

6 回答 6

15

步幅值计算为写入矩形中每“像素行”的字节数:

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

所需的缓冲区大小是每行的字节数乘以行数:

var bufferSize = rect.Height * stride;

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

于 2012-12-19T13:55:28.273 回答
3

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

因此,在您的示例中,这是 2。您不需要使用位图的每像素位数计算任何内容,WritePixels 方法知道所有这些信息。您需要提供有关输入数据结构的信息。

但是,如另一个答案中所述,如果位图也是 2x2,则您的示例将不起作用。那么起始坐标将是 0,0。

编辑:

当我仔细查看您的示例时,我发现了错误。你说 colourData 是输入颜色。但这是每个像素的输入。因此,如果要更改 2x2 的矩形,则需要以下输入数据:

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

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

于 2012-12-20T10:11:53.083 回答
3

这是执行检查的 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 }));
        }
于 2014-03-20T13:44:03.563 回答
3

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

虽然在评论中给出并讨论了细节,但缺少一个全面的片段(以及 .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);
于 2018-01-22T19:09:32.343 回答
1

我正在处理这个。60z 飞速

   this.playerOpacityMaskImage.WritePixels(
                new Int32Rect(0, 0, this.depthWidth, this.depthHeight),
                this.greenScreenPixelData,
                this.depthWidth * ((this.playerOpacityMaskImage.Format.BitsPerPixel + 7) / 8),
                0);
于 2013-09-13T06:36:41.763 回答
-1

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

   }
于 2012-12-19T13:56:38.913 回答