Tesseract  3.02
tesseract-ocr/textord/edgloop.cpp
Go to the documentation of this file.
00001 /**********************************************************************
00002  * File:        edgloop.c  (Formerly edgeloop.c)
00003  * Description: Functions to clean up an outline before approximation.
00004  * Author:                                      Ray Smith
00005  * Created:                                     Tue Mar 26 16:56:25 GMT 1991
00006  *
00007  * (C) Copyright 1991, Hewlett-Packard Ltd.
00008  ** Licensed under the Apache License, Version 2.0 (the "License");
00009  ** you may not use this file except in compliance with the License.
00010  ** You may obtain a copy of the License at
00011  ** http://www.apache.org/licenses/LICENSE-2.0
00012  ** Unless required by applicable law or agreed to in writing, software
00013  ** distributed under the License is distributed on an "AS IS" BASIS,
00014  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015  ** See the License for the specific language governing permissions and
00016  ** limitations under the License.
00017  *
00018  **********************************************************************/
00019 
00020 #include "mfcpch.h"
00021 #include          "scanedg.h"
00022 #include          "drawedg.h"
00023 #include          "edgloop.h"
00024 
00025 // Include automatically generated configuration file if running autoconf.
00026 #ifdef HAVE_CONFIG_H
00027 #include "config_auto.h"
00028 #endif
00029 
00030 #define MINEDGELENGTH   8        // min decent length
00031 
00032 INT_VAR(edges_maxedgelength, 16000, "Max steps in any outline");
00033 
00034 /**********************************************************************
00035  * complete_edge
00036  *
00037  * Complete the edge by cleaning it up.
00038  **********************************************************************/
00039 
00040 void complete_edge(CRACKEDGE *start,  //start of loop
00041                    C_OUTLINE_IT* outline_it) {
00042   ScrollView::Color colour;                 //colour to draw in
00043   inT16 looplength;              //steps in loop
00044   ICOORD botleft;                //bounding box
00045   ICOORD topright;
00046   C_OUTLINE *outline;            //new outline
00047 
00048                                  //check length etc.
00049   colour = check_path_legal (start);
00050 
00051   if (colour == ScrollView::RED || colour == ScrollView::BLUE) {
00052     looplength = loop_bounding_box (start, botleft, topright);
00053     outline = new C_OUTLINE (start, botleft, topright, looplength);
00054                                  //add to list
00055     outline_it->add_after_then_move (outline);
00056   }
00057 }
00058 
00059 
00060 /**********************************************************************
00061  * check_path_legal
00062  *
00063  * Check that the outline is legal for length and for chaincode sum.
00064  * The return value is RED for a normal black-inside outline,
00065  * BLUE for a white-inside outline, MAGENTA if it is too short,
00066  * YELLOW if it is too long, and GREEN if it is illegal.
00067  * These colours are used to draw the raw outline.
00068  **********************************************************************/
00069 
00070 ScrollView::Color check_path_legal(                  //certify outline
00071                         CRACKEDGE *start  //start of loop
00072                        ) {
00073   int lastchain;              //last chain code
00074   int chaindiff;               //chain code diff
00075   inT32 length;                  //length of loop
00076   inT32 chainsum;                //sum of chain diffs
00077   CRACKEDGE *edgept;             //current point
00078   const ERRCODE ED_ILLEGAL_SUM = "Illegal sum of chain codes";
00079 
00080   length = 0;
00081   chainsum = 0;                  //sum of chain codes
00082   edgept = start;
00083   lastchain = edgept->prev->stepdir; //previous chain code
00084   do {
00085     length++;
00086     if (edgept->stepdir != lastchain) {
00087                                  //chain code difference
00088       chaindiff = edgept->stepdir - lastchain;
00089       if (chaindiff > 2)
00090         chaindiff -= 4;
00091       else if (chaindiff < -2)
00092         chaindiff += 4;
00093       chainsum += chaindiff;     //sum differences
00094       lastchain = edgept->stepdir;
00095     }
00096     edgept = edgept->next;
00097   }
00098   while (edgept != start && length < edges_maxedgelength);
00099 
00100   if ((chainsum != 4 && chainsum != -4)
00101   || edgept != start || length < MINEDGELENGTH) {
00102     if (edgept != start) {
00103      return ScrollView::YELLOW;
00104     } else if (length < MINEDGELENGTH) {
00105      return ScrollView::MAGENTA;
00106     } else {
00107       ED_ILLEGAL_SUM.error ("check_path_legal", TESSLOG, "chainsum=%d",
00108         chainsum);
00109       return ScrollView::GREEN;
00110     }
00111   }
00112                                  //colour on inside
00113   return chainsum < 0 ? ScrollView::BLUE : ScrollView::RED;
00114 }
00115 
00116 /**********************************************************************
00117  * loop_bounding_box
00118  *
00119  * Find the bounding box of the edge loop.
00120  **********************************************************************/
00121 
00122 inT16 loop_bounding_box(                    //get bounding box
00123                         CRACKEDGE *&start,  //edge loop
00124                         ICOORD &botleft,    //bounding box
00125                         ICOORD &topright) {
00126   inT16 length;                  //length of loop
00127   inT16 leftmost;                //on top row
00128   CRACKEDGE *edgept;             //current point
00129   CRACKEDGE *realstart;          //topleft start
00130 
00131   edgept = start;
00132   realstart = start;
00133   botleft = topright = ICOORD (edgept->pos.x (), edgept->pos.y ());
00134   leftmost = edgept->pos.x ();
00135   length = 0;                    //coutn length
00136   do {
00137     edgept = edgept->next;
00138     if (edgept->pos.x () < botleft.x ())
00139                                  //get bounding box
00140       botleft.set_x (edgept->pos.x ());
00141     else if (edgept->pos.x () > topright.x ())
00142       topright.set_x (edgept->pos.x ());
00143     if (edgept->pos.y () < botleft.y ())
00144                                  //get bounding box
00145       botleft.set_y (edgept->pos.y ());
00146     else if (edgept->pos.y () > topright.y ()) {
00147       realstart = edgept;
00148       leftmost = edgept->pos.x ();
00149       topright.set_y (edgept->pos.y ());
00150     }
00151     else if (edgept->pos.y () == topright.y ()
00152     && edgept->pos.x () < leftmost) {
00153                                  //leftmost on line
00154       leftmost = edgept->pos.x ();
00155       realstart = edgept;
00156     }
00157     length++;                    //count elements
00158   }
00159   while (edgept != start);
00160   start = realstart;             //shift it to topleft
00161   return length;
00162 }