21 #include "config_auto.h" 27 #include "allheaders.h" 30 #if defined(USE_OPENCL) 41 #if defined(HAVE_LIBARCHIVE) 48 #if defined(HAVE_TIFFIO_H) 52 static void Win32ErrorHandler(
const char* module,
const char* fmt,
54 if (module !=
nullptr) {
55 fprintf(stderr,
"%s: ", module);
57 vfprintf(stderr, fmt, ap);
58 fprintf(stderr,
".\n");
61 static void Win32WarningHandler(
const char* module,
const char* fmt,
63 if (module !=
nullptr) {
64 fprintf(stderr,
"%s: ", module);
66 fprintf(stderr,
"Warning, ");
67 vfprintf(stderr, fmt, ap);
68 fprintf(stderr,
".\n");
73 class AutoWin32ConsoleOutputCP {
75 explicit AutoWin32ConsoleOutputCP(UINT codeCP) {
76 oldCP_ = GetConsoleOutputCP();
77 SetConsoleOutputCP(codeCP);
79 ~AutoWin32ConsoleOutputCP() {
80 SetConsoleOutputCP(oldCP_);
86 static AutoWin32ConsoleOutputCP autoWin32ConsoleOutputCP(CP_UTF8);
90 static void PrintVersionInfo() {
95 versionStrP = getLeptonicaVersion();
96 printf(
" %s\n", versionStrP);
97 lept_free(versionStrP);
99 versionStrP = getImagelibVersions();
100 printf(
" %s\n", versionStrP);
101 lept_free(versionStrP);
104 cl_platform_id platform[4];
105 cl_uint num_platforms;
107 printf(
" OpenCL info:\n");
108 if (clGetPlatformIDs(4, platform, &num_platforms) == CL_SUCCESS) {
109 printf(
" Found %u platform(s).\n", num_platforms);
110 for (
unsigned n = 0; n < num_platforms; n++) {
112 if (clGetPlatformInfo(platform[n], CL_PLATFORM_NAME, 256, info, 0) ==
114 printf(
" Platform %u name: %s.\n", n + 1, info);
116 if (clGetPlatformInfo(platform[n], CL_PLATFORM_VERSION, 256, info, 0) ==
118 printf(
" Version: %s.\n", info);
120 cl_device_id devices[2];
122 if (clGetDeviceIDs(platform[n], CL_DEVICE_TYPE_ALL, 2, devices,
123 &num_devices) == CL_SUCCESS) {
124 printf(
" Found %u device(s).\n", num_devices);
125 for (
unsigned i = 0; i < num_devices; ++i) {
126 if (clGetDeviceInfo(devices[i], CL_DEVICE_NAME, 256, info, 0) ==
128 printf(
" Device %u name: %s.\n", i + 1, info);
142 printf(
" Found OpenMP %d\n", _OPENMP);
144 #if defined(HAVE_LIBARCHIVE) 145 # if ARCHIVE_VERSION_NUMBER >= 3002000 146 printf(
" Found %s\n", archive_version_details());
148 printf(
" Found %s\n", archive_version_string());
149 # endif // ARCHIVE_VERSION_NUMBER 150 #endif // HAVE_LIBARCHIVE 154 static void PrintHelpForPSM() {
156 "Page segmentation modes:\n" 157 " 0 Orientation and script detection (OSD) only.\n" 158 " 1 Automatic page segmentation with OSD.\n" 159 " 2 Automatic page segmentation, but no OSD, or OCR. (not implemented)\n" 160 " 3 Fully automatic page segmentation, but no OSD. (Default)\n" 161 " 4 Assume a single column of text of variable sizes.\n" 162 " 5 Assume a single uniform block of vertically aligned text.\n" 163 " 6 Assume a single uniform block of text.\n" 164 " 7 Treat the image as a single text line.\n" 165 " 8 Treat the image as a single word.\n" 166 " 9 Treat the image as a single word in a circle.\n" 167 " 10 Treat the image as a single character.\n" 168 " 11 Sparse text. Find as much text as possible in no" 169 " particular order.\n" 170 " 12 Sparse text with OSD.\n" 171 " 13 Raw line. Treat the image as a single text line,\n" 172 " bypassing hacks that are Tesseract-specific.\n";
174 #ifdef DISABLED_LEGACY_ENGINE 175 const char* disabled_osd_msg =
176 "\nNOTE: The OSD modes are currently disabled.\n";
177 printf(
"%s%s", msg, disabled_osd_msg);
183 #ifndef DISABLED_LEGACY_ENGINE 184 static void PrintHelpForOEM() {
186 "OCR Engine modes:\n" 187 " 0 Legacy engine only.\n" 188 " 1 Neural nets LSTM engine only.\n" 189 " 2 Legacy + LSTM engines.\n" 190 " 3 Default, based on what is available.\n";
194 #endif // ndef DISABLED_LEGACY_ENGINE 196 static void PrintHelpExtra(
const char* program) {
199 " %s --help | --help-extra | --help-psm | " 200 #ifndef DISABLED_LEGACY_ENGINE
204 " %s --list-langs [--tessdata-dir PATH]\n" 205 " %s --print-parameters [options...] [configfile...]\n" 206 " %s imagename|imagelist|stdin outputbase|stdout [options...] [configfile...]\n" 209 " --tessdata-dir PATH Specify the location of tessdata path.\n" 210 " --user-words PATH Specify the location of user words file.\n" 211 " --user-patterns PATH Specify the location of user patterns file.\n" 212 " --dpi VALUE Specify DPI for input image.\n" 213 " -l LANG[+LANG] Specify language(s) used for OCR.\n" 214 " -c VAR=VALUE Set value for config variables.\n" 215 " Multiple -c arguments are allowed.\n" 216 " --psm NUM Specify page segmentation mode.\n" 217 #ifndef DISABLED_LEGACY_ENGINE
218 " --oem NUM Specify OCR Engine mode.\n" 220 "NOTE: These options must occur before any configfile.\n" 222 program, program, program, program
226 #ifndef DISABLED_LEGACY_ENGINE 234 " -h, --help Show minimal help message.\n" 235 " --help-extra Show extra help for advanced users.\n" 236 " --help-psm Show page segmentation modes.\n" 237 #ifndef DISABLED_LEGACY_ENGINE
238 " --help-oem Show OCR Engine modes.\n" 240 " -v, --version Show version information.\n" 241 " --list-langs List available languages for tesseract engine.\n" 242 " --print-parameters Print tesseract parameters.\n" 246 static void PrintHelpMessage(
const char* program) {
249 " %s --help | --help-extra | --version\n" 251 " %s imagename outputbase [options...] [configfile...]\n" 254 " -l LANG[+LANG] Specify language(s) used for OCR.\n" 255 "NOTE: These options must occur before any configfile.\n" 258 " --help Show this help message.\n" 259 " --help-extra Show extra help for advanced users.\n" 260 " --version Show version information.\n" 261 " --list-langs List available languages for tesseract engine.\n",
262 program, program, program
268 char opt1[256], opt2[255];
269 for (
int i = 0; i < argc; i++) {
270 if (strcmp(argv[i],
"-c") == 0 && i + 1 < argc) {
271 strncpy(opt1, argv[i + 1], 255);
273 char* p = strchr(opt1,
'=');
275 fprintf(stderr,
"Missing = in configvar assignment\n");
279 strncpy(opt2, strchr(argv[i + 1],
'=') + 1,
sizeof(opt2) - 1);
284 fprintf(stderr,
"Could not set option: %s=%s\n", opt1, opt2);
293 printf(
"List of available languages (%d):\n", languages.
size());
294 for (
int index = 0; index < languages.
size(); ++index) {
295 STRING&
string = languages[index];
296 printf(
"%s\n",
string.
string());
301 static void PrintBanner() {
302 tprintf(
"Tesseract Open Source OCR Engine v%s with Leptonica\n",
326 static void checkArgValues(
int arg,
const char* mode,
int count) {
327 if (arg >=
count || arg < 0) {
328 printf(
"Invalid %s value, please enter a number between 0-%d\n", mode,
count - 1);
334 static void ParseArgs(
const int argc,
char** argv,
const char** lang,
335 const char** image,
const char** outputbase,
336 const char** datapath, l_int32* dpi,
bool* list_langs,
343 for (i = 1; i < argc && (*outputbase ==
nullptr || argv[i][0] ==
'-'); i++) {
344 if (*image !=
nullptr && *outputbase ==
nullptr) {
346 *outputbase = argv[i];
347 }
else if ((strcmp(argv[i],
"-h") == 0) || (strcmp(argv[i],
"--help") == 0)) {
348 PrintHelpMessage(argv[0]);
350 }
else if (strcmp(argv[i],
"--help-extra") == 0) {
351 PrintHelpExtra(argv[0]);
353 }
else if ((strcmp(argv[i],
"--help-psm") == 0)) {
356 #ifndef DISABLED_LEGACY_ENGINE 357 }
else if ((strcmp(argv[i],
"--help-oem") == 0)) {
361 }
else if ((strcmp(argv[i],
"-v") == 0) ||
362 (strcmp(argv[i],
"--version") == 0)) {
365 }
else if (strcmp(argv[i],
"-l") == 0 && i + 1 < argc) {
368 }
else if (strcmp(argv[i],
"--tessdata-dir") == 0 && i + 1 < argc) {
369 *datapath = argv[i + 1];
371 }
else if (strcmp(argv[i],
"--dpi") == 0 && i + 1 < argc) {
372 *dpi = atoi(argv[i + 1]);
374 }
else if (strcmp(argv[i],
"--user-words") == 0 && i + 1 < argc) {
378 }
else if (strcmp(argv[i],
"--user-patterns") == 0 && i + 1 < argc) {
379 vars_vec->
push_back(
"user_patterns_file");
382 }
else if (strcmp(argv[i],
"--list-langs") == 0) {
385 }
else if (strcmp(argv[i],
"--psm") == 0 && i + 1 < argc) {
389 }
else if (strcmp(argv[i],
"--oem") == 0 && i + 1 < argc) {
390 #ifndef DISABLED_LEGACY_ENGINE 391 int oem = atoi(argv[i + 1]);
396 }
else if (strcmp(argv[i],
"--print-parameters") == 0) {
398 *print_parameters =
true;
399 }
else if (strcmp(argv[i],
"-c") == 0 && i + 1 < argc) {
402 }
else if (*image ==
nullptr) {
406 fprintf(stderr,
"Error, unknown command line argument '%s'\n", argv[i]);
415 if (*lang !=
nullptr && strcmp(*lang,
"osd")) {
418 fprintf(stderr,
"Warning, detects only orientation with -l %s\n", *lang);
425 if (*outputbase ==
nullptr && noocr ==
false) {
426 PrintHelpMessage(argv[0]);
431 static void PreloadRenderers(
436 #ifndef DISABLED_LEGACY_ENGINE 438 #endif // ndef DISABLED_LEGACY_ENGINE 448 if (renderer->happy()) {
452 tprintf(
"Error, could not create hOCR output file: %s\n",
462 if (renderer->happy()) {
466 tprintf(
"Error, could not create ALTO output file: %s\n",
478 if (renderer->happy()) {
482 tprintf(
"Error, could not create TSV output file: %s\n",
491 if (_setmode(_fileno(stdout), _O_BINARY) == -1)
492 tprintf(
"ERROR: cin to binary: %s", strerror(errno));
499 if (renderer->happy()) {
503 tprintf(
"Error, could not create PDF output file: %s\n",
514 if (renderer->happy()) {
518 tprintf(
"Error, could not create UNLV output file: %s\n",
528 if (renderer->happy()) {
532 tprintf(
"Error, could not create LSTM BOX output file: %s\n",
542 if (renderer->happy()) {
546 tprintf(
"Error, could not create BOX output file: %s\n",
556 if (renderer->happy()) {
560 tprintf(
"Error, could not create WordStr BOX output file: %s\n",
567 if (b || (!error && renderers->
empty())) {
573 if (renderer->happy()) {
577 tprintf(
"Error, could not create TXT output file: %s\n",
583 if (!renderers->
empty()) {
586 for (
int r = 1; r < renderers->
size(); ++r) {
587 (*renderers)[0]->insert((*renderers)[r]);
588 (*renderers)[r] =
nullptr;
599 int main(
int argc,
char** argv) {
600 const char* lang =
nullptr;
601 const char* image =
nullptr;
602 const char* outputbase =
nullptr;
603 const char* datapath =
nullptr;
604 bool list_langs =
false;
605 bool print_parameters =
false;
609 #ifdef DISABLED_LEGACY_ENGINE 622 setMsgSeverity(L_SEVERITY_ERROR);
625 #if defined(HAVE_TIFFIO_H) && defined(_WIN32) 627 TIFFSetErrorHandler(Win32ErrorHandler);
628 TIFFSetWarningHandler(Win32WarningHandler);
629 #endif // HAVE_TIFFIO_H && _WIN32 631 ParseArgs(argc, argv, &lang, &image, &outputbase, &datapath, &dpi,
632 &list_langs, &print_parameters, &vars_vec, &vars_values, &arg_i,
633 &pagesegmode, &enginemode);
635 if (lang ==
nullptr) {
640 if (image ==
nullptr && !list_langs && !print_parameters)
653 const int init_failed = api.
Init(datapath, lang, enginemode, &(argv[arg_i]),
654 argc - arg_i, &vars_vec, &vars_values,
false);
656 SetVariablesFromCLArgs(&api, argc, argv);
662 PrintLangsList(&api);
667 fprintf(stderr,
"Could not initialize tesseract.\n");
671 if (print_parameters) {
673 fprintf(stdout,
"Tesseract parameters:\n");
679 FixPageSegMode(&api, pagesegmode);
682 char dpi_string[255];
683 snprintf(dpi_string, 254,
"%d", dpi);
688 int ret_val = EXIT_SUCCESS;
690 Pix* pixs = pixRead(image);
692 fprintf(stderr,
"Leptonica can't process input file: %s\n", image);
707 it->
Orientation(&orientation, &direction, &order, &deskew_angle);
709 "Orientation: %d\nWritingDirection: %d\nTextlineOrder: %d\n" 710 "Deskew angle: %.4f\n",
711 orientation, direction, order, deskew_angle);
713 ret_val = EXIT_FAILURE;
726 bool in_training_mode =
732 #ifdef DISABLED_LEGACY_ENGINE 734 auto osd_warning = std::string(
"");
736 const char* disabled_osd_msg =
737 "\nERROR: The page segmentation mode 0 (OSD Only) is currently disabled.\n\n";
738 fprintf(stderr,
"%s", disabled_osd_msg);
743 "\nWarning: The page segmentation mode 1 (Auto+OSD) is currently disabled. " 744 "Using PSM 3 (Auto) instead.\n\n";
748 "\nWarning: The page segmentation mode 12 (Sparse text + OSD) is currently disabled. " 749 "Using PSM 11 (Sparse text) instead.\n\n";
751 #endif // def DISABLED_LEGACY_ENGINE 756 if (in_training_mode) {
758 }
else if (outputbase !=
nullptr) {
759 PreloadRenderers(&api, &renderers, pagesegmode, outputbase);
763 if (outputbase !=
nullptr && strcmp(outputbase,
"-") &&
764 strcmp(outputbase,
"stdout")) {
768 if (!renderers.
empty()) {
769 if (banner) PrintBanner();
770 #ifdef DISABLED_LEGACY_ENGINE 771 if (!osd_warning.empty()) {
772 fprintf(stderr,
"%s",osd_warning.c_str());
775 bool succeed = api.
ProcessPages(image,
nullptr, 0, renderers[0]);
777 fprintf(stderr,
"Error during processing.\n");
bool GetBoolVariable(const char *name, bool *value) const
DLLSYM void tprintf(const char *format,...)
const char * GetDatapath()
bool SetVariable(const char *name, const char *value)
void SetPageSegMode(PageSegMode mode)
static bool IsAVX512FAvailable()
struct TessHOcrRenderer TessHOcrRenderer
Orientation and script detection only.
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)
struct TessBoxTextRenderer TessBoxTextRenderer
static const char * Version()
struct TessTextRenderer TessTextRenderer
int main(int argc, char **argv)
Sparse text with orientation and script det.
PageIterator * AnalyseLayout()
static TESS_API void Update()
struct TessUnlvRenderer TessUnlvRenderer
Find as much text as possible in no particular order.
Automatic page segmentation, but no OSD, or OCR.
static TESS_API DawgCache * GlobalDawgCache()
static bool IsAVX512BWAvailable()
bool ProcessPages(const char *filename, const char *retry_config, int timeout_millisec, TessResultRenderer *renderer)
struct TessPDFRenderer TessPDFRenderer
void SetImage(const unsigned char *imagedata, int width, int height, int bytes_per_pixel, int bytes_per_line)
static bool IsAVX2Available()
void Orientation(tesseract::Orientation *orientation, tesseract::WritingDirection *writing_direction, tesseract::TextlineOrder *textline_order, float *deskew_angle) const
static bool IsFMAAvailable()
Fully automatic page segmentation, but no OSD.
void SetOutputName(const char *name)
static bool IsSSEAvailable()
Assume a single uniform block of text. (Default.)
PageSegMode GetPageSegMode() const
void PrintVariables(FILE *fp) const
void GetAvailableLanguagesAsVector(GenericVector< STRING > *langs) const
static bool IsAVXAvailable()