tesseract
3.03
|
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 }