gocr-ruby 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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__ */