File: polyblob.cpp

package info (click to toggle)
tesseract 2.04-2%2Bsqueeze1
  • links: PTS
  • area: main
  • in suites: squeeze
  • size: 7,336 kB
  • ctags: 6,860
  • sloc: cpp: 81,388; sh: 3,446; java: 1,220; makefile: 376
file content (357 lines) | stat: -rw-r--r-- 12,563 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
/**********************************************************************
 * File:        polyblob.cpp  (Formerly blob.c)
 * Description: Code for PBLOB class.
 * Author:		Ray Smith
 * Created:		Wed Oct 23 15:17:41 BST 1991
 *
 * (C) Copyright 1991, Hewlett-Packard Ltd.
 ** Licensed under the Apache License, Version 2.0 (the "License");
 ** you may not use this file except in compliance with the License.
 ** You may obtain a copy of the License at
 ** http://www.apache.org/licenses/LICENSE-2.0
 ** Unless required by applicable law or agreed to in writing, software
 ** distributed under the License is distributed on an "AS IS" BASIS,
 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 ** See the License for the specific language governing permissions and
 ** limitations under the License.
 *
 **********************************************************************/

#include "mfcpch.h"
#include          "varable.h"
#include          "ocrrow.h"
#include          "polyblob.h"
//#include                                                      "lapoly.h"
#include          "polyaprx.h"

#define EXTERN

EXTERN BOOL_VAR (polygon_tess_approximation, TRUE,
"Do tess poly instead of greyscale");

ELISTIZE_S (PBLOB)
/**********************************************************************
 * position_outline
 *
 * Position the outline in the given list at the relevant place
 * according to its nesting.
 **********************************************************************/
static void position_outline(                        //put in place
                             OUTLINE *outline,       //thing to place
                             OUTLINE_LIST *destlist  //desstination list
                            ) {
  OUTLINE *dest_outline;         //outline from dest list
  OUTLINE_IT it = destlist;      //iterator
                                 //iterator on children
  OUTLINE_IT child_it = outline->child ();

  if (!it.empty ()) {
    do {
      dest_outline = it.data (); //get destination
                                 //encloses dest
      if (*dest_outline < *outline) {
                                 //take off list
        dest_outline = it.extract ();
                                 //put this in place
        it.add_after_then_move (outline);
                                 //make it a child
        child_it.add_to_end (dest_outline);
        while (!it.at_last ()) {
          it.forward ();         //do rest of list
                                 //check for other children
          dest_outline = it.data ();
          if (*dest_outline < *outline) {
                                 //take off list
            dest_outline = it.extract ();
            child_it.add_to_end (dest_outline);
            //make it a child
            if (it.empty ())
              break;
          }
        }
        return;                  //finished
      }
                                 //enclosed by dest
      else if (*outline < *dest_outline) {
        position_outline (outline, dest_outline->child ());
        //place in child list
        return;                  //finished
      }
      it.forward ();
    }
    while (!it.at_first ());
  }
  it.add_to_end (outline);       //at outer level
}


/**********************************************************************
 * plot_outline_list
 *
 * Draw a list of outlines in the given colour and their children
 * in the child colour.
 **********************************************************************/

#ifndef GRAPHICS_DISABLED
static void plot_outline_list(                     //draw outlines
                              OUTLINE_LIST *list,  //outline to draw
                              ScrollView* window,       //window to draw in
                              ScrollView::Color colour,       //colour to use
                              ScrollView::Color child_colour  //colour of children
                             ) {
  OUTLINE *outline;              //current outline
  OUTLINE_IT it = list;          //iterator

  for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
    outline = it.data ();
                                 //draw it
    outline->plot (window, colour);
    if (!outline->child ()->empty ())
      plot_outline_list (outline->child (), window,
        child_colour, child_colour);
  }
}
#endif


/**********************************************************************
 * PBLOB::PBLOB
 *
 * Constructor to build a PBLOB from a list of OUTLINEs.
 * The OUTLINEs are not copied so the source list is emptied.
 * The OUTLINEs are nested correctly in the blob.
 **********************************************************************/

PBLOB::PBLOB(                            //constructor
             OUTLINE_LIST *outline_list  //in random order
            ) {
  OUTLINE *outline;              //current outline
  OUTLINE_IT it = outline_list;  //iterator

  while (!it.empty ()) {         //grab the list
    outline = it.extract ();     //get off the list
                                 //put it in place
    position_outline(outline, &outlines);
    if (!it.empty ())
      it.forward ();
  }
}


/**********************************************************************
 * approximate_outline_list
 *
 * Convert a list of outlines to polygonal form.
 **********************************************************************/

static void approximate_outline_list(                          //do list of outlines
                                     C_OUTLINE_LIST *srclist,  //list to convert
                                     OUTLINE_LIST *destlist,   //desstination list
                                     float xheight             //height of line
                                    ) {
  C_OUTLINE *src_outline;        //outline from src list
  OUTLINE *dest_outline;         //result
  C_OUTLINE_IT src_it = srclist; //source iterator
  OUTLINE_IT dest_it = destlist; //iterator

  do {
    src_outline = src_it.data ();
    //              if (polygon_tess_approximation)
    dest_outline = tesspoly_outline (src_outline, xheight);
    //              else
    //                      dest_outline=greypoly_outline(src_outline,xheight);
    if (dest_outline != NULL) {
      dest_it.add_after_then_move (dest_outline);
      if (!src_outline->child ()->empty ())
                                 //do child list
        approximate_outline_list (src_outline->child (), dest_outline->child (), xheight);
    }
    src_it.forward ();
  }
  while (!src_it.at_first ());
}


