gocr-ruby 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE +21 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +29 -0
  7. data/Rakefile +49 -0
  8. data/ext/gocr/Makefile +141 -0
  9. data/ext/gocr/Makefile.in +140 -0
  10. data/ext/gocr/amiga.h +31 -0
  11. data/ext/gocr/barcode.c +2108 -0
  12. data/ext/gocr/barcode.h +11 -0
  13. data/ext/gocr/box.c +496 -0
  14. data/ext/gocr/config.h +37 -0
  15. data/ext/gocr/config.h.in +36 -0
  16. data/ext/gocr/database.c +468 -0
  17. data/ext/gocr/detect.c +1003 -0
  18. data/ext/gocr/extconf.rb +6 -0
  19. data/ext/gocr/gocr.c +436 -0
  20. data/ext/gocr/gocr.h +290 -0
  21. data/ext/gocr/jconv.c +168 -0
  22. data/ext/gocr/job.c +92 -0
  23. data/ext/gocr/lines.c +364 -0
  24. data/ext/gocr/list.c +334 -0
  25. data/ext/gocr/list.h +91 -0
  26. data/ext/gocr/ocr0.c +7312 -0
  27. data/ext/gocr/ocr0.h +63 -0
  28. data/ext/gocr/ocr0n.c +1527 -0
  29. data/ext/gocr/ocr1.c +85 -0
  30. data/ext/gocr/ocr1.h +3 -0
  31. data/ext/gocr/otsu.c +310 -0
  32. data/ext/gocr/otsu.h +23 -0
  33. data/ext/gocr/output.c +291 -0
  34. data/ext/gocr/output.h +37 -0
  35. data/ext/gocr/pcx.c +153 -0
  36. data/ext/gocr/pcx.h +9 -0
  37. data/ext/gocr/pgm2asc.c +3259 -0
  38. data/ext/gocr/pgm2asc.h +105 -0
  39. data/ext/gocr/pixel.c +538 -0
  40. data/ext/gocr/pnm.c +538 -0
  41. data/ext/gocr/pnm.h +35 -0
  42. data/ext/gocr/progress.c +87 -0
  43. data/ext/gocr/progress.h +42 -0
  44. data/ext/gocr/remove.c +715 -0
  45. data/ext/gocr/tga.c +87 -0
  46. data/ext/gocr/tga.h +6 -0
  47. data/ext/gocr/unicode.c +1318 -0
  48. data/ext/gocr/unicode.h +62 -0
  49. data/ext/gocr/unicode_defs.h +1245 -0
  50. data/ext/gocr/version.h +2 -0
  51. data/gocr-ruby.gemspec +28 -0
  52. data/image.png +0 -0
  53. data/lib/gocr.rb +6 -0
  54. data/lib/gocr/image.rb +8 -0
  55. data/lib/gocr/version.rb +3 -0
  56. metadata +156 -0
