25#include <allheaders.h>
34#define FLIP_COLOUR(pix) (1 - (pix))
42static void free_crackedges(
CRACKEDGE *start);
45 C_OUTLINE_IT *outline_it);
50static void make_margins(
PDBLK *block,
BLOCK_LINE_IT *line_it, uint8_t *pixels, uint8_t margin,
64 C_OUTLINE_IT *outline_it) {
69 int width = pixGetWidth(t_pix);
70 int height = pixGetHeight(t_pix);
71 int wpl = pixGetWpl(t_pix);
73 std::unique_ptr<CRACKEDGE *[]> ptrline(
new CRACKEDGE *[width + 1]);
79 int block_width = tright.
x() - bleft.
x();
80 for (
int x = block_width;
x >= 0;
x--) {
84 std::unique_ptr<uint8_t[]> bwline(
new uint8_t[width]);
88 for (
int y = tright.
y() - 1;
y >= bleft.
y() - 1;
y--) {
89 if (
y >= bleft.
y() &&
y < tright.
y()) {
91 l_uint32 *line = pixGetData(t_pix) + wpl * (height - 1 -
y);
92 for (
int x = 0;
x < block_width; ++
x) {
93 bwline[
x] = GET_DATA_BIT(line,
x + bleft.
x()) ^ 1;
95 make_margins(block, &line_it, bwline.get(), margin, bleft.
x(), tright.
x(),
y);
97 memset(bwline.get(), margin, block_width *
sizeof(bwline[0]));
99 line_edges(bleft.
x(),
y, block_width, margin, bwline.get(), ptrline.get(), &free_cracks,
103 free_crackedges(free_cracks);
112static void make_margins(
114 BLOCK_LINE_IT *line_it,
123 if (block->poly_block() !=
nullptr) {
124 std::unique_ptr<PB_LINE_IT> lines(
new PB_LINE_IT(block->poly_block()));
125 const std::unique_ptr< ICOORDELT_LIST> segments(lines->get_line(
y));
126 if (!segments->empty()) {
127 seg_it.set_to_list(segments.get());
128 seg_it.mark_cycle_pt();
129 auto start = seg_it.data()->x();
130 auto xext = seg_it.data()->y();
131 for (
auto xindex = left; xindex < right; xindex++) {
132 if (xindex >= start && !seg_it.cycled_list()) {
133 xindex = start + xext - 1;
135 start = seg_it.data()->x();
136 xext = seg_it.data()->y();
138 pixels[xindex - left] = margin;
142 for (
auto xindex = left; xindex < right; xindex++) {
143 pixels[xindex - left] = margin;
148 auto start = line_it->get_line(
y, xext);
149 for (
auto xindex = left; xindex < start; xindex++) {
150 pixels[xindex - left] = margin;
152 for (
auto xindex = start + xext; xindex < right; xindex++) {
153 pixels[xindex - left] = margin;
170 CRACKEDGE **prevline,
171 CRACKEDGE **free_cracks, C_OUTLINE_IT *outline_it) {
172 CrackPos pos = {free_cracks,
x,
y};
176 CRACKEDGE *newcurrent;
179 prevcolour = uppercolour;
183 for (; pos.x < xmax; pos.x++, prevline++) {
184 const int colour = *bwpos++;
185 if (*prevline !=
nullptr) {
189 if (colour == prevcolour) {
190 if (colour == uppercolour) {
192 join_edges(current, *prevline, free_cracks, outline_it);
196 current = h_edge(uppercolour - colour, *prevline, &pos);
200 if (colour == uppercolour) {
201 *prevline = v_edge(colour - prevcolour, *prevline, &pos);
204 join_edges(current, *prevline, free_cracks, outline_it);
205 current = h_edge(uppercolour - colour,
nullptr, &pos);
206 *prevline = v_edge(colour - prevcolour, current, &pos);
208 newcurrent = h_edge(uppercolour - colour, *prevline, &pos);
209 *prevline = v_edge(colour - prevcolour, current, &pos);
210 current = newcurrent;
215 if (colour != prevcolour) {
216 *prevline = current = v_edge(colour - prevcolour, current, &pos);
219 if (colour != uppercolour) {
220 current = h_edge(uppercolour - colour, current, &pos);
226 if (current !=
nullptr) {
228 if (*prevline !=
nullptr) {
229 join_edges(current, *prevline, free_cracks, outline_it);
233 *prevline = v_edge(
FLIP_COLOUR(prevcolour) - prevcolour, current, &pos);
235 }
else if (*prevline !=
nullptr) {
237 *prevline = v_edge(
FLIP_COLOUR(prevcolour) - prevcolour, *prevline, &pos);
247static CRACKEDGE *h_edge(
int sign,
252 if (*pos->free_cracks !=
nullptr) {
253 newpt = *pos->free_cracks;
254 *pos->free_cracks = newpt->
next;
256 newpt =
new CRACKEDGE;
262 newpt->pos.set_x(pos->x + 1);
266 newpt->pos.set_x(pos->x);
271 if (join ==
nullptr) {
275 if (newpt->pos.x() + newpt->stepx == join->pos.x() && newpt->pos.y() == join->pos.y()) {
276 newpt->prev = join->prev;
277 newpt->prev->next = newpt;
281 newpt->next = join->next;
282 newpt->next->prev = newpt;
296static CRACKEDGE *v_edge(
int sign,
297 CRACKEDGE *join, CrackPos *pos) {
300 if (*pos->free_cracks !=
nullptr) {
301 newpt = *pos->free_cracks;
302 *pos->free_cracks = newpt->
next;
304 newpt =
new CRACKEDGE;
310 newpt->pos.set_y(pos->y);
314 newpt->pos.set_y(pos->y + 1);
319 if (join ==
nullptr) {
323 if (newpt->pos.x() == join->pos.x() && newpt->pos.y() + newpt->stepy == join->pos.y()) {
324 newpt->prev = join->prev;
325 newpt->prev->next = newpt;
329 newpt->next = join->next;
330 newpt->next->prev = newpt;
345static void join_edges(CRACKEDGE *edge1,
347 CRACKEDGE **free_cracks, C_OUTLINE_IT *outline_it) {
348 if (edge1->pos.x() + edge1->stepx != edge2->pos.x() ||
349 edge1->pos.y() + edge1->stepy != edge2->pos.y()) {
350 CRACKEDGE *tempedge = edge1;
355 if (edge1->next == edge2) {
359 edge1->prev->next = *free_cracks;
360 *free_cracks = edge1;
363 edge2->prev->next = edge1->next;
364 edge1->next->prev = edge2->prev;
376static void free_crackedges(CRACKEDGE *start) {
380 for (current = start; current !=
nullptr; current =
next) {
381 next = current->next;
void complete_edge(CRACKEDGE *start, C_OUTLINE_IT *outline_it)
void block_edges(Image t_pix, PDBLK *block, C_OUTLINE_IT *outline_it)
void bounding_box(ICOORD &bottom_left, ICOORD &top_right) const
get box
void set_x(TDimension xin)
rewrite function
TDimension y() const
access_function
void set_y(TDimension yin)
rewrite function
TDimension x() const
access function