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,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