tesseract  4.0.0-1-g2a2b
scanedg.cpp File Reference
#include "scanedg.h"
#include <memory>
#include "allheaders.h"
#include "edgloop.h"

Go to the source code of this file.

Macros

#define WHITE_PIX   1 /*thresholded colours */
 
#define BLACK_PIX   0
 
#define FLIP_COLOUR(pix)   (1-(pix))
 

Functions

void block_edges (Pix *t_pix, PDBLK *block, C_OUTLINE_IT *outline_it)
 
void make_margins (PDBLK *block, BLOCK_LINE_IT *line_it, uint8_t *pixels, uint8_t margin, int16_t left, int16_t right, int16_t y)
 
void line_edges (int16_t x, int16_t y, int16_t xext, uint8_t uppercolour, uint8_t *bwpos, CRACKEDGE **prevline, CRACKEDGE **free_cracks, C_OUTLINE_IT *outline_it)
 
CRACKEDGEh_edge (int sign, CRACKEDGE *join, CrackPos *pos)
 
CRACKEDGEv_edge (int sign, CRACKEDGE *join, CrackPos *pos)
 
void join_edges (CRACKEDGE *edge1, CRACKEDGE *edge2, CRACKEDGE **free_cracks, C_OUTLINE_IT *outline_it)
 
void free_crackedges (CRACKEDGE *start)
 

Macro Definition Documentation

◆ BLACK_PIX

#define BLACK_PIX   0

Definition at line 27 of file scanedg.cpp.

◆ FLIP_COLOUR

#define FLIP_COLOUR (   pix)    (1-(pix))

Definition at line 29 of file scanedg.cpp.

◆ WHITE_PIX

#define WHITE_PIX   1 /*thresholded colours */

Definition at line 26 of file scanedg.cpp.

Function Documentation

◆ block_edges()

void block_edges ( Pix *  t_pix,
PDBLK block,
C_OUTLINE_IT *  outline_it 
)

Definition at line 37 of file scanedg.cpp.

39  {
40  ICOORD bleft; // bounding box
41  ICOORD tright;
42  BLOCK_LINE_IT line_it = block; // line iterator
43 
44  int width = pixGetWidth(t_pix);
45  int height = pixGetHeight(t_pix);
46  int wpl = pixGetWpl(t_pix);
47  // lines in progress
48  std::unique_ptr<CRACKEDGE*[]> ptrline(new CRACKEDGE*[width + 1]);
49  CRACKEDGE *free_cracks = nullptr;
50 
51  block->bounding_box(bleft, tright); // block box
52  ASSERT_HOST(tright.x() <= width);
53  ASSERT_HOST(tright.y() <= height);
54  int block_width = tright.x() - bleft.x();
55  for (int x = block_width; x >= 0; x--)
56  ptrline[x] = nullptr; // no lines in progress
57 
58  std::unique_ptr<uint8_t[]> bwline(new uint8_t[width]);
59 
60  uint8_t margin = WHITE_PIX;
61 
62  for (int y = tright.y() - 1; y >= bleft.y() - 1; y--) {
63  if (y >= bleft.y() && y < tright.y()) {
64  // Get the binary pixels from the image.
65  l_uint32* line = pixGetData(t_pix) + wpl * (height - 1 - y);
66  for (int x = 0; x < block_width; ++x) {
67  bwline[x] = GET_DATA_BIT(line, x + bleft.x()) ^ 1;
68  }
69  make_margins(block, &line_it, bwline.get(), margin, bleft.x(), tright.x(), y);
70  } else {
71  memset(bwline.get(), margin, block_width * sizeof(bwline[0]));
72  }
73  line_edges(bleft.x(), y, block_width,
74  margin, bwline.get(), ptrline.get(), &free_cracks, outline_it);
75  }
76 
77  free_crackedges(free_cracks); // really free them
78 }
void free_crackedges(CRACKEDGE *start)
Definition: scanedg.cpp:362
int16_t y() const
access_function
Definition: points.h:57
void line_edges(int16_t x, int16_t y, int16_t xext, uint8_t uppercolour, uint8_t *bwpos, CRACKEDGE **prevline, CRACKEDGE **free_cracks, C_OUTLINE_IT *outline_it)
Definition: scanedg.cpp:142
void make_margins(PDBLK *block, BLOCK_LINE_IT *line_it, uint8_t *pixels, uint8_t margin, int16_t left, int16_t right, int16_t y)
Definition: scanedg.cpp:87
integer coordinate
Definition: points.h:32
int16_t x() const
access function
Definition: points.h:53
#define WHITE_PIX
Definition: scanedg.cpp:26
void bounding_box(ICOORD &bottom_left, ICOORD &top_right) const
get box
Definition: pdblock.h:60
rectangle iterator
Definition: pdblock.h:145
#define ASSERT_HOST(x)
Definition: errcode.h:84

