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