/src/tesseract/src/textord/blkocc.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /***************************************************************************** |
2 | | * |
3 | | * File: blkocc.cpp (Formerly blockocc.c) |
4 | | * Description: Block Occupancy routines |
5 | | * Author: Chris Newton |
6 | | * |
7 | | * (c) Copyright 1991, Hewlett-Packard Company. |
8 | | ** Licensed under the Apache License, Version 2.0 (the "License"); |
9 | | ** you may not use this file except in compliance with the License. |
10 | | ** You may obtain a copy of the License at |
11 | | ** http://www.apache.org/licenses/LICENSE-2.0 |
12 | | ** Unless required by applicable law or agreed to in writing, software |
13 | | ** distributed under the License is distributed on an "AS IS" BASIS, |
14 | | ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
15 | | ** See the License for the specific language governing permissions and |
16 | | ** limitations under the License. |
17 | | * |
18 | | ******************************************************************************/ |
19 | | |
20 | | #include "blkocc.h" |
21 | | |
22 | | #include "drawtord.h" |
23 | | #include "errcode.h" |
24 | | |
25 | | #include <cctype> |
26 | | #include <cmath> |
27 | | |
28 | | #include "helpers.h" |
29 | | |
30 | | namespace tesseract { |
31 | | |
32 | | double_VAR(textord_underline_threshold, 0.5, "Fraction of width occupied"); |
33 | | |
34 | | // Forward declarations of static functions |
35 | | static void horizontal_cblob_projection(C_BLOB *blob, // blob to project |
36 | | STATS *stats); // output |
37 | | static void horizontal_coutline_projection(C_OUTLINE *outline, |
38 | | STATS *stats); // output |
39 | | |
40 | | /** |
41 | | * test_underline |
42 | | * |
43 | | * Check to see if the blob is an underline. |
44 | | * Return true if it is. |
45 | | */ |
46 | | |
47 | | bool test_underline( // look for underlines |
48 | | bool testing_on, ///< drawing blob |
49 | | C_BLOB *blob, ///< blob to test |
50 | | int16_t baseline, ///< coords of baseline |
51 | | int16_t xheight ///< height of line |
52 | 63.9k | ) { |
53 | 63.9k | TDimension occ; |
54 | 63.9k | STATS projection; |
55 | | |
56 | 63.9k | auto blob_box = blob->bounding_box(); |
57 | 63.9k | auto blob_width = blob->bounding_box().width(); |
58 | 63.9k | projection.set_range(blob_box.bottom(), blob_box.top()); |
59 | 63.9k | if (testing_on) { |
60 | | // blob->plot(to_win,GOLDENROD,GOLDENROD); |
61 | | // line_color_index(to_win,GOLDENROD); |
62 | | // move2d(to_win,blob_box.left(),baseline); |
63 | | // draw2d(to_win,blob_box.right(),baseline); |
64 | | // move2d(to_win,blob_box.left(),baseline+xheight); |
65 | | // draw2d(to_win,blob_box.right(),baseline+xheight); |
66 | 0 | tprintf("Testing underline on blob at (%d,%d)->(%d,%d), base=%d\nOccs:", |
67 | 0 | blob->bounding_box().left(), blob->bounding_box().bottom(), |
68 | 0 | blob->bounding_box().right(), blob->bounding_box().top(), baseline); |
69 | 0 | } |
70 | 63.9k | horizontal_cblob_projection(blob, &projection); |
71 | 63.9k | int32_t desc_occ = 0; |
72 | 344k | for (occ = blob_box.bottom(); occ < baseline; occ++) { |
73 | 280k | if (occ <= blob_box.top() && projection.pile_count(occ) > desc_occ) { |
74 | | // max in region |
75 | 56.5k | desc_occ = projection.pile_count(occ); |
76 | 56.5k | } |
77 | 280k | } |
78 | 63.9k | int32_t x_occ = 0; |
79 | 447k | for (occ = baseline; occ <= baseline + xheight; occ++) { |
80 | 383k | if (occ >= blob_box.bottom() && occ <= blob_box.top() && projection.pile_count(occ) > x_occ) { |
81 | | // max in region |
82 | 83.9k | x_occ = projection.pile_count(occ); |
83 | 83.9k | } |
84 | 383k | } |
85 | 63.9k | int32_t asc_occ = 0; |
86 | 795k | for (occ = baseline + xheight + 1; occ <= blob_box.top(); occ++) { |
87 | 731k | if (occ >= blob_box.bottom() && projection.pile_count(occ) > asc_occ) { |
88 | 62.8k | asc_occ = projection.pile_count(occ); |
89 | 62.8k | } |
90 | 731k | } |
91 | 63.9k | if (testing_on) { |
92 | 0 | tprintf("%d %d %d\n", desc_occ, x_occ, asc_occ); |
93 | 0 | } |
94 | 63.9k | if (desc_occ == 0 && x_occ == 0 && asc_occ == 0) { |
95 | 0 | tprintf("Bottom=%d, top=%d, base=%d, x=%d\n", blob_box.bottom(), blob_box.top(), baseline, |
96 | 0 | xheight); |
97 | 0 | projection.print(); |
98 | 0 | } |
99 | 63.9k | if (desc_occ > x_occ + x_occ && desc_occ > blob_width * textord_underline_threshold) { |
100 | 15.0k | return true; // real underline |
101 | 15.0k | } |
102 | 48.8k | return asc_occ > x_occ + x_occ && asc_occ > blob_width * textord_underline_threshold; // overline |
103 | | // neither |
104 | 63.9k | } |
105 | | |
106 | | /** |
107 | | * horizontal_cblob_projection |
108 | | * |
109 | | * Compute the horizontal projection of a cblob from its outlines |
110 | | * and add to the given STATS. |
111 | | */ |
112 | | |
113 | | static void horizontal_cblob_projection( // project outlines |
114 | | C_BLOB *blob, ///< blob to project |
115 | | STATS *stats ///< output |
116 | 63.9k | ) { |
117 | | // outlines of blob |
118 | 63.9k | C_OUTLINE_IT out_it = blob->out_list(); |
119 | | |
120 | 127k | for (out_it.mark_cycle_pt(); !out_it.cycled_list(); out_it.forward()) { |
121 | 63.9k | horizontal_coutline_projection(out_it.data(), stats); |
122 | 63.9k | } |
123 | 63.9k | } |
124 | | |
125 | | /** |
126 | | * horizontal_coutline_projection |
127 | | * |
128 | | * Compute the horizontal projection of an outline from its outlines |
129 | | * and add to the given STATS. |
130 | | */ |
131 | | |
132 | | static void horizontal_coutline_projection( // project outlines |
133 | | C_OUTLINE *outline, ///< outline to project |
134 | | STATS *stats ///< output |
135 | 63.9k | ) { |
136 | 63.9k | ICOORD pos; // current point |
137 | 63.9k | ICOORD step; // edge step |
138 | 63.9k | int32_t length; // of outline |
139 | 63.9k | int16_t stepindex; // current step |
140 | 63.9k | C_OUTLINE_IT out_it = outline->child(); |
141 | | |
142 | 63.9k | pos = outline->start_pos(); |
143 | 63.9k | length = outline->pathlength(); |
144 | 17.3M | for (stepindex = 0; stepindex < length; stepindex++) { |
145 | 17.3M | step = outline->step(stepindex); |
146 | 17.3M | if (step.y() > 0) { |
147 | 2.62M | stats->add(pos.y(), pos.x()); |
148 | 14.6M | } else if (step.y() < 0) { |
149 | 2.62M | stats->add(pos.y() - 1, -pos.x()); |
150 | 2.62M | } |
151 | 17.3M | pos += step; |
152 | 17.3M | } |
153 | | |
154 | 63.9k | for (out_it.mark_cycle_pt(); !out_it.cycled_list(); out_it.forward()) { |
155 | 0 | horizontal_coutline_projection(out_it.data(), stats); |
156 | 0 | } |
157 | 63.9k | } |
158 | | |
159 | | } // namespace tesseract |