From 2e3ec50d90630b368b711cbf81da95e32642b624 Mon Sep 17 00:00:00 2001 From: Simon Hofmann Date: Sat, 5 Sep 2020 20:39:17 +0200 Subject: [PATCH] (#20) Split screengrab.c --- CMakeLists.txt | 8 +-- src/linux/screengrab.c | 35 ++++++++++ src/macos/screengrab.c | 44 ++++++++++++ src/screengrab.c | 147 ----------------------------------------- src/win32/screengrab.c | 71 ++++++++++++++++++++ 5 files changed, 154 insertions(+), 151 deletions(-) create mode 100644 src/linux/screengrab.c create mode 100644 src/macos/screengrab.c delete mode 100644 src/screengrab.c create mode 100644 src/win32/screengrab.c diff --git a/CMakeLists.txt b/CMakeLists.txt index b7613f0..f2a868e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,13 +4,13 @@ set(CMAKE_CXX_STANDARD 17) project(libnut) # Source -set(SOURCE_FILES "src/main.cc" "src/deadbeef_rand.c" "src/keycode.c" "src/MMBitmap.c" "src/screengrab.c") +set(SOURCE_FILES "src/main.cc" "src/deadbeef_rand.c" "src/keycode.c" "src/MMBitmap.c") if (UNIX AND NOT APPLE) - set(SOURCE_FILES "${SOURCE_FILES}" "src/linux/keypress.c" "src/linux/mouse.c" "src/linux/screen.c" "src/linux/xdisplay.c" "src/linux/highlightwindow.c" "src/linux/window_manager.cc") + set(SOURCE_FILES "${SOURCE_FILES}" "src/linux/keypress.c" "src/linux/mouse.c" "src/linux/screen.c" "src/linux/screengrab.c" "src/linux/xdisplay.c" "src/linux/highlightwindow.c" "src/linux/window_manager.cc") elseif (UNIX AND APPLE) - set(SOURCE_FILES "${SOURCE_FILES}" "src/macos/keypress.c" "src/macos/mouse.c" "src/macos/screen.c" "src/macos/highlightwindow.m" "src/macos/window_manager.mm") + set(SOURCE_FILES "${SOURCE_FILES}" "src/macos/keypress.c" "src/macos/mouse.c" "src/macos/screen.c" "src/macos/screengrab.c" "src/macos/highlightwindow.m" "src/macos/window_manager.mm") elseif (WIN32) - set(SOURCE_FILES "${SOURCE_FILES}" "src/win32/keypress.c" "src/win32/mouse.c" "src/win32/screen.c" "src/win32/highlightwindow.c" "src/win32/window_manager.cc") + set(SOURCE_FILES "${SOURCE_FILES}" "src/win32/keypress.c" "src/win32/mouse.c" "src/win32/screen.c" "src/win32/screengrab.c" "src/win32/highlightwindow.c" "src/win32/window_manager.cc") endif() add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${CMAKE_JS_SRC}) diff --git a/src/linux/screengrab.c b/src/linux/screengrab.c new file mode 100644 index 0000000..5be31b6 --- /dev/null +++ b/src/linux/screengrab.c @@ -0,0 +1,35 @@ +#include "../screengrab.h" +#include "../endian.h" +#include /* malloc() */ + +#include +#include +#include "../xdisplay.h" + +MMBitmapRef copyMMBitmapFromDisplayInRect(MMRect rect) +{ + 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; +} diff --git a/src/macos/screengrab.c b/src/macos/screengrab.c new file mode 100644 index 0000000..d0d8d86 --- /dev/null +++ b/src/macos/screengrab.c @@ -0,0 +1,44 @@ +#include "../screengrab.h" +#include "../endian.h" +#include /* malloc() */ + +#include + +MMBitmapRef copyMMBitmapFromDisplayInRect(MMRect rect) +{ + 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; +} diff --git a/src/screengrab.c b/src/screengrab.c deleted file mode 100644 index 6ac9657..0000000 --- a/src/screengrab.c +++ /dev/null @@ -1,147 +0,0 @@ -#include "screengrab.h" -#include "endian.h" -#include /* malloc() */ - -#if defined(IS_MACOSX) - #include - #include - #include -#elif defined(USE_X11) - #include - #include - #include "xdisplay.h" -#elif defined(IS_WINDOWS) -#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 -} diff --git a/src/win32/screengrab.c b/src/win32/screengrab.c new file mode 100644 index 0000000..71d5cdb --- /dev/null +++ b/src/win32/screengrab.c @@ -0,0 +1,71 @@ +#include "../screengrab.h" +#include "../endian.h" +#include /* malloc() */ + +MMBitmapRef copyMMBitmapFromDisplayInRect(MMRect rect) +{ + 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; +}