21 #include "config_auto.h"
27 #include "allheaders.h"
30 #if defined(USE_OPENCL)
41 #if defined(HAVE_LIBARCHIVE)
44 #if defined(HAVE_LIBCURL)
45 #include <curl/curl.h>
51 #if defined(HAVE_TIFFIO_H)
55 static void Win32ErrorHandler(
const char* module,
const char* fmt,
57 if (module !=
nullptr) {
58 fprintf(stderr,
"%s: ", module);
60 vfprintf(stderr, fmt, ap);
61 fprintf(stderr,
".\n");
64 static void Win32WarningHandler(
const char* module,
const char* fmt,
66 if (module !=
nullptr) {
67 fprintf(stderr,
"%s: ", module);
69 fprintf(stderr,
"Warning, ");
70 vfprintf(stderr, fmt, ap);
71 fprintf(stderr,
".\n");
76 class AutoWin32ConsoleOutputCP {
78 explicit AutoWin32ConsoleOutputCP(UINT codeCP) {
79 oldCP_ = GetConsoleOutputCP();
80 SetConsoleOutputCP(codeCP);
82 ~AutoWin32ConsoleOutputCP() {
83 SetConsoleOutputCP(oldCP_);
89 static AutoWin32ConsoleOutputCP autoWin32ConsoleOutputCP(CP_UTF8);
93 static void PrintVersionInfo() {
98 versionStrP = getLeptonicaVersion();
99 printf(
" %s\n", versionStrP);
100 lept_free(versionStrP);
102 versionStrP = getImagelibVersions();
103 printf(
" %s\n", versionStrP);
104 lept_free(versionStrP);
107 cl_platform_id platform[4];
108 cl_uint num_platforms;
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++) {
115 if (clGetPlatformInfo(platform[n], CL_PLATFORM_NAME, 256, info, 0) ==
117 printf(
" Platform %u name: %s.\n", n + 1, info);
119 if (clGetPlatformInfo(platform[n], CL_PLATFORM_VERSION, 256, info, 0) ==
121 printf(
" Version: %s.\n", info);
123 cl_device_id devices[2];
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) ==
131 printf(
" Device %u name: %s.\n", i + 1, info);
145 printf(
" Found OpenMP %d\n", _OPENMP);
147 #if defined(HAVE_LIBARCHIVE)
148 # if ARCHIVE_VERSION_NUMBER >= 3002000
149 printf(
" Found %s\n", archive_version_details());
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());
159 static void PrintHelpForPSM() {
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";
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);
188 #ifndef DISABLED_LEGACY_ENGINE
189 static void PrintHelpForOEM() {
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";
199 #endif // ndef DISABLED_LEGACY_ENGINE
201 static void PrintHelpExtra(
const char* program) {
204 " %s --help | --help-extra | --help-psm | "
205 #ifndef DISABLED_LEGACY_ENGINE
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"
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"
225 "NOTE: These options must occur before any configfile.\n"
227 program, program, program, program
231 #ifndef DISABLED_LEGACY_ENGINE
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"
245 " -v, --version Show version information.\n"
246 " --list-langs List available languages for tesseract engine.\n"
247 " --print-parameters Print tesseract parameters.\n"
251 static void PrintHelpMessage(
const char* program) {
254 " %s --help | --help-extra | --version\n"
256 " %s imagename outputbase [options...] [configfile...]\n"
259 " -l LANG[+LANG] Specify language(s) used for OCR.\n"
260 "NOTE: These options must occur before any configfile.\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
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);
278 char* p = strchr(opt1,
'=');
280 fprintf(stderr,
"Missing = in configvar assignment\n");
284 strncpy(opt2, strchr(argv[i + 1],
'=') + 1,
sizeof(opt2) - 1);
289 fprintf(stderr,
"Could not set option: %s=%s\n", opt1, opt2);
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());
306 static void PrintBanner() {
307 tprintf(
"Tesseract Open Source OCR Engine v%s with Leptonica\n",
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);
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,
348 for (i = 1; i < argc && (*outputbase ==
nullptr || argv[i][0] ==
'-'); i++) {
349 if (*image !=
nullptr && *outputbase ==
nullptr) {
351 *outputbase = argv[i];
352 }
else if ((strcmp(argv[i],
"-h") == 0) || (strcmp(argv[i],
"--help") == 0)) {
353 PrintHelpMessage(argv[0]);
355 }
else if (strcmp(argv[i],
"--help-extra") == 0) {
356 PrintHelpExtra(argv[0]);
358 }
else if ((strcmp(argv[i],
"--help-psm") == 0)) {
361 #ifndef DISABLED_LEGACY_ENGINE
362 }
else if ((strcmp(argv[i],
"--help-oem") == 0)) {
366 }
else if ((strcmp(argv[i],
"-v") == 0) ||
367 (strcmp(argv[i],
"--version") == 0)) {
370 }
else if (strcmp(argv[i],
"-l") == 0 && i + 1 < argc) {
373 }
else if (strcmp(argv[i],
"--tessdata-dir") == 0 && i + 1 < argc) {
374 *datapath = argv[i + 1];
376 }
else if (strcmp(argv[i],
"--dpi") == 0 && i + 1 < argc) {
377 *dpi = atoi(argv[i + 1]);
379 }
else if (strcmp(argv[i],
"--user-words") == 0 && i + 1 < argc) {
383 }
else if (strcmp(argv[i],
"--user-patterns") == 0 && i + 1 < argc) {
384 vars_vec->
push_back(
"user_patterns_file");
387 }
else if (strcmp(argv[i],
"--list-langs") == 0) {
390 }
else if (strcmp(argv[i],
"--psm") == 0 && i + 1 < argc) {
392 *pagesegmode = static_cast<tesseract::PageSegMode>(atoi(argv[i + 1]));
394 }
else if (strcmp(argv[i],
"--oem") == 0 && i + 1 < argc) {
395 #ifndef DISABLED_LEGACY_ENGINE
396 int oem = atoi(argv[i + 1]);
398 *enginemode = static_cast<tesseract::OcrEngineMode>(oem);
401 }
else if (strcmp(argv[i],
"--print-parameters") == 0) {
403 *print_parameters =
true;
404 }
else if (strcmp(argv[i],
"-c") == 0 && i + 1 < argc) {
407 }
else if (*image ==
nullptr) {
411 fprintf(stderr,
"Error, unknown command line argument '%s'\n", argv[i]);
420 if (*lang !=
nullptr && strcmp(*lang,
"osd")) {
423 fprintf(stderr,
"Warning, detects only orientation with -l %s\n", *lang);
430 if (*outputbase ==
nullptr && noocr ==
false) {
431 PrintHelpMessage(argv[0]);
436 static void PreloadRenderers(
441 #ifndef DISABLED_LEGACY_ENGINE
443 #endif // ndef DISABLED_LEGACY_ENGINE
453 if (renderer->happy()) {
457 tprintf(
"Error, could not create hOCR output file: %s\n",
467 if (renderer->happy()) {
471 tprintf(
"Error, could not create ALTO output file: %s\n",
483 if (renderer->happy()) {
487 tprintf(
"Error, could not create TSV output file: %s\n",
496 if (_setmode(_fileno(stdout), _O_BINARY) == -1)
497 tprintf(
"ERROR: cin to binary: %s", strerror(errno));
504 if (renderer->happy()) {
508 tprintf(
"Error, could not create PDF output file: %s\n",
519 if (renderer->happy()) {
523 tprintf(
"Error, could not create UNLV output file: %s\n",
533 if (renderer->happy()) {
537 tprintf(
"Error, could not create LSTM BOX output file: %s\n",
547 if (renderer->happy()) {
551 tprintf(
"Error, could not create BOX output file: %s\n",
561 if (renderer->happy()) {
565 tprintf(
"Error, could not create WordStr BOX output file: %s\n",
572 if (b || (!error && renderers->
empty())) {
578 if (renderer->happy()) {
582 tprintf(
"Error, could not create TXT output file: %s\n",
588 if (!renderers->
empty()) {
591 for (
int r = 1; r < renderers->
size(); ++r) {
592 (*renderers)[0]->insert((*renderers)[r]);
593 (*renderers)[r] =
nullptr;
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;
614 #ifdef DISABLED_LEGACY_ENGINE
627 setMsgSeverity(L_SEVERITY_ERROR);
630 #if defined(HAVE_TIFFIO_H) && defined(_WIN32)
632 TIFFSetErrorHandler(Win32ErrorHandler);
633 TIFFSetWarningHandler(Win32WarningHandler);
634 #endif // HAVE_TIFFIO_H && _WIN32
636 ParseArgs(argc, argv, &lang, &image, &outputbase, &datapath, &dpi,
637 &list_langs, &print_parameters, &vars_vec, &vars_values, &arg_i,
638 &pagesegmode, &enginemode);
640 if (lang ==
nullptr) {
645 if (image ==
nullptr && !list_langs && !print_parameters)
658 const int init_failed = api.
Init(datapath, lang, enginemode, &(argv[arg_i]),
659 argc - arg_i, &vars_vec, &vars_values,
false);
661 SetVariablesFromCLArgs(&api, argc, argv);
667 PrintLangsList(&api);
672 fprintf(stderr,
"Could not initialize tesseract.\n");
676 if (print_parameters) {
678 fprintf(stdout,
"Tesseract parameters:\n");
684 FixPageSegMode(&api, pagesegmode);
687 char dpi_string[255];
688 snprintf(dpi_string, 254,
"%d", dpi);
693 int ret_val = EXIT_SUCCESS;
695 Pix* pixs = pixRead(image);
697 fprintf(stderr,
"Leptonica can't process input file: %s\n", image);
712 it->
Orientation(&orientation, &direction, &order, &deskew_angle);
714 "Orientation: %d\nWritingDirection: %d\nTextlineOrder: %d\n"
715 "Deskew angle: %.4f\n",
716 orientation, direction, order, deskew_angle);
718 ret_val = EXIT_FAILURE;
731 bool in_training_mode =
737 #ifdef DISABLED_LEGACY_ENGINE
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);
748 "\nWarning: The page segmentation mode 1 (Auto+OSD) is currently disabled. "
749 "Using PSM 3 (Auto) instead.\n\n";
753 "\nWarning: The page segmentation mode 12 (Sparse text + OSD) is currently disabled. "
754 "Using PSM 11 (Sparse text) instead.\n\n";
756 #endif // def DISABLED_LEGACY_ENGINE
761 if (in_training_mode) {
763 }
else if (outputbase !=
nullptr) {
764 PreloadRenderers(&api, &renderers, pagesegmode, outputbase);
768 if (outputbase !=
nullptr && strcmp(outputbase,
"-") &&
769 strcmp(outputbase,
"stdout")) {
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());
780 bool succeed = api.
ProcessPages(image,
nullptr, 0, renderers[0]);
782 fprintf(stderr,
"Error during processing.\n");