forked from mpereiraesaa/libnut
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathscreengrab.c
101 lines (86 loc) · 2.86 KB
/
screengrab.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include "../screengrab.h"
#include "../endian.h"
#include <stdlib.h> /* malloc() */
MMRect getScaledRect(MMRect input)
{
// Configure DPI awareness to fetch unscaled display size
DPI_AWARENESS_CONTEXT initialDpiAwareness = SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
size_t scaledDesktopWidth = (size_t)GetSystemMetrics(SM_CXSCREEN);
size_t scaledDesktopHeight = (size_t)GetSystemMetrics(SM_CYSCREEN);
// Reset DPI awareness to avoid inconsistencies on future calls to copyMMBitmapFromDisplayInRect
SetThreadDpiAwarenessContext(initialDpiAwareness);
size_t desktopWidth = (size_t)GetSystemMetrics(SM_CXSCREEN);
size_t desktopHeight = (size_t)GetSystemMetrics(SM_CYSCREEN);
double scaleX = (double)(desktopWidth / (double)scaledDesktopWidth);
double scaleY = (double)(desktopHeight / (double)scaledDesktopHeight);
return MMRectMake(
input.origin.x / scaleX,
input.origin.y / scaleY,
input.size.width / scaleX,
input.size.height / scaleY
);
}
MMBitmapRef copyMMBitmapFromDisplayInRect(MMRect rect)
{
MMBitmapRef bitmap;
void *data;
HDC screen = NULL, screenMem = NULL;
HBITMAP dib;
BITMAPINFO bi;
screen = GetWindowDC(NULL); /* Get entire screen */
MMRect scaledRect = getScaledRect(rect);
if (screen == NULL) {
return NULL;
}
/* Initialize bitmap info. */
bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
bi.bmiHeader.biWidth = (long)scaledRect.size.width;
bi.bmiHeader.biHeight = -(long)scaledRect.size.height; /* Non-cartesian, please */
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 32;
bi.bmiHeader.biCompression = BI_RGB;
bi.bmiHeader.biSizeImage = (DWORD)(4 * scaledRect.size.width * scaledRect.size.height);
bi.bmiHeader.biXPelsPerMeter = 0;
bi.bmiHeader.biYPelsPerMeter = 0;
bi.bmiHeader.biClrUsed = 0;
bi.bmiHeader.biClrImportant = 0;
/* 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)scaledRect.size.width,
(int)scaledRect.size.height,
screen,
(int)scaledRect.origin.x,
(int)scaledRect.origin.y,
SRCCOPY))
{
/* Error copying data. */
ReleaseDC(NULL, screen);
DeleteObject(dib);
if (screenMem != NULL) {
DeleteDC(screenMem);
}
return NULL;
}
bitmap = createMMBitmap(NULL,
scaledRect.size.width,
scaledRect.size.height,
4 * scaledRect.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;
}