I am creating a function to save a screenshot into a .bmp file, I've managed to save the screen into an HBITMAP but I'm having trouble when saving it. I would appreciate some help.
Here is the header with the function:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <stdbool.h>
#include <wingdi.h>
#include <winuser.h>
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned long u32;
typedef unsigned long long u64;
void getScreen()
{
u16 screenHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN);
u16 screenWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN);
HDC hdc = GetDC(NULL); //get a desktop dc (NULL for entire screen)
HDC hDest = CreateCompatibleDC(hdc); //create a dc for capture
ReleaseDC(NULL, hdc);
HBITMAP hbCapture = CreateCompatibleBitmap(hdc, screenWidth, screenHeight);
SelectObject(hDest, hbCapture);
//Copy screen to bitmap
BitBlt(hDest, 0, 0, screenWidth, screenHeight, hdc, 0, 0, SRCCOPY);
//test
ReleaseDC(NULL, hdc);
char memBuffer[10000];
BITMAPINFO bitmapInfo;
bitmapInfo.bmiHeader.biHeight = screenHeight;
bitmapInfo.bmiHeader.biWidth = screenWidth;
bitmapInfo.bmiHeader.biSize = screenWidth * screenHeight * 3;
bitmapInfo.bmiHeader.biCompression = BI_RGB;//NOT SURE
bitmapInfo.bmiHeader.biPlanes = 1;
bitmapInfo.bmiHeader.biBitCount = 8; //NOT SURE
bitmapInfo.bmiHeader.biClrImportant = 0;
GetDIBits(hDest, hbCapture, 0, screenHeight, &memBuffer, &bitmapInfo, DIB_RGB_COLORS);
FILE * fPointer = fopen("screen.png", "wb");//TO CHANGE
WriteFile(fPointer, &memBuffer, (WORD) sizeof(memBuffer), 0, NULL);
fclose(fPointer);
//test
//Clean up
ReleaseDC(NULL, hdc);
DeleteDC(hDest);
DeleteObject(hbCapture);
}
And here is also the main.c:
#include "main.h"
int main()
{
getScreen();
return 0;
}
I've already read all the questions about this topic in StackOverflow and none of them has clarified the issue for me.
biSizeis not the total pixel count, it's the size of bitmap info structure, it's alwayssizeof(BITMAPINFOHEADER).You want to set
bitmapInfo.bmiHeader.biSizeImageinstead. This value is roughly (width * height * bits_per_pixel/8) but it has to be adjusted because each row is padded. Also don't mixfopenhandle withCreateFilehandle as noted in comments.You cannot save to png format using this method. You need a different library like Gdiplus for png format.
To save as bitmap, you have to setup
BITMAFILEHEADER,BITMAPINFOHEADERand write them to file, and then write the bits obtained fromGetDIBitsYou may want to avoid using
typedef unsigned char u8;etc. You can include<stdint.h>and use standard typesuint8_t,uint16_t,uint32_tetc. Or you can use standard Windows types likeBYTE