123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596 |
- #include "stdafx.h"
- #include "screencapture.h"
- #ifdef RVC_OS_WIN
- static HMONITOR GetPrimaryMonitorHandle()
- {
- const POINT ptZero = {0, 0};
- return MonitorFromPoint(ptZero, MONITOR_DEFAULTTOPRIMARY);
- }
- static HBITMAP CopyScreenToBitmap(LPRECT lpRect)
- {
- HDC hScrDC, hMemDC; // screen DC and memory DC
- // HBITMAP hBitmap; //,
- // HBITMAP hBitmap;
- // HBITMAP hOldBitmap; // handles to deice-dependent bitmaps
- int nX, nY, nX2, nY2; // coordinates of rectangle to grab
- int nWidth, nHeight; // DIB width and height
- int xScrn, yScrn; // screen resolution
- HGDIOBJ hOldBitmap , hBitmap;
- // check for an empty rectangle
- if (IsRectEmpty(lpRect))
- return NULL;
- // create a DC for the screen and create
- // a memory DC compatible to screen DC
- MONITORINFOEX mi;
- mi.cbSize = sizeof(mi);
- GetMonitorInfoA(GetPrimaryMonitorHandle(), &mi);
- //hScrDC = CreateDCA("DISPLAY", NULL, NULL, NULL);
- hScrDC = CreateDCA(mi.szDevice, NULL, NULL, NULL);
- hMemDC = CreateCompatibleDC(hScrDC); // get points of rectangle to grab
- nX = lpRect->left;
- nY = lpRect->top;
- nX2 = lpRect->right;
- nY2 = lpRect->bottom; // get screen resolution
- xScrn = GetDeviceCaps(hScrDC, HORZRES);
- yScrn = GetDeviceCaps(hScrDC, VERTRES);
- //make sure bitmap rectangle is visible
- if (nX < 0)
- nX = 0;
- if (nY < 0)
- nY = 0;
- if (nX2 > xScrn)
- nX2 = xScrn;
- if (nY2 > yScrn)
- nY2 = yScrn;
- nWidth = nX2 - nX;
- nHeight = nY2 - nY;
- // create a bitmap compatible with the screen DC
- hBitmap = CreateCompatibleBitmap(hScrDC, nWidth, nHeight);
- // select new bitmap into memory DC
- hOldBitmap = SelectObject (hMemDC, hBitmap);
- // bitblt screen DC to memory DC
- BitBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, nX, nY, SRCCOPY);
- // select old bitmap back into memory DC and get handle to
- // bitmap of the screen
- hBitmap = SelectObject(hMemDC, hOldBitmap);
- // clean up
- DeleteDC(hScrDC);
- DeleteDC(hMemDC);
- // return handle to the bitmap
- return (HBITMAP)hBitmap;
- }
- static HPALETTE GetSystemPalette()
- {
- HDC hDC; // handle to a DC
- static HPALETTE hPal = NULL; // handle to a palette
- HANDLE hLogPal; // handle to a logical palette
- LPLOGPALETTE lpLogPal; // pointer to a logical palette
- int nColors; // number of colors
- // Find out how many palette entries we want.
- MONITORINFOEX mi;
- mi.cbSize = sizeof(mi);
- GetMonitorInfoA(GetPrimaryMonitorHandle(), &mi);
- hDC = CreateDCA(mi.szDevice, NULL, NULL, NULL);
- //hDC = CreateDC ( TEXT("DISPLAY"), NULL, NULL, NULL );
- if (!hDC)
- return NULL;
- nColors = 256; //PalEntriesOnDevice(hDC); // Number of palette entries
- // Allocate room for the palette and lock it.
- hLogPal = GlobalAlloc(GHND, sizeof(LOGPALETTE) + nColors *
- sizeof(PALETTEENTRY));
- // if we didn't get a logical palette, return NULL
- if (!hLogPal)
- return NULL;
- // get a pointer to the logical palette
- lpLogPal = (LPLOGPALETTE)GlobalLock(hLogPal);
- // set some important fields
- lpLogPal->palVersion = 0x300; //PALVERSION;
- lpLogPal->palNumEntries = nColors;
- // Copy the current system palette into our logical palette
- GetSystemPaletteEntries(hDC, 0, nColors,
- (LPPALETTEENTRY)(lpLogPal->palPalEntry));
- // Go ahead and create the palette. Once it's created,
- // we no longer need the LOGPALETTE, so free it.
- hPal = CreatePalette(lpLogPal);
- // clean up
- GlobalUnlock(hLogPal);
- GlobalFree(hLogPal);
- DeleteDC(hDC);
- return hPal;
- }
- static WORD DibNumColors (VOID FAR * pv)
- {
- int bits;
- LPBITMAPINFOHEADER lpbi;
- LPBITMAPCOREHEADER lpbc;
- lpbi = ((LPBITMAPINFOHEADER)pv);
- lpbc = ((LPBITMAPCOREHEADER)pv);
-
- /* With the BITMAPINFO format headers, the size of the palette
- * is in biClrUsed, whereas in the BITMAPCORE - style headers, it
- * is dependent on the bits per pixel ( = 2 raised to the power of
- * bits/pixel).
- */
-
- if (lpbi->biSize != sizeof(BITMAPCOREHEADER))
- {
- if (lpbi->biClrUsed != 0)
- return (WORD)lpbi->biClrUsed;
-
- bits = lpbi->biBitCount;
- }
- else
- bits = lpbc->bcBitCount;
- switch (bits)
- {
- case 1:
- return 2;
- case 4:
- return 16;
- case 8:
- return 256;
- default:
- // A 24 bitcount DIB has no color table
- return 0;
- }
-
- }
- static WORD PaletteSize (VOID FAR * pv)
- {
- LPBITMAPINFOHEADER lpbi;
- WORD NumColors;
- lpbi = (LPBITMAPINFOHEADER)pv;
- NumColors = DibNumColors(lpbi);
- if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
- return NumColors * sizeof(RGBTRIPLE);
- else
- return NumColors * sizeof(RGBQUAD);
- }
- static HANDLE AllocRoomForDIB(BITMAPINFOHEADER bi, HBITMAP hBitmap)
- {
- DWORD dwLen;
- HANDLE hDIB;
- HDC hDC;
- LPBITMAPINFOHEADER lpbi;
- HANDLE hTemp;
- // Figure out the size needed to hold the BITMAPINFO structure
- // (which includes the BITMAPINFOHEADER and the color table).
- dwLen = bi.biSize + PaletteSize((LPSTR) &bi);
- hDIB = GlobalAlloc(GHND,dwLen);
- // Check that DIB handle is valid
- if (!hDIB)
- return NULL;
- // Set up the BITMAPINFOHEADER in the newly allocated global memory,
- // then call GetDIBits() with lpBits = NULL to have it fill in the
- // biSizeImage field for us.
- lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
- *lpbi = bi;
- MONITORINFOEX mi;
- mi.cbSize = sizeof(mi);
- GetMonitorInfoA(GetPrimaryMonitorHandle(), &mi);
- hDC = CreateDCA(mi.szDevice, NULL, NULL, NULL);
- GetDIBits(hDC, hBitmap, 0, (UINT) bi.biHeight, NULL, (LPBITMAPINFO)lpbi,
- DIB_RGB_COLORS);
- DeleteDC(hDC);
- // If the driver did not fill in the biSizeImage field,
- // fill it in -- NOTE: this is a bug in the driver!
- if (lpbi->biSizeImage == 0)
- lpbi->biSizeImage = (DWORD)(lpbi->biWidth * lpbi->biBitCount) * lpbi->biHeight / 8;
- // Get the size of the memory block we need
- dwLen = lpbi->biSize + PaletteSize((LPSTR) &bi) + lpbi->biSizeImage;
- // Unlock the memory block
- GlobalUnlock(hDIB);
- // ReAlloc the buffer big enough to hold all the bits
- if (hTemp = GlobalReAlloc(hDIB,dwLen,0))
- return hTemp;
- else
- {
- // Else free memory block and return failure
- GlobalFree(hDIB);
- return NULL;
- }
- }
- static HANDLE ChangeBitmapFormat(HBITMAP hBitmap, WORD wBitCount, DWORD dwCompression, HPALETTE hPal)
- {
- HDC hDC; // Screen DC
- HANDLE hNewDIB=NULL; // Handle to new DIB
- BITMAP Bitmap; // BITMAP data structure
- BITMAPINFOHEADER bi; // Bitmap info. header
- LPBITMAPINFOHEADER lpbi; // Pointer to bitmap header
- HPALETTE hOldPal=NULL; // Handle to palette
- WORD NewBPP; // New bits per pixel
- DWORD NewComp; // New compression format
- // Check for a valid bitmap handle
- if (!hBitmap)
- return NULL;
- // Validate wBitCount and dwCompression
- // They must match correctly (i.e., BI_RLE4 and 4 BPP or
- // BI_RLE8 and 8BPP, etc.) or we return failure
- if (wBitCount == 0)
- {
- NewComp = dwCompression;
- if (NewComp == BI_RLE4)
- NewBPP = 4;
- else if (NewComp == BI_RLE8)
- NewBPP = 8;
- else // Not enough info */
- return NULL;
- }
- else if (wBitCount == 1 && dwCompression == BI_RGB)
- {
- NewBPP = wBitCount;
- NewComp = BI_RGB;
- }
- else if (wBitCount == 4)
- {
- NewBPP = wBitCount;
- if (dwCompression == BI_RGB || dwCompression == BI_RLE4)
- NewComp = dwCompression;
- else
- return NULL;
- }
- else if (wBitCount == 8)
- {
- NewBPP = wBitCount;
- if (dwCompression == BI_RGB || dwCompression == BI_RLE8)
- NewComp = dwCompression;
- else
- return NULL;
- }
- else if (wBitCount == 24 && dwCompression == BI_RGB)
- {
- NewBPP = wBitCount;
- NewComp = BI_RGB;
- }
- else
- return NULL;
- // Get info about the bitmap
- GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
- // Fill in the BITMAPINFOHEADER appropriately
- bi.biSize = sizeof(BITMAPINFOHEADER);
- bi.biWidth = Bitmap.bmWidth;
- bi.biHeight = Bitmap.bmHeight;
- bi.biPlanes = 1;
- bi.biBitCount = NewBPP;
- bi.biCompression = NewComp;
- bi.biSizeImage = 0;
- bi.biXPelsPerMeter = 0;
- bi.biYPelsPerMeter = 0;
- bi.biClrUsed = 0;
- bi.biClrImportant = 0;
- // Go allocate room for the new DIB
- hNewDIB = AllocRoomForDIB(bi, hBitmap);
- if (!hNewDIB)
- return NULL;
- // Get a pointer to the new DIB
- lpbi = (LPBITMAPINFOHEADER)GlobalLock(hNewDIB);
- // If we have a palette, get a DC and select/realize it
- if (hPal)
- {
- MONITORINFOEX mi;
- mi.cbSize = sizeof(mi);
- GetMonitorInfoA(GetPrimaryMonitorHandle(), &mi);
- hDC = CreateDCA(mi.szDevice, NULL, NULL, NULL);
- hOldPal = SelectPalette(hDC, hPal, FALSE);
- RealizePalette(hDC);
- }
- // Call GetDIBits and get the new DIB bits
- if (!GetDIBits(hDC, hBitmap, 0, (UINT) lpbi->biHeight, (LPSTR)lpbi +
- (WORD)lpbi->biSize + PaletteSize((LPSTR)lpbi), (LPBITMAPINFO)lpbi,
- DIB_RGB_COLORS))
- {
- GlobalUnlock(hNewDIB);
- GlobalFree(hNewDIB);
- hNewDIB = NULL;
- }
- // Clean up and return
- if (hOldPal)
- {
- SelectPalette(hDC, hOldPal, TRUE);
- RealizePalette(hDC);
- DeleteDC(hDC);
- }
- // Unlock the new DIB's memory block
- if (hNewDIB)
- GlobalUnlock(hNewDIB);
- return hNewDIB;
- }
- static int SaveDib(HANDLE hDib, void *buf)
- {
- BITMAPFILEHEADER bmfHdr; // Header for Bitmap file
- LPBITMAPINFOHEADER lpBI; // Pointer to DIB info structure
- DWORD dwDIBSize;
- lpBI = (LPBITMAPINFOHEADER)GlobalLock(hDib);
- if (!lpBI)
- {
- return -1;
- }
- if (lpBI->biSize != sizeof(BITMAPINFOHEADER))
- {
- GlobalUnlock(hDib);
- return -1;
- }
- memcpy(buf, (LPSTR)lpBI + (WORD)lpBI->biSize + PaletteSize((LPSTR)lpBI), lpBI->biSizeImage);
- GlobalUnlock(hDib);
- return 0;
- }
- int screencapture_capture1(RECT *lprc, void *buf, int *size)
- {
- int width = lprc->right - lprc->left;
- int height = lprc->bottom - lprc->top;
- int linesize = (width * 3 + 3) & 0xfffffffc;
- if (buf == NULL) {
- *size = linesize * height;
- return 0;
- }
- HBITMAP hBitmap = CopyScreenToBitmap(lprc);
- HPALETTE hPal = GetSystemPalette();
- HANDLE hDIB = ChangeBitmapFormat(hBitmap, 24, BI_RGB, hPal);
- SaveDib(hDIB, buf);
- GlobalFree(hDIB);
- DeleteObject(hPal);
- DeleteObject(hBitmap);
- return 0;
- }
- int screencapture_capture(RECT *lprc, void *buf, int *size)
- {
- int width = lprc->right - lprc->left;
- int height = lprc->bottom - lprc->top;
- int linesize = (width * 3 + 3) & 0xfffffffc;
- if (buf == NULL) {
- *size = linesize * height;
- return 0;
- }
- assert(*size >= linesize * height);
- HDC dc = NULL;
- HDC memdc = NULL;
- HBITMAP hbm = NULL;
- int rc;
- BITMAPINFO bmpInfo;
- //HWND hWndDeskTop = GetDesktopWindow();
- void *data;
- MONITORINFOEX mi;
- mi.cbSize = sizeof(mi);
- GetMonitorInfoA(GetPrimaryMonitorHandle(), &mi);
- dc = CreateDCA(mi.szDevice, NULL, NULL, NULL);
- //dc = GetDC(hWndDeskTop);
- //dc = CreateDCA("DISPLAY", 0, 0, 0);
- if (!dc)
- return -1;
- memdc = CreateCompatibleDC(dc);
- if (memdc) {
- memset(&bmpInfo, 0, sizeof(bmpInfo));
- bmpInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
- bmpInfo.bmiHeader.biPlanes = 1;
- bmpInfo.bmiHeader.biWidth = width;
- bmpInfo.bmiHeader.biHeight = height;
- bmpInfo.bmiHeader.biCompression = BI_RGB;
- bmpInfo.bmiHeader.biBitCount = 24;
- bmpInfo.bmiHeader.biSizeImage = width * height * 3;
- hbm = CreateDIBSection(dc, &bmpInfo, DIB_RGB_COLORS, &data, NULL, 0);
- //hbm = CreateCompatibleBitmap(memdc, width, height);
- }
- if (!memdc || !hbm) {
- rc = -1;
- goto on_error;
- }
- HGDIOBJ old = SelectObject(memdc, hbm);
- BOOL bret = BitBlt(memdc, 0, 0, width, height, dc, lprc ? lprc->left : 0, lprc ? lprc->top : 0, SRCCOPY);
- if (!bret) {
- rc = -1;
- goto on_error;
- }
- SelectObject(memdc, old);
- memcpy(buf, data, bmpInfo.bmiHeader.biSizeImage);
- *size = linesize * height;
- rc = 0;
- on_error:
- if (memdc)
- DeleteDC(memdc);
- if (hbm)
- DeleteObject(hbm);
- if (dc)
- DeleteDC(dc);//
- return rc;
- }
- #else
- #include <X11/Xutil.h>
- #include <X11/Xlib.h>
- int screencapture_capture(RECT* lprc, void* buf, int* size) {
- int width = lprc->right - lprc->left;
- int height = lprc->bottom - lprc->top;
- int linesize = (width * 3 + 3) & 0xfffffffc;
- if (buf == NULL) {
- *size = linesize * height;
- return 0;
- }
- Display* display = XOpenDisplay(NULL);
- Window root = DefaultRootWindow(display);
- XImage* image = XGetImage(display, root, lprc ? lprc->left : 0, lprc ? lprc->top : 0, width, height, AllPlanes, ZPixmap);
- unsigned long red_mask = image->red_mask;
- unsigned long green_mask = image->green_mask;
- unsigned long blue_mask = image->blue_mask;
- for (int x = 0; x < width; x++){
- for (int y = 0; y < height; y++)
- {
- unsigned long pixel = XGetPixel(image, x, y);
- unsigned char blue = pixel & blue_mask;
- unsigned char green = (pixel & green_mask) >> 8;
- unsigned char red = (pixel & red_mask) >> 16;
- ((unsigned char *)buf)[(x + width * y) * 3] = red;
- ((unsigned char*)buf)[(x + width * y) * 3 + 1] = green;
- ((unsigned char*)buf)[(x + width * y) * 3 + 2] = blue;
- }
- }
- *size = linesize * height;
- if (image != NULL) {
- XDestroyImage(image);
- image = NULL;
- }
- if (display != NULL) {
- XCloseDisplay(display);
- display = NULL;
- }
- return 0;
- }
- int getScreenSize(int* width, int* height) {
- Display* display = XOpenDisplay(NULL);
- int default_id = DefaultScreen(display);
- Screen* screen = ScreenOfDisplay(display, default_id);
- *width = screen->width;
- *height = screen->height;
- if (display != NULL) {
- XCloseDisplay(display);
- display = NULL;
- }
- return 0;
- }
- #endif
- int screencapture_clipoff(int width, int height, void* buf, int n_rc, RECT* rcs)
- {
- int i, k;
- char* p;
- for (i = 0; i < n_rc; ++i) {
- RECT* lprc = &rcs[i];
- for (k = lprc->top, p = (char*)buf + lprc->top * width * 3 + lprc->left * 3; k < lprc->bottom; ++k) {
- memset(p, 0, (lprc->right - lprc->left) * 3);
- p += width * 3;
- }
- }
- return 0;
- }
|