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