Tesseract
3.02
|
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 }