#include "screengrab.h" #include "../base/bmp_io_init.h" #include "../base/endian.h" #include /* malloc() */ #if defined(IS_MACOSX) #include #include #include #elif defined(USE_X11) #include #include #include "../base/xdisplay_init.h" #elif defined(IS_WINDOWS) // #include "windows.h" // #include #include #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 }