2009-12-31 149 views
7

我试图通过使用图像和的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,称“值不落在预期范围内“。这不是这样做的方式吗?我没有正确地打这个电话吗?

回答

35

你的步伐是不正确的。步幅是为 位图的一条扫描线分配的字节数。因此,使用下面的:

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不是字节边界,然后我们得到上面给出的正确公式。

+0

谢谢,但你究竟如何提出这种表达?为什么它不是简单的RenderWidth * 4?是不是一行的字节数? – 2009-12-31 04:26:03

+1

对不起,我应该提供详细信息。在你的情况下,你有'bpp = 32'所以是公式简化为'RenderWidth * 4'。但有一些奇怪的情况(便宜的LCD使用18 bpp)以及扫描线必须在32位边界上对齐的事实。我提供了如何在上面提出的一般公式和解释。希望它是澄清。 – jason 2009-12-31 05:09:22

+1

谢谢。还有一个问题。波浪对像这样的整数做什么? – 2009-12-31 05:23:51

相关问题