为什么BitmapSource.Create会引发ArgumentException?
问题描述:
我试图通过使用图像和的BitmapSource得到从原始数据创建WPF中显示,一个位图:为什么BitmapSource.Create会引发ArgumentException?
Int32[] data = new Int32[RenderHeight * RenderWidth];
for (Int32 i = 0; i < RenderHeight; i++)
{
for (Int32 j = 0; j < RenderWidth; j++)
{
Int32 index = j + (i * RenderHeight);
if (i + j % 2 == 0)
data[index] = 0xFF0000;
else
data[index] = 0x00FF00;
}
}
BitmapSource source = BitmapSource.Create(RenderWidth, RenderHeight, 96.0, 96.0, PixelFormats.Bgr32, null, data, 0);
RenderImage.Source = source;
但是调用BitmapSource.Create引发ArgumentException,称“值不落在预期范围内“。这不是这样做的方式吗?我没有正确地打这个电话吗?
答
你的步伐是不正确的。步幅是为 位图的一条扫描线分配的字节数。因此,使用下面的:
int stride = ((RenderWidth * 32 + 31) & ~31)/8;
并用stride
取代如上所定义的最后一个参数(目前0
)。
下面是神秘步幅式的解释:
事实:必须Scanlines的在32位边界(reference)对准。
每扫描线的字节数天真的公式是:
(width * bpp)/8
但这可能不会给我们一个32位的边界上对齐的位图和(宽* BPP)甚至可能没有被8。
所以整除,我们做的是我们强迫我们的位图至少有32位在一排(我们假设width > 0
):
width * bpp + 31
,然后我们说我们不关心的低位(位0--4),因为我们正试图对齐在32位边界:
(width * bpp + 31) & ~31
,然后除以8要回字节:
((width * bpp + 31) & ~31)/8
的填充可以通过
int padding = stride - (((width * bpp) + 7)/8)
来计算的幼稚公式将是
stride - ((width * bpp)/8)
但是width * bpp
可能不会在字节边界上对齐,并且当它不包含此公式时会超过一个字节的填充数。 (想想使用1 bpp的1个像素宽的位图,步幅是4,而朴素的公式会说填充是4,但实际上它是3)。因此,我们添加一点点以涵盖width * bpp
不是字节边界,然后我们得到上面给出的正确公式。
谢谢,但你究竟如何提出这种表达?为什么它不是简单的RenderWidth * 4?是不是一行的字节数? – 2009-12-31 04:26:03
对不起,我应该提供详细信息。在你的情况下,你有'bpp = 32'所以是公式简化为'RenderWidth * 4'。但有一些奇怪的情况(便宜的LCD使用18 bpp)以及扫描线必须在32位边界上对齐的事实。我提供了如何在上面提出的一般公式和解释。希望它是澄清。 – jason 2009-12-31 05:09:22
谢谢。还有一个问题。波浪对像这样的整数做什么? – 2009-12-31 05:23:51