tesseract  4.1.1
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 
52 static 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 
61 static 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 
73 class 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 
86 static AutoWin32ConsoleOutputCP autoWin32ConsoleOutputCP(CP_UTF8);
87 
88 #endif // _WIN32
89 
90 static 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 
154 static 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
184 static 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 
196 static 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 
246 static 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 
266 static 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 
290 static 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 
301 static void PrintBanner() {
302  tprintf("Tesseract Open Source OCR Engine v%s with Leptonica\n",
304 }
305 
320 static void FixPageSegMode(tesseract::TessBaseAPI* api,
321  tesseract::PageSegMode pagesegmode) {
323  api->SetPageSegMode(pagesegmode);
324 }
325 
326 static 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
334 static 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 
431 static 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 
599 int 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;
699  tesseract::WritingDirection direction;
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 }
tesseract::TessLSTMBoxRenderer
Definition: renderer.h:263
TessHOcrRenderer
struct TessHOcrRenderer TessHOcrRenderer
Definition: capi.h:89
simddetect.h
tesseract::PSM_SPARSE_TEXT_OSD
@ PSM_SPARSE_TEXT_OSD
Sparse text with orientation and script det.
Definition: publictypes.h:178
tesseract::SIMDDetect::IsAVX2Available
static bool IsAVX2Available()
Definition: simddetect.h:38
tesseract::PSM_SINGLE_BLOCK
@ PSM_SINGLE_BLOCK
Assume a single uniform block of text. (Default.)
Definition: publictypes.h:172
tesseract::SIMDDetect::IsFMAAvailable
static bool IsFMAAvailable()
Definition: simddetect.h:50
tesseract::TessBaseAPI::End
void End()
Definition: baseapi.cpp:1875
tesseract::TessBaseAPI::SetPageSegMode
void SetPageSegMode(PageSegMode mode)
Definition: baseapi.cpp:515
main
int main(int argc, char **argv)
Definition: tesseractmain.cpp:599
tesseract::TessBaseAPI::Version
static const char * Version()
Definition: baseapi.cpp:233
tesseract::TessBaseAPI::GetPageSegMode
PageSegMode GetPageSegMode() const
Definition: baseapi.cpp:522
tesseract::WritingDirection
WritingDirection
Definition: publictypes.h:135
GenericVector< STRING >
tesseract::PageIterator
Definition: pageiterator.h:52
tesseract::OEM_LSTM_ONLY
@ OEM_LSTM_ONLY
Definition: publictypes.h:270
TessPDFRenderer
struct TessPDFRenderer TessPDFRenderer
Definition: capi.h:90
tesseract::TessBaseAPI::ProcessPages
bool ProcessPages(const char *filename, const char *retry_config, int timeout_millisec, TessResultRenderer *renderer)
Definition: baseapi.cpp:1076
tesseract::TessBaseAPI::SetOutputName
void SetOutputName(const char *name)
Definition: baseapi.cpp:279
tprintf
DLLSYM void tprintf(const char *format,...)
Definition: tprintf.cpp:35
tesseract::TessBaseAPI::AnalyseLayout
PageIterator * AnalyseLayout()
Definition: baseapi.cpp:810
baseapi.h
tesseract::TessBaseAPI::SetVariable
bool SetVariable(const char *name, const char *value)
Definition: baseapi.cpp:286
TessBoxTextRenderer
struct TessBoxTextRenderer TessBoxTextRenderer
Definition: capi.h:92
tesseract::SIMDDetect::IsAVXAvailable
static bool IsAVXAvailable()
Definition: simddetect.h:34
tesseract::PSM_COUNT
@ PSM_COUNT
Number of enum entries.
Definition: publictypes.h:182
tesseract::PSM_AUTO_OSD
@ PSM_AUTO_OSD
script detection. (OSD)
Definition: publictypes.h:165
tesseract::SIMDDetect::IsAVX512FAvailable
static bool IsAVX512FAvailable()
Definition: simddetect.h:42
tesseract::OcrEngineMode
OcrEngineMode
Definition: publictypes.h:268
count
int count(LIST var_list)
Definition: oldlist.cpp:95
renderer.h
tesseract::TessBaseAPI::GetAvailableLanguagesAsVector
void GetAvailableLanguagesAsVector(GenericVector< STRING > *langs) const
Definition: baseapi.cpp:456
tesseract::TessBaseAPI::GetDatapath
const char * GetDatapath()
Definition: baseapi.cpp:966
tesseract::OEM_COUNT
@ OEM_COUNT
Definition: publictypes.h:281
TessUnlvRenderer
struct TessUnlvRenderer TessUnlvRenderer
Definition: capi.h:91
tesseract::TextlineOrder
TextlineOrder
Definition: publictypes.h:152
tesseract::OEM_DEFAULT
@ OEM_DEFAULT
Definition: publictypes.h:274
tprintf.h
tesseract::TessWordStrBoxRenderer
Definition: renderer.h:285
tesseract::PointerVector
Definition: genericvector.h:456
tesseract::PageIterator::Orientation
void Orientation(tesseract::Orientation *orientation, tesseract::WritingDirection *writing_direction, tesseract::TextlineOrder *textline_order, float *deskew_angle) const
Definition: pageiterator.cpp:519
tesseract::PSM_AUTO_ONLY
@ PSM_AUTO_ONLY
Automatic page segmentation, but no OSD, or OCR.
Definition: publictypes.h:167
tesseract::TessBaseAPI::Init
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
tesseract::TessTsvRenderer
Definition: renderer.h:197
tesseract::SIMDDetect::IsSSEAvailable
static bool IsSSEAvailable()
Definition: simddetect.h:54
GenericVector::size
int size() const
Definition: genericvector.h:72
tesseract::SIMDDetect::Update
static TESS_API void Update()
Definition: simddetect.cpp:173
tesseract::TessBaseAPI::GetBoolVariable
bool GetBoolVariable(const char *name, bool *value) const
Definition: baseapi.cpp:306
tesseract::TessBaseAPI::SetImage
void SetImage(const unsigned char *imagedata, int width, int height, int bytes_per_pixel, int bytes_per_line)
Definition: baseapi.cpp:580
tesseract::TessBaseAPI::PrintVariables
void PrintVariables(FILE *fp) const
Definition: baseapi.cpp:334
openclwrapper.h
tesseract::PageSegMode
PageSegMode
Definition: publictypes.h:163
tesseract::PSM_OSD_ONLY
@ PSM_OSD_ONLY
Orientation and script detection only.
Definition: publictypes.h:164
TessTextRenderer
struct TessTextRenderer TessTextRenderer
Definition: capi.h:88
tesseract::Orientation
Orientation
Definition: publictypes.h:120
tesseract::PSM_SPARSE_TEXT
@ PSM_SPARSE_TEXT
Find as much text as possible in no particular order.
Definition: publictypes.h:177
dict.h
tesseract::Dict::GlobalDawgCache
static TESS_API DawgCache * GlobalDawgCache()
Definition: dict.cpp:184
tesseract::PSM_AUTO
@ PSM_AUTO
Fully automatic page segmentation, but no OSD.
Definition: publictypes.h:168
STRING
Definition: strngs.h:45
GenericVector< T * >::empty
bool empty() const
Definition: genericvector.h:91
tesseract::SIMDDetect::IsAVX512BWAvailable
static bool IsAVX512BWAvailable()
Definition: simddetect.h:46
tesseract::TessAltoRenderer
Definition: renderer.h:184
tesseract::TessOsdRenderer
Definition: renderer.h:298
tesseract::TessBaseAPI
Definition: baseapi.h:91
GenericVector::push_back
int push_back(T object)
Definition: genericvector.h:837