tesseract 4.1.1
Loading...
Searching...
No Matches
tesseractmain.cpp
Go to the documentation of this file.
1/**********************************************************************
2 * File: tesseractmain.cpp
3 * Description: Main program for merge of tess and editor.
4 * Author: Ray Smith
5 *
6 * (C) Copyright 1992, Hewlett-Packard Ltd.
7 ** Licensed under the Apache License, Version 2.0 (the "License");
8 ** you may not use this file except in compliance with the License.
9 ** You may obtain a copy of the License at
10 ** http://www.apache.org/licenses/LICENSE-2.0
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 *
17 **********************************************************************/
18
19// Include automatically generated configuration file if running autoconf
20#ifdef HAVE_CONFIG_H
21#include "config_auto.h"
22#endif
23
24#include <cerrno> // for errno
25#include <iostream>
26
27#include "allheaders.h"
28#include "baseapi.h"
29#include "dict.h"
30#if defined(USE_OPENCL)
31#include "openclwrapper.h" // for OpenclDevice
32#endif
33#include "renderer.h"
34#include "simddetect.h"
35#include "tprintf.h" // for tprintf
36
37#ifdef _OPENMP
38#include <omp.h>
39#endif
40
41#if defined(HAVE_LIBARCHIVE)
42#include <archive.h>
43#endif
44
45#if defined(_WIN32)
46#include <fcntl.h>
47#include <io.h>
48#if defined(HAVE_TIFFIO_H)
49
50#include <tiffio.h>
51
52static void Win32ErrorHandler(const char* module, const char* fmt,
53 va_list ap) {
54 if (module != nullptr) {
55 fprintf(stderr, "%s: ", module);
56 }
57 vfprintf(stderr, fmt, ap);
58 fprintf(stderr, ".\n");
59}
60
61static void Win32WarningHandler(const char* module, const char* fmt,
62 va_list ap) {
63 if (module != nullptr) {
64 fprintf(stderr, "%s: ", module);
65 }
66 fprintf(stderr, "Warning, ");
67 vfprintf(stderr, fmt, ap);
68 fprintf(stderr, ".\n");
69}
70
71#endif /* HAVE_TIFFIO_H */
72
73class AutoWin32ConsoleOutputCP {
74 public:
75 explicit AutoWin32ConsoleOutputCP(UINT codeCP) {
76 oldCP_ = GetConsoleOutputCP();
77 SetConsoleOutputCP(codeCP);
78 }
79 ~AutoWin32ConsoleOutputCP() {
80 SetConsoleOutputCP(oldCP_);
81 }
82 private:
83 UINT oldCP_;
84};
85
86static AutoWin32ConsoleOutputCP autoWin32ConsoleOutputCP(CP_UTF8);
87
88#endif // _WIN32
89
90static void PrintVersionInfo() {
91 char* versionStrP;
92
93 printf("tesseract %s\n", tesseract::TessBaseAPI::Version());
94
95 versionStrP = getLeptonicaVersion();
96 printf(" %s\n", versionStrP);
97 lept_free(versionStrP);
98
99 versionStrP = getImagelibVersions();
100 printf(" %s\n", versionStrP);
101 lept_free(versionStrP);
102
103#ifdef USE_OPENCL
104 cl_platform_id platform[4];
105 cl_uint num_platforms;
106
107 printf(" OpenCL info:\n");
108 if (clGetPlatformIDs(4, platform, &num_platforms) == CL_SUCCESS) {
109 printf(" Found %u platform(s).\n", num_platforms);
110 for (unsigned n = 0; n < num_platforms; n++) {
111 char info[256];
112 if (clGetPlatformInfo(platform[n], CL_PLATFORM_NAME, 256, info, 0) ==
113 CL_SUCCESS) {
114 printf(" Platform %u name: %s.\n", n + 1, info);
115 }
116 if (clGetPlatformInfo(platform[n], CL_PLATFORM_VERSION, 256, info, 0) ==
117 CL_SUCCESS) {
118 printf(" Version: %s.\n", info);
119 }
120 cl_device_id devices[2];
121 cl_uint num_devices;
122 if (clGetDeviceIDs(platform[n], CL_DEVICE_TYPE_ALL, 2, devices,
123 &num_devices) == CL_SUCCESS) {
124 printf(" Found %u device(s).\n", num_devices);
125 for (unsigned i = 0; i < num_devices; ++i) {
126 if (clGetDeviceInfo(devices[i], CL_DEVICE_NAME, 256, info, 0) ==
127 CL_SUCCESS) {
128 printf(" Device %u name: %s.\n", i + 1, info);
129 }
130 }
131 }
132 }
133 }
134#endif
135 if (tesseract::SIMDDetect::IsAVX512BWAvailable()) printf(" Found AVX512BW\n");
136 if (tesseract::SIMDDetect::IsAVX512FAvailable()) printf(" Found AVX512F\n");
137 if (tesseract::SIMDDetect::IsAVX2Available()) printf(" Found AVX2\n");
138 if (tesseract::SIMDDetect::IsAVXAvailable()) printf(" Found AVX\n");
139 if (tesseract::SIMDDetect::IsFMAAvailable()) printf(" Found FMA\n");
140 if (tesseract::SIMDDetect::IsSSEAvailable()) printf(" Found SSE\n");
141#ifdef _OPENMP
142 printf(" Found OpenMP %d\n", _OPENMP);
143#endif
144#if defined(HAVE_LIBARCHIVE)
145# if ARCHIVE_VERSION_NUMBER >= 3002000
146 printf(" Found %s\n", archive_version_details());
147# else
148 printf(" Found %s\n", archive_version_string());
149# endif // ARCHIVE_VERSION_NUMBER
150#endif // HAVE_LIBARCHIVE
151
152}
153
154static void PrintHelpForPSM() {
155 const char* msg =
156 "Page segmentation modes:\n"
157 " 0 Orientation and script detection (OSD) only.\n"
158 " 1 Automatic page segmentation with OSD.\n"
159 " 2 Automatic page segmentation, but no OSD, or OCR. (not implemented)\n"
160 " 3 Fully automatic page segmentation, but no OSD. (Default)\n"
161 " 4 Assume a single column of text of variable sizes.\n"
162 " 5 Assume a single uniform block of vertically aligned text.\n"
163 " 6 Assume a single uniform block of text.\n"
164 " 7 Treat the image as a single text line.\n"
165 " 8 Treat the image as a single word.\n"
166 " 9 Treat the image as a single word in a circle.\n"
167 " 10 Treat the image as a single character.\n"
168 " 11 Sparse text. Find as much text as possible in no"
169 " particular order.\n"
170 " 12 Sparse text with OSD.\n"
171 " 13 Raw line. Treat the image as a single text line,\n"
172 " bypassing hacks that are Tesseract-specific.\n";
173
174#ifdef DISABLED_LEGACY_ENGINE
175 const char* disabled_osd_msg =
176 "\nNOTE: The OSD modes are currently disabled.\n";
177 printf("%s%s", msg, disabled_osd_msg);
178#else
179 printf("%s", msg);
180#endif
181}
182
183#ifndef DISABLED_LEGACY_ENGINE
184static void PrintHelpForOEM() {
185 const char* msg =
186 "OCR Engine modes:\n"
187 " 0 Legacy engine only.\n"
188 " 1 Neural nets LSTM engine only.\n"
189 " 2 Legacy + LSTM engines.\n"
190 " 3 Default, based on what is available.\n";
191
192 printf("%s", msg);
193}
194#endif // ndef DISABLED_LEGACY_ENGINE
195
196static void PrintHelpExtra(const char* program) {
197 printf(
198 "Usage:\n"
199 " %s --help | --help-extra | --help-psm | "
200#ifndef DISABLED_LEGACY_ENGINE
201 "--help-oem | "
202#endif
203 "--version\n"
204 " %s --list-langs [--tessdata-dir PATH]\n"
205 " %s --print-parameters [options...] [configfile...]\n"
206 " %s imagename|imagelist|stdin outputbase|stdout [options...] [configfile...]\n"
207 "\n"
208 "OCR options:\n"
209 " --tessdata-dir PATH Specify the location of tessdata path.\n"
210 " --user-words PATH Specify the location of user words file.\n"
211 " --user-patterns PATH Specify the location of user patterns file.\n"
212 " --dpi VALUE Specify DPI for input image.\n"
213 " -l LANG[+LANG] Specify language(s) used for OCR.\n"
214 " -c VAR=VALUE Set value for config variables.\n"
215 " Multiple -c arguments are allowed.\n"
216 " --psm NUM Specify page segmentation mode.\n"
217#ifndef DISABLED_LEGACY_ENGINE
218 " --oem NUM Specify OCR Engine mode.\n"
219#endif
220 "NOTE: These options must occur before any configfile.\n"
221 "\n",
222 program, program, program, program
223 );
224
225 PrintHelpForPSM();
226#ifndef DISABLED_LEGACY_ENGINE
227 printf("\n");
228 PrintHelpForOEM();
229#endif
230
231 printf(
232 "\n"
233 "Single options:\n"
234 " -h, --help Show minimal help message.\n"
235 " --help-extra Show extra help for advanced users.\n"
236 " --help-psm Show page segmentation modes.\n"
237#ifndef DISABLED_LEGACY_ENGINE
238 " --help-oem Show OCR Engine modes.\n"
239#endif
240 " -v, --version Show version information.\n"
241 " --list-langs List available languages for tesseract engine.\n"
242 " --print-parameters Print tesseract parameters.\n"
243 );
244}
245
246static void PrintHelpMessage(const char* program) {
247 printf(
248 "Usage:\n"
249 " %s --help | --help-extra | --version\n"
250 " %s --list-langs\n"
251 " %s imagename outputbase [options...] [configfile...]\n"
252 "\n"
253 "OCR options:\n"
254 " -l LANG[+LANG] Specify language(s) used for OCR.\n"
255 "NOTE: These options must occur before any configfile.\n"
256 "\n"
257 "Single options:\n"
258 " --help Show this help message.\n"
259 " --help-extra Show extra help for advanced users.\n"
260 " --version Show version information.\n"
261 " --list-langs List available languages for tesseract engine.\n",
262 program, program, program
263 );
264}
265
266static void SetVariablesFromCLArgs(tesseract::TessBaseAPI* api, int argc,
267 char** argv) {
268 char opt1[256], opt2[255];
269 for (int i = 0; i < argc; i++) {
270 if (strcmp(argv[i], "-c") == 0 && i + 1 < argc) {
271 strncpy(opt1, argv[i + 1], 255);
272 opt1[255] = '\0';
273 char* p = strchr(opt1, '=');
274 if (!p) {
275 fprintf(stderr, "Missing = in configvar assignment\n");
276 exit(EXIT_FAILURE);
277 }
278 *p = 0;
279 strncpy(opt2, strchr(argv[i + 1], '=') + 1, sizeof(opt2) - 1);
280 opt2[254] = 0;
281 ++i;
282
283 if (!api->SetVariable(opt1, opt2)) {
284 fprintf(stderr, "Could not set option: %s=%s\n", opt1, opt2);
285 }
286 }
287 }
288}
289
290static void PrintLangsList(tesseract::TessBaseAPI* api) {
291 GenericVector<STRING> languages;
292 api->GetAvailableLanguagesAsVector(&languages);
293 printf("List of available languages (%d):\n", languages.size());
294 for (int index = 0; index < languages.size(); ++index) {
295 STRING& string = languages[index];
296 printf("%s\n", string.string());
297 }
298 api->End();
299}
300
301static void PrintBanner() {
302 tprintf("Tesseract Open Source OCR Engine v%s with Leptonica\n",
303 tesseract::TessBaseAPI::Version());
304}
305
320static void FixPageSegMode(tesseract::TessBaseAPI* api,
321 tesseract::PageSegMode pagesegmode) {
323 api->SetPageSegMode(pagesegmode);
324}
325
326static void checkArgValues(int arg, const char* mode, int count) {
327 if (arg >= count || arg < 0) {
328 printf("Invalid %s value, please enter a number between 0-%d\n", mode, count - 1);
329 exit(EXIT_SUCCESS);
330 }
331}
332
333// NOTE: arg_i is used here to avoid ugly *i so many times in this function
334static void ParseArgs(const int argc, char** argv, const char** lang,
335 const char** image, const char** outputbase,
336 const char** datapath, l_int32* dpi, bool* list_langs,
337 bool* print_parameters, GenericVector<STRING>* vars_vec,
338 GenericVector<STRING>* vars_values, l_int32* arg_i,
339 tesseract::PageSegMode* pagesegmode,
340 tesseract::OcrEngineMode* enginemode) {
341 bool noocr = false;
342 int i;
343 for (i = 1; i < argc && (*outputbase == nullptr || argv[i][0] == '-'); i++) {
344 if (*image != nullptr && *outputbase == nullptr) {
345 // outputbase follows image, don't allow options at that position.
346 *outputbase = argv[i];
347 } else if ((strcmp(argv[i], "-h") == 0) || (strcmp(argv[i], "--help") == 0)) {
348 PrintHelpMessage(argv[0]);
349 noocr = true;
350 } else if (strcmp(argv[i], "--help-extra") == 0) {
351 PrintHelpExtra(argv[0]);
352 noocr = true;
353 } else if ((strcmp(argv[i], "--help-psm") == 0)) {
354 PrintHelpForPSM();
355 noocr = true;
356#ifndef DISABLED_LEGACY_ENGINE
357 } else if ((strcmp(argv[i], "--help-oem") == 0)) {
358 PrintHelpForOEM();
359 noocr = true;
360#endif
361 } else if ((strcmp(argv[i], "-v") == 0) ||
362 (strcmp(argv[i], "--version") == 0)) {
363 PrintVersionInfo();
364 noocr = true;
365 } else if (strcmp(argv[i], "-l") == 0 && i + 1 < argc) {
366 *lang = argv[i + 1];
367 ++i;
368 } else if (strcmp(argv[i], "--tessdata-dir") == 0 && i + 1 < argc) {
369 *datapath = argv[i + 1];
370 ++i;
371 } else if (strcmp(argv[i], "--dpi") == 0 && i + 1 < argc) {
372 *dpi = atoi(argv[i + 1]);
373 ++i;
374 } else if (strcmp(argv[i], "--user-words") == 0 && i + 1 < argc) {
375 vars_vec->push_back("user_words_file");
376 vars_values->push_back(argv[i + 1]);
377 ++i;
378 } else if (strcmp(argv[i], "--user-patterns") == 0 && i + 1 < argc) {
379 vars_vec->push_back("user_patterns_file");
380 vars_values->push_back(argv[i + 1]);
381 ++i;
382 } else if (strcmp(argv[i], "--list-langs") == 0) {
383 noocr = true;
384 *list_langs = true;
385 } else if (strcmp(argv[i], "--psm") == 0 && i + 1 < argc) {
386 checkArgValues(atoi(argv[i+1]), "PSM", tesseract::PSM_COUNT);
387 *pagesegmode = static_cast<tesseract::PageSegMode>(atoi(argv[i + 1]));
388 ++i;
389 } else if (strcmp(argv[i], "--oem") == 0 && i + 1 < argc) {
390#ifndef DISABLED_LEGACY_ENGINE
391 int oem = atoi(argv[i + 1]);
392 checkArgValues(oem, "OEM", tesseract::OEM_COUNT);
393 *enginemode = static_cast<tesseract::OcrEngineMode>(oem);
394#endif
395 ++i;
396 } else if (strcmp(argv[i], "--print-parameters") == 0) {
397 noocr = true;
398 *print_parameters = true;
399 } else if (strcmp(argv[i], "-c") == 0 && i + 1 < argc) {
400 // handled properly after api init
401 ++i;
402 } else if (*image == nullptr) {
403 *image = argv[i];
404 } else {
405 // Unexpected argument.
406 fprintf(stderr, "Error, unknown command line argument '%s'\n", argv[i]);
407 exit(EXIT_FAILURE);
408 }
409 }
410
411 *arg_i = i;
412
413 if (*pagesegmode == tesseract::PSM_OSD_ONLY) {
414 // OSD = orientation and script detection.
415 if (*lang != nullptr && strcmp(*lang, "osd")) {
416 // If the user explicitly specifies a language (other than osd)
417 // or a script, only orientation can be detected.
418 fprintf(stderr, "Warning, detects only orientation with -l %s\n", *lang);
419 } else {
420 // That mode requires osd.traineddata to detect orientation and script.
421 *lang = "osd";
422 }
423 }
424
425 if (*outputbase == nullptr && noocr == false) {
426 PrintHelpMessage(argv[0]);
427 exit(EXIT_FAILURE);
428 }
429}
430
431static void PreloadRenderers(
434 tesseract::PageSegMode pagesegmode, const char* outputbase) {
435 if (pagesegmode == tesseract::PSM_OSD_ONLY) {
436#ifndef DISABLED_LEGACY_ENGINE
437 renderers->push_back(new tesseract::TessOsdRenderer(outputbase));
438#endif // ndef DISABLED_LEGACY_ENGINE
439 } else {
440 bool error = false;
441 bool b;
442 api->GetBoolVariable("tessedit_create_hocr", &b);
443 if (b) {
444 bool font_info;
445 api->GetBoolVariable("hocr_font_info", &font_info);
446 auto* renderer =
447 new tesseract::TessHOcrRenderer(outputbase, font_info);
448 if (renderer->happy()) {
449 renderers->push_back(renderer);
450 } else {
451 delete renderer;
452 tprintf("Error, could not create hOCR output file: %s\n",
453 strerror(errno));
454 error = true;
455 }
456 }
457
458 api->GetBoolVariable("tessedit_create_alto", &b);
459 if (b) {
460 auto* renderer =
461 new tesseract::TessAltoRenderer(outputbase);
462 if (renderer->happy()) {
463 renderers->push_back(renderer);
464 } else {
465 delete renderer;
466 tprintf("Error, could not create ALTO output file: %s\n",
467 strerror(errno));
468 error = true;
469 }
470 }
471
472 api->GetBoolVariable("tessedit_create_tsv", &b);
473 if (b) {
474 bool font_info;
475 api->GetBoolVariable("hocr_font_info", &font_info);
476 auto* renderer =
477 new tesseract::TessTsvRenderer(outputbase, font_info);
478 if (renderer->happy()) {
479 renderers->push_back(renderer);
480 } else {
481 delete renderer;
482 tprintf("Error, could not create TSV output file: %s\n",
483 strerror(errno));
484 error = true;
485 }
486 }
487
488 api->GetBoolVariable("tessedit_create_pdf", &b);
489 if (b) {
490 #ifdef WIN32
491 if (_setmode(_fileno(stdout), _O_BINARY) == -1)
492 tprintf("ERROR: cin to binary: %s", strerror(errno));
493 #endif // WIN32
494 bool textonly;
495 api->GetBoolVariable("textonly_pdf", &textonly);
496 auto* renderer =
497 new tesseract::TessPDFRenderer(outputbase, api->GetDatapath(),
498 textonly);
499 if (renderer->happy()) {
500 renderers->push_back(renderer);
501 } else {
502 delete renderer;
503 tprintf("Error, could not create PDF output file: %s\n",
504 strerror(errno));
505 error = true;
506 }
507 }
508
509 api->GetBoolVariable("tessedit_write_unlv", &b);
510 if (b) {
511 api->SetVariable("unlv_tilde_crunching", "true");
512 auto* renderer =
513 new tesseract::TessUnlvRenderer(outputbase);
514 if (renderer->happy()) {
515 renderers->push_back(renderer);
516 } else {
517 delete renderer;
518 tprintf("Error, could not create UNLV output file: %s\n",
519 strerror(errno));
520 error = true;
521 }
522 }
523
524 api->GetBoolVariable("tessedit_create_lstmbox", &b);
525 if (b) {
526 auto* renderer =
527 new tesseract::TessLSTMBoxRenderer(outputbase);
528 if (renderer->happy()) {
529 renderers->push_back(renderer);
530 } else {
531 delete renderer;
532 tprintf("Error, could not create LSTM BOX output file: %s\n",
533 strerror(errno));
534 error = true;
535 }
536 }
537
538 api->GetBoolVariable("tessedit_create_boxfile", &b);
539 if (b) {
540 auto* renderer =
541 new tesseract::TessBoxTextRenderer(outputbase);
542 if (renderer->happy()) {
543 renderers->push_back(renderer);
544 } else {
545 delete renderer;
546 tprintf("Error, could not create BOX output file: %s\n",
547 strerror(errno));
548 error = true;
549 }
550 }
551
552 api->GetBoolVariable("tessedit_create_wordstrbox", &b);
553 if (b) {
554 auto* renderer =
555 new tesseract::TessWordStrBoxRenderer(outputbase);
556 if (renderer->happy()) {
557 renderers->push_back(renderer);
558 } else {
559 delete renderer;
560 tprintf("Error, could not create WordStr BOX output file: %s\n",
561 strerror(errno));
562 error = true;
563 }
564 }
565
566 api->GetBoolVariable("tessedit_create_txt", &b);
567 if (b || (!error && renderers->empty())) {
568 // Create text output if no other output was requested
569 // even if text output was not explicitly requested unless
570 // there was an error.
571 auto* renderer =
572 new tesseract::TessTextRenderer(outputbase);
573 if (renderer->happy()) {
574 renderers->push_back(renderer);
575 } else {
576 delete renderer;
577 tprintf("Error, could not create TXT output file: %s\n",
578 strerror(errno));
579 }
580 }
581 }
582
583 if (!renderers->empty()) {
584 // Since the PointerVector auto-deletes, null-out the renderers that are
585 // added to the root, and leave the root in the vector.
586 for (int r = 1; r < renderers->size(); ++r) {
587 (*renderers)[0]->insert((*renderers)[r]);
588 (*renderers)[r] = nullptr;
589 }
590 }
591}
592
593
594/**********************************************************************
595 * main()
596 *
597 **********************************************************************/
598
599int main(int argc, char** argv) {
600 const char* lang = nullptr;
601 const char* image = nullptr;
602 const char* outputbase = nullptr;
603 const char* datapath = nullptr;
604 bool list_langs = false;
605 bool print_parameters = false;
606 l_int32 dpi = 0;
607 int arg_i = 1;
609#ifdef DISABLED_LEGACY_ENGINE
610 auto enginemode = tesseract::OEM_LSTM_ONLY;
611#else
613#endif
614 /* main() calls functions like ParseArgs which call exit().
615 * This results in memory leaks if vars_vec and vars_values are
616 * declared as auto variables (destructor is not called then). */
617 static GenericVector<STRING> vars_vec;
618 static GenericVector<STRING> vars_values;
619
620#if !defined(DEBUG)
621 // Disable debugging and informational messages from Leptonica.
622 setMsgSeverity(L_SEVERITY_ERROR);
623#endif
624
625#if defined(HAVE_TIFFIO_H) && defined(_WIN32)
626 /* Show libtiff errors and warnings on console (not in GUI). */
627 TIFFSetErrorHandler(Win32ErrorHandler);
628 TIFFSetWarningHandler(Win32WarningHandler);
629#endif // HAVE_TIFFIO_H && _WIN32
630
631 ParseArgs(argc, argv, &lang, &image, &outputbase, &datapath, &dpi,
632 &list_langs, &print_parameters, &vars_vec, &vars_values, &arg_i,
633 &pagesegmode, &enginemode);
634
635 if (lang == nullptr) {
636 // Set default language if none was given.
637 lang = "eng";
638 }
639
640 if (image == nullptr && !list_langs && !print_parameters)
641 return EXIT_SUCCESS;
642
643 // Call GlobalDawgCache here to create the global DawgCache object before
644 // the TessBaseAPI object. This fixes the order of destructor calls:
645 // first TessBaseAPI must be destructed, DawgCache must be the last object.
647
648 // Avoid memory leak caused by auto variable when return is called.
649 static tesseract::TessBaseAPI api;
650
651 api.SetOutputName(outputbase);
652
653 const int init_failed = api.Init(datapath, lang, enginemode, &(argv[arg_i]),
654 argc - arg_i, &vars_vec, &vars_values, false);
655
656 SetVariablesFromCLArgs(&api, argc, argv);
657
658 // SIMD settings might be overridden by config variable.
660
661 if (list_langs) {
662 PrintLangsList(&api);
663 return EXIT_SUCCESS;
664 }
665
666 if (init_failed) {
667 fprintf(stderr, "Could not initialize tesseract.\n");
668 return EXIT_FAILURE;
669 }
670
671 if (print_parameters) {
672 FILE* fout = stdout;
673 fprintf(stdout, "Tesseract parameters:\n");
674 api.PrintVariables(fout);
675 api.End();
676 return EXIT_SUCCESS;
677 }
678
679 FixPageSegMode(&api, pagesegmode);
680
681 if (dpi) {
682 char dpi_string[255];
683 snprintf(dpi_string, 254, "%d", dpi);
684 api.SetVariable("user_defined_dpi", dpi_string);
685 }
686
687 if (pagesegmode == tesseract::PSM_AUTO_ONLY) {
688 int ret_val = EXIT_SUCCESS;
689
690 Pix* pixs = pixRead(image);
691 if (!pixs) {
692 fprintf(stderr, "Leptonica can't process input file: %s\n", image);
693 return 2;
694 }
695
696 api.SetImage(pixs);
697
698 tesseract::Orientation orientation;
701 float deskew_angle;
702
703 const tesseract::PageIterator* it = api.AnalyseLayout();
704 if (it) {
705 // TODO: Implement output of page segmentation, see documentation
706 // ("Automatic page segmentation, but no OSD, or OCR").
707 it->Orientation(&orientation, &direction, &order, &deskew_angle);
708 tprintf(
709 "Orientation: %d\nWritingDirection: %d\nTextlineOrder: %d\n"
710 "Deskew angle: %.4f\n",
711 orientation, direction, order, deskew_angle);
712 } else {
713 ret_val = EXIT_FAILURE;
714 }
715
716 delete it;
717
718 pixDestroy(&pixs);
719 return ret_val;
720 }
721
722 // Set in_training_mode to true when using one of these configs:
723 // ambigs.train, box.train, box.train.stderr, linebox, rebox, lstm.train.
724 // In this mode no other OCR result files are written.
725 bool b = false;
726 bool in_training_mode =
727 (api.GetBoolVariable("tessedit_ambigs_training", &b) && b) ||
728 (api.GetBoolVariable("tessedit_resegment_from_boxes", &b) && b) ||
729 (api.GetBoolVariable("tessedit_make_boxes_from_boxes", &b) && b) ||
730 (api.GetBoolVariable("tessedit_train_line_recognizer", &b) && b);
731
732#ifdef DISABLED_LEGACY_ENGINE
733 auto cur_psm = api.GetPageSegMode();
734 auto osd_warning = std::string("");
735 if (cur_psm == tesseract::PSM_OSD_ONLY) {
736 const char* disabled_osd_msg =
737 "\nERROR: The page segmentation mode 0 (OSD Only) is currently disabled.\n\n";
738 fprintf(stderr, "%s", disabled_osd_msg);
739 return EXIT_FAILURE;
740 } else if (cur_psm == tesseract::PSM_AUTO_OSD) {
742 osd_warning +=
743 "\nWarning: The page segmentation mode 1 (Auto+OSD) is currently disabled. "
744 "Using PSM 3 (Auto) instead.\n\n";
745 } else if (cur_psm == tesseract::PSM_SPARSE_TEXT_OSD) {
747 osd_warning +=
748 "\nWarning: The page segmentation mode 12 (Sparse text + OSD) is currently disabled. "
749 "Using PSM 11 (Sparse text) instead.\n\n";
750 }
751#endif // def DISABLED_LEGACY_ENGINE
752
753 // Avoid memory leak caused by auto variable when exit() is called.
755
756 if (in_training_mode) {
757 renderers.push_back(nullptr);
758 } else if (outputbase != nullptr) {
759 PreloadRenderers(&api, &renderers, pagesegmode, outputbase);
760 }
761
762 bool banner = false;
763 if (outputbase != nullptr && strcmp(outputbase, "-") &&
764 strcmp(outputbase, "stdout")) {
765 banner = true;
766 }
767
768 if (!renderers.empty()) {
769 if (banner) PrintBanner();
770#ifdef DISABLED_LEGACY_ENGINE
771 if (!osd_warning.empty()) {
772 fprintf(stderr, "%s",osd_warning.c_str());
773 }
774#endif
775 bool succeed = api.ProcessPages(image, nullptr, 0, renderers[0]);
776 if (!succeed) {
777 fprintf(stderr, "Error during processing.\n");
778 return EXIT_FAILURE;
779 }
780 }
781
782 return EXIT_SUCCESS;
783}
int main(int argc, char **argv)
DLLSYM void tprintf(const char *format,...)
Definition: tprintf.cpp:35
int count(LIST var_list)
Definition: oldlist.cpp:95
@ PSM_AUTO_OSD
script detection. (OSD)
Definition: publictypes.h:165
@ PSM_OSD_ONLY
Orientation and script detection only.
Definition: publictypes.h:164
@ PSM_COUNT
Number of enum entries.
Definition: publictypes.h:182
@ PSM_SPARSE_TEXT
Find as much text as possible in no particular order.
Definition: publictypes.h:177
@ PSM_AUTO_ONLY
Automatic page segmentation, but no OSD, or OCR.
Definition: publictypes.h:167
@ PSM_AUTO
Fully automatic page segmentation, but no OSD.
Definition: publictypes.h:168
@ PSM_SINGLE_BLOCK
Assume a single uniform block of text. (Default.)
Definition: publictypes.h:172
@ PSM_SPARSE_TEXT_OSD
Sparse text with orientation and script det.
Definition: publictypes.h:178
int push_back(T object)
bool empty() const
Definition: genericvector.h:91
int size() const
Definition: genericvector.h:72
void SetPageSegMode(PageSegMode mode)
Definition: baseapi.cpp:515
const char * GetDatapath()
Definition: baseapi.cpp:966
bool SetVariable(const char *name, const char *value)
Definition: baseapi.cpp:286
bool ProcessPages(const char *filename, const char *retry_config, int timeout_millisec, TessResultRenderer *renderer)
Definition: baseapi.cpp:1076
PageSegMode GetPageSegMode() const
Definition: baseapi.cpp:522
int Init(const char *datapath, const char *language, OcrEngineMode mode, char **configs, int configs_size, const GenericVector< STRING > *vars_vec, const GenericVector< STRING > *vars_values, bool set_only_non_debug_params)
Definition: baseapi.cpp:346
void PrintVariables(FILE *fp) const
Definition: baseapi.cpp:334
void SetImage(const unsigned char *imagedata, int width, int height, int bytes_per_pixel, int bytes_per_line)
Definition: baseapi.cpp:580
PageIterator * AnalyseLayout()
Definition: baseapi.cpp:810
bool GetBoolVariable(const char *name, bool *value) const
Definition: baseapi.cpp:306
void GetAvailableLanguagesAsVector(GenericVector< STRING > *langs) const
Definition: baseapi.cpp:456
void SetOutputName(const char *name)
Definition: baseapi.cpp:279
static bool IsAVX512BWAvailable()
Definition: simddetect.h:46
static bool IsFMAAvailable()
Definition: simddetect.h:50
static bool IsAVXAvailable()
Definition: simddetect.h:34
static bool IsAVX512FAvailable()
Definition: simddetect.h:42
static bool IsSSEAvailable()
Definition: simddetect.h:54
static bool IsAVX2Available()
Definition: simddetect.h:38
static TESS_API void Update()
Definition: simddetect.cpp:173
void Orientation(tesseract::Orientation *orientation, tesseract::WritingDirection *writing_direction, tesseract::TextlineOrder *textline_order, float *deskew_angle) const
Definition: strngs.h:45
static TESS_API DawgCache * GlobalDawgCache()
Definition: dict.cpp:184