◆ free_crackedges()

void free_crackedges ( CRACKEDGE start)

Definition at line 362 of file scanedg.cpp.

362  {
363  CRACKEDGE *current; // current edge to free
364  CRACKEDGE *next; // next one to free
365 
366  for (current = start; current != nullptr; current = next) {
367  next = current->next;
368  delete current; // delete them all
369  }
370 }
CRACKEDGE * next
Definition: crakedge.h:35

◆ h_edge()

CRACKEDGE* h_edge ( int  sign,
CRACKEDGE join,
CrackPos pos 
)

Definition at line 226 of file scanedg.cpp.

228  {
229  CRACKEDGE *newpt; // return value
230 
231  if (*pos->free_cracks != nullptr) {
232  newpt = *pos->free_cracks;
233  *pos->free_cracks = newpt->next; // get one fast
234  } else {
235  newpt = new CRACKEDGE;
236  }
237  newpt->pos.set_y(pos->y + 1); // coords of pt
238  newpt->stepy = 0; // edge is horizontal
239 
240  if (sign > 0) {
241  newpt->pos.set_x(pos->x + 1); // start location
242  newpt->stepx = -1;
243  newpt->stepdir = 0;
244  } else {
245  newpt->pos.set_x(pos->x); // start location
246  newpt->stepx = 1;
247  newpt->stepdir = 2;
248  }
249 
250  if (join == nullptr) {
251  newpt->next = newpt; // ptrs to other ends
252  newpt->prev = newpt;
253  } else {
254  if (newpt->pos.x() + newpt->stepx == join->pos.x()
255  && newpt->pos.y() == join->pos.y()) {
256  newpt->prev = join->prev; // update other ends
257  newpt->prev->next = newpt;
258  newpt->next = join; // join up
259  join->prev = newpt;
260  } else {
261  newpt->next = join->next; // update other ends
262  newpt->next->prev = newpt;
263  newpt->prev = join; // join up
264  join->next = newpt;
265  }
266  }
267  return newpt;
268 }
int x
Definition: scanedg.h:31
CRACKEDGE * prev
Definition: crakedge.h:34
CRACKEDGE ** free_cracks
Definition: scanedg.h:30
int8_t stepx
Definition: crakedge.h:31
void set_x(int16_t xin)
rewrite function
Definition: points.h:62
int16_t y() const
access_function
Definition: points.h:57
int y
Definition: scanedg.h:32
struct list_rec * next
Definition: oldlist.h:132
int8_t stepdir
Definition: crakedge.h:33
int16_t x() const
access function
Definition: points.h:53
LIST join(LIST list1, LIST list2)
Definition: oldlist.cpp:231
ICOORD pos
Definition: crakedge.h:30
CRACKEDGE * next
Definition: crakedge.h:35
int8_t stepy
Definition: crakedge.h:32
void set_y(int16_t yin)
rewrite function
Definition: points.h:66

◆ join_edges()

void join_edges ( CRACKEDGE edge1,
CRACKEDGE edge2,
CRACKEDGE **  free_cracks,
C_OUTLINE_IT *  outline_it 
)

Definition at line 329 of file scanedg.cpp.

332  {
333  if (edge1->pos.x() + edge1->stepx != edge2->pos.x()
334  || edge1->pos.y() + edge1->stepy != edge2->pos.y()) {
335  CRACKEDGE *tempedge = edge1;
336  edge1 = edge2; // swap around
337  edge2 = tempedge;
338  }
339 
340  if (edge1->next == edge2) {
341  // already closed
342  complete_edge(edge1, outline_it);
343  // attach freelist to end
344  edge1->prev->next = *free_cracks;
345  *free_cracks = edge1; // and free list
346  } else {
347  // update opposite ends
348  edge2->prev->next = edge1->next;
349  edge1->next->prev = edge2->prev;
350  edge1->next = edge2; // make joins
351  edge2->prev = edge1;
352  }
353 }
CRACKEDGE * prev
Definition: crakedge.h:34
int8_t stepx
Definition: crakedge.h:31
void complete_edge(CRACKEDGE *start, C_OUTLINE_IT *outline_it)
Definition: edgloop.cpp:37
int16_t y() const
access_function
Definition: points.h:57
int16_t x() const
access function
Definition: points.h:53
ICOORD pos
Definition: crakedge.h:30
CRACKEDGE * next
Definition: crakedge.h:35
int8_t stepy
Definition: crakedge.h:32

