如何计算System.Drawing.Bitmap的底层缓冲区的正确大小?

时间:2017-03-17 01:42:34

标签: c# .net bitmap

我正在使用$(function() { $('#home a, .navbar-default a').bind('click', function(event) { var $anchor = $(this); $('html, body').stop().animate({ scrollTop: $($anchor.attr('href')).offset().top - 49 }, 1000); event.preventDefault(); }); }); ,需要访问单个像素,但System.Drawing.BitmapGetPixel()对我来说太慢了。

使用the technique described in this answer,我正在分配SetPixel(),将其固定在内存中,将原始byte[]复制到其中,并取消固定。然后我使用Bitmap,稍后我将其固定,用缓冲区构造一个新的byte[]并保存。

我以Bitmap的形式计算缓冲区的大小(以字节为单位)。我正在使用width * height * BytesPerPixel,所以PixelFormat.Format32bppArgb

这一切都很好用,但我显然分配的缓冲区太小而在复制位图时会导致访问冲突。我必须添加额外的空间(很多)以避免访问冲突,并且一切似乎都有效。

如何计算BytesPerPixel == 4所需的正确尺寸?

编辑:我刚刚发现原始图片是_buffer。但是,这是每像素3个字节,我认为我的缓冲区应该足够大。

这是一个演示问题的完整程序。 PixelFormat.Format24bppRgb控制我必须分配的额外字节......:

ExtraSpace

1 个答案:

答案 0 :(得分:2)

请记住,Windows位图对象要求步长为DWORD(4字节)对齐。宽度不是4的倍数的24位图像将具有不同于4 *宽度的步幅。

另请注意,步幅以字节为单位,而不是位,因此在任何情况下您的计算都是错误的。你告诉checkWord类它有Bitmap的步幅,它是它应该的8倍,所以GDI +可能会早于1/8号用尽有效的内存地址进入图像(如果你很幸运......如果你没有,它会将随机数据写入重要的地方)。

以下是计算结果:

32 * width

注意int stride = 4 * ((_width * bytesPerPixel + 3) / 4); 而不是bytesPerPixel。确保根据位图格式正确计算,而不仅仅是将const设置为4。