2013-02-25 88 views
0

我有一個需要在桌面(或窗體)上顯示的字節數組。我正在使用WinApi,不確定如何一次設置所有像素。字節數組在我的記憶中,並且需要儘快顯示(僅使用WinApi)。WinApi - 字節數組到灰度8位位圖(+性能)

我使用C#,但簡單的僞代碼會爲我是確定:

// create bitmap 
byte[] bytes = ...;// contains pixel data, 1 byte per pixel 
HDC desktopDC = GetWindowDC(GetDesktopWindow()); 
HDC bitmapDC = CreateCompatibleDC(desktopDC); 
HBITMAP bitmap = CreateCompatibleBitmap(bitmapDC, 320, 240); 
DeleteObject(SelectObject(bitmapDC, bitmap)); 

BITMAPINFO info = new BITMAPINFO(); 
info.bmiColors = new tagRGBQUAD[256]; 
for (int i = 0; i < info.bmiColors.Length; i++) 
{ 
    info.bmiColors[i].rgbRed = (byte)i; 
    info.bmiColors[i].rgbGreen = (byte)i; 
    info.bmiColors[i].rgbBlue = (byte)i; 
    info.bmiColors[i].rgbReserved = 0; 
} 
info.bmiHeader = new BITMAPINFOHEADER(); 
info.bmiHeader.biSize = (uint) Marshal.SizeOf(info.bmiHeader); 
info.bmiHeader.biWidth = 320; 
info.bmiHeader.biHeight = 240; 
info.bmiHeader.biPlanes = 1; 
info.bmiHeader.biBitCount = 8; 
info.bmiHeader.biCompression = BI_RGB; 
info.bmiHeader.biSizeImage = 0; 
info.bmiHeader.biClrUsed = 256; 
info.bmiHeader.biClrImportant = 0; 
// next line throws wrong parameter exception all the time 
// SetDIBits(bitmapDC, bh, 0, 240, Marshal.UnsafeAddrOfPinnedArrayElement(info.bmiColors, 0), ref info, DIB_PAL_COLORS); 

// how do i store all pixels into the bitmap at once ? 
for (int i = 0; i < bytes.Length;i++) 
    SetPixel(bitmapDC, i % 320, i/320, random(0x1000000)); 

// draw the bitmap 
BitBlt(desktopDC, 0, 0, 320, 240, bitmapDC, 0, 0, SRCCOPY); 

當我試圖通過自身與SetPixel()設置每個像素我看沒有灰色單色圖像只有黑色和白色。我怎樣才能正確創建一個灰度位圖顯示?我該如何做到這一點?


更新: 該調用結束了WinApi中我的程序外的錯誤。不能趕上例外:

public const int DIB_RGB_COLORS = 0; 
public const int DIB_PAL_COLORS = 1; 

[DllImport("gdi32.dll")] 
public static extern int SetDIBits(IntPtr hdc, IntPtr hbmp, uint uStartScan, uint cScanLines, byte[] lpvBits, [In] ref BITMAPINFO lpbmi, uint fuColorUse); 

// parameters as above 
SetDIBits(bitmapDC, bitmap, 0, 240, bytes, ref info, DIB_RGB_COLORS); 

回答

1

SetDIBits參數中的兩個是錯誤的:

  • lpvBits - 這是圖像數據,但你傳遞的調色板數據。你應該傳遞你的bytes數組。
  • lpBmi - 這是行 - BITMAPINFO結構包含BITMAPINFOHEADER和調色板,所以你不需要單獨傳遞調色板。我對你的其他問題的回答描述瞭如何聲明結構。
  • fuColorUse - 它描述了調色板的格式。您正在使用RGB調色板,因此您應該通過DIB_RGB_COLORS
+0

感謝您試圖幫助解決這兩個問題。但更改參數後,應用程序崩潰,我無法捕捉異常。請參閱更新。 – Bitterblue 2013-02-26 08:11:28

+0

我嘗試過使用SetDIBits的聲明,並將BITMAPINFO中的SizeConst設置爲256.它可以工作。還有其他一些錯誤。對CreateCompatibleBitmap的調用應使用桌面DC,否則您將獲得單色位圖(因爲新DC中的默認位圖是單色的)。您不應該在SelectObject的返回值上調用DeleteObject(當您完成後,您應該選擇原始對象回到DC中,並刪除新對象)。 – arx 2013-02-26 14:02:34