node-native-win-utils 1.3.2 → 1.3.3
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.
- package/LICENSE +20 -20
- package/README.md +758 -350
- package/binding.gyp +46 -46
- package/dist/index.d.ts +178 -173
- package/dist/index.js +163 -143
- package/dist/keyCodes.d.ts +101 -2
- package/dist/keyCodes.js +204 -102
- package/include/opencv2/opencv_modules.hpp +17 -17
- package/package.json +6 -4
- package/prebuilds/win32-x64/{node.napi.node → node-native-win-utils.node} +0 -0
- package/src/cpp/capturewindow.cpp +173 -173
- package/src/cpp/getWindowData.cpp +45 -45
- package/src/cpp/helpers.cpp +14 -14
- package/src/cpp/helpers.h +8 -8
- package/src/cpp/keyboard.cpp +238 -204
- package/src/cpp/main.cpp +30 -29
- package/src/cpp/mouse.cpp +175 -175
- package/src/cpp/opencv.cpp +425 -425
package/src/cpp/opencv.cpp
CHANGED
|
@@ -1,426 +1,426 @@
|
|
|
1
|
-
#include <iostream>
|
|
2
|
-
#include <opencv2/core.hpp>
|
|
3
|
-
#include <opencv2/imgcodecs.hpp>
|
|
4
|
-
#include <opencv2/imgproc.hpp>
|
|
5
|
-
#include <napi.h>
|
|
6
|
-
|
|
7
|
-
Napi::Value Imread(const Napi::CallbackInfo &info)
|
|
8
|
-
{
|
|
9
|
-
Napi::Env env = info.Env();
|
|
10
|
-
|
|
11
|
-
if (info.Length() < 1 || !info[0].IsString())
|
|
12
|
-
{
|
|
13
|
-
Napi::TypeError::New(env, "String expected for image file path").ThrowAsJavaScriptException();
|
|
14
|
-
return env.Null();
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
std::string filename = info[0].ToString().Utf8Value();
|
|
18
|
-
|
|
19
|
-
int flags = cv::IMREAD_COLOR;
|
|
20
|
-
if (info.Length() > 1 && info[1].IsNumber())
|
|
21
|
-
{
|
|
22
|
-
flags = info[1].ToNumber().Int32Value();
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
cv::Mat image = cv::imread(filename, flags);
|
|
26
|
-
|
|
27
|
-
if (image.empty())
|
|
28
|
-
{
|
|
29
|
-
Napi::TypeError::New(env, "Failed to load image").ThrowAsJavaScriptException();
|
|
30
|
-
return env.Null();
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// Create a new Uint8Array with the correct size
|
|
34
|
-
|
|
35
|
-
size_t totalBytes = image.total() * image.elemSize();
|
|
36
|
-
Napi::ArrayBuffer arrayBuffer = Napi::ArrayBuffer::New(env, totalBytes);
|
|
37
|
-
Napi::Uint8Array uint8Array = Napi::Uint8Array::New(env, totalBytes, arrayBuffer, 0);
|
|
38
|
-
|
|
39
|
-
// Copy the image data to the Uint8Array
|
|
40
|
-
memcpy(uint8Array.Data(), image.data, totalBytes);
|
|
41
|
-
// std::cout << totalBytes << std::endl;
|
|
42
|
-
// std::cout << uint8Array.ByteLength() << std::endl;
|
|
43
|
-
// Create a JavaScript object with 'width', 'height', and 'data' properties
|
|
44
|
-
Napi::Object result = Napi::Object::New(env);
|
|
45
|
-
|
|
46
|
-
result.Set("width", image.cols);
|
|
47
|
-
result.Set("height", image.rows);
|
|
48
|
-
result.Set("data", uint8Array);
|
|
49
|
-
|
|
50
|
-
return result;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
Napi::Value Imwrite(const Napi::CallbackInfo &info)
|
|
54
|
-
{
|
|
55
|
-
Napi::Env env = info.Env();
|
|
56
|
-
|
|
57
|
-
if (info.Length() < 1 || !info[0].IsObject())
|
|
58
|
-
{
|
|
59
|
-
Napi::TypeError::New(env, "Invalid arguments. Expected: object").ThrowAsJavaScriptException();
|
|
60
|
-
return env.Null();
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
Napi::Object imageData = info[0].As<Napi::Object>();
|
|
64
|
-
|
|
65
|
-
if (!imageData.Has("width") || !imageData.Has("height") || !imageData.Has("data"))
|
|
66
|
-
{
|
|
67
|
-
Napi::TypeError::New(env, "Invalid image data object. Expected properties: 'width', 'height', 'data'").ThrowAsJavaScriptException();
|
|
68
|
-
return env.Null();
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
int width = imageData.Get("width").ToNumber().Int32Value();
|
|
72
|
-
int height = imageData.Get("height").ToNumber().Int32Value();
|
|
73
|
-
|
|
74
|
-
cv::Mat image;
|
|
75
|
-
if (imageData.Get("data").IsTypedArray())
|
|
76
|
-
{
|
|
77
|
-
Napi::TypedArray typedArray = imageData.Get("data").As<Napi::TypedArray>();
|
|
78
|
-
int elementSize = typedArray.ByteLength() / (width * height);
|
|
79
|
-
// std::cout << typedArray.ByteLength() << std::endl;
|
|
80
|
-
// std::cout << elementSize << std::endl;
|
|
81
|
-
int type = elementSize == 1 ? CV_8UC1 : CV_8UC3;
|
|
82
|
-
|
|
83
|
-
image = cv::Mat(height, width, type);
|
|
84
|
-
memcpy(image.data, typedArray.As<Napi::Uint8Array>().Data(), typedArray.ByteLength());
|
|
85
|
-
}
|
|
86
|
-
else
|
|
87
|
-
{
|
|
88
|
-
Napi::TypeError::New(env, "'data' property must be a TypedArray").ThrowAsJavaScriptException();
|
|
89
|
-
return env.Null();
|
|
90
|
-
}
|
|
91
|
-
std::vector<uchar> buffer;
|
|
92
|
-
cv::imencode(".png", image, buffer);
|
|
93
|
-
|
|
94
|
-
Napi::Buffer<uchar> resultBuffer = Napi::Buffer<uchar>::Copy(env, buffer.data(), buffer.size());
|
|
95
|
-
return resultBuffer;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
Napi::Value MatchTemplate(const Napi::CallbackInfo &info)
|
|
99
|
-
{
|
|
100
|
-
Napi::Env env = info.Env();
|
|
101
|
-
|
|
102
|
-
if (info.Length() < 2 || !info[0].IsObject() || !info[1].IsObject())
|
|
103
|
-
{
|
|
104
|
-
Napi::TypeError::New(env, "Invalid arguments. Expected: (object, object[, object])").ThrowAsJavaScriptException();
|
|
105
|
-
return env.Null();
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
Napi::Object srcObj = info[0].As<Napi::Object>();
|
|
109
|
-
Napi::Object templObj = info[1].As<Napi::Object>();
|
|
110
|
-
int method = cv::TM_CCOEFF_NORMED;
|
|
111
|
-
if (info.Length() > 2 && !info[2].IsNumber())
|
|
112
|
-
{
|
|
113
|
-
method = info[2].ToNumber().Int32Value();
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
if (!srcObj.Has("data") || !templObj.Has("data"))
|
|
117
|
-
{
|
|
118
|
-
Napi::TypeError::New(env, "Invalid image data objects. Expected properties: 'data'").ThrowAsJavaScriptException();
|
|
119
|
-
return env.Null();
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
if (!srcObj.Has("width") || !srcObj.Has("height") || !templObj.Has("width") || !templObj.Has("height"))
|
|
123
|
-
{
|
|
124
|
-
Napi::TypeError::New(env, "Invalid image data objects. Expected properties: 'width', 'height'").ThrowAsJavaScriptException();
|
|
125
|
-
return env.Null();
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
if (!srcObj.Get("data").IsTypedArray() || !templObj.Get("data").IsTypedArray())
|
|
129
|
-
{
|
|
130
|
-
Napi::TypeError::New(env, "TypedArray expected for 'data' properties").ThrowAsJavaScriptException();
|
|
131
|
-
return env.Null();
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
int srcWidth = srcObj.Get("width").ToNumber().Int32Value();
|
|
135
|
-
int srcHeight = srcObj.Get("height").ToNumber().Int32Value();
|
|
136
|
-
int templWidth = templObj.Get("width").ToNumber().Int32Value();
|
|
137
|
-
int templHeight = templObj.Get("height").ToNumber().Int32Value();
|
|
138
|
-
|
|
139
|
-
Napi::ArrayBuffer srcBufferData = srcObj.Get("data").As<Napi::TypedArray>().ArrayBuffer();
|
|
140
|
-
Napi::ArrayBuffer templBufferData = templObj.Get("data").As<Napi::TypedArray>().ArrayBuffer();
|
|
141
|
-
|
|
142
|
-
cv::Mat src(srcHeight, srcWidth, CV_8UC1, srcBufferData.Data());
|
|
143
|
-
cv::Mat templ(templHeight, templWidth, CV_8UC1, templBufferData.Data());
|
|
144
|
-
|
|
145
|
-
cv::Mat mask;
|
|
146
|
-
if (info.Length() >= 4 && info[2].IsObject())
|
|
147
|
-
{
|
|
148
|
-
Napi::Object maskObj = info[2].As<Napi::Object>();
|
|
149
|
-
if (maskObj.Has("data") && maskObj.Get("data").IsTypedArray())
|
|
150
|
-
{
|
|
151
|
-
int maskWidth = maskObj.Get("width").ToNumber().Int32Value();
|
|
152
|
-
int maskHeight = maskObj.Get("height").ToNumber().Int32Value();
|
|
153
|
-
Napi::ArrayBuffer maskBufferData = maskObj.Get("data").As<Napi::TypedArray>().ArrayBuffer();
|
|
154
|
-
mask = cv::Mat(maskHeight, maskWidth, CV_8UC1, maskBufferData.Data());
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
cv::Mat result;
|
|
159
|
-
if (mask.empty())
|
|
160
|
-
{
|
|
161
|
-
cv::matchTemplate(src, templ, result, cv::TM_CCOEFF_NORMED);
|
|
162
|
-
}
|
|
163
|
-
else
|
|
164
|
-
{
|
|
165
|
-
cv::matchTemplate(src, templ, result, cv::TM_CCOEFF_NORMED, mask);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
double minVal, maxVal;
|
|
169
|
-
cv::Point minLoc, maxLoc;
|
|
170
|
-
cv::minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc);
|
|
171
|
-
|
|
172
|
-
Napi::Object matchResult = Napi::Object::New(env);
|
|
173
|
-
matchResult.Set("minValue", minVal);
|
|
174
|
-
matchResult.Set("maxValue", maxVal);
|
|
175
|
-
Napi::Object minLocation = Napi::Object::New(env);
|
|
176
|
-
minLocation.Set("x", Napi::Number::New(env, minLoc.x));
|
|
177
|
-
minLocation.Set("y", Napi::Number::New(env, minLoc.y));
|
|
178
|
-
matchResult.Set("minLocation", minLocation);
|
|
179
|
-
|
|
180
|
-
Napi::Object maxLocation = Napi::Object::New(env);
|
|
181
|
-
maxLocation.Set("x", Napi::Number::New(env, maxLoc.x));
|
|
182
|
-
maxLocation.Set("y", Napi::Number::New(env, maxLoc.y));
|
|
183
|
-
matchResult.Set("maxLocation", maxLocation);
|
|
184
|
-
|
|
185
|
-
return matchResult;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
Napi::Value BgrToGray(const Napi::CallbackInfo &info)
|
|
189
|
-
{
|
|
190
|
-
Napi::Env env = info.Env();
|
|
191
|
-
|
|
192
|
-
if (info.Length() < 1 || !info[0].IsObject())
|
|
193
|
-
{
|
|
194
|
-
Napi::TypeError::New(env, "Invalid arguments. Expected: (object)").ThrowAsJavaScriptException();
|
|
195
|
-
return env.Null();
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
Napi::Object srcObj = info[0].As<Napi::Object>();
|
|
199
|
-
|
|
200
|
-
if (!srcObj.Has("data") || !srcObj.Has("width") || !srcObj.Has("height"))
|
|
201
|
-
{
|
|
202
|
-
Napi::TypeError::New(env, "Invalid image data object. Expected properties: 'data', 'width', 'height'").ThrowAsJavaScriptException();
|
|
203
|
-
return env.Null();
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
if (!srcObj.Get("data").IsTypedArray())
|
|
207
|
-
{
|
|
208
|
-
Napi::TypeError::New(env, "TypedArray expected for 'data' property").ThrowAsJavaScriptException();
|
|
209
|
-
return env.Null();
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
int width = srcObj.Get("width").ToNumber().Int32Value();
|
|
213
|
-
int height = srcObj.Get("height").ToNumber().Int32Value();
|
|
214
|
-
|
|
215
|
-
cv::Mat src(height, width, CV_8UC3, srcObj.Get("data").As<Napi::TypedArray>().ArrayBuffer().Data());
|
|
216
|
-
cv::Mat gray;
|
|
217
|
-
|
|
218
|
-
cv::cvtColor(src, gray, cv::COLOR_BGR2GRAY);
|
|
219
|
-
|
|
220
|
-
Napi::Object result = Napi::Object::New(env);
|
|
221
|
-
// Create a new Uint8Array with the correct size
|
|
222
|
-
// std::cout << gray.elemSize() << std::endl;
|
|
223
|
-
size_t totalBytes = width * height;
|
|
224
|
-
Napi::ArrayBuffer arrayBuffer = Napi::ArrayBuffer::New(env, totalBytes);
|
|
225
|
-
Napi::Uint8Array uint8Array = Napi::Uint8Array::New(env, totalBytes, arrayBuffer, 0);
|
|
226
|
-
|
|
227
|
-
// Copy the image data to the Uint8Array
|
|
228
|
-
memcpy(uint8Array.Data(), gray.data, totalBytes);
|
|
229
|
-
|
|
230
|
-
result.Set("width", width);
|
|
231
|
-
result.Set("height", height);
|
|
232
|
-
result.Set("data", uint8Array);
|
|
233
|
-
|
|
234
|
-
return result;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
Napi::Value Blur(const Napi::CallbackInfo &info)
|
|
238
|
-
{
|
|
239
|
-
Napi::Env env = info.Env();
|
|
240
|
-
|
|
241
|
-
if (info.Length() < 3 || !info[0].IsObject() || !info[1].IsNumber() || !info[2].IsNumber())
|
|
242
|
-
{
|
|
243
|
-
Napi::TypeError::New(env, "Invalid arguments. Expected: (object, number, number)").ThrowAsJavaScriptException();
|
|
244
|
-
return env.Null();
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
Napi::Object srcObj = info[0].As<Napi::Object>();
|
|
248
|
-
int ksizeX = info[1].As<Napi::Number>().Int32Value();
|
|
249
|
-
int ksizeY = info[2].As<Napi::Number>().Int32Value();
|
|
250
|
-
|
|
251
|
-
if (!srcObj.Has("data") || !srcObj.Has("width") || !srcObj.Has("height"))
|
|
252
|
-
{
|
|
253
|
-
Napi::TypeError::New(env, "Invalid image data object. Expected properties: 'data', 'width', 'height'").ThrowAsJavaScriptException();
|
|
254
|
-
return env.Null();
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
if (!srcObj.Get("data").IsTypedArray())
|
|
258
|
-
{
|
|
259
|
-
Napi::TypeError::New(env, "TypedArray expected for 'data' property").ThrowAsJavaScriptException();
|
|
260
|
-
return env.Null();
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
int width = srcObj.Get("width").ToNumber().Int32Value();
|
|
264
|
-
int height = srcObj.Get("height").ToNumber().Int32Value();
|
|
265
|
-
|
|
266
|
-
cv::Mat src(height, width, CV_8UC3, srcObj.Get("data").As<Napi::TypedArray>().ArrayBuffer().Data());
|
|
267
|
-
cv::Mat blurred;
|
|
268
|
-
|
|
269
|
-
cv::blur(src, blurred, cv::Size(ksizeX, ksizeY));
|
|
270
|
-
|
|
271
|
-
Napi::Object result = Napi::Object::New(env);
|
|
272
|
-
size_t totalBytes = blurred.total() * blurred.elemSize();
|
|
273
|
-
Napi::ArrayBuffer arrayBuffer = Napi::ArrayBuffer::New(env, totalBytes);
|
|
274
|
-
Napi::Uint8Array uint8Array = Napi::Uint8Array::New(env, totalBytes, arrayBuffer, 0);
|
|
275
|
-
|
|
276
|
-
// Copy the image data to the Uint8Array
|
|
277
|
-
memcpy(uint8Array.Data(), blurred.data, totalBytes);
|
|
278
|
-
result.Set("width", width);
|
|
279
|
-
result.Set("height", height);
|
|
280
|
-
result.Set("data", uint8Array);
|
|
281
|
-
return result;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
Napi::Value DrawRectangle(const Napi::CallbackInfo &info)
|
|
285
|
-
{
|
|
286
|
-
Napi::Env env = info.Env();
|
|
287
|
-
|
|
288
|
-
if (info.Length() < 5 || !info[0].IsObject() || !info[1].IsArray() || !info[2].IsArray() || !info[3].IsArray() || !info[4].IsNumber())
|
|
289
|
-
{
|
|
290
|
-
Napi::TypeError::New(env, "Invalid arguments. Expected: (object, array, array, array, number)").ThrowAsJavaScriptException();
|
|
291
|
-
return env.Null();
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
Napi::Object imageObj = info[0].As<Napi::Object>();
|
|
295
|
-
Napi::Array point1Array = info[1].As<Napi::Array>();
|
|
296
|
-
Napi::Array point2Array = info[2].As<Napi::Array>();
|
|
297
|
-
int thickness = info[4].As<Napi::Number>().Int32Value();
|
|
298
|
-
if (point1Array.Length() < 2 || point2Array.Length() < 2)
|
|
299
|
-
{
|
|
300
|
-
Napi::TypeError::New(env, "Invalid point array length. Expected: [x, y]").ThrowAsJavaScriptException();
|
|
301
|
-
return env.Null();
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
int x1 = point1Array.Get((uint32_t)0).ToNumber().Int32Value();
|
|
305
|
-
int y1 = point1Array.Get((uint32_t)1).ToNumber().Int32Value();
|
|
306
|
-
int x2 = point2Array.Get((uint32_t)0).ToNumber().Int32Value();
|
|
307
|
-
int y2 = point2Array.Get((uint32_t)1).ToNumber().Int32Value();
|
|
308
|
-
|
|
309
|
-
Napi::Array colorArray = info[3].As<Napi::Array>();
|
|
310
|
-
|
|
311
|
-
if (colorArray.Length() < 3)
|
|
312
|
-
{
|
|
313
|
-
Napi::TypeError::New(env, "Invalid color array length. Expected: [r, g, b]").ThrowAsJavaScriptException();
|
|
314
|
-
return env.Null();
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
int r = colorArray.Get((uint32_t)0).ToNumber().Int32Value();
|
|
318
|
-
int g = colorArray.Get((uint32_t)1).ToNumber().Int32Value();
|
|
319
|
-
int b = colorArray.Get((uint32_t)2).ToNumber().Int32Value();
|
|
320
|
-
|
|
321
|
-
if (!imageObj.Has("data") || !imageObj.Has("width") || !imageObj.Has("height"))
|
|
322
|
-
{
|
|
323
|
-
Napi::TypeError::New(env, "Invalid image data object. Expected properties: 'data', 'width', 'height'").ThrowAsJavaScriptException();
|
|
324
|
-
return env.Null();
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
if (!imageObj.Get("data").IsTypedArray())
|
|
328
|
-
{
|
|
329
|
-
Napi::TypeError::New(env, "TypedArray expected for 'data' property").ThrowAsJavaScriptException();
|
|
330
|
-
return env.Null();
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
int width = imageObj.Get("width").ToNumber().Int32Value();
|
|
334
|
-
int height = imageObj.Get("height").ToNumber().Int32Value();
|
|
335
|
-
|
|
336
|
-
cv::Mat image(height, width, CV_8UC3, imageObj.Get("data").As<Napi::TypedArray>().ArrayBuffer().Data());
|
|
337
|
-
|
|
338
|
-
cv::rectangle(image, cv::Point(x1, y1), cv::Point(x2, y2), cv::Scalar(b, g, r), thickness);
|
|
339
|
-
Napi::Object result = Napi::Object::New(env);
|
|
340
|
-
|
|
341
|
-
size_t totalBytes = image.total() * image.elemSize();
|
|
342
|
-
Napi::ArrayBuffer arrayBuffer = Napi::ArrayBuffer::New(env, totalBytes);
|
|
343
|
-
Napi::Uint8Array uint8Array = Napi::Uint8Array::New(env, totalBytes, arrayBuffer, 0);
|
|
344
|
-
|
|
345
|
-
// Copy the image data to the Uint8Array
|
|
346
|
-
memcpy(uint8Array.Data(), image.data, totalBytes);
|
|
347
|
-
result.Set("width", width);
|
|
348
|
-
result.Set("height", height);
|
|
349
|
-
result.Set("data", uint8Array);
|
|
350
|
-
return result;
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
Napi::Value GetRegion(const Napi::CallbackInfo &info)
|
|
354
|
-
{
|
|
355
|
-
Napi::Env env = info.Env();
|
|
356
|
-
|
|
357
|
-
if (info.Length() < 2 || !info[0].IsObject() || !info[1].IsObject())
|
|
358
|
-
{
|
|
359
|
-
Napi::TypeError::New(env, "Invalid arguments. Expected: (object)").ThrowAsJavaScriptException();
|
|
360
|
-
return env.Null();
|
|
361
|
-
}
|
|
362
|
-
Napi::Object imageObj = info[0].As<Napi::Object>();
|
|
363
|
-
Napi::Object options = info[1].As<Napi::Object>();
|
|
364
|
-
|
|
365
|
-
int x = options.Get((uint32_t)0).ToNumber().Int32Value();
|
|
366
|
-
int y = options.Get((uint32_t)1).ToNumber().Int32Value();
|
|
367
|
-
int width = options.Get((uint32_t)2).ToNumber().Int32Value();
|
|
368
|
-
int height = options.Get((uint32_t)3).ToNumber().Int32Value();
|
|
369
|
-
|
|
370
|
-
if (!imageObj.Has("data") || !imageObj.Has("width") || !imageObj.Has("height"))
|
|
371
|
-
{
|
|
372
|
-
Napi::TypeError::New(env, "Invalid image data object. Expected properties: 'data', 'width', 'height'").ThrowAsJavaScriptException();
|
|
373
|
-
return env.Null();
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
if (!imageObj.Get("data").IsTypedArray())
|
|
377
|
-
{
|
|
378
|
-
Napi::TypeError::New(env, "TypedArray expected for 'data' property").ThrowAsJavaScriptException();
|
|
379
|
-
return env.Null();
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
int imageWidth = imageObj.Get("width").ToNumber().Int32Value();
|
|
383
|
-
int imageHeight = imageObj.Get("height").ToNumber().Int32Value();
|
|
384
|
-
|
|
385
|
-
if (x < 0 || y < 0 || width <= 0 || height <= 0 || x + width > imageWidth || y + height > imageHeight)
|
|
386
|
-
{
|
|
387
|
-
Napi::TypeError::New(env, "Invalid region coordinates or size").ThrowAsJavaScriptException();
|
|
388
|
-
return env.Null();
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
cv::Mat image(imageHeight, imageWidth, CV_8UC3, imageObj.Get("data").As<Napi::TypedArray>().ArrayBuffer().Data());
|
|
392
|
-
|
|
393
|
-
cv::Rect region(x, y, width, height);
|
|
394
|
-
cv::Mat regionImage = image(region).clone();
|
|
395
|
-
|
|
396
|
-
size_t totalBytes = regionImage.total() * regionImage.elemSize();
|
|
397
|
-
Napi::ArrayBuffer arrayBuffer = Napi::ArrayBuffer::New(env, totalBytes);
|
|
398
|
-
Napi::Uint8Array uint8Array = Napi::Uint8Array::New(env, totalBytes, arrayBuffer, 0);
|
|
399
|
-
|
|
400
|
-
// Copy the image data to the Uint8Array
|
|
401
|
-
memcpy(uint8Array.Data(), regionImage.data, totalBytes);
|
|
402
|
-
Napi::Object result = Napi::Object::New(env);
|
|
403
|
-
result.Set("data", uint8Array);
|
|
404
|
-
result.Set("width", Napi::Number::New(env, regionImage.cols));
|
|
405
|
-
result.Set("height", Napi::Number::New(env, regionImage.rows));
|
|
406
|
-
|
|
407
|
-
return result;
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
// Napi::Value ReadImage(const Napi::CallbackInfo &info)
|
|
411
|
-
// {
|
|
412
|
-
// Napi::Env env = info.Env();
|
|
413
|
-
// std::string imagePath = info[0].As<Napi::String>();
|
|
414
|
-
|
|
415
|
-
// cv::Mat image = cv::imread(imagePath, cv::IMREAD_COLOR);
|
|
416
|
-
// if (image.empty())
|
|
417
|
-
// {
|
|
418
|
-
// Napi::TypeError::New(env, "Could not read the image").ThrowAsJavaScriptException();
|
|
419
|
-
// return env.Null();
|
|
420
|
-
// }
|
|
421
|
-
|
|
422
|
-
// cv::Mat grayImage;
|
|
423
|
-
// cv::cvtColor(image, grayImage, cv::COLOR_BGR2GRAY);
|
|
424
|
-
|
|
425
|
-
// return Napi::Number::New(env, grayImage.rows * grayImage.cols);
|
|
1
|
+
#include <iostream>
|
|
2
|
+
#include <opencv2/core.hpp>
|
|
3
|
+
#include <opencv2/imgcodecs.hpp>
|
|
4
|
+
#include <opencv2/imgproc.hpp>
|
|
5
|
+
#include <napi.h>
|
|
6
|
+
|
|
7
|
+
Napi::Value Imread(const Napi::CallbackInfo &info)
|
|
8
|
+
{
|
|
9
|
+
Napi::Env env = info.Env();
|
|
10
|
+
|
|
11
|
+
if (info.Length() < 1 || !info[0].IsString())
|
|
12
|
+
{
|
|
13
|
+
Napi::TypeError::New(env, "String expected for image file path").ThrowAsJavaScriptException();
|
|
14
|
+
return env.Null();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
std::string filename = info[0].ToString().Utf8Value();
|
|
18
|
+
|
|
19
|
+
int flags = cv::IMREAD_COLOR;
|
|
20
|
+
if (info.Length() > 1 && info[1].IsNumber())
|
|
21
|
+
{
|
|
22
|
+
flags = info[1].ToNumber().Int32Value();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
cv::Mat image = cv::imread(filename, flags);
|
|
26
|
+
|
|
27
|
+
if (image.empty())
|
|
28
|
+
{
|
|
29
|
+
Napi::TypeError::New(env, "Failed to load image").ThrowAsJavaScriptException();
|
|
30
|
+
return env.Null();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Create a new Uint8Array with the correct size
|
|
34
|
+
|
|
35
|
+
size_t totalBytes = image.total() * image.elemSize();
|
|
36
|
+
Napi::ArrayBuffer arrayBuffer = Napi::ArrayBuffer::New(env, totalBytes);
|
|
37
|
+
Napi::Uint8Array uint8Array = Napi::Uint8Array::New(env, totalBytes, arrayBuffer, 0);
|
|
38
|
+
|
|
39
|
+
// Copy the image data to the Uint8Array
|
|
40
|
+
memcpy(uint8Array.Data(), image.data, totalBytes);
|
|
41
|
+
// std::cout << totalBytes << std::endl;
|
|
42
|
+
// std::cout << uint8Array.ByteLength() << std::endl;
|
|
43
|
+
// Create a JavaScript object with 'width', 'height', and 'data' properties
|
|
44
|
+
Napi::Object result = Napi::Object::New(env);
|
|
45
|
+
|
|
46
|
+
result.Set("width", image.cols);
|
|
47
|
+
result.Set("height", image.rows);
|
|
48
|
+
result.Set("data", uint8Array);
|
|
49
|
+
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
Napi::Value Imwrite(const Napi::CallbackInfo &info)
|
|
54
|
+
{
|
|
55
|
+
Napi::Env env = info.Env();
|
|
56
|
+
|
|
57
|
+
if (info.Length() < 1 || !info[0].IsObject())
|
|
58
|
+
{
|
|
59
|
+
Napi::TypeError::New(env, "Invalid arguments. Expected: object").ThrowAsJavaScriptException();
|
|
60
|
+
return env.Null();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
Napi::Object imageData = info[0].As<Napi::Object>();
|
|
64
|
+
|
|
65
|
+
if (!imageData.Has("width") || !imageData.Has("height") || !imageData.Has("data"))
|
|
66
|
+
{
|
|
67
|
+
Napi::TypeError::New(env, "Invalid image data object. Expected properties: 'width', 'height', 'data'").ThrowAsJavaScriptException();
|
|
68
|
+
return env.Null();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
int width = imageData.Get("width").ToNumber().Int32Value();
|
|
72
|
+
int height = imageData.Get("height").ToNumber().Int32Value();
|
|
73
|
+
|
|
74
|
+
cv::Mat image;
|
|
75
|
+
if (imageData.Get("data").IsTypedArray())
|
|
76
|
+
{
|
|
77
|
+
Napi::TypedArray typedArray = imageData.Get("data").As<Napi::TypedArray>();
|
|
78
|
+
int elementSize = typedArray.ByteLength() / (width * height);
|
|
79
|
+
// std::cout << typedArray.ByteLength() << std::endl;
|
|
80
|
+
// std::cout << elementSize << std::endl;
|
|
81
|
+
int type = elementSize == 1 ? CV_8UC1 : CV_8UC3;
|
|
82
|
+
|
|
83
|
+
image = cv::Mat(height, width, type);
|
|
84
|
+
memcpy(image.data, typedArray.As<Napi::Uint8Array>().Data(), typedArray.ByteLength());
|
|
85
|
+
}
|
|
86
|
+
else
|
|
87
|
+
{
|
|
88
|
+
Napi::TypeError::New(env, "'data' property must be a TypedArray").ThrowAsJavaScriptException();
|
|
89
|
+
return env.Null();
|
|
90
|
+
}
|
|
91
|
+
std::vector<uchar> buffer;
|
|
92
|
+
cv::imencode(".png", image, buffer);
|
|
93
|
+
|
|
94
|
+
Napi::Buffer<uchar> resultBuffer = Napi::Buffer<uchar>::Copy(env, buffer.data(), buffer.size());
|
|
95
|
+
return resultBuffer;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
Napi::Value MatchTemplate(const Napi::CallbackInfo &info)
|
|
99
|
+
{
|
|
100
|
+
Napi::Env env = info.Env();
|
|
101
|
+
|
|
102
|
+
if (info.Length() < 2 || !info[0].IsObject() || !info[1].IsObject())
|
|
103
|
+
{
|
|
104
|
+
Napi::TypeError::New(env, "Invalid arguments. Expected: (object, object[, object])").ThrowAsJavaScriptException();
|
|
105
|
+
return env.Null();
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
Napi::Object srcObj = info[0].As<Napi::Object>();
|
|
109
|
+
Napi::Object templObj = info[1].As<Napi::Object>();
|
|
110
|
+
int method = cv::TM_CCOEFF_NORMED;
|
|
111
|
+
if (info.Length() > 2 && !info[2].IsNumber())
|
|
112
|
+
{
|
|
113
|
+
method = info[2].ToNumber().Int32Value();
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (!srcObj.Has("data") || !templObj.Has("data"))
|
|
117
|
+
{
|
|
118
|
+
Napi::TypeError::New(env, "Invalid image data objects. Expected properties: 'data'").ThrowAsJavaScriptException();
|
|
119
|
+
return env.Null();
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (!srcObj.Has("width") || !srcObj.Has("height") || !templObj.Has("width") || !templObj.Has("height"))
|
|
123
|
+
{
|
|
124
|
+
Napi::TypeError::New(env, "Invalid image data objects. Expected properties: 'width', 'height'").ThrowAsJavaScriptException();
|
|
125
|
+
return env.Null();
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (!srcObj.Get("data").IsTypedArray() || !templObj.Get("data").IsTypedArray())
|
|
129
|
+
{
|
|
130
|
+
Napi::TypeError::New(env, "TypedArray expected for 'data' properties").ThrowAsJavaScriptException();
|
|
131
|
+
return env.Null();
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
int srcWidth = srcObj.Get("width").ToNumber().Int32Value();
|
|
135
|
+
int srcHeight = srcObj.Get("height").ToNumber().Int32Value();
|
|
136
|
+
int templWidth = templObj.Get("width").ToNumber().Int32Value();
|
|
137
|
+
int templHeight = templObj.Get("height").ToNumber().Int32Value();
|
|
138
|
+
|
|
139
|
+
Napi::ArrayBuffer srcBufferData = srcObj.Get("data").As<Napi::TypedArray>().ArrayBuffer();
|
|
140
|
+
Napi::ArrayBuffer templBufferData = templObj.Get("data").As<Napi::TypedArray>().ArrayBuffer();
|
|
141
|
+
|
|
142
|
+
cv::Mat src(srcHeight, srcWidth, CV_8UC1, srcBufferData.Data());
|
|
143
|
+
cv::Mat templ(templHeight, templWidth, CV_8UC1, templBufferData.Data());
|
|
144
|
+
|
|
145
|
+
cv::Mat mask;
|
|
146
|
+
if (info.Length() >= 4 && info[2].IsObject())
|
|
147
|
+
{
|
|
148
|
+
Napi::Object maskObj = info[2].As<Napi::Object>();
|
|
149
|
+
if (maskObj.Has("data") && maskObj.Get("data").IsTypedArray())
|
|
150
|
+
{
|
|
151
|
+
int maskWidth = maskObj.Get("width").ToNumber().Int32Value();
|
|
152
|
+
int maskHeight = maskObj.Get("height").ToNumber().Int32Value();
|
|
153
|
+
Napi::ArrayBuffer maskBufferData = maskObj.Get("data").As<Napi::TypedArray>().ArrayBuffer();
|
|
154
|
+
mask = cv::Mat(maskHeight, maskWidth, CV_8UC1, maskBufferData.Data());
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
cv::Mat result;
|
|
159
|
+
if (mask.empty())
|
|
160
|
+
{
|
|
161
|
+
cv::matchTemplate(src, templ, result, cv::TM_CCOEFF_NORMED);
|
|
162
|
+
}
|
|
163
|
+
else
|
|
164
|
+
{
|
|
165
|
+
cv::matchTemplate(src, templ, result, cv::TM_CCOEFF_NORMED, mask);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
double minVal, maxVal;
|
|
169
|
+
cv::Point minLoc, maxLoc;
|
|
170
|
+
cv::minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc);
|
|
171
|
+
|
|
172
|
+
Napi::Object matchResult = Napi::Object::New(env);
|
|
173
|
+
matchResult.Set("minValue", minVal);
|
|
174
|
+
matchResult.Set("maxValue", maxVal);
|
|
175
|
+
Napi::Object minLocation = Napi::Object::New(env);
|
|
176
|
+
minLocation.Set("x", Napi::Number::New(env, minLoc.x));
|
|
177
|
+
minLocation.Set("y", Napi::Number::New(env, minLoc.y));
|
|
178
|
+
matchResult.Set("minLocation", minLocation);
|
|
179
|
+
|
|
180
|
+
Napi::Object maxLocation = Napi::Object::New(env);
|
|
181
|
+
maxLocation.Set("x", Napi::Number::New(env, maxLoc.x));
|
|
182
|
+
maxLocation.Set("y", Napi::Number::New(env, maxLoc.y));
|
|
183
|
+
matchResult.Set("maxLocation", maxLocation);
|
|
184
|
+
|
|
185
|
+
return matchResult;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
Napi::Value BgrToGray(const Napi::CallbackInfo &info)
|
|
189
|
+
{
|
|
190
|
+
Napi::Env env = info.Env();
|
|
191
|
+
|
|
192
|
+
if (info.Length() < 1 || !info[0].IsObject())
|
|
193
|
+
{
|
|
194
|
+
Napi::TypeError::New(env, "Invalid arguments. Expected: (object)").ThrowAsJavaScriptException();
|
|
195
|
+
return env.Null();
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
Napi::Object srcObj = info[0].As<Napi::Object>();
|
|
199
|
+
|
|
200
|
+
if (!srcObj.Has("data") || !srcObj.Has("width") || !srcObj.Has("height"))
|
|
201
|
+
{
|
|
202
|
+
Napi::TypeError::New(env, "Invalid image data object. Expected properties: 'data', 'width', 'height'").ThrowAsJavaScriptException();
|
|
203
|
+
return env.Null();
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (!srcObj.Get("data").IsTypedArray())
|
|
207
|
+
{
|
|
208
|
+
Napi::TypeError::New(env, "TypedArray expected for 'data' property").ThrowAsJavaScriptException();
|
|
209
|
+
return env.Null();
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
int width = srcObj.Get("width").ToNumber().Int32Value();
|
|
213
|
+
int height = srcObj.Get("height").ToNumber().Int32Value();
|
|
214
|
+
|
|
215
|
+
cv::Mat src(height, width, CV_8UC3, srcObj.Get("data").As<Napi::TypedArray>().ArrayBuffer().Data());
|
|
216
|
+
cv::Mat gray;
|
|
217
|
+
|
|
218
|
+
cv::cvtColor(src, gray, cv::COLOR_BGR2GRAY);
|
|
219
|
+
|
|
220
|
+
Napi::Object result = Napi::Object::New(env);
|
|
221
|
+
// Create a new Uint8Array with the correct size
|
|
222
|
+
// std::cout << gray.elemSize() << std::endl;
|
|
223
|
+
size_t totalBytes = width * height;
|
|
224
|
+
Napi::ArrayBuffer arrayBuffer = Napi::ArrayBuffer::New(env, totalBytes);
|
|
225
|
+
Napi::Uint8Array uint8Array = Napi::Uint8Array::New(env, totalBytes, arrayBuffer, 0);
|
|
226
|
+
|
|
227
|
+
// Copy the image data to the Uint8Array
|
|
228
|
+
memcpy(uint8Array.Data(), gray.data, totalBytes);
|
|
229
|
+
|
|
230
|
+
result.Set("width", width);
|
|
231
|
+
result.Set("height", height);
|
|
232
|
+
result.Set("data", uint8Array);
|
|
233
|
+
|
|
234
|
+
return result;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
Napi::Value Blur(const Napi::CallbackInfo &info)
|
|
238
|
+
{
|
|
239
|
+
Napi::Env env = info.Env();
|
|
240
|
+
|
|
241
|
+
if (info.Length() < 3 || !info[0].IsObject() || !info[1].IsNumber() || !info[2].IsNumber())
|
|
242
|
+
{
|
|
243
|
+
Napi::TypeError::New(env, "Invalid arguments. Expected: (object, number, number)").ThrowAsJavaScriptException();
|
|
244
|
+
return env.Null();
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
Napi::Object srcObj = info[0].As<Napi::Object>();
|
|
248
|
+
int ksizeX = info[1].As<Napi::Number>().Int32Value();
|
|
249
|
+
int ksizeY = info[2].As<Napi::Number>().Int32Value();
|
|
250
|
+
|
|
251
|
+
if (!srcObj.Has("data") || !srcObj.Has("width") || !srcObj.Has("height"))
|
|
252
|
+
{
|
|
253
|
+
Napi::TypeError::New(env, "Invalid image data object. Expected properties: 'data', 'width', 'height'").ThrowAsJavaScriptException();
|
|
254
|
+
return env.Null();
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if (!srcObj.Get("data").IsTypedArray())
|
|
258
|
+
{
|
|
259
|
+
Napi::TypeError::New(env, "TypedArray expected for 'data' property").ThrowAsJavaScriptException();
|
|
260
|
+
return env.Null();
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
int width = srcObj.Get("width").ToNumber().Int32Value();
|
|
264
|
+
int height = srcObj.Get("height").ToNumber().Int32Value();
|
|
265
|
+
|
|
266
|
+
cv::Mat src(height, width, CV_8UC3, srcObj.Get("data").As<Napi::TypedArray>().ArrayBuffer().Data());
|
|
267
|
+
cv::Mat blurred;
|
|
268
|
+
|
|
269
|
+
cv::blur(src, blurred, cv::Size(ksizeX, ksizeY));
|
|
270
|
+
|
|
271
|
+
Napi::Object result = Napi::Object::New(env);
|
|
272
|
+
size_t totalBytes = blurred.total() * blurred.elemSize();
|
|
273
|
+
Napi::ArrayBuffer arrayBuffer = Napi::ArrayBuffer::New(env, totalBytes);
|
|
274
|
+
Napi::Uint8Array uint8Array = Napi::Uint8Array::New(env, totalBytes, arrayBuffer, 0);
|
|
275
|
+
|
|
276
|
+
// Copy the image data to the Uint8Array
|
|
277
|
+
memcpy(uint8Array.Data(), blurred.data, totalBytes);
|
|
278
|
+
result.Set("width", width);
|
|
279
|
+
result.Set("height", height);
|
|
280
|
+
result.Set("data", uint8Array);
|
|
281
|
+
return result;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
Napi::Value DrawRectangle(const Napi::CallbackInfo &info)
|
|
285
|
+
{
|
|
286
|
+
Napi::Env env = info.Env();
|
|
287
|
+
|
|
288
|
+
if (info.Length() < 5 || !info[0].IsObject() || !info[1].IsArray() || !info[2].IsArray() || !info[3].IsArray() || !info[4].IsNumber())
|
|
289
|
+
{
|
|
290
|
+
Napi::TypeError::New(env, "Invalid arguments. Expected: (object, array, array, array, number)").ThrowAsJavaScriptException();
|
|
291
|
+
return env.Null();
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
Napi::Object imageObj = info[0].As<Napi::Object>();
|
|
295
|
+
Napi::Array point1Array = info[1].As<Napi::Array>();
|
|
296
|
+
Napi::Array point2Array = info[2].As<Napi::Array>();
|
|
297
|
+
int thickness = info[4].As<Napi::Number>().Int32Value();
|
|
298
|
+
if (point1Array.Length() < 2 || point2Array.Length() < 2)
|
|
299
|
+
{
|
|
300
|
+
Napi::TypeError::New(env, "Invalid point array length. Expected: [x, y]").ThrowAsJavaScriptException();
|
|
301
|
+
return env.Null();
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
int x1 = point1Array.Get((uint32_t)0).ToNumber().Int32Value();
|
|
305
|
+
int y1 = point1Array.Get((uint32_t)1).ToNumber().Int32Value();
|
|
306
|
+
int x2 = point2Array.Get((uint32_t)0).ToNumber().Int32Value();
|
|
307
|
+
int y2 = point2Array.Get((uint32_t)1).ToNumber().Int32Value();
|
|
308
|
+
|
|
309
|
+
Napi::Array colorArray = info[3].As<Napi::Array>();
|
|
310
|
+
|
|
311
|
+
if (colorArray.Length() < 3)
|
|
312
|
+
{
|
|
313
|
+
Napi::TypeError::New(env, "Invalid color array length. Expected: [r, g, b]").ThrowAsJavaScriptException();
|
|
314
|
+
return env.Null();
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
int r = colorArray.Get((uint32_t)0).ToNumber().Int32Value();
|
|
318
|
+
int g = colorArray.Get((uint32_t)1).ToNumber().Int32Value();
|
|
319
|
+
int b = colorArray.Get((uint32_t)2).ToNumber().Int32Value();
|
|
320
|
+
|
|
321
|
+
if (!imageObj.Has("data") || !imageObj.Has("width") || !imageObj.Has("height"))
|
|
322
|
+
{
|
|
323
|
+
Napi::TypeError::New(env, "Invalid image data object. Expected properties: 'data', 'width', 'height'").ThrowAsJavaScriptException();
|
|
324
|
+
return env.Null();
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
if (!imageObj.Get("data").IsTypedArray())
|
|
328
|
+
{
|
|
329
|
+
Napi::TypeError::New(env, "TypedArray expected for 'data' property").ThrowAsJavaScriptException();
|
|
330
|
+
return env.Null();
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
int width = imageObj.Get("width").ToNumber().Int32Value();
|
|
334
|
+
int height = imageObj.Get("height").ToNumber().Int32Value();
|
|
335
|
+
|
|
336
|
+
cv::Mat image(height, width, CV_8UC3, imageObj.Get("data").As<Napi::TypedArray>().ArrayBuffer().Data());
|
|
337
|
+
|
|
338
|
+
cv::rectangle(image, cv::Point(x1, y1), cv::Point(x2, y2), cv::Scalar(b, g, r), thickness);
|
|
339
|
+
Napi::Object result = Napi::Object::New(env);
|
|
340
|
+
|
|
341
|
+
size_t totalBytes = image.total() * image.elemSize();
|
|
342
|
+
Napi::ArrayBuffer arrayBuffer = Napi::ArrayBuffer::New(env, totalBytes);
|
|
343
|
+
Napi::Uint8Array uint8Array = Napi::Uint8Array::New(env, totalBytes, arrayBuffer, 0);
|
|
344
|
+
|
|
345
|
+
// Copy the image data to the Uint8Array
|
|
346
|
+
memcpy(uint8Array.Data(), image.data, totalBytes);
|
|
347
|
+
result.Set("width", width);
|
|
348
|
+
result.Set("height", height);
|
|
349
|
+
result.Set("data", uint8Array);
|
|
350
|
+
return result;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
Napi::Value GetRegion(const Napi::CallbackInfo &info)
|
|
354
|
+
{
|
|
355
|
+
Napi::Env env = info.Env();
|
|
356
|
+
|
|
357
|
+
if (info.Length() < 2 || !info[0].IsObject() || !info[1].IsObject())
|
|
358
|
+
{
|
|
359
|
+
Napi::TypeError::New(env, "Invalid arguments. Expected: (object)").ThrowAsJavaScriptException();
|
|
360
|
+
return env.Null();
|
|
361
|
+
}
|
|
362
|
+
Napi::Object imageObj = info[0].As<Napi::Object>();
|
|
363
|
+
Napi::Object options = info[1].As<Napi::Object>();
|
|
364
|
+
|
|
365
|
+
int x = options.Get((uint32_t)0).ToNumber().Int32Value();
|
|
366
|
+
int y = options.Get((uint32_t)1).ToNumber().Int32Value();
|
|
367
|
+
int width = options.Get((uint32_t)2).ToNumber().Int32Value();
|
|
368
|
+
int height = options.Get((uint32_t)3).ToNumber().Int32Value();
|
|
369
|
+
|
|
370
|
+
if (!imageObj.Has("data") || !imageObj.Has("width") || !imageObj.Has("height"))
|
|
371
|
+
{
|
|
372
|
+
Napi::TypeError::New(env, "Invalid image data object. Expected properties: 'data', 'width', 'height'").ThrowAsJavaScriptException();
|
|
373
|
+
return env.Null();
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
if (!imageObj.Get("data").IsTypedArray())
|
|
377
|
+
{
|
|
378
|
+
Napi::TypeError::New(env, "TypedArray expected for 'data' property").ThrowAsJavaScriptException();
|
|
379
|
+
return env.Null();
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
int imageWidth = imageObj.Get("width").ToNumber().Int32Value();
|
|
383
|
+
int imageHeight = imageObj.Get("height").ToNumber().Int32Value();
|
|
384
|
+
|
|
385
|
+
if (x < 0 || y < 0 || width <= 0 || height <= 0 || x + width > imageWidth || y + height > imageHeight)
|
|
386
|
+
{
|
|
387
|
+
Napi::TypeError::New(env, "Invalid region coordinates or size").ThrowAsJavaScriptException();
|
|
388
|
+
return env.Null();
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
cv::Mat image(imageHeight, imageWidth, CV_8UC3, imageObj.Get("data").As<Napi::TypedArray>().ArrayBuffer().Data());
|
|
392
|
+
|
|
393
|
+
cv::Rect region(x, y, width, height);
|
|
394
|
+
cv::Mat regionImage = image(region).clone();
|
|
395
|
+
|
|
396
|
+
size_t totalBytes = regionImage.total() * regionImage.elemSize();
|
|
397
|
+
Napi::ArrayBuffer arrayBuffer = Napi::ArrayBuffer::New(env, totalBytes);
|
|
398
|
+
Napi::Uint8Array uint8Array = Napi::Uint8Array::New(env, totalBytes, arrayBuffer, 0);
|
|
399
|
+
|
|
400
|
+
// Copy the image data to the Uint8Array
|
|
401
|
+
memcpy(uint8Array.Data(), regionImage.data, totalBytes);
|
|
402
|
+
Napi::Object result = Napi::Object::New(env);
|
|
403
|
+
result.Set("data", uint8Array);
|
|
404
|
+
result.Set("width", Napi::Number::New(env, regionImage.cols));
|
|
405
|
+
result.Set("height", Napi::Number::New(env, regionImage.rows));
|
|
406
|
+
|
|
407
|
+
return result;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// Napi::Value ReadImage(const Napi::CallbackInfo &info)
|
|
411
|
+
// {
|
|
412
|
+
// Napi::Env env = info.Env();
|
|
413
|
+
// std::string imagePath = info[0].As<Napi::String>();
|
|
414
|
+
|
|
415
|
+
// cv::Mat image = cv::imread(imagePath, cv::IMREAD_COLOR);
|
|
416
|
+
// if (image.empty())
|
|
417
|
+
// {
|
|
418
|
+
// Napi::TypeError::New(env, "Could not read the image").ThrowAsJavaScriptException();
|
|
419
|
+
// return env.Null();
|
|
420
|
+
// }
|
|
421
|
+
|
|
422
|
+
// cv::Mat grayImage;
|
|
423
|
+
// cv::cvtColor(image, grayImage, cv::COLOR_BGR2GRAY);
|
|
424
|
+
|
|
425
|
+
// return Napi::Number::New(env, grayImage.rows * grayImage.cols);
|
|
426
426
|
// }
|