How to convert an Array of pixels to HBITMAP

后端 未结 3 1650
天涯浪人
天涯浪人 2020-12-17 20:46

I have an array of pixels which I need to convert to HBITMAP in order to display it in a window. I tried to use CreateDIBitmap() but I don\'t have the BMP headers. I tried

相关标签:
3条回答
  • 2020-12-17 20:57

    Your post was very helpful (the answer) however it didn't work for me, here is the code with small corrections:

        // 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);
    
    0 讨论(0)
  • 2020-12-17 21:03

    The other answers here are very helpful, but i ended up being able to achieve it with just 1 line.

    HBITMAP hBm = CreateBitmap(width,height,1,32,pixels); // 1 plane, 32 bits
    

    Hope it may be useful to any future readers.


    Also, there's CreateCompatibleBitmap and SetDIBits incase you need to use a device context.

    At MSDN for CreateDIBitmap it states:

    Calling CreateDIBitmap with fdwInit as CBM_INIT is equivalent to calling the CreateCompatibleBitmap function to create a DDB in the format of the device and then calling the SetDIBits function to translate the DIB bits to the DDB.

    0 讨论(0)
  • 2020-12-17 21:08

    I found how to do it. We need to use CreateDIBSection() instead of CreateDIBitmap() So here is the working code

    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));
    

    For grey level images, copy the pixels to DIB in a loop instead of with 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 讨论(0)
提交回复
热议问题