special_input_device 0.0.0 → 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/special_input_device/color.c +25 -6
- data/ext/special_input_device/color.h +5 -1
- data/ext/special_input_device/extconf.rb +2 -2
- data/ext/special_input_device/image.c +728 -0
- data/ext/special_input_device/image.h +8 -0
- data/ext/special_input_device/{interception_connector.c → interception.c} +7 -3
- data/ext/special_input_device/{interception_connector.h → interception.h} +0 -0
- data/ext/special_input_device/keyboard.c +4 -4
- data/ext/special_input_device/mouse.c +26 -28
- data/ext/special_input_device/ruby_macro.h +11 -3
- data/ext/special_input_device/screen.c +54 -164
- data/ext/special_input_device/special_input_device.c +2 -2
- data/ext/special_input_device/special_input_device.h +2 -1
- data/ext/special_input_device/win32error.c +0 -2
- data/ext/special_input_device/window.c +82 -105
- data/lib/special_input_device/color.rb +2 -3
- data/lib/special_input_device/image.rb +2 -61
- data/lib/special_input_device/point.rb +0 -1
- data/lib/special_input_device/special_input_device.rb +0 -1
- metadata +7 -15
- data/lib/special_input_device/image/bmp.rb +0 -89
- data/lib/special_input_device/image/error/damaged_image_error.rb +0 -4
- data/lib/special_input_device/image/error/image_error.rb +0 -3
- data/lib/special_input_device/image/error/unsupported_image_format_error.rb +0 -4
- data/lib/special_input_device/table_2d.rb +0 -157
- data/stab/keyboard.rb +0 -35
- data/stab/mouse.rb +0 -189
- data/stab/screen.rb +0 -56
- data/stab/win32_error.rb +0 -20
- data/stab/window.rb +0 -398
|
@@ -0,0 +1,728 @@
|
|
|
1
|
+
#include "special_input_device.h"
|
|
2
|
+
#include "color.h"
|
|
3
|
+
|
|
4
|
+
#define BI_RGB 0L
|
|
5
|
+
#define BI_BITFIELDS 3L
|
|
6
|
+
#define BI_ALPHABITFIELDS 6L
|
|
7
|
+
|
|
8
|
+
#define PixelAt(x, y) (cData->pixelTable[cData->height + ~y][x])
|
|
9
|
+
|
|
10
|
+
static VALUE ruby__alloc(VALUE self);
|
|
11
|
+
|
|
12
|
+
typedef struct {
|
|
13
|
+
UINT height;
|
|
14
|
+
RGBQUAD **pixelTable;
|
|
15
|
+
} SID_IMAGE_DATA;
|
|
16
|
+
|
|
17
|
+
VALUE ruby___image_new(UINT cWidth, UINT cHeight) {
|
|
18
|
+
VALUE instance = ruby__alloc(specialInputDevice_image);
|
|
19
|
+
SID_IMAGE_DATA *cData = GET_DATA_OBJECT(instance);
|
|
20
|
+
UINT cT;
|
|
21
|
+
cData->height = cHeight;
|
|
22
|
+
cData->pixelTable = ALLOC_N(LPRGBQUAD, cHeight);
|
|
23
|
+
rb_iv_set(instance, "@width", UINT2NUM(cWidth));
|
|
24
|
+
rb_iv_set(instance, "@height", UINT2NUM(cHeight));
|
|
25
|
+
for (cT = 0; cT < cHeight; cT++)
|
|
26
|
+
cData->pixelTable[cT] = ALLOC_N(RGBQUAD, cWidth);
|
|
27
|
+
return instance;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
VALUE ruby___image_new_from_bitmap(HBITMAP cHBitmap) {
|
|
31
|
+
VALUE instance;
|
|
32
|
+
SID_IMAGE_DATA *cData;
|
|
33
|
+
HDC cScreenDC = GetDC(NULL);
|
|
34
|
+
BITMAP cBitmap;
|
|
35
|
+
UINT cWidth;
|
|
36
|
+
UINT cHeight;
|
|
37
|
+
BITMAPINFO cBitmapInfo;
|
|
38
|
+
UINT cT0;
|
|
39
|
+
UINT cT1;
|
|
40
|
+
GetObject(cHBitmap, sizeof(BITMAP), &cBitmap);
|
|
41
|
+
cWidth = (UINT) abs(cBitmap.bmWidth);
|
|
42
|
+
cHeight = (UINT) abs(cBitmap.bmHeight);
|
|
43
|
+
instance = ruby___image_new(cWidth, cHeight);
|
|
44
|
+
cData = GET_DATA_OBJECT(instance);
|
|
45
|
+
cBitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
|
46
|
+
cBitmapInfo.bmiHeader.biWidth = (LONG) cWidth;
|
|
47
|
+
cBitmapInfo.bmiHeader.biHeight = (LONG) cHeight;
|
|
48
|
+
cBitmapInfo.bmiHeader.biPlanes = 1;
|
|
49
|
+
cBitmapInfo.bmiHeader.biBitCount = 32;
|
|
50
|
+
cBitmapInfo.bmiHeader.biCompression = BI_RGB;
|
|
51
|
+
cBitmapInfo.bmiHeader.biSizeImage = 0;
|
|
52
|
+
cBitmapInfo.bmiHeader.biXPelsPerMeter = 0;
|
|
53
|
+
cBitmapInfo.bmiHeader.biYPelsPerMeter = 0;
|
|
54
|
+
cBitmapInfo.bmiHeader.biClrUsed = 0;
|
|
55
|
+
cBitmapInfo.bmiHeader.biClrImportant = 0;
|
|
56
|
+
for (cT0 = 0; cT0 < cHeight; cT0++) {
|
|
57
|
+
GetDIBits(cScreenDC, cHBitmap, cT0, 1, cData->pixelTable[cT0], &cBitmapInfo, DIB_RGB_COLORS);
|
|
58
|
+
for (cT1 = 0; cT1 < cWidth; cT1++)
|
|
59
|
+
cData->pixelTable[cT0][cT1].rgbReserved = 0xFF;
|
|
60
|
+
}
|
|
61
|
+
return instance;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
typedef union {
|
|
65
|
+
BITMAPINFOHEADER v1;
|
|
66
|
+
BITMAPV4HEADER v4;
|
|
67
|
+
BITMAPV5HEADER v5;
|
|
68
|
+
} DIB_HEADER;
|
|
69
|
+
|
|
70
|
+
/*
|
|
71
|
+
* Load an image from a file.
|
|
72
|
+
* @overload load(path)
|
|
73
|
+
* @param [String] path a path of file
|
|
74
|
+
* @return [SpecialInputDevice::Image] a new image
|
|
75
|
+
*/
|
|
76
|
+
static VALUE ruby__load(VALUE self, VALUE path) {
|
|
77
|
+
LPCTSTR cPath = RUBY_VALUE_TO_LPCTSTR(path);
|
|
78
|
+
VALUE image;
|
|
79
|
+
SID_IMAGE_DATA *cData;
|
|
80
|
+
FILE *cFile;
|
|
81
|
+
BITMAPFILEHEADER cFileHeader;
|
|
82
|
+
DIB_HEADER cDIBHeader;
|
|
83
|
+
RGBQUAD *cColorTable;
|
|
84
|
+
BYTE *cPixelArray;
|
|
85
|
+
LARGE_INTEGER cSystemFileSize;
|
|
86
|
+
UINT cWidth;
|
|
87
|
+
UINT cHeight;
|
|
88
|
+
UINT cRowSize;
|
|
89
|
+
DWORD cByteRead;
|
|
90
|
+
UINT cT0;
|
|
91
|
+
UINT cT1;
|
|
92
|
+
UINT cT2;
|
|
93
|
+
UINT cT3;
|
|
94
|
+
cFile = CreateFile(cPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
|
|
95
|
+
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
|
|
96
|
+
if (cFile == INVALID_HANDLE_VALUE)
|
|
97
|
+
RAISE_WIN32_ERROR();
|
|
98
|
+
if (!ReadFile(cFile, &cFileHeader, sizeof(cFileHeader), &cByteRead, NULL))
|
|
99
|
+
RAISE_WIN32_ERROR();
|
|
100
|
+
switch (cFileHeader.bfType) {
|
|
101
|
+
case 0x4D42: // BM
|
|
102
|
+
case 0x4142: // BA
|
|
103
|
+
case 0x4943: // CI
|
|
104
|
+
case 0x5043: // CP
|
|
105
|
+
case 0x4349: // IC
|
|
106
|
+
case 0x5450: // PT
|
|
107
|
+
break;
|
|
108
|
+
default:
|
|
109
|
+
rb_raise(rb_eArgError, "The path does not point to a bitmap file.");
|
|
110
|
+
}
|
|
111
|
+
if (!GetFileSizeEx(cFile, &cSystemFileSize))
|
|
112
|
+
RAISE_WIN32_ERROR();
|
|
113
|
+
if (cSystemFileSize.QuadPart != cFileHeader.bfSize)
|
|
114
|
+
rb_raise(rb_eArgError, "The size of the file should be %lu bytes, but the image only has %lli bytes.",
|
|
115
|
+
cFileHeader.bfSize, cSystemFileSize.QuadPart);
|
|
116
|
+
if (!ReadFile(cFile, &cDIBHeader.v1.biSize, sizeof(DWORD), &cByteRead, NULL))
|
|
117
|
+
RAISE_WIN32_ERROR();
|
|
118
|
+
switch (cDIBHeader.v1.biSize) {
|
|
119
|
+
case sizeof(BITMAPINFOHEADER):
|
|
120
|
+
case sizeof(BITMAPV4HEADER):
|
|
121
|
+
case sizeof(BITMAPV5HEADER):
|
|
122
|
+
break;
|
|
123
|
+
default:
|
|
124
|
+
rb_raise(rb_eArgError, "The bitmap file is using an unsupported DIB header.");
|
|
125
|
+
}
|
|
126
|
+
if (!ReadFile(cFile, &cDIBHeader.v1.biSize + 1, cDIBHeader.v1.biSize - sizeof(DWORD), &cByteRead, NULL))
|
|
127
|
+
RAISE_WIN32_ERROR();
|
|
128
|
+
cWidth = (UINT) abs(cDIBHeader.v1.biWidth);
|
|
129
|
+
cHeight = (UINT) abs(cDIBHeader.v1.biHeight);
|
|
130
|
+
cRowSize =
|
|
131
|
+
(cDIBHeader.v1.biBitCount * cWidth + (8 * sizeof(RGBQUAD) - 1)) / (8 * sizeof(RGBQUAD)) * sizeof(RGBQUAD);
|
|
132
|
+
if (cDIBHeader.v1.biWidth < 0)
|
|
133
|
+
rb_raise(rb_eArgError, "The bitmap file has been damaged. (width < 0)");
|
|
134
|
+
if (cDIBHeader.v1.biPlanes != 1)
|
|
135
|
+
rb_raise(rb_eArgError, "The bitmap file has been damaged. (planes != 1)");
|
|
136
|
+
switch (cDIBHeader.v1.biCompression) {
|
|
137
|
+
case BI_RGB:
|
|
138
|
+
break;
|
|
139
|
+
case BI_BITFIELDS:
|
|
140
|
+
case BI_ALPHABITFIELDS:
|
|
141
|
+
switch (cDIBHeader.v1.biBitCount) {
|
|
142
|
+
case 16:
|
|
143
|
+
case 24:
|
|
144
|
+
case 32:
|
|
145
|
+
break;
|
|
146
|
+
default:
|
|
147
|
+
rb_raise(rb_eArgError, "The bitmap file is using an unsupported compression method.");
|
|
148
|
+
}
|
|
149
|
+
break;
|
|
150
|
+
default:
|
|
151
|
+
rb_raise(rb_eArgError, "The bitmap file is using an unsupported compression method.");
|
|
152
|
+
}
|
|
153
|
+
if (cDIBHeader.v1.biSizeImage != cRowSize * cHeight)
|
|
154
|
+
rb_raise(rb_eArgError, "The bitmap file has been damaged. (incorrect sizeImage)");
|
|
155
|
+
switch (cDIBHeader.v1.biSize) {
|
|
156
|
+
case sizeof(BITMAPINFOHEADER):
|
|
157
|
+
switch (cDIBHeader.v1.biCompression) {
|
|
158
|
+
case BI_BITFIELDS:
|
|
159
|
+
if (!ReadFile(cFile, &cDIBHeader.v5.bV5RedMask, sizeof(DWORD) * 3, &cByteRead, NULL))
|
|
160
|
+
RAISE_WIN32_ERROR();
|
|
161
|
+
cDIBHeader.v5.bV5AlphaMask = 0x00000000;
|
|
162
|
+
break;
|
|
163
|
+
case BI_ALPHABITFIELDS:
|
|
164
|
+
if (!ReadFile(cFile, &cDIBHeader.v5.bV5RedMask, sizeof(DWORD) * 4, &cByteRead, NULL))
|
|
165
|
+
RAISE_WIN32_ERROR();
|
|
166
|
+
break;
|
|
167
|
+
default:
|
|
168
|
+
switch (cDIBHeader.v1.biBitCount) {
|
|
169
|
+
case 1:
|
|
170
|
+
case 4:
|
|
171
|
+
case 8:
|
|
172
|
+
cDIBHeader.v5.bV5RedMask = 0;
|
|
173
|
+
cDIBHeader.v5.bV5GreenMask = 0;
|
|
174
|
+
cDIBHeader.v5.bV5BlueMask = 0;
|
|
175
|
+
cDIBHeader.v5.bV5AlphaMask = 0;
|
|
176
|
+
case 16:
|
|
177
|
+
cDIBHeader.v5.bV5RedMask = 0x7C00;
|
|
178
|
+
cDIBHeader.v5.bV5GreenMask = 0x03E0;
|
|
179
|
+
cDIBHeader.v5.bV5BlueMask = 0x001F;
|
|
180
|
+
cDIBHeader.v5.bV5AlphaMask = 0x0000;
|
|
181
|
+
case 24:
|
|
182
|
+
cDIBHeader.v5.bV5RedMask = 0xFF0000;
|
|
183
|
+
cDIBHeader.v5.bV5GreenMask = 0x00FF00;
|
|
184
|
+
cDIBHeader.v5.bV5BlueMask = 0x0000FF;
|
|
185
|
+
cDIBHeader.v5.bV5AlphaMask = 0x000000;
|
|
186
|
+
break;
|
|
187
|
+
case 32:
|
|
188
|
+
cDIBHeader.v5.bV5RedMask = 0x00FF0000;
|
|
189
|
+
cDIBHeader.v5.bV5GreenMask = 0x0000FF00;
|
|
190
|
+
cDIBHeader.v5.bV5BlueMask = 0x000000FF;
|
|
191
|
+
cDIBHeader.v5.bV5AlphaMask = 0x00000000;
|
|
192
|
+
break;
|
|
193
|
+
default:
|
|
194
|
+
break;
|
|
195
|
+
}
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
198
|
+
cDIBHeader.v5.bV5CSType = LCS_WINDOWS_COLOR_SPACE;
|
|
199
|
+
cDIBHeader.v5.bV5Endpoints.ciexyzRed.ciexyzX = 0;
|
|
200
|
+
cDIBHeader.v5.bV5Endpoints.ciexyzRed.ciexyzY = 0;
|
|
201
|
+
cDIBHeader.v5.bV5Endpoints.ciexyzRed.ciexyzZ = 0;
|
|
202
|
+
cDIBHeader.v5.bV5Endpoints.ciexyzGreen.ciexyzX = 0;
|
|
203
|
+
cDIBHeader.v5.bV5Endpoints.ciexyzGreen.ciexyzY = 0;
|
|
204
|
+
cDIBHeader.v5.bV5Endpoints.ciexyzGreen.ciexyzZ = 0;
|
|
205
|
+
cDIBHeader.v5.bV5Endpoints.ciexyzBlue.ciexyzX = 0;
|
|
206
|
+
cDIBHeader.v5.bV5Endpoints.ciexyzBlue.ciexyzY = 0;
|
|
207
|
+
cDIBHeader.v5.bV5Endpoints.ciexyzBlue.ciexyzZ = 0;
|
|
208
|
+
cDIBHeader.v5.bV5GammaRed = 0;
|
|
209
|
+
cDIBHeader.v5.bV5GammaGreen = 0;
|
|
210
|
+
cDIBHeader.v5.bV5GammaBlue = 0;
|
|
211
|
+
case sizeof(BITMAPV4HEADER):
|
|
212
|
+
cDIBHeader.v5.bV5Intent = LCS_GM_ABS_COLORIMETRIC;
|
|
213
|
+
cDIBHeader.v5.bV5ProfileData = 0;
|
|
214
|
+
cDIBHeader.v5.bV5ProfileSize = 0;
|
|
215
|
+
cDIBHeader.v5.bV5Reserved = 0;
|
|
216
|
+
case sizeof(BITMAPV5HEADER):
|
|
217
|
+
break;
|
|
218
|
+
default:
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
cColorTable = NULL;
|
|
223
|
+
switch (cDIBHeader.v1.biBitCount) {
|
|
224
|
+
case 1:
|
|
225
|
+
case 4:
|
|
226
|
+
case 8: {
|
|
227
|
+
UINT cColorTableSize = cDIBHeader.v1.biClrUsed;
|
|
228
|
+
UINT cMaxColorTableSize = (UINT) (1 << cDIBHeader.v1.biBitCount);
|
|
229
|
+
if (cColorTableSize > cMaxColorTableSize)
|
|
230
|
+
rb_raise(rb_eArgError, "The bitmap file has been damaged. (clrUsed too large)");
|
|
231
|
+
if (cColorTableSize == 0)
|
|
232
|
+
cColorTableSize = cMaxColorTableSize;
|
|
233
|
+
cColorTable = ALLOC_N(RGBQUAD, cColorTableSize);
|
|
234
|
+
ReadFile(cFile, cColorTable, sizeof(RGBQUAD) * cColorTableSize, &cByteRead, NULL);
|
|
235
|
+
break;
|
|
236
|
+
}
|
|
237
|
+
case 16:
|
|
238
|
+
case 24:
|
|
239
|
+
case 32:
|
|
240
|
+
break;
|
|
241
|
+
default:
|
|
242
|
+
rb_raise(rb_eArgError, "The bitmap file is using unsupported color depth.");
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (!SetFilePointer(cFile, cFileHeader.bfOffBits, NULL, FILE_BEGIN))
|
|
246
|
+
RAISE_WIN32_ERROR();
|
|
247
|
+
|
|
248
|
+
image = ruby___image_new(cWidth, cHeight);
|
|
249
|
+
cData = GET_DATA_OBJECT(image);
|
|
250
|
+
|
|
251
|
+
cPixelArray = ALLOC_N(BYTE, cRowSize);
|
|
252
|
+
for (cT0 = 0; cT0 < cHeight; cT0++) {
|
|
253
|
+
UINT cPixelY = cDIBHeader.v1.biHeight >= 0 ? cT0 : cHeight + ~cT0;
|
|
254
|
+
if (!ReadFile(cFile, cPixelArray, cRowSize, &cByteRead, NULL))
|
|
255
|
+
RAISE_WIN32_ERROR();
|
|
256
|
+
switch (cDIBHeader.v1.biBitCount) {
|
|
257
|
+
case 1:
|
|
258
|
+
case 4:
|
|
259
|
+
case 8: {
|
|
260
|
+
INT cPixelPerByte = 8 / cDIBHeader.v1.biBitCount;
|
|
261
|
+
for (cT1 = 0; cT1 < cWidth; cT1++) {
|
|
262
|
+
INT cByteIndex = cT1 / cPixelPerByte;
|
|
263
|
+
INT cBitsIndex = (cPixelPerByte + ~(cT1 % cPixelPerByte)) * cDIBHeader.v1.biBitCount;
|
|
264
|
+
INT cBitsFilter = (1 << cDIBHeader.v1.biBitCount) - 1;
|
|
265
|
+
INT cColorIndex = (cPixelArray[cByteIndex] >> cBitsIndex) & cBitsFilter;
|
|
266
|
+
cData->pixelTable[cPixelY][cT1] = cColorTable[cColorIndex];
|
|
267
|
+
cData->pixelTable[cPixelY][cT1].rgbReserved = 0xFF;
|
|
268
|
+
}
|
|
269
|
+
break;
|
|
270
|
+
}
|
|
271
|
+
case 16:
|
|
272
|
+
case 24:
|
|
273
|
+
case 32: {
|
|
274
|
+
BYTE *cPixel;
|
|
275
|
+
INT cBytePrePixel = cDIBHeader.v1.biBitCount / 8;
|
|
276
|
+
LONG cValue;
|
|
277
|
+
LONG cMask;
|
|
278
|
+
LONG cBuffer;
|
|
279
|
+
LONG cBitIndex;
|
|
280
|
+
LONG cBit;
|
|
281
|
+
|
|
282
|
+
for (cT1 = 0; cT1 < cWidth; cT1++) {
|
|
283
|
+
|
|
284
|
+
cPixel = (BYTE *) &cData->pixelTable[cPixelY][cT1];
|
|
285
|
+
|
|
286
|
+
cValue = 0;
|
|
287
|
+
for (cT2 = 0; cT2 < cBytePrePixel; cT2++)
|
|
288
|
+
cValue += ((LONG) cPixelArray[cT1 * cBytePrePixel + cT2]) << (cT2 * 8);
|
|
289
|
+
|
|
290
|
+
for (cT2 = 0; cT2 < 4; cT2++) {
|
|
291
|
+
switch (cT2) {
|
|
292
|
+
case 0:
|
|
293
|
+
cMask = cDIBHeader.v5.bV5BlueMask;
|
|
294
|
+
break;
|
|
295
|
+
case 1:
|
|
296
|
+
cMask = cDIBHeader.v5.bV5GreenMask;
|
|
297
|
+
break;
|
|
298
|
+
case 2:
|
|
299
|
+
cMask = cDIBHeader.v5.bV5RedMask;
|
|
300
|
+
break;
|
|
301
|
+
case 3:
|
|
302
|
+
cMask = cDIBHeader.v5.bV5AlphaMask;
|
|
303
|
+
break;
|
|
304
|
+
default:
|
|
305
|
+
cMask = 0;
|
|
306
|
+
break;
|
|
307
|
+
}
|
|
308
|
+
if (cMask) {
|
|
309
|
+
cBuffer = 0;
|
|
310
|
+
cBitIndex = 0;
|
|
311
|
+
for (cT3 = 0; cT3 < cDIBHeader.v1.biBitCount; cT3++) {
|
|
312
|
+
cBit = 1 << cT3;
|
|
313
|
+
if (cMask & cBit)
|
|
314
|
+
cBuffer += (cValue & cBit) >> (cT3 - cBitIndex++);
|
|
315
|
+
}
|
|
316
|
+
cPixel[cT2] = (BYTE) (cBuffer * 0xFF / ((1 << cBitIndex) - 1));
|
|
317
|
+
} else
|
|
318
|
+
cPixel[cT2] = 0xFF;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
break;
|
|
322
|
+
}
|
|
323
|
+
default:
|
|
324
|
+
break;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
xfree(cPixelArray);
|
|
329
|
+
if (cColorTable)
|
|
330
|
+
xfree(cColorTable);
|
|
331
|
+
|
|
332
|
+
return image;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
static VOID callback_image_free(SID_IMAGE_DATA *cData) {
|
|
336
|
+
UINT cT;
|
|
337
|
+
for (cT = 0; cT < cData->height; cT++)
|
|
338
|
+
xfree(cData->pixelTable[cT]);
|
|
339
|
+
xfree(cData->pixelTable);
|
|
340
|
+
xfree(cData);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
static VALUE ruby__alloc(VALUE self) {
|
|
344
|
+
return NEW_DATA_OBJECT(specialInputDevice_image, SID_IMAGE_DATA, NULL, callback_image_free);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/*
|
|
348
|
+
* @!scope class
|
|
349
|
+
* @overload new(width, height)
|
|
350
|
+
* @param [Integer] width the width of table
|
|
351
|
+
* @param [Integer] height the height of table
|
|
352
|
+
*/
|
|
353
|
+
static VALUE ruby_initialize(VALUE self, VALUE width, VALUE height) {
|
|
354
|
+
UINT cWidth = NUM2UINT(width);
|
|
355
|
+
UINT cHeight = NUM2UINT(height);
|
|
356
|
+
SID_IMAGE_DATA *cData = GET_SELF_DATA_OBJECT();
|
|
357
|
+
INT cT0;
|
|
358
|
+
INT cT1;
|
|
359
|
+
cData->height = cHeight;
|
|
360
|
+
cData->pixelTable = ALLOC_N(LPRGBQUAD, cHeight);
|
|
361
|
+
for (cT0 = 0; cT0 < cHeight; cT0++) {
|
|
362
|
+
cData->pixelTable[cT0] = ALLOC_N(RGBQUAD, cWidth);
|
|
363
|
+
for (cT1 = 0; cT1 < cWidth; cT1++) {
|
|
364
|
+
cData->pixelTable[cT0][cT1].rgbBlue = 0;
|
|
365
|
+
cData->pixelTable[cT0][cT1].rgbGreen = 0;
|
|
366
|
+
cData->pixelTable[cT0][cT1].rgbRed = 0;
|
|
367
|
+
cData->pixelTable[cT0][cT1].rgbReserved = 0;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
rb_iv_set(self, "@width", width);
|
|
371
|
+
rb_iv_set(self, "@height", height);
|
|
372
|
+
return Qnil;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/*
|
|
376
|
+
* Save this image to a file.
|
|
377
|
+
* @overload save(path)
|
|
378
|
+
* @param [String] path a path to target file
|
|
379
|
+
* @return [SpecialInputDevice::Image] self
|
|
380
|
+
*/
|
|
381
|
+
static VALUE ruby_save(VALUE self, VALUE path) {
|
|
382
|
+
VALUE width = rb_iv_get(self, "@width");
|
|
383
|
+
UINT cWidth = NUM2UINT(width);
|
|
384
|
+
LPCTSTR cPath = RUBY_VALUE_TO_LPCTSTR(path);
|
|
385
|
+
SID_IMAGE_DATA *cData = GET_SELF_DATA_OBJECT();
|
|
386
|
+
size_t cHeaderSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPV5HEADER);
|
|
387
|
+
INT cDataSize = sizeof(RGBQUAD) * cWidth * cData->height;
|
|
388
|
+
FILE *cFile;
|
|
389
|
+
BITMAPFILEHEADER cFileHeader;
|
|
390
|
+
BITMAPV5HEADER cDIBHeader;
|
|
391
|
+
DWORD cByteWritten;
|
|
392
|
+
INT cT;
|
|
393
|
+
cFile = CreateFile(cPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
|
|
394
|
+
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
|
|
395
|
+
if (cFile == INVALID_HANDLE_VALUE)
|
|
396
|
+
RAISE_WIN32_ERROR();
|
|
397
|
+
cFileHeader.bfType = 0x4D42;
|
|
398
|
+
cFileHeader.bfSize = cHeaderSize + cDataSize;
|
|
399
|
+
cFileHeader.bfReserved1 = 0;
|
|
400
|
+
cFileHeader.bfReserved2 = 0;
|
|
401
|
+
cFileHeader.bfOffBits = cHeaderSize;
|
|
402
|
+
cDIBHeader.bV5Size = sizeof(BITMAPV5HEADER);
|
|
403
|
+
cDIBHeader.bV5Width = (LONG) cWidth;
|
|
404
|
+
cDIBHeader.bV5Height = (LONG) cData->height;
|
|
405
|
+
cDIBHeader.bV5Planes = 1;
|
|
406
|
+
cDIBHeader.bV5BitCount = 8 * sizeof(RGBQUAD);
|
|
407
|
+
cDIBHeader.bV5Compression = BI_BITFIELDS;
|
|
408
|
+
cDIBHeader.bV5SizeImage = (DWORD) cDataSize;
|
|
409
|
+
cDIBHeader.bV5XPelsPerMeter = 0;
|
|
410
|
+
cDIBHeader.bV5YPelsPerMeter = 0;
|
|
411
|
+
cDIBHeader.bV5ClrUsed = 0;
|
|
412
|
+
cDIBHeader.bV5ClrImportant = 0;
|
|
413
|
+
cDIBHeader.bV5RedMask = 0x00FF0000;
|
|
414
|
+
cDIBHeader.bV5GreenMask = 0x0000FF00;
|
|
415
|
+
cDIBHeader.bV5BlueMask = 0x000000FF;
|
|
416
|
+
cDIBHeader.bV5AlphaMask = 0xFF000000;
|
|
417
|
+
cDIBHeader.bV5CSType = LCS_WINDOWS_COLOR_SPACE;
|
|
418
|
+
cDIBHeader.bV5Endpoints.ciexyzRed.ciexyzX = 0;
|
|
419
|
+
cDIBHeader.bV5Endpoints.ciexyzRed.ciexyzY = 0;
|
|
420
|
+
cDIBHeader.bV5Endpoints.ciexyzRed.ciexyzZ = 0;
|
|
421
|
+
cDIBHeader.bV5Endpoints.ciexyzGreen.ciexyzX = 0;
|
|
422
|
+
cDIBHeader.bV5Endpoints.ciexyzGreen.ciexyzY = 0;
|
|
423
|
+
cDIBHeader.bV5Endpoints.ciexyzGreen.ciexyzZ = 0;
|
|
424
|
+
cDIBHeader.bV5Endpoints.ciexyzBlue.ciexyzX = 0;
|
|
425
|
+
cDIBHeader.bV5Endpoints.ciexyzBlue.ciexyzY = 0;
|
|
426
|
+
cDIBHeader.bV5Endpoints.ciexyzBlue.ciexyzZ = 0;
|
|
427
|
+
cDIBHeader.bV5GammaRed = 0;
|
|
428
|
+
cDIBHeader.bV5GammaGreen = 0;
|
|
429
|
+
cDIBHeader.bV5GammaBlue = 0;
|
|
430
|
+
cDIBHeader.bV5Intent = LCS_GM_ABS_COLORIMETRIC;
|
|
431
|
+
cDIBHeader.bV5ProfileData = 0;
|
|
432
|
+
cDIBHeader.bV5ProfileSize = 0;
|
|
433
|
+
cDIBHeader.bV5Reserved = 0;
|
|
434
|
+
WriteFile(cFile, &cFileHeader, sizeof(cFileHeader), &cByteWritten, NULL);
|
|
435
|
+
WriteFile(cFile, &cDIBHeader, sizeof(cDIBHeader), &cByteWritten, NULL);
|
|
436
|
+
for (cT = 0; cT < cData->height; cT++)
|
|
437
|
+
WriteFile(cFile, cData->pixelTable[cT], (DWORD) (sizeof(RGBQUAD) * cWidth), &cByteWritten, NULL);
|
|
438
|
+
return self;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/*
|
|
442
|
+
* @overload [](x, y)
|
|
443
|
+
* @param [Integer] x the x coordinate, can be negative
|
|
444
|
+
* @param [Integer] y the y coordinate, can be negative
|
|
445
|
+
* @return [SpecialInputDevice::Color] the color of pixel at the specific coordinate
|
|
446
|
+
*/
|
|
447
|
+
static VALUE ruby_OS_CS(VALUE self, VALUE x, VALUE y) {
|
|
448
|
+
INT cWidth = NUM2INT(rb_iv_get(self, "@width"));
|
|
449
|
+
INT cX = NUM2INT(x);
|
|
450
|
+
INT cY = NUM2INT(y);
|
|
451
|
+
SID_IMAGE_DATA *cData = GET_SELF_DATA_OBJECT();
|
|
452
|
+
if (cX < -cWidth || cX >= cWidth)
|
|
453
|
+
rb_raise(rb_eRangeError, "The image only has %d columns. x = %d is out of range.", cWidth, cX);
|
|
454
|
+
if (cX < 0)
|
|
455
|
+
cX += cWidth;
|
|
456
|
+
if (cY < (INT) -cData->height || cY >= cData->height)
|
|
457
|
+
rb_raise(rb_eRangeError, "The image only has %d rows. y = %d is out of range.", cData->height, cY);
|
|
458
|
+
if (cY < 0)
|
|
459
|
+
cY += cData->height;
|
|
460
|
+
return ruby___color_new_from_rgb_quad(&PixelAt(cX, cY));
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/*
|
|
464
|
+
* @overload []=(x, y, value)
|
|
465
|
+
* @param [Integer] x the x coordinate, can be negative
|
|
466
|
+
* @param [Integer] y the y coordinate, can be negative
|
|
467
|
+
* @param [SpecialInputDevice::Color] value the new color
|
|
468
|
+
* @return [SpecialInputDevice::Color] the new color
|
|
469
|
+
*/
|
|
470
|
+
static VALUE ruby_OS_CS_EQ(VALUE self, VALUE x, VALUE y, VALUE value) {
|
|
471
|
+
INT cWidth = NUM2INT(rb_iv_get(self, "@width"));
|
|
472
|
+
INT cX = NUM2INT(x);
|
|
473
|
+
INT cY = NUM2INT(y);
|
|
474
|
+
RGBQUAD cVALUE = ruby___color_to_rgb_quad(value);
|
|
475
|
+
SID_IMAGE_DATA *cData = GET_SELF_DATA_OBJECT();
|
|
476
|
+
if (cX < -cWidth || cX >= cWidth)
|
|
477
|
+
rb_raise(rb_eRangeError, "The image only has %d columns. x = %d is out of range.", cWidth, cX);
|
|
478
|
+
if (cX < 0)
|
|
479
|
+
cX += cWidth;
|
|
480
|
+
if (cY < (INT) -cData->height || cY >= cData->height)
|
|
481
|
+
rb_raise(rb_eRangeError, "The image only has %d rows. y = %d is out of range.", cData->height, cY);
|
|
482
|
+
if (cY < 0)
|
|
483
|
+
cY += cData->height;
|
|
484
|
+
PixelAt(cX, cY) = cVALUE;
|
|
485
|
+
return value;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
/*
|
|
489
|
+
* @overload try_get(x, y)
|
|
490
|
+
* @param [Integer] x the x coordinate, can be negative
|
|
491
|
+
* @param [Integer] y the y coordinate, can be negative
|
|
492
|
+
* @return [NilClass, SpecialInputDevice::Color] the color of pixel at the specific coordinate or nil if out of range
|
|
493
|
+
*/
|
|
494
|
+
static VALUE ruby_try_get(VALUE self, VALUE x, VALUE y) {
|
|
495
|
+
INT cWidth = NUM2INT(rb_iv_get(self, "@width"));
|
|
496
|
+
INT cX = NUM2INT(x);
|
|
497
|
+
INT cY = NUM2INT(y);
|
|
498
|
+
SID_IMAGE_DATA *cData = GET_SELF_DATA_OBJECT();
|
|
499
|
+
if (cX < -cWidth || cX >= cWidth || cY < (INT) -cData->height || cY >= cData->height)
|
|
500
|
+
return Qnil;
|
|
501
|
+
if (cX < 0)
|
|
502
|
+
cX += cWidth;
|
|
503
|
+
if (cY < 0)
|
|
504
|
+
cY += cData->height;
|
|
505
|
+
return ruby___color_new_from_rgb_quad(&PixelAt(cX, cY));
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
/*
|
|
509
|
+
* @overload try_set(x, y, value)
|
|
510
|
+
* @param [Integer] x the x coordinate, can be negative
|
|
511
|
+
* @param [Integer] y the y coordinate, can be negative
|
|
512
|
+
* @param [SpecialInputDevice::Color] value the new color
|
|
513
|
+
* @return [SpecialInputDevice::Color] the new color
|
|
514
|
+
*/
|
|
515
|
+
static VALUE ruby_try_set(VALUE self, VALUE x, VALUE y, VALUE value) {
|
|
516
|
+
INT cWidth = NUM2INT(rb_iv_get(self, "@width"));
|
|
517
|
+
INT cX = NUM2INT(x);
|
|
518
|
+
INT cY = NUM2INT(y);
|
|
519
|
+
RGBQUAD cVALUE = ruby___color_to_rgb_quad(value);
|
|
520
|
+
SID_IMAGE_DATA *cData = GET_SELF_DATA_OBJECT();
|
|
521
|
+
if (cX >= -cWidth && cX < cWidth && cY >= (INT) -cData->height && cY < cData->height) {
|
|
522
|
+
if (cX < 0)
|
|
523
|
+
cX += cWidth;
|
|
524
|
+
if (cY < 0)
|
|
525
|
+
cY += cData->height;
|
|
526
|
+
PixelAt(cX, cY) = cVALUE;
|
|
527
|
+
}
|
|
528
|
+
return value;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
/*
|
|
532
|
+
* @overload each(&block)
|
|
533
|
+
* @param [Proc] block the action
|
|
534
|
+
* @yield [value] the action
|
|
535
|
+
* @yieldparam [SpecialInputDevice::Color] value the value
|
|
536
|
+
* @yieldreturn [Object] value will be ignored
|
|
537
|
+
* @return [Enumerator, SpecialInputDevice::Image] a Enumerator if no block gavin, self otherwise.
|
|
538
|
+
*/
|
|
539
|
+
static VALUE ruby_each(VARIABLE_ARGUMENTS_C) {
|
|
540
|
+
VALUE block;
|
|
541
|
+
SID_IMAGE_DATA *cData = GET_SELF_DATA_OBJECT();
|
|
542
|
+
UINT cWidth = NUM2UINT(rb_iv_get(self, "@width"));
|
|
543
|
+
SCAN_ARGUMENTS("&", &block);
|
|
544
|
+
if (RTEST(block)) {
|
|
545
|
+
UINT cT0;
|
|
546
|
+
UINT cT1;
|
|
547
|
+
for (cT0 = 0; cT0 < cData->height; cT0++) {
|
|
548
|
+
for (cT1 = 0; cT1 < cWidth; cT1++) {
|
|
549
|
+
RGBQUAD *cColor = &PixelAt(cT1, cT0);
|
|
550
|
+
VALUE color = ruby___color_new_from_rgb_quad(cColor);
|
|
551
|
+
rb_yield(color);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
return self;
|
|
555
|
+
} else {
|
|
556
|
+
VALUE newEnumeratorArguments[1];
|
|
557
|
+
newEnumeratorArguments[0] = self;
|
|
558
|
+
return rb_class_new_instance(1, newEnumeratorArguments, rb_cEnumerator);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/*
|
|
563
|
+
* @overload each_row(&block)
|
|
564
|
+
* @param [Proc] block the action
|
|
565
|
+
* @yield [row] the action
|
|
566
|
+
* @yieldparam [Array<SpecialInputDevice::Color>] row the row
|
|
567
|
+
* @yieldreturn [Object] value will be ignored
|
|
568
|
+
* @return [Enumerator, SpecialInputDevice::Image] a Enumerator if no block gavin, self otherwise.
|
|
569
|
+
*/
|
|
570
|
+
static VALUE ruby_each_row(VARIABLE_ARGUMENTS_C) {
|
|
571
|
+
VALUE block;
|
|
572
|
+
SID_IMAGE_DATA *cData = GET_SELF_DATA_OBJECT();
|
|
573
|
+
LONG cWidth = NUM2LONG(rb_iv_get(self, "@width"));
|
|
574
|
+
SCAN_ARGUMENTS("&", &block);
|
|
575
|
+
if (RTEST(block)) {
|
|
576
|
+
UINT cT0;
|
|
577
|
+
UINT cT1;
|
|
578
|
+
VALUE *cRow = ALLOC_N(VALUE, cWidth);
|
|
579
|
+
for (cT0 = 0; cT0 < cData->height; cT0++) {
|
|
580
|
+
for (cT1 = 0; cT1 < cWidth; cT1++) {
|
|
581
|
+
cRow[cT1] = ruby___color_new_from_rgb_quad(&PixelAt(cT1, cT0));
|
|
582
|
+
rb_yield(rb_ary_new_from_values(cWidth, cRow));
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
return self;
|
|
586
|
+
} else {
|
|
587
|
+
VALUE newEnumeratorArguments[2];
|
|
588
|
+
newEnumeratorArguments[0] = self;
|
|
589
|
+
newEnumeratorArguments[1] = NEW_SYMBOL("each_row");
|
|
590
|
+
return rb_class_new_instance(2, newEnumeratorArguments, rb_cEnumerator);
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
/*
|
|
595
|
+
* @overload each_column(&block)
|
|
596
|
+
* @param [Proc] block the action
|
|
597
|
+
* @yield [row] the action
|
|
598
|
+
* @yieldparam [Array<SpecialInputDevice::Color>] column the column
|
|
599
|
+
* @yieldreturn [Object] value will be ignored
|
|
600
|
+
* @return [Enumerator, SpecialInputDevice::Image] a Enumerator if no block gavin, self otherwise.
|
|
601
|
+
*/
|
|
602
|
+
static VALUE ruby_each_column(VARIABLE_ARGUMENTS_C) {
|
|
603
|
+
VALUE block;
|
|
604
|
+
SID_IMAGE_DATA *cData = GET_SELF_DATA_OBJECT();
|
|
605
|
+
LONG cWidth = NUM2LONG(rb_iv_get(self, "@width"));
|
|
606
|
+
SCAN_ARGUMENTS("&", &block);
|
|
607
|
+
if (RTEST(block)) {
|
|
608
|
+
UINT cT0;
|
|
609
|
+
UINT cT1;
|
|
610
|
+
VALUE *cColumn = ALLOC_N(VALUE, cData->height);
|
|
611
|
+
for (cT0 = 0; cT0 < cWidth; cT0++) {
|
|
612
|
+
for (cT1 = 0; cT1 < cData->height; cT1++) {
|
|
613
|
+
cColumn[cT1] = ruby___color_new_from_rgb_quad(&PixelAt(cT0, cT1));
|
|
614
|
+
rb_yield(rb_ary_new_from_values((LONG) cData->height, cColumn));
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
return self;
|
|
618
|
+
} else {
|
|
619
|
+
VALUE newEnumeratorArguments[2];
|
|
620
|
+
newEnumeratorArguments[0] = self;
|
|
621
|
+
newEnumeratorArguments[1] = NEW_SYMBOL("each_column");
|
|
622
|
+
return rb_class_new_instance(2, newEnumeratorArguments, rb_cEnumerator);
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
/*
|
|
627
|
+
* @overload each_in_row(y, &block)
|
|
628
|
+
* @param [Integer] y specific which row, can be negative
|
|
629
|
+
* @param [Proc] block the action
|
|
630
|
+
* @yield [pixel] the action
|
|
631
|
+
* @yieldparam [SpecialInputDevice::Color] pixel the pixel
|
|
632
|
+
* @yieldreturn [Object] value will be ignored
|
|
633
|
+
* @return [Enumerator, SpecialInputDevice::Image] a Enumerator if no block gavin, self otherwise.
|
|
634
|
+
*/
|
|
635
|
+
static VALUE ruby_each_in_row(VARIABLE_ARGUMENTS_C) {
|
|
636
|
+
VALUE y;
|
|
637
|
+
VALUE block;
|
|
638
|
+
SID_IMAGE_DATA *cData = GET_SELF_DATA_OBJECT();
|
|
639
|
+
INT cY;
|
|
640
|
+
LONG cWidth = NUM2LONG(rb_iv_get(self, "@width"));
|
|
641
|
+
SCAN_ARGUMENTS("1&", &y, &block);
|
|
642
|
+
cY = NUM2INT(y);
|
|
643
|
+
if (cY < (INT) -cData->height || cY >= cData->height)
|
|
644
|
+
rb_raise(rb_eRangeError, "The image only has %d rows. y = %d is out of range.", cData->height, cY);
|
|
645
|
+
if (cY < 0)
|
|
646
|
+
cY += cWidth;
|
|
647
|
+
if (RTEST(block)) {
|
|
648
|
+
UINT cT;
|
|
649
|
+
VALUE cPixel;
|
|
650
|
+
for (cT = 0; cT < cWidth; cT++) {
|
|
651
|
+
cPixel = ruby___color_new_from_rgb_quad(&PixelAt(cT, cY));
|
|
652
|
+
rb_yield(cPixel);
|
|
653
|
+
}
|
|
654
|
+
return self;
|
|
655
|
+
} else {
|
|
656
|
+
VALUE newEnumeratorArguments[3];
|
|
657
|
+
newEnumeratorArguments[0] = self;
|
|
658
|
+
newEnumeratorArguments[1] = NEW_SYMBOL("each_in_row");
|
|
659
|
+
newEnumeratorArguments[2] = y;
|
|
660
|
+
return rb_class_new_instance(3, newEnumeratorArguments, rb_cEnumerator);
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
/*
|
|
665
|
+
* @overload each_in_column(x, &block)
|
|
666
|
+
* @param [Integer] x specific which column, can be negative
|
|
667
|
+
* @param [Proc] block the action
|
|
668
|
+
* @yield [pixel] the action
|
|
669
|
+
* @yieldparam [SpecialInputDevice::Color] pixel the pixel
|
|
670
|
+
* @yieldreturn [Object] value will be ignored
|
|
671
|
+
* @return [Enumerator, SpecialInputDevice::Image] a Enumerator if no block gavin, self otherwise.
|
|
672
|
+
*/
|
|
673
|
+
static VALUE ruby_each_in_column(VARIABLE_ARGUMENTS_C) {
|
|
674
|
+
VALUE x;
|
|
675
|
+
VALUE block;
|
|
676
|
+
SID_IMAGE_DATA *cData = GET_SELF_DATA_OBJECT();
|
|
677
|
+
INT cX;
|
|
678
|
+
LONG cWidth = NUM2LONG(rb_iv_get(self, "@width"));
|
|
679
|
+
SCAN_ARGUMENTS("1&", &x, &block);
|
|
680
|
+
cX = NUM2INT(x);
|
|
681
|
+
if (cX < -cWidth || cX >= cWidth)
|
|
682
|
+
rb_raise(rb_eRangeError, "The image only has %d columns. x = %d is out of range.", (INT) cWidth, cX);
|
|
683
|
+
if (cX < 0)
|
|
684
|
+
cX += cWidth;
|
|
685
|
+
if (RTEST(block)) {
|
|
686
|
+
UINT cT;
|
|
687
|
+
VALUE cPixel;
|
|
688
|
+
for (cT = 0; cT < cData->height; cT++) {
|
|
689
|
+
cPixel = ruby___color_new_from_rgb_quad(&PixelAt(cX, cT));
|
|
690
|
+
rb_yield(cPixel);
|
|
691
|
+
}
|
|
692
|
+
return self;
|
|
693
|
+
} else {
|
|
694
|
+
VALUE newEnumeratorArguments[3];
|
|
695
|
+
newEnumeratorArguments[0] = self;
|
|
696
|
+
newEnumeratorArguments[1] = NEW_SYMBOL("each_column");
|
|
697
|
+
newEnumeratorArguments[2] = x;
|
|
698
|
+
return rb_class_new_instance(3, newEnumeratorArguments, rb_cEnumerator);
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
VOID Init_image() {
|
|
703
|
+
#ifdef YARD
|
|
704
|
+
specialInputDevice = rb_define_module("SpecialInputDevice");
|
|
705
|
+
specialInputDevice_image = rb_define_class_under(specialInputDevice, "Image", rb_cData);
|
|
706
|
+
#endif
|
|
707
|
+
rb_define_singleton_method(specialInputDevice_image, "load", ruby__load, 1);
|
|
708
|
+
rb_define_alloc_func(specialInputDevice_image, (rb_alloc_func_t) ruby__alloc);
|
|
709
|
+
/*
|
|
710
|
+
* @return [Integer] the width of the bitmap
|
|
711
|
+
*/
|
|
712
|
+
rb_define_attr(specialInputDevice_image, "width", TRUE, FALSE);
|
|
713
|
+
/*
|
|
714
|
+
* @return [Integer] the height of the bitmap
|
|
715
|
+
*/
|
|
716
|
+
rb_define_attr(specialInputDevice_image, "height", TRUE, FALSE);
|
|
717
|
+
rb_define_method(specialInputDevice_image, "initialize", ruby_initialize, 2);
|
|
718
|
+
rb_define_method(specialInputDevice_image, "save", ruby_save, 1);
|
|
719
|
+
rb_define_method(specialInputDevice_image, "[]", ruby_OS_CS, 2);
|
|
720
|
+
rb_define_method(specialInputDevice_image, "[]=", ruby_OS_CS_EQ, 3);
|
|
721
|
+
rb_define_method(specialInputDevice_image, "try_get", ruby_try_get, 2);
|
|
722
|
+
rb_define_method(specialInputDevice_image, "try_set", ruby_try_set, 3);
|
|
723
|
+
rb_define_method(specialInputDevice_image, "each", ruby_each, -1);
|
|
724
|
+
rb_define_method(specialInputDevice_image, "each_row", ruby_each_row, -1);
|
|
725
|
+
rb_define_method(specialInputDevice_image, "each_column", ruby_each_column, -1);
|
|
726
|
+
rb_define_method(specialInputDevice_image, "each_in_row", ruby_each_in_row, -1);
|
|
727
|
+
rb_define_method(specialInputDevice_image, "each_in_column", ruby_each_in_column, -1);
|
|
728
|
+
}
|