◆ line_edges()

void line_edges ( int16_t  x,
int16_t  y,
int16_t  xext,
uint8_t  uppercolour,
uint8_t *  bwpos,
CRACKEDGE **  prevline,
CRACKEDGE **  free_cracks,
C_OUTLINE_IT *  outline_it 
)

Definition at line 142 of file scanedg.cpp.

149  {
150  CrackPos pos = {free_cracks, x, y };
151  int xmax; // max x coord
152  int colour; // of current pixel
153  int prevcolour; // of previous pixel
154  CRACKEDGE *current; // current h edge
155  CRACKEDGE *newcurrent; // new h edge
156 
157  xmax = x + xext; // max allowable coord
158  prevcolour = uppercolour; // forced plain margin
159  current = nullptr; // nothing yet
160 
161  // do each pixel
162  for (; pos.x < xmax; pos.x++, prevline++) {
163  colour = *bwpos++; // current pixel
164  if (*prevline != nullptr) {
165  // changed above
166  // change colour
167  uppercolour = FLIP_COLOUR(uppercolour);
168  if (colour == prevcolour) {
169  if (colour == uppercolour) {
170  // finish a line
171  join_edges(current, *prevline, free_cracks, outline_it);
172  current = nullptr; // no edge now
173  } else {
174  // new horiz edge
175  current = h_edge(uppercolour - colour, *prevline, &pos);
176  }
177  *prevline = nullptr; // no change this time
178  } else {
179  if (colour == uppercolour)
180  *prevline = v_edge(colour - prevcolour, *prevline, &pos);
181  // 8 vs 4 connection
182  else if (colour == WHITE_PIX) {
183  join_edges(current, *prevline, free_cracks, outline_it);
184  current = h_edge(uppercolour - colour, nullptr, &pos);
185  *prevline = v_edge(colour - prevcolour, current, &pos);
186  } else {
187  newcurrent = h_edge(uppercolour - colour, *prevline, &pos);
188  *prevline = v_edge(colour - prevcolour, current, &pos);
189  current = newcurrent; // right going h edge
190  }
191  prevcolour = colour; // remember new colour
192  }
193  } else {
194  if (colour != prevcolour) {
195  *prevline = current = v_edge(colour - prevcolour, current, &pos);
196  prevcolour = colour;
197  }
198  if (colour != uppercolour)
199  current = h_edge(uppercolour - colour, current, &pos);
200  else
201  current = nullptr; // no edge now
202  }
203  }
204  if (current != nullptr) {
205  // out of block
206  if (*prevline != nullptr) { // got one to join to?
207  join_edges(current, *prevline, free_cracks, outline_it);
208  *prevline = nullptr; // tidy now
209  } else {
210  // fake vertical
211  *prevline = v_edge(FLIP_COLOUR(prevcolour)-prevcolour, current, &pos);
212  }
213  } else if (*prevline != nullptr) {
214  //continue fake
215  *prevline = v_edge(FLIP_COLOUR(prevcolour)-prevcolour, *prevline, &pos);
216  }
217 }
int x
Definition: scanedg.h:31
CRACKEDGE * v_edge(int sign, CRACKEDGE *join, CrackPos *pos)
Definition: scanedg.cpp:277
#define FLIP_COLOUR(pix)
Definition: scanedg.cpp:29
void join_edges(CRACKEDGE *edge1, CRACKEDGE *edge2, CRACKEDGE **free_cracks, C_OUTLINE_IT *outline_it)
Definition: scanedg.cpp:329
CRACKEDGE * h_edge(int sign, CRACKEDGE *join, CrackPos *pos)
Definition: scanedg.cpp:226
#define WHITE_PIX
Definition: scanedg.cpp:26

