@luii/node-tesseract-ocr 2.1.0 → 2.4.0

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.
@@ -20,20 +20,86 @@
20
20
  #include <cstddef>
21
21
  #include <cstdint>
22
22
  #include <cstring>
23
+ #include <iostream>
23
24
  #include <leptonica/allheaders.h>
24
25
  #include <string>
25
26
  #include <tesseract/publictypes.h>
26
27
 
27
28
  Napi::FunctionReference TesseractWrapper::constructor;
28
29
 
30
+ namespace {
31
+
32
+ Napi::Value RejectWithError(Napi::Env env, Napi::Error error, const char *code,
33
+ const std::string &message, const char *method) {
34
+ error.Set("code", Napi::String::New(env, code));
35
+ error.Set("method", Napi::String::New(env, method));
36
+
37
+ Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New(env);
38
+ deferred.Reject(error.Value());
39
+ return deferred.Promise();
40
+ }
41
+
42
+ Napi::Value RejectError(Napi::Env env, const std::string &message,
43
+ const char *method) {
44
+ return RejectWithError(env, Napi::Error::New(env, message),
45
+ "ERR_TESSERACT_RUNTIME", message, method);
46
+ }
47
+
48
+ Napi::Value RejectTypeError(Napi::Env env, const std::string &message,
49
+ const char *method) {
50
+ return RejectWithError(env, Napi::TypeError::New(env, message),
51
+ "ERR_INVALID_ARGUMENT", message, method);
52
+ }
53
+
54
+ Napi::Value RejectRangeError(Napi::Env env, const std::string &message,
55
+ const char *method) {
56
+ return RejectWithError(env, Napi::RangeError::New(env, message),
57
+ "ERR_OUT_OF_RANGE", message, method);
58
+ }
59
+
60
+ bool HasArg(const Napi::CallbackInfo &info, size_t index) {
61
+ return info.Length() > index && !info[index].IsUndefined();
62
+ }
63
+
64
+ } // namespace
65
+
29
66
  Napi::Object TesseractWrapper::InitAddon(Napi::Env env, Napi::Object exports) {
30
67
  Napi::Function func = DefineClass(
31
68
  env, "Tesseract",
32
69
  {
70
+ InstanceMethod("version", &TesseractWrapper::Version),
71
+ InstanceMethod("isInitialized", &TesseractWrapper::IsInitialized),
72
+ InstanceMethod("setInputName", &TesseractWrapper::SetInputName),
73
+ InstanceMethod("getInputName", &TesseractWrapper::GetInputName),
74
+ InstanceMethod("setInputImage", &TesseractWrapper::SetInputImage),
75
+ InstanceMethod("getInputImage", &TesseractWrapper::GetInputImage),
76
+ InstanceMethod("getSourceYResolution",
77
+ &TesseractWrapper::GetSourceYResolution),
78
+ InstanceMethod("getDataPath", &TesseractWrapper::GetDataPath),
79
+ InstanceMethod("setOutputName", &TesseractWrapper::SetOutputName),
80
+ InstanceMethod("clearPersistentCache",
81
+ &TesseractWrapper::ClearPersistentCache),
82
+ InstanceMethod("clearAdaptiveClassifier",
83
+ &TesseractWrapper::ClearAdaptiveClassifier),
84
+ InstanceMethod("getThresholdedImage",
85
+ &TesseractWrapper::GetThresholdedImage),
86
+ InstanceMethod("getThresholdedImageScaleFactor",
87
+ &TesseractWrapper::GetThresholdedImageScaleFactor),
33
88
  InstanceMethod("init", &TesseractWrapper::Init),
34
89
  InstanceMethod("initForAnalysePage",
35
90
  &TesseractWrapper::InitForAnalysePage),
36
- InstanceMethod("analysePage", &TesseractWrapper::AnalysePage),
91
+ InstanceMethod("analyseLayout", &TesseractWrapper::AnalyseLayout),
92
+ InstanceMethod("beginProcessPages",
93
+ &TesseractWrapper::BeginProcessPages),
94
+ InstanceMethod("addProcessPage", &TesseractWrapper::AddProcessPage),
95
+ InstanceMethod("finishProcessPages",
96
+ &TesseractWrapper::FinishProcessPages),
97
+ InstanceMethod("abortProcessPages",
98
+ &TesseractWrapper::AbortProcessPages),
99
+ InstanceMethod("getProcessPagesStatus",
100
+ &TesseractWrapper::GetProcessPagesStatus),
101
+ InstanceMethod("setDebugVariable",
102
+ &TesseractWrapper::SetDebugVariable),
37
103
  InstanceMethod("setVariable", &TesseractWrapper::SetVariable),
38
104
  InstanceMethod("getIntVariable", &TesseractWrapper::GetIntVariable),
39
105
  InstanceMethod("getBoolVariable", &TesseractWrapper::GetBoolVariable),
@@ -41,9 +107,9 @@ Napi::Object TesseractWrapper::InitAddon(Napi::Env env, Napi::Object exports) {
41
107
  &TesseractWrapper::GetDoubleVariable),
42
108
  InstanceMethod("getStringVariable",
43
109
  &TesseractWrapper::GetStringVariable),
110
+ InstanceMethod("setImage", &TesseractWrapper::SetImage),
44
111
  // InstanceMethod("printVariables",
45
112
  // &TesseractWrapper::PrintVariables),
46
- InstanceMethod("setImage", &TesseractWrapper::SetImage),
47
113
  InstanceMethod("setPageMode", &TesseractWrapper::SetPageMode),
48
114
  InstanceMethod("setRectangle", &TesseractWrapper::SetRectangle),
49
115
  InstanceMethod("setSourceResolution",
@@ -52,6 +118,14 @@ Napi::Object TesseractWrapper::InitAddon(Napi::Env env, Napi::Object exports) {
52
118
  InstanceMethod("detectOrientationScript",
53
119
  &TesseractWrapper::DetectOrientationScript),
54
120
  InstanceMethod("meanTextConf", &TesseractWrapper::MeanTextConf),
121
+ InstanceMethod("allWordConfidences",
122
+ &TesseractWrapper::AllWordConfidences),
123
+ InstanceMethod("getPAGEText", &TesseractWrapper::GetPAGEText),
124
+ InstanceMethod("getLSTMBoxText", &TesseractWrapper::GetLSTMBoxText),
125
+ InstanceMethod("getBoxText", &TesseractWrapper::GetBoxText),
126
+ InstanceMethod("getWordStrBoxText",
127
+ &TesseractWrapper::GetWordStrBoxText),
128
+ InstanceMethod("getOSDText", &TesseractWrapper::getOSDText),
55
129
  InstanceMethod("getUTF8Text", &TesseractWrapper::GetUTF8Text),
56
130
  InstanceMethod("getHOCRText", &TesseractWrapper::GetHOCRText),
57
131
  InstanceMethod("getTSVText", &TesseractWrapper::GetTSVText),
@@ -79,16 +153,185 @@ TesseractWrapper::TesseractWrapper(const Napi::CallbackInfo &info)
79
153
 
80
154
  TesseractWrapper::~TesseractWrapper() {}
81
155
 
156
+ Napi::Value TesseractWrapper::Version(const Napi::CallbackInfo &info) {
157
+ return _worker_thread.Enqueue(CommandVersion{});
158
+ }
159
+
160
+ Napi::Value TesseractWrapper::IsInitialized(const Napi::CallbackInfo &info) {
161
+ Napi::Env env = info.Env();
162
+
163
+ if (info.Length() > 0) {
164
+ return RejectTypeError(env, "isInitialized(): expected no arguments",
165
+ "isInitialized");
166
+ }
167
+
168
+ return _worker_thread.Enqueue(CommandIsInitialized{});
169
+ }
170
+
171
+ Napi::Value TesseractWrapper::SetInputName(const Napi::CallbackInfo &info) {
172
+ Napi::Env env = info.Env();
173
+
174
+ if (info.Length() > 1) {
175
+ return RejectTypeError(
176
+ env, "setInputName(inputName?): expected at most 1 argument",
177
+ "setInputName");
178
+ }
179
+
180
+ CommandSetInputName command{};
181
+ if (HasArg(info, 0)) {
182
+ if (!info[0].IsString()) {
183
+ return RejectTypeError(
184
+ env, "setInputName(inputName?): inputName must be a string",
185
+ "setInputName");
186
+ }
187
+
188
+ command.input_name = info[0].As<Napi::String>().Utf8Value();
189
+ }
190
+
191
+ return _worker_thread.Enqueue(command);
192
+ }
193
+
194
+ Napi::Value TesseractWrapper::GetInputName(const Napi::CallbackInfo &info) {
195
+ return _worker_thread.Enqueue(CommandGetInputName{});
196
+ }
197
+
198
+ Napi::Value TesseractWrapper::SetInputImage(const Napi::CallbackInfo &info) {
199
+ Napi::Env env = info.Env();
200
+
201
+ if (info.Length() > 1) {
202
+ return RejectTypeError(
203
+ env, "setInputImage(buffer?): expected at most 1 argument",
204
+ "setInputImage");
205
+ }
206
+
207
+ CommandSetInputImage command{};
208
+ if (HasArg(info, 0)) {
209
+ if (!info[0].IsBuffer()) {
210
+ return RejectTypeError(env,
211
+ "setInputImage(buffer?): buffer must be a Buffer",
212
+ "setInputImage");
213
+ }
214
+
215
+ Napi::Buffer<uint8_t> image_buffer = info[0].As<Napi::Buffer<uint8_t>>();
216
+ const uint8_t *data = image_buffer.Data();
217
+ const size_t length = image_buffer.Length();
218
+
219
+ if (length == 0) {
220
+ return RejectTypeError(env, "setInputImage(buffer?): buffer is empty",
221
+ "setInputImage");
222
+ }
223
+
224
+ command.bytes.assign(data, data + length);
225
+ }
226
+
227
+ return _worker_thread.Enqueue(command);
228
+ }
229
+
230
+ Napi::Value TesseractWrapper::GetInputImage(const Napi::CallbackInfo &info) {
231
+ Napi::Env env = info.Env();
232
+
233
+ if (info.Length() > 0) {
234
+ return RejectTypeError(env, "getInputImage(): expected no arguments",
235
+ "getInputImage");
236
+ }
237
+
238
+ return _worker_thread.Enqueue(CommandGetInputImage{});
239
+ }
240
+
241
+ Napi::Value
242
+ TesseractWrapper::GetSourceYResolution(const Napi::CallbackInfo &info) {
243
+ Napi::Env env = info.Env();
244
+
245
+ if (info.Length() > 0) {
246
+ return RejectTypeError(env, "getSourceYResolution(): expected no arguments",
247
+ "getSourceYResolution");
248
+ }
249
+
250
+ return _worker_thread.Enqueue(CommandGetSourceYResolution{});
251
+ }
252
+
253
+ Napi::Value TesseractWrapper::GetDataPath(const Napi::CallbackInfo &info) {
254
+ Napi::Env env = info.Env();
255
+
256
+ if (info.Length() > 0) {
257
+ return RejectTypeError(env, "getDataPath(): expected no arguments",
258
+ "getDataPath");
259
+ }
260
+
261
+ return _worker_thread.Enqueue(CommandGetDataPath{});
262
+ }
263
+
264
+ Napi::Value TesseractWrapper::SetOutputName(const Napi::CallbackInfo &info) {
265
+ Napi::Env env = info.Env();
266
+ CommandSetOutputName command{};
267
+
268
+ if (info.Length() != 1 || !info[0].IsString()) {
269
+ return RejectTypeError(
270
+ env, "setOutputName(outputName): outputName must be a string",
271
+ "setOutputName");
272
+ }
273
+
274
+ command.output_name = info[0].As<Napi::String>().Utf8Value();
275
+ return _worker_thread.Enqueue(command);
276
+ }
277
+
278
+ Napi::Value
279
+ TesseractWrapper::ClearPersistentCache(const Napi::CallbackInfo &info) {
280
+ Napi::Env env = info.Env();
281
+
282
+ if (info.Length() > 0) {
283
+ return RejectTypeError(env, "clearPersistentCache(): expected no arguments",
284
+ "clearPersistentCache");
285
+ }
286
+
287
+ return _worker_thread.Enqueue(CommandClearPersistentCache{});
288
+ }
289
+
290
+ Napi::Value
291
+ TesseractWrapper::ClearAdaptiveClassifier(const Napi::CallbackInfo &info) {
292
+ Napi::Env env = info.Env();
293
+
294
+ if (info.Length() > 0) {
295
+ return RejectTypeError(env,
296
+ "clearAdaptiveClassifier(): expected no arguments",
297
+ "clearAdaptiveClassifier");
298
+ }
299
+
300
+ return _worker_thread.Enqueue(CommandClearAdaptiveClassifier{});
301
+ }
302
+
303
+ Napi::Value
304
+ TesseractWrapper::GetThresholdedImage(const Napi::CallbackInfo &info) {
305
+ Napi::Env env = info.Env();
306
+
307
+ if (info.Length() > 0) {
308
+ return RejectTypeError(env, "getThresholdedImage(): expected no arguments",
309
+ "getThresholdedImage");
310
+ }
311
+
312
+ return _worker_thread.Enqueue(CommandGetThresholdedImage{});
313
+ }
314
+
315
+ Napi::Value TesseractWrapper::GetThresholdedImageScaleFactor(
316
+ const Napi::CallbackInfo &info) {
317
+ Napi::Env env = info.Env();
318
+
319
+ if (info.Length() > 0) {
320
+ return RejectTypeError(
321
+ env, "getThresholdedImageScaleFactor(): expected no arguments",
322
+ "getThresholdedImageScaleFactor");
323
+ }
324
+
325
+ return _worker_thread.Enqueue(CommandGetThresholdedImageScaleFactor{});
326
+ }
327
+
82
328
  Napi::Value TesseractWrapper::Init(const Napi::CallbackInfo &info) {
83
329
  Napi::Env env = info.Env();
84
- Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New(env);
85
330
 
86
331
  if (info.Length() != 1 || !info[0].IsObject()) {
87
- deferred.Reject(
88
- Napi::TypeError::New(
89
- env, "Expected required argument at index 0 to be of type object")
90
- .Value());
91
- return deferred.Promise();
332
+ return RejectTypeError(
333
+ env, "init(options): required argument at index 0 must be an object",
334
+ "init");
92
335
  }
93
336
 
94
337
  auto options = info[0].As<Napi::Object>();
@@ -97,10 +340,8 @@ Napi::Value TesseractWrapper::Init(const Napi::CallbackInfo &info) {
97
340
  const Napi::Value dataPathOption = options.Get("dataPath");
98
341
  if (!dataPathOption.IsUndefined()) {
99
342
  if (!dataPathOption.IsString()) {
100
- deferred.Reject(
101
- Napi::TypeError::New(env, "Option 'dataPath' must be a string")
102
- .Value());
103
- return deferred.Promise();
343
+ return RejectTypeError(
344
+ env, "init(options): options.dataPath must be a string", "init");
104
345
  }
105
346
 
106
347
  Napi::String dataPath = dataPathOption.As<Napi::String>();
@@ -110,10 +351,9 @@ Napi::Value TesseractWrapper::Init(const Napi::CallbackInfo &info) {
110
351
  const Napi::Value langsOption = options.Get("langs");
111
352
  if (!langsOption.IsUndefined()) {
112
353
  if (!langsOption.IsArray()) {
113
- deferred.Reject(
114
- Napi::TypeError::New(env, "Option 'langs' must be a array of strings")
115
- .Value());
116
- return deferred.Promise();
354
+ return RejectTypeError(
355
+ env, "init(options): options.langs must be an array of strings",
356
+ "init");
117
357
  }
118
358
 
119
359
  Napi::Array languages = langsOption.As<Napi::Array>();
@@ -133,18 +373,15 @@ Napi::Value TesseractWrapper::Init(const Napi::CallbackInfo &info) {
133
373
  const Napi::Value engineModeOption = options.Get("oem");
134
374
  if (!engineModeOption.IsUndefined()) {
135
375
  if (!engineModeOption.IsNumber()) {
136
- deferred.Reject(
137
- Napi::TypeError::New(env, "Option 'oem' must be of type number")
138
- .Value());
139
- return deferred.Promise();
376
+ return RejectTypeError(env, "init(options): options.oem must be a number",
377
+ "init");
140
378
  }
141
379
  tesseract::OcrEngineMode oem = static_cast<tesseract::OcrEngineMode>(
142
380
  engineModeOption.As<Napi::Number>().Int32Value());
143
381
 
144
382
  if (oem < 0 || oem >= tesseract::OEM_COUNT) {
145
- deferred.Reject(
146
- Napi::TypeError::New(env, "Unsupported OCR Engine Mode").Value());
147
- return deferred.Promise();
383
+ return RejectRangeError(
384
+ env, "init(options): options.oem is out of supported range", "init");
148
385
  }
149
386
 
150
387
  command.oem = oem;
@@ -154,11 +391,9 @@ Napi::Value TesseractWrapper::Init(const Napi::CallbackInfo &info) {
154
391
  options.Get("setOnlyNonDebugParams");
155
392
  if (!set_only_non_debug_params.IsUndefined()) {
156
393
  if (!set_only_non_debug_params.IsBoolean()) {
157
- deferred.Reject(
158
- Napi::TypeError::New(
159
- env, "Option 'setOnlyNonDebugParams' must be of type boolean")
160
- .Value());
161
- return deferred.Promise();
394
+ return RejectTypeError(
395
+ env, "init(options): options.setOnlyNonDebugParams must be a boolean",
396
+ "init");
162
397
  }
163
398
 
164
399
  command.set_only_non_debug_params =
@@ -168,10 +403,9 @@ Napi::Value TesseractWrapper::Init(const Napi::CallbackInfo &info) {
168
403
  const Napi::Value v = options.Get("configs");
169
404
  if (!v.IsUndefined()) {
170
405
  if (!v.IsArray()) {
171
- deferred.Reject(Napi::TypeError::New(
172
- env, "Option 'configs' must be an array of strings")
173
- .Value());
174
- return deferred.Promise();
406
+ return RejectTypeError(
407
+ env, "init(options): options.configs must be an array of strings",
408
+ "init");
175
409
  }
176
410
 
177
411
  Napi::Array arr = v.As<Napi::Array>();
@@ -183,10 +417,9 @@ Napi::Value TesseractWrapper::Init(const Napi::CallbackInfo &info) {
183
417
  for (uint32_t i = 0; i < len; ++i) {
184
418
  Napi::Value item = arr.Get(i);
185
419
  if (!item.IsString()) {
186
- deferred.Reject(Napi::TypeError::New(
187
- env, "Option 'configs' must contain only strings")
188
- .Value());
189
- return deferred.Promise();
420
+ return RejectTypeError(
421
+ env, "init(options): options.configs must contain only strings",
422
+ "init");
190
423
  }
191
424
  command.configs_storage.emplace_back(item.As<Napi::String>().Utf8Value());
192
425
  }
@@ -201,10 +434,8 @@ Napi::Value TesseractWrapper::Init(const Napi::CallbackInfo &info) {
201
434
 
202
435
  if (!varsOption.IsUndefined()) {
203
436
  if (!varsOption.IsObject()) {
204
- deferred.Reject(
205
- Napi::TypeError::New(env, "Options 'vars' must be of type object")
206
- .Value());
207
- return deferred.Promise();
437
+ return RejectTypeError(
438
+ env, "init(options): options.vars must be an object", "init");
208
439
  }
209
440
 
210
441
  // Napi::Array a = vars_vec.As<Napi::Array>();
@@ -219,10 +450,9 @@ Napi::Value TesseractWrapper::Init(const Napi::CallbackInfo &info) {
219
450
  for (uint32_t i = 0; i < length; ++i) {
220
451
  Napi::Value variable_value = vars.Get(variable_names.Get(i));
221
452
  if (!variable_names.Get(i).IsString() || !variable_value.IsString()) {
222
- deferred.Reject(
223
- Napi::TypeError::New(env, "'vars' must contain only strings")
224
- .Value());
225
- return deferred.Promise();
453
+ return RejectTypeError(
454
+ env, "init(options): options.vars must contain only strings",
455
+ "init");
226
456
  }
227
457
  command.vars_vec.emplace_back(
228
458
  variable_names.Get(i).As<Napi::String>().Utf8Value());
@@ -239,22 +469,22 @@ TesseractWrapper::InitForAnalysePage(const Napi::CallbackInfo &info) {
239
469
  return _worker_thread.Enqueue(CommandInitForAnalysePage{});
240
470
  }
241
471
 
242
- Napi::Value TesseractWrapper::AnalysePage(const Napi::CallbackInfo &info) {
472
+ Napi::Value TesseractWrapper::AnalyseLayout(const Napi::CallbackInfo &info) {
243
473
  Napi::Env env = info.Env();
244
- Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New(env);
245
474
  CommandAnalyseLayout command{};
246
475
 
247
476
  if (info.Length() > 1) {
248
- deferred.Reject(Napi::Error::New(env, "Too many arguments").Value());
249
- return deferred.Promise();
477
+ return RejectTypeError(
478
+ env, "analyseLayout(mergeSimilarWords?): expected at most 1 argument",
479
+ "analyseLayout");
250
480
  }
251
481
 
252
- if (!info[0].IsUndefined()) {
482
+ if (HasArg(info, 0)) {
253
483
  if (!info[0].IsBoolean()) {
254
- deferred.Reject(
255
- Napi::Error::New(env, "Expected argument to be of type boolean")
256
- .Value());
257
- return deferred.Promise();
484
+ return RejectTypeError(env,
485
+ "analyseLayout(mergeSimilarWords?): "
486
+ "mergeSimilarWords must be a boolean",
487
+ "analyseLayout");
258
488
  }
259
489
 
260
490
  command.merge_similar_words = info[0].As<Napi::Boolean>().Value();
@@ -263,38 +493,174 @@ Napi::Value TesseractWrapper::AnalysePage(const Napi::CallbackInfo &info) {
263
493
  return _worker_thread.Enqueue(command);
264
494
  }
265
495
 
266
- Napi::Value TesseractWrapper::SetPageMode(const Napi::CallbackInfo &info) {
496
+ Napi::Value
497
+ TesseractWrapper::BeginProcessPages(const Napi::CallbackInfo &info) {
267
498
  Napi::Env env = info.Env();
268
- Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New(env);
269
- CommandSetPageMode command{};
499
+ CommandBeginProcessPages command{};
270
500
 
271
- if (info.Length() > 1) {
272
- deferred.Reject(
273
- Napi::Error::New(env, "Expected only one parameter").Value());
274
- return deferred.Promise();
501
+ if (info.Length() != 1 || !info[0].IsObject()) {
502
+ return RejectTypeError(
503
+ env, "beginProcessPages(options): options must be an object",
504
+ "beginProcessPages");
275
505
  }
276
506
 
277
- if (!info[0].IsUndefined()) {
278
- if (!info[0].IsNumber()) {
279
- deferred.Reject(
280
- Napi::Error::New(
281
- env, "Expected page segmentation mode to be of type number")
282
- .Value());
283
- return deferred.Promise();
507
+ Napi::Object options = info[0].As<Napi::Object>();
508
+
509
+ Napi::Value output_base = options.Get("outputBase");
510
+ if (!output_base.IsUndefined()) {
511
+ if (!output_base.IsString()) {
512
+ return RejectTypeError(
513
+ env,
514
+ "beginProcessPages(options): options.outputBase must be a string",
515
+ "beginProcessPages");
284
516
  }
517
+ command.output_base = output_base.As<Napi::String>().Utf8Value();
518
+ }
285
519
 
286
- tesseract::PageSegMode psm = static_cast<tesseract::PageSegMode>(
287
- info[0].As<Napi::Number>().Int32Value());
520
+ Napi::Value title = options.Get("title");
521
+ if (title.IsUndefined() || !title.IsString()) {
522
+ return RejectTypeError(env,
523
+ "beginProcessPages(options): options.title is "
524
+ "required and must be a string",
525
+ "beginProcessPages");
526
+ }
527
+ command.title = title.As<Napi::String>().Utf8Value();
528
+
529
+ Napi::Value timeout = options.Get("timeout");
530
+ if (!timeout.IsUndefined()) {
531
+ if (!timeout.IsNumber()) {
532
+ return RejectTypeError(
533
+ env, "beginProcessPages(options): options.timeout must be a number",
534
+ "beginProcessPages");
535
+ }
536
+ command.timeout_millisec = timeout.As<Napi::Number>().Int32Value();
537
+ }
288
538
 
289
- if (psm < 0 || psm >= tesseract::PageSegMode::PSM_COUNT) {
290
- deferred.Reject(
291
- Napi::Error::New(env, "Page Segmentation Mode out of range").Value());
292
- return deferred.Promise();
539
+ Napi::Value textonly = options.Get("textonly");
540
+ if (!textonly.IsUndefined()) {
541
+ if (!textonly.IsBoolean()) {
542
+ return RejectTypeError(
543
+ env, "beginProcessPages(options): options.textonly must be a boolean",
544
+ "beginProcessPages");
293
545
  }
546
+ command.textonly = textonly.As<Napi::Boolean>().Value();
547
+ }
294
548
 
295
- command.psm = psm;
549
+ return _worker_thread.Enqueue(std::move(command));
550
+ }
551
+
552
+ Napi::Value TesseractWrapper::AddProcessPage(const Napi::CallbackInfo &info) {
553
+ Napi::Env env = info.Env();
554
+ CommandAddProcessPage command{};
555
+
556
+ if (info.Length() != 1 || !info[0].IsObject()) {
557
+ return RejectTypeError(env,
558
+ "addProcessPage(options): options must be an object",
559
+ "addProcessPage");
560
+ }
561
+
562
+ Napi::Object options = info[0].As<Napi::Object>();
563
+
564
+ Napi::Value buffer_value = options.Get("buffer");
565
+ if (!buffer_value.IsBuffer()) {
566
+ return RejectTypeError(
567
+ env, "addProcessPage(options): options.buffer must be a Buffer",
568
+ "addProcessPage");
296
569
  }
297
570
 
571
+ Napi::Buffer<uint8_t> page_buffer = buffer_value.As<Napi::Buffer<uint8_t>>();
572
+ const size_t length = page_buffer.Length();
573
+ if (length == 0) {
574
+ return RejectTypeError(env,
575
+ "addProcessPage(options): options.buffer is empty",
576
+ "addProcessPage");
577
+ }
578
+
579
+ Napi::Value filename_value = options.Get("filename");
580
+ if (!filename_value.IsUndefined() && !filename_value.IsNull()) {
581
+ if (!filename_value.IsString()) {
582
+ return RejectTypeError(
583
+ env, "addProcessPage(options): options.filename must be a string",
584
+ "addProcessPage");
585
+ }
586
+ command.filename = filename_value.As<Napi::String>().Utf8Value();
587
+ }
588
+
589
+ Napi::Value progress_callback_value = options.Get("progressCallback");
590
+ if (!progress_callback_value.IsUndefined() &&
591
+ !progress_callback_value.IsNull()) {
592
+ if (!progress_callback_value.IsFunction()) {
593
+ return RejectTypeError(env,
594
+ "addProcessPage(options): "
595
+ "options.progressCallback must be a function",
596
+ "addProcessPage");
597
+ }
598
+
599
+ Napi::Function progress_callback =
600
+ progress_callback_value.As<Napi::Function>();
601
+ Napi::ThreadSafeFunction progress_tsfn = Napi::ThreadSafeFunction::New(
602
+ env, progress_callback, "tesseract_progress_callback", 0, 1);
603
+ command.monitor_context =
604
+ std::make_shared<MonitorContext>(std::move(progress_tsfn));
605
+ }
606
+
607
+ command.page.bytes.resize(length);
608
+ std::memcpy(command.page.bytes.data(), page_buffer.Data(), length);
609
+
610
+ return _worker_thread.Enqueue(std::move(command));
611
+ }
612
+
613
+ Napi::Value
614
+ TesseractWrapper::FinishProcessPages(const Napi::CallbackInfo &info) {
615
+ return _worker_thread.Enqueue(CommandFinishProcessPages{});
616
+ }
617
+
618
+ Napi::Value
619
+ TesseractWrapper::AbortProcessPages(const Napi::CallbackInfo &info) {
620
+ CommandAbortProcessPages command{};
621
+ if (info.Length() > 0 && info[0].IsString()) {
622
+ command.reason = info[0].As<Napi::String>().Utf8Value();
623
+ }
624
+ return _worker_thread.Enqueue(std::move(command));
625
+ }
626
+
627
+ Napi::Value
628
+ TesseractWrapper::GetProcessPagesStatus(const Napi::CallbackInfo &info) {
629
+ Napi::Env env = info.Env();
630
+
631
+ if (info.Length() > 0) {
632
+ return RejectTypeError(env,
633
+ "getProcessPagesStatus(): expected no arguments",
634
+ "getProcessPagesStatus");
635
+ }
636
+
637
+ return _worker_thread.Enqueue(CommandGetProcessPagesStatus{});
638
+ }
639
+
640
+ Napi::Value TesseractWrapper::SetDebugVariable(const Napi::CallbackInfo &info) {
641
+ Napi::Env env = info.Env();
642
+ CommandSetDebugVariable command{};
643
+
644
+ if (info.Length() != 2) {
645
+ return RejectTypeError(
646
+ env, "setDebugVariable(name, value): expected exactly 2 arguments",
647
+ "setDebugVariable");
648
+ }
649
+
650
+ if (!info[0].IsString()) {
651
+ return RejectTypeError(
652
+ env, "setDebugVariable(name, value): name must be a string",
653
+ "setDebugVariable");
654
+ }
655
+ if (!info[1].IsString()) {
656
+ return RejectTypeError(
657
+ env, "setDebugVariable(name, value): value must be a string",
658
+ "setDebugVariable");
659
+ }
660
+
661
+ command.name = info[0].As<Napi::String>().Utf8Value();
662
+ command.value = info[1].As<Napi::String>().Utf8Value();
663
+
298
664
  return _worker_thread.Enqueue(command);
299
665
  }
300
666
 
@@ -302,23 +668,19 @@ Napi::Value TesseractWrapper::SetVariable(const Napi::CallbackInfo &info) {
302
668
  Napi::Env env = info.Env();
303
669
  CommandSetVariable command{};
304
670
 
305
- Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New(env);
306
-
307
671
  if (info.Length() != 2) {
308
- deferred.Reject(Napi::Error::New(env, "Expected two arguments").Value());
309
- return deferred.Promise();
672
+ return RejectTypeError(
673
+ env, "setVariable(name, value): expected exactly 2 arguments",
674
+ "setVariable");
310
675
  }
311
676
 
312
677
  if (!info[0].IsString()) {
313
- deferred.Reject(
314
- Napi::Error::New(env, "Expected variable name to be a string").Value());
315
- return deferred.Promise();
678
+ return RejectTypeError(
679
+ env, "setVariable(name, value): name must be a string", "setVariable");
316
680
  }
317
681
  if (!info[1].IsString()) {
318
- return deferred.Reject(
319
- Napi::Error::New(env, "Variable value must be a string")
320
- .Value()),
321
- deferred.Promise();
682
+ return RejectTypeError(
683
+ env, "setVariable(name, value): value must be a string", "setVariable");
322
684
  }
323
685
 
324
686
  const std::string variable_name = info[0].As<Napi::String>().Utf8Value();
@@ -332,22 +694,17 @@ Napi::Value TesseractWrapper::SetVariable(const Napi::CallbackInfo &info) {
332
694
 
333
695
  Napi::Value TesseractWrapper::GetIntVariable(const Napi::CallbackInfo &info) {
334
696
  Napi::Env env = info.Env();
335
- Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New(env);
336
697
  CommandGetIntVariable command{};
337
698
 
338
699
  if (info.Length() != 1) {
339
- deferred.Reject(
340
- Napi::Error::New(env,
341
- "GetIntVariable(name): exactly 1 argument required")
342
- .Value());
343
- return deferred.Promise();
700
+ return RejectTypeError(env,
701
+ "getIntVariable(name): expected exactly 1 argument",
702
+ "getIntVariable");
344
703
  }
345
704
 
346
705
  if (!info[0].IsString()) {
347
- deferred.Reject(
348
- Napi::Error::New(env, "GetIntVariable(name): name must be a string")
349
- .Value());
350
- return deferred.Promise();
706
+ return RejectTypeError(env, "getIntVariable(name): name must be a string",
707
+ "getIntVariable");
351
708
  }
352
709
 
353
710
  std::string name = info[0].As<Napi::String>().Utf8Value();
@@ -358,22 +715,17 @@ Napi::Value TesseractWrapper::GetIntVariable(const Napi::CallbackInfo &info) {
358
715
 
359
716
  Napi::Value TesseractWrapper::GetBoolVariable(const Napi::CallbackInfo &info) {
360
717
  Napi::Env env = info.Env();
361
- Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New(env);
362
718
  CommandGetBoolVariable command{};
363
719
 
364
720
  if (info.Length() != 1) {
365
- deferred.Reject(
366
- Napi::Error::New(env,
367
- "GetIntVariable(name): exactly 1 argument required")
368
- .Value());
369
- return deferred.Promise();
721
+ return RejectTypeError(env,
722
+ "getBoolVariable(name): expected exactly 1 argument",
723
+ "getBoolVariable");
370
724
  }
371
725
 
372
726
  if (!info[0].IsString()) {
373
- deferred.Reject(
374
- Napi::Error::New(env, "GetIntVariable(name): name must be a string")
375
- .Value());
376
- return deferred.Promise();
727
+ return RejectTypeError(env, "getBoolVariable(name): name must be a string",
728
+ "getBoolVariable");
377
729
  }
378
730
 
379
731
  std::string name = info[0].As<Napi::String>().Utf8Value();
@@ -385,22 +737,18 @@ Napi::Value TesseractWrapper::GetBoolVariable(const Napi::CallbackInfo &info) {
385
737
  Napi::Value
386
738
  TesseractWrapper::GetDoubleVariable(const Napi::CallbackInfo &info) {
387
739
  Napi::Env env = info.Env();
388
- Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New(env);
389
740
  CommandGetDoubleVariable command{};
390
741
 
391
742
  if (info.Length() != 1) {
392
- deferred.Reject(
393
- Napi::Error::New(env,
394
- "GetIntVariable(name): exactly 1 argument required")
395
- .Value());
396
- return deferred.Promise();
743
+ return RejectTypeError(
744
+ env, "getDoubleVariable(name): expected exactly 1 argument",
745
+ "getDoubleVariable");
397
746
  }
398
747
 
399
748
  if (!info[0].IsString()) {
400
- deferred.Reject(
401
- Napi::Error::New(env, "GetIntVariable(name): name must be a string")
402
- .Value());
403
- return deferred.Promise();
749
+ return RejectTypeError(env,
750
+ "getDoubleVariable(name): name must be a string",
751
+ "getDoubleVariable");
404
752
  }
405
753
 
406
754
  std::string name = info[0].As<Napi::String>().Utf8Value();
@@ -412,22 +760,18 @@ TesseractWrapper::GetDoubleVariable(const Napi::CallbackInfo &info) {
412
760
  Napi::Value
413
761
  TesseractWrapper::GetStringVariable(const Napi::CallbackInfo &info) {
414
762
  Napi::Env env = info.Env();
415
- Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New(env);
416
763
  CommandGetStringVariable command{};
417
764
 
418
765
  if (info.Length() != 1) {
419
- deferred.Reject(
420
- Napi::Error::New(env,
421
- "GetIntVariable(name): exactly 1 argument required")
422
- .Value());
423
- return deferred.Promise();
766
+ return RejectTypeError(
767
+ env, "getStringVariable(name): expected exactly 1 argument",
768
+ "getStringVariable");
424
769
  }
425
770
 
426
771
  if (!info[0].IsString()) {
427
- deferred.Reject(
428
- Napi::Error::New(env, "GetIntVariable(name): name must be a string")
429
- .Value());
430
- return deferred.Promise();
772
+ return RejectTypeError(env,
773
+ "getStringVariable(name): name must be a string",
774
+ "getStringVariable");
431
775
  }
432
776
 
433
777
  std::string name = info[0].As<Napi::String>().Utf8Value();
@@ -438,13 +782,11 @@ TesseractWrapper::GetStringVariable(const Napi::CallbackInfo &info) {
438
782
 
439
783
  Napi::Value TesseractWrapper::SetImage(const Napi::CallbackInfo &info) {
440
784
  Napi::Env env = info.Env();
441
- Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New(env);
442
785
  CommandSetImage command{};
443
786
 
444
787
  if (info.Length() < 1 || !info[0].IsBuffer()) {
445
- deferred.Reject(
446
- Napi::Error::New(env, "SetImage(buffer): buffer required").Value());
447
- return deferred.Promise();
788
+ return RejectTypeError(env, "setImage(buffer): buffer argument is required",
789
+ "setImage");
448
790
  }
449
791
 
450
792
  Napi::Buffer<uint8_t> image_buffer = info[0].As<Napi::Buffer<uint8_t>>();
@@ -452,16 +794,14 @@ Napi::Value TesseractWrapper::SetImage(const Napi::CallbackInfo &info) {
452
794
  const size_t length = image_buffer.Length();
453
795
 
454
796
  if (length == 0) {
455
- deferred.Reject(Napi::Error::New(env, "SetImage: buffer is empty").Value());
456
- return deferred.Promise();
797
+ return RejectTypeError(env, "setImage(buffer): buffer is empty",
798
+ "setImage");
457
799
  }
458
800
 
459
801
  Pix *pix = pixReadMem(data, length);
460
802
  if (!pix) {
461
- deferred.Reject(
462
- Napi::Error::New(env, "SetImage: failed to decode image buffer")
463
- .Value());
464
- return deferred.Promise();
803
+ return RejectError(env, "setImage(buffer): failed to decode image buffer",
804
+ "setImage");
465
805
  }
466
806
 
467
807
  Pix *normalized = pix;
@@ -499,9 +839,8 @@ Napi::Value TesseractWrapper::SetImage(const Napi::CallbackInfo &info) {
499
839
  pixDestroy(&normalized);
500
840
  }
501
841
  pixDestroy(&pix);
502
- deferred.Reject(
503
- Napi::Error::New(env, "SetImage: invalid decoded image data").Value());
504
- return deferred.Promise();
842
+ return RejectError(env, "setImage(buffer): invalid decoded image data",
843
+ "setImage");
505
844
  }
506
845
 
507
846
  command.width = width;
@@ -519,16 +858,43 @@ Napi::Value TesseractWrapper::SetImage(const Napi::CallbackInfo &info) {
519
858
  return _worker_thread.Enqueue(command);
520
859
  }
521
860
 
861
+ Napi::Value TesseractWrapper::SetPageMode(const Napi::CallbackInfo &info) {
862
+ Napi::Env env = info.Env();
863
+ CommandSetPageMode command{};
864
+
865
+ if (info.Length() > 1) {
866
+ return RejectTypeError(
867
+ env, "setPageMode(psm?): expected at most 1 argument", "setPageMode");
868
+ }
869
+
870
+ if (HasArg(info, 0)) {
871
+ if (!info[0].IsNumber()) {
872
+ return RejectTypeError(env, "setPageMode(psm?): psm must be a number",
873
+ "setPageMode");
874
+ }
875
+
876
+ tesseract::PageSegMode psm = static_cast<tesseract::PageSegMode>(
877
+ info[0].As<Napi::Number>().Int32Value());
878
+
879
+ if (psm < 0 || psm >= tesseract::PageSegMode::PSM_COUNT) {
880
+ return RejectRangeError(env, "setPageMode(psm?): psm is out of range",
881
+ "setPageMode");
882
+ }
883
+
884
+ command.psm = psm;
885
+ }
886
+
887
+ return _worker_thread.Enqueue(command);
888
+ }
889
+
522
890
  Napi::Value TesseractWrapper::SetRectangle(const Napi::CallbackInfo &info) {
523
891
  Napi::Env env = info.Env();
524
- Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New(env);
525
892
  CommandSetRectangle command{};
526
893
 
527
894
  if (info.Length() != 1 || !info[0].IsObject()) {
528
- deferred.Reject(
529
- Napi::Error::New(env, "Expected first argument to be a object")
530
- .Value());
531
- return deferred.Promise();
895
+ return RejectTypeError(
896
+ env, "setRectangle(rectangle): rectangle must be an object",
897
+ "setRectangle");
532
898
  }
533
899
 
534
900
  Napi::Object rectangle = info[0].As<Napi::Object>();
@@ -540,11 +906,10 @@ Napi::Value TesseractWrapper::SetRectangle(const Napi::CallbackInfo &info) {
540
906
 
541
907
  if (!maybe_left.IsNumber() || !maybe_top.IsNumber() ||
542
908
  !maybe_width.IsNumber() || !maybe_height.IsNumber()) {
543
- deferred.Reject(
544
- Napi::Error::New(env,
545
- "SetRectangle: missing property in rectangle object")
546
- .Value());
547
- return deferred.Promise();
909
+ return RejectTypeError(env,
910
+ "setRectangle(rectangle): "
911
+ "rectangle.left/top/width/height must be numbers",
912
+ "setRectangle");
548
913
  }
549
914
 
550
915
  int32_t left = maybe_left.As<Napi::Number>().Int32Value();
@@ -563,19 +928,18 @@ Napi::Value TesseractWrapper::SetRectangle(const Napi::CallbackInfo &info) {
563
928
  Napi::Value
564
929
  TesseractWrapper::SetSourceResolution(const Napi::CallbackInfo &info) {
565
930
  Napi::Env env = info.Env();
566
- Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New(env);
567
931
  CommandSetSourceResolution command{};
568
932
 
569
- if (info.Length() > 1) {
570
- deferred.Reject(
571
- Napi::Error::New(env, "Expected only one parameter").Value());
572
- return deferred.Promise();
933
+ if (info.Length() != 1) {
934
+ return RejectTypeError(
935
+ env, "setSourceResolution(ppi): expected exactly 1 argument",
936
+ "setSourceResolution");
573
937
  }
574
938
 
575
939
  if (!info[0].IsNumber()) {
576
- deferred.Reject(
577
- Napi::Error::New(env, "Expected ppi to be of type number").Value());
578
- return deferred.Promise();
940
+ return RejectTypeError(env,
941
+ "setSourceResolution(ppi): ppi must be a number",
942
+ "setSourceResolution");
579
943
  }
580
944
 
581
945
  int ppi = info[0].As<Napi::Number>().Int32Value();
@@ -587,16 +951,14 @@ TesseractWrapper::SetSourceResolution(const Napi::CallbackInfo &info) {
587
951
 
588
952
  Napi::Value TesseractWrapper::Recognize(const Napi::CallbackInfo &info) {
589
953
  Napi::Env env = info.Env();
590
- Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New(env);
591
954
  CommandRecognize command{};
592
955
 
593
- if (!info[0].IsUndefined()) {
956
+ if (HasArg(info, 0)) {
594
957
  if (!info[0].IsFunction()) {
595
- deferred.Reject(
596
- Napi::Error::New(env,
597
- "Expected progress callback to be of type function")
598
- .Value());
599
- return deferred.Promise();
958
+ return RejectTypeError(
959
+ env,
960
+ "recognize(progressCallback?): progressCallback must be a function",
961
+ "recognize");
600
962
  }
601
963
 
602
964
  Napi::Function progress_callback = info[0].As<Napi::Function>();
@@ -619,22 +981,129 @@ Napi::Value TesseractWrapper::MeanTextConf(const Napi::CallbackInfo &info) {
619
981
  return _worker_thread.Enqueue(CommandMeanTextConf{});
620
982
  }
621
983
 
984
+ Napi::Value
985
+ TesseractWrapper::AllWordConfidences(const Napi::CallbackInfo &info) {
986
+ return _worker_thread.Enqueue(CommandAllWordConfidences{});
987
+ }
988
+
989
+ Napi::Value TesseractWrapper::GetPAGEText(const Napi::CallbackInfo &info) {
990
+ Napi::Env env = info.Env();
991
+ CommandGetPAGEText command{};
992
+ command.page_number = 0;
993
+
994
+ if (HasArg(info, 0)) {
995
+ if (!info[0].IsFunction()) {
996
+ return RejectTypeError(env,
997
+ "getPAGEText(progressCallback?, pageNumber?): "
998
+ "progressCallback must be a function",
999
+ "getPAGEText");
1000
+ }
1001
+
1002
+ Napi::Function progress_callback = info[0].As<Napi::Function>();
1003
+ Napi::ThreadSafeFunction progress_tsfn = Napi::ThreadSafeFunction::New(
1004
+ env, progress_callback, "tesseract_progress_callback", 0, 1);
1005
+
1006
+ command.monitor_context =
1007
+ std::make_shared<MonitorContext>(std::move(progress_tsfn));
1008
+ }
1009
+
1010
+ if (HasArg(info, 1)) {
1011
+ if (!info[1].IsNumber()) {
1012
+ return RejectTypeError(env,
1013
+ "getPAGEText(progressCallback?, pageNumber?): "
1014
+ "pageNumber must be a number",
1015
+ "getPAGEText");
1016
+ }
1017
+
1018
+ command.page_number = info[1].As<Napi::Number>().Int32Value();
1019
+ }
1020
+
1021
+ return _worker_thread.Enqueue(command);
1022
+ }
1023
+
1024
+ Napi::Value TesseractWrapper::GetLSTMBoxText(const Napi::CallbackInfo &info) {
1025
+ Napi::Env env = info.Env();
1026
+ CommandGetLSTMBoxText command{};
1027
+ command.page_number = 0;
1028
+
1029
+ if (HasArg(info, 0)) {
1030
+ if (!info[0].IsNumber()) {
1031
+ return RejectTypeError(
1032
+ env, "getLSTMBoxText(pageNumber?): pageNumber must be a number",
1033
+ "getLSTMBoxText");
1034
+ }
1035
+ command.page_number = info[0].As<Napi::Number>().Int32Value();
1036
+ }
1037
+
1038
+ return _worker_thread.Enqueue(command);
1039
+ }
1040
+
1041
+ Napi::Value TesseractWrapper::GetBoxText(const Napi::CallbackInfo &info) {
1042
+ Napi::Env env = info.Env();
1043
+ CommandGetBoxText command{};
1044
+ command.page_number = 0;
1045
+
1046
+ if (HasArg(info, 0)) {
1047
+ if (!info[0].IsNumber()) {
1048
+ return RejectTypeError(
1049
+ env, "getBoxText(pageNumber?): pageNumber must be a number",
1050
+ "getBoxText");
1051
+ }
1052
+ command.page_number = info[0].As<Napi::Number>().Int32Value();
1053
+ }
1054
+
1055
+ return _worker_thread.Enqueue(command);
1056
+ }
1057
+
1058
+ Napi::Value
1059
+ TesseractWrapper::GetWordStrBoxText(const Napi::CallbackInfo &info) {
1060
+ Napi::Env env = info.Env();
1061
+ CommandGetWordStrBoxText command{};
1062
+ command.page_number = 0;
1063
+
1064
+ if (HasArg(info, 0)) {
1065
+ if (!info[0].IsNumber()) {
1066
+ return RejectTypeError(
1067
+ env, "getWordStrBoxText(pageNumber?): pageNumber must be a number",
1068
+ "getWordStrBoxText");
1069
+ }
1070
+ command.page_number = info[0].As<Napi::Number>().Int32Value();
1071
+ }
1072
+
1073
+ return _worker_thread.Enqueue(command);
1074
+ }
1075
+
1076
+ Napi::Value TesseractWrapper::getOSDText(const Napi::CallbackInfo &info) {
1077
+ Napi::Env env = info.Env();
1078
+ CommandGetOSDText command{};
1079
+ command.page_number = 0;
1080
+
1081
+ if (HasArg(info, 0)) {
1082
+ if (!info[0].IsNumber()) {
1083
+ return RejectTypeError(
1084
+ env, "getOSDText(pageNumber?): pageNumber must be a number",
1085
+ "getOSDText");
1086
+ }
1087
+ command.page_number = info[0].As<Napi::Number>().Int32Value();
1088
+ }
1089
+
1090
+ return _worker_thread.Enqueue(command);
1091
+ }
1092
+
622
1093
  Napi::Value TesseractWrapper::GetUTF8Text(const Napi::CallbackInfo &info) {
623
1094
  return _worker_thread.Enqueue(CommandGetUTF8Text{});
624
1095
  }
625
1096
 
626
1097
  Napi::Value TesseractWrapper::GetHOCRText(const Napi::CallbackInfo &info) {
627
1098
  Napi::Env env = info.Env();
628
- Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New(env);
629
1099
  CommandGetHOCRText command{};
630
1100
 
631
- if (!info[0].IsUndefined()) {
1101
+ if (HasArg(info, 0)) {
632
1102
  if (!info[0].IsFunction()) {
633
- deferred.Reject(
634
- Napi::Error::New(env,
635
- "Expected progress callback to be of type function")
636
- .Value());
637
- return deferred.Promise();
1103
+ return RejectTypeError(env,
1104
+ "getHOCRText(progressCallback?, pageNumber?): "
1105
+ "progressCallback must be a function",
1106
+ "getHOCRText");
638
1107
  }
639
1108
 
640
1109
  Napi::Function progress_callback = info[0].As<Napi::Function>();
@@ -645,12 +1114,12 @@ Napi::Value TesseractWrapper::GetHOCRText(const Napi::CallbackInfo &info) {
645
1114
  std::make_shared<MonitorContext>(std::move(progress_tsfn));
646
1115
  }
647
1116
 
648
- if (!info[1].IsUndefined()) {
1117
+ if (HasArg(info, 1)) {
649
1118
  if (!info[1].IsNumber()) {
650
- deferred.Reject(
651
- Napi::Error::New(env, "Expected page_number to be of type number")
652
- .Value());
653
- return deferred.Promise();
1119
+ return RejectTypeError(env,
1120
+ "getHOCRText(progressCallback?, pageNumber?): "
1121
+ "pageNumber must be a number",
1122
+ "getHOCRText");
654
1123
  }
655
1124
 
656
1125
  int32_t page_number = info[1].As<Napi::Number>().Int32Value();
@@ -662,15 +1131,13 @@ Napi::Value TesseractWrapper::GetHOCRText(const Napi::CallbackInfo &info) {
662
1131
 
663
1132
  Napi::Value TesseractWrapper::GetTSVText(const Napi::CallbackInfo &info) {
664
1133
  Napi::Env env = info.Env();
665
- Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New(env);
666
1134
  CommandGetTSVText command{};
667
1135
 
668
- if (!info[0].IsUndefined()) {
1136
+ if (HasArg(info, 0)) {
669
1137
  if (!info[0].IsNumber()) {
670
- deferred.Reject(
671
- Napi::Error::New(env, "Expected page_number to be of type number")
672
- .Value());
673
- return deferred.Promise();
1138
+ return RejectTypeError(
1139
+ env, "getTSVText(pageNumber?): pageNumber must be a number",
1140
+ "getTSVText");
674
1141
  }
675
1142
 
676
1143
  int32_t page_number = info[0].As<Napi::Number>().Int32Value();
@@ -686,15 +1153,13 @@ Napi::Value TesseractWrapper::GetUNLVText(const Napi::CallbackInfo &info) {
686
1153
 
687
1154
  Napi::Value TesseractWrapper::GetALTOText(const Napi::CallbackInfo &info) {
688
1155
  Napi::Env env = info.Env();
689
- Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New(env);
690
1156
  CommandGetALTOText command{};
691
1157
 
692
- if (!info[0].IsUndefined()) {
1158
+ if (HasArg(info, 0)) {
693
1159
  if (!info[0].IsNumber()) {
694
- deferred.Reject(
695
- Napi::Error::New(env, "Expected page_number to be of type number")
696
- .Value());
697
- return deferred.Promise();
1160
+ return RejectTypeError(
1161
+ env, "getALTOText(pageNumber?): pageNumber must be a number",
1162
+ "getALTOText");
698
1163
  }
699
1164
 
700
1165
  int32_t page_number = info[0].As<Napi::Number>().Int32Value();