mirror of
https://github.com/go-vgo/robotgo.git
synced 2025-06-03 07:33:55 +00:00
164 lines
5.1 KiB
C
164 lines
5.1 KiB
C
#include "screengrab.h"
|
|
#include "../base/bmp_io_init.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_init.h"
|
|
#elif defined(IS_WINDOWS)
|
|
// #include "windows.h"
|
|
// #include <wingdi.h>
|
|
#include <string.h>
|
|
#endif
|
|
|
|
MMBitmapRef copyMMBitmapFromDisplayInRect(MMRect rect)
|
|
{
|
|
#if defined(IS_MACOSX)
|
|
|
|
size_t bytewidth;
|
|
uint8_t bitsPerPixel, bytesPerPixel;
|
|
//uint8_t *buffer;
|
|
|
|
CGDirectDisplayID displayID = CGMainDisplayID();
|
|
|
|
//Replacement for CGDisplayBitsPerPixel.
|
|
CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displayID);
|
|
size_t depth = 0;
|
|
|
|
CFStringRef pixEnc = CGDisplayModeCopyPixelEncoding(mode);
|
|
if(CFStringCompare(pixEnc, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo)
|
|
depth = 32;
|
|
else if(CFStringCompare(pixEnc, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo)
|
|
depth = 16;
|
|
else if(CFStringCompare(pixEnc, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo)
|
|
depth = 8;
|
|
|
|
CGDisplayModeRelease(mode);
|
|
CFRelease(pixEnc);
|
|
|
|
bitsPerPixel = (uint8_t) depth;
|
|
bytesPerPixel = bitsPerPixel / 8;
|
|
/* Align width to padding. */
|
|
//bytewidth = ADD_PADDING(rect.size.width * bytesPerPixel);
|
|
bytewidth = rect.size.width * bytesPerPixel;
|
|
|
|
/* Convert Quartz point to postscript point. */
|
|
//rect.origin.y = CGDisplayPixelsHigh(displayID) - rect.origin.y - rect.size.height;
|
|
|
|
CGImageRef image = CGDisplayCreateImageForRect(displayID, CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height));
|
|
|
|
// Request access to the raw pixel data via the image's DataProvider.
|
|
CGDataProviderRef provider = CGImageGetDataProvider(image);
|
|
CFDataRef data = CGDataProviderCopyData(provider);
|
|
|
|
size_t width, height;
|
|
width = CGImageGetWidth(image);
|
|
height = CGImageGetHeight(image);
|
|
size_t bpp = CGImageGetBitsPerPixel(image) / 8;
|
|
|
|
uint8 *pixels = malloc(width * height * bpp);
|
|
memcpy(pixels, CFDataGetBytePtr(data), width * height * bpp);
|
|
CFRelease(data);
|
|
CGImageRelease(image);
|
|
|
|
return createMMBitmap(pixels, rect.size.width, rect.size.height, bytewidth,
|
|
bitsPerPixel, bytesPerPixel);
|
|
#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
|
|
}
|