如何计算WriteableBitmap.WritePixels方法所需的缓冲区大小?
我正在使用带有四个参数的重载,第一个是Int32Rect,下一个是包含颜色的RGBA数字的字节数组,第三个是步幅(这是我的可写位图的宽度乘以位每个像素除以8),最后一个是缓冲区(在Intellisense中称为偏移量)。
我在下面的代码中得到缓冲区大小不够运行时错误:
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);
我需要使用什么公式来计算上面代码中所需的缓冲区值?
答案 0 :(得分:3)
步幅只是输入缓冲区的宽度(以字节为单位)。它被称为步幅,因为有时在图像的每一行后面都有额外的内存,这使得无法使用图像的宽度来读取图像的每一行。
因此在您的示例中,这是2.您不需要使用位图的每像素位计算任何内容,WritePixels方法知道所有这些信息。您需要提供有关输入数据结构的信息。
但是,如其他答案中所述,如果位图也是2x2,则您的示例将不起作用。然后起始坐标为0,0。
修改强>
当我仔细观察你的例子时,我看到了错误。您说colourData是输入颜色。但这是每像素输入。因此,如果要更改2x2的矩形,则需要以下inputdata:
byte[] colourData = { 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0 };
然后每个像素的字节数等于位图的字节数,因此它是每行(2)宽度的4倍,总计为8。
答案 1 :(得分: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 }));
}
答案 2 :(得分:1)
我正在与此合作。 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 :(得分:1)
虽然用户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);
答案 4 :(得分:0)
我不确定但尝试这适用于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));
}