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