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,11 @@
1
+ #ifndef _BARCODE_H
2
+ #define _BARCODE_H
3
+ #include "pnm.h"
4
+
5
+ /*
6
+ detect barcode and add a string to the box (obj-pointer)
7
+ */
8
+
9
+ int detect_barcode(job_t *job);
10
+
11
+ #endif
@@ -0,0 +1,496 @@
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
+ */
22
+
23
+ #include <stdio.h>
24
+ #include <stdlib.h>
25
+ #include <assert.h>
26
+ #include <string.h>
27
+ #include "gocr.h"
28
+ #include "pgm2asc.h"
29
+
30
+ /* for sorting letters by position on the image
31
+ / ToDo: - use function same line like this or include lines.m1 etc. */
32
+ int box_gt(struct box *box1, struct box *box2) {
33
+ // box1 after box2 ?
34
+ if (box1->line > box2->line)
35
+ return 1;
36
+ if (box1->line < box2->line)
37
+ return 0;
38
+ if (box1->x0 > box2->x1) // before
39
+ return 1;
40
+ if (box1->x1 < box2->x0) // before
41
+ return 0;
42
+ if (box1->x0 > box2->x0) // before, overlapping!
43
+ return 1;
44
+
45
+ return 0;
46
+ }
47
+
48
+ /* --- copy part of pix p into new pix b ---- len=10000
49
+ * Returns: 0 on success, 1 on error.
50
+ * naming it as copybox isnt very clever, because it dont have to do with the
51
+ * char boxes (struct box)
52
+ */
53
+ int copybox (pix * p, int x0, int y0, int dx, int dy, pix * b, int len) {
54
+ int x, y;
55
+
56
+ /* test boundaries */
57
+ if (b->p == NULL || dx < 0 || dy < 0 || dx * dy > len) {
58
+ fprintf(stderr, " error-copybox x=%5d %5d d=%5d %5d\n", x0, y0, dx, dy);
59
+ return 1;
60
+ }
61
+
62
+ b->x = dx;
63
+ b->y = dy;
64
+ b->bpp = 1;
65
+ #ifdef FASTER_INCOMPLETE
66
+ for (y = 0; y < dy; y++)
67
+ memcpy(&pixel_atp(b, 0, y), &pixel_atp(p, x0, y + y0 ), dx);
68
+ // and unmark pixels
69
+ #else
70
+ for (y = 0; y < dy; y++)
71
+ for (x = 0; x < dx; x++)
72
+ pixel_atp(b, x, y) = getpixel(p, x + x0, y + y0);
73
+ #endif
74
+
75
+ return 0;
76
+ }
77
+
78
+ /* reset table of alternative chars (and free memory) */
79
+ int reset_box_ac(struct box *box){
80
+ int i;
81
+ for (i=0; i<box->num_ac; i++)
82
+ if (box->tas[i]) {
83
+ /* fprintf(stderr,"DBG free_s[%d] %p %s\n",i,box->tas[i],box->tas[i]); */
84
+ free(box->tas[i]);
85
+ box->tas[i]=0; /* prevent double freeing */
86
+ }
87
+ box->num_ac=0; /* mark as freed */
88
+ return 0;
89
+ }
90
+
91
+ /* ini or copy a box: get memory for box and initialize the memory */
92
+ struct box *malloc_box (struct box *inibox) {
93
+ struct box *buf;
94
+ int i;
95
+
96
+ buf = (struct box *) malloc(sizeof(struct box));
97
+ if (!buf)
98
+ return NULL;
99
+ if (inibox) {
100
+ memcpy(buf, inibox, sizeof(struct box));
101
+ /* only pointer are copied, we want to copy the contents too */
102
+ for (i=0;i<inibox->num_ac;i++) {
103
+ if (inibox->tas[i]) {
104
+ buf->tas[i]=(char *)malloc(strlen(inibox->tas[i])+1);
105
+ memcpy(buf->tas[i], inibox->tas[i], strlen(inibox->tas[i])+1);
106
+ }
107
+ }
108
+ }
109
+ else { /* ToDo: init it */
110
+ buf->num_ac=0;
111
+ buf->num_frames=0;
112
+ }
113
+ /* fprintf(stderr,"\nDBG ini_box %p",buf); */
114
+ return buf;
115
+ }
116
+
117
+ /* free memory of box */
118
+ int free_box (struct box *box) {
119
+ if (!box) return 0;
120
+ /* fprintf(stderr,"DBG free_box %p\n",box); out_x(box); */
121
+ reset_box_ac(box); /* free alternative char table */
122
+ free(box); /* free the box memory */
123
+ return 0;
124
+ }
125
+
126
+ /* simplify the vectorgraph,
127
+ * but what is the best way?
128
+ * a) melting two neighbouring vectors with nearly same direction?
129
+ * (nearest angle to pi)
130
+ * b) melting three neigbours with smallest area?
131
+ * ToDo:
132
+ * mode = 0 - only lossless
133
+ * mode = 1 - reduce one vector, smallest possible loss
134
+ * mode = 2 - remove jitter (todo, or somewhere else)
135
+ * ToDo: include also loop around (last - first element)
136
+ * ToDo: reduce by 10..50%
137
+ */
138
+ int reduce_vectors ( struct box *box1, int mode ) {
139
+ int i1, i2, nx, ny, mx, my, len,
140
+ minlen=1024, /* minlength of to neighbouring vectors */
141
+ besti1=0, /* frame for best reduction */
142
+ besti2=2; /* vector replacing its predecessor */
143
+ double sprod, maxsprod=-1;
144
+ if (mode!=1) fprintf(stderr,"ERR not supported yet, ToDo\n");
145
+ for (i2=1,i1=0; i1<box1->num_frames; i1++) { /* every frame */
146
+ for (;i2<box1->num_frame_vectors[i1]-1; i2++) { /* every vector */
147
+ /* predecessor n */
148
+ nx = box1->frame_vector[i2-0][0] - box1->frame_vector[i2-1][0];
149
+ ny = box1->frame_vector[i2-0][1] - box1->frame_vector[i2-1][1];
150
+ /* successor m */
151
+ mx = box1->frame_vector[i2+1][0] - box1->frame_vector[i2-0][0];
152
+ my = box1->frame_vector[i2+1][1] - box1->frame_vector[i2-0][1];
153
+ /* angle is w = a*b/(|a|*|b|) = 1 means parallel */
154
+ /* normalized: minimize w^2 = (a*b/(|a|*|b|)-1)^2 */
155
+ /* -1=90grd, 0=0grd, -2=180grd */
156
+ sprod = /* fabs */(abs(nx*mx+ny*my)*(nx*mx+ny*my)
157
+ /(1.*(nx*nx+ny*ny)*(mx*mx+my*my))-1);
158
+ if (sprod<0) sprod=-sprod;
159
+ len = (mx*mx+my*my)*(nx*nx+ny*ny); /* sum lengths^2 */
160
+ // ..c ###c ... .. ...
161
+ // .b. len=2+2 #b.. len=2+5 #bc len=1+2 bc len=1+1 b#a len=4+5
162
+ // a.. spr=0 a... spr=1/10 a.. spr=1/4 a. spr=1 ##c spr=9/5
163
+ //
164
+ if ( len* sprod* sprod* sprod* sprod
165
+ <minlen*maxsprod*maxsprod*maxsprod*maxsprod
166
+ || maxsprod<0) /* Bad! ToDo! */
167
+ { maxsprod=sprod; besti1=i1; besti2=i2; minlen=len; }
168
+ }
169
+ }
170
+ if (box1->num_frames>0)
171
+ for (i2=besti2; i2<box1->num_frame_vectors[ box1->num_frames-1 ]-1; i2++) {
172
+ box1->frame_vector[i2][0]=box1->frame_vector[i2+1][0];
173
+ box1->frame_vector[i2][1]=box1->frame_vector[i2+1][1];
174
+ }
175
+ for (i1=besti1; i1<box1->num_frames; i1++)
176
+ box1->num_frame_vectors[i1]--;
177
+ // fprintf(stderr,"\nDBG_reduce_vectors i= %d nv= %d sprod=%f len2=%d\n# ...",
178
+ // besti2,box1->num_frame_vectors[ box1->num_frames-1 ],maxsprod,minlen);
179
+ // out_x(box1);
180
+ return 0;
181
+ }
182
+
183
+ /* add the contents of box2 to box1
184
+ * especially add vectors of box2 to box1
185
+ */
186
+ int merge_boxes( struct box *box1, struct box *box2 ) {
187
+ int i1, i2, i3, i4;
188
+ struct box tmpbox, *bsmaller, *bbigger; /* for mixing and sorting */
189
+ /* DEBUG, use valgrind to check uninitialized memory */
190
+ #if 0
191
+ fprintf(stderr,"\nDBG merge_boxes_input:"); out_x(box1); out_x(box2);
192
+ #endif
193
+ /* pair distance is to expendable, taking borders is easier */
194
+ // JS-2010-09 fix bug width=1
195
+ if ((box2->x1 - box2->x0 + 1)*(box2->y1 - box2->y0 + 1)
196
+ >(box1->x1 - box1->x0 + 1)*(box1->y1 - box1->y0 + 1)) {
197
+ bbigger=box2; bsmaller=box1; }
198
+ else {
199
+ bbigger=box1; bsmaller=box2; } // if called by glue_holes_inside_chars()
200
+ // fprintf(stderr,"\n y bigger"); out_x(bbigger); out_x(bsmaller);
201
+ /* ToDo: does not work if a third box is added */
202
+ if (box2->y0>box1->y1 || box2->y1<box1->y0
203
+ || box2->x0>box1->x1 || box2->x1<box1->x0) {
204
+ box1->num_boxes += box2->num_boxes; /* num separate objects 2=ij */
205
+ // if ( 4 * box2->y1 < 3*box1->y0 + box1->y1
206
+ // && box2->y0 < box1->y0 ) (box1->dots)++; // 2010-09-24 ???
207
+ if ( 4 * box1->y1 < 3*box2->y0 + box2->y1
208
+ && box1->y0 < box2->y0 ) (box2->dots)++; // 2010-09-24 :
209
+ } else {
210
+ if (box2->num_boxes>box1->num_boxes) box1->num_boxes=box2->num_boxes;
211
+ // 2010-09 subboxes are already counted, do not count twice!
212
+ box1->num_subboxes = bbigger->num_subboxes; /* num holes 1=abdepq 2=B */
213
+ // box1->num_subboxes += box2->num_subboxes+1; /* num holes 1=abdepq 2=B */
214
+ }
215
+ box1->dots += box2->dots; /* num i-dots ??? */
216
+ if ( box2->x0 < box1->x0 ) box1->x0 = box2->x0;
217
+ if ( box2->x1 > box1->x1 ) box1->x1 = box2->x1;
218
+ if ( box2->y0 < box1->y0 ) box1->y0 = box2->y0;
219
+ if ( box2->y1 > box1->y1 ) box1->y1 = box2->y1;
220
+ i1 = i2 = 0;
221
+ if (bbigger->num_frames)
222
+ i1 = bbigger->num_frame_vectors[ bbigger->num_frames - 1 ];
223
+ if (bsmaller->num_frames)
224
+ i2 = bsmaller->num_frame_vectors[ bsmaller->num_frames - 1 ];
225
+ while (i1+i2 > MaxFrameVectors) {
226
+ if (i1>i2) { reduce_vectors( bbigger, 1 ); i1--; }
227
+ else { reduce_vectors( bsmaller, 1 ); i2--; }
228
+ }
229
+ /* if i1+i2>MaxFrameVectors simplify the vectorgraph */
230
+ /* if sum num_frames>MaxNumFrames through shortest graph away and warn */
231
+ /* first copy the bigger box */
232
+ memcpy(&tmpbox, bbigger, sizeof(struct box));
233
+ /* attach the smaller box */
234
+ for (i4=i3=0; i3<bsmaller->num_frames; i3++) {
235
+ if (tmpbox.num_frames>=MaxNumFrames) break;
236
+
237
+ for (; i4<bsmaller->num_frame_vectors[i3]; i4++) {
238
+ memcpy(tmpbox.frame_vector[i1],
239
+ bsmaller->frame_vector[i4],2*sizeof(int));
240
+ i1++;
241
+ }
242
+ tmpbox.num_frame_vectors[ tmpbox.num_frames ] = i1;
243
+ tmpbox.frame_vol[ tmpbox.num_frames ] = bsmaller->frame_vol[ i3 ];
244
+ tmpbox.frame_per[ tmpbox.num_frames ] = bsmaller->frame_per[ i3 ];
245
+ tmpbox.num_frames++;
246
+ if (tmpbox.num_frames>=MaxNumFrames) {
247
+ if (OCR_JOB->cfg.verbose)
248
+ fprintf(stderr,"\nDBG merge_boxes MaxNumFrames reached");
249
+ break;
250
+ }
251
+ }
252
+ /* copy tmpbox to destination */
253
+ box1->num_frames = tmpbox.num_frames;
254
+ memcpy(box1->num_frame_vectors,
255
+ tmpbox.num_frame_vectors,sizeof(int)*MaxNumFrames);
256
+ memcpy(box1->frame_vol,
257
+ tmpbox.frame_vol,sizeof(int)*MaxNumFrames);
258
+ memcpy(box1->frame_per,
259
+ tmpbox.frame_per,sizeof(int)*MaxNumFrames);
260
+ memcpy(box1->frame_vector,
261
+ tmpbox.frame_vector,sizeof(int)*2*MaxFrameVectors);
262
+ #if 0
263
+ if ((OCR_JOB->cfg.verbose&48)==48) {
264
+ fprintf(stderr,"\nDBG merge_boxes_result:"); out_x(box1); }
265
+ #endif
266
+ return 0;
267
+ }
268
+
269
+ /* used for division of glued chars
270
+ * after a box is splitted into 2, where vectors are copied to both,
271
+ * vectors outside the new box are cutted and thrown away,
272
+ * later replaced by
273
+ * - 1st remove outside vectors with outside neighbours (complete frames?)
274
+ * add vector on outside vector with inside neighbours
275
+ * care about connections through box between outside vectors
276
+ * - 2nd reduce outside crossings (inclusive splitting frames if necessary)
277
+ * depending on direction (rotation) of outside connections
278
+ * - 3th shift outside vectors to crossing points
279
+ * - split add this points, connect only in-out...out-in,
280
+ * - cutting can result in more (fi) or less objects (ke)
281
+ * ToDo:
282
+ * dont connect --1---4--------3----2-- new-y1 (inside above not drawn)
283
+ * \ \-<<<<-/ / outside
284
+ * \---->>>>-----/ old-y1
285
+ * |======| subtractable?
286
+ *
287
+ * only connect --1---2--------3----4-- new-y1
288
+ * \>>/ \>>>/ old-y1 outside
289
+ * ToDo: what about cutting 2 frames (example: 2fold melted MN,ke)
290
+ * better restart framing algo (modified pgm2asc.frame_vector())?
291
+ * (would be require pixel last 3 bits modifications?)
292
+ *
293
+ * ToDo: new vol, per
294
+ * sample: tmp08/gocr0810* 2010-10-12
295
+ frame 0 ( +66, 50,21)
296
+ #00 0 0 #01 0 8 #02 0 6 #03 1 5 #04 4 8 #05 5 8 #06 6 7
297
+ #07 7 8 #08 11 8 #09 8 8 #10 6 6 #11 7 5 #12 12 5 #13 12 3
298
+ #14 11 2 #15 7 2 #16 6 3 #17 5 2 #18 4 2 #19 1 5 #20 0 4
299
+ frame 1 ( -10, 13, 8)
300
+ #21 4 3 #22 5 2 #23 6 3 #24 6 7 #25 5 8 #26 2 5 #27 2 4
301
+ #28 3 3
302
+ frame 2 ( -8, 12, 7)
303
+ #29 7 3 #30 8 2 #31 10 2 #32 12 4 #33 11 5 #34 7 5 #35 6 4
304
+ # list pattern d= 13 9
305
+ $............ @............<-
306
+ @............ @............
307
+ @...$$.$$@$$. @...@@.@@@@@.<
308
+ @..$$.$$...@$ @..@@.@@...@@
309
+ $.$...$.....$ @.@...@.....@
310
+ @$$...@$@@@$$ @@@...@@@@@@@
311
+ $.@@..$...... @.@@..@......
312
+ @..@@.$@..... @..@@.@@.....
313
+ $...$$.$$@@$. @...@@.@@@@@.<-
314
+ ^cut ^cut
315
+ 1st) get a list of cutting positions and sort them (going along border):
316
+ [#05-#06(5,8,io) #16-#17(5,2,oi)] [#22-#23(5,2,io) #24-#25(5,8,oi)]
317
+ [#05-#06(5,8,io) [#24-#25(5,8,oi) #22-#23(5,2,io)] #16-#17(5,2,oi)]
318
+ // positive rotation momentum io(0)->io(1)->oi(0)->oi(1)->back
319
+ // io=inside_to_outside oi=outside_to_inside
320
+ 2nd)
321
+ rebuild frames ... #04 #05 - #25 #26 #27 #28 #21 #22 #23 - #17 #18 ...
322
+ */
323
+ #if 0 // new version 1010-10 works on cutting multiple frames
324
+ #define MAXNUMCUTS 8 // used in function cut_box() only
325
+ int cut_box( struct box *box1) {
326
+ int i1, i2, i3, i4, i4l, i5, x, y, lx, ly, dbg=0;
327
+ int cut_num = 0, // number of cuts
328
+ cut_idx[MAXNUMCUTS], // index to cutted vector
329
+ cut_dir[MAXNUMCUTS]; // direction of vector inside_outside=1
330
+ // outside_inside=2
331
+ struct box tmpbox; // = (*box1); temp. buffer, after some corrections
332
+ #ifdef DO_DEBUG
333
+ if (OCR_JOB->cfg.verbose) dbg=1+2; // debug level, enlarge to get more output
334
+ #endif
335
+ if (dbg) fprintf(stderr,"\n cut box x= %3d %3d", box1->x0, box1->y0);
336
+ /* check if complete frames are outside the box */
337
+ for (i1=0; i1<box1->num_frames; i1++){
338
+ if (dbg>2) fprintf(stderr,"\n checking frame %d ", i1);
339
+ /* using frame_per as marker first (recalculate later) */
340
+ i2 = ((i1)?box1->num_frame_vectors[ i1-1 ]:0); // start of this frame
341
+ i3 = box1->num_frame_vectors[ i1 ]; // start of next frame
342
+ x = box1->frame_vector[ i3-1 ][0]; /* initial */
343
+ y = box1->frame_vector[ i3-1 ][1]; /* initial */
344
+ i4l = i3 - 1; // initial index of last vector
345
+ if (x<box1->x0 || x>box1->x1 || y<box1->y0 || y>box1->y1) i5=1; // outside
346
+ for (i4=i2; i4 < i3; i4++) {
347
+ lx = x; /* last x = vector[i4l] */
348
+ ly = y; /* last y = vector[i4l] */
349
+ x = box1->frame_vector[i4][0];
350
+ y = box1->frame_vector[i4][1];
351
+ // fprintf(stderr,"DBG LEV3 i4= %3d xy= %3d %3d",i4,x,y);
352
+ /* check if outside */
353
+ if (x<box1->x0 || x>box1->x1 || y<box1->y0 || y>box1->y1) { // outside
354
+ /* replace by nearest point at border, ToDo: better crossingpoint */
355
+ if (i5==0) { /* inside_to_outside, wrong if it starts outside */
356
+ if (x < box1->x0) x = box1->frame_vector[i4][0] = box1->x0;
357
+ if (x > box1->x1) x = box1->frame_vector[i4][0] = box1->x1;
358
+ if (y < box1->y0) y = box1->frame_vector[i4][1] = box1->y0;
359
+ if (y > box1->y1) y = box1->frame_vector[i4][1] = box1->y1;
360
+ if (cut_num<MAXCUTNUM) {
361
+ cut_idx[cut_num] = i4;
362
+ cut_dir[cut_num] = 1; // inside_to_outside
363
+ cut_num++;
364
+ }
365
+ /* search other frames for near outside_to_inside and copy frame in */
366
+ }
367
+ i5 = 1; // flag: we_are_outside_of_box
368
+ } else if (i5==1) { /* outside_to_inside */
369
+ /* ToDo: better crossing point last vector and border */
370
+ if (lx < box1->x0) lx = box1->x0;
371
+ if (lx > box1->x1) lx = box1->x1;
372
+ if (ly < box1->y0) ly = box1->y0;
373
+ if (ly > box1->y1) ly = box1->y1;
374
+ box1->frame_vector[i4l][0] = lx;
375
+ box1->frame_vector[i4l][1] = ly;
376
+ if (cut_num<MAXCUTNUM) {
377
+ cut_idx[cut_num] = i4l;
378
+ cut_dir[cut_num] = 2; // outside_to_inside
379
+ cut_num++;
380
+ }
381
+ i5 = 0; // flag: we_are_inside_of_box
382
+ }
383
+ i4l=i4; // index of last vector
384
+ // fprintf(stderr," xy= %3d %3d\n",x,y);
385
+ }
386
+ }
387
+ for (i1=0; i1<cut_num; i1+=2) {
388
+ }
389
+ if (dbg>2) { fprintf(stderr,"\nDBG cut_box_result:"); out_x(box1); }
390
+ return 0;
391
+ }
392
+ #else // old bad version works for one cutted frame only
393
+ int cut_box( struct box *box1) {
394
+ int i1, i2, i3, i4, x, y, lx, ly, dbg=0;
395
+ #ifdef DO_DEBUG
396
+ if (OCR_JOB->cfg.verbose) dbg=1+2; // debug level, enlarge to get more output
397
+ #endif
398
+ if (dbg) fprintf(stderr,"\n cut box x= %3d %3d", box1->x0, box1->y0);
399
+ /* check if complete frames are outside the box */
400
+ for (i1=0; i1<box1->num_frames; i1++){
401
+ if (dbg>2) fprintf(stderr,"\n checking frame %d ", i1);
402
+ /* using frame_per as marker first (recalculate later) */
403
+ box1->frame_per[i1]=0;
404
+ i2 = ((i1)?box1->num_frame_vectors[ i1-1 ]:0); // this frame
405
+ i3 = box1->num_frame_vectors[ i1 ]; // next frame
406
+ for (i4=i2; i4 < i3; i4++) {
407
+ x = box1->frame_vector[i4][0];
408
+ y = box1->frame_vector[i4][1];
409
+ /* 1 if one vector is lying inside */
410
+ /* 2 if one vector is lying outside */
411
+ if (x>=box1->x0 && x<=box1->x1
412
+ && y>=box1->y0 && y<=box1->y1) box1->frame_per[i1]|=1;
413
+ if (x< box1->x0 || x> box1->x1
414
+ || y< box1->y0 || y> box1->y1) box1->frame_per[i1]|=2;
415
+ }
416
+ if (dbg>2) fprintf(stderr,"in1+out2= %d", box1->frame_per[i1]);
417
+ if (box1->frame_per[i1]==2) { /* all vectors outside */
418
+ if (dbg>1) fprintf(stderr," remove frame %d",i1);
419
+ /* replace all frames i1,i1+1,... by i1+1,i1+2,... */
420
+ /* replace (x,y) pairs first */
421
+ for (i4=i2; i4<box1->num_frame_vectors[ box1->num_frames-1 ]-(i3-i2);
422
+ i4++) {
423
+ box1->frame_vector[i4][0] = box1->frame_vector[i4+i3-i2][0];
424
+ box1->frame_vector[i4][1] = box1->frame_vector[i4+i3-i2][1];
425
+ }
426
+ /* replace the num_frame_vectors */
427
+ for (i4=i1; i4<box1->num_frames-1; i4++) {
428
+ box1->num_frame_vectors[ i4 ] =
429
+ box1->num_frame_vectors[ i4+1 ]-(i3-i2);
430
+ box1->frame_vol[i4]=box1->frame_vol[i4+1];
431
+ box1->frame_per[i4]=box1->frame_per[i4+1];
432
+ }
433
+ box1->num_frames--; i1--;
434
+ }
435
+ }
436
+ /* remove vectors outside the box and connect vectors pointing outside
437
+ * to next vectors pointing inside (every frame), see above sample "ke"
438
+ * ToDo: partly implemented, start i2source=search = i2dest=trace,
439
+ * i2source>i2dest on reconnect (evl. frame number changed)
440
+ */
441
+ i3=0; /* flag 0=inside=no_change 1++=outside_remove_or_concat */
442
+ for (i1=0; i1<box1->num_frames; i1++){
443
+ if (dbg>2) fprintf(stderr,"\n check cutting vectors on frame %d", i1);
444
+ x = box1->frame_vector[0][0]; /* initial x */
445
+ y = box1->frame_vector[0][1]; /* initial y */
446
+ /* ToDo: start inside to get a closed object */
447
+ if (x<box1->x0 || x>box1->x1 || y<box1->y0 || y>box1->y1) i3=1;
448
+ for (i2=0; i2<box1->num_frame_vectors[ i1 ]; i2++) {
449
+ lx = x; /* last x */
450
+ ly = y; /* last y */
451
+ x = box1->frame_vector[i2][0];
452
+ y = box1->frame_vector[i2][1];
453
+ // fprintf(stderr,"DBG LEV3 i2= %3d xy= %3d %3d",i2,x,y);
454
+ /* check if outside */
455
+ if (x<box1->x0 || x>box1->x1 || y<box1->y0 || y>box1->y1) {
456
+ /* replace by nearest point at border, ToDo: better crossingpoint */
457
+ if (i3==0) { /* inside_to_outside, wrong if it starts outside */
458
+ if (x < box1->x0) x = box1->frame_vector[i2][0] = box1->x0;
459
+ if (x > box1->x1) x = box1->frame_vector[i2][0] = box1->x1;
460
+ if (y < box1->y0) y = box1->frame_vector[i2][1] = box1->y0;
461
+ if (y > box1->y1) y = box1->frame_vector[i2][1] = box1->y1;
462
+ /* search other frames for near outside_to_inside and copy frame in */
463
+ } else { /* outside_to_outside */
464
+ /* remove vector */
465
+ if (dbg>1) fprintf(stderr,"\n remove vector[%d][%d] x= %2d %2d",i1,i2,x-box1->x0,y-box1->y0);
466
+ for (i4=i2;i4<box1->num_frame_vectors[ box1->num_frames-1 ]-1;i4++) {
467
+ box1->frame_vector[i4][0] = box1->frame_vector[i4+1][0];
468
+ box1->frame_vector[i4][1] = box1->frame_vector[i4+1][1];
469
+ }
470
+ for (i4=i1; i4<box1->num_frames; i4++)
471
+ box1->num_frame_vectors[ i4 ]--;
472
+ i2--; /* next element is shiftet now, setting back the counter */
473
+ }
474
+ i3++;
475
+ // fprintf(stderr," outside i3= %d\n",i3);
476
+ continue;
477
+ }
478
+ /* outside_or_inside to inside */
479
+ // fprintf(stderr," inside i3= %d",i3);
480
+ if (i3) { /* outside_to_inside */
481
+ /* ToDo: better crossing point last vector and border */
482
+ if (lx < box1->x0) lx = box1->x0;
483
+ if (lx > box1->x1) lx = box1->x1;
484
+ if (ly < box1->y0) ly = box1->y0;
485
+ if (ly > box1->y1) ly = box1->y1;
486
+ x = box1->frame_vector[i2][0] = lx;
487
+ y = box1->frame_vector[i2][1] = ly;
488
+ i3 = 0;
489
+ }
490
+ // fprintf(stderr," xy= %3d %3d\n",x,y);
491
+ }
492
+ }
493
+ if (dbg>2) { fprintf(stderr,"\nDBG cut_box_result:"); out_x(box1); }
494
+ return 0;
495
+ }
496
+ #endif