StretchBlt function returns a weird white dots bitmap

111 Views Asked by At

I'm trying to write a simple bitmap resizer application using window API, this is my bitmap resizer function:

BOOL ResizeBitmap(HBITMAP hOriginalBitmap, const char resizedFilename[], BitmapAngle NewAngle, BitmapAngle BmAngle){
    HDC hdcSrc = CreateCompatibleDC(NULL);
    HGDIOBJ originalObject = SelectObject(hdcSrc, hOriginalBitmap);

    HDC hdcDest = CreateCompatibleDC(NULL);
    HBITMAP hNewBitmap = CreateCompatibleBitmap(hdcDest, NewAngle.Width, NewAngle.Height);

    if (!hNewBitmap) {
        GetErrorCode("CreateCompatibleBitmap");
        ExitProcess(0);
    }

    SelectObject(hdcDest, hNewBitmap);

    // Set the stretch mode to HALFTONE for better quality
    SetStretchBltMode(hdcDest, HALFTONE);
    SetBrushOrgEx(hdcDest, 0, 0, NULL);

    // Use StretchBlt to resize the original bitmap onto the new bitmap
    StretchBlt(hdcDest, 0, 0, NewAngle.Width, NewAngle.Height,
               hdcSrc, 0, 0, BmAngle.Width, BmAngle.Height,
               SRCCOPY);

    // BitBlt(hdcDest, 0, 0, NewAngle.Width, NewAngle.Height, hdcSrc, 0, 0, SRCCOPY);
    // Save the resized bitmap to a file
    SaveBitmapToFile(hNewBitmap, NewAngle, resizedFilename);

    SelectObject(hdcSrc, originalObject);
    DeleteDC(hdcSrc);
    DeleteDC(hdcDest);
    DeleteObject(hNewBitmap);

    return TRUE;
}

this is my SaveBitmapToFile function:

BOOL SaveBitmapToFile(HBITMAP hBitMap, BitmapAngle Angle, const char NewFileName[]) {
    HDC hDevice = CreateCompatibleDC(NULL);
    SelectObject(hDevice, hBitMap);

    BITMAPINFOHEADER BitmapInfoHeader = GetBitmapInfoHeader(Angle);
    BITMAPFILEHEADER BitMapFileHeader = GetBitmapFileHeader(Angle);

    DWORD AllocatedSize = Angle.Width * Angle.Height * 3;  // Assuming 24 bits per pixel

    BYTE* BitmapData = VirtualAlloc(NULL, AllocatedSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

    int Result = GetDIBits(hDevice, hBitMap, 0, Angle.Height, BitmapData, (BITMAPINFO*)&BitmapInfoHeader, DIB_RGB_COLORS);

    if (!Result) {
        GetErrorCode("GetDIBits");
        ExitProcess(0);
    }

    HANDLE hFile = CreateFileA(NewFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
    if (!hFile) {
        GetErrorCode("CreateFileA");
        ExitProcess(0);
    }

    // Write headers and bitmap data to the file
    WriteFile(hFile, &BitMapFileHeader, sizeof(BITMAPFILEHEADER), NULL, NULL);
    WriteFile(hFile, &BitmapInfoHeader, sizeof(BITMAPINFOHEADER), NULL, NULL);
    WriteFile(hFile, BitmapData, AllocatedSize, NULL, NULL);

    CloseHandle(hFile);

    VirtualFree(BitmapData, AllocatedSize, MEM_RELEASE);

    DeleteDC(hDevice);

    if (!GetLastError()) {
        return TRUE;
    } else {
        GetErrorCode("SaveBitmapToFile");
        return FALSE;
    }
}

However, the result bitmap file looks really weird, it just a bitmap with white dot:

The input bitmap The Output bitmap

The SaveBitmapToFile function works really fine, when i try to take a screenshot, so i think the problem is in ResizeBitmap function

This is my screenshot function, which works really fine.

HBITMAP GetScreenBitmap() {
    HDC hdcScreen = GetDC(NULL);
    int screenWidth = GetSystemMetrics(SM_CXSCREEN);
    int screenHeight = GetSystemMetrics(SM_CYSCREEN);

    // Create a compatible memory DC using the screen DC
    HDC hdcMem = CreateCompatibleDC(hdcScreen);

    // Create a compatible bitmap using the screen DC
    HBITMAP hBitmap = CreateCompatibleBitmap(hdcScreen, screenWidth, screenHeight);

    // Select the bitmap into the memory DC
    SelectObject(hdcMem, hBitmap);

    // BitBlt to copy the contents of the screen to the memory DC
    BitBlt(hdcMem, 0, 0, screenWidth, screenHeight, hdcScreen, 0, 0, SRCCOPY);

    // Release resources
    ReleaseDC(NULL, hdcScreen);
    DeleteDC(hdcMem);

    return hBitmap;
}

HBITMAP hCurrentScreen = GetScreenBitmap();
BitmapAngle BmAngle; BmAngle.Height = GetSystemMetrics(SM_CYSCREEN); BmAngle.Width = GetSystemMetrics(SM_CXSCREEN);
SaveBitmapToFile(hCurrentScreen, BmAngle, "TEST.bmp");
1

There are 1 best solutions below

1
On

Thank to @IInspectable

Just change the line CreateCompatibleBitmap(hdcDest, NewAngle.Width, NewAngle.Height);

To CreateCompatibleBitmap(hdcSrc, NewAngle.Width, NewAngle.Height);

Will solve the problem!

resource