robotgo/screen/screengrab_init.h
2016-10-06 18:41:37 +08:00

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
}