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