Tesseract  3.02
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
edgloop.cpp
Go to the documentation of this file.
1 /**********************************************************************
2  * File: edgloop.c (Formerly edgeloop.c)
3  * Description: Functions to clean up an outline before approximation.
4  * Author: Ray Smith
5  * Created: Tue Mar 26 16:56:25 GMT 1991
6  *
7  * (C) Copyright 1991, Hewlett-Packard Ltd.
8  ** Licensed under the Apache License, Version 2.0 (the "License");
9  ** you may not use this file except in compliance with the License.
10  ** You may obtain a copy of the License at
11  ** http://www.apache.org/licenses/LICENSE-2.0
12  ** Unless required by applicable law or agreed to in writing, software
13  ** distributed under the License is distributed on an "AS IS" BASIS,
14  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  ** See the License for the specific language governing permissions and
16  ** limitations under the License.
17  *
18  **********************************************************************/
19 
20 #include "mfcpch.h"
21 #include "scanedg.h"
22 #include "drawedg.h"
23 #include "edgloop.h"
24 
25 // Include automatically generated configuration file if running autoconf.
26 #ifdef HAVE_CONFIG_H
27 #include "config_auto.h"
28 #endif
29 
30 #define MINEDGELENGTH 8 // min decent length
31 
32 INT_VAR(edges_maxedgelength, 16000, "Max steps in any outline");
33 
34 /**********************************************************************
35  * complete_edge
36  *
37  * Complete the edge by cleaning it up.
38  **********************************************************************/
39 
40 void complete_edge(CRACKEDGE *start, //start of loop
41  C_OUTLINE_IT* outline_it) {
42  ScrollView::Color colour; //colour to draw in
43  inT16 looplength; //steps in loop
44  ICOORD botleft; //bounding box
45  ICOORD topright;
46  C_OUTLINE *outline; //new outline
47 
48  //check length etc.
49  colour = check_path_legal (start);
50 
51  if (colour == ScrollView::RED || colour == ScrollView::BLUE) {
52  looplength = loop_bounding_box (start, botleft, topright);
53  outline = new C_OUTLINE (start, botleft, topright, looplength);
54  //add to list
55  outline_it->add_after_then_move (outline);
56  }
57 }
58 
59 
60 /**********************************************************************
61  * check_path_legal
62  *
63  * Check that the outline is legal for length and for chaincode sum.
64  * The return value is RED for a normal black-inside outline,
65  * BLUE for a white-inside outline, MAGENTA if it is too short,
66  * YELLOW if it is too long, and GREEN if it is illegal.
67  * These colours are used to draw the raw outline.
68  **********************************************************************/
69 
71  CRACKEDGE *start //start of loop
72  ) {
73  int lastchain; //last chain code
74  int chaindiff; //chain code diff
75  inT32 length; //length of loop
76  inT32 chainsum; //sum of chain diffs
77  CRACKEDGE *edgept; //current point
78  const ERRCODE ED_ILLEGAL_SUM = "Illegal sum of chain codes";
79 
80  length = 0;
81  chainsum = 0; //sum of chain codes
82  edgept = start;
83  lastchain = edgept->prev->stepdir; //previous chain code
84  do {
85  length++;
86  if (edgept->stepdir != lastchain) {
87  //chain code difference
88  chaindiff = edgept->stepdir - lastchain;
89  if (chaindiff > 2)
90  chaindiff -= 4;
91  else if (chaindiff < -2)
92  chaindiff += 4;
93  chainsum += chaindiff; //sum differences
94  lastchain = edgept->stepdir;
95  }
96  edgept = edgept->next;
97  }
98  while (edgept != start && length < edges_maxedgelength);
99 
100  if ((chainsum != 4 && chainsum != -4)
101  || edgept != start || length < MINEDGELENGTH) {
102  if (edgept != start) {
103  return ScrollView::YELLOW;
104  } else if (length < MINEDGELENGTH) {
105  return ScrollView::MAGENTA;
106  } else {
107  ED_ILLEGAL_SUM.error ("check_path_legal", TESSLOG, "chainsum=%d",
108  chainsum);
109  return ScrollView::GREEN;
110  }
111  }
112  //colour on inside
113  return chainsum < 0 ? ScrollView::BLUE : ScrollView::RED;
114 }
115 
116 /**********************************************************************
117  * loop_bounding_box
118  *
119  * Find the bounding box of the edge loop.
120  **********************************************************************/
121 
122 inT16 loop_bounding_box( //get bounding box
123  CRACKEDGE *&start, //edge loop
124  ICOORD &botleft, //bounding box
125  ICOORD &topright) {
126  inT16 length; //length of loop
127  inT16 leftmost; //on top row
128  CRACKEDGE *edgept; //current point
129  CRACKEDGE *realstart; //topleft start
130 
131  edgept = start;
132  realstart = start;
133  botleft = topright = ICOORD (edgept->pos.x (), edgept->pos.y ());
134  leftmost = edgept->pos.x ();
135  length = 0; //coutn length
136  do {
137  edgept = edgept->next;
138  if (edgept->pos.x () < botleft.x ())
139  //get bounding box
140  botleft.set_x (edgept->pos.x ());
141  else if (edgept->pos.x () > topright.x ())
142  topright.set_x (edgept->pos.x ());
143  if (edgept->pos.y () < botleft.y ())
144  //get bounding box
145  botleft.set_y (edgept->pos.y ());
146  else if (edgept->pos.y () > topright.y ()) {
147  realstart = edgept;
148  leftmost = edgept->pos.x ();
149  topright.set_y (edgept->pos.y ());
150  }
151  else if (edgept->pos.y () == topright.y ()
152  && edgept->pos.x () < leftmost) {
153  //leftmost on line
154  leftmost = edgept->pos.x ();
155  realstart = edgept;
156  }
157  length++; //count elements
158  }
159  while (edgept != start);
160  start = realstart; //shift it to topleft
161  return length;
162 }