As mentioned in this thread - Video-based remote desktop , I'm trying to implement screen capturing using GDI BitBlt. I've simplified it down to single capture and store as BMP.
It looks like it's ALMOST working, but there is some corruption going on, and I'm not sure where that came from.
Can someone please have a look?
Minimum compilable code, no special setup required -
Code:
#include <iostream>
#include <fstream>
#include <cstdint>
#include <cassert>
#include <Windows.h>
int main()
{
HDC screen = GetDC(NULL);
HDC target = CreateCompatibleDC(screen);
uint32_t width = GetSystemMetrics(SM_CXSCREEN);
uint32_t height = GetSystemMetrics(SM_CYSCREEN);
HBITMAP bmp = CreateCompatibleBitmap(screen, width, height);
SelectObject(target, bmp);
int ret = 0;
ret = BitBlt(target, 0, 0, width, height, screen, 0, 0, SRCCOPY | CAPTUREBLT);
assert(ret);
BITMAPINFO bminfo;
bminfo.bmiHeader.biBitCount = 32;
bminfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bminfo.bmiHeader.biCompression = BI_RGB;
bminfo.bmiHeader.biPlanes = 1;
bminfo.bmiHeader.biWidth = width;
bminfo.bmiHeader.biHeight = height;
bminfo.bmiHeader.biSizeImage = width * 4 * height; // must be DWORD aligned
bminfo.bmiHeader.biXPelsPerMeter = 0;
bminfo.bmiHeader.biYPelsPerMeter = 0;
bminfo.bmiHeader.biClrUsed = 0;
bminfo.bmiHeader.biClrImportant = 0;
// get bitmap info from the bitmap
//ret = GetDIBits(mTarget, mBmp, 0, mHeight, NULL, (BITMAPINFO *) &bminfo, DIB_RGB_COLORS);
//assert(ret);
uint8_t *bmpBuffer = new uint8_t[bminfo.bmiHeader.biSizeImage];
// real capture
ret = GetDIBits(target, bmp, 0, height, bmpBuffer, &bminfo, DIB_RGB_COLORS);
assert(ret);
BITMAPFILEHEADER fheader;
fheader.bfType = 0x4D42;
fheader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + bminfo.bmiHeader.biSizeImage;
fheader.bfReserved1 = 0;
fheader.bfReserved2 = 0;
fheader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
std::ofstream bmp_file("test.bmp");
bmp_file.write((const char *) &fheader, sizeof(fheader));
bmp_file.write((const char *) &(bminfo.bmiHeader), sizeof(bminfo.bmiHeader));
bmp_file.write((const char *) bmpBuffer, bminfo.bmiHeader.biSizeImage);
bmp_file.close();
std::cout << "done" << std::endl;
return true;
}
It should capture your primary screen, and generate a bmp in your working directory.
Attached is the output image (BMP in ZIP, because I want to preserve the BMP byte by byte).
I've tried it on 2 computers with the same result.
Thanks!