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