1 /* -*-C-*-
2 ********************************************************************************
3 *
4 * File: blobs.c (Formerly blobs.c)
5 * Description: Blob definition
6 * Author: Mark Seaman, OCR Technology
7 * Created: Fri Oct 27 15:39:52 1989
8 * Modified: Thu Mar 28 15:33:26 1991 (Mark Seaman) marks@hpgrlt
9 * Language: C
10 * Package: N/A
11 * Status: Experimental (Do Not Distribute)
12 *
13 * (c) Copyright 1989, Hewlett-Packard Company.
14 ** Licensed under the Apache License, Version 2.0 (the "License");
15 ** you may not use this file except in compliance with the License.
16 ** You may obtain a copy of the License at
17 ** http://www.apache.org/licenses/LICENSE-2.0
18 ** Unless required by applicable law or agreed to in writing, software
19 ** distributed under the License is distributed on an "AS IS" BASIS,
20 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 ** See the License for the specific language governing permissions and
22 ** limitations under the License.
23 *
24 *********************************************************************************/
25
26 /*----------------------------------------------------------------------
27 I n c l u d e s
28 ----------------------------------------------------------------------*/
29 #include "mfcpch.h"
30 #include "blobs.h"
31 #include "cutil.h"
32 #include "emalloc.h"
33 #include "structures.h"
34
35 /*----------------------------------------------------------------------
36 F u n c t i o n s
37 ----------------------------------------------------------------------*/
38 /**********************************************************************
39 * blob_origin
40 *
41 * Compute the origin of a compound blob, define to be the centre
42 * of the bounding box.
43 **********************************************************************/
blob_origin(TBLOB * blob,TPOINT * origin)44 void blob_origin(TBLOB *blob, /*blob to compute on */
45 TPOINT *origin) { /*return value */
46 TPOINT topleft; /*bounding box */
47 TPOINT botright;
48
49 /*find bounding box */
50 blob_bounding_box(blob, &topleft, &botright);
51 /*centre of box */
52 origin->x = (topleft.x + botright.x) / 2;
53 origin->y = (topleft.y + botright.y) / 2;
54 }
55
56
57 /**********************************************************************
58 * blob_bounding_box
59 *
60 * Compute the bounding_box of a compound blob, define to be the
61 * max coordinate value of the bounding boxes of all the top-level
62 * outlines in the box.
63 **********************************************************************/
blob_bounding_box(TBLOB * blob,register TPOINT * topleft,register TPOINT * botright)64 void blob_bounding_box(TBLOB *blob, /*blob to compute on */
65 register TPOINT *topleft, /*bounding box */
66 register TPOINT *botright) {
67 register TESSLINE *outline; /*current outline */
68
69 if (blob == NULL || blob->outlines == NULL) {
70 topleft->x = topleft->y = 0;
71 *botright = *topleft; /*default value */
72 }
73 else {
74 outline = blob->outlines;
75 *topleft = outline->topleft;
76 *botright = outline->botright;
77 for (outline = outline->next; outline != NULL; outline = outline->next) {
78 if (outline->topleft.x < topleft->x)
79 /*find extremes */
80 topleft->x = outline->topleft.x;
81 if (outline->botright.x > botright->x)
82 /*find extremes */
83 botright->x = outline->botright.x;
84 if (outline->topleft.y > topleft->y)
85 /*find extremes */
86 topleft->y = outline->topleft.y;
87 if (outline->botright.y < botright->y)
88 /*find extremes */
89 botright->y = outline->botright.y;
90 }
91 }
92 }
93
94
95 /**********************************************************************
96 * blobs_bounding_box
97 *
98 * Return the smallest extreme point that contain this word.
99 **********************************************************************/
blobs_bounding_box(TBLOB * blobs,TPOINT * topleft,TPOINT * botright)100 void blobs_bounding_box(TBLOB *blobs, TPOINT *topleft, TPOINT *botright) {
101 TPOINT tl;
102 TPOINT br;
103 TBLOB *blob;
104 /* Start with first blob */
105 blob_bounding_box(blobs, topleft, botright);
106
107 iterate_blobs(blob, blobs) {
108 blob_bounding_box(blob, &tl, &br);
109
110 if (tl.x < topleft->x)
111 topleft->x = tl.x;
112 if (tl.y > topleft->y)
113 topleft->y = tl.y;
114 if (br.x > botright->x)
115 botright->x = br.x;
116 if (br.y < botright->y)
117 botright->y = br.y;
118 }
119 }
120
121
122 /**********************************************************************
123 * blobs_origin
124 *
125 * Compute the origin of a compound blob, define to be the centre
126 * of the bounding box.
127 **********************************************************************/
blobs_origin(TBLOB * blobs,TPOINT * origin)128 void blobs_origin(TBLOB *blobs, /*blob to compute on */
129 TPOINT *origin) { /*return value */
130 TPOINT topleft; /*bounding box */
131 TPOINT botright;
132
133 /*find bounding box */
134 blobs_bounding_box(blobs, &topleft, &botright);
135 /*center of box */
136 origin->x = (topleft.x + botright.x) / 2;
137 origin->y = (topleft.y + botright.y) / 2;
138 }
139
140
141 /**********************************************************************
142 * blobs_widths
143 *
144 * Compute the widths of a list of blobs. Return an array of the widths
145 * and gaps.
146 **********************************************************************/
blobs_widths(TBLOB * blobs)147 WIDTH_RECORD *blobs_widths(TBLOB *blobs) { /*blob to compute on */
148 WIDTH_RECORD *width_record;
149 TPOINT topleft; /*bounding box */
150 TPOINT botright;
151 TBLOB *blob; /*blob to compute on */
152 int i = 0;
153 int blob_end;
154 int num_blobs = count_blobs (blobs);
155
156 /* Get memory */
157 width_record = (WIDTH_RECORD *) memalloc (sizeof (int) * num_blobs * 2);
158 width_record->num_chars = num_blobs;
159
160 blob_bounding_box(blobs, &topleft, &botright);
161 width_record->widths[i++] = botright.x - topleft.x;
162 /* First width */
163 blob_end = botright.x;
164
165 iterate_blobs (blob, blobs->next) {
166 blob_bounding_box(blob, &topleft, &botright);
167 width_record->widths[i++] = topleft.x - blob_end;
168 width_record->widths[i++] = botright.x - topleft.x;
169 blob_end = botright.x;
170 }
171 return (width_record);
172 }
173
174
175 /**********************************************************************
176 * count_blobs
177 *
178 * Return a count of the number of blobs attached to this one.
179 **********************************************************************/
count_blobs(TBLOB * blobs)180 int count_blobs(TBLOB *blobs) {
181 TBLOB *b;
182 int x = 0;
183
184 iterate_blobs (b, blobs) x++;
185 return (x);
186 }
187
188
189 /**********************************************************************
190 * delete_word
191 *
192 * Reclaim the memory taken by this word structure and all of its
193 * lower level structures.
194 **********************************************************************/
delete_word(TWERD * word)195 void delete_word(TWERD *word) {
196 TBLOB *blob;
197 TBLOB *nextblob;
198 TESSLINE *outline;
199 TESSLINE *nextoutline;
200 TESSLINE *child;
201 TESSLINE *nextchild;
202
203 for (blob = word->blobs; blob; blob = nextblob) {
204 nextblob = blob->next;
205
206 for (outline = blob->outlines; outline; outline = nextoutline) {
207 nextoutline = outline->next;
208
209 delete_edgepts (outline->loop);
210
211 for (child = outline->child; child; child = nextchild) {
212 nextchild = child->next;
213
214 delete_edgepts (child->loop);
215
216 oldoutline(child);
217 }
218 oldoutline(outline);
219 }
220 oldblob(blob);
221 }
222 if (word->correct != NULL)
223 strfree (word->correct); /* Reclaim memory */
224 oldword(word);
225 }
226
227
228 /**********************************************************************
229 * delete_edgepts
230 *
231 * Delete a list of EDGEPT structures.
232 **********************************************************************/
delete_edgepts(register EDGEPT * edgepts)233 void delete_edgepts(register EDGEPT *edgepts) {
234 register EDGEPT *this_edge;
235 register EDGEPT *next_edge;
236
237 if (edgepts == NULL)
238 return;
239
240 this_edge = edgepts;
241 do {
242 next_edge = this_edge->next;
243 oldedgept(this_edge);
244 this_edge = next_edge;
245 }
246 while (this_edge != edgepts);
247 }
248