2009-12-31 152 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

相關問題