◆ make_margins()

void make_margins ( PDBLK block,
BLOCK_LINE_IT line_it,
uint8_t *  pixels,
uint8_t  margin,
int16_t  left,
int16_t  right,
int16_t  y 
)

Definition at line 87 of file scanedg.cpp.

95  {
96  ICOORDELT_IT seg_it;
97  int32_t start; //of segment
98  int16_t xext; //of segment
99  int xindex; //index to pixel
100 
101  if (block->poly_block () != nullptr) {
102  std::unique_ptr<PB_LINE_IT> lines(new PB_LINE_IT (block->poly_block ()));
103  const std::unique_ptr</*non-const*/ ICOORDELT_LIST> segments(
104  lines->get_line(y));
105  if (!segments->empty ()) {
106  seg_it.set_to_list(segments.get());
107  seg_it.mark_cycle_pt ();
108  start = seg_it.data ()->x ();
109  xext = seg_it.data ()->y ();
110  for (xindex = left; xindex < right; xindex++) {
111  if (xindex >= start && !seg_it.cycled_list ()) {
112  xindex = start + xext - 1;
113  seg_it.forward ();
114  start = seg_it.data ()->x ();
115  xext = seg_it.data ()->y ();
116  }
117  else
118  pixels[xindex - left] = margin;
119  }
120  }
121  else {
122  for (xindex = left; xindex < right; xindex++)
123  pixels[xindex - left] = margin;
124  }
125  }
126  else {
127  start = line_it->get_line (y, xext);
128  for (xindex = left; xindex < start; xindex++)
129  pixels[xindex - left] = margin;
130  for (xindex = start + xext; xindex < right; xindex++)
131  pixels[xindex - left] = margin;
132  }
133 }
int16_t get_line(int16_t y, int16_t &xext)
Definition: pdblock.cpp:347
POLY_BLOCK * poly_block() const
Definition: pdblock.h:56

◆ v_edge()

CRACKEDGE* v_edge ( int  sign,
CRACKEDGE join,
CrackPos pos 
)

Definition at line 277 of file scanedg.cpp.

279  {
280  CRACKEDGE *newpt; // return value
281 
282  if (*pos->free_cracks != nullptr) {
283  newpt = *pos->free_cracks;
284  *pos->free_cracks = newpt->next; // get one fast
285  } else {
286  newpt = new CRACKEDGE;
287  }
288  newpt->pos.set_x(pos->x); // coords of pt
289  newpt->stepx = 0; // edge is vertical
290 
291  if (sign > 0) {
292  newpt->pos.set_y(pos->y); // start location
293  newpt->stepy = 1;
294  newpt->stepdir = 3;
295  } else {
296  newpt->pos.set_y(pos->y + 1); // start location
297  newpt->stepy = -1;
298  newpt->stepdir = 1;
299  }
300 
301  if (join == nullptr) {
302  newpt->next = newpt; //ptrs to other ends
303  newpt->prev = newpt;
304  } else {
305  if (newpt->pos.x() == join->pos.x()
306  && newpt->pos.y() + newpt->stepy == join->pos.y()) {
307  newpt->prev = join->prev; // update other ends
308  newpt->prev->next = newpt;
309  newpt->next = join; // join up
310  join->prev = newpt;
311  } else {
312  newpt->next = join->next; // update other ends
313  newpt->next->prev = newpt;
314  newpt->prev = join; // join up
315  join->next = newpt;
316  }
317  }
318  return newpt;
319 }
int x
Definition: scanedg.h:31
CRACKEDGE * prev
Definition: crakedge.h:34
CRACKEDGE ** free_cracks
Definition: scanedg.h:30
int8_t stepx
Definition: crakedge.h:31
void set_x(int16_t xin)
rewrite function
Definition: points.h:62
int16_t y() const
access_function
Definition: points.h:57
int y
Definition: scanedg.h:32
struct list_rec * next
Definition: oldlist.h:132
int8_t stepdir
Definition: crakedge.h:33
int16_t x() const
access function
Definition: points.h:53
LIST join(LIST list1, LIST list2)
Definition: oldlist.cpp:231
ICOORD pos
Definition: crakedge.h:30
CRACKEDGE * next
Definition: crakedge.h:35
int8_t stepy
Definition: crakedge.h:32
void set_y(int16_t yin)
rewrite function
Definition: points.h:66