robotgo/screen/screengrab_c.h
2018-02-11 19:03:35 +08:00

150 lines
4.1 KiB
C

#include "screengrab.h"
#include "../base/bmp_io_c.h"
#include "../base/endian.h"
#include <stdlib.h> /* malloc() */
#if defined(IS_MACOSX)
#include <OpenGL/OpenGL.h>
#include <OpenGL/gl.h>
#include <ApplicationServices/ApplicationServices.h>
#elif defined(USE_X11)
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "../base/xdisplay_c.h"
#elif defined(IS_WINDOWS)
// #include "windows.h"
// #include <wingdi.h>
#include <string.h>
#endif
MMBitmapRef copyMMBitmapFromDisplayInRect(MMRect rect){
#if defined(IS_MACOSX)
MMBitmapRef bitmap = NULL;
uint8_t *buffer = NULL;
size_t bufferSize = 0;
CGDirectDisplayID displayID = CGMainDisplayID();
CGImageRef image = CGDisplayCreateImageForRect(displayID,
CGRectMake(rect.origin.x,
rect.origin.y,
rect.size.width,
rect.size.height));
if (!image) { return NULL; }
CFDataRef imageData = CGDataProviderCopyData(CGImageGetDataProvider(image));
if (!imageData) { return NULL; }
bufferSize = CFDataGetLength(imageData);
buffer = malloc(bufferSize);
CFDataGetBytes(imageData, CFRangeMake(0,bufferSize), buffer);
bitmap = createMMBitmap(buffer,
CGImageGetWidth(image),
CGImageGetHeight(image),
CGImageGetBytesPerRow(image),
CGImageGetBitsPerPixel(image),
CGImageGetBitsPerPixel(image) / 8);
CFRelease(imageData);
CGImageRelease(image);
return bitmap;
#elif defined(USE_X11)
MMBitmapRef bitmap;
Display *display = XOpenDisplay(NULL);
XImage *image = XGetImage(display,
XDefaultRootWindow(display),
(int)rect.origin.x,
(int)rect.origin.y,
(unsigned int)rect.size.width,
(unsigned int)rect.size.height,
AllPlanes, ZPixmap);
XCloseDisplay(display);
if (image == NULL) return NULL;
bitmap = createMMBitmap((uint8_t *)image->data,
rect.size.width,
rect.size.height,
(size_t)image->bytes_per_line,
(uint8_t)image->bits_per_pixel,
(uint8_t)image->bits_per_pixel / 8);
image->data = NULL; /* Steal ownership of bitmap data so we don't have to
* copy it. */
XDestroyImage(image);
return bitmap;
#elif defined(IS_WINDOWS)
MMBitmapRef bitmap;
void *data;
HDC screen = NULL, screenMem = NULL;
HBITMAP dib;
BITMAPINFO bi;
/* Initialize bitmap info. */
bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
bi.bmiHeader.biWidth = (long)rect.size.width;
bi.bmiHeader.biHeight = -(long)rect.size.height; /* Non-cartesian, please */
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 32;
bi.bmiHeader.biCompression = BI_RGB;
bi.bmiHeader.biSizeImage = (DWORD)(4 * rect.size.width * rect.size.height);
bi.bmiHeader.biXPelsPerMeter = 0;
bi.bmiHeader.biYPelsPerMeter = 0;
bi.bmiHeader.biClrUsed = 0;
bi.bmiHeader.biClrImportant = 0;
screen = GetDC(NULL); /* Get entire screen */
if (screen == NULL) return NULL;
/* Get screen data in display device context. */
dib = CreateDIBSection(screen, &bi, DIB_RGB_COLORS, &data, NULL, 0);
/* Copy the data into a bitmap struct. */
if ((screenMem = CreateCompatibleDC(screen)) == NULL ||
SelectObject(screenMem, dib) == NULL ||
!BitBlt(screenMem,
(int)0,
(int)0,
(int)rect.size.width,
(int)rect.size.height,
screen,
rect.origin.x,
rect.origin.y,
SRCCOPY)) {
/* Error copying data. */
ReleaseDC(NULL, screen);
DeleteObject(dib);
if (screenMem != NULL) DeleteDC(screenMem);
return NULL;
}
bitmap = createMMBitmap(NULL,
rect.size.width,
rect.size.height,
4 * rect.size.width,
(uint8_t)bi.bmiHeader.biBitCount,
4);
/* Copy the data to our pixel buffer. */
if (bitmap != NULL) {
bitmap->imageBuffer = malloc(bitmap->bytewidth * bitmap->height);
memcpy(bitmap->imageBuffer, data, bitmap->bytewidth * bitmap->height);
}
ReleaseDC(NULL, screen);
DeleteObject(dib);
DeleteDC(screenMem);
return bitmap;
#endif
}