/**********************************************************************
 * PBLOB::PBLOB
 *
 * Constructor to build a PBLOB from a C_BLOB by polygonal approximation.
 **********************************************************************/

PBLOB::PBLOB(                //constructor
             C_BLOB *cblob,  //compact blob
             float xheight   //height of line
            ) {
  TBOX bbox;                      //bounding box

  if (!cblob->out_list ()->empty ()) {
                                 //get bounding box
    bbox = cblob->bounding_box ();
    if (bbox.height () > xheight)
      xheight = bbox.height ();  //max of line and blob
                                 //copy it
    approximate_outline_list (cblob->out_list (), &outlines, xheight);
  }
}


/**********************************************************************
 * PBLOB::bounding_box
 *
 * Return the bounding box of the blob.
 **********************************************************************/

TBOX PBLOB::bounding_box() {  //bounding box
  OUTLINE *outline;              //current outline
  OUTLINE_IT it = &outlines;     //outlines of blob
  TBOX box;                       //bounding box

  for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
    outline = it.data ();
    box += outline->bounding_box ();
  }
  return box;
}


/**********************************************************************
 * PBLOB::area
 *
 * Return the area of the blob.
 **********************************************************************/

float PBLOB::area() {  //area
  OUTLINE *outline;              //current outline
  OUTLINE_IT it = &outlines;     //outlines of blob
  float total;                   //total area

  total = 0.0f;
  for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
    outline = it.data ();
    total += outline->area ();
  }
  return total;
}


/**********************************************************************
 * PBLOB::baseline_normalise
 *
 * Baseline normalize a blob
 **********************************************************************/

PBLOB *PBLOB::baseline_normalise(                //normalize blob
                                 ROW *row,       //row it came from
                                 DENORM *denorm  //inverse mapping
                                ) {
  TBOX blob_box = bounding_box ();
  float x_centre = (blob_box.left () + blob_box.right ()) / 2.0;
  PBLOB *bn_blob;                //copied blob

  *denorm = DENORM (x_centre, bln_x_height / row->x_height (), row);
  bn_blob = new PBLOB;           //get one
  *bn_blob = *this;              //deep copy
  bn_blob->move (FCOORD (-denorm->origin (), -row->base_line (x_centre)));
  bn_blob->scale (denorm->scale ());
  bn_blob->move (FCOORD (0.0, bln_baseline_offset));
  return bn_blob;
}


/**********************************************************************
 * PBLOB::baseline_denormalise
 *
 * DeBaseline Normalise the blob properly with the given denorm.
 **********************************************************************/

void PBLOB::baseline_denormalise(                      // Tess style BL Norm
                                 const DENORM *denorm  //antidote
                                ) {
  float blob_x_left;           // Left edge of blob.
  TBOX blob_box;                  //blob bounding box

  move(FCOORD (0.0f, 0.0f - bln_baseline_offset));
  blob_box = bounding_box ();
  blob_x_left = blob_box.left ();
  scale (1.0 / denorm->scale_at_x (blob_x_left));
  move (FCOORD (denorm->origin (),
    denorm->yshift_at_x (blob_x_left)));
}


/**********************************************************************
 * PBLOB::move
 *
 * Move PBLOB by vector
 **********************************************************************/

void PBLOB::move(                  // reposition blob
                 const FCOORD vec  // by vector
                ) {
  OUTLINE_IT it(&outlines);  // iterator

  for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ())
    it.data ()->move (vec);      // move each outline
}


/**********************************************************************
 * PBLOB::scale
 *
 * Scale PBLOB by float multiplier
 **********************************************************************/

void PBLOB::scale(               // scale blob
                  const float f  // by multiplier
                 ) {
  OUTLINE_IT it(&outlines);  // iterator

  for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ())
    it.data ()->scale (f);       // scale each outline
}


/**********************************************************************
 * PBLOB::scale
 *
 * Scale PBLOB by float multiplier
 **********************************************************************/

void PBLOB::scale(                  // scale blob
                  const FCOORD vec  // by multiplier
                 ) {
  OUTLINE_IT it(&outlines);  // iterator

  for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ())
    it.data ()->scale (vec);     // scale each outline
}

/**********************************************************************
 * PBLOB::rotate
 *
 * Rotate PBLOB 90 deg anti
 **********************************************************************/

void PBLOB::rotate() {  // Rotate 90 deg anti
  OUTLINE_IT it(&outlines);  // iterator

  for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
    it.data ()->rotate (FCOORD(0.0f, 1.0f));     // rotate each outline
  }
}

/**********************************************************************
 * PBLOB::plot
 *
 * Draw the PBLOB in the given colour.
 **********************************************************************/

#ifndef GRAPHICS_DISABLED
void PBLOB::plot(                     //draw it
                 ScrollView* window,       //window to draw in
                 ScrollView::Color blob_colour,  //main colour
                 ScrollView::Color child_colour  //for holes
                ) {
  plot_outline_list(&outlines, window, blob_colour, child_colour);
}
#endif