Search code examples
c++windowsbitmapscreenshotgdi

GDI Screenshot, results varying on different computer


I try to take a screenshot with GDI, then i use it in FFmpeg. The screenshot works well and FFmpeg handle it without any problem.

But, on some computer, the image is not very what i want like you can see below.

enter image description here

Here is the code i use to init my bitmap :

//--
mImageBuffer = new unsigned char[mWxHxS];
memset(mImageBuffer, 0, mWxHxS);
//--
hScreenDC = GetDC(0);
hMemoryDC = CreateCompatibleDC(hScreenDC);
//--
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biBitCount = 24;
bi.bmiHeader.biWidth = mWidth;
bi.bmiHeader.biHeight = mHeight;
bi.bmiHeader.biCompression = BI_RGB;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biClrUsed = 24;
bi.bmiHeader.biClrImportant = 256;
hBitmap = CreateDIBSection(hMemoryDC, &bi, DIB_RGB_COLORS, &mImageBuffer, 0, 0);
SelectObject(hMemoryDC, hBitmap);

And here for each screenshot :

if(BitBlt(
    hMemoryDC,
    0,
    0,
    mWidth,
    mHeight,
    hScreenDC,
    mPx,
    mPy,
    SRCCOPY | CAPTUREBLT
))

I do not have any error running my application but this ugly image and only on some computer. I don't know what is the difference causing that on these computer (All are Win7, Aero actived...). I do not understand because my code follow all example i found...

Please help me !


Solution

  • So i finaly find the solution :

    It seems that the BitBlt and StretchBlt doesnt really handle correctly the transfer between 32 to 24 bits on some computers...

    Now, i use only 32bits with GDI and let FFmpeg with libswscale convert my RGBA image to a YUV format.

    My changes :

    mWidth = GetDeviceCaps(hScreenDC, HORZRES);
    mHeight = GetDeviceCaps(hScreenDC, VERTRES);
    mWxHxS = mWidth*mHeight*4;
    
    bi.bmiHeader.biBitCount = 32;
    hBitmap = CreateCompatibleBitmap(hScreenDC, mWidth, mHeight);
    
    
    if(BitBlt(
        hMemoryDC,
        0,
        0,
        mWidth,
        mHeight,
        hScreenDC,
        mPx,
        mPy,
        SRCCOPY | CAPTUREBLT
        ) && GetDIBits(hScreenDC, hBitmap, 0, mHeight, mImageBuffer, &bi, DIB_RGB_COLORS))
        {
        return true;
        }
    

    Thanks trying to help me !