我想在我的Windows机器上用C截取屏幕截图并将其保存为jpg或bmp等等。无论如何,我试图通过我自己做,它没关系,并且运行良好,但它不可靠,不像prt scr
键 - 我想知道是否有办法访问prt scr
剪贴板并以某种方式将其粘贴到jpg中/ png文件或者如果有更快的方法来获取所有屏幕像素。
那是我的代码:
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;
}
函数save_png_to_file
正在正常工作,循环耗时太长(我的屏幕是1366x768并且它有超过百万个循环条目) - 当密钥prt scr
正在轻松执行时,为什么这么慢?
答案 0 :(得分:0)
这在此解释:
http://msdn.microsoft.com/en-us/library/dd183402(v=vs.85).aspx
请参阅示例中的CaptureAnImage()
函数。整个代码有点复杂,因为它是一个完整的win32应用程序,但它显示了如何捕获一个特定的窗口并保存到filename.bmp
。
答案 1 :(得分:0)
嗯...... GetPixel()
本身真的很慢,然后将它与一个循环结合起来,这很多人都做不好......不会很好。
函数BitBlt
更快 - 这是一个例子:
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;
}