@@ -0,0 +1,6 @@
1
+ require 'mkmf'
2
+
3
+ #extension_name = 'gocr'
4
+ #dir_config('gocr')
5
+ #create_makefile('gocr')
6
+ create_makefile 'gocr/gocr'
@@ -0,0 +1,436 @@
1
+ /*
2
+ This is a Optical-Character-Recognition program
3
+ Copyright (C) GPLv2 2000-2013 Joerg Schulenburg
4
+
5
+ This program is free software; you can redistribute it and/or
6
+ modify it under the terms of the GNU General Public License
7
+ as published by the Free Software Foundation; either version 2
8
+ of the License, or (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License
16
+ along with this program; if not, write to the Free Software
17
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
+
19
+ see README for EMAIL-address
20
+
21
+ sometimes I have written comments in german language, sorry for that
22
+
23
+ This file was retrieved from pgm2asc.cc of Joerg, in order to have
24
+ a library of the ocr-engine from Klaas Freitag
25
+
26
+ */
27
+ #include "config.h"
28
+ #include <stdlib.h>
29
+ #include <stdio.h>
30
+ #include <assert.h>
31
+ #include <string.h>
32
+ #ifdef HAVE_GETTIMEOFDAY
33
+ #include <sys/time.h>
34
+ #endif
35
+ #ifdef HAVE_UNISTD_H
36
+ #include <unistd.h>
37
+ #endif
38
+
39
+ #include "pnm.h"
40
+ #include "pgm2asc.h"
41
+ #include "pcx.h"
42
+ #include "ocr0.h" /* only_numbers */
43
+ #include "progress.h"
44
+ #include "version.h"
45
+ #include "ruby.h"
46
+
47
+ /*
48
+ #ifndef RSTRING_PTR
49
+ #define RSTRING_PTR(s) (RSTRING(s))
50
+ #endif
51
+ #ifndef RSTRING_LEN
52
+ #define RSTRING_LEN(s) (RSTRING(s))
53
+ #endif
54
+ */
55
+ static void out_version(int v) {
56
+ fprintf(stderr, " Optical Character Recognition --- gocr "
57
+ version_string " " release_string "\n"
58
+ " Copyright (C) 2001-2010 Joerg Schulenburg GPG=1024D/53BDFBE3\n"
59
+ " released under the GNU General Public License\n");
60
+ /* as recommended, (c) and license should be part of the binary */
61
+ /* no email because of SPAM, see README for contacting the author */
62
+ if (v)
63
+ fprintf(stderr, " use option -h for help\n");
64
+ if (v & 2)
65
+ exit(1);
66
+ return;
67
+ }
68
+
69
+ static void help(void) {
70
+ out_version(0);
71
+ /* output is shortened to essentials, see manual page for details */
72
+ fprintf(stderr,
73
+ " using: gocr [options] pnm_file_name # use - for stdin\n"
74
+ " options (see gocr manual pages for more details):\n"
75
+ " -h, --help\n"
76
+ " -i name - input image file (pnm,pgm,pbm,ppm,pcx,...)\n"
77
+ " -o name - output file (redirection of stdout)\n"
78
+ " -e name - logging file (redirection of stderr)\n"
79
+ " -x name - progress output to fifo (see manual)\n"
80
+ " -p name - database path including final slash (default is ./db/)\n");
81
+ fprintf(stderr, /* string length less than 509 bytes for ISO C89 */
82
+ " -f fmt - output format (ISO8859_1 TeX HTML XML UTF8 ASCII)\n"
83
+ " -l num - threshold grey level 0<160<=255 (0 = autodetect)\n"
84
+ " -d num - dust_size (remove small clusters, -1 = autodetect)\n"
85
+ " -s num - spacewidth/dots (0 = autodetect)\n"
86
+ " -v num - verbose (see manual page)\n"
87
+ " -c string - list of chars (debugging, see manual)\n"
88
+ " -C string - char filter (ex. hexdigits: ""0-9A-Fx"", only ASCII)\n"
89
+ " -m num - operation modes (bitpattern, see manual)\n");
90
+ fprintf(stderr, /* string length less than 509 bytes for ISO C89 */
91
+ " -a num - value of certainty (in percent, 0..100, default=95)\n"
92
+ " -u string - output this string for every unrecognized character\n");
93
+ fprintf(stderr, /* string length less than 509 bytes for ISO C89 */
94
+ " examples:\n"
95
+ "\tgocr -m 4 text1.pbm # do layout analyzis\n"
96
+ "\tgocr -m 130 -p ./database/ text1.pbm # extend database\n"
97
+ "\tdjpeg -pnm -gray text.jpg | gocr - # use jpeg-file via pipe\n"
98
+ "\n");
99
+ fprintf(stderr, " webpage: http://jocr.sourceforge.net/ (may out of date)\n");
100
+ fprintf(stderr, " mirror: http://www-e.uni-magdeburg.de/jschulen/ocr/\n");
101
+ exit(0);
102
+ }
103
+
104
+ #ifdef HAVE_GETTIMEOFDAY
105
+ /* from the glibc documentation */
106
+ static int timeval_subtract (struct timeval *result, struct timeval *x,
107
+ struct timeval *y) {
108
+
109
+ /* Perform the carry for the later subtraction by updating Y. */
110
+ if (x->tv_usec < y->tv_usec) {
111
+ int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
112
+ y->tv_usec -= 1000000 * nsec;
113
+ y->tv_sec += nsec;
114
+ }
115
+ if (x->tv_usec - y->tv_usec > 1000000) {
116
+ int nsec = (x->tv_usec - y->tv_usec) / 1000000;
117
+ y->tv_usec += 1000000 * nsec;
118
+ y->tv_sec -= nsec;
119
+ }
120
+
121
+ /* Compute the time remaining to wait.
122
+ `tv_usec' is certainly positive. */
123
+ result->tv_sec = x->tv_sec - y->tv_sec;
124
+ result->tv_usec = x->tv_usec - y->tv_usec;
125
+
126
+ /* Return 1 if result is negative. */
127
+ return x->tv_sec < y->tv_sec;
128
+ }
129
+ #endif
130
+
131
+ static void process_arguments(job_t *job, int argn, char *argv[])
132
+ {
133
+ int i;
134
+ char *s1;
135
+
136
+ assert(job);
137
+
138
+ if (argn <= 1) {
139
+ out_version(1);
140
+ exit(0);
141
+ }
142
+ #ifdef HAVE_PGM_H
143
+ pnm_init(&argn, &argv);
144
+ #endif
145
+
146
+ /* process arguments */
147
+ for (i = 1; i < argn; i++) {
148
+ if (strcmp(argv[i], "--help") == 0)
149
+ help(); /* and quits */
150
+ if (argv[i][0] == '-' && argv[i][1] != 0) {
151
+ s1 = "";
152
+ if (i + 1 < argn)
153
+ s1 = argv[i + 1];
154
+ switch (argv[i][1]) {
155
+ case 'h': /* help */
156
+ help();
157
+ break;
158
+ case 'i': /* input image file */
159
+ job->src.fname = s1;
160
+ i++;
161
+ break;
162
+ case 'e': /* logging file */
163
+ if (s1[0] == '-' && s1[1] == '\0') {
164
+ #ifdef HAVE_UNISTD_H
165
+ dup2(STDOUT_FILENO, STDERR_FILENO); /* -e /dev/stdout works */
166
+ #else
167
+ fprintf(stderr, "stderr redirection not possible without unistd.h\n");
168
+ #endif
169
+ }
170
+ else if (!freopen(s1, "w", stderr)) {
171
+ fprintf(stderr, "stderr redirection to %s failed\n", s1);
172
+ }
173
+ i++;
174
+ break;
175
+ case 'p': /* database path */
176
+ job->cfg.db_path=s1;
177
+ i++;
178
+ break;
179
+ case 'o': /* output file */
180
+ if (s1[0] == '-' && s1[1] == '\0') { /* default */
181
+ }
182
+ else if (!freopen(s1, "w", stdout)) {
183
+ fprintf(stderr, "stdout redirection to %s failed\n", s1);
184
+ };
185
+ i++;
186
+ break;
187
+ case 'f': /* output format */
188
+ if (strcmp(s1, "ISO8859_1") == 0) job->cfg.out_format=ISO8859_1; else
189
+ if (strcmp(s1, "TeX") == 0) job->cfg.out_format=TeX; else
190
+ if (strcmp(s1, "HTML") == 0) job->cfg.out_format=HTML; else
191
+ if (strcmp(s1, "XML") == 0) job->cfg.out_format=XML; else
192
+ if (strcmp(s1, "SGML") == 0) job->cfg.out_format=SGML; else
193
+ if (strcmp(s1, "UTF8") == 0) job->cfg.out_format=UTF8; else
194
+ if (strcmp(s1, "ASCII") == 0) job->cfg.out_format=ASCII; else
195
+ fprintf(stderr,"Warning: unknown format (-f %s)\n",s1);
196
+ i++;
197
+ break;
198
+ case 'c': /* list of chars (_ = not recognized chars) */
199
+ job->cfg.lc = s1;
200
+ i++;
201
+ break;
202
+ case 'C': /* char filter, default: NULL (all chars) */
203
+ /* ToDo: UTF8 input, wchar */
204
+ job->cfg.cfilter = s1;
205
+ i++;
206
+ break;
207
+ case 'd': /* dust size */
208
+ job->cfg.dust_size = atoi(s1);
209
+ i++;
210
+ break;
211
+ case 'l': /* grey level 0<160<=255, 0 for autodetect */
212
+ job->cfg.cs = atoi(s1);
213
+ i++;
214
+ break;
215
+ case 's': /* spacewidth/dots (0 = autodetect) */
216
+ job->cfg.spc = atoi(s1);
217
+ i++;
218
+ break;
219
+ case 'v': /* verbose mode */
220
+ job->cfg.verbose |= atoi(s1);
221
+ i++;
222
+ break;
223
+ case 'm': /* operation modes */
224
+ job->cfg.mode |= atoi(s1);
225
+ i++;
226
+ break;
227
+ case 'n': /* numbers only */
228
+ job->cfg.only_numbers = atoi(s1);
229
+ i++;
230
+ break;
231
+ case 'x': /* initialize progress output s1=fname */
232
+ ini_progress(s1);
233
+ i++;
234
+ break;
235
+ case 'a': /* set certainty */
236
+ job->cfg.certainty = atoi(s1);;
237
+ i++;
238
+ break;
239
+ case 'u': /* output marker for unrecognized chars */
240
+ job->cfg.unrec_marker = s1;
241
+ i++;
242
+ break;
243
+ default:
244
+ fprintf(stderr, "# unknown option use -h for help\n");
245
+ }
246
+ continue;
247
+ }
248
+ else /* argument can be filename v0.2.5 */ if (argv[i][0] != '-'
249
+ || argv[i][1] == '\0' ) {
250
+ job->src.fname = argv[i];
251
+ }
252
+ }
253
+ }
254
+
255
+ static void mark_start(job_t *job) {
256
+ assert(job);
257
+
258
+ if (job->cfg.verbose) {
259
+ out_version(0);
260
+ /* insert some helpful info for support */
261
+ fprintf(stderr, "# compiled: " __DATE__ );
262
+ #if defined(__GNUC__)
263
+ fprintf(stderr, " GNUC-%d", __GNUC__ );
264
+ #endif
265
+ #ifdef __GNUC_MINOR__
266
+ fprintf(stderr, ".%d", __GNUC_MINOR__ );
267
+ #endif
268
+ #if defined(__linux)
269
+ fprintf(stderr, " linux");
270
+ #elif defined(__unix)
271
+ fprintf(stderr, " unix");
272
+ #endif
273
+ #if defined(__WIN32) || defined(__WIN32__)
274
+ fprintf(stderr, " WIN32");
275
+ #endif
276
+ #if defined(__WIN64) || defined(__WIN64__)
277
+ fprintf(stderr, " WIN64");
278
+ #endif
279
+ #if defined(__VERSION__)
280
+ fprintf(stderr, " version " __VERSION__ );
281
+ #endif
282
+ fprintf(stderr, "\n");
283
+ fprintf(stderr,
284
+ "# options are: -l %d -s %d -v %d -c %s -m %d -d %d -n %d -a %d -C \"%s\"\n",
285
+ job->cfg.cs, job->cfg.spc, job->cfg.verbose, job->cfg.lc, job->cfg.mode,
286
+ job->cfg.dust_size, job->cfg.only_numbers, job->cfg.certainty,
287
+ job->cfg.cfilter);
288
+ fprintf(stderr, "# file: %s\n", job->src.fname);
289
+ #ifdef USE_UNICODE
290
+ fprintf(stderr,"# using unicode\n");
291
+ #endif
292
+ #ifdef HAVE_GETTIMEOFDAY
293
+ gettimeofday(&job->tmp.init_time, NULL);
294
+ #endif
295
+ }
296
+ }
297
+
298
+ static void mark_end(job_t *job) {
299
+ assert(job);
300
+
301
+ #ifdef HAVE_GETTIMEOFDAY
302
+ /* show elapsed time */
303
+ if (job->cfg.verbose) {
304
+ struct timeval end, result;
305
+ gettimeofday(&end, NULL);
306
+ timeval_subtract(&result, &end, &job->tmp.init_time);
307
+ fprintf(stderr,"Elapsed time: %d:%02d:%3.3f.\n", (int)result.tv_sec/60,
308
+ (int)result.tv_sec%60, (float)result.tv_usec/1000);
309
+ }
310
+ #endif
311
+ }
312
+
313
+ static int read_picture(job_t *job) {
314
+ int rc=0;
315
+ assert(job);
316
+
317
+ if (strstr(job->src.fname, ".pcx"))
318
+ readpcx(job->src.fname, &job->src.p, job->cfg.verbose);
319
+ else
320
+ rc=readpgm(job->src.fname, &job->src.p, job->cfg.verbose);
321
+ return rc; /* 1 for multiple images, -1 on error, 0 else */
322
+ }
323
+
324
+ /* subject of change, we need more output for XML (ToDo) */
325
+ void print_output(job_t *job) {
326
+ int linecounter = 0;
327
+ const char *line;
328
+
329
+ assert(job);
330
+
331
+ /* TODO: replace getTextLine-loop(line) by output_text() (libs have to use pipes)
332
+ simplify code 2010-09-26
333
+ */
334
+ linecounter = 0;
335
+ line = getTextLine(&(job->res.linelist), linecounter++);
336
+ while (line) {
337
+ /* notice: decode() is shiftet to getTextLine since 0.38 */
338
+ fputs(line, stdout);
339
+ if (job->cfg.out_format==HTML) fputs("<br />",stdout);
340
+ if (job->cfg.out_format!=XML) fputc('\n', stdout);
341
+ line = getTextLine(&(job->res.linelist), linecounter++);
342
+ }
343
+ free_textlines(&(job->res.linelist));
344
+ }
345
+
346
+ /* FIXME jb: remove JOB; renamed to OCR_JOB 2010-09-26 */
347
+ job_t *OCR_JOB;
348
+
349
+
350
+ char* gocr_recognize(char* filename) {
351
+ char* line;
352
+ int multipnm=1;
353
+ job_t job1, *job; /* fixme, dont want global variables for lib */
354
+ job=OCR_JOB=&job1;
355
+
356
+ setvbuf(stdout, (char *) NULL, _IONBF, 0); /* not buffered */
357
+
358
+ job_init(job); /* init cfg and db */
359
+ job->src.fname = filename;
360
+ /* load character data base (JS1002: now outside pgm2asc) */
361
+ if ( job->cfg.mode & 2 ) /* check for db-option flag */
362
+ load_db(job);
363
+ /* load_db uses readpnm() and would conflict with multi images */
364
+
365
+ job_init_image(job); /* single image */
366
+ mark_start(job);
367
+ read_picture(job);
368
+
369
+ pgm2asc(job);
370
+ mark_end(job);
371
+ line = getTextLine(&(job->res.linelist), 0);
372
+ job_free_image(job);
373
+ return line;
374
+ }
375
+
376
+
377
+ static VALUE image_recognize(VALUE self, VALUE arg) {
378
+ char* filename = StringValuePtr(arg);
379
+ return rb_str_new2( gocr_recognize(filename) );
380
+ }
381
+
382
+ /*
383
+ * @brief define ruby class GOCR::Image and method recognize
384
+ *
385
+ */
386
+ void Init_gocr() {
387
+ VALUE mGocr = rb_define_module("GOCR");
388
+ VALUE mImage = rb_define_class_under(mGocr, "Image", rb_cObject);
389
+ rb_define_singleton_method(mImage, "recognize", image_recognize, 1);
390
+ }
391
+
392
+
393
+ /* -------------------------------------------------------------
394
+ // ------ MAIN - replace this by your own aplication!
395
+ // ------------------------------------------------------------- */
396
+ //int main(int argn, char *argv[]) {
397
+ // int multipnm=1;
398
+ // job_t job1, *job; /* fixme, dont want global variables for lib */
399
+ // job=OCR_JOB=&job1;
400
+ //
401
+ // setvbuf(stdout, (char *) NULL, _IONBF, 0); /* not buffered */
402
+ //
403
+ // job_init(job); /* init cfg and db */
404
+ //
405
+ // process_arguments(job, argn, argv);
406
+ //
407
+ // /* load character data base (JS1002: now outside pgm2asc) */
408
+ // if ( job->cfg.mode & 2 ) /* check for db-option flag */
409
+ // load_db(job);
410
+ // /* load_db uses readpnm() and would conflict with multi images */
411
+ //
412
+ // while (multipnm==1) { /* multi-image loop */
413
+ //
414
+ // job_init_image(job); /* single image */
415
+ //
416
+ // mark_start(job);
417
+ //
418
+ // multipnm = read_picture(job);
419
+ // /* separation of main and rest for using as lib
420
+ // this will be changed later => introduction of set_option()
421
+ // for better communication to the engine */
422
+ // if (multipnm<0) break; /* read error */
423
+ //
424
+ // /* call main loop */
425
+ // pgm2asc(job);
426
+ //
427
+ // mark_end(job);
428
+ //
429
+ // print_output(job);
430
+ //
431
+ // job_free_image(job);
432
+ //
433
+ // }
434
+ //
435
+ // return ((multipnm<0)?multipnm:0); /* -1=255 on error, 0 ok */
436
+ //}
@@ -0,0 +1,290 @@
1
+ /*
2
+ This is a Optical-Character-Recognition program
3
+ Copyright (C) 2000-2010 Joerg Schulenburg
4
+
5
+ This program is free software; you can redistribute it and/or
6
+ modify it under the terms of the GNU General Public License
7
+ as published by the Free Software Foundation; either version 2
8
+ of the License, or (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License
16
+ along with this program; if not, write to the Free Software
17
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
+
19
+ see README for EMAIL-address
20
+
21
+ sometimes I have written comments in german language, sorry for that
22
+
23
+ - look for ??? for preliminary code
24
+ */
25
+
26
+ /* General headerfile with gocr-definitions */
27
+
28
+ #ifndef __GOCR_H__
29
+ #define __GOCR_H__
30
+
31
+ #include "pnm.h"
32
+ #include "unicode.h" /* FORMAT definition */
33
+ #include "list.h"
34
+ #include <stddef.h>
35
+ #ifdef HAVE_GETTIMEOFDAY
36
+ #include <sys/time.h>
37
+ #endif
38
+
39
+ /*
40
+ * wchar_t should always exist (ANSI), but WCHAR.H is sometimes missing
41
+ * USE_UNICODE should be removed or replaced by HAVE_WCHAR_H in future
42
+ */
43
+ #ifdef HAVE_WCHAR_H
44
+ #define USE_UNICODE 1
45
+ #endif
46
+
47
+ /* extern "C"{ */
48
+ /* ------------------------ feature extraction ----------------- */
49
+ #define AT 7 /* mark */
50
+ #define M1 1 /* mark */
51
+ enum direction {
52
+ UP=1, DO, RI, LE
53
+ };
54
+ typedef enum direction DIRECTION;
55
+ #define ST 7 /* stop */
56
+ /* ------------------------------------------------------------- */
57
+ /* detect maximas in of line overlapps (return in %) and line koord */
58
+ #define HOR 1 /* horizontal */
59
+ #define VER 2 /* vertikal */
60
+ #define RIS 3 /* rising=steigend */
61
+ #define FAL 4 /* falling=fallend */
62
+
63
+ #define MAXlines 1024
64
+
65
+ /* ToDo: if we have a tree instead of a list, a line could be a node object */
66
+ struct tlines {
67
+ int num;
68
+ int dx, dy; /* direction of text lines (straight/skew) */
69
+ int m1[MAXlines], /* start of line = upper bound of 'A' */
70
+ m2[MAXlines], /* upper bound of 'e' */
71
+ m3[MAXlines], /* lower bound of 'e' = baseline */
72
+ m4[MAXlines]; /* stop of line = lower bound of 'q' */
73
+ /* ToDo: add sureness per m1,m2 etc? */
74
+ int x0[MAXlines],
75
+ x1[MAXlines]; /* left and right border */
76
+ int wt[MAXlines]; /* weight, how sure thats correct in percent, v0.41 */
77
+ int pitch[MAXlines]; /* word pitch (later per box?), v0.41 */
78
+ int mono[MAXlines]; /* spacing type, 0=proportional, 1=monospaced */
79
+ };
80
+
81
+ #define NumAlt 10 /* maximal number of alternative chars (table length) */
82
+ #define MaxNumFrames 8 /* maximum number of frames per char/box */
83
+ #define MaxFrameVectors 128 /* maximum vectors per frame (*8=1KB/box) */
84
+ /* ToDo: use only malloc_box(),free_box(),copybox() for creation, destroy etc.
85
+ * adding reference_counter to avoid pointer pointing to freed box
86
+ */
87
+ struct box { /* this structure should contain all pixel infos of a letter */
88
+ int x0,x1,y0,y1,x,y,dots; /* xmin,xmax,ymin,ymax,reference-pixel,i-dots */
89
+ int num_boxes, /* 1 "abc", 2 "!i?", 3 "&auml;" (composed objects) 0.41 */
90
+ num_subboxes; /* 1 for "abdegopqADOPQR", 2 for "B" (holes) 0.41 */
91
+ wchar_t c; /* detected char (same as tac[0], obsolete?) */
92
+ wchar_t modifier; /* default=0, see compose() in unicode.c */
93
+ int num; /* same number = same char */
94
+ int line; /* line number (points to struct tlines lines) */
95
+ int m1,m2,m3,m4; /* m2 = upper boundary, m3 = baseline */
96
+ /* planed: sizeof hole_1, hole_2, certainty (run1=100%,run2=90%,etc.) */
97
+ pix *p; /* pointer to pixmap (v0.2.5) */
98
+ /* tac, wac is used together with setac() to manage very similar chars */
99
+ int num_ac; /* length of table (alternative chars), default=0 */
100
+ wchar_t tac[NumAlt]; /* alternative chars, only used by setac(),getac() */
101
+ int wac[NumAlt]; /* weight of alternative chars */
102
+ char *tas[NumAlt]; /* alternative UTF8-strings or XML codes if tac[]=0 */
103
+ /* replacing old obj */
104
+ /* ToDo: (*obj)[NumAlt] + olen[NumAlt] ??? */
105
+ /* ToDo: bitmap for possible Picture|Object|Char ??? */
106
+ /* char *obj; */ /* pointer to text-object ... -> replaced by tas[] */
107
+ /* ... (melted chars, barcode, picture coords, ...) */
108
+ /* must be freed before box is freed! */
109
+ /* do _not_ copy only the pointer to object */
110
+ /* --------------------------------------------------------
111
+ * extension since v0.41 js05, Store frame vectors,
112
+ * which is a table of vectors sourrounding the char and its
113
+ * inner white holes. The advantage is the independence from
114
+ * resolution, handling of holes, overlap and rotation.
115
+ * --------------------------------------------------------- */
116
+ int num_frames; /* number of frames: 1 for cfhklmnrstuvwxyz */
117
+ /* 2 for abdegijopq */
118
+ int frame_vol[MaxNumFrames]; /* volume inside frame +/- (black/white) */
119
+ int frame_per[MaxNumFrames]; /* periphery, summed length of vectors */
120
+ int num_frame_vectors[MaxNumFrames]; /* index to next frame */
121
+ /* biggest frame should be stored first (outer frame) */
122
+ /* biggest has the maximum pair distance */
123
+ /* num vector loops */
124
+ int frame_vector[MaxFrameVectors][2]; /* may be 16*int=fixpoint_number */
125
+
126
+ };
127
+ typedef struct box Box;
128
+
129
+ /* true if the coordination pair (a,b) is outside the image p */
130
+ #define outbounds(p, a, b) (a < 0 || b < 0 || a >= (p)->x || b >= (p)->y)
131
+
132
+ /* ToDo: this structure seems to be obsolete, remove it */
133
+ typedef struct path {
134
+ int start; /* color at the beginning of the path, (0=white, 1=black) */
135
+ int *x; /* x coordinates of transitions */
136
+ int *y; /* y coordinates of transitions */
137
+ int num; /* current number of entries in x or y */
138
+ int max; /* maximum number of entries in x or y */
139
+ /* (if more values need to be stored, the arrays are enlarged) */
140
+ } path_t;
141
+
142
+ /* job_t contains all information needed for an OCR task */
143
+ typedef struct job_s {
144
+ struct { /* source data */
145
+ char *fname; /* input filename; default value: "-" */
146
+ pix p; /* source pixel data, pixelmap 8bit gray */
147
+ } src;
148
+ struct { /* temporary stuff, e.g. buffers */
149
+ #ifdef HAVE_GETTIMEOFDAY
150
+ struct timeval init_time; /* starting time of this job */
151
+ #endif
152
+ pix ppo; /* pixmap for visual debugging output, obsolete */
153
+
154
+ /* sometimes recognition function is called again and again, if result was 0
155
+ n_run tells the pixel function to return alternative results */
156
+ int n_run; /* num of run, if run_2 critical pattern get other results */
157
+ /* used for 2nd try, pixel uses slower filter function etc. */
158
+ List dblist; /* list of boxes loaded from the character database */
159
+ } tmp;
160
+ struct { /* results */
161
+ List boxlist; /* store every object in a box, which contains */
162
+ /* the characteristics of the object (see struct box) */
163
+ List linelist; /* recognized text lines after recognition */
164
+
165
+ struct tlines lines; /* used to access to line-data (statistics) */
166
+ /* here the positions (frames) of lines are */
167
+ /* stored for further use */
168
+ int avX,avY; /* average X,Y (avX=sumX/numC) */
169
+ int sumX,sumY,numC; /* sum of all X,Y; num chars */
170
+ } res;
171
+ struct { /* configuration */
172
+ int cs; /* critical grey value (pixel<cs => black pixel) */
173
+ /* range: 0..255, 0 means autodetection */
174
+ int spc; /* spacewidth/dots (0 = autodetect); default value: 0 */
175
+ int mode; /* operation modes; default value: 0 */
176
+ /* operation mode (see --help) */
177
+ int dust_size; /* dust size; default value: 10 */
178
+ int only_numbers; /* numbers only; default value: 0 */
179
+ int verbose; /* verbose mode; default value: 0 */
180
+ /* verbose option (see --help) */
181
+ FORMAT out_format; /* output format; default value: ISO8859_1 */
182
+ char *lc; /* debuglist of chars (_ = not recognized chars) */
183
+ /* default value: "_" */
184
+ char *db_path; /* pathname for database; default value: NULL */
185
+ char *cfilter; /* char filter; default value: NULL, ex: "A-Za-z" */
186
+ /* limit of certainty where chars are accepted as identified */
187
+ int certainty; /* in units of 100 (percent); 0..100; default 95 */
188
+ char *unrec_marker; /* output this string for every unrecognized char */
189
+ } cfg;
190
+ } job_t;
191
+
192
+ /* initialze job structure */
193
+ void job_init(job_t *job); /* once for cfg and db */
194
+ void job_init_image(job_t *job); /* for each of a multiimage */
195
+
196
+ /* free job structure */
197
+ void job_free_image(job_t *job); /* for each of a multiimage */
198
+
199
+ /* FIXME jb: remove JOB; 2010-09-25 renamed to OCR_JOB */
200
+ /* as a first step OCR_JOB will be remain in DO_DEBUG mode only */
201
+ extern job_t *OCR_JOB;
202
+
203
+ /* calculate the overlapp of the line (0-1) with black points
204
+ * by rekursiv bisection
205
+ * (evl. Fehlertoleranz mit pixel in Umgebung dx,dy suchen) (umschaltbar) ???
206
+ * MidPoint Line Algorithm (Bresenham) Foley: ComputerGraphics better?
207
+ * will be replaced by vector functions
208
+ */
209
+
210
+ /* gerade y=dy/dx*x+b, implizit d=F(x,y)=dy*x-dx*y+b*dx=0
211
+ * incrementell y(i+1)=m*(x(i)+1)+b, F(x+1,y+1)=f(F(x,y)) */
212
+ int get_line(int x0, int y0, int x1, int y1, pix *p, int cs, int ret);
213
+ int get_line2(int x0, int y0, int x1, int y1, pix *p, int cs, int ret);
214
+
215
+ /* look for white 0x02 or black 0x01 dots (0x03 = white+black) */
216
+ char get_bw(int x0, int x1, int y0, int y1,
217
+ pix *p, int cs,int mask);
218
+
219
+ /* look for black crossing a line x0,y0,x1,y1
220
+ * follow line and count crossings ([white]-black-transitions)
221
+ */
222
+ int num_cross(int x0, int x1, int y0, int y1,
223
+ pix *p, int cs);
224
+
225
+ /* memory allocation with error checking */
226
+ void *xrealloc(void *ptr, size_t size);
227
+
228
+ /* follow a line x0,y0,x1,y1 recording locations of transitions,
229
+ * return count of transitions
230
+ */
231
+ int follow_path(int x0, int x1, int y0, int y1, pix *p, int cs, path_t *path);
232
+
233
+ /* -------------------------------------------------------------
234
+ * mark edge-points
235
+ * - first move forward until b/w-edge
236
+ * - more than 2 pixel?
237
+ * - loop around
238
+ * - if forward pixel : go up, rotate right
239
+ * - if forward no pixel : rotate left
240
+ * - stop if found first 2 pixel in same order
241
+ * mit an rechter-Wand-entlang-gehen strategie
242
+ * --------------------------------------------------------------
243
+ * turmite game: inp: start-x,y, regel r_black=UP,r_white=RIght until border
244
+ * out: last-position
245
+ * Zaehle dabei, Schritte,Sackgassen,xmax,ymax,ro-,ru-,lo-,lu-Ecken
246
+ * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
247
+ *
248
+ * is this the right place for declaration?
249
+ */
250
+ void turmite(pix *p, int *x, int *y,
251
+ int x0, int x1, int y0, int y1, int cs, int rw, int rb);
252
+
253
+ /* test if points are connected via t-pixel (rekursiv!) */
254
+ int joined(pix *p, int x0, int y0, int x1, int y1, int cs);
255
+
256
+ /* move from x,y to direction r until pixel or l steps
257
+ * return number of steps
258
+ */
259
+ int loop(pix *p, int x, int y, int l, int cs, int col, DIRECTION r);
260
+
261
+ #define MAX_HOLES 3
262
+ typedef struct list_holes {
263
+ int num; /* numbers of holes, initialize with 0 */
264
+ struct hole_s {
265
+ int size,x,y,x0,y0,x1,y1; /* size, start point, outer rectangle */
266
+ } hole[MAX_HOLES];
267
+ } holes_t;
268
+
269
+ /* look for white holes surrounded by black points
270
+ * at moment white point with black in all four directions
271
+ */
272
+ int num_hole(int x0, int x1, int y0, int y1, pix *p, int cs, holes_t *holes);
273
+
274
+ /* count for black nonconnected objects --- used for i,auml,ouml,etc. */
275
+ int num_obj(int x0, int x1, int y0, int y1, pix *p, int cs);
276
+
277
+ int distance( pix *p1, struct box *box1, /* box-frame */
278
+ pix *p2, struct box *box2, int cs);
279
+
280
+ /* call the OCR engine ;) */
281
+ /* char whatletter(struct box *box1,int cs); */
282
+
283
+ /* declared in pixel.c */
284
+ /* getpixel() was pixel() but it may collide with netpnm pixel declaration */
285
+ int getpixel(pix *p, int x, int y);
286
+ int marked(pix *p, int x, int y);
287
+ void put(pix * p, int x, int y, int ia, int io);
288
+
289
+ /* } */ /* extern C */
290
+ #endif /* __GOCR_H__ */