Tesseract  3.02
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
tesseractmain.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 * File: tessedit.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 // #define USE_VLD //Uncomment for Visual Leak Detector.
21 #if (defined _MSC_VER && defined USE_VLD)
22 #include "mfcpch.h"
23 #include <vld.h>
24 #endif
25 
26 // Include automatically generated configuration file if running autoconf
27 #ifdef HAVE_CONFIG_H
28 #include "config_auto.h"
29 #endif
30 #ifdef USING_GETTEXT
31 #include <libintl.h>
32 #include <locale.h>
33 #define _(x) gettext(x)
34 #else
35 #define _(x) (x)
36 #endif
37 
38 #include "allheaders.h"
39 #include "baseapi.h"
40 #include "basedir.h"
41 #include "strngs.h"
42 #include "tesseractmain.h"
43 #include "tprintf.h"
44 
45 /**********************************************************************
46  * main()
47  *
48  **********************************************************************/
49 
50 int main(int argc, char **argv) {
51 #ifdef USING_GETTEXT
52  setlocale (LC_ALL, "");
53  bindtextdomain (PACKAGE, LOCALEDIR);
54  textdomain (PACKAGE);
55 #endif
56  if ((argc == 2 && strcmp(argv[1], "-v") == 0) ||
57  (argc == 2 && strcmp(argv[1], "--version") == 0)) {
58  char *versionStrP;
59 
60  fprintf(stderr, "tesseract %s\n", tesseract::TessBaseAPI::Version());
61 
62  versionStrP = getLeptonicaVersion();
63  fprintf(stderr, " %s\n", versionStrP);
64  lept_free(versionStrP);
65 
66  versionStrP = getImagelibVersions();
67  fprintf(stderr, " %s\n", versionStrP);
68  lept_free(versionStrP);
69 
70  exit(0);
71  }
72 
74  STRING tessdata_dir;
75  truncate_path(argv[0], &tessdata_dir);
76  int rc = api.Init(tessdata_dir.string(), NULL);
77  if (rc) {
78  fprintf(stderr, _("Could not initialize tesseract.\n"));
79  exit(1);
80  }
81 
82  if (argc == 2 && strcmp(argv[1], "--list-langs") == 0) {
83  GenericVector<STRING> languages;
84  api.GetAvailableLanguagesAsVector(&languages);
85  fprintf(stderr, _("List of available languages (%d):\n"), languages.size());
86  for (int index = 0; index < languages.size(); ++index) {
87  STRING& string = languages[index];
88  fprintf(stderr, "%s\n", string.string());
89  }
90  api.Clear();
91  exit(0);
92  }
93  api.End();
94 
95  // Make the order of args a bit more forgiving than it used to be.
96  const char* lang = "eng";
97  const char* image = NULL;
98  const char* output = NULL;
100  int arg = 1;
101  while (arg < argc && (output == NULL || argv[arg][0] == '-')) {
102  if (strcmp(argv[arg], "-l") == 0 && arg + 1 < argc) {
103  lang = argv[arg + 1];
104  ++arg;
105  } else if (strcmp(argv[arg], "-psm") == 0 && arg + 1 < argc) {
106  pagesegmode = static_cast<tesseract::PageSegMode>(atoi(argv[arg + 1]));
107  ++arg;
108  } else if (image == NULL) {
109  image = argv[arg];
110  } else if (output == NULL) {
111  output = argv[arg];
112  }
113  ++arg;
114  }
115  if (output == NULL) {
116  fprintf(stderr, _("Usage:%s imagename outputbase [-l lang] "
117  "[-psm pagesegmode] [configfile...]\n\n"), argv[0]);
118  fprintf(stderr,
119  _("pagesegmode values are:\n"
120  "0 = Orientation and script detection (OSD) only.\n"
121  "1 = Automatic page segmentation with OSD.\n"
122  "2 = Automatic page segmentation, but no OSD, or OCR\n"
123  "3 = Fully automatic page segmentation, but no OSD. (Default)\n"
124  "4 = Assume a single column of text of variable sizes.\n"
125  "5 = Assume a single uniform block of vertically aligned text.\n"
126  "6 = Assume a single uniform block of text.\n"
127  "7 = Treat the image as a single text line.\n"
128  "8 = Treat the image as a single word.\n"
129  "9 = Treat the image as a single word in a circle.\n"
130  "10 = Treat the image as a single character.\n"));
131  fprintf(stderr, _("-l lang and/or -psm pagesegmode must occur before any"
132  "configfile.\n\n"));
133  fprintf(stderr, _("Single options:\n"));
134  fprintf(stderr, _(" -v --version: version info\n"));
135  fprintf(stderr, _(" --list-langs: list available languages for tesseract "
136  "engine\n"));
137  exit(1);
138  }
139 
140 
141  api.SetOutputName(output);
142 
143  rc = api.Init(tessdata_dir.string(), lang, tesseract::OEM_DEFAULT,
144  &(argv[arg]), argc - arg, NULL, NULL, false);
145  if (rc) {
146  fprintf(stderr, _("Could not initialize tesseract.\n"));
147  exit(1);
148  }
149 
150  // We have 2 possible sources of pagesegmode: a config file and
151  // the command line. For backwards compatability reasons, the
152  // default in tesseract is tesseract::PSM_SINGLE_BLOCK, but the
153  // default for this program is tesseract::PSM_AUTO. We will let
154  // the config file take priority, so the command-line default
155  // can take priority over the tesseract default, so we use the
156  // value from the command line only if the retrieved mode
157  // is still tesseract::PSM_SINGLE_BLOCK, indicating no change
158  // in any config file. Therefore the only way to force
159  // tesseract::PSM_SINGLE_BLOCK is from the command line.
160  // It would be simpler if we could set the value before Init,
161  // but that doesn't work.
163  api.SetPageSegMode(pagesegmode);
164  tprintf("Tesseract Open Source OCR Engine v%s with Leptonica\n",
166 
167 
168  FILE* fin = fopen(image, "rb");
169  if (fin == NULL) {
170  fprintf(stderr, _("Cannot open input file: %s\n"), image);
171  exit(2);
172  }
173  fclose(fin);
174 
175  PIX *pixs;
176  if ((pixs = pixRead(image)) == NULL) {
177  fprintf(stderr, _("Unsupported image type.\n"));
178  exit(3);
179  }
180  pixDestroy(&pixs);
181 
183  if (!api.ProcessPages(image, NULL, 0, &text_out)) {
184  fprintf(stderr, _("Error during processing.\n"));
185  }
186  bool output_hocr = false;
187  api.GetBoolVariable("tessedit_create_hocr", &output_hocr);
188  bool output_box = false;
189  api.GetBoolVariable("tessedit_create_boxfile", &output_box);
190  STRING outfile = output;
191  outfile += output_hocr ? ".html" : output_box ? ".box" : ".txt";
192  FILE* fout = fopen(outfile.string(), "wb");
193  if (fout == NULL) {
194  fprintf(stderr, _("Cannot create output file %s\n"), outfile.string());
195  exit(1);
196  }
197  fwrite(text_out.string(), 1, text_out.length(), fout);
198  fclose(fout);
199 
200  return 0; // Normal exit
201 }
202 
203 #ifdef _WIN32
204 
205 char szAppName[] = "Tesseract"; //app name
206 int initialized = 0;
207 
208 /**********************************************************************
209 * WinMain
210 *
211 * Main function for a windows program.
212 **********************************************************************/
213 
214 int WINAPI WinMain( //main for windows //command line
215  HINSTANCE hInstance,
216  HINSTANCE hPrevInstance,
217  LPSTR lpszCmdLine,
218  int nCmdShow) {
219  WNDCLASS wc;
220  HWND hwnd;
221  MSG msg;
222 
223  char **argv;
224  char *argsin[2];
225  int argc;
226  int exit_code;
227 
228  wc.style = CS_NOCLOSE | CS_OWNDC;
229  wc.lpfnWndProc = (WNDPROC) WndProc;
230  wc.cbClsExtra = 0;
231  wc.cbWndExtra = 0;
232  wc.hInstance = hInstance;
233  wc.hIcon = NULL; //LoadIcon (NULL, IDI_APPLICATION);
234  wc.hCursor = NULL; //LoadCursor (NULL, IDC_ARROW);
235  wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
236  wc.lpszMenuName = NULL;
237  wc.lpszClassName = szAppName;
238 
239  RegisterClass(&wc);
240 
241  hwnd = CreateWindow (szAppName, szAppName,
242  WS_OVERLAPPEDWINDOW | WS_DISABLED,
243  CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
244  CW_USEDEFAULT, HWND_DESKTOP, NULL, hInstance, NULL);
245 
246  argsin[0] = strdup (szAppName);
247  argsin[1] = strdup (lpszCmdLine);
248  /*allocate memory for the args. There can never be more than half*/
249  /*the total number of characters in the arguments.*/
250  argv = (char **)malloc(((strlen(argsin[0]) + strlen(argsin[1])) / 2 + 1) *
251  sizeof(char *));
252 
253  /*now construct argv as it should be for C.*/
254  argc = parse_args (2, argsin, argv);
255 
256  // ShowWindow (hwnd, nCmdShow);
257  // UpdateWindow (hwnd);
258 
259  if (initialized) {
260  exit_code = main (argc, argv);
261  free (argsin[0]);
262  free (argsin[1]);
263  free(argv);
264  return exit_code;
265  }
266  while (GetMessage (&msg, NULL, 0, 0)) {
267  TranslateMessage(&msg);
268  DispatchMessage(&msg);
269  if (initialized) {
270  exit_code = main (argc, argv);
271  break;
272  }
273  else
274  exit_code = msg.wParam;
275  }
276  free (argsin[0]);
277  free (argsin[1]);
278  free(argv);
279  return exit_code;
280 }
281 
282 
283 /**********************************************************************
284 * WndProc
285 *
286 * Function to respond to messages.
287 **********************************************************************/
288 
289 LONG WINAPI WndProc( //message handler
290  HWND hwnd, //window with message
291  UINT msg, //message typ
292  WPARAM wParam,
293  LPARAM lParam) {
294  HDC hdc;
295 
296  if (msg == WM_CREATE) {
297  //
298  // Create a rendering context.
299  //
300  hdc = GetDC (hwnd);
301  ReleaseDC(hwnd, hdc);
302  initialized = 1;
303  return 0;
304  }
305  return DefWindowProc (hwnd, msg, wParam, lParam);
306 }
307 
308 
309 /**********************************************************************
310 * parse_args
311 *
312 * Turn a list of args into a new list of args with each separate
313 * whitespace spaced string being an arg.
314 **********************************************************************/
315 
316 int
317 parse_args ( /*refine arg list */
318  int argc, /*no of input args */
319  char *argv[], /*input args */
320  char *arglist[] /*output args */
321  ) {
322  int argcount; /*converted argc */
323  char *testchar; /*char in option string */
324  int arg; /*current argument */
325 
326  argcount = 0; /*no of options */
327  for (arg = 0; arg < argc; arg++) {
328  testchar = argv[arg]; /*start of arg */
329  do {
330  while (*testchar
331  && (*testchar == ' ' || *testchar == '\n'
332  || *testchar == '\t'))
333  testchar++; /*skip white space */
334  if (*testchar) {
335  /*new arg */
336  arglist[argcount++] = testchar;
337  /*skip to white space */
338  for (testchar++; *testchar && *testchar != ' ' && *testchar != '\n' && *testchar != '\t'; testchar++) ;
339  if (*testchar)
340  *testchar++ = '\0'; /*turn to separate args */
341  }
342  }
343  while (*testchar);
344  }
345  return argcount; /*new number of args */
346 }
347 #endif