gocr-ruby 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +49 -0
- data/ext/gocr/Makefile +141 -0
- data/ext/gocr/Makefile.in +140 -0
- data/ext/gocr/amiga.h +31 -0
- data/ext/gocr/barcode.c +2108 -0
- data/ext/gocr/barcode.h +11 -0
- data/ext/gocr/box.c +496 -0
- data/ext/gocr/config.h +37 -0
- data/ext/gocr/config.h.in +36 -0
- data/ext/gocr/database.c +468 -0
- data/ext/gocr/detect.c +1003 -0
- data/ext/gocr/extconf.rb +6 -0
- data/ext/gocr/gocr.c +436 -0
- data/ext/gocr/gocr.h +290 -0
- data/ext/gocr/jconv.c +168 -0
- data/ext/gocr/job.c +92 -0
- data/ext/gocr/lines.c +364 -0
- data/ext/gocr/list.c +334 -0
- data/ext/gocr/list.h +91 -0
- data/ext/gocr/ocr0.c +7312 -0
- data/ext/gocr/ocr0.h +63 -0
- data/ext/gocr/ocr0n.c +1527 -0
- data/ext/gocr/ocr1.c +85 -0
- data/ext/gocr/ocr1.h +3 -0
- data/ext/gocr/otsu.c +310 -0
- data/ext/gocr/otsu.h +23 -0
- data/ext/gocr/output.c +291 -0
- data/ext/gocr/output.h +37 -0
- data/ext/gocr/pcx.c +153 -0
- data/ext/gocr/pcx.h +9 -0
- data/ext/gocr/pgm2asc.c +3259 -0
- data/ext/gocr/pgm2asc.h +105 -0
- data/ext/gocr/pixel.c +538 -0
- data/ext/gocr/pnm.c +538 -0
- data/ext/gocr/pnm.h +35 -0
- data/ext/gocr/progress.c +87 -0
- data/ext/gocr/progress.h +42 -0
- data/ext/gocr/remove.c +715 -0
- data/ext/gocr/tga.c +87 -0
- data/ext/gocr/tga.h +6 -0
- data/ext/gocr/unicode.c +1318 -0
- data/ext/gocr/unicode.h +62 -0
- data/ext/gocr/unicode_defs.h +1245 -0
- data/ext/gocr/version.h +2 -0
- data/gocr-ruby.gemspec +28 -0
- data/image.png +0 -0
- data/lib/gocr.rb +6 -0
- data/lib/gocr/image.rb +8 -0
- data/lib/gocr/version.rb +3 -0
- metadata +156 -0
data/ext/gocr/ocr0.h
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
#ifndef _OCR0_H
|
2
|
+
#define _OCR0_H
|
3
|
+
#include "pgm2asc.h"
|
4
|
+
|
5
|
+
/* ----------------------------------------------------------------
|
6
|
+
- functions with thousand of lines make the compilation very slow
|
7
|
+
therefore the ocr0-function is splitted in subfunctions
|
8
|
+
- shared data used often in ocr0-subroutines are stored
|
9
|
+
in ocr0_shared structure.
|
10
|
+
* ------------------------------------------------------------ */
|
11
|
+
|
12
|
+
typedef struct ocr0_shared { /* shared variables and properties */
|
13
|
+
|
14
|
+
struct box *box1; /* box in whole image */
|
15
|
+
pix *bp; /* extracted temporarly box, cleaned */
|
16
|
+
int cs; /* global threshold value (gray level) */
|
17
|
+
|
18
|
+
/* ToDo: or MACROS: X0 = box1->x0 */
|
19
|
+
int x0, x1, y0, y1; /* box coordinates related to box1 */
|
20
|
+
int dx, dy; /* size of box */
|
21
|
+
int hchar, gchar; /* relation to m1..m4 */
|
22
|
+
int aa[4][4]; /* corner points, see xX (x,y,dist^2,vector_idx) v0.41 */
|
23
|
+
holes_t holes; /* list of holes (max MAX_HOLES) */
|
24
|
+
|
25
|
+
} ocr0_shared_t;
|
26
|
+
|
27
|
+
/* tests for umlaut */
|
28
|
+
int testumlaut(struct box *box1, int cs, int m, wchar_t *modifier);
|
29
|
+
/* detect chars */
|
30
|
+
wchar_t ocr0(struct box *box1, pix *b, int cs);
|
31
|
+
/* detect numbers */
|
32
|
+
wchar_t ocr0n(ocr0_shared_t *sdata);
|
33
|
+
|
34
|
+
static inline int sq(int x) { return x*x; } /* square */
|
35
|
+
|
36
|
+
/*
|
37
|
+
* go from vector j1 to vector j2 and measure maximum deviation of
|
38
|
+
* the steps from the line connecting j1 and j2
|
39
|
+
* return the squared maximum distance
|
40
|
+
* in units of the box size times 1024
|
41
|
+
*/
|
42
|
+
int line_deviation( struct box *box1, int j1, int j2 );
|
43
|
+
|
44
|
+
/*
|
45
|
+
* search vectors between j1 and j2 for nearest point a to point r
|
46
|
+
* example:
|
47
|
+
*
|
48
|
+
* r-> $$...$$ $ - mark vectors
|
49
|
+
* @@$..@@ @ - black pixels
|
50
|
+
* @@$..@@ . - white pixels
|
51
|
+
* @@@@.$@
|
52
|
+
* a-> @@$@$@@
|
53
|
+
* @$.@@@@
|
54
|
+
* @@..$@@
|
55
|
+
* @@..$@@
|
56
|
+
* j1 --> $$...$$ <-- j2
|
57
|
+
*
|
58
|
+
* ToDo: vector aa[5] = {rx,ry,x,y,d^2,idx} statt rx,ry?
|
59
|
+
* j1 and j2 must be in the same frame
|
60
|
+
* return aa?
|
61
|
+
*/
|
62
|
+
int nearest_frame_vector( struct box *box1, int j1, int j2, int rx, int ry);
|
63
|
+
#endif
|
data/ext/gocr/ocr0n.c
ADDED
@@ -0,0 +1,1527 @@
|
|
1
|
+
/* ocr-engine numbers only */
|
2
|
+
/*
|
3
|
+
This is a Optical-Character-Recognition program
|
4
|
+
Copyright (C) 2000-2010 Joerg Schulenburg
|
5
|
+
|
6
|
+
This program is free software; you can redistribute it and/or
|
7
|
+
modify it under the terms of the GNU General Public License
|
8
|
+
as published by the Free Software Foundation; either version 2
|
9
|
+
of the License, or (at your option) any later version.
|
10
|
+
|
11
|
+
This program is distributed in the hope that it will be useful,
|
12
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
GNU General Public License for more details.
|
15
|
+
|
16
|
+
You should have received a copy of the GNU General Public License
|
17
|
+
along with this program; if not, write to the Free Software
|
18
|
+
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
19
|
+
|
20
|
+
see README for EMAIL-address
|
21
|
+
|
22
|
+
OCR engine (c) Joerg Schulenburg
|
23
|
+
first engine: rule based --- numbers 0..9
|
24
|
+
|
25
|
+
*/
|
26
|
+
|
27
|
+
#include <stdlib.h>
|
28
|
+
#include <stdio.h>
|
29
|
+
/* #include "pgm2asc.h" */
|
30
|
+
#include "ocr0.h"
|
31
|
+
#include "ocr1.h"
|
32
|
+
#include "amiga.h"
|
33
|
+
#include "pnm.h"
|
34
|
+
#include "gocr.h"
|
35
|
+
#include "unicode_defs.h"
|
36
|
+
|
37
|
+
/* only for debugging and development */
|
38
|
+
#define IFV if(OCR_JOB->cfg.verbose&4)
|
39
|
+
#define MM {IFV fprintf(stderr,"\nDBG %c L%04d (%d,%d): ",(char)c_ask,__LINE__,box1->x0,box1->y0);}
|
40
|
+
|
41
|
+
/* the old debug mode (0.40) was only for a special char, for another char
|
42
|
+
* code must be recompiled with C_ASK='char'
|
43
|
+
* new debug mode (0.41) explains why char is declined or accepted as ABC...
|
44
|
+
* the output can be filtered by external scripts
|
45
|
+
* ToDo: we could reduce output to filter string
|
46
|
+
*/
|
47
|
+
#ifndef DO_DEBUG /* can be defined outside */
|
48
|
+
#define DO_DEBUG 0 /* 0 is the default */
|
49
|
+
#endif
|
50
|
+
|
51
|
+
/* this macro is for debugging output: "if char is declined, why?" */
|
52
|
+
#if DO_DEBUG /* 0=Work mode, 1=debugging mode */
|
53
|
+
// Setac: output, that char is choosen with a probability
|
54
|
+
// Break: output, why the char is not choosen
|
55
|
+
// MSG: debugging functions for char C_ASK, mostly messages
|
56
|
+
// DBG: definitions usefull only for debugging
|
57
|
+
#define Setac(box1,ac,ad) { MM;IFV fprintf(stderr,"setac %d",ad);setac(box1,ac,ad); }
|
58
|
+
#define Break { MM;IFV fprintf(stderr,"break"); break; }
|
59
|
+
#define MSG(x) { MM;IFV x }
|
60
|
+
#define DBG(x) x
|
61
|
+
#else
|
62
|
+
#define Setac(box1,ac,ad) setac(box1,ac,ad)
|
63
|
+
#define Break break
|
64
|
+
#define MSG(x)
|
65
|
+
#define DBG(x)
|
66
|
+
#endif
|
67
|
+
|
68
|
+
/* extern "C"{ */
|
69
|
+
|
70
|
+
// OCR engine ;)
|
71
|
+
wchar_t ocr0n(ocr0_shared_t *sdata){
|
72
|
+
struct box *box1=sdata->box1;
|
73
|
+
pix *bp=sdata->bp;
|
74
|
+
int d,x,y,x0=box1->x0,x1=box1->x1,y0=box1->y0,y1=box1->y1;
|
75
|
+
int dx=x1-x0+1,dy=y1-y0+1,cs=sdata->cs; // size
|
76
|
+
int xa,xb,ya,yb, /* tmp-vars */
|
77
|
+
i1,i2,i3,i4,i,j;
|
78
|
+
int (*aa)[4]=sdata->aa; /* corner-points, (x,y,dist^2,vector_idx) */
|
79
|
+
wchar_t bc=UNKNOWN; // best char
|
80
|
+
int ad=0; // propability 0..100
|
81
|
+
int hchar=sdata->hchar; // char is higher than 'e'
|
82
|
+
int gchar=sdata->gchar; // char has ink lower than m3
|
83
|
+
int dots=box1->dots;
|
84
|
+
// --- test 5 near S ---------------------------------------------------
|
85
|
+
for(ad=d=100;dx>2 && dy>4;){ // min 3x4
|
86
|
+
DBG( char c_ask='5'; )
|
87
|
+
if (sdata->holes.num > 1) Break; /* be tolerant */
|
88
|
+
if( num_cross( dx/2, dx/2,0,dy-1,bp,cs)!=3
|
89
|
+
&& num_cross(6*dx/8,2*dx/8,0,dy-1,bp,cs)!=3 ) Break; // 2010-09-25 6x7
|
90
|
+
|
91
|
+
i1=loop(bp,dx-1,dy-1,dx,cs,0,LE);
|
92
|
+
i2=loop(bp,dx-1,dy-2,dx,cs,0,LE);
|
93
|
+
if (i2-i1 >= dx/4) Break; // ~{ 5x7font
|
94
|
+
// i1, i2 unused now
|
95
|
+
|
96
|
+
if (dx<13 && dy<17) { // oebb_teletext S5 Aug10
|
97
|
+
i1=loop(bp, 0,0,dx,cs,0,RI);
|
98
|
+
i2=loop(bp, 0,1,dx,cs,0,RI);
|
99
|
+
i3=loop(bp,dx-1,0,dx,cs,0,LE);
|
100
|
+
if (i1>i2 && i3>0) ad=98*ad/100;
|
101
|
+
}
|
102
|
+
// i1, i2, i3 unused now
|
103
|
+
|
104
|
+
// get the upper and lower hole koords, y around dy/4 ???
|
105
|
+
x=5*dx/8;
|
106
|
+
y =loop(bp,x,0,dy,cs,0,DO); if(y>dy/8) Break;
|
107
|
+
y +=loop(bp,x,y,dy,cs,1,DO); if(y>(dy+2)/4) Break; // 6x7 2010-09-25
|
108
|
+
i1 =loop(bp,x,y,dy,cs,0,DO)+y; if(i1>5*dy/8) Break;
|
109
|
+
i3=y=(y+i1)/2; // upper end can be shifted to the right for italic
|
110
|
+
x =loop(bp,0,y,dx,cs,0,RI); if(x>4*dx/8) Break;
|
111
|
+
x +=loop(bp,x,y,dx,cs,1,RI); if(x>5*dx/8) Break;
|
112
|
+
i1 =loop(bp,x,y,dx,cs,0,RI); i1=(i1+2*x)/2; // upper center (i1,i3)
|
113
|
+
y=11*dy/16;
|
114
|
+
x =loop(bp,dx-1 ,y,dx,cs,0,LE); if(x>dx/4) Break;
|
115
|
+
x +=loop(bp,dx-1-x,y,dx,cs,1,LE); if(x>dx/2) Break;
|
116
|
+
i2 =loop(bp,dx-1-x,y,dx,cs,0,LE); i2=dx-1-(i2+2*x)/2; // lower center x
|
117
|
+
|
118
|
+
MSG( fprintf(stderr,"i1,i3=%d,%d i2,y=%d,%d (upper+lower center)",i1,i3,i2,y);)
|
119
|
+
|
120
|
+
y =loop(bp,i1,0,dy,cs,0,DO);
|
121
|
+
y +=loop(bp,i1,y,dy,cs,1,DO);
|
122
|
+
y =(3*y+i3)/4;
|
123
|
+
if( num_cross( i1, dx-1, y, y,bp,cs)>0 ){ /* S or serif5 ? */
|
124
|
+
y =loop(bp,i1 ,i3,dy,cs,0,DO);
|
125
|
+
i =loop(bp,i1-1,i3,dy,cs,0,DO);
|
126
|
+
if (y>i ) ad=99*ad/100; /* looks like S */
|
127
|
+
y =loop(bp,i1 ,i3,dy,cs,0,UP);
|
128
|
+
i =loop(bp,i1+1,i3,dy,cs,0,UP);
|
129
|
+
if (i<y ) ad=99*ad/100; /* looks like S */
|
130
|
+
x =loop(bp,dx-1,0,dx,cs,0,LE);
|
131
|
+
i =loop(bp,dx-1,1,dx,cs,0,LE);
|
132
|
+
if (x>i ) ad=99*ad/100; /* looks like S */
|
133
|
+
if( num_cross( 0, dx/2, dy-1, dy-1,bp,cs)>1
|
134
|
+
&& num_cross( dx/2,dx-1, 0, 0,bp,cs)>1 ) ad=98*ad/100; /* serifs */
|
135
|
+
if (loop(bp,0,dy-1,dx,cs,0,RI)==0) ad=98*ad/100; /* S or 7segment */
|
136
|
+
ad=99*ad/100;
|
137
|
+
}
|
138
|
+
|
139
|
+
for(y=dy/5;y<3*dy/4;y++) // right gap?
|
140
|
+
if( num_cross(i1,dx-1,y,y,bp,cs)==0 ) break;
|
141
|
+
if( y==3*dy/4 ) Break;
|
142
|
+
|
143
|
+
for(y=dy/4;y<=11*dy/16;y++) // left gap?
|
144
|
+
if( num_cross(0,i2,y,y,bp,cs)==0 ) break;
|
145
|
+
if( y>11*dy/16 ) Break;
|
146
|
+
|
147
|
+
// if( num_hole( x0, x1, y0, y1, box1->p,cs,NULL) > 0 ) break;
|
148
|
+
if (sdata->holes.num>0) Break;
|
149
|
+
|
150
|
+
// sS5 \sl z left upper v-bow ?
|
151
|
+
for(x=dx,i=y=dy/4;y<dy/2;y++){
|
152
|
+
j=loop(bp,0,y,dx,cs,0,RI); if(j<x) { x=j; i=y; }
|
153
|
+
} y=i; /* get smalles left gap and its y position */
|
154
|
+
i1=loop(bp,0, dy/16 ,dx,cs,0,RI); /* left gap at top */
|
155
|
+
i2=loop(bp,0,(y+dy/16)/2 ,dx,cs,0,RI); /* left gap below top */
|
156
|
+
i =loop(bp,0,(y+dy/16)/2+1,dx,cs,0,RI); if( i>i2 ) i2=i;
|
157
|
+
i3=loop(bp,0, y ,dx,cs,0,RI); /* left gap at y */
|
158
|
+
i =loop(bp,0, y-1,dx,cs,0,RI); if( i<i3 ) i3=i;
|
159
|
+
if( 2*i2+ dx/16 < i1+i3 ) ad=99*ad/100; /* 5S oebb_teletext */
|
160
|
+
if( 2*i2+1+dx/16 < i1+i3 ) Break; /* break if bow */
|
161
|
+
|
162
|
+
if( dy>=20 && dx<16 ) /* tall S */
|
163
|
+
if( loop(bp,0, dy/5 ,dx,cs,0,RI)
|
164
|
+
==loop(bp,0, dy/4 ,dx,cs,0,RI)
|
165
|
+
&&
|
166
|
+
loop(bp,0, dy/10 ,dx,cs,0,RI)
|
167
|
+
>loop(bp,0, dy/4 ,dx,cs,0,RI)
|
168
|
+
&&
|
169
|
+
loop(bp,0, 1 ,dx,cs,0,RI)
|
170
|
+
>loop(bp,0, dy/4 ,dx,cs,0,RI)+1
|
171
|
+
&&
|
172
|
+
loop(bp,dx-1, 0 ,dx,cs,0,LE)
|
173
|
+
>loop(bp,dx-1, 1 ,dx,cs,0,LE) ) Break;
|
174
|
+
|
175
|
+
if( dy>=30 && dx>15 ) /* large S */
|
176
|
+
if( loop(bp,dx/4,3*dy/10,dy,cs,1,DO)>0 ) // check start
|
177
|
+
if( loop(bp,dx-2,3*dy/4 ,dy,cs,1,UP)>0 ) // check end
|
178
|
+
if( num_cross(dx/4,dx-2,3*dy/10,3*dy/4,bp,cs)==1 ) Break; // connected?
|
179
|
+
MSG(fprintf(stderr,"~S ad=%d",ad);)
|
180
|
+
|
181
|
+
// small fat s is very similar to rounded serif 5
|
182
|
+
// but has a fat diagonal arrea (Oct08 JS)
|
183
|
+
if ( num_cross(dx/8,dx-1-dx/8,3*dy/10,3*dy/4,bp,cs)==1 ) ad=98*ad/100;
|
184
|
+
MSG(fprintf(stderr,"~S ad=%d",ad);)
|
185
|
+
|
186
|
+
if( dy>17 && dx>9 ) /* S */
|
187
|
+
if( loop(bp, 0,dy/2 ,dx,cs,0,RI)<dx/2
|
188
|
+
|| loop(bp, 0,dy/2-1 ,dx,cs,0,RI)<dx/2 )
|
189
|
+
if( loop(bp,dx/4,3*dy/10,dy,cs,1,DO)>0 ) // check start
|
190
|
+
if( loop(bp,dx-2,2*dy/3 ,dy,cs,1,UP)>0 ) // check end
|
191
|
+
if( loop(bp, 0, dy/16,dx,cs,0,RI)
|
192
|
+
>= loop(bp,dx-1, dy-1-dy/16,dx,cs,0,LE) ) ad=ad*98/100;
|
193
|
+
MSG(fprintf(stderr,"~S ad=%d",ad);)
|
194
|
+
if( loop(bp,3*dx/4 , 0,dy,cs,1,DO) // ToDo: improve!
|
195
|
+
< loop(bp, dx/4 ,dy-1,dy,cs,1,UP)
|
196
|
+
&& loop(bp,3*dx/4-1, 0,dy,cs,0,DO)
|
197
|
+
< loop(bp, dx/4+1,dy-1,dy,cs,0,UP) ) ad=ad*98/100;
|
198
|
+
MSG(fprintf(stderr,"~S ad=%d",ad);)
|
199
|
+
|
200
|
+
if ( gchar) ad=99*ad/100;
|
201
|
+
if (!hchar) ad=98*ad/100; // ~s 6x7 font tmp08/gocr0801_bad5.jpg
|
202
|
+
if (box1->m2 && y0>=box1->m2 && ad<100 && ad>96) {ad=96;MSG({})} // s
|
203
|
+
Setac(box1,(wchar_t)'5',ad);
|
204
|
+
if (ad==100) return '5';
|
205
|
+
break;
|
206
|
+
|
207
|
+
}
|
208
|
+
// --- test 1 ---------------------------------------------------
|
209
|
+
for(ad=d=100;dy>4 && dy>dx && 2*dy>box1->m3-box1->m2;){ // min 3x4
|
210
|
+
DBG( char c_ask='1'; )
|
211
|
+
if( dots==1 ) Break;
|
212
|
+
if (sdata->holes.num > 1) Break; /* be tolerant */
|
213
|
+
|
214
|
+
if( num_cross(0, dx-1, 0 , 0 ,bp,cs) != 1
|
215
|
+
&& num_cross(0, dx-1, 1 , 1 ,bp,cs) != 1 ) Break;
|
216
|
+
if( num_cross(0, dx-1,dy/2,dy/2,bp,cs) != 1 ) Break;
|
217
|
+
if( num_cross(0, dx-1,dy-1,dy-1,bp,cs) != 1
|
218
|
+
&& num_cross(0, dx-1,dy-2,dy-2,bp,cs) != 1 ) Break;
|
219
|
+
/* 5x7 micr ocr-a 6x10 6x9 bad 6x9
|
220
|
+
mozilla
|
221
|
+
3x6 5x7 5x7 ..@@..<-
|
222
|
+
.@@@.. @@@...<- @@@...<-
|
223
|
+
..@@.. @.@... ..@...
|
224
|
+
ooo @@@.. ..@@..< ..@... ..@...
|
225
|
+
.$. ooo ..@.. ..@@.. ..@...< ..@...<
|
226
|
+
$@. oo ..@.. ..@@.. ..@... ..@...
|
227
|
+
.$. oo ..@.. ..@@.. ..@... ..@...
|
228
|
+
.@. ooooo ..@.@ ..@@.. ..@... ..@...
|
229
|
+
.$. ooooo ..@.@ ..@@.. ..@... ..@...
|
230
|
+
$@$ ooooo @@@@@ @@@@@@<- @@@@@@<- @@@@@@<-
|
231
|
+
gocr0801_bad5
|
232
|
+
*/
|
233
|
+
i4=0; // human font
|
234
|
+
if (num_cross(0, dx-1,3*dy/4,3*dy/4,bp,cs) != 2 ) { // except ocr-a
|
235
|
+
for (y=1; y<dy/2; y++) {
|
236
|
+
if (num_cross(0, dx-1, y , y ,bp,cs) == 2 ) break;
|
237
|
+
} if (y>=dy/2) {
|
238
|
+
if (dx>6) ad=98*ad/100;
|
239
|
+
else ad=99*ad/100; MSG(fprintf(stderr,"ad= %d",ad);) }
|
240
|
+
for( i=dy/8,y=7*dy/16;y<dy-1 && i;y++ ){
|
241
|
+
if( num_cross(0, dx-1, y , y ,bp,cs) != 1 ) i--;
|
242
|
+
} if( dy>8 && !i ) Break;
|
243
|
+
} else { // ocr-a-1
|
244
|
+
i= loop(bp,dx/2,0,dy,cs,0,DO);
|
245
|
+
if (loop(bp,dx/2,i,dy,cs,1,DO)<dy-1) Break;
|
246
|
+
i= loop(bp,dx -1,dy-1-dy/16,dx,cs,0,LE);
|
247
|
+
if (loop(bp,dx-i-1,dy-1-dy/16,dx,cs,1,LE)<dx-1) Break;
|
248
|
+
i= loop(bp,0,dy/16,dx,cs,0,RI);
|
249
|
+
if (loop(bp,i,dy/16,dx,cs,1,RI)<dx/2) Break;
|
250
|
+
i4=1;
|
251
|
+
MSG(fprintf(stderr,"ocr-a-1 detected ad= %d", ad);)
|
252
|
+
}
|
253
|
+
|
254
|
+
if( num_cross(0, dx-1, 0 , 0 ,bp,cs) > 1
|
255
|
+
&& num_cross(0, dx-1, 1 , 1 ,bp,cs) > 1 ) Break; // ~/it_7
|
256
|
+
|
257
|
+
// calculate upper and lower mass center (without lower serif)
|
258
|
+
|
259
|
+
x =loop(bp,0,7*dy/8-1,dx,cs,0,RI); i2=x;
|
260
|
+
x+=loop(bp,x,7*dy/8-1,dx,cs,1,RI)-1; i2=(i2+x)/2;
|
261
|
+
|
262
|
+
i1=loop(bp,dx-1 ,1+0* dy/4,dx,cs,0,LE); i1=dx-1-i1-(x-i2)/2;
|
263
|
+
|
264
|
+
x =(i1-i2+4)/8; i1+=x; i2-=x;
|
265
|
+
|
266
|
+
if( get_line2(i1,0,i2,dy-1,bp,cs,100)<95 ) { // dont work for ocr-a-1
|
267
|
+
i1=loop(bp,dx-1 ,1+0* dy/4,dx,cs,0,LE); i1=dx-1-i1;
|
268
|
+
if( get_line2(i1,0,i2,dy-1,bp,cs,100)<95 ) Break;
|
269
|
+
}
|
270
|
+
// upper and lower width
|
271
|
+
x =loop(bp,(i1+i2)/2,dy/2,dx,cs,1,RI); i=x; i3=0;
|
272
|
+
for (y=0;y<7*dy/8;y++)
|
273
|
+
if ( loop(bp,i1+y*(i2-i1)/dy, y,dx,cs,1,RI)-i > 1+dx/8 ) break;
|
274
|
+
if (y<7*dy/8) { ad=98*ad/100; // serif or ocr-a-1 ?
|
275
|
+
MSG(fprintf(stderr,"i12 %d %d ad= %d", i1,i2,ad);) }
|
276
|
+
if (y<6*dy/8) { ad=99*ad/100; /* MICR E-13B font Jan07 */
|
277
|
+
MSG(fprintf(stderr,"i12 %d %d ad= %d", i1,i2,ad);) }
|
278
|
+
if (y<4*dy/8) Break;
|
279
|
+
MSG(fprintf(stderr,"i12 %d %d ad= %d", i1,i2,ad);)
|
280
|
+
// out_x(box1); printf(" i12=%d %d\n",i1,i2);
|
281
|
+
x =loop(bp,i2,dy-1,dx,cs,1,LE); j=x;
|
282
|
+
x =loop(bp,i2,dy-2,dx,cs,1,LE); if(x>j)j=x; i=j;
|
283
|
+
x =loop(bp,i2,dy-1,dx,cs,1,RI); j=x;
|
284
|
+
x =loop(bp,i2,dy-2,dx,cs,1,RI); if(x>j)j=x;
|
285
|
+
if(abs(i-j)>1+dx/8) i3|=1;
|
286
|
+
if(i3) Break;
|
287
|
+
// out_x(box1);printf(" 11 i=%d j=%d i2=%d dx=%d\n",i,j,i1,dx);
|
288
|
+
MSG(fprintf(stderr,"ad= %d", ad);)
|
289
|
+
// get most left upper point (i,j)
|
290
|
+
for(i=dx,j=y=0;y<7*dy/16;y++){
|
291
|
+
x =loop(bp,0,y,dx,cs,0,RI); if(x<i) { i=x;j=y; }
|
292
|
+
}
|
293
|
+
if ( i1-i<7*dx/16 ) { ad=ad*98/100;
|
294
|
+
MSG(fprintf(stderr,"i1i %d %d ad= %d", i1,i,ad);) }
|
295
|
+
if ( i1-i<6*dx/16 ) { ad=ad*98/100; // 4*dx/8 => 7*dx/16 MICR E-13B font
|
296
|
+
MSG(fprintf(stderr,"i1i %d %d ad= %d", i1,i,ad);) }
|
297
|
+
if ( i1-i<4*dx/16 ) Break;
|
298
|
+
MSG(fprintf(stderr,"i12 %d %d ad= %d", i1,i2,ad);)
|
299
|
+
x =loop(bp,0,dy/2,dx,cs,0,RI); // right distance
|
300
|
+
j =loop(bp,x,dy/2,dx,cs,1,RI); // thickness
|
301
|
+
if( j>x+(dy+16)/32 ) ad=98*ad/100; // ~l but MICR E-13B font
|
302
|
+
x =loop(bp,0,0,dx,cs,0,RI); // straight line ???
|
303
|
+
j =loop(bp,0,1,dx,cs,0,RI);
|
304
|
+
if (j>x) {
|
305
|
+
if (dy>9) { Break; }
|
306
|
+
else { if (ad>99) ad=ad*99/100; MSG({}) } // ~l but gocr0801_bad5
|
307
|
+
}
|
308
|
+
if (x==j) j =loop(bp,0,dy/8,dx,cs,0,RI);
|
309
|
+
if (j>x && y>9 && !i4) { Break; }
|
310
|
+
else if (j>x && !i4 && ad>99) { ad=ad*99/100; MSG({}) }
|
311
|
+
if (x==j) if(loop(bp,0,dy/4,dx,cs,0,RI)>x) { // ~l
|
312
|
+
// check micr-1 first before taken as 'l'
|
313
|
+
if (loop(bp,dx-1,dy/8,dx,cs,0,LE)<=dx/4
|
314
|
+
&& loop(bp, 0,3*dy/4,dx,cs,1,RI)< dx-1) ad=97*ad/100;
|
315
|
+
}
|
316
|
+
MSG(fprintf(stderr,"1l check ad= %d", ad);)
|
317
|
+
x=j;
|
318
|
+
// j =loop(bp,0,2,dx,cs,0,RI); if( j>=x ) Break; x=j; // ~l
|
319
|
+
// j =loop(bp,0, 0,dx,cs,0,DO); if( !j ) Break; // ~7
|
320
|
+
if( !hchar ) // ~ right part of n
|
321
|
+
/* look for upper right side, not going from nw to se */
|
322
|
+
if( loop(bp,dx-1, 1,dx,cs,0,LE)-dy/6
|
323
|
+
> loop(bp,dx-1,dy/4,dx,cs,0,LE)
|
324
|
+
// failes on small fonts with 1 point spaces between chars
|
325
|
+
// also do not know what the purpose of this line was (JS Oct08)
|
326
|
+
// || get_bw(x1+1,x1+2,y0,y0+dy/8,box1->p,cs,1)==1
|
327
|
+
) Break; // Mai00
|
328
|
+
if( loop(bp,dx-1,3*dy/4,dx,cs,0,LE) > dx/2
|
329
|
+
&& get_bw(x1-dx/4,x1,y1-1,y1,box1->p,cs,1)==1 ) Break; // ~z Jun00
|
330
|
+
|
331
|
+
i=loop(bp, dx/8,0,dy,cs,0,DO);
|
332
|
+
for (y=dy,x=dx/2;x<3*dx/4;x++){ /* get upper end y */
|
333
|
+
j=loop(bp,x,0,dy,cs,0,DO); if (j<y) { y=j; }
|
334
|
+
}
|
335
|
+
if(y<dy/2 && y+dy/16>=i) ad=98*ad/100; // ~\tt l ??? ocr-a_1
|
336
|
+
MSG(fprintf(stderr,"1l check i= %d y= %d ad= %d", i, y, ad);)
|
337
|
+
|
338
|
+
if( loop(bp, 0, dy/8,dx,cs,0,RI)
|
339
|
+
-(dx-loop(bp,dx-1,7*dy/8,dx,cs,0,LE)) > dx/4 ) Break; // ~/
|
340
|
+
|
341
|
+
i= loop(bp, 0, 0,dy,cs,0,DO); // horizontal line?
|
342
|
+
if(dy>=12 && i>dy/8 && i<dy/2){
|
343
|
+
if( loop(bp,dx-1,3*dy/16,dx,cs,0,LE)-dx/8
|
344
|
+
>loop(bp,dx-1, i,dx,cs,0,LE)
|
345
|
+
|| loop(bp,dx-1,3*dy/16,dx,cs,0,LE)-dx/8
|
346
|
+
>loop(bp,dx-1, i+1,dx,cs,0,LE) ) Break; // ~t,~f
|
347
|
+
i= loop(bp, 0,dy-1-dy/32,dx,cs,0,RI);
|
348
|
+
x= loop(bp, 0,dy-2-dy/32,dx,cs,0,RI); if (i<x) x=i;
|
349
|
+
if( x-loop(bp, 0, 3*dy/4,dx,cs,0,RI)>dx/8
|
350
|
+
&& loop(bp,dx-1, 3*dy/4,dx,cs,0,LE)-dx/8
|
351
|
+
>loop(bp,dx-1,dy-1-dy/32,dx,cs,0,LE) ) Break; // ~t
|
352
|
+
if( loop(bp, 0,i-1,dx,cs,0,RI)>1 && dx<6) {
|
353
|
+
ad=99*ad/100;
|
354
|
+
if ( loop(bp,dx-1,i-1,dx,cs,0,LE)>1 ) Break; // ~t
|
355
|
+
}
|
356
|
+
}
|
357
|
+
|
358
|
+
if (dx>8){
|
359
|
+
if (loop(bp,0,3*dy/4,dx,cs,0,RI)-
|
360
|
+
loop(bp,0,dy/2-1,dx,cs,0,RI)>dx/4) ad=95*ad/100; // ~3
|
361
|
+
if (loop(bp,dx-1,dy/2-1,dx,cs,0,LE)-
|
362
|
+
loop(bp,dx-1,3*dy/4,dx,cs,0,LE)>dx/8) ad=99*ad/100; // ~3 ocr-a?
|
363
|
+
if (loop(bp,dx-1, dy/4 ,dx,cs,0,LE)<dx/3 // 2010-09-25 6x9
|
364
|
+
&& loop(bp,dx-1, dy/16,dx,cs,0,LE)-
|
365
|
+
loop(bp,dx-1, dy/4,dx,cs,0,LE)>dx/8) ad=95*ad/100; // ~23
|
366
|
+
MSG(fprintf(stderr,"23 check ad= %d", ad);)
|
367
|
+
}
|
368
|
+
/* font 5x9 "2" recognized as "1" */
|
369
|
+
i=loop(bp,dx-1-dx/8,dy-1,dy,cs,0,UP);
|
370
|
+
if (i<=dy/4) {
|
371
|
+
i+=loop(bp,dx-1-dx/8,dy-1-i,dy,cs,1,UP);
|
372
|
+
if (i<=dy/4) {
|
373
|
+
i=loop(bp,dx-1-dx/8,dy-1-i,dx,cs,0,LE);
|
374
|
+
if (loop(bp,dx-1,dy/4,dx,cs,0,LE)<dx/2) // 2010-09-25 6x9 1
|
375
|
+
if (2*i>=dx && loop(bp,dx/4,0,dy,cs,0,DO)<dy/2) {
|
376
|
+
if (dx<17) ad=98*ad/100;
|
377
|
+
if (dx<9) ad=97*ad/100;
|
378
|
+
MSG(fprintf(stderr,"5x9 2 check ad= %d", ad);)
|
379
|
+
}
|
380
|
+
}
|
381
|
+
}
|
382
|
+
|
383
|
+
// 2010-10-01 sample tmp10/barcode_code128_145
|
384
|
+
if (dx<3 && dy>7 && box1->m4==0) ad=ad*96/100; // just a vertical line?
|
385
|
+
|
386
|
+
// looking for ###
|
387
|
+
// ..# pattern (its important, we dont want perp. lines as 1)
|
388
|
+
// ToDo: better check that we have exact one on top
|
389
|
+
for (i2=0,i=dx,y=0;y<dy/2;y++) {
|
390
|
+
j=loop(bp,0,y,dx,cs,0,RI); if (j<i) i=j;
|
391
|
+
if (j>i+dx/8) { break; }
|
392
|
+
} if (y>=dy/2) ad=95*ad/100; // Feb07 care plates, right black border
|
393
|
+
MSG(fprintf(stderr,"ad= %d", ad);)
|
394
|
+
|
395
|
+
if (sdata->holes.num > 0) Break; // mini holes should be filtered
|
396
|
+
if (!box1->m3 && ad>98) ad=98; else {
|
397
|
+
if (!hchar) ad=99*ad/100;
|
398
|
+
if (box1->y0>box1->m2) ad=98*ad/100;
|
399
|
+
if (box1->y1<(1*box1->m2+3*box1->m3)/4) ad=98*ad/100;
|
400
|
+
if (box1->y1-box1->y0<(box1->m3-box1->m1)/2) ad=98*ad/100;
|
401
|
+
if ( gchar) ad=99*ad/100;
|
402
|
+
}
|
403
|
+
|
404
|
+
Setac(box1,(wchar_t)'1',ad);
|
405
|
+
break;
|
406
|
+
}
|
407
|
+
// --- test 2 old pixelbased - remove! -----------------------------
|
408
|
+
#ifdef Old_pixel_based
|
409
|
+
for(ad=d=100;dx>2 && dy>4;){ // min 3x4
|
410
|
+
DBG( char c_ask='2'; )
|
411
|
+
if (sdata->holes.num > 1) Break; /* be tolerant */
|
412
|
+
if( get_bw(x0+dx/2, x0+dx/2 , y1-dy/5, y1 ,box1->p,cs,1) != 1 ) Break;
|
413
|
+
if( get_bw(x0+dx/2, x0+dx/2 , y0 , y0+dy/5,box1->p,cs,1) != 1 ) Break;
|
414
|
+
if( get_bw(x0+dx/8, x1-dx/3 , y1-dy/3, y1-dy/3,box1->p,cs,1) != 1 ) Break;
|
415
|
+
|
416
|
+
if( get_bw(x1-dx/3, x1 , y0+dy/3 , y0+dy/3,box1->p,cs,1) != 1 ) Break;
|
417
|
+
if( get_bw(x0 , x0+dx/ 8, y1-dy/16, y1 ,box1->p,cs,1) != 1 ) Break;
|
418
|
+
if( num_cross(x0, x1-dx/8, y0+dy/2, y0+dy/2,box1->p,cs) != 1 ) Break;
|
419
|
+
if( get_bw(x0, x0+dx/9 , y0 , y0 ,box1->p,cs,1) == 1
|
420
|
+
&& get_bw(x0, x0+dx/2 ,y0+3*dy/16,y0+3*dy/16,box1->p,cs,1) == 1 ) Break;
|
421
|
+
if( get_bw(x0, x0+dx/9 , y0 , y0 ,box1->p,cs,1)
|
422
|
+
!= get_bw(x1-dx/9, x1 , y0 , y0 ,box1->p,cs,1) )
|
423
|
+
{ if (dx<6 && dy<9) ad=99*ad/100; else Break; }
|
424
|
+
// out_x(box1);
|
425
|
+
|
426
|
+
for( x=x0+dx/4;x<x1-dx/6;x++ ) // C
|
427
|
+
if( num_cross( x, x, y0, y0+dy/2,box1->p,cs) == 2 ) break;
|
428
|
+
if( x>=x1-dx/6 ) Break;
|
429
|
+
|
430
|
+
for( x=x0+dx/4;x<x1-dx/6;x++ ) // C, but acr-a
|
431
|
+
if( num_cross( x, x, y0+3*dy/8,y1,box1->p,cs) == 2 ) break;
|
432
|
+
if( x>=x1-dx/6 ) Break;
|
433
|
+
|
434
|
+
for(i=1,y=y0;y<y0+dy/2;y++ )
|
435
|
+
if( num_cross( x0, x1, y, y,box1->p,cs) == 2 ) i=0;
|
436
|
+
if( i ) ad=99*ad/100; // ToDo: ocr-a-2 should have 100%
|
437
|
+
|
438
|
+
for(i=1,y=y0+dy/5;y<y0+3*dy/4;y++ )
|
439
|
+
if( get_bw( x0, x0+dx/3, y, y,box1->p,cs,1) == 0 ) i=0;
|
440
|
+
if( i ) Break;
|
441
|
+
|
442
|
+
x=x1-dx/3,y=y1; /* center bottom */
|
443
|
+
turmite(box1->p,&x,&y,x0,x1,y0,y1,cs,UP,ST); if( y<y1-dy/5 ) Break;
|
444
|
+
turmite(box1->p,&x,&y,x0,x1,y0,y1,cs,ST,UP); if( y<y1-dy/4 ) ad=99*ad/100;
|
445
|
+
if( y<y1-dy/3 ) Break;
|
446
|
+
turmite(box1->p,&x,&y,x0,x1,y0,y1,cs,UP,ST); if( y<y0+dy/3 ) Break; y++;
|
447
|
+
turmite(box1->p,&x,&y,x0,x1,y0,y1,cs,RI,ST);
|
448
|
+
if( x<x1 ){ x--; // hmm thick font and serifs
|
449
|
+
turmite(box1->p,&x,&y,x0,x1,y0,y1,cs,UP,ST); if( y<y0+dy/2 ) Break; y++;
|
450
|
+
turmite(box1->p,&x,&y,x0,x1,y0,y1,cs,RI,ST);
|
451
|
+
if( x<x1 ) Break;
|
452
|
+
}
|
453
|
+
|
454
|
+
// test ob rechte Kante ansteigend
|
455
|
+
for(x=0,y=dy/18;y<=dy/3;y++){ // rechts abfallende Kante/Rund?
|
456
|
+
i=loop(box1->p,x1,y0+y,dx,cs,0,LE); // use p (not b) for broken chars
|
457
|
+
if( i<x ) break; // rund
|
458
|
+
if( i>x ) x=i;
|
459
|
+
}
|
460
|
+
if (y>dy/3 ) Break; // z
|
461
|
+
|
462
|
+
// hole is only allowed in beauty fonts
|
463
|
+
// if( num_hole( x0, x1, y0, y1,box1->p,cs,NULL) > 0 ) // there is no hole
|
464
|
+
// if( num_hole( x0, x0+dx/2, y0, y0+dy/2,box1->p,cs,NULL) == 0 ) // except in some beauty fonts
|
465
|
+
if (sdata->holes.num>0)
|
466
|
+
if (sdata->holes.hole[0].x1 >= dx/2 || sdata->holes.hole[0].y1 >= dy/2)
|
467
|
+
Break;
|
468
|
+
|
469
|
+
if (loop(bp,dx-1, 0,dx,cs,0,LE)
|
470
|
+
<loop(bp,dx-1,dy/4,dx,cs,0,LE)-dx/8) Break; // 5x7,5x8 z Jul09
|
471
|
+
i1=loop(bp,dx-1-dx/16,0,dy,cs,0,DO); // Jul00
|
472
|
+
i2=loop(bp, dx/ 2,0,dy,cs,0,DO); if( i2+dy/32>=i1 ) Break; // ~z
|
473
|
+
i1=loop(bp,dx-1,dy-3*dy/16,dx,cs,0,LE);
|
474
|
+
i2=loop(bp, 0,dy-3*dy/16,dx,cs,0,RI); if( i2>i1 ) ad=98*ad/100; // ~i
|
475
|
+
if (dots) ad=98*ad/100; // i
|
476
|
+
if (loop(bp,dx-1,dy-1-dy/16,dx,cs,0,LE)>dx/4) ad=96*ad/100; // \it i
|
477
|
+
|
478
|
+
if ((!hchar) && box1->m4!=0) ad=80*ad/100;
|
479
|
+
Setac(box1,(wchar_t)'2',ad);
|
480
|
+
if (ad==100) return '2';
|
481
|
+
break;
|
482
|
+
}
|
483
|
+
#endif
|
484
|
+
// --- test 2 new edge based v0.44 --------------------------------------
|
485
|
+
for(ad=d=100;dx>2 && dy>4;){ // min 3x4
|
486
|
+
// rewritten for vectors 0.42
|
487
|
+
int ld, i1, i2, i3, i4, i5, i6, i7; // line derivation + corners
|
488
|
+
DBG( wchar_t c_ask='2'; )
|
489
|
+
if (sdata->holes.num > 0) Break; /* no hole */
|
490
|
+
/* half distance to the center */
|
491
|
+
d=2*sq(128/4);
|
492
|
+
/* now we check for the lower ends, must be near to the corner */
|
493
|
+
if (aa[1][2]>d/4) Break; /* [2] = distance, ~7... */
|
494
|
+
if (aa[2][2]>d/2) Break; /* [2] = distance, ~r... */
|
495
|
+
if (aa[0][2]>d/1) Break; /* [2] = distance, ~d... */
|
496
|
+
if (aa[3][2]>d/1) Break; /* [2] = distance, ~bhk... */
|
497
|
+
/* searching for 4 notches between neighbouring ends */
|
498
|
+
|
499
|
+
/*
|
500
|
+
type A B
|
501
|
+
|
502
|
+
1OOO OO
|
503
|
+
2 1 2 <- 6
|
504
|
+
7-> OOOO O
|
505
|
+
O O <- 5
|
506
|
+
3OO4 3OO4
|
507
|
+
*/
|
508
|
+
|
509
|
+
// ToDo: replace by vector code (get point on line at dy/4)
|
510
|
+
if (loop(bp,dx-1, 0,dx,cs,0,LE)
|
511
|
+
<loop(bp,dx-1,dy/4,dx,cs,0,LE)-dx/8) Break; // 5x7,5x8 z Jul09
|
512
|
+
|
513
|
+
/* get a point on the inner low left side of the J */
|
514
|
+
i =box1->num_frame_vectors[0] - 1;
|
515
|
+
/* rightmost point on upper left side */
|
516
|
+
i2=nearest_frame_vector(box1, aa[0][3], aa[1][3], x1+dx, y0+dy/4);
|
517
|
+
/* upper leftmost vector */
|
518
|
+
i1=nearest_frame_vector(box1, aa[0][3], i2, x0-dx, (y0+y1)/2);
|
519
|
+
i3=aa[1][3];
|
520
|
+
/* low leftmost vector */
|
521
|
+
i5=nearest_frame_vector(box1, aa[2][3], aa[3][3], x0, y1);
|
522
|
+
/* low mostright vector */
|
523
|
+
i4=nearest_frame_vector(box1, aa[1][3], i5, x1+dx, y1);
|
524
|
+
/* next local max_x-point after i5 */
|
525
|
+
i6=i5;
|
526
|
+
for (i=i5;i!=aa[0][3];i=(i+1)%box1->num_frame_vectors[0]) {
|
527
|
+
if (box1->frame_vector[ i][0]
|
528
|
+
>box1->frame_vector[i6][0]) i6=i; // get next maximum
|
529
|
+
if (box1->frame_vector[ i][0]<x0+dx/3
|
530
|
+
&& box1->frame_vector[ i][1]<y0+dy/3
|
531
|
+
&& box1->frame_vector[i6][0]>x0+dx/2) break; // 5
|
532
|
+
}
|
533
|
+
/* which type? ToDo: have a more sure algorithm */
|
534
|
+
i7=nearest_frame_vector(box1, i2, i3, x0-dx/8, (y0+y1)/2);
|
535
|
+
if (box1->frame_vector[i7][0]<=x0+ dx/4
|
536
|
+
&& box1->frame_vector[i7][1]<=y0+2*dy/3) {
|
537
|
+
MSG(fprintf(stderr,"7-segment-type");)
|
538
|
+
} else { /* regular-book-type */
|
539
|
+
MSG( fprintf(stderr,"upper bow not z-like? ad %d", ad); )
|
540
|
+
if (aa[3][0]>=x1-dx/8 // x of upper right point
|
541
|
+
&& aa[3][1]< y0+dy/8) ad=99*ad/100; // y of upper right point
|
542
|
+
if (aa[0][0]<=x0+dx/8 // x of upper left point
|
543
|
+
&& aa[0][1]< y0+dy/8) ad=99*ad/100; // y of upper left point
|
544
|
+
if (aa[3][2]<=aa[1][2]) ad=97*ad/100; // dist to (maxx,0) <= (0,maxy)
|
545
|
+
}
|
546
|
+
// ToDo: output no=(x,y)
|
547
|
+
MSG( fprintf(stderr,"i1-7 %d %d %d %d %d %d %d ad %d",
|
548
|
+
i1,i2,i3,i4,i5,i6,i7,ad); )
|
549
|
+
if (i5==i6) Break; // ~+
|
550
|
+
|
551
|
+
if (box1->frame_vector[i5][1]
|
552
|
+
-box1->frame_vector[i6][1]<dy/4) Break; // ~5
|
553
|
+
if (box1->frame_vector[i1][1]>y0+dy/2) Break; // not to low
|
554
|
+
if (box1->frame_vector[i1][0]>x0+dx/8+dx/16) Break; // slanted ?
|
555
|
+
if (box1->frame_vector[i2][1]>(y0+ y1)/2) Break;
|
556
|
+
if (box1->frame_vector[i2][1]>(5*y0+3*y1)/8) ad=99*ad/100;
|
557
|
+
MSG( fprintf(stderr,"ad %d", ad); )
|
558
|
+
if (box1->frame_vector[i2][0]<(x0+x1+1)/2) Break; // fat tiny fonts?
|
559
|
+
if (box1->frame_vector[i2][0]<(x0+2*x1)/3) ad=99*ad/100;
|
560
|
+
MSG( fprintf(stderr,"ad %d", ad); )
|
561
|
+
if (box1->frame_vector[i3][0]>(3*x0+x1)/4) Break;
|
562
|
+
if (box1->frame_vector[i3][0]>(7*x0+x1)/8) ad=99*ad/100;
|
563
|
+
MSG( fprintf(stderr,"ad %d", ad); )
|
564
|
+
/* check lowest left point */
|
565
|
+
if (box1->frame_vector[i3][1]<(y0+3*y1)/4) Break;
|
566
|
+
if (box1->frame_vector[i3][1]<(y0+7*y1)/8) ad=99*ad/100;
|
567
|
+
MSG( fprintf(stderr,"ad %d", ad); )
|
568
|
+
/* check lower leftmost point from right side */
|
569
|
+
if (box1->frame_vector[i5][0]>(x0+2*x1)/3) Break;
|
570
|
+
if (box1->frame_vector[i5][0]>(x0+ x1)/2) ad=98*ad/100;
|
571
|
+
if (box1->frame_vector[i5][0]>(2*x0+2+x1)/3) ad=99*ad/100; /* 9x10 2 */
|
572
|
+
MSG( fprintf(stderr,"ad %d", ad); )
|
573
|
+
if (box1->frame_vector[i5][1]<(3*y0+5*y1)/8) Break;
|
574
|
+
if (box1->frame_vector[i5][1]<(y0+3*y1)/4) ad=99*ad/100;
|
575
|
+
MSG( fprintf(stderr,"ad %d", ad); )
|
576
|
+
if (box1->frame_vector[i6][1]>(y0+2*y1)/3) Break;
|
577
|
+
if (box1->frame_vector[i6][1]>(y0+ y1)/2) ad=99*ad/100;
|
578
|
+
MSG( fprintf(stderr,"ad %d", ad); )
|
579
|
+
if (box1->frame_vector[i6][0]<(x0+3*x1)/4) Break;
|
580
|
+
if (box1->frame_vector[i6][0]<(x0+7*x1)/8) ad=99*ad/100;
|
581
|
+
|
582
|
+
/* check for zZ */
|
583
|
+
|
584
|
+
/* check if lower left and right points are joined directly */
|
585
|
+
ld=line_deviation(box1, i3, i4);
|
586
|
+
MSG(fprintf(stderr,"i1-i2 %d %d dist= %d/%d",i1,i2,ld,2*sq(1024/4));)
|
587
|
+
if (ld >2*sq(1024/4)) Break;
|
588
|
+
if (ld > sq(1024/4)) ad=99*ad/100;
|
589
|
+
|
590
|
+
if (box1->m3) {
|
591
|
+
if(!hchar){ ad=99*ad/100; }
|
592
|
+
if( gchar){ ad=99*ad/100; }
|
593
|
+
} else { if (ad==100) ad=99; } /* not 100% sure */
|
594
|
+
Setac(box1,'2',ad);
|
595
|
+
if (ad==100) return '2';
|
596
|
+
break;
|
597
|
+
}
|
598
|
+
// --- test 3 -------
|
599
|
+
for(ad=d=100;dx>3 && dy>4;){ // dy<=dx nicht perfekt! besser mittleres
|
600
|
+
// min-suchen fuer m
|
601
|
+
int i1, i2, i3, i4, i5, i6, i7, i8; // line derivation + corners
|
602
|
+
DBG( char c_ask='3'; )
|
603
|
+
if (sdata->holes.num > 1) Break; /* be tolerant */
|
604
|
+
if (sdata->holes.num > 0) ad=98*ad/100; /* be tolerant */
|
605
|
+
if (4*dx<dy) ad=98*ad/100; // to tall 1:2 - 1:3 is usual
|
606
|
+
// --- vector based code ---
|
607
|
+
/* half distance to the center */
|
608
|
+
d=2*sq(128/4);
|
609
|
+
/* now we check for the lower ends, must be near to the corner */
|
610
|
+
if (aa[1][2]>d/1) Break; /* [2] = distance, ~7... */
|
611
|
+
if (aa[2][2]>d/1) Break; /* [2] = distance, ~r... */
|
612
|
+
if (aa[0][2]>d/1) Break; /* [2] = distance, ~d... */
|
613
|
+
if (aa[3][2]>d/1) Break; /* [2] = distance, ~bhk... */
|
614
|
+
/*
|
615
|
+
type A B C
|
616
|
+
|
617
|
+
1OO8 1OO 1OO8
|
618
|
+
O 8 2 <- 7,8
|
619
|
+
2 2 7
|
620
|
+
1-5-> 3OO7 37 3OO
|
621
|
+
4 4 4
|
622
|
+
O 6 6 <- 6
|
623
|
+
5OO6 5OO 5OO
|
624
|
+
*/
|
625
|
+
/* rightmost point on upper left side */
|
626
|
+
i2=nearest_frame_vector(box1, aa[0][3], aa[1][3], x1, y0+3*dy/16);
|
627
|
+
/* rightmost point on lower left side */
|
628
|
+
i4=nearest_frame_vector(box1, aa[0][3], aa[1][3], x1, y1-dy/4);
|
629
|
+
/* leftmost point on middle left side */
|
630
|
+
i3=nearest_frame_vector(box1, i2, i4, x0, y0+dy/2);
|
631
|
+
/* upper leftmost vector */
|
632
|
+
i1=nearest_frame_vector(box1, aa[0][3], i2, x0-dx, (y0+y1)/2);
|
633
|
+
i5=aa[1][3]; // points to vector point in point list
|
634
|
+
i6=aa[2][3];
|
635
|
+
i8=aa[3][3];
|
636
|
+
/* leftmost point on middle right side */
|
637
|
+
i7=nearest_frame_vector(box1, i6, i8, x0 , y0+dy/2);
|
638
|
+
/* which type? ToDo: have a more sure algorithm */
|
639
|
+
if (box1->frame_vector[i7][0]>=x1- dx/4
|
640
|
+
&& box1->frame_vector[i6][0]>=x1- dx/8 // ToDo: ...
|
641
|
+
&& box1->frame_vector[i6][1]>=y1- dy/8) {
|
642
|
+
MSG(fprintf(stderr,"7-segment-type");)
|
643
|
+
} else { /* regular-book-type */
|
644
|
+
}
|
645
|
+
// ToDo: output no=(x,y)
|
646
|
+
MSG(fprintf(stderr,"i1-8 %d %d %d %d %d %d %d %d",i1,i2,i3,i4,i5,i6,i7,i8);)
|
647
|
+
// if (i5==i6) Break; // ~+
|
648
|
+
|
649
|
+
// i2 = upper left gap ) , i3 = middle left <
|
650
|
+
if (box1->frame_vector[i2][0]
|
651
|
+
-box1->frame_vector[i3][0]<dx/4) Break; // video samples
|
652
|
+
if (box1->frame_vector[i4][0]
|
653
|
+
-box1->frame_vector[i3][0]<dx/4) Break; // video samples
|
654
|
+
if (box1->frame_vector[i4][0]
|
655
|
+
-box1->frame_vector[i5][0]<dx/2) Break; // video samples
|
656
|
+
if (box1->frame_vector[i2][0]
|
657
|
+
-box1->frame_vector[i1][0]<dx/2) Break; // video samples
|
658
|
+
if (box1->frame_vector[i1][1]>y0+dy/2) Break; // not to low
|
659
|
+
if (box1->frame_vector[i1][0]>x0+dx/4+dx/16) Break; // slanted?
|
660
|
+
if (box1->frame_vector[i5][1]<y1-dy/2) Break; // not to high
|
661
|
+
if (box1->frame_vector[i5][0]>x0+dx/4) Break;
|
662
|
+
// ToDo ....
|
663
|
+
|
664
|
+
// --- pixel based old code ---
|
665
|
+
// if( get_bw(x0+dx/2,x0+dx/2,y0,y0+dy/4,box1->p,cs,1) == 0 ) Break; // ~4
|
666
|
+
// if( get_bw(x0+dx/2,x0+dx/2,y1-dy/8,y1,box1->p,cs,1) == 0 ) Break; // ~4
|
667
|
+
// if( num_cross(x0+dx/2,x0+dx/2,y0 ,y1,box1->p,cs) < 2 ) Break;
|
668
|
+
// if( num_cross(x0+dx/4,x0+dx/4,y1-dy/2,y1,box1->p,cs) == 0 ) Break;
|
669
|
+
if( get_bw(dx/2,dx/2, 0,dy/6,bp,cs,1) == 0 ) Break; // ~4
|
670
|
+
if( get_bw(dx/2,dx-1, dy/6,dy/6,bp,cs,1) == 0 ) Break; // ~j
|
671
|
+
if( get_bw(dx/2,dx/2,dy-1-dy/8,dy-1,bp,cs,1) == 0 ) Break; // ~4
|
672
|
+
if( num_cross(dx/2,dx/2,0 ,dy-1,bp,cs) < 2 // normal
|
673
|
+
&& num_cross(dx/3,dx/3,0 ,dy-1,bp,cs) < 2 ) Break; // fat LCD
|
674
|
+
if( num_cross(dx/4,dx/4,dy-1-dy/2,dy-1,bp,cs) == 0 ) Break;
|
675
|
+
if( loop(bp,dx/2, 0 ,dy,cs,0,DO)>dy/4 ) Break;
|
676
|
+
if( loop(bp,dx/2, dy-1,dy,cs,0,UP)>dy/4 ) Break;
|
677
|
+
if( loop(bp,dx-1, dy/3,dy,cs,0,LE)>dy/4 /* 3 with upper bow */
|
678
|
+
&& loop(bp,dx-1, dy/8,dy,cs,0,LE)>dy/4 /* 3 with horizontal line */
|
679
|
+
&& loop(bp,dx/4, dy/8,dy,cs,1,RI)<dy/2 ) Break;
|
680
|
+
if( loop(bp,dx-1,2*dy/3,dy,cs,0,LE)>dy/4 ) Break;
|
681
|
+
if( loop(bp,dx-1,3*dy/4,dy,cs,0,LE)>dy/2 ) Break; // ~2 Feb06
|
682
|
+
if( loop(bp,dx-1,7*dy/8,dy,cs,0,LE)>dy/2 ) Break; // ~2 Feb06
|
683
|
+
// search upper right half circle (may fail on 4x5 font)
|
684
|
+
for( i3=x=0,i1=y=dy/5;y<dy/2;y++ ){
|
685
|
+
i=loop(bp,0,y,dx,cs,0,RI);
|
686
|
+
if (i>x) { i3=x=i; i1=y; }
|
687
|
+
} i3--;
|
688
|
+
if( loop(bp,i3,i1,1,cs,0,UP)==1 ) { // find hidden gap in tiny fonts
|
689
|
+
i1--; i3+=loop(bp,i3,i1,dx,cs,0,RI)-1;
|
690
|
+
}
|
691
|
+
if (i3<dx/3 && i3+1+loop(bp,i3+1,i1,dx,cs,1,RI)<3*dx/4) Break;
|
692
|
+
if (loop(bp,dx-1,i1,dx,cs,0,LE)>1+dx/8) ad=ad*99/100; // ~1 with a pixel
|
693
|
+
// search lower right half circle
|
694
|
+
for( i4=x=0,i2=y=dy-1-dy/8;y>=dy/2;y-- ){
|
695
|
+
i=loop(bp,0,y,dx,cs,0,RI);
|
696
|
+
if( i>x ) { i4=x=i;i2=y; }
|
697
|
+
} i4--; if(i4<dx/3 && i4+1+loop(bp,i4+1,i2,dx,cs,1,RI)<3*dx/4) Break;
|
698
|
+
if (loop(bp,dx-1,i2,dx,cs,0,LE)>1+dx/8) ad=ad*99/100; // ~1 with a pixel
|
699
|
+
|
700
|
+
for( x=xa=0,ya=y=dy/4;y<3*dy/4;y++ ){ // right gap, not on LCD-font
|
701
|
+
i=loop(bp,dx-1,y,dx,cs,0,LE);
|
702
|
+
if (i>=xa) { xa=i;ya=y;x=xa+loop(bp,dx-1-xa,y,dx,cs,1,LE); }
|
703
|
+
} if (dy>3*dx) if (xa<2 && x-xa<dx/2) Break; // ~]
|
704
|
+
if (xa>1+dx/8 // noLCD
|
705
|
+
&& xa<=loop(bp,dx-1,i2,dx,cs,0,LE)) ad=ad*99/100; // ~1 with a pixel
|
706
|
+
if (xa>1+dx/8 // noLCD
|
707
|
+
&& xa<=loop(bp,dx-1,i1,dx,cs,0,LE)) ad=ad*99/100; // ~1 with a pixel
|
708
|
+
|
709
|
+
// upper left gap = (i3,i1)
|
710
|
+
// lower left gap = (i4,i2)
|
711
|
+
MSG(fprintf(stderr,"left white gaps (%d,%d) (%d,%d)",i3,i1,i4,i2);)
|
712
|
+
if( get_bw(i3,i3,i1,i2 ,bp,cs,1) != 1 ) Break; // no hor. middle line?
|
713
|
+
if( get_bw(i4,i4,i1,i2 ,bp,cs,1) != 1 ) Break;
|
714
|
+
if( get_bw(i3,i3,0 ,i1 ,bp,cs,1) != 1 ) Break; // no upper bow?
|
715
|
+
if( get_bw(i4,i4,i2,dy-1,bp,cs,1) != 1 ) Break; // no lower bow?
|
716
|
+
// hole is only allowed in beauty fonts
|
717
|
+
// if( num_hole( x0, x1, y0, y1,box1->p,cs,NULL) > 0 ) // there is no hole
|
718
|
+
// if( num_hole( x0, x0+dx/2, y0, y0+dy/2,box1->p,cs,NULL) == 0 ) // except in some beauty fonts
|
719
|
+
if (sdata->holes.num>0)
|
720
|
+
if (sdata->holes.hole[0].x1 >= dx/2 || sdata->holes.hole[0].y1 >= dy/2)
|
721
|
+
Break;
|
722
|
+
Setac(box1,(wchar_t)'3',ad);
|
723
|
+
if (ad==100) return '3';
|
724
|
+
break;
|
725
|
+
}
|
726
|
+
// --- test 4 --------------------------------------------------- 25Nov06
|
727
|
+
for(ad=d=100;dy>3 && dx>2;){ // min 3x4 ~<gA',
|
728
|
+
// rewritten for vectors 0.42
|
729
|
+
int ld, i1, i2, i3, i4, i5, i6, i7, i2up; // line derivation + corners
|
730
|
+
DBG( wchar_t c_ask='4'; )
|
731
|
+
if (sdata->holes.num > 1) Break; /* no or one hole */
|
732
|
+
/* half distance to the center */
|
733
|
+
d=2*sq(128/4); /* 2048 */
|
734
|
+
/* now we check for the lower left end, must be far away */
|
735
|
+
/* lowest is 144 for 9x10 screen font (Apr2009) */
|
736
|
+
if (aa[1][2]<d/16) { /* Apr09: d/8=256 to d/16=128 */
|
737
|
+
MSG( fprintf(stderr," low-left-dist= %d < max= %d", aa[1][2], d); )
|
738
|
+
Break; /* [2] = distance, ~ABDEF... */
|
739
|
+
}
|
740
|
+
/* searching for 4 notches between neighbouring ends */
|
741
|
+
|
742
|
+
/* 5x8 2010-10
|
743
|
+
type A B C D ...@.<-
|
744
|
+
..@@.
|
745
|
+
1 5 1 1 1 .@.@.<
|
746
|
+
O O O O5 O5 @..@. left=i2up
|
747
|
+
2OO3 O 5 O O O O <- 7 6 @..@.
|
748
|
+
O 2O3O 2OO3 2OO3O @@@@@
|
749
|
+
4 4 4 4 ...@.
|
750
|
+
...@.<-
|
751
|
+
|
752
|
+
|
753
|
+
y4-y3 should be significant (bigger y3-y6)?
|
754
|
+
*/
|
755
|
+
|
756
|
+
/* Warning: aa0 can be left upper or left lower point for type B */
|
757
|
+
/* get a point on the inner low left side of the J */
|
758
|
+
i =box1->num_frame_vectors[0] - 1;
|
759
|
+
/* leftmost upper point */
|
760
|
+
i1=nearest_frame_vector(box1, 0, i, x0, y0-dy);
|
761
|
+
/* lowest from leftmost vector can be very low (20/23) */
|
762
|
+
i2=nearest_frame_vector(box1, 0, i, x0-2*dx, (y0+7*y1)/8);
|
763
|
+
i2up=
|
764
|
+
nearest_frame_vector(box1, 0, i, x0-2*dx, (5*y0+3*y1)/8);
|
765
|
+
/* lowest vector */
|
766
|
+
i4=nearest_frame_vector(box1, 0, i, (x0+2*x1)/3, y1+dy);
|
767
|
+
/* right center crossing point */
|
768
|
+
i3=nearest_frame_vector(box1, i2, i4, x1, (3*y0+y1)/4);
|
769
|
+
/* get a point on the outer right side below top serif */
|
770
|
+
/* next local max_y-point after i4 */
|
771
|
+
i5=i4;
|
772
|
+
for (i=i4;i!=i2;i=(i+1)%box1->num_frame_vectors[0]) {
|
773
|
+
if (box1->frame_vector[ i][1]
|
774
|
+
<box1->frame_vector[i5][1]) i5=i; // get next maximum
|
775
|
+
if (box1->frame_vector[ i][1]
|
776
|
+
>box1->frame_vector[i5][1]+1) break; // break after maximum
|
777
|
+
if (box1->frame_vector[ i][0]<x0+dx/4) break; // type A B
|
778
|
+
}
|
779
|
+
if (box1->num_frames>1) { // type C D
|
780
|
+
i = box1->num_frame_vectors[0] - 1; // end outer loop
|
781
|
+
j = box1->num_frame_vectors[1] - 1; // end inner loop
|
782
|
+
if (box1->num_frames>2) { // see font2.png, 2nd one pixel hole
|
783
|
+
j = box1->num_frame_vectors[2] - 1; // end inner loop
|
784
|
+
ad=99*ad/100; // little bit unsure
|
785
|
+
}
|
786
|
+
i6=nearest_frame_vector(box1, i+1, j, x1, y1);
|
787
|
+
i7=nearest_frame_vector(box1, i+1, j, x0, y1);
|
788
|
+
if (box1->frame_vector[i1][0]
|
789
|
+
-box1->frame_vector[i2][0]<dx/4+1) ad=96*ad/100; // ~4x6q
|
790
|
+
i =nearest_frame_vector(box1, i+1, j, x0, y0); // top left
|
791
|
+
MSG(fprintf(stderr,"triangle type top-left i=%d",i);)
|
792
|
+
if (box1->frame_vector[i ][0]-x0<dx/4+1
|
793
|
+
&& box1->frame_vector[i ][1]-y0<dy/4+1
|
794
|
+
&& dx>7) ad=97*ad/100; // q
|
795
|
+
|
796
|
+
} else { // type A B
|
797
|
+
i6=nearest_frame_vector(box1, i5, i1, (x0+3*x1)/4, y1-dy/8);
|
798
|
+
i7=nearest_frame_vector(box1, i5, i1, x0 , y1-dy/8);
|
799
|
+
MSG(fprintf(stderr,"open type");)
|
800
|
+
if (box1->frame_vector[i6][1]-y0>3*dy/4
|
801
|
+
|| box1->frame_vector[i7][1]-y0>3*dy/4) ad=96*ad/100; // ~uU
|
802
|
+
}
|
803
|
+
// ToDo: output no=(x,y)
|
804
|
+
MSG(fprintf(stderr,"i1-7 %d %d %d %d %d %d %d 2up %d",i1,i2,i3,i4,i5,i6,i7,i2up);)
|
805
|
+
if (i5==i6) Break; // ~+
|
806
|
+
|
807
|
+
if (box1->frame_vector[i1][1]>y0+dy/8) Break; // not to low
|
808
|
+
if (box1->frame_vector[i2][1]
|
809
|
+
-box1->frame_vector[i1][1]<dy/2) Break;
|
810
|
+
if (box1->frame_vector[i3][0]
|
811
|
+
-box1->frame_vector[i2][0]<dx/4) Break;
|
812
|
+
if (abs(box1->frame_vector[i3][1]
|
813
|
+
-box1->frame_vector[i2][1])>dy/4) Break;
|
814
|
+
if (box1->frame_vector[i2][0]>x0+dx/8) Break;
|
815
|
+
if (box1->frame_vector[i2][1]>y1-dy/8) Break;
|
816
|
+
if (box1->frame_vector[i4][1]
|
817
|
+
-box1->frame_vector[i2][1]<dy/8) Break;
|
818
|
+
if (box1->frame_vector[i4][1]
|
819
|
+
-box1->frame_vector[i2][1]<dy/6) ad=99*ad/100;
|
820
|
+
/* min. distance of the horizontal bar to the ground */
|
821
|
+
/* y4-y3 should be significant (bigger y3-y6)? */
|
822
|
+
if (box1->frame_vector[i4][1]
|
823
|
+
-box1->frame_vector[i3][1]<1+dy/16) Break;
|
824
|
+
if ((box1->frame_vector[i4][1]
|
825
|
+
-box1->frame_vector[i3][1])*2<=
|
826
|
+
(box1->frame_vector[i3][1]
|
827
|
+
-box1->frame_vector[i6][1])) Break; // 090728 gas_meter (flat-ulike)
|
828
|
+
if ((box1->frame_vector[i4][1]
|
829
|
+
-box1->frame_vector[i3][1])<
|
830
|
+
(box1->frame_vector[i3][1]
|
831
|
+
-box1->frame_vector[i6][1])) ad=99*ad/100;
|
832
|
+
if (box1->frame_vector[i4][1]
|
833
|
+
-box1->frame_vector[i3][1]<dy/6) ad=99*ad/100; /* tall chars */
|
834
|
+
if (box1->frame_vector[i4][1]
|
835
|
+
-box1->frame_vector[i3][1]<dy/8) ad=99*ad/100;
|
836
|
+
if (box1->frame_vector[i4][1]<y1-1-dy/8) Break;
|
837
|
+
if (box1->frame_vector[i3][0]<x0+dx/4) Break;
|
838
|
+
if (box1->frame_vector[i3][0]<x0+dx/2) ad=98*ad/100;
|
839
|
+
/* on very tall chars the i3 point can be near to the groundline */
|
840
|
+
if (box1->frame_vector[i3][1]>y1-1) Break;
|
841
|
+
if (box1->frame_vector[i3][1]>y1-dy/16) Break;
|
842
|
+
if (box1->frame_vector[i3][1]>=y1) Break; // ~5x5#
|
843
|
+
if (box1->frame_vector[i5][0]<x0+dx/3) Break;
|
844
|
+
/* upper end of right vertical line */
|
845
|
+
if (box1->frame_vector[i5][1]>y0+2*dy/3) Break;
|
846
|
+
if (box1->frame_vector[i6][1]
|
847
|
+
-box1->frame_vector[i5][1]<1+dy/16) Break;
|
848
|
+
if (box1->frame_vector[i6][0]<x0+dx/3) Break;
|
849
|
+
if (box1->frame_vector[i7][0]>x0+dx/2) Break;
|
850
|
+
if (box1->frame_vector[i7][0]>x0+dx/3) ad=ad*99/100;
|
851
|
+
if (box1->frame_vector[i6][1]<y0+dy/3) Break;
|
852
|
+
if (box1->frame_vector[i6][0]<x0+dx/2) ad=96*ad/100; // ~ 42
|
853
|
+
if (box1->frame_vector[i6][0]<aa[2][0]-dx/2
|
854
|
+
&& aa[2][1]>=y1-1-dy/8) ad=96*ad/100; // ~ 42
|
855
|
+
if (box1->frame_vector[i7][1]<y0+dy/3) Break;
|
856
|
+
if (abs(box1->frame_vector[i3][1]
|
857
|
+
-box1->frame_vector[i2][1])>dy/4) Break;
|
858
|
+
|
859
|
+
/* check if upper left and lower left points are joined directly */
|
860
|
+
ld=line_deviation(box1, i1, i2up);
|
861
|
+
MSG(fprintf(stderr,"i1-i2up %d %d dist= %d/%d",i1,i2up,ld,2*sq(1024/4));)
|
862
|
+
if (ld >2*sq(1024/4)) Break;
|
863
|
+
if (i2!=i2up) ld=line_deviation(box1, i2up, i2); else ld=0;
|
864
|
+
MSG(fprintf(stderr,"i2up-i2 %d %d dist= %d/%d",i2up,i2,ld,2*sq(1024/4));)
|
865
|
+
if (ld >2*sq(1024/4)) Break;
|
866
|
+
/* check if lower right and upper right points are joined directly */
|
867
|
+
ld=line_deviation(box1, i2, i3);
|
868
|
+
MSG(fprintf(stderr,"i2-i3 %d %d dist= %d/%d",i2,i3,ld,2*sq(1024/4));)
|
869
|
+
if (ld > sq(1024/4)) Break;
|
870
|
+
/* check if lower right and upper right points are joined directly */
|
871
|
+
ld=line_deviation(box1, i3, i4);
|
872
|
+
MSG(fprintf(stderr,"i3-i4 %d %d dist= %d/%d",i3,i4,ld,2*sq(1024/4));)
|
873
|
+
if (ld > sq(1024/4)) Break;
|
874
|
+
/* check if lower right and upper right points are joined directly */
|
875
|
+
ld=line_deviation(box1, i6, i7);
|
876
|
+
MSG(fprintf(stderr,"i6-i7 %d %d dist= %d/%d",i6,i7,ld,2*sq(1024/4));)
|
877
|
+
if (ld >2*sq(1024/4)) Break;
|
878
|
+
|
879
|
+
// handwritten a i1=(9,0) i5=(21,1) Aug2010
|
880
|
+
if (sdata->holes.num == 1 // type C and D against italic a, alpha
|
881
|
+
&& // expect no distance between 1 and 5
|
882
|
+
box1->frame_vector[i5][0]
|
883
|
+
- box1->frame_vector[i1][0] > dx/4 ) Break;
|
884
|
+
|
885
|
+
// 4 exists as gchar and ~gchar
|
886
|
+
if(!hchar){ ad=99*ad/100; }
|
887
|
+
Setac(box1,'4',ad);
|
888
|
+
break;
|
889
|
+
}
|
890
|
+
#ifdef Old_pixel_based
|
891
|
+
// --- old test 4 pixelbased ------- remove!
|
892
|
+
for(ad=d=100;dx>3 && dy>5;){ // dy>dx, min 4x6 font
|
893
|
+
DBG( char c_ask='4'; )
|
894
|
+
if (sdata->holes.num > 2) Break; /* be tolerant */
|
895
|
+
if (sdata->holes.num > 1) ad=97*ad/100;
|
896
|
+
// upper raising or vertical line
|
897
|
+
if( loop(bp,0 ,3*dy/16,dx,cs,0,RI)
|
898
|
+
< loop(bp,0 ,2*dy/4 ,dx,cs,0,RI)-dx/8 ) Break;
|
899
|
+
// search for a vertical line on lower end
|
900
|
+
for (y=0;y<dy/4;y++)
|
901
|
+
if( loop(bp,0 ,dy-1-y,dx,cs,0,RI)
|
902
|
+
+ loop(bp,dx-1,dy-1-y,dx,cs,0,LE) >= dx/2 ) break;
|
903
|
+
if (y>=dy/4) Break;
|
904
|
+
if( loop(bp,0 ,dy-1-dy/8,dx,cs,0,RI) < dx/4 ) Break;
|
905
|
+
// --- follow line from (1,0) to (0,.7)
|
906
|
+
y=0; x=loop(bp,0,0,dx,cs,0,RI);
|
907
|
+
if (x<=dx/4) { // ocr-a-4
|
908
|
+
i=loop(bp,0,dy/4,dx,cs,0,RI); if (i>dx/4) Break;
|
909
|
+
i=loop(bp,i,dy/4,dx,cs,1,RI); if (i>dx/2) Break;
|
910
|
+
j=loop(bp,i,dy/4,dy,cs,0,DO)+dy/4; if (j>7*dy/8) Break;
|
911
|
+
}
|
912
|
+
turmite(bp,&x,&y,0,dx-1,0,dy-1,cs,DO,LE); if( x>=0 ) Break;
|
913
|
+
|
914
|
+
y=loop(bp,0,0,dy,cs,0,DO);
|
915
|
+
if( (y+loop(bp,0,y,dy,cs,1,DO)) < dy/2 ) Break;
|
916
|
+
if( get_bw(x0 , x0+3*dx/8, y1-dy/7, y1-dy/7,box1->p,cs,1) == 1 ) Break;
|
917
|
+
if( get_bw(x0+dx/2, x1 , y1-dy/3, y1-dy/3,box1->p,cs,1) != 1 ) Break;
|
918
|
+
if( get_bw(x0+dx/2, x0+dx/2, y0+dy/3, y1-dy/5,box1->p,cs,1) != 1 ) Break;
|
919
|
+
i=loop(bp,bp->x-1, bp->y/4,dx,cs,0,LE);
|
920
|
+
if( i > loop(bp,bp->x-1,2*bp->y/4,dx,cs,0,LE)+1
|
921
|
+
&& i > loop(bp,bp->x-1,3*bp->y/8,dx,cs,0,LE)+1 ) Break;
|
922
|
+
if (loop(bp,0,0,dx,cs,0,RI)>dx/4) {
|
923
|
+
for(i=dx/8+1,x=0;x<dx && i;x++){
|
924
|
+
if( num_cross(x ,x ,0 ,dy-1, bp,cs) == 2 ) i--;
|
925
|
+
} if( i ) Break;
|
926
|
+
}
|
927
|
+
for(i=dy/6+1,y=dy/4;y<dy && i;y++){
|
928
|
+
if( num_cross(0 ,dx-1,y ,y , bp,cs) == 2 ) i--;
|
929
|
+
} if( dy>15 && i ) Break;
|
930
|
+
for(i=dy/10+1,y=dy-1-dy/4;y<dy && i;y++){
|
931
|
+
if( num_cross(0 ,dx-1,y ,y , bp,cs) == 1 )
|
932
|
+
if( num_cross(dx/2,dx-1,y ,y , bp,cs) == 1 ) i--;
|
933
|
+
} if( i ) Break;
|
934
|
+
// i4 = num_hole ( x0, x1, y0, y1,box1->p,cs,NULL);
|
935
|
+
// ToDo:
|
936
|
+
// - get start and endpoint of left edge of left vert. line
|
937
|
+
// and check if that is an streight line
|
938
|
+
// - check the right edge of the inner hole (if there) too
|
939
|
+
i4 = sdata->holes.num;
|
940
|
+
if (sdata->holes.num >0) { // ~q
|
941
|
+
i = loop(bp,0,dy/16,dx,cs,0,RI);
|
942
|
+
if (i < dx/3) Break;
|
943
|
+
if (i < dx/2) ad=98*ad/100; // hole?
|
944
|
+
if ( loop(bp, 0,dy-1,dy,cs,0,UP)
|
945
|
+
-loop(bp,dx/8+1,dy-1,dy,cs,0,UP)>dy/16) ad=97*ad/100;
|
946
|
+
}
|
947
|
+
// thickness of left vertical line
|
948
|
+
for (j=y=0;y<dy/6;y++) {
|
949
|
+
i=loop(bp,dx-1 ,y,dx,cs,0,LE);
|
950
|
+
i=loop(bp,dx-1-i,y,dx,cs,1,LE); if (i>j) j=i;
|
951
|
+
}
|
952
|
+
if (j>=dx/2) ad=98*ad/100; // ~q handwritten a (or very thinn 4)
|
953
|
+
// ToDo: check y of masscenter of the hole q4
|
954
|
+
|
955
|
+
if( i4 ) if( dx > 15 )
|
956
|
+
if( loop(bp, dx/2, 0,dy,cs,0,DO)<dy/16
|
957
|
+
&& loop(bp, dx/4, 0,dy,cs,0,DO)<dy/8
|
958
|
+
&& loop(bp,3*dx/4, 0,dy,cs,0,DO)<dy/8
|
959
|
+
&& loop(bp, dx/4,dy-1,dy,cs,0,UP)<dy/8
|
960
|
+
&& loop(bp, dx/2,dy-1,dy,cs,0,UP)<dy/8
|
961
|
+
&& loop(bp,3*dx/4,dy-1,dy,cs,0,UP)<dy/4 ) Break; // ~9
|
962
|
+
|
963
|
+
i =loop(bp,dx-1 ,dy-1,dx,cs,0,LE); // ~9
|
964
|
+
i+=loop(bp,dx-1-i,dy-1,dx,cs,1,LE);
|
965
|
+
if( i>3*dx/4
|
966
|
+
&& i-loop(bp,dx-1,dy-1-dy/8,dx,cs,0,LE)>dx/4 ) Break;
|
967
|
+
|
968
|
+
i =loop(bp,dx-1-dx/4,dy-1,dx,cs,0,UP);
|
969
|
+
if (i> dy/2) ad=97*ad/100;
|
970
|
+
if (i>3*dy/4) ad=97*ad/100; /* handwritten n */
|
971
|
+
|
972
|
+
if( num_cross(0 ,dx-1,dy/16 ,dy/16 , bp,cs) == 2 // ~9
|
973
|
+
&& loop(bp,dx-1,dy/16 ,dx,cs,0,LE)>
|
974
|
+
loop(bp,dx-1,dy/16+1+dy/32,dx,cs,0,LE) ) Break;
|
975
|
+
if ( !hchar) ad=99*ad/100;
|
976
|
+
if (gchar && !hchar) ad=98*ad/100; // ~q
|
977
|
+
Setac(box1,(wchar_t)'4',ad);
|
978
|
+
if (ad>99) bc='4';
|
979
|
+
break;
|
980
|
+
}
|
981
|
+
#endif
|
982
|
+
// --- test 6 ------- ocr-a-6 looks like a b :(
|
983
|
+
for(ad=d=100;dx>3 && dy>4;){ // dy>dx
|
984
|
+
DBG( char c_ask='6'; )
|
985
|
+
if (sdata->holes.num > 2) Break; /* be tolerant */
|
986
|
+
if( loop(bp, 0, dy/4,dx,cs,0,RI)>dx/2 // ocr-a=6
|
987
|
+
&& loop(bp,dx-1, 0,dy,cs,0,DO)>dy/4 ) Break; // italic-6
|
988
|
+
if( loop(bp, 0, dy/2,dx,cs,0,RI)>dx/4 ) Break;
|
989
|
+
if( loop(bp, 0,3*dy/4,dx,cs,0,RI)>dx/4 ) Break;
|
990
|
+
if( loop(bp,dx-1,3*dy/4,dx,cs,0,LE)>dx/2 ) Break;
|
991
|
+
if( num_cross(x0+ dx/2,x0+ dx/2,y0 ,y1 ,box1->p,cs) != 3
|
992
|
+
&& num_cross(x0+5*dx/8,x0+5*dx/8,y0 ,y1 ,box1->p,cs) != 3 ) {
|
993
|
+
if( num_cross(x0+ dx/2,x0+ dx/2,y0+dy/4,y1 ,box1->p,cs) != 2
|
994
|
+
&& num_cross(x0+5*dx/8,x0+5*dx/8,y0+dy/4,y1 ,box1->p,cs) != 2 ) Break;
|
995
|
+
// here we have the problem to decide between ocr-a-6 and b
|
996
|
+
if ( loop(box1->p,(x0+x1)/2,y0,dy,cs,0,DO)<dy/2 ) Break;
|
997
|
+
ad=99*ad/100;
|
998
|
+
} else {
|
999
|
+
if (loop(box1->p,x0+dx/2,y0,dx,cs,0,DO)>dy/8
|
1000
|
+
&& loop(box1->p,x1-dx/4,y0,dx,cs,0,DO)>dy/8 ) Break;
|
1001
|
+
}
|
1002
|
+
if( num_cross(x0 ,x1 ,y1-dy/4,y1-dy/4,box1->p,cs) != 2 ) Break;
|
1003
|
+
for( y=y0+dy/6;y<y0+dy/2;y++ ){
|
1004
|
+
x =loop(box1->p,x1 ,y ,dx,cs,0,LE); if( x>dx/2 ) break;
|
1005
|
+
x+=loop(box1->p,x1-x+1,y-1,dx,cs,0,LE); if( x>dx/2 ) break;
|
1006
|
+
} if( y>=y0+dy/2 ) Break;
|
1007
|
+
if (loop(box1->p,x0,y1-dy/3,dx,cs,0,RI)>dx/4 ) Break;
|
1008
|
+
if (loop(box1->p,x1,y1-dy/3,dx,cs,0,LE)>dx/4 ) Break;
|
1009
|
+
|
1010
|
+
if (sdata->holes.num != 1) Break;
|
1011
|
+
if (sdata->holes.hole[0].y1 < dy/2) ad=95*ad/100; // whats good for?
|
1012
|
+
if (sdata->holes.hole[0].y0 < dy/4) Break;
|
1013
|
+
MSG( fprintf(stderr,"hole[0].x0,x1 %d %d", sdata->holes.hole[0].x0,
|
1014
|
+
sdata->holes.hole[0].x1); )
|
1015
|
+
if (sdata->holes.hole[0].x0<1
|
1016
|
+
&& dx-1-sdata->holes.hole[0].x1>2) ad=ad*99/100; // melted serif sS ?
|
1017
|
+
if (loop(box1->p,x0,y0+dy/2,dx,cs,0,RI)>0
|
1018
|
+
&& loop(box1->p,x0,y0+dy/4,dx,cs,0,RI)==0
|
1019
|
+
&& loop(box1->p,x0,y1-dy/4,dx,cs,0,RI)==0) ad=97*ad/100; // molten serif sS
|
1020
|
+
// if( num_hole ( x0, x1, y0, y0+dy/2,box1->p,cs,NULL) > 0 ) ad=95*ad/100;
|
1021
|
+
// if( num_hole ( x0, x1, y0+dy/4, y1,box1->p,cs,NULL) != 1 ) Break;
|
1022
|
+
// if( num_hole ( x0, x1, y0 , y1,box1->p,cs,NULL) != 1 ) Break;
|
1023
|
+
// out_x(box1); printf(" x0 y0 %d %d\n",x0,y0);
|
1024
|
+
/* check left vertical bow */
|
1025
|
+
i1=loop(bp,0,dy/8 ,dx,cs,0,RI);
|
1026
|
+
i3=loop(bp,0,dy-1-dy/8,dx,cs,0,RI);
|
1027
|
+
i2=loop(bp,0,dy/2 ,dx,cs,0,RI);
|
1028
|
+
if(i1+i3-2*i2<-2-dx/16 && i1+i2+i3>0) Break; // convex from left
|
1029
|
+
if(i1+i3-2*i2<1 && i1+i2+i3>0) ad=99*ad/100; // 7-segment-font
|
1030
|
+
for( x=dx,y=0;y<dy/4;y++ ){ // ~ b (serife?)
|
1031
|
+
i1=loop(bp, 0,y,dx,cs,0,RI);
|
1032
|
+
i2=loop(bp,i1,y,dx,cs,1,RI);
|
1033
|
+
if (i2+i1>dx/2 && i2>dx/4) break; /* its a 6 (example: 7-segment) */
|
1034
|
+
if (i1<x) x=i1; else if (i1>x) break; /* may be serifen b */
|
1035
|
+
} if (y<dy/4 && i1+i2<=dx/2) Break;
|
1036
|
+
// ~& (with open upper loop)
|
1037
|
+
for( i=0,y=dy/2;y<dy;y++){
|
1038
|
+
if( num_cross(dx/2,dx-1,y,y,bp,cs) > 1 ) i++; if( i>dy/8 ) break;
|
1039
|
+
} if( y<dy ) Break;
|
1040
|
+
if ( gchar) ad=99*ad/100;
|
1041
|
+
if (!hchar) ad=98*ad/100;
|
1042
|
+
if ( box1->dots ) ad=98*ad/100;
|
1043
|
+
Setac(box1,(wchar_t)'6',ad);
|
1044
|
+
bc='6';
|
1045
|
+
break;
|
1046
|
+
}
|
1047
|
+
// --- test 7 ---------------------------------------------------
|
1048
|
+
for(ad=d=100;dx>2 && dy>4;){ // dx>1 dy>2*dx
|
1049
|
+
DBG( char c_ask='7'; )
|
1050
|
+
if (sdata->holes.num > 1) Break; /* be tolerant */
|
1051
|
+
if( loop(bp,dx/2,0,dy,cs,0,DO)>dy/8 ) Break;
|
1052
|
+
if( num_cross(0,dx-1,3*dy/4,3*dy/4,bp,cs) != 1 ) Break; // preselect
|
1053
|
+
for( yb=xb=y=0;y<dy/2;y++){ // upper h-line and gap
|
1054
|
+
j=loop(bp,0,y,dx,cs,0,RI);if(xb>0 && j>dx/4) break; // gap after h-line
|
1055
|
+
j=loop(bp,j,y,dx,cs,1,RI);if(j>xb){ xb=j;yb=y; } // h-line
|
1056
|
+
} if( xb<dx/4 || y==dy/2 ) Break;
|
1057
|
+
j=loop(bp,0,dy/2,dx,cs,0,RI);
|
1058
|
+
j=loop(bp,j,dy/2,dx,cs,1,RI); if(xb<2*j) Break; // minimum thickness
|
1059
|
+
for(x=0,y+=dy/16;y<dy;y++){ // one v-line?
|
1060
|
+
if( num_cross(0,dx-1,y,y,bp,cs) != 1 ) break;
|
1061
|
+
j=loop(bp,dx-1,y,dx,cs,0,LE); if( j<x ) break; if( j-1>x ) x=j-1;
|
1062
|
+
} if( y<dy || x<dx/3 ) {
|
1063
|
+
MSG( fprintf(stderr,"xy= %d %d",x,y); )
|
1064
|
+
Break;
|
1065
|
+
}
|
1066
|
+
j =loop(bp,dx-1,0,dy,cs,0,DO); // ~T
|
1067
|
+
j+=loop(bp,dx-1,j,dy,cs,1,DO)+dy/16;
|
1068
|
+
i =loop(bp,dx-1,j,dx,cs,0,LE); if(j<dy/2) {
|
1069
|
+
if (i>j) Break;
|
1070
|
+
j=loop(bp, 0,j,dx,cs,0,RI);
|
1071
|
+
if(j>dx/4 && j<=i+dx/16) Break; // tall T
|
1072
|
+
}
|
1073
|
+
|
1074
|
+
MSG( fprintf(stderr,"7: ad= %d",ad); )
|
1075
|
+
if( loop(bp, 0,3*dy/8,dx,cs,0,RI)
|
1076
|
+
<=loop(bp,dx-1,3*dy/8,dx,cs,0,LE)+dx/8 ) ad=ad*98/100; // l
|
1077
|
+
MSG( fprintf(stderr,"7: ad= %d",ad); )
|
1078
|
+
if( num_cross(0,dx-1,dy/4,dy/4,bp,cs) == 1
|
1079
|
+
&& loop(bp,0,dy/4,dx,cs,0,RI) < dx/2 ) ad=ad*96/100; // J
|
1080
|
+
MSG( fprintf(stderr,"7: ad= %d",ad); )
|
1081
|
+
|
1082
|
+
if (box1->m3 && dy<box1->m3-box1->m2) ad=99*ad/100; // too small
|
1083
|
+
if (box1->m3 && 2*dy<box1->m3-box1->m2) ad=96*ad/100; // too small
|
1084
|
+
if (dy>3*dx) ad=99*ad/100; // )
|
1085
|
+
if ( gchar) ad=99*ad/100; // J
|
1086
|
+
if (!hchar) ad=99*ad/100;
|
1087
|
+
Setac(box1,(wchar_t)'7',ad);
|
1088
|
+
break;
|
1089
|
+
}
|
1090
|
+
// --- test 8 ---------------------------------------------------
|
1091
|
+
// last change: May15th,2000 JS
|
1092
|
+
for(ad=d=100;dx>2 && dy>4;){ // or we need large height
|
1093
|
+
DBG( char c_ask='8'; )
|
1094
|
+
if (sdata->holes.num != 2) Break;
|
1095
|
+
if( num_cross(x0,x1,y0 +dy/4,y0 +dy/4,box1->p,cs) != 2 ) Break; // ~gr (glued)
|
1096
|
+
if( num_cross(x0,x1,y1 -dy/4,y1 -dy/4,box1->p,cs) != 2
|
1097
|
+
&& num_cross(x0,x1,y1-3*dy/8,y1-3*dy/8,box1->p,cs) != 2 ) Break;
|
1098
|
+
if( get_bw(x0,x0+dx/4,y1-dy/4,y1-dy/4,box1->p,cs,1) == 0 ) Break; // ~9
|
1099
|
+
if( get_bw(x0,x0+dx/2,y0+dy/4,y0+dy/4,box1->p,cs,1) == 0 ) Break;
|
1100
|
+
if( get_bw(x0+dx/2,x0+dx/2,y0+dy/4,y1-dy/4,box1->p,cs,1) == 0 ) Break; // ~0
|
1101
|
+
// MSG( printf(" x0 y0 %d %d\n",x0,y0); )
|
1102
|
+
for( i2=i1=x=0,i=y=y0+dy/3;y<=y1-dy/3;y++){ // check left middle nick
|
1103
|
+
j=loop(box1->p,x0,y,dx,cs,0,RI);
|
1104
|
+
if (j>x || (abs(j-x)<=dx/8 /* care about MICR E-13B font */
|
1105
|
+
&& (i1=loop(box1->p,x0+j,y,dx,cs,1,RI))>dx/2)) {
|
1106
|
+
if (j>x) x=j; i=y; if (i1>i2) i2=i1; }
|
1107
|
+
} if(i>=y1-dy/3 || (x<dx/8 && i2<=dx/2) || x>dx/2) Break; // no gB
|
1108
|
+
if (x< dx/4) ad=99*ad/100; // no B
|
1109
|
+
if (x<=dx/8) ad=98*ad/100; // no B
|
1110
|
+
j = loop(box1->p,x1,y1- dy/4,dx,cs,0,LE);
|
1111
|
+
if( j>loop(box1->p,x1,y1- dy/5,dx,cs,0,LE)
|
1112
|
+
&& j>loop(box1->p,x1,y1-2*dy/5,dx,cs,0,LE) ) Break; // &
|
1113
|
+
// check for upper hole
|
1114
|
+
for (j=0;j<sdata->holes.num;j++) {
|
1115
|
+
if (sdata->holes.hole[j].y1 < i-y0+1 ) break;
|
1116
|
+
if (sdata->holes.hole[j].y1 < i-y0+dy/8) break;
|
1117
|
+
} if (j==sdata->holes.num) Break; // not found
|
1118
|
+
// if( num_hole(x0,x1,y0,i+1 ,box1->p,cs,NULL)!=1 )
|
1119
|
+
// if( num_hole(x0,x1,y0,i+dy/8,box1->p,cs,NULL)!=1 ) Break; // upper hole
|
1120
|
+
// check for lower hole
|
1121
|
+
for (j=0;j<sdata->holes.num;j++) {
|
1122
|
+
if (sdata->holes.hole[j].y0 > i-y0-1 ) break;
|
1123
|
+
} if (j==sdata->holes.num) Break; // not found
|
1124
|
+
// if( num_hole(x0,x1,i-1,y1,box1->p,cs,NULL)!=1 ) Break;
|
1125
|
+
i1=i; // left middle nick
|
1126
|
+
/* find the middle right nick */
|
1127
|
+
for( x=0,i2=i=y=y0+dy/3;y<=y1-dy/3;y++){
|
1128
|
+
j=loop(box1->p,x1,y,dx,cs,0,LE); if( j>=x ) i2=y;
|
1129
|
+
/* we care also for 7-segment and unusual fonts */
|
1130
|
+
if (j>x || (abs(j-x)<=(dx+4)/8
|
1131
|
+
&& loop(box1->p,x1-j,y,dx,cs,1,LE)>dx/2)){
|
1132
|
+
if (j>x) x=j; i=y; }
|
1133
|
+
// MSG(fprintf(stderr," yjix %d %d %d %d %d %d",y-y0,j,i-y0,x,loop(box1->p,x1-j,y,dx,cs,1,LE),dx/2);)
|
1134
|
+
}
|
1135
|
+
if( i>y0+dy/2+dy/10 ) Break;
|
1136
|
+
// if( x<dx/8 ) Break;
|
1137
|
+
if( x>dx/2 ) Break;
|
1138
|
+
MSG(fprintf(stderr,"center bar at y= %d %d x=%d+%d i1=%d",i-y0,i2-y0,x,j,i1);)
|
1139
|
+
if( num_cross(x0,x1, i , i ,box1->p,cs) != 1
|
1140
|
+
&& num_cross(x0,x1, i+1 , i+1 ,box1->p,cs) != 1
|
1141
|
+
&& num_cross(x0,x1,(i+i2)/2,(i+i2)/2,box1->p,cs) != 1 ) Break; // no g
|
1142
|
+
if(abs(i1-i)>(dy+5)/10) ad=99*ad/100; // y-distance right-left-nick
|
1143
|
+
if(abs(i1-i)>(dy+4)/8) ad=99*ad/100; // y-distance right-left-nick
|
1144
|
+
if(abs(i1-i)>(dy+2)/4) Break;
|
1145
|
+
// ~B ff
|
1146
|
+
for(i=dx,y=0;y<dy/8+2;y++){
|
1147
|
+
j=loop(bp,0,y,dx,cs,0,RI); if( j<i ) i=j; if( j>i+dx/16 ) break;
|
1148
|
+
} if( y<dy/8+2 ) Break;
|
1149
|
+
for(i=dx,y=0;y<dy/8+2;y++){
|
1150
|
+
j=loop(bp,0,dy-1-y,dx,cs,0,RI);
|
1151
|
+
if( j<i ) i=j; if( j>i+dx/16 ) break;
|
1152
|
+
} if( y<dy/8+2 ) Break;
|
1153
|
+
if( dy>16 && num_cross(0,dx-1,dy-1,dy-1,bp,cs) > 1
|
1154
|
+
&& loop(bp,0,dy-1,dx,cs,0,RI) <dx/8+1 ) Break; // no fat serif S
|
1155
|
+
for( i=0,y=dy/2;y<dy;y++){
|
1156
|
+
if( num_cross(0,dx-1,y,y,bp,cs) > 2 ) i++; if( i>dy/8 ) break;
|
1157
|
+
} if( y<dy ) Break;
|
1158
|
+
if ( loop(bp,dx-1,0,dx,cs,0,LE)==0 ) ad=99*ad/100;
|
1159
|
+
if (num_cross( 0,dx-1,dy-1,dy-1,bp,cs) > 1) ad=98*ad/100; // &
|
1160
|
+
if (num_cross(dx-1,dx-1,dy/2,dy-1,bp,cs) > 1) ad=98*ad/100; // &
|
1161
|
+
if (num_cross( 0,dx-1, 0, 0,bp,cs) > 1) ad=98*ad/100;
|
1162
|
+
if (dy>15)
|
1163
|
+
if (num_cross( 0,dx-1, 1, 1,bp,cs) > 1) ad=98*ad/100;
|
1164
|
+
/* if m1..4 is unsure ignore hchar and gchar ~ga */
|
1165
|
+
if (!hchar) {
|
1166
|
+
if ((box1->m2-box1->y0)*8>=dy) ad=98*ad/100;
|
1167
|
+
else ad=99*ad/100;
|
1168
|
+
}
|
1169
|
+
if ( gchar
|
1170
|
+
&& (box1->y1-box1->m3)*8>=dy) ad=99*ad/100;
|
1171
|
+
Setac(box1,(wchar_t)'8',ad);
|
1172
|
+
break;
|
1173
|
+
}
|
1174
|
+
// --- test 9 \it g ---------------------------------------------------
|
1175
|
+
/*
|
1176
|
+
*
|
1177
|
+
* lcd micr round
|
1178
|
+
* ooo ooo ooo
|
1179
|
+
* o o o o o o
|
1180
|
+
* ooo ooo ooo
|
1181
|
+
* o o o
|
1182
|
+
* ooo o o
|
1183
|
+
*/
|
1184
|
+
for(ad=d=100;dx>2 && dy>4;){ // dx>1 dy>2*dx
|
1185
|
+
DBG( char c_ask='9'; )
|
1186
|
+
if (sdata->holes.num > 1) Break;
|
1187
|
+
if( num_cross(x0+ dx/2,x0+ dx/2,y0,y1-dy/4,box1->p,cs) != 2 // pre select
|
1188
|
+
&& num_cross(x0+ dx/2,x0+ dx/2,y0, y1,box1->p,cs) != 3 // pre select
|
1189
|
+
&& num_cross(x0+3*dx/8,x0+3*dx/8,y0,y1,box1->p,cs) != 3
|
1190
|
+
&& num_cross(x0+ dx/4,x1 -dx/4,y0,y1,box1->p,cs) != 3 ) Break;
|
1191
|
+
if( num_cross(x0+ dx/2,x0 +dx/2,y0,y0+dy/4,box1->p,cs) < 1 ) Break;
|
1192
|
+
if( num_cross(x0+ dx/2,x1, y0+dy/2 ,y0+dy/2,box1->p,cs) < 1 ) Break;
|
1193
|
+
if( num_cross(x0,x1, y0+ dy/4 ,y0+ dy/4,box1->p,cs) != 2
|
1194
|
+
&& num_cross(x0,x1, y0+3*dy/8 ,y0+3*dy/8,box1->p,cs) != 2 ) Break;
|
1195
|
+
if( num_cross(x1-dx/8,x1,y0+dy/4,y0+dy/4,box1->p,cs) == 0) ad=ad*97/100; // ~4
|
1196
|
+
for( x=0,i=y=y0+dy/2;y<=y1-dy/4;y++){ // find notch (suche kerbe)
|
1197
|
+
j=loop(box1->p,x0,y,dx,cs,0,RI);
|
1198
|
+
if( j>x ) { x=j; i=y; }
|
1199
|
+
} if (x<1 || x<dx/8) Break; y=i;
|
1200
|
+
// fprintf(stderr," debug 9: %d %d\n",x,i-y0);
|
1201
|
+
if( x<dx/2 ) { /* big bow? */
|
1202
|
+
j=loop(box1->p,x0+x-1,y,dy/8+1,cs,0,DO)/2; y=i=y+j;
|
1203
|
+
j=loop(box1->p,x0+x-1,y,dx/2 ,cs,0,RI); x+=j;
|
1204
|
+
if (x<dx/2) Break;
|
1205
|
+
}
|
1206
|
+
// check for the right lower bow
|
1207
|
+
MSG( fprintf(stderr,"bow-y0= %d",i-y0); )
|
1208
|
+
if (dx>5)
|
1209
|
+
if( num_cross(x0+dx/2,x1,i,y1 ,box1->p,cs) != 1 /* fails on 5x8 */
|
1210
|
+
&& num_cross(x0+dx/2,x1,i,y1-dy/8,box1->p,cs) != 1 ) Break;
|
1211
|
+
if( num_cross(x0+dx/2,x0+dx/2,i,y1,box1->p,cs) > 1 ) Break;
|
1212
|
+
if( num_cross(x0+dx/2,x1 ,i, i,box1->p,cs) != 1 ) Break;
|
1213
|
+
|
1214
|
+
if (sdata->holes.num < 1) { /* happens for 5x7 font */
|
1215
|
+
if (dx<8) ad=98*ad/100; else Break; }
|
1216
|
+
else {
|
1217
|
+
if (sdata->holes.hole[0].y1 >= i+1) Break;
|
1218
|
+
if (sdata->holes.hole[0].y0 > i-1) Break;
|
1219
|
+
if (sdata->holes.num > 1)
|
1220
|
+
if (sdata->holes.hole[1].y0 > i-1) Break;
|
1221
|
+
// if( num_hole(x0,x1,y0,i+1,box1->p,cs,NULL)!=1 ) Break;
|
1222
|
+
// if( num_hole(x0,x1,i-1,y1,box1->p,cs,NULL)!=0 ) Break;
|
1223
|
+
}
|
1224
|
+
if( loop(box1->p,x0,y1 ,dy,cs,0,RI)>dx/3 &&
|
1225
|
+
loop(box1->p,x0,y1-1,dy,cs,0,RI)>dx/3
|
1226
|
+
&& (box1->m3==0 || (box1->m3!=0 && (!hchar || gchar)))) ad=98*ad/100; // no q OR ocr-a-9
|
1227
|
+
for( x=0,i=y=y0+dy/3;y<=y1-dy/3;y++){ // suche kerbe
|
1228
|
+
j=loop(box1->p,x1,y,dx,cs,0,LE);
|
1229
|
+
if( j>x ) { x=j; i=y; }
|
1230
|
+
} if( x>dx/2 ) Break; // no g
|
1231
|
+
i1=loop(bp,dx-1,dy/8 ,dx,cs,0,LE); if(i1>dx/2) Break;
|
1232
|
+
i3=loop(bp,dx-1,dy-1-dy/8,dx,cs,0,LE);
|
1233
|
+
i2=loop(bp,dx-1,dy/2 ,dx,cs,0,LE); if(i1+i3-2*i2<-1-dx/16) Break; // konvex
|
1234
|
+
i1=loop(bp,dx-1,dy/4 ,dx,cs,0,LE); if(i1>dx/2) Break;
|
1235
|
+
i3=loop(bp,dx-1,dy-1-dy/8,dx,cs,0,LE);
|
1236
|
+
for(y=dy/4;y<dy-1-dy/4;y++){ // may fail on type=round
|
1237
|
+
i2=loop(bp,dx-1,y,dx,cs,0,LE);
|
1238
|
+
// konvex from right ~g ~3 Jul09
|
1239
|
+
if(i2>i1+(i3-i1)*(2*y-dy/2)/dy+dx/16) break;
|
1240
|
+
// MSG(fprintf(stderr," y i2 %d %d %d",y,i2,i1+(i3-i1)*(2*y-dy/2)/dy);)
|
1241
|
+
} if(y<dy-1-dy/4) Break;
|
1242
|
+
x=loop(bp,dx -1,6*dy/8,dx,cs,0,LE); if(x>0){
|
1243
|
+
x--; // robust
|
1244
|
+
y=loop(bp,dx-x-1, dy-1,dy,cs,0,UP);
|
1245
|
+
if(y<dy/8) Break; // ~q (serif!)
|
1246
|
+
}
|
1247
|
+
// check for agglutinated serif y
|
1248
|
+
if (dy>=16 && dx>9
|
1249
|
+
&& loop(bp, 0,dy/ 4,dx,cs,0,RI)
|
1250
|
+
-loop(bp, 0,dy/16,dx,cs,0,RI)>dx/6
|
1251
|
+
&& loop(bp,dx-1,dy/ 4,dx,cs,0,LE)
|
1252
|
+
-loop(bp,dx-1,dy/16,dx,cs,0,LE)>dx/6) Break; // ~ serif yY
|
1253
|
+
|
1254
|
+
if (box1->m3) {
|
1255
|
+
if ( gchar) ad=99*ad/100; /* unsure (italic g)? */
|
1256
|
+
if (box1->m2 && (!gchar) && y1 > box1->m3){
|
1257
|
+
ad=99*ad/100;
|
1258
|
+
if (box1->m4-box1->m3<3) ad=99*ad/100;
|
1259
|
+
// if (!hchar) ad = 99*ad/100;
|
1260
|
+
}
|
1261
|
+
if (!hchar) ad=99*ad/100; /* unsure */
|
1262
|
+
} else { if (ad==100) ad=99; } /* not 100% sure */
|
1263
|
+
Setac(box1,(wchar_t)'9',ad);
|
1264
|
+
break;
|
1265
|
+
}
|
1266
|
+
// 0 is same as O !?
|
1267
|
+
// --- test 0 (with one big hole in it ) -----------------------------
|
1268
|
+
for(d=ad=100;dx>2 && dy>3;){ // min 3x4
|
1269
|
+
DBG( char c_ask='0'; )
|
1270
|
+
if (sdata->holes.num > 1) Break; /* be tolerant */
|
1271
|
+
if( get_bw(x0 , x0+dx/3,y0+dy/2 , y0+dy/2,box1->p,cs,1) != 1 ) Break;
|
1272
|
+
if( get_bw(x1-dx/3 , x1 ,y0+dy/2 , y0+dy/2,box1->p,cs,1) != 1 ) Break;
|
1273
|
+
/* could be an O, unless we find a dot in the center */
|
1274
|
+
if( get_bw(x0 , x1 ,y0+dy/2 , y0+dy/2,box1->p,cs,1) != 3 ) ad=99;
|
1275
|
+
if( get_bw(x0+dx/2 , x0+dx/2,y1-dy/3 , y1,box1->p,cs,1) != 1 ) Break;
|
1276
|
+
if( get_bw(x0+dx/2 , x0+dx/2,y0 , y0+dy/3,box1->p,cs,1) != 1 ) Break;
|
1277
|
+
/* accept 0 with dot in center, accept \/0 too ... */
|
1278
|
+
if( get_bw(x0+dx/2 , x0+dx/2,y0+dy/3 , y1-dy/3,box1->p,cs,1) != 0 ) Break;
|
1279
|
+
|
1280
|
+
if( num_cross(x0+dx/2,x0+dx/2,y0 , y1 ,box1->p,cs) != 2 ) Break;
|
1281
|
+
if( num_cross(x0+dx/3,x1-dx/3,y0 , y0 ,box1->p,cs) != 1 ) // AND
|
1282
|
+
if( num_cross(x0+dx/3,x1-dx/3,y0+1 , y0+1 ,box1->p,cs) != 1 ) Break;
|
1283
|
+
if( num_cross(x0+dx/3,x1-dx/3,y1 , y1 ,box1->p,cs) != 1 ) // against "rauschen"
|
1284
|
+
if( num_cross(x0+dx/3,x1-dx/3,y1-1 , y1-1 ,box1->p,cs) != 1 ) Break;
|
1285
|
+
if( num_cross(x0 ,x0 ,y0+dy/3 , y1-dy/3,box1->p,cs) != 1 )
|
1286
|
+
if( num_cross(x0+1 ,x0+1 ,y0+dy/3 , y1-dy/3,box1->p,cs) != 1 ) Break;
|
1287
|
+
if( num_cross(x1 ,x1 ,y0+dy/3 , y1-dy/3,box1->p,cs) != 1 )
|
1288
|
+
if( num_cross(x1-1 ,x1-1 ,y0+dy/3 , y1-dy/3,box1->p,cs) != 1 ) Break;
|
1289
|
+
// if( num_hole(x0,x1,y0,y1,box1->p,cs,NULL) != 1 ) Break;
|
1290
|
+
if (sdata->holes.num != 1) Break;
|
1291
|
+
|
1292
|
+
i= loop(bp,0 ,0 ,x1-x0,cs,0,RI)-
|
1293
|
+
loop(bp,0 ,2 ,x1-x0,cs,0,RI);
|
1294
|
+
if (i<0) Break;
|
1295
|
+
if (i==0) {
|
1296
|
+
if (loop(bp,dx-1,0 ,x1-x0,cs,0,LE)>
|
1297
|
+
loop(bp,dx-1,2 ,x1-x0,cs,0,LE) ) ad=98*ad/100;
|
1298
|
+
ad=99*ad/100; /* LCD-type? */
|
1299
|
+
}
|
1300
|
+
|
1301
|
+
x=loop(bp,dx-1,dy-1-dy/3,x1-x0,cs,0,LE); // should be minimum
|
1302
|
+
for (y=dy-1-dy/3;y<dy;y++){
|
1303
|
+
i=loop(bp,dx-1,y,x1-x0,cs,0,LE);
|
1304
|
+
if (i<x-dx/16-1) break; if (i>x) x=i;
|
1305
|
+
}
|
1306
|
+
if( y<dy ) Break;
|
1307
|
+
|
1308
|
+
// ~D (but ocr-a-font)
|
1309
|
+
i= loop(bp, 0, dy/16,dx,cs,0,RI)
|
1310
|
+
+ loop(bp, 0,dy-1-dy/16,dx,cs,0,RI)
|
1311
|
+
- 2*loop(bp, 0, dy/2 ,dx,cs,0,RI);
|
1312
|
+
j= loop(bp,dx-1, dy/16,dx,cs,0,LE)
|
1313
|
+
+ loop(bp,dx-1,dy-1-dy/16,dx,cs,0,LE)
|
1314
|
+
<= 2*loop(bp,dx-1, dy/2 ,dx,cs,0,LE);
|
1315
|
+
if (i<-dx/8 || i+dx/8<j) Break; // not konvex
|
1316
|
+
|
1317
|
+
if( loop(bp,dx-1, dy/16,dx,cs,0,LE)>dx/8 )
|
1318
|
+
if( loop(bp,0 , dy/16,dx,cs,0,RI)<dx/16 ) Break;
|
1319
|
+
if( loop(bp,dx-1,dy-1-dy/16,dx,cs,0,LE)>dx/8 )
|
1320
|
+
if( loop(bp,0 ,dy-1-dy/16,dx,cs,0,RI)<dx/16 ) Break;
|
1321
|
+
if( get_bw(x1-dx/32,x1,y0,y0+dy/32,box1->p,cs,1) == 0
|
1322
|
+
&& get_bw(x1-dx/32,x1,y1-dy/32,y1,box1->p,cs,1) == 0
|
1323
|
+
&& ( get_bw(x0,x0+dx/32,y0,y0+dy/32,box1->p,cs,1) == 1
|
1324
|
+
|| get_bw(x0,x0+dx/32,y1-dy/32,y1,box1->p,cs,1) == 1 ) ) {
|
1325
|
+
if (dx<32) ad=ad*99/100; else Break; // ~D
|
1326
|
+
}
|
1327
|
+
|
1328
|
+
// search lowest inner white point
|
1329
|
+
for(y=dy,j=x=0;x<dx;x++) {
|
1330
|
+
i =loop(bp,x,dy-1 ,y1-y0,cs,0,UP);
|
1331
|
+
i+=loop(bp,x,dy-1-i,y1-y0,cs,1,UP);
|
1332
|
+
if (i<=y) { y=i; j=x; }
|
1333
|
+
} i=y;
|
1334
|
+
// italic a
|
1335
|
+
for(y=dy-1-i;y<dy-1;y++)
|
1336
|
+
if( num_cross(j,dx-1,y,y,bp,cs) > 1 ) ad=99*ad/100; // ~a \it a
|
1337
|
+
|
1338
|
+
if (loop(bp, 0, 0,x1-x0,cs,0,RI)>=dx/8) { // round, notLCD
|
1339
|
+
if (loop(bp,dx-1,dy-1,x1-x0,cs,0,LE)<dx/8) ad=98*ad/100; // \it a
|
1340
|
+
if (loop(bp,dx-1, 0,x1-x0,cs,0,LE)<dx/8) ad=98*ad/100; // \it a
|
1341
|
+
}
|
1342
|
+
|
1343
|
+
if (abs(loop(bp,dx/2, 0,dy,cs,0,DO)
|
1344
|
+
-loop(bp,dx/2,dy-1,dy,cs,0,UP))>dy/8
|
1345
|
+
|| num_cross(0,dx-1, 0, 0,bp,cs) > 1
|
1346
|
+
|| num_cross(0,dx-1,dy-1,dy-1,bp,cs) > 1
|
1347
|
+
) ad=98*ad/100; // ~bq
|
1348
|
+
|
1349
|
+
if (box1->m3) {
|
1350
|
+
if (!hchar) ad=98*ad/100; else // ~o
|
1351
|
+
if ( gchar) ad=99*ad/100; // wrong line detection?
|
1352
|
+
} else { if (ad==100) ad=99; } /* not 100% sure */
|
1353
|
+
if (ad>98) ad=98; /* we can never be sure having a O, (2010-10 98%)
|
1354
|
+
let context correction decide, see below! */
|
1355
|
+
Setac(box1,(wchar_t)'0',ad);
|
1356
|
+
break;
|
1357
|
+
}
|
1358
|
+
// --- test 0 with a straight line in it -------------------
|
1359
|
+
for(ad=100;dx>4 && dy>5;){ /* v0.3.1+ */
|
1360
|
+
DBG( char c_ask='0'; )
|
1361
|
+
if (sdata->holes.num > 3) Break; /* be tolerant */
|
1362
|
+
if (sdata->holes.num < 1) Break;
|
1363
|
+
if (sdata->holes.num != 2) ad=95*ad/100;
|
1364
|
+
if( get_bw(x0 , x0+dx/2,y0+dy/2 , y0+dy/2,box1->p,cs,1) != 1 ) Break;
|
1365
|
+
if( get_bw(x1-dx/2 , x1 ,y0+dy/2 , y0+dy/2,box1->p,cs,1) != 1 ) Break;
|
1366
|
+
if( get_bw(x0+dx/2 , x0+dx/2,y1-dy/2 , y1,box1->p,cs,1) != 1 ) Break;
|
1367
|
+
if( get_bw(x0+dx/2 , x0+dx/2,y0 , y0+dy/2,box1->p,cs,1) != 1 ) Break;
|
1368
|
+
if( get_bw(x0+dx/2 , x0+dx/2,y0+dy/3 , y1-dy/3,box1->p,cs,1) != 1 ) Break;
|
1369
|
+
// out_x(box1); printf(" x0 y0 %d %d\n",x0,y0);
|
1370
|
+
if( num_cross(x0+dx/2,x0+dx/2,y0 , y1 ,box1->p,cs) != 3 ) Break;
|
1371
|
+
if( num_cross(x0+dx/3,x1-dx/3,y0 , y0 ,box1->p,cs) != 1 ) // AND
|
1372
|
+
if( num_cross(x0+dx/3,x1-dx/3,y0+1 , y0+1 ,box1->p,cs) != 1 ) Break;
|
1373
|
+
if( num_cross(x0+dx/3,x1-dx/3,y1 , y1 ,box1->p,cs) != 1 ) // against "rauschen"
|
1374
|
+
if( num_cross(x0+dx/3,x1-dx/3,y1-1 , y1-1 ,box1->p,cs) != 1 ) Break;
|
1375
|
+
if( num_cross(x0 ,x0 ,y0+dy/3 , y1-dy/3,box1->p,cs) != 1 )
|
1376
|
+
if( num_cross(x0+1 ,x0+1 ,y0+dy/3 , y1-dy/3,box1->p,cs) != 1 ) Break;
|
1377
|
+
if( num_cross(x1 ,x1 ,y0+dy/3 , y1-dy/3,box1->p,cs) != 1 )
|
1378
|
+
if( num_cross(x1-1 ,x1-1 ,y0+dy/3 , y1-dy/3,box1->p,cs) != 1 ) Break;
|
1379
|
+
// if( num_hole(x0,x1,y0,y1,box1->p,cs,NULL) != 2 ) Break;
|
1380
|
+
if (sdata->holes.num != 2) ad=85*ad/100;
|
1381
|
+
|
1382
|
+
if( loop(bp,0 , 0,x1-x0,cs,0,RI)<=
|
1383
|
+
loop(bp,0 , 2+dy/32,x1-x0,cs,0,RI) ) Break;
|
1384
|
+
x= loop(bp,0 ,dy/2 ,x1-x0,cs,0,RI);
|
1385
|
+
i= loop(bp,0 ,dy/2-1,x1-x0,cs,0,RI); if (i>x) x=i;
|
1386
|
+
i= loop(bp,0 ,dy/2-2,x1-x0,cs,0,RI); if (i>x && dy>8) x=i;
|
1387
|
+
if( loop(bp,0 , dy/4,x1-x0,cs,0,RI)<x ) Break; // ~8
|
1388
|
+
x= loop(bp,dx-1,dy/2 ,x1-x0,cs,0,LE);
|
1389
|
+
i= loop(bp,dx-1,dy/2-1,x1-x0,cs,0,LE); if(i>x) x=i;
|
1390
|
+
i= loop(bp,dx-1,dy/2-1,x1-x0,cs,0,LE); if(i>x && dy>8) x=i;
|
1391
|
+
if( loop(bp,dx-1,3*dy/4,x1-x0,cs,0,LE)<x) Break; // ~8
|
1392
|
+
|
1393
|
+
x=loop(bp,dx-1,dy-1-dy/3,x1-x0,cs,0,LE); // should be minimum
|
1394
|
+
for( y=dy-1-dy/3;y<dy;y++ ){
|
1395
|
+
i=loop(bp,dx-1,y,x1-x0,cs,0,LE);
|
1396
|
+
if (i<x-dx/16) break;
|
1397
|
+
if (i>x) x=i;
|
1398
|
+
}
|
1399
|
+
if( y<dy ) Break;
|
1400
|
+
|
1401
|
+
/* test for straight line */
|
1402
|
+
y =loop(bp,dx/2,dy-1 ,y1-y0,cs,0,UP); if(y>dy/4) Break;
|
1403
|
+
y+=loop(bp,dx/2,dy-1-y,y1-y0,cs,1,UP); if(y>dy/3) Break; if (y>dy/4) ad=ad*99/100;
|
1404
|
+
y+=loop(bp,dx/2,dy-1-y,y1-y0,cs,0,UP); if(3*y>2*dy) Break;
|
1405
|
+
x =loop(bp,dx/2,dy-y,dx/2,cs,0,RI); if(x==0) Break;
|
1406
|
+
// MM; fprintf(stderr," y=%d x=%d\n",y-1,x);
|
1407
|
+
if( loop(bp,dx/2+x-1-dx/16,dy-y,y1-y0,cs,0,UP)==0 ) Break;
|
1408
|
+
// $
|
1409
|
+
for(i=0,y=dy/4;y<dy-dy/4-1;y++)
|
1410
|
+
if( loop(bp, 0,y,dx-1,cs,0,RI) > dx/4
|
1411
|
+
|| loop(bp,dx-1,y,dx-1,cs,0,LE) > dx/4 ) break;
|
1412
|
+
if( y<dy-dy/4-1 ) Break;
|
1413
|
+
|
1414
|
+
// ~D
|
1415
|
+
if( loop(bp,0, dy/16,dx,cs,0,RI)
|
1416
|
+
+ loop(bp,0,dy-1-dy/16,dx,cs,0,RI)
|
1417
|
+
<= 2*loop(bp,0, dy/2 ,dx,cs,0,RI)+dx/8 ) Break; // not konvex
|
1418
|
+
|
1419
|
+
if( loop(bp,dx-1, dy/16,dx,cs,0,LE)>dx/8 )
|
1420
|
+
if( loop(bp,0 , dy/16,dx,cs,0,RI)<dx/16 ) Break;
|
1421
|
+
if( loop(bp,dx-1,dy-1-dy/16,dx,cs,0,LE)>dx/8 )
|
1422
|
+
if( loop(bp,0 ,dy-1-dy/16,dx,cs,0,RI)<dx/16 ) Break;
|
1423
|
+
if( get_bw(x1-dx/32,x1,y0,y0+dy/32,box1->p,cs,1) == 0
|
1424
|
+
&& get_bw(x1-dx/32,x1,y1-dy/32,y1,box1->p,cs,1) == 0
|
1425
|
+
&& ( get_bw(x0,x0+dx/32,y0,y0+dy/32,box1->p,cs,1) == 1
|
1426
|
+
|| get_bw(x0,x0+dx/32,y1-dy/32,y1,box1->p,cs,1) == 1 ) ) Break; // ~D
|
1427
|
+
|
1428
|
+
/* 5x9 font "9" is like "0" */
|
1429
|
+
if (dx<16)
|
1430
|
+
if ( num_cross(x0,x0,y0,y1,box1->p,cs) != 1 ) ad=98*ad/100;
|
1431
|
+
|
1432
|
+
// italic a
|
1433
|
+
for(i=0,y=6*dy/8;y<dy-dy/16;y++)
|
1434
|
+
if( num_cross(0,dx-1,y,y,bp,cs) > 2 ) i++; else i--;
|
1435
|
+
if(i>0) ad=ad*98/100; // ~'a' \it a
|
1436
|
+
if( !hchar ) ad=90*ad/100;
|
1437
|
+
Setac(box1,(wchar_t)'0',ad);
|
1438
|
+
break;
|
1439
|
+
}
|
1440
|
+
// --- test 0 with a dot in it -------------------
|
1441
|
+
for(ad=100;dx>4 && dy>5;){ /* v0.46+ */
|
1442
|
+
DBG( char c_ask='0'; )
|
1443
|
+
if (sdata->holes.num != 1) Break; /* do not be tolerant */
|
1444
|
+
// 8x10 font 2-pixel line width has 3 frames
|
1445
|
+
if (sdata->box1->num_frames != 3) ad=85*ad/100; // 2010-09-24
|
1446
|
+
// MSG(fprintf(stderr,"ad=%d",ad);)
|
1447
|
+
if( get_bw(x0 , x0+dx/2,y0+dy/2 , y0+dy/2,box1->p,cs,1) != 1 ) Break;
|
1448
|
+
if( get_bw(x1-dx/2 , x1 ,y0+dy/2 , y0+dy/2,box1->p,cs,1) != 1 ) Break;
|
1449
|
+
if( get_bw(x0+dx/2 , x0+dx/2,y1-dy/2 , y1,box1->p,cs,1) != 1 ) Break;
|
1450
|
+
if( get_bw(x0+dx/2 , x0+dx/2,y0 , y0+dy/2,box1->p,cs,1) != 1 ) Break;
|
1451
|
+
if( get_bw(x0+dx/2 , x0+dx/2,y0+dy/3 , y1-dy/3,box1->p,cs,1) != 1 ) Break;
|
1452
|
+
// out_x(box1); printf(" x0 y0 %d %d\n",x0,y0);
|
1453
|
+
if( num_cross(x0+dx/2,x0+dx/2,y0 , y1 ,box1->p,cs) != 3 ) Break;
|
1454
|
+
if( num_cross(x0+dx/3,x1-dx/3,y0 , y0 ,box1->p,cs) != 1 ) // AND
|
1455
|
+
if( num_cross(x0+dx/3,x1-dx/3,y0+1 , y0+1 ,box1->p,cs) != 1 ) Break;
|
1456
|
+
if( num_cross(x0+dx/3,x1-dx/3,y1 , y1 ,box1->p,cs) != 1 ) // against "rauschen"
|
1457
|
+
if( num_cross(x0+dx/3,x1-dx/3,y1-1 , y1-1 ,box1->p,cs) != 1 ) Break;
|
1458
|
+
if( num_cross(x0 ,x0 ,y0+dy/3 , y1-dy/3,box1->p,cs) != 1 )
|
1459
|
+
if( num_cross(x0+1 ,x0+1 ,y0+dy/3 , y1-dy/3,box1->p,cs) != 1 ) Break;
|
1460
|
+
if( num_cross(x1 ,x1 ,y0+dy/3 , y1-dy/3,box1->p,cs) != 1 )
|
1461
|
+
if( num_cross(x1-1 ,x1-1 ,y0+dy/3 , y1-dy/3,box1->p,cs) != 1 ) Break;
|
1462
|
+
// if( num_hole(x0,x1,y0,y1,box1->p,cs,NULL) != 2 ) Break;
|
1463
|
+
// MSG(fprintf(stderr,"ad=%d",ad);)
|
1464
|
+
|
1465
|
+
if( loop(bp,0 , 0,x1-x0,cs,0,RI)<=
|
1466
|
+
loop(bp,0 , 2+dy/32,x1-x0,cs,0,RI) ) Break;
|
1467
|
+
x= loop(bp,0 ,dy/2 ,x1-x0,cs,0,RI);
|
1468
|
+
i= loop(bp,0 ,dy/2-1,x1-x0,cs,0,RI); if (i>x) x=i;
|
1469
|
+
i= loop(bp,0 ,dy/2-2,x1-x0,cs,0,RI); if (i>x && dy>8) x=i;
|
1470
|
+
if( loop(bp,0 , dy/4,x1-x0,cs,0,RI)<x ) Break; // ~8
|
1471
|
+
x= loop(bp,dx-1,dy/2 ,x1-x0,cs,0,LE);
|
1472
|
+
i= loop(bp,dx-1,dy/2-1,x1-x0,cs,0,LE); if(i>x) x=i;
|
1473
|
+
i= loop(bp,dx-1,dy/2-1,x1-x0,cs,0,LE); if(i>x && dy>8) x=i;
|
1474
|
+
if( loop(bp,dx-1,3*dy/4,x1-x0,cs,0,LE)<x) Break; // ~8
|
1475
|
+
|
1476
|
+
x=loop(bp,dx-1,dy-1-dy/3,x1-x0,cs,0,LE); // should be minimum
|
1477
|
+
for( y=dy-1-dy/3;y<dy;y++ ){
|
1478
|
+
i=loop(bp,dx-1,y,x1-x0,cs,0,LE);
|
1479
|
+
if (i<x-dx/16) break;
|
1480
|
+
if (i>x) x=i;
|
1481
|
+
}
|
1482
|
+
if( y<dy ) Break;
|
1483
|
+
|
1484
|
+
/* test for straight line */
|
1485
|
+
y =loop(bp,dx/2,dy-1 ,y1-y0,cs,0,UP); if(y>dy/4) Break;
|
1486
|
+
y+=loop(bp,dx/2,dy-1-y,y1-y0,cs,1,UP); if(y>dy/3) Break;
|
1487
|
+
if (y>dy/4) { ad=ad*99/100;MSG(fprintf(stderr,"ad=%d",ad);) }
|
1488
|
+
y+=loop(bp,dx/2,dy-1-y,y1-y0,cs,0,UP); if(3*y>2*dy) Break;
|
1489
|
+
x =loop(bp,dx/2,dy-y,dx/2,cs,0,RI); if(x==0) Break;
|
1490
|
+
// MM; fprintf(stderr," y=%d x=%d\n",y-1,x);
|
1491
|
+
if( loop(bp,dx/2+x-1-dx/16,dy-y,y1-y0,cs,0,UP)==0 ) Break;
|
1492
|
+
// $
|
1493
|
+
for(i=0,y=dy/4;y<dy-dy/4-1;y++)
|
1494
|
+
if( loop(bp, 0,y,dx-1,cs,0,RI) > dx/4
|
1495
|
+
|| loop(bp,dx-1,y,dx-1,cs,0,LE) > dx/4 ) break;
|
1496
|
+
if( y<dy-dy/4-1 ) Break;
|
1497
|
+
|
1498
|
+
// ~D
|
1499
|
+
if( loop(bp,0, dy/16,dx,cs,0,RI)
|
1500
|
+
+ loop(bp,0,dy-1-dy/16,dx,cs,0,RI)
|
1501
|
+
<= 2*loop(bp,0, dy/2 ,dx,cs,0,RI)+dx/8 ) Break; // not konvex
|
1502
|
+
|
1503
|
+
if( loop(bp,dx-1, dy/16,dx,cs,0,LE)>dx/8 )
|
1504
|
+
if( loop(bp,0 , dy/16,dx,cs,0,RI)<dx/16 ) Break;
|
1505
|
+
if( loop(bp,dx-1,dy-1-dy/16,dx,cs,0,LE)>dx/8 )
|
1506
|
+
if( loop(bp,0 ,dy-1-dy/16,dx,cs,0,RI)<dx/16 ) Break;
|
1507
|
+
if( get_bw(x1-dx/32,x1,y0,y0+dy/32,box1->p,cs,1) == 0
|
1508
|
+
&& get_bw(x1-dx/32,x1,y1-dy/32,y1,box1->p,cs,1) == 0
|
1509
|
+
&& ( get_bw(x0,x0+dx/32,y0,y0+dy/32,box1->p,cs,1) == 1
|
1510
|
+
|| get_bw(x0,x0+dx/32,y1-dy/32,y1,box1->p,cs,1) == 1 ) ) Break; // ~D
|
1511
|
+
|
1512
|
+
/* 5x9 font "9" is like "0" */
|
1513
|
+
if (dx<16)
|
1514
|
+
if (num_cross(x0,x0,y0,y1,box1->p,cs) != 1) {
|
1515
|
+
ad=98*ad/100;MSG(fprintf(stderr,"ad=%d",ad);) }
|
1516
|
+
|
1517
|
+
// italic a
|
1518
|
+
for(i=0,y=6*dy/8;y<dy-dy/16;y++)
|
1519
|
+
if (num_cross(0,dx-1,y,y,bp,cs) > 2) i++; else i--;
|
1520
|
+
if (i>0) { ad=ad*98/100; MSG(fprintf(stderr,"i=%d ad=%d",i,ad);) }
|
1521
|
+
|
1522
|
+
if (!hchar) ad=90*ad/100;
|
1523
|
+
Setac(box1,(wchar_t)'0',ad);
|
1524
|
+
break;
|
1525
|
+
}
|
1526
|
+
return box1->c;
|
1527
|
+
}
|