2
Copyright (c) 1993-2008, Cognitive Technologies
5
����������� ��������� ��������������� � ������������� ��� � ���� ��������� ����,
6
��� � � �������� �����, � ����������� ��� ���, ��� ���������� ��������� �������:
8
* ��� ��������� ��������������� ��������� ���� ������ ���������� ���������
9
���� ����������� �� ��������� �����, ���� ������ ������� � �����������
11
* ��� ��������� ��������������� ��������� ���� � ������������ �/��� �
12
������ ����������, ������������ ��� ���������������, ������ �����������
13
��������� ���� ���������� �� ��������� �����, ���� ������ ������� �
14
����������� ����� �� ��������.
15
* �� �������� Cognitive Technologies, �� ����� �� ����������� �� �����
16
���� ������������ � �������� �������� ��������� �/��� �����������
17
���������, ���������� �� ���� ��, ��� ���������������� �����������
20
��� ��������� ������������� ����������� ��������� ���� �/��� ������� ������ "���
21
��� ����" ��� ������-���� ���� ��������, ���������� ���� ��� ���������������,
22
������� �������� ������������ �������� � ����������� ��� ���������� ����, �� ��
23
������������� ���. �� �������� ��������� ���� � �� ���� ������ ����, �������
24
����� �������� �/��� �������� �������������� ���������, �� � ���� ������ ��
25
��Ѩ� ���������������, ������� ����� �����, ���������, ����������� ���
26
������������� ������, ��������� � �������������� ��� ���������� ����������
27
������������� ������������� ��������� (������� ������ ������, ��� ������,
28
������� ���������, ��� ������ �/��� ������ �������, ���������� ��-�� ��������
29
������� ��� �/��� ������ ��������� �������� ��������� � ������� �����������,
30
�� �� ������������� ����� ��������), �� �� ������������� ���, ���� ���� �����
31
�������� ��� ������ ���� ���� �������� � ����������� ����� ������� � ������.
33
Redistribution and use in source and binary forms, with or without modification,
34
are permitted provided that the following conditions are met:
36
* Redistributions of source code must retain the above copyright notice,
37
this list of conditions and the following disclaimer.
38
* Redistributions in binary form must reproduce the above copyright notice,
39
this list of conditions and the following disclaimer in the documentation
40
and/or other materials provided with the distribution.
41
* Neither the name of the Cognitive Technologies nor the names of its
42
contributors may be used to endorse or promote products derived from this
43
software without specific prior written permission.
45
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
46
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
47
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
48
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
49
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
51
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
52
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
53
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
54
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
57
#define _NOT_ALL_ // �� ������ ������ �����
58
// #define _NEED_SCALE_ // �������������� ��� ����������� ������
59
#define STANDARD_HEIGHT 38 // ����������� ������
2
Copyright (c) 1993-2008, Cognitive Technologies
5
Разрешается повторное распространение и использование как в виде исходного кода,
6
так и в двоичной форме, с изменениями или без, при соблюдении следующих условий:
8
* При повторном распространении исходного кода должны оставаться указанное
9
выше уведомление об авторском праве, этот список условий и последующий
11
* При повторном распространении двоичного кода в документации и/или в
12
других материалах, поставляемых при распространении, должны сохраняться
13
указанная выше информация об авторском праве, этот список условий и
14
последующий отказ от гарантий.
15
* Ни название Cognitive Technologies, ни имена ее сотрудников не могут
16
быть использованы в качестве средства поддержки и/или продвижения
17
продуктов, основанных на этом ПО, без предварительного письменного
20
ЭТА ПРОГРАММА ПРЕДОСТАВЛЕНА ВЛАДЕЛЬЦАМИ АВТОРСКИХ ПРАВ И/ИЛИ ДРУГИМИ ЛИЦАМИ "КАК
21
ОНА ЕСТЬ" БЕЗ КАКОГО-ЛИБО ВИДА ГАРАНТИЙ, ВЫРАЖЕННЫХ ЯВНО ИЛИ ПОДРАЗУМЕВАЕМЫХ,
22
ВКЛЮЧАЯ ГАРАНТИИ КОММЕРЧЕСКОЙ ЦЕННОСТИ И ПРИГОДНОСТИ ДЛЯ КОНКРЕТНОЙ ЦЕЛИ, НО НЕ
23
ОГРАНИЧИВАЯСЬ ИМИ. НИ ВЛАДЕЛЕЦ АВТОРСКИХ ПРАВ И НИ ОДНО ДРУГОЕ ЛИЦО, КОТОРОЕ
24
МОЖЕТ ИЗМЕНЯТЬ И/ИЛИ ПОВТОРНО РАСПРОСТРАНЯТЬ ПРОГРАММУ, НИ В КОЕМ СЛУЧАЕ НЕ
25
НЕСЁТ ОТВЕТСТВЕННОСТИ, ВКЛЮЧАЯ ЛЮБЫЕ ОБЩИЕ, СЛУЧАЙНЫЕ, СПЕЦИАЛЬНЫЕ ИЛИ
26
ПОСЛЕДОВАВШИЕ УБЫТКИ, СВЯЗАННЫЕ С ИСПОЛЬЗОВАНИЕМ ИЛИ ПОНЕСЕННЫЕ ВСЛЕДСТВИЕ
27
НЕВОЗМОЖНОСТИ ИСПОЛЬЗОВАНИЯ ПРОГРАММЫ (ВКЛЮЧАЯ ПОТЕРИ ДАННЫХ, ИЛИ ДАННЫЕ,
28
СТАВШИЕ НЕГОДНЫМИ, ИЛИ УБЫТКИ И/ИЛИ ПОТЕРИ ДОХОДОВ, ПОНЕСЕННЫЕ ИЗ-ЗА ДЕЙСТВИЙ
29
ТРЕТЬИХ ЛИЦ И/ИЛИ ОТКАЗА ПРОГРАММЫ РАБОТАТЬ СОВМЕСТНО С ДРУГИМИ ПРОГРАММАМИ,
30
НО НЕ ОГРАНИЧИВАЯСЬ ЭТИМИ СЛУЧАЯМИ), НО НЕ ОГРАНИЧИВАЯСЬ ИМИ, ДАЖЕ ЕСЛИ ТАКОЙ
31
ВЛАДЕЛЕЦ ИЛИ ДРУГОЕ ЛИЦО БЫЛИ ИЗВЕЩЕНЫ О ВОЗМОЖНОСТИ ТАКИХ УБЫТКОВ И ПОТЕРЬ.
33
Redistribution and use in source and binary forms, with or without modification,
34
are permitted provided that the following conditions are met:
36
* Redistributions of source code must retain the above copyright notice,
37
this list of conditions and the following disclaimer.
38
* Redistributions in binary form must reproduce the above copyright notice,
39
this list of conditions and the following disclaimer in the documentation
40
and/or other materials provided with the distribution.
41
* Neither the name of the Cognitive Technologies nor the names of its
42
contributors may be used to endorse or promote products derived from this
43
software without specific prior written permission.
45
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
46
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
47
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
48
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
49
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
51
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
52
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
53
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
54
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
57
#define _NOT_ALL_ // не делать полный поиск
58
// #define _NEED_SCALE_ // масштабировать под стандартную высоту
59
#define STANDARD_HEIGHT 38 // стандартная высота
61
60
//#define _TEST_ADD_FAT_
65
64
//#define CHECK_EQUAL
67
// ����������� ������ �� ����������
66
// размазывать мелких на полпиксела
68
67
//#define _USE_HALF_
72
71
#define POROG_HALF_WIDTH 4 // 21
73
72
#define POROG_HALF_HEIGHT 13 // 23
77
73
#include <stdlib.h>
78
74
#include <string.h>
81
/*#include <sys\stat.h>*/
90
85
#include "fonrec.h"
91
86
#include "ctbdefs.h"
92
87
#include "ligas.h" // 13.09.2000
94
extern Word8 language;
97
WORD cmp(PBYTE r,WORD fullwb,WORD w,WORD h,welet * wl);
98
SINT RazmazHalf(BYTE *bSource,BYTE *bDest,SINT xbit,SINT yrow);
88
extern uchar language;
90
uint16_t cmp(puchar r, uint16_t fullwb, uint16_t w, uint16_t h, welet * wl);
91
int16_t RazmazHalf(uchar *bSource, uchar *bDest, int16_t xbit, int16_t yrow);
99
92
///////////////////////
101
// �������� ������� �����
94
// штрафуем дальние точки
105
static int sign_tab[513]={
106
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 0
107
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 1
108
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 2
109
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 3
110
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 4
111
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 5
112
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 6
113
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 7
114
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 8
115
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 9
116
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // a
117
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // b
118
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // c
119
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // d
120
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // e
121
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // f
123
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0
124
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1
125
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2
126
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3
127
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 4
128
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 5
129
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 6
130
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 7
131
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 8
132
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 9
133
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // a
134
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // b
135
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // c
136
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // d
137
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // e
138
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 // f
98
static int sign_tab[513] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0
99
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 1
100
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 2
101
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 3
102
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 4
103
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 5
104
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 6
105
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 7
106
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 8
107
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 9
108
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // a
109
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // b
110
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // c
111
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // d
112
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // e
113
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // f
114
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
115
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
116
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2
117
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3
118
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4
119
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 5
120
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6
121
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7
122
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8
123
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9
124
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // a
125
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // b
126
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // c
127
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // d
128
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // e
129
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // f
141
132
#include "array1.h"
142
static int DistToWelet(PBYTE r,int fullByte,int w,int h,welet * wl,
143
int xo,int yo,int porog,
146
PCHAR curr, currn,currh;
152
curr = wl->raster + WR_MAX_WIDTH*((WR_MAX_HEIGHT-h)/2) +
154
curr += xo + WR_MAX_WIDTH * yo; // variation
155
currh = curr + WR_MAX_WIDTH * h;
157
sign=&sign_tab[256]-dist1;
158
for(dist=0; curr<currh;curr += WR_MAX_WIDTH,r+=fullByte)
162
for(currn=curr,rr=r,rn=r+rbyte;rr!=rn; rr++, currn+=8)
164
dist += bit_distance[*rr](currn);
175
dist += bit_distance[*r](curr);
178
dist += bit_distance[*r](curr)+bit_distance[*(r+1)](curr+8);
181
dist += bit_distance[*r](curr)+bit_distance[*(r+1)](curr+8)+
182
bit_distance[*(r+2)](curr+16);
185
dist += bit_distance[*r](curr)+bit_distance[*(r+1)](curr+8)+
186
bit_distance[*(r+2)](curr+16)+bit_distance[*(r+3)](curr+24);
189
for(currn=curr,rr=r,rn=r+rbyte;rr!=rn; rr++, currn+=8)
191
dist += bit_distance[*rr](currn);
133
static int DistToWelet(puchar r, int fullByte, int w, int h, welet * wl,
134
int xo, int yo, int porog, int dist1) {
135
pchar curr, currn, currh;
140
curr = wl->raster + WR_MAX_WIDTH * ((WR_MAX_HEIGHT - h) / 2)
141
+ (WR_MAX_WIDTH - w) / 2;
142
curr += xo + WR_MAX_WIDTH * yo; // variation
143
currh = curr + WR_MAX_WIDTH * h;
144
rbyte = (w + 7) >> 3;
145
sign = &sign_tab[256] - dist1;
146
for (dist = 0; curr < currh; curr += WR_MAX_WIDTH, r += fullByte) {
147
if (dist + 8 >= porog) {
148
for (currn = curr, rr = r, rn = r + rbyte; rr != rn; rr++, currn
150
dist += bit_distance[*rr](currn);
158
dist += bit_distance[*r](curr);
161
dist += bit_distance[*r](curr) + bit_distance[*(r + 1)](curr
165
dist += bit_distance[*r](curr) + bit_distance[*(r + 1)](curr
166
+ 8) + bit_distance[*(r + 2)](curr + 16);
169
dist += bit_distance[*r](curr) + bit_distance[*(r + 1)](curr
170
+ 8) + bit_distance[*(r + 2)](curr + 16)
171
+ bit_distance[*(r + 3)](curr + 24);
174
for (currn = curr, rr = r, rn = r + rbyte; rr != rn; rr++, currn
176
dist += bit_distance[*rr](currn);
200
185
///////////////////////
202
// �������� ����� cluster's
187
// штрафуем точки cluster's
204
static int sig_tab[513]={
205
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0
206
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1
207
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2
208
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3
209
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 4
210
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 5
211
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 6
212
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 7
213
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 8
214
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 9
215
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // a
216
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // b
217
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // c
218
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // d
219
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // e
220
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // f
222
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0
223
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 1
224
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 1
225
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 3
226
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 4
227
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 5
228
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 6
229
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 7
230
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 8
231
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 9
232
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // a
233
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // b
234
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // c
235
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // d
236
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // e
237
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 // f
189
static int sig_tab[513] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
190
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
191
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2
192
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3
193
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4
194
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 5
195
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6
196
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7
197
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8
198
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9
199
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // a
200
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // b
201
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // c
202
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // d
203
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // e
204
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // f
205
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
206
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
207
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
208
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3
209
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
210
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
211
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
212
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
213
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
214
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
215
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // a
216
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // b
217
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // c
218
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // d
219
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // e
220
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // f
240
SINT DistWeletRazmaz(PBYTE r,int fullByte,int w,int h,welet * wl,
241
int xo,int yo, int porog, int wei)
243
int ww=wl->w, hh=wl->h;
248
int startx=(WR_MAX_WIDTH-w)/2;
249
int starty=(WR_MAX_HEIGHT-h)/2;
250
int stx=(WR_MAX_WIDTH-ww)/2; // start cluster
251
int sty=(WR_MAX_HEIGHT-hh)/2;
252
int lasty,lastx,lastx8;
253
BYTE maskaStart,maskaHvost;
257
// wei=(wl->weight)/3; // better on sb0_037
258
//bit_dist_level=wei;
259
sign=&sig_tab[256]-wei;
262
starty += yo; // variation
264
curr = wl->raster+sty*WR_MAX_WIDTH;
268
for(i=sty;i<starty;i++,curr+=WR_MAX_WIDTH)
269
for(j=stx;j<stx+ww;j++) if(curr[j]> wei) dist++;
270
if(dist > porog) return dist;
272
lasty=MIN(starty+h,sty+hh);
273
lastx=MIN(startx+w,stx+ww);
275
if( starty < sty) r+=(sty-starty)*fullByte;
282
maskaStart = 0xFF<<(8-stx+startx);
284
else maskaStart = 0; // from first bit
286
lastx8=startx+((lastx-startx)&0xfff8);
289
if( lastx < lastx8+8)
290
maskaHvost=0xFF<<(lastx8+8-lastx);
294
// now - start inside frame
295
for(; i < lasty;i++,curr +=WR_MAX_WIDTH,r+=fullByte)
297
for(j=stx;j<startx;j++)
306
cbyte=~( (*rr) | maskaStart );
308
for(j=startx;j<lastx8;j+=8)
310
dist += bit_distance[cbyte](curr+j);
316
// ������� ������ (>lastx) �� ������������ - maska!
321
dist += bit_distance[cbyte](curr+j);
327
// last points in row
338
for(;i<sty+hh;i++,curr+=WR_MAX_WIDTH)
339
for(j=stx;j<stx+ww;j++) if(curr[j]> wei) dist++;
223
int16_t DistWeletRazmaz(puchar r, int fullByte, int w, int h, welet * wl, int xo,
224
int yo, int porog, int wei) {
225
int ww = wl->w, hh = wl->h;
230
int startx = (WR_MAX_WIDTH - w) / 2;
231
int starty = (WR_MAX_HEIGHT - h) / 2;
232
int stx = (WR_MAX_WIDTH - ww) / 2; // start cluster
233
int sty = (WR_MAX_HEIGHT - hh) / 2;
234
int lasty, lastx, lastx8;
235
uchar maskaStart, maskaHvost;
239
// wei=(wl->weight)/3; // better on sb0_037
240
//bit_dist_level=wei;
241
sign = &sig_tab[256] - wei;
244
starty += yo; // variation
246
curr = wl->raster + sty * WR_MAX_WIDTH;
250
for (i = sty; i < starty; i++, curr += WR_MAX_WIDTH)
251
for (j = stx; j < stx + ww; j++)
257
lasty = MIN(starty + h, sty + hh);
258
lastx = MIN(startx + w, stx + ww);
261
r += (sty - starty) * fullByte;
264
j = (stx - startx) >> 3;
267
maskaStart = 0xFF << (8 - stx + startx);
269
maskaStart = 0; // from first bit
271
lastx8 = startx + ((lastx - startx) & 0xfff8);
274
if (lastx < lastx8 + 8)
275
maskaHvost = 0xFF << (lastx8 + 8 - lastx);
279
// now - start inside frame
280
for (; i < lasty; i++, curr += WR_MAX_WIDTH, r += fullByte) {
281
for (j = stx; j < startx; j++) {
289
cbyte = ~((*rr) | maskaStart);
291
for (j = startx; j < lastx8; j += 8) {
292
dist += bit_distance[cbyte](curr + j);
298
// реально лишнее (>lastx) не используется - maska!
300
if (lastx8 < lastx) {
302
dist += bit_distance[cbyte](curr + j);
308
// last points in row
309
for (; j < lastx; j++) {
318
for (; i < sty + hh; i++, curr += WR_MAX_WIDTH)
319
for (j = stx; j < stx + ww; j++)
343
325
////////////////////
346
static int DistToWelet(PBYTE r,int fullByte,int w,int h,welet * wl,
347
int xo,int yo,int porog,int dist1)
328
static int DistToWelet(puchar r,int fullByte,int w,int h,welet * wl,
329
int xo,int yo,int porog,int dist1)
356
curr = wl->raster + WR_MAX_WIDTH*((WR_MAX_HEIGHT-h)/2) +
358
curr += xo + WR_MAX_WIDTH * yo; // variation
362
for(i=0,dist=0; i < h;i++,curr += WR_MAX_WIDTH,r+=fullByte)
364
for(j=jj=0;j<rbyte;j++)
367
if(cbyte == 0) {jj+=8;continue;}
369
for(cc=128;cc;cc>>=1,jj++)
337
curr = wl->raster + WR_MAX_WIDTH*((WR_MAX_HEIGHT-h)/2) +
339
curr += xo + WR_MAX_WIDTH * yo; // variation
343
for(i=0,dist=0; i < h;i++,curr += WR_MAX_WIDTH,r+=fullByte)
373
if( curr[jj] < dist1 )
375
else if( curr[jj] == dist1 )
345
for(j=jj=0;j<rbyte;j++)
348
if(cbyte == 0) {jj+=8;continue;}
350
for(cc=128;cc;cc>>=1,jj++)
354
if( curr[jj] < dist1 )
356
else if( curr[jj] == dist1 )
361
if( dist > porog ) return dist;
368
///////////////////////
370
// штрафуем точки cluster's
372
int16_t DistWeletRazmaz(puchar r,int fullByte,int w,int h,welet * wl,
373
int xo,int yo, int porog,int wei)
375
int16_t ww=wl->w, hh=wl->h;
381
int startx=(WR_MAX_WIDTH-w)/2;
382
int starty=(WR_MAX_HEIGHT-h)/2;
383
int stx=(WR_MAX_WIDTH-ww)/2; // start cluster
384
int sty=(WR_MAX_HEIGHT-hh)/2;
390
// wei=(wl->weight)/3; // better on sb0_037
391
// wei=wl->weight>>1; // old version
394
starty += yo; // variation
397
curr = wl->raster+sty*WR_MAX_WIDTH;
401
for(i=sty;i<starty;i++,curr+=WR_MAX_WIDTH)
402
for(j=stx;j<stx+ww;j++) if(curr[j]> wei) dist++;
403
if(dist > porog) return dist;
405
lasty=MIN(starty+h,sty+hh);
406
lastx=MIN(startx+w,stx+ww);
407
if( starty < sty) r+=(sty-starty)*fullByte;
410
{ initCC=128>>((stx-startx)&7);
380
if( dist > porog ) return dist;
387
///////////////////////
389
// �������� ����� cluster's
391
SINT DistWeletRazmaz(PBYTE r,int fullByte,int w,int h,welet * wl,
392
int xo,int yo, int porog,int wei)
394
SINT ww=wl->w, hh=wl->h;
400
int startx=(WR_MAX_WIDTH-w)/2;
401
int starty=(WR_MAX_HEIGHT-h)/2;
402
int stx=(WR_MAX_WIDTH-ww)/2; // start cluster
403
int sty=(WR_MAX_HEIGHT-hh)/2;
409
// wei=(wl->weight)/3; // better on sb0_037
410
// wei=wl->weight>>1; // old version
413
starty += yo; // variation
416
curr = wl->raster+sty*WR_MAX_WIDTH;
420
for(i=sty;i<starty;i++,curr+=WR_MAX_WIDTH)
421
for(j=stx;j<stx+ww;j++) if(curr[j]> wei) dist++;
422
if(dist > porog) return dist;
424
lasty=MIN(starty+h,sty+hh);
425
lastx=MIN(startx+w,stx+ww);
426
if( starty < sty) r+=(sty-starty)*fullByte;
429
{initCC=128>>((stx-startx)&7);
432
else initCC=128; // from first bit
434
// now - start inside frame
435
for(; i < lasty;i++,curr +=WR_MAX_WIDTH,r+=fullByte)
437
for(j=stx;j<startx;j++) if(curr[j] > wei ) dist++;
438
if(dist > porog ) return dist;
443
for(;j<lastx;j++,cc>>=1)
445
if(cc==0) {cc=128;cbyte=*(++rr);}
446
if( ((cbyte & cc)==0) && curr[j]>wei ) dist++;
448
if(dist > porog) return dist;
450
// last points in row
451
for(;j<stx+ww;j++) if(curr[j] > wei ) dist++;
452
if(dist > porog) return dist;
456
for(;i<sty+hh;i++,curr+=WR_MAX_WIDTH)
457
for(j=stx;j<stx+ww;j++) if(curr[j]> wei) dist++;
413
else initCC=128; // from first bit
415
// now - start inside frame
416
for(; i < lasty;i++,curr +=WR_MAX_WIDTH,r+=fullByte)
418
for(j=stx;j<startx;j++) if(curr[j] > wei ) dist++;
419
if(dist > porog ) return dist;
424
for(;j<lastx;j++,cc>>=1)
426
if(cc==0) {cc=128;cbyte=*(++rr);}
427
if( ((cbyte & cc)==0) && curr[j]>wei ) dist++;
429
if(dist > porog) return dist;
431
// last points in row
432
for(;j<stx+ww;j++) if(curr[j] > wei ) dist++;
433
if(dist > porog) return dist;
437
for(;i<sty+hh;i++,curr+=WR_MAX_WIDTH)
438
for(j=stx;j<stx+ww;j++) if(curr[j]> wei) dist++;
465
int distOne(BYTE *buf,BYTE *bufrazmaz,int w,int h,int bestdist,welet *wel,int x,int y,int countRazmaz)
446
int distOne(uchar *buf, uchar *bufrazmaz, int w, int h, int bestdist,
447
welet *wel, int x, int y, int countRazmaz) {
471
452
#ifdef _USE_HALF_
472
// �� �����-�� �������, �� �� ���� ����
473
if( w < POROG_HALF_WIDTH || h < POROG_HALF_HEIGHT )
475
//return 255 - cmp( buf, (w+7)>>3, w, h, wel);
453
// на каких-то отлично, но на иных бяка
454
if( w < POROG_HALF_WIDTH || h < POROG_HALF_HEIGHT )
456
//return 255 - cmp( buf, (w+7)>>3, w, h, wel);
477
458
//dist1 = wel->weight/10;
478
459
//dist1 = wel->weight/3;
489
wei = wel->weight/3; // /10
469
wei = wel->weight/3; // /10
493
// wei = wel->weight/3;
473
// wei = wel->weight/3;
503
dist1 = wel->summa/wel->fill;
505
// not-weighted distance == 2
506
if(dist1 < 64 ) dist1 *=2;
511
wei=(wel->weight)/3; // better on sb0_037
518
dist=DistToWelet(buf,(w+7)>>3,w,h,wel,x,y,bestdist-1,dist1);
483
dist1 = wel->summa / wel->fill;
485
// not-weighted distance == 2
493
wei = (wel->weight) / 3; // better on sb0_037
499
dist = DistToWelet(buf, (w + 7) >> 3, w, h, wel, x, y, bestdist - 1, dist1);
500
if (dist >= bestdist)
503
if (countRazmaz <= 0)
526
506
#ifdef _USE_HALF_
527
if( w < POROG_HALF_WIDTH || h < POROG_HALF_HEIGHT )
507
if( w < POROG_HALF_WIDTH || h < POROG_HALF_HEIGHT )
528
508
j= DistWeletRazmaz(bufrazmaz,(w>>3)+1,w+1,h+1,wel,x,y,(bestdist-dist-1)*countRazmaz,wei);
532
j= DistWeletRazmaz(bufrazmaz,(w2+7)>>3,w2,h2,wel,x,y,(bestdist-dist-1)*countRazmaz,wei);
512
j = DistWeletRazmaz(bufrazmaz, (w2 + 7) >> 3, w2, h2, wel, x, y, (bestdist
513
- dist - 1) * countRazmaz, wei);
534
return dist+((j+countRazmaz-1)/countRazmaz);
515
return dist + ((j + countRazmaz - 1) / countRazmaz);
537
int distWelet(BYTE *buf,BYTE *bufraz,int w,int h,welet * wl,int porog,int countRazmaz)
539
WORD best,east,west,north,south,center;
540
int lbest; // local best
541
int bound=140; //2*MIN(50,w+h);
544
best=east=west=north=south=center=lbest=0;
546
// center - special threshold??? check !!!
547
center =best=distOne(buf,bufraz,w,h,bound,wl,0,0,countRazmaz);
548
// center =best=distOne(buf,bufraz,w,h,porog,wl,0,0);
549
if(best == 0 ) return best;
551
// test - if very bad, go away ... !!!
552
if(best >= bound ) return porog+1;
554
if(best < porog) porog=best;
556
if((south = distOne(buf,bufraz,w,h,porog,wl, 0, 1,countRazmaz)) < best )
558
if(best==0) return best;
559
if(best < porog) porog=best;
560
if((north = distOne(buf,bufraz,w,h,porog,wl, 0,-1,countRazmaz)) < best )
562
if(best==0) return best;
563
if(best < porog) porog=best;
564
if((east = distOne(buf,bufraz,w,h,porog,wl, 1, 0,countRazmaz)) < best )
566
if(best==0) return best;
567
if(best < porog) porog=best;
568
if((west = distOne(buf,bufraz,w,h,porog,wl,-1, 0,countRazmaz)) < best )
571
if(best==0) return best;
572
if(best < porog) porog=best;
574
if(best < north && best < south && best < east && best < west)
578
if( best >= initPorog)
581
center=best; // to save old best for compare
582
// where try move ? - now two positions may be
583
if( north == center || east == center )
585
if((lbest = distOne(buf,bufraz,w,h,porog,wl,1,-1,countRazmaz)) < best )
588
if(best < porog) porog=best;
591
if(east == center || south == center )
593
if((lbest = distOne(buf,bufraz,w,h,porog,wl,1, 1,countRazmaz)) < best )
596
if(best < porog) porog=best;
599
if(south == center || west == center)
601
if((lbest = distOne(buf,bufraz,w,h,porog,wl,-1, 1,countRazmaz)) < best )
604
if(best < porog) porog=best;
607
if( west == center || north == center)
609
if((lbest = distOne(buf,bufraz,w,h,porog,wl,-1,-1,countRazmaz)) < best )
518
int distWelet(uchar *buf, uchar *bufraz, int w, int h, welet * wl, int porog,
520
uint16_t best, east, west, north, south, center;
521
int lbest; // local best
522
int bound = 140; //2*MIN(50,w+h);
523
int initPorog = porog;
525
best = east = west = north = south = center = lbest = 0;
527
// center - special threshold??? check !!!
528
center = best = distOne(buf, bufraz, w, h, bound, wl, 0, 0, countRazmaz);
529
// center =best=distOne(buf,bufraz,w,h,porog,wl,0,0);
533
// test - if very bad, go away ... !!!
540
if ((south = distOne(buf, bufraz, w, h, porog, wl, 0, 1, countRazmaz))
547
if ((north = distOne(buf, bufraz, w, h, porog, wl, 0, -1, countRazmaz))
554
if ((east = distOne(buf, bufraz, w, h, porog, wl, 1, 0, countRazmaz))
561
if ((west = distOne(buf, bufraz, w, h, porog, wl, -1, 0, countRazmaz))
570
if (best < north && best < south && best < east && best < west)
574
if (best >= initPorog)
577
center = best; // to save old best for compare
578
// where try move ? - now two positions may be
579
if (north == center || east == center) {
580
if ((lbest = distOne(buf, bufraz, w, h, porog, wl, 1, -1, countRazmaz))
587
if (east == center || south == center) {
588
if ((lbest = distOne(buf, bufraz, w, h, porog, wl, 1, 1, countRazmaz))
595
if (south == center || west == center) {
596
if ((lbest = distOne(buf, bufraz, w, h, porog, wl, -1, 1, countRazmaz))
603
if (west == center || north == center) {
604
if ((lbest = distOne(buf, bufraz, w, h, porog, wl, -1, -1, countRazmaz))
616
612
///////////////////////////
617
// 0xba - ����������� ��� i � ���������� ������
618
static const char Palki[]="!1Iil"; // \xba";
613
// 0xba - обозначение для i с приклееной точкой
614
static const char Palki[] = "!1Iil"; // \xba";
620
616
/////////////////
621
static int LookBestClusters(int w,int h,BYTE *buf,BYTE *bufrazmaz,
622
int NumClus, int porog,welet *wel,
623
RECRESULT *recres,int maxNames,int nInCTB,
624
int col,int row,int countRazmaz)
630
for(i=num=0 ;i<NumClus;i++,wel++)
632
if( wel->invalid ) continue;
633
if( !(wel->attr & FON_CLU_SOLID) ) continue;
635
// �� ������������ ���� ?
636
if( wel->weight == 1 &&
637
(wel->nInCTB ==nInCTB ||
638
//wel->sr_col == col && wel->sr_row==row
639
abs(col-wel->sr_col)<=1 && abs(row-wel->sr_row)<=1
642
// wel-> work < 230 )
644
// dist=(255 - wel->work + 4)/(2*STRAFPOINT) ;
646
if( wel->num < 0 ) // �� �� ������ ��������
649
// check for height likeness
652
if( strchr(Palki,wel->let) ||
653
wel->let == liga_i ||
654
(language == LANG_TURKISH && // 30.05.2002 E.P.
655
(wel->let==i_sans_accent||wel->let==II_dot_accent)
659
if( j*5 > MIN(h,wel->mh) )
664
if( j > 2 && j*4 > MAX(h,wel->mh) )
669
if( j > 3 && j*3 >= MAX(w,wel->mw) ) continue;
671
dist=distWelet(buf,bufrazmaz,w,h,wel,porog+1,countRazmaz);
674
{ num=AddVersion( recres,(BYTE)wel->let,(BYTE)(255-dist),i,
677
{porog=255-recres[maxNames-1].prob-1;
680
// if(dist==0) break;
687
j=255-recres[i].prob;
689
// ����� ������ �� �����
691
// for every point - add straf
692
recres[i].prob=(BYTE)j;
617
static int LookBestClusters(int w, int h, uchar *buf, uchar *bufrazmaz,
618
int NumClus, int porog, welet *wel, RECRESULT *recres, int maxNames,
619
int nInCTB, int col, int row, int countRazmaz) {
624
for (i = num = 0; i < NumClus; i++, wel++) {
627
if (!(wel->attr & FON_CLU_SOLID))
630
// не распознавать себя ?
631
if (wel->weight == 1 && (wel->nInCTB == nInCTB ||
632
//wel->sr_col == col && wel->sr_row==row
633
abs(col - wel->sr_col) <= 1 && abs(row - wel->sr_row) <= 1))
634
// wel-> work < 230 )
636
// dist=(255 - wel->work + 4)/(2*STRAFPOINT) ;
638
if (wel->num < 0) // не из нашего алфавита
641
// check for height likeness
642
j = abs(wel->mh - h);
644
if (strchr(Palki, wel->let) || wel->let == liga_i || (language
645
== LANG_TURKISH && // 30.05.2002 E.P.
646
(wel->let == i_sans_accent || wel->let == II_dot_accent))) {
647
if (j * 5 > MIN(h, wel->mh))
650
if (j > 2 && j * 4 > MAX(h, wel->mh))
654
j = abs(wel->mw - w);
655
if (j > 3 && j * 3 >= MAX(w, wel->mw))
658
dist = distWelet(buf, bufrazmaz, w, h, wel, porog + 1, countRazmaz);
661
num = AddVersion(recres, (uchar) wel->let, (uchar)(255 - dist), i,
663
if (num >= maxNames) {
664
porog = 255 - recres[maxNames - 1].prob - 1;
668
// if(dist==0) break;
673
for (i = 0; i < num; i++) {
674
j = 255 - recres[i].prob;
675
j = 255 - STRAFPOINT * j;
676
// очень слабые не нужны
679
// for every point - add straf
680
recres[i].prob = (uchar) j;
699
687
///////////////////////
701
int AddTestAlt(Word8 prob,int numAlt,FonTestInfo *attr,
702
welet *wel,int nClust)
704
Word8 flg =CTB_PRINT_FONT;
707
if(wel->attr & FON_CLU_ITALIC)
708
flg|=CTB_PRINT_ITALIC;
709
if(wel->attr & FON_CLU_BOLD)
711
if(wel->attr & FON_CLU_SERIF)
712
flg|=CTB_PRINT_SERIFIC;
713
if(wel->attr & FON_CLU_GELV)
715
if(wel->attr & FON_CLU_NARROW)
716
flg|=CTB_PRINT_NARROW;
718
for(j=0;j<numAlt;j++ )
720
if( attr[j].flag == flg )
722
if( attr[j].prob < prob )
725
attr[j].kegl = wel->kegl;
726
attr[j].nClust = nClust;
689
int AddTestAlt(uchar prob, int numAlt, FonTestInfo *attr, welet *wel,
691
uchar flg = CTB_PRINT_FONT;
694
if (wel->attr & FON_CLU_ITALIC)
695
flg |= CTB_PRINT_ITALIC;
696
if (wel->attr & FON_CLU_BOLD)
697
flg |= CTB_PRINT_BOLD;
698
if (wel->attr & FON_CLU_SERIF)
699
flg |= CTB_PRINT_SERIFIC;
700
if (wel->attr & FON_CLU_GELV)
701
flg |= CTB_PRINT_GELV;
702
if (wel->attr & FON_CLU_NARROW)
703
flg |= CTB_PRINT_NARROW;
705
for (j = 0; j < numAlt; j++) {
706
if (attr[j].flag == flg) {
707
if (attr[j].prob < prob) {
709
attr[j].kegl = wel->kegl;
710
attr[j].nClust = nClust;
714
if (prob > attr[j].prob)
718
if (j >= MAXCHECKALT)
730
if(prob > attr[j].prob) break;
733
if( j >= MAXCHECKALT )
737
for(k=j+1;k<numAlt;k++ )
739
if( attr[k].flag == flg )
748
memmove(attr+j+1,attr+j,sizeof(FonTestInfo)*(k-j));
752
attr[j].kegl = wel->kegl;
753
attr[j].nClust = nClust;
722
for (k = j + 1; k < numAlt; k++) {
723
if (attr[k].flag == flg)
726
if (k == MAXCHECKALT)
732
memmove(attr + j + 1, attr + j, sizeof(FonTestInfo) * (k - j));
736
attr[j].kegl = wel->kegl;
737
attr[j].nClust = nClust;
758
static SINT CheckLetter(SINT w,SINT h,BYTE *buf,BYTE *bufrazmaz,
759
FONBASE *fbase,int porog, int let,FonTestInfo *attr ,Int16 nInCTB)
766
if( let<0 || let > 255)
770
for(num=0;i>0; i=wel->next)
772
wel=fbase->start+i-1;
774
if( wel->let != let ) continue;
775
if( wel->invalid ) continue;
776
if( !(wel->attr & FON_CLU_SOLID) ) continue;
777
if( wel->weight == 1 && wel->nInCTB == nInCTB )
781
dist=distWelet(buf,bufrazmaz,w,h,wel,porog+1,1);
785
Word8 prob=MAX(0,255-STRAFPOINT*dist);
786
numAlt = AddTestAlt( prob,numAlt,attr,wel,i);
791
if(num <= 0) return -1; // no such letter
742
static int16_t CheckLetter(int16_t w, int16_t h, uchar *buf, uchar *bufrazmaz,
743
FONBASE *fbase, int porog, int let, FonTestInfo *attr, int16_t nInCTB) {
749
if (let < 0 || let > 255)
752
i = fbase->first[let];
753
for (num = 0; i > 0; i = wel->next) {
754
wel = fbase->start + i - 1;
760
if (!(wel->attr & FON_CLU_SOLID))
762
if (wel->weight == 1 && wel->nInCTB == nInCTB)
766
dist = distWelet(buf, bufrazmaz, w, h, wel, porog + 1, 1);
769
uchar prob = MAX(0, 255 - STRAFPOINT * dist);
770
numAlt = AddTestAlt(prob, numAlt, attr, wel, i);
776
return -1; // no such letter
795
780
///////////////////////
796
static BYTE buf[REC_MAX_RASTER_SIZE];
797
static BYTE bufrazmaz[REC_MAX_RASTER_SIZE];
798
static BYTE const mask0[8]={255,128,192,224,240,248,252,254};
781
static uchar buf[REC_MAX_RASTER_SIZE];
782
static uchar bufrazmaz[REC_MAX_RASTER_SIZE];
783
static uchar const mask0[8] = { 255, 128, 192, 224, 240, 248, 252, 254 };
800
SINT RecogClu(BYTE *rast,SINT xbyte,SINT xbit,SINT yrow,
801
RECRESULT *recres, SINT maxNames,
802
welet *wl,int numWel,
803
int porog ,int nInCTB, Int16 col, Int16 row,
807
int rbyte=(xbit+7)>>3;
809
BYTE hvost=mask0[xbit&7];
812
if(wl==NULL || numWel <= 0) return 0;
813
if(xbyte*yrow > REC_MAX_RASTER_SIZE) yrow=REC_MAX_RASTER_SIZE/xbyte;
815
for(i=0,b1=buf;i<yrow;i++,b1+=rbyte,rast+=xbyte)
817
memcpy(b1,rast,rbyte);
785
int16_t RecogClu(uchar *rast, int16_t xbyte, int16_t xbit, int16_t yrow, RECRESULT *recres,
786
int16_t maxNames, welet *wl, int numWel, int porog, int nInCTB,
787
int16_t col, int16_t row, int32_t countRazmaz) {
789
int rbyte = (xbit + 7) >> 3;
791
uchar hvost = mask0[xbit & 7];
793
if (wl == NULL || numWel <= 0)
795
if (xbyte * yrow > REC_MAX_RASTER_SIZE)
796
yrow = REC_MAX_RASTER_SIZE / xbyte;
798
for (i = 0, b1 = buf; i < yrow; i++, b1 += rbyte, rast += xbyte) {
799
memcpy(b1, rast, rbyte);
800
b1[rbyte - 1] &= hvost;
821
803
#ifdef _USE_HALF_
822
if( xbit < POROG_HALF_WIDTH || yrow < POROG_HALF_HEIGHT )
823
RazmazHalf(buf,bufrazmaz,xbit,yrow);
804
if( xbit < POROG_HALF_WIDTH || yrow < POROG_HALF_HEIGHT )
805
RazmazHalf(buf,bufrazmaz,xbit,yrow);
826
Razmaz2(buf,bufrazmaz,xbit,yrow, 0,POROG_ANGLES);
829
porog=MIN(50,xbit+yrow+4);
831
if(maxNames > MAX_ALT )
834
i=LookBestClusters(xbit,yrow,buf,bufrazmaz,
835
numWel,porog,wl,recres, maxNames,nInCTB,col,row,countRazmaz);
808
Razmaz2(buf, bufrazmaz, xbit, yrow, 0, POROG_ANGLES);
811
porog = MIN(50, xbit + yrow + 4);
813
if (maxNames > MAX_ALT)
816
i = LookBestClusters(xbit, yrow, buf, bufrazmaz, numWel, porog, wl, recres,
817
maxNames, nInCTB, col, row, countRazmaz);
837
819
#ifdef CHECK_EQUAL
839
recres[0].prob - 3 <= recres[1].prob )
841
int CheckRaster(PBYTE r,WORD fullBytes,WORD w,WORD h,
821
recres[0].prob - 3 <= recres[1].prob )
823
int CheckRaster(puchar r,uint16_t fullBytes,uint16_t w,uint16_t h,
842
824
welet *wel,int inBase,int let);
844
prob0= CheckRaster(buf,rbyte,xbit,yrow,wl,numWel,recres[0].name);
845
prob1= CheckRaster(buf,rbyte,xbit,yrow,wl,numWel,recres[1].name);
848
RECRESULT tmpRec=recres[0];
862
#ifdef _TEST_ADD_FAT_
864
static int AddTestRecogCollection( BYTE *rast,int xbit,int yrow,
865
int num,RECRESULT *recres, welet *wl,int numWel );
866
i=AddTestRecogCollection ( buf,(int)xbit,(int)yrow,
867
i, recres, wl,(int)numWel);
873
///////////////////////////
874
SINT CheckClu(BYTE *rast,SINT xbyte,SINT xbit,SINT yrow,
875
FONBASE *fbase,int let,FonTestInfo *attr,Int16 nInCTB)
878
int rbyte=(xbit+7)>>3;
881
BYTE hvost=mask0[xbit&7];
883
if( fbase==NULL || fbase->inBase <= 0)
885
if(xbyte*yrow > REC_MAX_RASTER_SIZE) yrow=REC_MAX_RASTER_SIZE/xbyte;
887
for(i=0,b1=buf;i<yrow;i++,b1+=rbyte,rast+=xbyte)
889
memcpy(b1,rast,rbyte);
895
if( xbit < POROG_HALF_WIDTH || yrow < POROG_HALF_HEIGHT )
896
RazmazHalf(buf,bufrazmaz,xbit,yrow);
899
Razmaz2(buf,bufrazmaz,xbit,yrow,
900
0,(SINT)POROG_ANGLES );
902
//porog=MAX(xbit,yrow);
903
porog=MIN(50,xbit+yrow);
905
i=CheckLetter(xbit,yrow,buf,bufrazmaz,
906
fbase, porog, let, attr,nInCTB);
909
///////////////////////////
910
int CompareCluster(BYTE *rast,int xbyte,int xbit,int yrow,welet *wel,
914
int rbyte=(xbit+7)>>3;
916
BYTE hvost=mask0[xbit&7];
918
if( wel==NULL ) return 0;
919
if(xbyte*yrow > REC_MAX_RASTER_SIZE) yrow=REC_MAX_RASTER_SIZE/xbyte;
922
for(i=0,b1=buf;i<yrow;i++,b1+=rbyte,rast+=xbyte)
923
{memcpy(b1,rast,rbyte);
928
if( xbit < POROG_HALF_WIDTH || yrow < POROG_HALF_HEIGHT )
929
RazmazHalf(buf,bufrazmaz,(SINT)xbit,(SINT)yrow);
932
Razmaz2(buf,bufrazmaz,(SINT)xbit,(SINT)yrow,
933
(SINT)0,(SINT)POROG_ANGLES);
935
i=distOne(buf,bufrazmaz,xbit,yrow,85,wel,movex,movey,1);
936
return MAX(0,255-STRAFPOINT*i);
938
///////////////////////////
939
#ifdef _TEST_ADD_FAT_
941
static int DistToWeletReal(PBYTE r,int fullByte,int w,int h,welet * wl,
942
int xo,int yo,int porog)
950
// dist1 = wl->summa/wl->fill;
952
curr = wl->raster + WR_MAX_WIDTH*((WR_MAX_HEIGHT-h)/2) +
954
curr += xo + WR_MAX_WIDTH * yo; // variation
958
for(i=0,dist=0; i < h;i++,curr += WR_MAX_WIDTH,r+=fullByte)
960
for(j=jj=0;j<rbyte;j++)
963
if(cbyte == 0) {jj+=8;continue;}
965
for(cc=128;cc;cc>>=1,jj++)
973
if( curr[jj] > 0 ) dist++;
976
if( dist > porog ) return dist;
826
prob0= CheckRaster(buf,rbyte,xbit,yrow,wl,numWel,recres[0].name);
827
prob1= CheckRaster(buf,rbyte,xbit,yrow,wl,numWel,recres[1].name);
830
RECRESULT tmpRec=recres[0];
844
#ifdef _TEST_ADD_FAT_
846
static int AddTestRecogCollection( uchar *rast,int xbit,int yrow,
847
int num,RECRESULT *recres, welet *wl,int numWel );
848
i=AddTestRecogCollection ( buf,(int)xbit,(int)yrow,
849
i, recres, wl,(int)numWel);
855
///////////////////////////
856
int16_t CheckClu(uchar *rast, int16_t xbyte, int16_t xbit, int16_t yrow, FONBASE *fbase,
857
int let, FonTestInfo *attr, int16_t nInCTB) {
859
int rbyte = (xbit + 7) >> 3;
862
uchar hvost = mask0[xbit & 7];
864
if (fbase == NULL || fbase->inBase <= 0)
866
if (xbyte * yrow > REC_MAX_RASTER_SIZE)
867
yrow = REC_MAX_RASTER_SIZE / xbyte;
869
for (i = 0, b1 = buf; i < yrow; i++, b1 += rbyte, rast += xbyte) {
870
memcpy(b1, rast, rbyte);
871
b1[rbyte - 1] &= hvost;
875
if( xbit < POROG_HALF_WIDTH || yrow < POROG_HALF_HEIGHT )
876
RazmazHalf(buf,bufrazmaz,xbit,yrow);
879
Razmaz2(buf, bufrazmaz, xbit, yrow, 0, (int16_t) POROG_ANGLES);
881
//porog=MAX(xbit,yrow);
882
porog = MIN(50, xbit + yrow);
885
= CheckLetter(xbit, yrow, buf, bufrazmaz, fbase, porog, let, attr,
889
///////////////////////////
890
int CompareCluster(uchar *rast, int xbyte, int xbit, int yrow, welet *wel,
891
int movex, int movey) {
893
int rbyte = (xbit + 7) >> 3;
895
uchar hvost = mask0[xbit & 7];
899
if (xbyte * yrow > REC_MAX_RASTER_SIZE)
900
yrow = REC_MAX_RASTER_SIZE / xbyte;
903
for (i = 0, b1 = buf; i < yrow; i++, b1 += rbyte, rast += xbyte) {
904
memcpy(b1, rast, rbyte);
905
b1[rbyte - 1] &= hvost;
909
if( xbit < POROG_HALF_WIDTH || yrow < POROG_HALF_HEIGHT )
910
RazmazHalf(buf,bufrazmaz,(int16_t)xbit,(int16_t)yrow);
913
Razmaz2(buf, bufrazmaz, (int16_t) xbit, (int16_t) yrow, (int16_t) 0,
914
(int16_t) POROG_ANGLES);
916
i = distOne(buf, bufrazmaz, xbit, yrow, 85, wel, movex, movey, 1);
917
return MAX(0, 255 - STRAFPOINT * i);
919
///////////////////////////
920
#ifdef _TEST_ADD_FAT_
922
static int DistToWeletReal(puchar r,int fullByte,int w,int h,welet * wl,
923
int xo,int yo,int porog)
931
// dist1 = wl->summa/wl->fill;
933
curr = wl->raster + WR_MAX_WIDTH*((WR_MAX_HEIGHT-h)/2) +
935
curr += xo + WR_MAX_WIDTH * yo; // variation
939
for(i=0,dist=0; i < h;i++,curr += WR_MAX_WIDTH,r+=fullByte)
941
for(j=jj=0;j<rbyte;j++)
944
if(cbyte == 0) {jj+=8;continue;}
946
for(cc=128;cc;cc>>=1,jj++)
954
if( curr[jj] > 0 ) dist++;
957
if( dist > porog ) return dist;
983
964
///////////////////////
984
static int AddTestRecogCollection( BYTE *rast,int xbit,int yrow,
985
int num,RECRESULT *recres,
986
welet *wl,int numWel )
965
static int AddTestRecogCollection( uchar *rast,int xbit,int yrow,
966
int num,RECRESULT *recres,
967
welet *wl,int numWel )
988
int rbyte=(xbit+7)>>3;
969
int rbyte=(xbit+7)>>3;
996
977
if(recres[0].prob < 250)
999
980
if(recres[1].prob < recres[0].prob)
1002
983
for(iSame=0,best=0;iSame<num;iSame++)
1006
987
if(recres[iSame].prob < recres[0].prob)
1008
989
straf[iSame]= DistToWeletReal(rast,rbyte,xbit,yrow,
1009
wl+recres[iSame].nClust, 0,0,100);
990
wl+recres[iSame].nClust, 0,0,100);
1010
991
if(straf[iSame] < straf[best])
1014
995
for(i=0;i<iSame;i++)
1016
997
straf[i]-=straf[best];
1019
1000
if(straf[i]<recres[i].prob)
1020
recres[i].prob-=straf[i];
1001
recres[i].prob-=straf[i];
1025
1006
// not optimal !!!
1051
1032
// for handprinted recognition
1052
1033
/////////////////
1054
// �� ���������� ����� �� ���������� <= bound
1035
// не штрафовать точки на расстоянии <= bound
1056
1037
#define STRAF_NOTFAR 2
1057
1038
#define STRAF_FAR 4
1058
1039
#define STRAF_CLUFAR 1
1060
static int distOkr1(PBYTE r,int w,int h,welet * wl,
1061
int xo,int yo,int porog,int bound)
1070
dist1 = wl->summa/wl->fill;
1072
if( dist1 > 127) dist1=127;
1074
// not-weighted distance
1075
if(dist1 < 64 ) dist2 =dist1*2;
1081
curr = wl->raster + WR_MAX_WIDTH*((WR_MAX_HEIGHT-h)/2) +
1083
curr += xo + WR_MAX_WIDTH * yo; // variation
1087
for(i=0,dist=0; i < h;i++,curr += WR_MAX_WIDTH,r+=rbyte)
1089
for(j=jj=0;j<rbyte;j++)
1092
if(cbyte == 0) {jj+=8;continue;}
1094
for(cc=128;cc;cc>>=1,jj++)
1041
static int distOkr1(puchar r, int w, int h, welet * wl, int xo, int yo,
1042
int porog, int bound) {
1050
dist1 = wl->summa / wl->fill;
1055
// not-weighted distance
1064
curr = wl->raster + WR_MAX_WIDTH * ((WR_MAX_HEIGHT - h) / 2)
1065
+ (WR_MAX_WIDTH - w) / 2;
1066
curr += xo + WR_MAX_WIDTH * yo; // variation
1068
rbyte = (w + 7) >> 3;
1070
for (i = 0, dist = 0; i < h; i++, curr += WR_MAX_WIDTH, r += rbyte) {
1071
for (j = jj = 0; j < rbyte; j++) {
1078
for (cc = 128; cc; cc >>= 1, jj++) {
1080
if (curr[jj] < dist2)
1082
else if (curr[jj] < dist1)
1083
dist += STRAF_NOTFAR;
1095
///////////////////////
1096
///////////////////////
1098
// штрафуем точки cluster's
1100
int16_t distOkr2(puchar r, int w, int h, welet * wl, int xo, int yo, int porog,
1102
int16_t ww = wl->w, hh = wl->h;
1108
int startx = (WR_MAX_WIDTH - w) / 2;
1109
int starty = (WR_MAX_HEIGHT - h) / 2;
1110
int stx = (WR_MAX_WIDTH - ww) / 2; // start cluster
1111
int sty = (WR_MAX_HEIGHT - hh) / 2;
1118
wei = (wei * proc) / 100;
1121
starty += yo; // variation
1122
rbyte = (w + 7) >> 3;
1124
curr = wl->raster + sty * WR_MAX_WIDTH;
1128
for (i = sty; i < starty; i++, curr += WR_MAX_WIDTH)
1129
for (j = stx; j < stx + ww; j++)
1135
lasty = MIN(starty + h, sty + hh);
1136
lastx = MIN(startx + w, stx + ww);
1138
r += (sty - starty) * rbyte;
1141
initCC = 128 >> ((stx - startx) & 7);
1142
r += (stx - startx) >> 3;
1144
initCC = 128; // from first bit
1146
// now - start inside frame
1147
for (; i < lasty; i++, curr += WR_MAX_WIDTH, r += rbyte) {
1148
for (j = stx; j < startx; j++)
1157
for (; j < lastx; j++, cc >>= 1) {
1162
if (((cbyte & cc) == 0) && curr[j] > wei)
1168
// last points in row
1169
for (; j < stx + ww; j++)
1177
for (; i < sty + hh; i++, curr += WR_MAX_WIDTH)
1178
for (j = stx; j < stx + ww; j++)
1185
static int distOneOkr(puchar r, puchar razmaz, int w, int h, int porog,
1186
welet * wel, int x, int y, int bound, int proc) {
1189
dist = distOkr1(r, w, h, wel, x, y, porog - 1, bound);
1193
j = distOkr2(razmaz, w + 2, h + 2, wel, x, y, porog - dist - 1, proc);
1197
///////////////////////////
1199
static int distWeletOkr(uchar *buf, uchar *razmaz, int w, int h, welet * wl,
1200
int porog, int okr, int proc) {
1201
uint16_t best, east, west, north, south, center;
1202
int lbest; // local best
1203
int bound = 200; //2*MIN(50,w+h);
1204
int initPorog = porog;
1207
best = east = west = north = south = center = lbest = 0;
1209
// center - special threshold??? check !!!
1210
center = best = distOneOkr(buf, razmaz, w, h, bound, wl, 0, 0, okr, proc);
1211
// center =best=distOne(buf,bufraz,w,h,porog,wl,0,0);
1215
// test - if very bad, go away ... !!!
1216
// if(best >= bound ) return porog+1;
1221
if ((south = distOneOkr(buf, razmaz, w, h, porog, wl, 0, 1, okr, proc))
1228
if ((north = distOneOkr(buf, razmaz, w, h, porog, wl, 0, -1, okr, proc))
1235
if ((east = distOneOkr(buf, razmaz, w, h, porog, wl, 1, 0, okr, proc))
1242
if ((west = distOneOkr(buf, razmaz, w, h, porog, wl, -1, 0, okr, proc))
1251
// if(best < north && best < south && best < east && best < west)
1255
if (best >= initPorog) {
1256
north = south = east = west = best;
1258
} else if (best < north && best < south && best < east && best < west)
1261
center = best; // to save old best for compare
1262
// where try move ? - now two positions may be
1263
ne = es = sw = wn = 0;
1265
if (north == center || east == center) {
1266
if ((lbest = distOneOkr(buf, razmaz, w, h, porog, wl, 1, -1, okr, proc))
1274
if (east == center || south == center) {
1275
if ((lbest = distOneOkr(buf, razmaz, w, h, porog, wl, 1, 1, okr, proc))
1284
if (south == center || west == center) {
1285
if ((lbest = distOneOkr(buf, razmaz, w, h, porog, wl, -1, 1, okr, proc))
1294
if (west == center || north == center) {
1296
= distOneOkr(buf, razmaz, w, h, porog, wl, -1, -1, okr, proc))
1098
if( curr[jj] < dist2 )
1100
else if( curr[jj] < dist1 )
1305
int movX = 0, movY = 0;
1318
} else if (south == best)
1320
else if (north == best)
1322
else if (east == best)
1324
else if (west == best)
1327
if ((lbest = distOneOkr(buf, razmaz, w, h, porog, wl, movX, movY, okr,
1113
///////////////////////
1114
///////////////////////
1116
// �������� ����� cluster's
1118
SINT distOkr2(PBYTE r,int w,int h,welet * wl,
1119
int xo,int yo, int porog,int proc)
1121
SINT ww=wl->w, hh=wl->h;
1127
int startx=(WR_MAX_WIDTH-w)/2;
1128
int starty=(WR_MAX_HEIGHT-h)/2;
1129
int stx=(WR_MAX_WIDTH-ww)/2; // start cluster
1130
int sty=(WR_MAX_HEIGHT-hh)/2;
1141
starty += yo; // variation
1144
curr = wl->raster+sty*WR_MAX_WIDTH;
1148
for(i=sty;i<starty;i++,curr+=WR_MAX_WIDTH)
1149
for(j=stx;j<stx+ww;j++) if(curr[j]> wei) dist++;
1150
if(dist > porog) return dist;
1152
lasty=MIN(starty+h,sty+hh);
1153
lastx=MIN(startx+w,stx+ww);
1154
if( starty < sty) r+=(sty-starty)*rbyte;
1157
{initCC=128>>((stx-startx)&7);
1160
else initCC=128; // from first bit
1162
// now - start inside frame
1163
for(; i < lasty;i++,curr +=WR_MAX_WIDTH,r+=rbyte)
1165
for(j=stx;j<startx;j++) if(curr[j] > wei ) dist++;
1166
if(dist > porog ) return dist;
1171
for(;j<lastx;j++,cc>>=1)
1173
if(cc==0) {cc=128;cbyte=*(++rr);}
1174
if( ((cbyte & cc)==0) && curr[j]>wei ) dist++;
1176
if(dist > porog) return dist;
1178
// last points in row
1179
for(;j<stx+ww;j++) if(curr[j] > wei ) dist++;
1180
if(dist > porog) return dist;
1184
for(;i<sty+hh;i++,curr+=WR_MAX_WIDTH)
1185
for(j=stx;j<stx+ww;j++) if(curr[j]> wei) dist++;
1190
static int distOneOkr(PBYTE r,PBYTE razmaz,int w,int h,int porog,welet * wel,
1191
int x,int y,int bound,int proc)
1195
dist=distOkr1(r,w,h,wel,x,y,porog-1,bound);
1196
if(dist >= porog) return dist;
1198
j= distOkr2(razmaz,w+2,h+2,wel,x,y,porog-dist-1,proc);
1202
///////////////////////////
1204
static int distWeletOkr(BYTE *buf,BYTE *razmaz,int w,int h,welet * wl,int porog,int okr,int proc)
1206
WORD best,east,west,north,south,center;
1207
int lbest; // local best
1208
int bound=200; //2*MIN(50,w+h);
1209
int initPorog=porog;
1212
best=east=west=north=south=center=lbest=0;
1214
// center - special threshold??? check !!!
1215
center =best=distOneOkr(buf,razmaz,w,h,bound,wl,0,0,okr,proc);
1216
// center =best=distOne(buf,bufraz,w,h,porog,wl,0,0);
1217
if(best == 0 ) return best;
1219
// test - if very bad, go away ... !!!
1220
// if(best >= bound ) return porog+1;
1222
if(best < porog) porog=best;
1224
if((south = distOneOkr(buf,razmaz,w,h,porog,wl, 0, 1,okr,proc)) < best )
1226
if(best==0) return best;
1227
if(best < porog) porog=best;
1228
if((north = distOneOkr(buf,razmaz,w,h,porog,wl, 0,-1,okr,proc)) < best )
1230
if(best==0) return best;
1231
if(best < porog) porog=best;
1232
if((east = distOneOkr(buf,razmaz,w,h,porog,wl, 1, 0,okr,proc)) < best )
1234
if(best==0) return best;
1235
if(best < porog) porog=best;
1236
if((west = distOneOkr(buf,razmaz,w,h,porog,wl,-1, 0,okr,proc)) < best )
1239
if(best==0) return best;
1240
if(best < porog) porog=best;
1242
// if(best < north && best < south && best < east && best < west)
1246
if( best >= initPorog)
1248
north=south=east=west=best;
1251
else if(best < north && best < south && best < east && best < west)
1254
center=best; // to save old best for compare
1255
// where try move ? - now two positions may be
1258
if( north == center || east == center )
1260
if((lbest = distOneOkr(buf,razmaz,w,h,porog,wl,1,-1,okr,proc)) < best )
1264
if(best < porog) porog=best;
1267
if(east == center || south == center )
1269
if((lbest = distOneOkr(buf,razmaz,w,h,porog,wl,1, 1,okr,proc)) < best )
1272
if(best < porog) porog=best;
1277
if(south == center || west == center)
1279
if((lbest = distOneOkr(buf,razmaz,w,h,porog,wl,-1, 1,okr,proc)) < best )
1282
if(best < porog) porog=best;
1287
if( west == center || north == center)
1289
if((lbest = distOneOkr(buf,razmaz,w,h,porog,wl,-1,-1,okr,proc)) < best )
1299
if( ne ) { movX=2; movY=-2;}
1300
else if(es) { movX=2; movY=2;}
1301
else if(sw) { movX=-2; movY=2;}
1302
else if(wn) { movX=-2; movY=-2;}
1303
else if( south == best ) movY=2;
1304
else if( north == best ) movY=-2;
1305
else if( east == best ) movX=2;
1306
else if( west == best ) movX=-2;
1308
if((lbest = distOneOkr(buf,razmaz,w,h,porog,wl,movX,movY,okr,proc)) < best )
1314
///////////////////////////
1315
///////////////////////////
1316
// 0xba - ����������� ��� i � ���������� ������
1334
///////////////////////////
1335
///////////////////////////
1336
// 0xba - обозначение для i с приклееной точкой
1317
1337
//static const char Palki[]="!1Iil\xba";
1318
1338
/////////////////
1319
static int LookBestOkr(int w,int h,BYTE *buf,BYTE *razmaz,
1320
int NumClus, int porog,welet *wel,
1321
RECRESULT *recres,int maxNames,int nInCTB,
1322
int col,int row,int okr,int proc)
1328
for(i=num=0 ;i<NumClus;i++,wel++)
1330
if( wel->invalid ) continue;
1331
if( !(wel->attr & FON_CLU_SOLID) ) continue;
1333
// �� ������������ ���� ?
1334
if( wel->weight == 1 &&
1335
(wel->nInCTB ==nInCTB ||
1336
//wel->sr_col == col && wel->sr_row==row
1337
abs(col-wel->sr_col)<=1 && abs(row-wel->sr_row)<=1
1340
// wel-> work < 230 )
1342
// dist=(255 - wel->work + 4)/(2*STRAFPOINT) ;
1344
if( wel->num < 0 ) // �� �� ������ ��������
1347
// check for height likeness
1349
if( j > 2 && j*3 > MAX(h,wel->mh) )
1353
if( j > 3 && j*3 >= MAX(w,wel->mw) )
1356
dist=distWeletOkr(buf,razmaz,w,h,wel,porog+1,okr,proc);
1359
{ num=AddVersion( recres,(BYTE)wel->let,(BYTE)(255-dist),i,
1362
{porog=255-recres[maxNames-1].prob-1;
1363
if(porog < 0) break;
1365
// if(dist==0) break;
1339
static int LookBestOkr(int w, int h, uchar *buf, uchar *razmaz, int NumClus,
1340
int porog, welet *wel, RECRESULT *recres, int maxNames, int nInCTB,
1341
int col, int row, int okr, int proc) {
1346
for (i = num = 0; i < NumClus; i++, wel++) {
1349
if (!(wel->attr & FON_CLU_SOLID))
1352
// не распознавать себя ?
1353
if (wel->weight == 1 && (wel->nInCTB == nInCTB ||
1354
//wel->sr_col == col && wel->sr_row==row
1355
abs(col - wel->sr_col) <= 1 && abs(row - wel->sr_row) <= 1))
1356
// wel-> work < 230 )
1358
// dist=(255 - wel->work + 4)/(2*STRAFPOINT) ;
1360
if (wel->num < 0) // не из нашего алфавита
1363
// check for height likeness
1364
j = abs(wel->mh - h);
1365
if (j > 2 && j * 3 > MAX(h, wel->mh))
1368
j = abs(wel->mw - w);
1369
if (j > 3 && j * 3 >= MAX(w, wel->mw))
1372
dist = distWeletOkr(buf, razmaz, w, h, wel, porog + 1, okr, proc);
1374
if (dist <= porog) {
1375
num = AddVersion(recres, (uchar) wel->let, (uchar)(255 - dist), i,
1377
if (num >= maxNames) {
1378
porog = 255 - recres[maxNames - 1].prob - 1;
1382
// if(dist==0) break;
1373
1390
///////////////////////
1374
int RecogCluOkr(BYTE *rast,SINT xbyte,SINT xbit,SINT yrow,
1375
RECRESULT *recres, SINT maxNames,
1376
welet *wl,int numWel,
1377
int porog ,int nInCTB, Int16 col, Int16 row,
1381
int rbyte=(xbit+7)>>3;
1383
BYTE hvost=mask0[xbit&7];
1386
if(wl==NULL || numWel <= 0) return 0;
1387
if(xbyte*yrow > REC_MAX_RASTER_SIZE) yrow=REC_MAX_RASTER_SIZE/xbyte;
1389
for(i=0,b1=buf;i<yrow;i++,b1+=rbyte,rast+=xbyte)
1391
memcpy(b1,rast,rbyte);
1395
Razmaz2(buf,bufrazmaz,xbit,yrow,0,POROG_ANGLES);
1397
//porog=MAX(xbit,yrow);
1398
if(porog < 0) porog= 200;
1400
if(maxNames > MAX_ALT )
1402
i=LookBestOkr(xbit,yrow,buf,bufrazmaz,
1403
numWel,porog,wl,recres, maxNames,nInCTB,col,row,okr,proc);
1407
///////////////////////////
1408
int CompareClusterOkr(BYTE *rast,int xbyte,int xbit,int yrow,welet *wel,
1409
int movex,int movey,int okr,int proc,
1410
int *dist1,int *dist2)
1413
int rbyte=(xbit+7)>>3;
1415
BYTE hvost=mask0[xbit&7];
1417
if( wel==NULL ) return 0;
1418
if(xbyte*yrow > REC_MAX_RASTER_SIZE) yrow=REC_MAX_RASTER_SIZE/xbyte;
1421
for(i=0,b1=buf;i<yrow;i++,b1+=rbyte,rast+=xbyte)
1422
{memcpy(b1,rast,rbyte);
1425
Razmaz2(buf,bufrazmaz,(SINT)xbit,(SINT)yrow,0,POROG_ANGLES);
1427
i=distOneOkr(buf,bufrazmaz,xbit,yrow,250,wel,movex,movey,okr,proc);
1428
*dist1=distOkr1(buf,xbit,yrow,wel,movex,movey,250,okr);
1429
*dist2 =distOkr2(bufrazmaz,xbit+2,yrow+2,wel,movex,movey,250,proc);
1432
///////////////////////////
1433
// ������� ����� �������
1434
static int distOkr(PBYTE r,int w,int h,welet * wl,
1435
int xo,int yo,int porog)
1443
curr = wl->raster + WR_MAX_WIDTH*((WR_MAX_HEIGHT-h)/2) +
1445
curr += xo + WR_MAX_WIDTH * yo; // variation
1449
for(i=0,dist=0; i < h;i++,curr += WR_MAX_WIDTH,r+=rbyte)
1451
for(j=jj=0;j<rbyte;j++)
1454
if(cbyte == 0) {jj+=8;continue;}
1456
for(cc=128;cc;cc>>=1,jj++)
1391
int RecogCluOkr(uchar *rast, int16_t xbyte, int16_t xbit, int16_t yrow,
1392
RECRESULT *recres, int16_t maxNames, welet *wl, int numWel, int porog,
1393
int nInCTB, int16_t col, int16_t row, int okr, int proc) {
1395
int rbyte = (xbit + 7) >> 3;
1397
uchar hvost = mask0[xbit & 7];
1399
if (wl == NULL || numWel <= 0)
1401
if (xbyte * yrow > REC_MAX_RASTER_SIZE)
1402
yrow = REC_MAX_RASTER_SIZE / xbyte;
1404
for (i = 0, b1 = buf; i < yrow; i++, b1 += rbyte, rast += xbyte) {
1405
memcpy(b1, rast, rbyte);
1406
b1[rbyte - 1] &= hvost;
1409
Razmaz2(buf, bufrazmaz, xbit, yrow, 0, POROG_ANGLES);
1411
//porog=MAX(xbit,yrow);
1415
if (maxNames > MAX_ALT)
1417
i = LookBestOkr(xbit, yrow, buf, bufrazmaz, numWel, porog, wl, recres,
1418
maxNames, nInCTB, col, row, okr, proc);
1422
///////////////////////////
1423
int CompareClusterOkr(uchar *rast, int xbyte, int xbit, int yrow, welet *wel,
1424
int movex, int movey, int okr, int proc, int *dist1, int *dist2) {
1426
int rbyte = (xbit + 7) >> 3;
1428
uchar hvost = mask0[xbit & 7];
1432
if (xbyte * yrow > REC_MAX_RASTER_SIZE)
1433
yrow = REC_MAX_RASTER_SIZE / xbyte;
1436
for (i = 0, b1 = buf; i < yrow; i++, b1 += rbyte, rast += xbyte) {
1437
memcpy(b1, rast, rbyte);
1438
b1[rbyte - 1] &= hvost;
1440
Razmaz2(buf, bufrazmaz, (int16_t) xbit, (int16_t) yrow, 0, POROG_ANGLES);
1442
i = distOneOkr(buf, bufrazmaz, xbit, yrow, 250, wel, movex, movey, okr,
1444
*dist1 = distOkr1(buf, xbit, yrow, wel, movex, movey, 250, okr);
1445
*dist2 = distOkr2(bufrazmaz, xbit + 2, yrow + 2, wel, movex, movey, 250,
1449
///////////////////////////
1450
// сколько точек вылазит
1451
static int distOkr(puchar r, int w, int h, welet * wl, int xo, int yo,
1459
curr = wl->raster + WR_MAX_WIDTH * ((WR_MAX_HEIGHT - h) / 2)
1460
+ (WR_MAX_WIDTH - w) / 2;
1461
curr += xo + WR_MAX_WIDTH * yo; // variation
1463
rbyte = (w + 7) >> 3;
1465
for (i = 0, dist = 0; i < h; i++, curr += WR_MAX_WIDTH, r += rbyte) {
1466
for (j = jj = 0; j < rbyte; j++) {
1473
for (cc = 128; cc; cc >>= 1, jj++) {
1473
1488
///////////////////////
1474
1489
//#define KOEFF 4
1475
static int LookBestInner(int w,int h,BYTE *buf,BYTE *razmaz,
1476
int NumClus, welet *wel,
1477
RECRESULT *recres,int maxNames,int nInCTB,
1478
Int16 *col,Int16 *row)
1491
float KOEFF=MAX(1.0f,(w*h)/250.0f);
1493
for(i=num=0 ;i<NumClus;i++,wel++)
1495
if( wel->invalid ) continue;
1496
if( !(wel->attr & FON_CLU_SOLID) ) continue;
1498
// �� ������������ ���� ?
1500
if( wel->num < 0 ) // �� �� ������ ��������
1503
if( wel->mh*2 < h ||
1490
static int LookBestInner(int w, int h, uchar *buf, uchar *razmaz, int NumClus,
1491
welet *wel, RECRESULT *recres, int maxNames, int nInCTB, int16_t *col,
1504
float KOEFF = MAX(1.0f, (w * h) / 250.0f);
1506
for (i = num = 0; i < NumClus; i++, wel++) {
1509
if (!(wel->attr & FON_CLU_SOLID))
1512
// не распознавать себя ?
1514
if (wel->num < 0) // не из нашего алфавита
1517
if (wel->mh * 2 < h || wel->mw * 2 < w)
1510
1522
#ifdef _NOT_ALL_
1515
for(y=-1,k=0;y<=1;y++)
1517
for(x=-1;x<=1;x++,k++)
1519
dist=(int)(distOkr(buf,w,h,wel,x,y,(int)(porog*KOEFF))/KOEFF);
1522
j = distOkr2(razmaz,w+2,h+2,wel,x,y,porog-dist,30);
1533
if( porog == 0 ) break;
1572
case 4: goto addvers;
1524
for (k = 0; k < 9; k++)
1527
for (y = -1, k = 0; y <= 1; y++) {
1528
for (x = -1; x <= 1; x++, k++) {
1529
dist = (int) (distOkr(buf, w, h, wel, x, y, (int) (porog
1533
j = distOkr2(razmaz, w + 2, h + 2, wel, x, y, porog - dist, 30);
1554
startx = starty = -2;
1617
for(x=startx;x!=lastx;x+=stepx)
1619
for(y=starty;y!=lasty;y+=stepy)
1621
dist=(int)(distOkr(buf,w,h,wel,x,y,(int)(porog*KOEFF))/KOEFF);
1624
j = distOkr2(razmaz,w+2,h+2,wel,x,y,porog-dist,30);
1631
if( porog == 0 ) break;
1628
for (x = startx; x != lastx; x += stepx) {
1629
for (y = starty; y != lasty; y += stepy) {
1630
dist = (int) (distOkr(buf, w, h, wel, x, y, (int) (porog
1634
j = distOkr2(razmaz, w + 2, h + 2, wel, x, y, porog - dist, 30);
1648
addvers: if (porog >= 240)
1651
if (num <= 0 || recres[0].prob < 255 - porog) {
1656
num = AddVersion(recres, (uchar) wel->let, (uchar)(255 - porog), i,
1642
if( num <= 0 || recres[0].prob < 255-porog )
1648
num=AddVersion( recres,(BYTE)wel->let,(BYTE)(255-porog),i,
1656
1663
///////////////////////
1657
static int ScaleSymbol(BYTE *inbuf,int fullByte,int allSizeX, int allSizeY,BYTE *outbuf,int newX,int newY);
1660
int RecogCluInner(BYTE *rast,SINT xbyte,SINT xbit,SINT yrow,
1661
RECRESULT *recres, SINT maxNames,
1662
welet *wl,int numWel,
1663
int nInCTB, Int16 *col, Int16 *row )
1666
int rbyte=(xbit+7)>>3;
1668
BYTE hvost=mask0[xbit&7];
1669
Bool32 needCopy=TRUE;
1672
if(wl==NULL || numWel <= 0)
1674
if( xbit <= 0 || yrow <= 0 )
1677
if(xbyte*yrow > REC_MAX_RASTER_SIZE)
1678
yrow=REC_MAX_RASTER_SIZE/xbyte;
1664
static int ScaleSymbol(uchar *inbuf, int fullByte, int allSizeX, int allSizeY,
1665
uchar *outbuf, int newX, int newY);
1667
int RecogCluInner(uchar *rast, int16_t xbyte, int16_t xbit, int16_t yrow,
1668
RECRESULT *recres, int16_t maxNames, welet *wl, int numWel, int nInCTB,
1669
int16_t *col, int16_t *row) {
1671
int rbyte = (xbit + 7) >> 3;
1673
uchar hvost = mask0[xbit & 7];
1674
Bool32 needCopy = TRUE;
1676
if (wl == NULL || numWel <= 0)
1678
if (xbit <= 0 || yrow <= 0)
1681
if (xbyte * yrow > REC_MAX_RASTER_SIZE)
1682
yrow = REC_MAX_RASTER_SIZE / xbyte;
1680
1684
#ifdef _NEED_SCALE_
1682
if( *col > 0 || *row > 0 )
1684
int newX=*col,newY=*row;
1686
if( *col > 0 || *row > 0 )
1688
int newX=*col,newY=*row;
1687
1691
newY = (yrow*newX)/xbit;
1692
// our symbol inside full frame must be STANDARD_HEIGHT
1693
// STANDARD_WIDTH - don't use
1694
newX = (xbit*STANDARD_HEIGHT)/newY;
1695
newY = (yrow*STANDARD_HEIGHT)/newY;
1696
// our symbol inside full frame must be STANDARD_HEIGHT
1697
// STANDARD_WIDTH - don't use
1698
newX = (xbit*STANDARD_HEIGHT)/newY;
1699
newY = (yrow*STANDARD_HEIGHT)/newY;
1697
if( newX != xbit || newY != yrow )
1699
int AddBitmapToSnap(BYTE *buf,int xbit,int yrow,int name,int dist);
1700
i= ScaleSymbol(rast,xbyte,xbit, yrow, buf, newX,newY);
1707
// AddBitmapToSnap(buf,xbit, yrow,0,newY);
1701
if( newX != xbit || newY != yrow )
1703
int AddBitmapToSnap(uchar *buf,int xbit,int yrow,int name,int dist);
1704
i= ScaleSymbol(rast,xbyte,xbit, yrow, buf, newX,newY);
1711
// AddBitmapToSnap(buf,xbit, yrow,0,newY);
1715
for(i=0,b1=buf;i<yrow;i++,b1+=rbyte,rast+=xbyte)
1717
memcpy(b1,rast,rbyte);
1722
Razmaz2(buf,bufrazmaz,xbit,yrow,0,POROG_ANGLES);
1724
if(maxNames > MAX_ALT )
1726
i=LookBestInner(xbit,yrow,buf,bufrazmaz,
1727
numWel,wl,recres, maxNames,nInCTB,col,row);
1718
for (i = 0, b1 = buf; i < yrow; i++, b1 += rbyte, rast += xbyte) {
1719
memcpy(b1, rast, rbyte);
1720
b1[rbyte - 1] &= hvost;
1724
Razmaz2(buf, bufrazmaz, xbit, yrow, 0, POROG_ANGLES);
1726
if (maxNames > MAX_ALT)
1728
i = LookBestInner(xbit, yrow, buf, bufrazmaz, numWel, wl, recres, maxNames,
1731
1733
///////////////////////////
1732
static BYTE *tmpBufScale=NULL;
1734
static uchar *tmpBufScale = NULL;
1736
void EndScale(void) {
1737
1738
free(tmpBufScale);
1739
1740
tmpBufScale = NULL;
1742
static int ScaleSymbol(BYTE *inbuf,int fullByte,int allSizeX, int allSizeY,BYTE *outbuf,int newX,int newY)
1748
int bigStep,oneStep;
1755
if( allSizeX <= 0 || allSizeY <= 0)
1743
static int ScaleSymbol(uchar *inbuf, int fullByte, int allSizeX, int allSizeY,
1744
uchar *outbuf, int newX, int newY) {
1749
int bigStep, oneStep;
1755
if (allSizeX <= 0 || allSizeY <= 0)
1760
if(xbyte*newY > REC_MAX_RASTER_SIZE)
1761
newY=REC_MAX_RASTER_SIZE/xbyte;
1763
allSize = allSizeX*newX*allSizeY*newY;
1764
tmpBufScale=realloc(tmpBufScale,allSize);
1758
xbyte = (newX + 7) >> 3;
1760
if (xbyte * newY > REC_MAX_RASTER_SIZE)
1761
newY = REC_MAX_RASTER_SIZE / xbyte;
1763
allSize = allSizeX * newX * allSizeY * newY;
1764
tmpBufScale = realloc(tmpBufScale, allSize);
1769
memset(tmpBufScale,0,allSize);
1771
bigStep = allSizeX*newX*newY;
1772
oneStep = allSizeX*newX;
1775
for(i=0,tbuf=tmpBufScale;i< allSizeY;i++,tbuf+=bigStep,obuf+=fullByte)
1777
for(j=0,cc=128;j<allSizeX;j++,cc>>=1)
1783
for(k=0,cbuf=tbuf+j*newX;k<newY;k++,cbuf+=oneStep)
1784
memset(cbuf,1,newX);
1769
memset(tmpBufScale, 0, allSize);
1771
bigStep = allSizeX * newX * newY;
1772
oneStep = allSizeX * newX;
1775
for (i = 0, tbuf = tmpBufScale; i < allSizeY; i++, tbuf += bigStep, obuf
1777
for (j = 0, cc = 128; j < allSizeX; j++, cc >>= 1) {
1780
if (obuf[j >> 3] & cc) {
1781
for (k = 0, cbuf = tbuf + j * newX; k < newY; k++, cbuf
1783
memset(cbuf, 1, newX);
1789
memset(outbuf,0,xbyte*newY);
1788
memset(outbuf, 0, xbyte * newY);
1792
bigStep = allSizeX*newX*allSizeY;
1791
bigStep = allSizeX * newX * allSizeY;
1794
for(i=0,tbuf=tmpBufScale;i< newY;i++,tbuf+=bigStep,obuf+=xbyte)
1796
for(j=0,cc=128;j<newX;j++,cc>>=1)
1793
for (i = 0, tbuf = tmpBufScale; i < newY; i++, tbuf += bigStep, obuf
1795
for (j = 0, cc = 128; j < newX; j++, cc >>= 1) {
1801
cbuf = tbuf + j*allSizeX;
1803
for(k=0;k<allSizeY;k++,cbuf+=oneStep)
1805
for(kk=0;kk<allSizeX;kk++)
1799
cbuf = tbuf + j * allSizeX;
1801
for (k = 0; k < allSizeY; k++, cbuf += oneStep) {
1802
for (kk = 0; kk < allSizeX; kk++)
1809
if(summa*2 >= allSizeX*allSizeY )
1806
if (summa * 2 >= allSizeX * allSizeY)