2009-12-31 25 views
7

Tôi đang cố gắng để có được một bitmap được tạo ra từ dữ liệu thô để hiển thị trong WPF, bằng cách sử dụng một hình ảnh và một BitmapSource:Tại sao BitmapSource.Create lại ném một 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; 

Tuy nhiên các cuộc gọi đến BitmapSource.Create ném một ArgumentException, nói rằng "Giá trị không nằm trong phạm vi dự kiến ​​". Đây không phải là cách để làm điều này? Tôi không thực hiện cuộc gọi đó đúng cách?

Trả lời

35

Sải chân của bạn không chính xác. Stride là số byte được phân bổ cho một quét của bitmap . Vì vậy, sử dụng như sau:

int stride = ((RenderWidth * 32 + 31) & ~31)/8; 

và thay thế các tham số cuối cùng (hiện 0) với stride như đã định nghĩa ở trên.

Dưới đây là một lời giải thích cho công thức sải chân bí ẩn:

Thực tế: scanlines phải được xếp trên ranh giới 32-bit (reference).

Công thức ngây thơ cho số byte cho mỗi scanline sẽ là:

(width * bpp)/8 

Nhưng điều này có thể không cung cấp cho chúng ta một bitmap xếp trên một ranh giới 32-bit và (chiều rộng * bpp) có thể thậm chí không có được chia hết cho 8.

Vì vậy, những gì chúng tôi làm là chúng tôi buộc bitmap của chúng tôi để có ít nhất 32 bit liên tiếp (chúng ta giả định rằng width > 0):

width * bpp + 31 

và sau đó chúng tôi nói rằng chúng tôi không quan tâm đến các bit có thứ tự thấp (bit 0--4) vì chúng tôi đang cố gắng căn chỉnh trên các ranh giới 32 bit:

(width * bpp + 31) & ~31 

và sau đó chia cho 8 để trở lại byte:

((width * bpp + 31) & ~31)/8 

Các đệm có thể được tính bằng cách

int padding = stride - (((width * bpp) + 7)/8) 

Công thức ngây thơ sẽ là

stride - ((width * bpp)/8) 

Nhưng width * bpp có thể không căn chỉnh trên một ranh giới byte và khi nó không công thức này sẽ hơn đếm padding bởi một byte. (Hãy suy nghĩ về một bitmap rộng 1 pixel sử dụng 1 bpp. Các bước tiến là 4 và công thức ngây thơ sẽ nói rằng padding là 4 nhưng trong thực tế nó là 3.) Vì vậy, chúng tôi thêm một chút để trang trải các trường hợp mà width * bpp không phải là một ranh giới byte và sau đó chúng tôi nhận được công thức chính xác được đưa ra ở trên.

+0

Cảm ơn bạn, nhưng bạn đã nghĩ ra cách diễn đạt như thế nào trên trái đất? Tại sao nó không chỉ đơn giản là RenderWidth * 4? Không phải là số byte cho một dòng? –

+1

Xin lỗi, tôi đã cung cấp chi tiết. Trong trường hợp của bạn, bạn có 'bpp = 32' để có công thức giảm xuống' RenderWidth * 4'. Nhưng có những trường hợp lẻ (màn hình LCD giá rẻ sử dụng 18 bpp) và thực tế là các đường quét phải được căn chỉnh trên các ranh giới 32 bit. Tôi đã cung cấp công thức chung và một lời giải thích về cách thức đưa ra nó ở trên. Hy vọng nó làm sáng tỏ. – jason

+1

Cảm ơn bạn. Một câu hỏi nữa. Dấu ngã làm gì trên một số nguyên như vậy? –