2013-04-10 48 views
8

我有一個像素數組,我需要將其轉換爲HBITMAP才能在窗口中顯示它。 我試圖使用CreateDIBitmap(),但我沒有BMP頭。 我試圖根據MSDN文檔手動構建它們,但這不起作用。如何將像素陣列轉換爲HBITMAP

我的代碼下面的樣子

HBITMAP hBitmap 
char pixels[160*120]; // White grayscale image of size 160x120 
memset(pixels,255,sizeof(pixels)); 

BITMAPINFOHEADER bmih; 
bmih.biSize  = sizeof(BITMAPINFOHEADER); 
bmih.biWidth = 160; 
bmih.biHeight = -120; 
bmih.biPlanes = 1; 
bmih.biBitCount = 8; 
bmih.biCompression = BI_RGB ; 
bmih.biSizeImage = 0; 
bmih.biXPelsPerMeter = 10; 
bmih.biYPelsPerMeter = 10; 
bmih.biClrUsed =0; 
bmih.biClrImportant =0; 

BITMAPINFO dbmi; 
dbmi.bmiHeader = bmih; 
dbmi.bmiColors->rgbBlue = 0; 
dbmi.bmiColors->rgbGreen = 0; 
dbmi.bmiColors->rgbRed = 0; 
dbmi.bmiColors->rgbReserved = 0; 
void* bits = (void*)&(pixels[0]); 
hBitmap = CreateDIBitmap(localDC, &bmih, CBM_INIT, qB.bmBits, &dbmi, DIB_RGB_COLORS); 

現在,我得到一個非NULL HBITMAP這是很好的,但它總是顯示黑色圖像,就好像它不指向像素陣列。 我檢查它使用的代碼

BITMAP qB; 
GetObject(reinterpret_cast<HGDIOBJ>(hBitmap),sizeof(BITMAP),reinterpret_cast<LPVOID>(&qB)); 

事實上qB.bmBits爲NULL。 什麼問題以及如何解決?

+0

我不認爲CreateDIBi tmap支持灰度圖像。你可以創建一個256色陰影的調色板,或者你可以將你的圖像轉換成RGB三元組。 – john 2013-04-10 16:04:57

+0

好吧,假設我這樣做:char像素[160 * 120 * 3];比我有RGB圖像。 – DanielHsH 2013-04-10 16:21:27

+0

我設置了bmih.biBitCount = 24;但我仍然無法工作 – DanielHsH 2013-04-10 16:21:56

回答

6

我發現如何去做。 我們需要使用CreateDIBSection()代替CreateDIBitmap() 因此,這裏是工作的代碼

HBITMAP hBitmap = NULL; 
    unsigned char pixels[160*120*3]; 
    for (int i=0; i<160*120*3; i++){ 
     pixels[i] = (i%4==1)*255;  // An BGR (not RGB) 160x120 image. 
    } 
BITMAPINFOHEADER bmih; 
bmih.biSize  = sizeof(BITMAPINFOHEADER); 
bmih.biWidth = 160; 
bmih.biHeight = -120; 
bmih.biPlanes = 1; 
bmih.biBitCount = 24; 
bmih.biCompression = BI_RGB ; 
bmih.biSizeImage = 0; 
bmih.biXPelsPerMeter = 10; 
bmih.biYPelsPerMeter = 10; 
bmih.biClrUsed =0; 
bmih.biClrImportant =0; 

BITMAPINFO dbmi; 
ZeroMemory(&dbmi, sizeof(dbmi)); 
dbmi.bmiHeader = bmih; 
dbmi.bmiColors->rgbBlue = 0; 
dbmi.bmiColors->rgbGreen = 0; 
dbmi.bmiColors->rgbRed = 0; 
dbmi.bmiColors->rgbReserved = 0; 
void* bits = (void*)&(pixels[0]); 

// Create DIB 
hBitmap = CreateDIBSection(localDC, &dbmi, DIB_RGB_COLORS, &bits, NULL, 0); 
if (hBitmap == NULL) { 
    ::MessageBox(NULL, __T("Could not load the desired image image"), __T("Error"), MB_OK); 
    return; 
} 
// copy pixels into DIB. 
memcpy(bits,pixels,sizeof(pixels)); 

對於灰度圖像,複製像素DIB在一個循環,而不是用的memcpy()

#define INTENSITY unsigned char 

INTENSITY* dest = (INTENSITY*)bits; 
const INTENSITY* src = .. Put your char array of pixels; 
for (int j=0; j<imageWidth; j++){ 
    for (int i=0; i<imageHeight; i++, src++){ 
     *dest++ = *src; 
     *dest++ = *src; 
     *dest++ = *src; 
    } 
    // Padd the line to round WORD. 
    if (imageWidth%2) 
     *dest++ = 0; 
} 
+0

注意:您可能需要將寬度填充爲4字節(32位整數)的倍數而不是16位WORD,就像我在示例中所做的一樣。 – DanielHsH 2015-04-20 08:33:00

+2

我不認爲'void * bits =(void *)&(pixels [0]);'在這裏有意義。應該使它成爲:'void * bits = NULL;'。 – 2015-04-24 16:45:27

3

你職位是非常有幫助的(答案),但是它沒有工作對我來說,這裏是微小調整代碼:

// creating input 

    unsigned char pixels[160*120*3]; 
    for (int i=0; i<160*120*3; i++){ 
     pixels[i] = (i%4==1)*255;  // An BGR (not RGB) 160x120 image. 

    // at this point we have some input 

    BITMAPINFOHEADER bmih; 
    bmih.biSize  = sizeof(BITMAPINFOHEADER); 
    bmih.biWidth = 160; 
    bmih.biHeight = -120; 
    bmih.biPlanes = 1; 
    bmih.biBitCount = 24; 
    bmih.biCompression = BI_RGB ; 
    bmih.biSizeImage = 0; 
    bmih.biXPelsPerMeter = 10; 
    bmih.biYPelsPerMeter = 10; 
    bmih.biClrUsed =0; 
    bmih.biClrImportant =0; 

    BITMAPINFO dbmi; 
    ZeroMemory(&dbmi, sizeof(dbmi)); 
    dbmi.bmiHeader = bmih; 
    dbmi.bmiColors->rgbBlue = 0; 
    dbmi.bmiColors->rgbGreen = 0; 
    dbmi.bmiColors->rgbRed = 0; 
    dbmi.bmiColors->rgbReserved = 0; 

    HDC hdc = ::GetDC(NULL); 

    HBITMAP hbmp = CreateDIBitmap(hdc, &bmih, CBM_INIT, pixels, &dbmi, DIB_RGB_COLORS); 
    if (hbmp == NULL) { 
     ::MessageBox(NULL, L"Could not load the desired image image", L"Error", MB_OK); 
     return; 
    } 

    ::ReleaseDC(NULL, hdc); 

    // a little test if everything is OK 
    OpenClipboard(NULL); 
    EmptyClipboard(); 
    SetClipboardData(CF_BITMAP, hbmp); 
    CloseClipboard(); 

    // cleanup 
    DeleteObject(hbmp);