I want to take a screenshot in C on my windows machine and save it as a jpg or bmp or whatever. Anyway, I tried to do it by my own, it's okay and working well but it's UNBEARABLY SLOW, unlike prt scr
key - I wonder if there's a way to access prt scr
clipboard and somehow paste it in a jpg/png file OR if there's a faster way to get all of the screen pixels.
That's my code:
int main()
{
bitmap_t pic;
int i, j;
pic.width = GetSystemMetrics(SM_CXSCREEN);
pic.height = GetSystemMetrics(SM_CYSCREEN);
pic.pixels = (pixel_t**)malloc(sizeof(pixel_t*)*pic.width);
for(i = 0 ; i < pic.height ; i++)
{
pic.pixels[i] = (pixel_t*)malloc(sizeof(pixel_t)*pic.height);
}
HDC hdc = GetDC(NULL);
COLORREF c;
printf("Size of your monitor is %d by %d.\n", pic.width, pic.height);
for(i = 0 ; i < pic.width ; i++)
{
for(j = 0 ; j < pic.height ; j++)
{
c = GetPixel(hdc, i, j);
pic.pixels[i][j].red = (uint8_t)GetRValue(c);
pic.pixels[i][j].green = (uint8_t)GetGValue(c);
pic.pixels[i][j].blue = (uint8_t)GetBValue(c);
}
}
ReleaseDC(NULL, hdc);
save_png_to_file(&pic, "D:\\pic.png");
for(i = 0 ; i < pic.height ; i++)
{
free(pic.pixels[i]);
}
free(pic.pixels);
return 0;
}
The function save_png_to_file
is working propely, the loop is taking too long (my screen is 1366x768 and it's over million loop entries) - why is it so slow when the key prt scr
is doing it easily?
Depending on your hardware, you may use the Windows Logo Key + PrtScn button as a shortcut for print screen. If your device does not have the PrtScn button, you may use Fn + Windows logo key + Space Bar to take a screenshot, which can then be printed.
Hmm... GetPixel()
is really slow by itself, then combining it in a loop with this many do-overs... Can't be good.
The function BitBlt
is A LOT faster - here is an example:
BOOL SaveToFile(HBITMAP hBitmap3, LPCTSTR lpszFileName)
{
HDC hDC;
int iBits;
WORD wBitCount;
DWORD dwPaletteSize=0, dwBmBitsSize=0, dwDIBSize=0, dwWritten=0;
BITMAP Bitmap0;
BITMAPFILEHEADER bmfHdr;
BITMAPINFOHEADER bi;
LPBITMAPINFOHEADER lpbi;
HANDLE fh, hDib, hPal,hOldPal2=NULL;
hDC = CreateDC("DISPLAY", NULL, NULL, NULL);
iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES);
DeleteDC(hDC);
if (iBits <= 1)
wBitCount = 1;
else if (iBits <= 4)
wBitCount = 4;
else if (iBits <= 8)
wBitCount = 8;
else
wBitCount = 24;
GetObject(hBitmap3, sizeof(Bitmap0), (LPSTR)&Bitmap0);
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = Bitmap0.bmWidth;
bi.biHeight =-Bitmap0.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = wBitCount;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrImportant = 0;
bi.biClrUsed = 256;
dwBmBitsSize = ((Bitmap0.bmWidth * wBitCount +31) & ~31) /8
* Bitmap0.bmHeight;
hDib = GlobalAlloc(GHND,dwBmBitsSize + dwPaletteSize + sizeof(BITMAPINFOHEADER));
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
*lpbi = bi;
hPal = GetStockObject(DEFAULT_PALETTE);
if (hPal)
{
hDC = GetDC(NULL);
hOldPal2 = SelectPalette(hDC, (HPALETTE)hPal, FALSE);
RealizePalette(hDC);
}
GetDIBits(hDC, hBitmap3, 0, (UINT) Bitmap0.bmHeight, (LPSTR)lpbi + sizeof(BITMAPINFOHEADER)
+dwPaletteSize, (BITMAPINFO *)lpbi, DIB_RGB_COLORS);
if (hOldPal2)
{
SelectPalette(hDC, (HPALETTE)hOldPal2, TRUE);
RealizePalette(hDC);
ReleaseDC(NULL, hDC);
}
fh = CreateFile(lpszFileName, GENERIC_WRITE,0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (fh == INVALID_HANDLE_VALUE)
return FALSE;
bmfHdr.bfType = 0x4D42; // "BM"
dwDIBSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPaletteSize + dwBmBitsSize;
bmfHdr.bfSize = dwDIBSize;
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER) + dwPaletteSize;
WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
WriteFile(fh, (LPSTR)lpbi, dwDIBSize, &dwWritten, NULL);
GlobalUnlock(hDib);
GlobalFree(hDib);
CloseHandle(fh);
return TRUE;
}
int screenCapture(int x, int y, int w, int h, LPCSTR fname)
{
HDC hdcSource = GetDC(NULL);
HDC hdcMemory = CreateCompatibleDC(hdcSource);
int capX = GetDeviceCaps(hdcSource, HORZRES);
int capY = GetDeviceCaps(hdcSource, VERTRES);
HBITMAP hBitmap = CreateCompatibleBitmap(hdcSource, w, h);
HBITMAP hBitmapOld = (HBITMAP)SelectObject(hdcMemory, hBitmap);
BitBlt(hdcMemory, 0, 0, w, h, hdcSource, x, y, SRCCOPY);
hBitmap = (HBITMAP)SelectObject(hdcMemory, hBitmapOld);
DeleteDC(hdcSource);
DeleteDC(hdcMemory);
HPALETTE hpal = NULL;
if(SaveToFile(hBitmap, fname)) return 1;
return 0;
}
int main()
{
screenCapture(0, 0, GetSystemMetric, 768, "D:\\MyFirstScreeshot.bmp");
return 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With