tesseract  3.03
/usr/local/google/home/jbreiden/tesseract-ocr-read-only/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          "scanedg.h"
00021 #include          "drawedg.h"
00022 #include          "edgloop.h"
00023 
00024 // Include automatically generated configuration file if running autoconf.
00025 #ifdef HAVE_CONFIG_H
00026 #include "config_auto.h"
00027 #endif
00028 
00029 #define MINEDGELENGTH   8        // min decent length
00030 
00031 /**********************************************************************
00032  * complete_edge
00033  *
00034  * Complete the edge by cleaning it up.
00035  **********************************************************************/
00036 
00037 void complete_edge(CRACKEDGE *start,  //start of loop
00038                    C_OUTLINE_IT* outline_it) {
00039   ScrollView::Color colour;                 //colour to draw in
00040   inT16 looplength;              //steps in loop
00041   ICOORD botleft;                //bounding box
00042   ICOORD topright;
00043   C_OUTLINE *outline;            //new outline
00044 
00045                                  //check length etc.
00046   colour = check_path_legal (start);
00047 
00048   if (colour == ScrollView::RED || colour == ScrollView::BLUE) {
00049     looplength = loop_bounding_box (start, botleft, topright);
00050     outline = new C_OUTLINE (start, botleft, topright, looplength);
00051                                  //add to list
00052     outline_it->add_after_then_move (outline);
00053   }
00054 }
00055 
00056 
00057 /**********************************************************************
00058  * check_path_legal
00059  *
00060  * Check that the outline is legal for length and for chaincode sum.
00061  * The return value is RED for a normal black-inside outline,
00062  * BLUE for a white-inside outline, MAGENTA if it is too short,
00063  * YELLOW if it is too long, and GREEN if it is illegal.
00064  * These colours are used to draw the raw outline.
00065  **********************************************************************/
00066 
00067 ScrollView::Color check_path_legal(                  //certify outline
00068                         CRACKEDGE *start  //start of loop
00069                        ) {
00070   int lastchain;              //last chain code
00071   int chaindiff;               //chain code diff
00072   inT32 length;                  //length of loop
00073   inT32 chainsum;                //sum of chain diffs
00074   CRACKEDGE *edgept;             //current point
00075   const ERRCODE ED_ILLEGAL_SUM = "Illegal sum of chain codes";
00076 
00077   length = 0;
00078   chainsum = 0;                  //sum of chain codes
00079   edgept = start;
00080   lastchain = edgept->prev->stepdir; //previous chain code
00081   do {
00082     length++;
00083     if (edgept->stepdir != lastchain) {
00084                                  //chain code difference
00085       chaindiff = edgept->stepdir - lastchain;
00086       if (chaindiff > 2)
00087         chaindiff -= 4;
00088       else if (chaindiff < -2)
00089         chaindiff += 4;
00090       chainsum += chaindiff;     //sum differences
00091       lastchain = edgept->stepdir;
00092     }
00093     edgept = edgept->next;
00094   }
00095   while (edgept != start && length < C_OUTLINE::kMaxOutlineLength);
00096 
00097   if ((chainsum != 4 && chainsum != -4)
00098   || edgept != start || length < MINEDGELENGTH) {
00099     if (edgept != start) {
00100      return ScrollView::YELLOW;
00101     } else if (length < MINEDGELENGTH) {
00102      return ScrollView::MAGENTA;
00103     } else {
00104       ED_ILLEGAL_SUM.error ("check_path_legal", TESSLOG, "chainsum=%d",
00105         chainsum);
00106       return ScrollView::GREEN;
00107     }
00108   }
00109                                  //colour on inside
00110   return chainsum < 0 ? ScrollView::BLUE : ScrollView::RED;
00111 }
00112 
00113 /**********************************************************************
00114  * loop_bounding_box
00115  *
00116  * Find the bounding box of the edge loop.
00117  **********************************************************************/
00118 
00119 inT16 loop_bounding_box(                    //get bounding box
00120                         CRACKEDGE *&start,  //edge loop
00121                         ICOORD &botleft,    //bounding box
00122                         ICOORD &topright) {
00123   inT16 length;                  //length of loop
00124   inT16 leftmost;                //on top row
00125   CRACKEDGE *edgept;             //current point
00126   CRACKEDGE *realstart;          //topleft start
00127 
00128   edgept = start;
00129   realstart = start;
00130   botleft = topright = ICOORD (edgept->pos.x (), edgept->pos.y ());
00131   leftmost = edgept->pos.x ();
00132   length = 0;                    //coutn length
00133   do {
00134     edgept = edgept->next;
00135     if (edgept->pos.x () < botleft.x ())
00136                                  //get bounding box
00137       botleft.set_x (edgept->pos.x ());
00138     else if (edgept->pos.x () > topright.x ())
00139       topright.set_x (edgept->pos.x ());
00140     if (edgept->pos.y () < botleft.y ())
00141                                  //get bounding box
00142       botleft.set_y (edgept->pos.y ());
00143     else if (edgept->pos.y () > topright.y ()) {
00144       realstart = edgept;
00145       leftmost = edgept->pos.x ();
00146       topright.set_y (edgept->pos.y ());
00147     }
00148     else if (edgept->pos.y () == topright.y ()
00149     && edgept->pos.x () < leftmost) {
00150                                  //leftmost on line
00151       leftmost = edgept->pos.x ();
00152       realstart = edgept;
00153     }
00154     length++;                    //count elements
00155   }
00156   while (edgept != start);
00157   start = realstart;             //shift it to topleft
00158   return length;
00159 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines