tesseract  5.0.0
pageiterator.cpp
Go to the documentation of this file.
1 // File: pageiterator.cpp
3 // Description: Iterator for tesseract page structure that avoids using
4 // tesseract internal data structures.
5 // Author: Ray Smith
6 //
7 // (C) Copyright 2010, Google Inc.
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 //
19 
20 #include <allheaders.h>
21 #include <tesseract/pageiterator.h>
22 #include "helpers.h"
23 #include "pageres.h"
24 #include "tesseractclass.h"
25 
26 #include <algorithm>
27 
28 namespace tesseract {
29 
31  int scaled_yres, int rect_left, int rect_top,
32  int rect_width, int rect_height)
33  : page_res_(page_res),
34  tesseract_(tesseract),
35  word_(nullptr),
36  word_length_(0),
37  blob_index_(0),
38  cblob_it_(nullptr),
39  include_upper_dots_(false),
40  include_lower_dots_(false),
41  scale_(scale),
42  scaled_yres_(scaled_yres),
43  rect_left_(rect_left),
44  rect_top_(rect_top),
45  rect_width_(rect_width),
46  rect_height_(rect_height) {
47  it_ = new PAGE_RES_IT(page_res);
49 }
50 
52  delete it_;
53  delete cblob_it_;
54 }
55 
62  : page_res_(src.page_res_),
63  tesseract_(src.tesseract_),
64  word_(nullptr),
65  word_length_(src.word_length_),
66  blob_index_(src.blob_index_),
67  cblob_it_(nullptr),
68  include_upper_dots_(src.include_upper_dots_),
69  include_lower_dots_(src.include_lower_dots_),
70  scale_(src.scale_),
71  scaled_yres_(src.scaled_yres_),
72  rect_left_(src.rect_left_),
73  rect_top_(src.rect_top_),
74  rect_width_(src.rect_width_),
75  rect_height_(src.rect_height_) {
76  it_ = new PAGE_RES_IT(*src.it_);
78 }
79 
81  page_res_ = src.page_res_;
82  tesseract_ = src.tesseract_;
85  scale_ = src.scale_;
87  rect_left_ = src.rect_left_;
88  rect_top_ = src.rect_top_;
91  delete it_;
92  it_ = new PAGE_RES_IT(*src.it_);
94  return *this;
95 }
96 
98  return (it_ == nullptr && it_ == other) ||
99  ((other != nullptr) && (it_ != nullptr) && (*it_ == *other));
100 }
101 
102 // ============= Moving around within the page ============.
103 
107  BeginWord(0);
108 }
109 
111  if (it_->block() == nullptr) {
112  return; // At end of the document.
113  }
114  PAGE_RES_IT para(page_res_);
115  PAGE_RES_IT next_para(para);
116  next_para.forward_paragraph();
117  while (next_para.cmp(*it_) <= 0) {
118  para = next_para;
119  next_para.forward_paragraph();
120  }
121  *it_ = para;
122  BeginWord(0);
123 }
124 
126  PageIterator p_start(*this);
127  p_start.RestartParagraph();
128  return p_start.it_->row() == it_->row();
129 }
130 
132  it_->restart_row();
133  BeginWord(0);
134 }
135 
150  if (it_->block() == nullptr) {
151  return false; // Already at the end!
152  }
153  if (it_->word() == nullptr) {
154  level = RIL_BLOCK;
155  }
156 
157  switch (level) {
158  case RIL_BLOCK:
159  it_->forward_block();
160  break;
161  case RIL_PARA:
163  break;
164  case RIL_TEXTLINE:
165  for (it_->forward_with_empties(); it_->row() == it_->prev_row();
167  ;
168  }
169  break;
170  case RIL_WORD:
172  break;
173  case RIL_SYMBOL:
174  if (cblob_it_ != nullptr) {
175  cblob_it_->forward();
176  }
177  ++blob_index_;
178  if (blob_index_ >= word_length_) {
180  } else {
181  return true;
182  }
183  break;
184  }
185  BeginWord(0);
186  return it_->block() != nullptr;
187 }
188 
195  if (it_->block() == nullptr) {
196  return false; // Already at the end!
197  }
198  if (it_->word() == nullptr) {
199  return true; // In an image block.
200  }
201  switch (level) {
202  case RIL_BLOCK:
203  return blob_index_ == 0 && it_->block() != it_->prev_block();
204  case RIL_PARA:
205  return blob_index_ == 0 &&
206  (it_->block() != it_->prev_block() ||
207  it_->row()->row->para() != it_->prev_row()->row->para());
208  case RIL_TEXTLINE:
209  return blob_index_ == 0 && it_->row() != it_->prev_row();
210  case RIL_WORD:
211  return blob_index_ == 0;
212  case RIL_SYMBOL:
213  return true;
214  }
215  return false;
216 }
217 
223  PageIteratorLevel element) const {
224  if (Empty(element)) {
225  return true; // Already at the end!
226  }
227  // The result is true if we step forward by element and find we are
228  // at the the end of the page or at beginning of *all* levels in:
229  // [level, element).
230  // When there is more than one level difference between element and level,
231  // we could for instance move forward one symbol and still be at the first
232  // word on a line, so we also have to be at the first symbol in a word.
233  PageIterator next(*this);
234  next.Next(element);
235  if (next.Empty(element)) {
236  return true; // Reached the end of the page.
237  }
238  while (element > level) {
239  element = static_cast<PageIteratorLevel>(element - 1);
240  if (!next.IsAtBeginningOf(element)) {
241  return false;
242  }
243  }
244  return true;
245 }
246 
253 int PageIterator::Cmp(const PageIterator &other) const {
254  int word_cmp = it_->cmp(*other.it_);
255  if (word_cmp != 0) {
256  return word_cmp;
257  }
258  if (blob_index_ < other.blob_index_) {
259  return -1;
260  }
261  if (blob_index_ == other.blob_index_) {
262  return 0;
263  }
264  return 1;
265 }
266 
267 // ============= Accessing data ==============.
268 // Coordinate system:
269 // Integer coordinates are at the cracks between the pixels.
270 // The top-left corner of the top-left pixel in the image is at (0,0).
271 // The bottom-right corner of the bottom-right pixel in the image is at
272 // (width, height).
273 // Every bounding box goes from the top-left of the top-left contained
274 // pixel to the bottom-right of the bottom-right contained pixel, so
275 // the bounding box of the single top-left pixel in the image is:
276 // (0,0)->(1,1).
277 // If an image rectangle has been set in the API, then returned coordinates
278 // relate to the original (full) image, rather than the rectangle.
279 
287  int *top, int *right,
288  int *bottom) const {
289  if (Empty(level)) {
290  return false;
291  }
292  TBOX box;
293  PARA *para = nullptr;
294  switch (level) {
295  case RIL_BLOCK:
298  break;
299  case RIL_PARA:
300  para = it_->row()->row->para();
301  // Fall through.
302  case RIL_TEXTLINE:
305  break;
306  case RIL_WORD:
309  break;
310  case RIL_SYMBOL:
311  if (cblob_it_ == nullptr) {
312  box = it_->word()->box_word->BlobBox(blob_index_);
313  } else {
314  box = cblob_it_->data()->bounding_box();
315  }
316  }
317  if (level == RIL_PARA) {
318  PageIterator other = *this;
319  other.Begin();
320  do {
321  if (other.it_->block() &&
322  other.it_->block()->block == it_->block()->block &&
323  other.it_->row() && other.it_->row()->row &&
324  other.it_->row()->row->para() == para) {
325  box = box.bounding_union(other.it_->row()->row->bounding_box());
326  }
327  } while (other.Next(RIL_TEXTLINE));
328  }
329  if (level != RIL_SYMBOL || cblob_it_ != nullptr) {
330  box.rotate(it_->block()->block->re_rotation());
331  }
332  // Now we have a box in tesseract coordinates relative to the image rectangle,
333  // we have to convert the coords to a top-down system.
334  const int pix_height = pixGetHeight(tesseract_->pix_binary());
335  const int pix_width = pixGetWidth(tesseract_->pix_binary());
336  *left = ClipToRange(static_cast<int>(box.left()), 0, pix_width);
337  *top = ClipToRange(pix_height - box.top(), 0, pix_height);
338  *right = ClipToRange(static_cast<int>(box.right()), *left, pix_width);
339  *bottom = ClipToRange(pix_height - box.bottom(), *top, pix_height);
340  return true;
341 }
342 
349 bool PageIterator::BoundingBox(PageIteratorLevel level, int *left, int *top,
350  int *right, int *bottom) const {
351  return BoundingBox(level, 0, left, top, right, bottom);
352 }
353 
354 bool PageIterator::BoundingBox(PageIteratorLevel level, const int padding,
355  int *left, int *top, int *right,
356  int *bottom) const {
357  if (!BoundingBoxInternal(level, left, top, right, bottom)) {
358  return false;
359  }
360  // Convert to the coordinate system of the original image.
361  *left = ClipToRange(*left / scale_ + rect_left_ - padding, rect_left_,
363  *top = ClipToRange(*top / scale_ + rect_top_ - padding, rect_top_,
365  *right = ClipToRange((*right + scale_ - 1) / scale_ + rect_left_ + padding,
366  *left, rect_left_ + rect_width_);
367  *bottom = ClipToRange((*bottom + scale_ - 1) / scale_ + rect_top_ + padding,
368  *top, rect_top_ + rect_height_);
369  return true;
370 }
371 
374  if (it_->block() == nullptr) {
375  return true; // Already at the end!
376  }
377  if (it_->word() == nullptr && level != RIL_BLOCK) {
378  return true; // image block
379  }
380  if (level == RIL_SYMBOL && blob_index_ >= word_length_) {
381  return true; // Zero length word, or already at the end of it.
382  }
383  return false;
384 }
385 
389  if (it_->block() == nullptr || it_->block()->block == nullptr) {
390  return PT_UNKNOWN; // Already at the end!
391  }
392  if (it_->block()->block->pdblk.poly_block() == nullptr) {
393  return PT_FLOWING_TEXT; // No layout analysis used - assume text.
394  }
395  return it_->block()->block->pdblk.poly_block()->isA();
396 }
397 
401  if (it_->block() == nullptr || it_->block()->block == nullptr) {
402  return nullptr; // Already at the end!
403  }
404  if (it_->block()->block->pdblk.poly_block() == nullptr) {
405  return nullptr; // No layout analysis used - no polygon.
406  }
407  // Copy polygon, so we can unrotate it to image coordinates.
408  POLY_BLOCK *internal_poly = it_->block()->block->pdblk.poly_block();
409  ICOORDELT_LIST vertices;
410  vertices.deep_copy(internal_poly->points(), ICOORDELT::deep_copy);
411  POLY_BLOCK poly(&vertices, internal_poly->isA());
412  poly.rotate(it_->block()->block->re_rotation());
413  ICOORDELT_IT it(poly.points());
414  Pta *pta = ptaCreate(it.length());
415  int num_pts = 0;
416  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward(), ++num_pts) {
417  ICOORD *pt = it.data();
418  // Convert to top-down coords within the input image.
419  int x = static_cast<float>(pt->x()) / scale_ + rect_left_;
420  int y = rect_top_ + rect_height_ - static_cast<float>(pt->y()) / scale_;
423  ptaAddPt(pta, x, y);
424  }
425  return pta;
426 }
427 
451  int left, top, right, bottom;
452  if (!BoundingBoxInternal(level, &left, &top, &right, &bottom)) {
453  return nullptr;
454  }
455  if (level == RIL_SYMBOL && cblob_it_ != nullptr &&
456  cblob_it_->data()->area() != 0) {
457  return cblob_it_->data()->render();
458  }
459  Box *box = boxCreate(left, top, right - left, bottom - top);
460  Image pix = pixClipRectangle(tesseract_->pix_binary(), box, nullptr);
461  boxDestroy(&box);
462  if (level == RIL_BLOCK || level == RIL_PARA) {
463  // Clip to the block polygon as well.
464  TBOX mask_box;
465  Image mask = it_->block()->block->render_mask(&mask_box);
466  int mask_x = left - mask_box.left();
467  int mask_y = top - (tesseract_->ImageHeight() - mask_box.top());
468  // AND the mask and pix, putting the result in pix.
469  pixRasterop(pix, std::max(0, -mask_x), std::max(0, -mask_y),
470  pixGetWidth(pix), pixGetHeight(pix), PIX_SRC & PIX_DST, mask,
471  std::max(0, mask_x), std::max(0, mask_y));
472  mask.destroy();
473  }
474  return pix;
475 }
476 
489  Pix *original_img, int *left, int *top) const {
490  int right, bottom;
491  if (!BoundingBox(level, left, top, &right, &bottom)) {
492  return nullptr;
493  }
494  if (original_img == nullptr) {
495  return GetBinaryImage(level);
496  }
497 
498  // Expand the box.
499  *left = std::max(*left - padding, 0);
500  *top = std::max(*top - padding, 0);
501  right = std::min(right + padding, rect_width_);
502  bottom = std::min(bottom + padding, rect_height_);
503  Box *box = boxCreate(*left, *top, right - *left, bottom - *top);
504  Image grey_pix = pixClipRectangle(original_img, box, nullptr);
505  boxDestroy(&box);
506  if (level == RIL_BLOCK || level == RIL_PARA) {
507  // Clip to the block polygon as well.
508  TBOX mask_box;
509  Image mask = it_->block()->block->render_mask(&mask_box);
510  // Copy the mask registered correctly into an image the size of grey_pix.
511  int mask_x = *left - mask_box.left();
512  int mask_y = *top - (pixGetHeight(original_img) - mask_box.top());
513  int width = pixGetWidth(grey_pix);
514  int height = pixGetHeight(grey_pix);
515  Image resized_mask = pixCreate(width, height, 1);
516  pixRasterop(resized_mask, std::max(0, -mask_x), std::max(0, -mask_y), width,
517  height, PIX_SRC, mask, std::max(0, mask_x),
518  std::max(0, mask_y));
519  mask.destroy();
520  pixDilateBrick(resized_mask, resized_mask, 2 * padding + 1,
521  2 * padding + 1);
522  pixInvert(resized_mask, resized_mask);
523  pixSetMasked(grey_pix, resized_mask, UINT32_MAX);
524  resized_mask.destroy();
525  }
526  return grey_pix;
527 }
528 
534 bool PageIterator::Baseline(PageIteratorLevel level, int *x1, int *y1, int *x2,
535  int *y2) const {
536  if (it_->word() == nullptr) {
537  return false; // Already at the end!
538  }
539  ROW *row = it_->row()->row;
540  WERD *word = it_->word()->word;
541  TBOX box = (level == RIL_WORD || level == RIL_SYMBOL) ? word->bounding_box()
542  : row->bounding_box();
543  int left = box.left();
544  ICOORD startpt(left, static_cast<int16_t>(row->base_line(left) + 0.5));
545  int right = box.right();
546  ICOORD endpt(right, static_cast<int16_t>(row->base_line(right) + 0.5));
547  // Rotate to image coordinates and convert to global image coords.
548  startpt.rotate(it_->block()->block->re_rotation());
549  endpt.rotate(it_->block()->block->re_rotation());
550  *x1 = startpt.x() / scale_ + rect_left_;
551  *y1 = (rect_height_ - startpt.y()) / scale_ + rect_top_;
552  *x2 = endpt.x() / scale_ + rect_left_;
553  *y2 = (rect_height_ - endpt.y()) / scale_ + rect_top_;
554  return true;
555 }
556 
557 void PageIterator::RowAttributes(float *row_height, float *descenders,
558  float *ascenders) const {
559  *row_height = it_->row()->row->x_height() + it_->row()->row->ascenders() -
560  it_->row()->row->descenders();
561  *descenders = it_->row()->row->descenders();
562  *ascenders = it_->row()->row->ascenders();
563 }
564 
566  tesseract::WritingDirection *writing_direction,
567  tesseract::TextlineOrder *textline_order,
568  float *deskew_angle) const {
569  BLOCK *block = it_->block()->block;
570 
571  // Orientation
572  FCOORD up_in_image(0.0, 1.0);
573  up_in_image.unrotate(block->classify_rotation());
574  up_in_image.rotate(block->re_rotation());
575 
576  if (up_in_image.x() == 0.0F) {
577  if (up_in_image.y() > 0.0F) {
578  *orientation = ORIENTATION_PAGE_UP;
579  } else {
580  *orientation = ORIENTATION_PAGE_DOWN;
581  }
582  } else if (up_in_image.x() > 0.0F) {
583  *orientation = ORIENTATION_PAGE_RIGHT;
584  } else {
585  *orientation = ORIENTATION_PAGE_LEFT;
586  }
587 
588  // Writing direction
589  bool is_vertical_text = (block->classify_rotation().x() == 0.0);
590  bool right_to_left = block->right_to_left();
591  *writing_direction = is_vertical_text
593  : (right_to_left ? WRITING_DIRECTION_RIGHT_TO_LEFT
595 
596  // Textline Order
597  const bool is_mongolian = false; // TODO(eger): fix me
598  *textline_order = is_vertical_text
599  ? (is_mongolian ? TEXTLINE_ORDER_LEFT_TO_RIGHT
602 
603  // Deskew angle
604  FCOORD skew = block->skew(); // true horizontal for textlines
605  *deskew_angle = -skew.angle();
606 }
607 
609  bool *is_list_item, bool *is_crown,
610  int *first_line_indent) const {
612  if (!it_->row() || !it_->row()->row || !it_->row()->row->para() ||
613  !it_->row()->row->para()->model) {
614  return;
615  }
616 
617  PARA *para = it_->row()->row->para();
618  *is_list_item = para->is_list_item;
619  *is_crown = para->is_very_first_or_continuation;
620  *first_line_indent = para->model->first_indent() - para->model->body_indent();
621  *just = para->model->justification();
622 }
623 
628 void PageIterator::BeginWord(int offset) {
629  WERD_RES *word_res = it_->word();
630  if (word_res == nullptr) {
631  // This is a non-text block, so there is no word.
632  word_length_ = 0;
633  blob_index_ = 0;
634  word_ = nullptr;
635  return;
636  }
637  if (word_res->best_choice != nullptr) {
638  // Recognition has been done, so we are using the box_word, which
639  // is already baseline denormalized.
640  word_length_ = word_res->best_choice->length();
641  if (word_res->box_word != nullptr) {
642  if (word_res->box_word->length() != static_cast<unsigned>(word_length_)) {
643  tprintf("Corrupted word! best_choice[len=%d] = %s, box_word[len=%d]: ",
644  word_length_, word_res->best_choice->unichar_string().c_str(),
645  word_res->box_word->length());
646  word_res->box_word->bounding_box().print();
647  }
648  ASSERT_HOST(word_res->box_word->length() ==
649  static_cast<unsigned>(word_length_));
650  }
651  word_ = nullptr;
652  // We will be iterating the box_word.
653  delete cblob_it_;
654  cblob_it_ = nullptr;
655  } else {
656  // No recognition yet, so a "symbol" is a cblob.
657  word_ = word_res->word;
658  ASSERT_HOST(word_->cblob_list() != nullptr);
659  word_length_ = word_->cblob_list()->length();
660  if (cblob_it_ == nullptr) {
661  cblob_it_ = new C_BLOB_IT;
662  }
663  cblob_it_->set_to_list(word_->cblob_list());
664  }
665  for (blob_index_ = 0; blob_index_ < offset; ++blob_index_) {
666  if (cblob_it_ != nullptr) {
667  cblob_it_->forward();
668  }
669  }
670 }
671 
673  if (it_->word() != nullptr) {
674  it_->word()->blamer_bundle = blamer_bundle;
675  return true;
676  } else {
677  return false;
678  }
679 }
680 
681 } // namespace tesseract.
#define ASSERT_HOST(x)
Definition: errcode.h:59
@ TEXTLINE_ORDER_LEFT_TO_RIGHT
Definition: publictypes.h:149
@ TEXTLINE_ORDER_RIGHT_TO_LEFT
Definition: publictypes.h:150
@ TEXTLINE_ORDER_TOP_TO_BOTTOM
Definition: publictypes.h:151
void tprintf(const char *format,...)
Definition: tprintf.cpp:41
ParagraphJustification
Definition: publictypes.h:248
@ JUSTIFICATION_UNKNOWN
Definition: publictypes.h:249
@ ORIENTATION_PAGE_LEFT
Definition: publictypes.h:120
@ ORIENTATION_PAGE_DOWN
Definition: publictypes.h:119
@ ORIENTATION_PAGE_UP
Definition: publictypes.h:117
@ ORIENTATION_PAGE_RIGHT
Definition: publictypes.h:118
T ClipToRange(const T &x, const T &lower_bound, const T &upper_bound)
Definition: helpers.h:110
@ WRITING_DIRECTION_TOP_TO_BOTTOM
Definition: publictypes.h:134
@ WRITING_DIRECTION_LEFT_TO_RIGHT
Definition: publictypes.h:132
@ WRITING_DIRECTION_RIGHT_TO_LEFT
Definition: publictypes.h:133
@ PT_FLOWING_TEXT
Definition: publictypes.h:55
void ParagraphInfo(tesseract::ParagraphJustification *justification, bool *is_list_item, bool *is_crown, int *first_line_indent) const
int Cmp(const PageIterator &other) const
bool BoundingBoxInternal(PageIteratorLevel level, int *left, int *top, int *right, int *bottom) const
virtual void RestartRow()
virtual bool Next(PageIteratorLevel level)
Pta * BlockPolygon() const
PolyBlockType BlockType() const
virtual bool IsAtBeginningOf(PageIteratorLevel level) const
bool PositionedAtSameWord(const PAGE_RES_IT *other) const
void RowAttributes(float *row_height, float *descenders, float *ascenders) const
bool SetWordBlamerBundle(BlamerBundle *blamer_bundle)
Pix * GetImage(PageIteratorLevel level, int padding, Pix *original_img, int *left, int *top) const
bool IsWithinFirstTextlineOfParagraph() const
virtual void RestartParagraph()
bool Empty(PageIteratorLevel level) const
bool Baseline(PageIteratorLevel level, int *x1, int *y1, int *x2, int *y2) const
const PageIterator & operator=(const PageIterator &src)
void BeginWord(int offset)
Pix * GetBinaryImage(PageIteratorLevel level) const
bool BoundingBox(PageIteratorLevel level, int *left, int *top, int *right, int *bottom) const
virtual bool IsAtFinalElement(PageIteratorLevel level, PageIteratorLevel element) const
PageIterator(PAGE_RES *page_res, Tesseract *tesseract, int scale, int scaled_yres, int rect_left, int rect_top, int rect_width, int rect_height)
void Orientation(tesseract::Orientation *orientation, tesseract::WritingDirection *writing_direction, tesseract::TextlineOrder *textline_order, float *deskew_angle) const
Image pix_binary() const
const TBOX & BlobBox(unsigned index) const
Definition: boxword.h:84
const TBOX & bounding_box() const
Definition: boxword.h:78
unsigned length() const
Definition: boxword.h:81
void destroy()
Definition: image.cpp:32
FCOORD classify_rotation() const
Definition: ocrblock.h:135
FCOORD re_rotation() const
Definition: ocrblock.h:129
PDBLK pdblk
Page Description Block.
Definition: ocrblock.h:185
bool right_to_left() const
Definition: ocrblock.h:74
FCOORD skew() const
Definition: ocrblock.h:141
TBOX restricted_bounding_box(bool upper_dots, bool lower_dots) const
Definition: ocrblock.cpp:88
Image render_mask(TBOX *mask_box)
Definition: ocrblock.h:155
const ParagraphModel * model
Definition: ocrpara.h:40
bool is_list_item
Definition: ocrpara.h:42
bool is_very_first_or_continuation
Definition: ocrpara.h:47
tesseract::ParagraphJustification justification() const
Definition: ocrpara.h:166
int body_indent() const
Definition: ocrpara.h:175
int first_indent() const
Definition: ocrpara.h:172
TBOX restricted_bounding_box(bool upper_dots, bool lower_dots) const
Definition: ocrrow.cpp:84
float x_height() const
Definition: ocrrow.h:66
float base_line(float xpos) const
Definition: ocrrow.h:61
PARA * para() const
Definition: ocrrow.h:120
TBOX bounding_box() const
Definition: ocrrow.h:90
float ascenders() const
Definition: ocrrow.h:84
float descenders() const
Definition: ocrrow.h:87
WERD_CHOICE * best_choice
Definition: pageres.h:239
BlamerBundle * blamer_bundle
Definition: pageres.h:250
tesseract::BoxWord * box_word
Definition: pageres.h:270
WERD_RES * forward_with_empties()
Definition: pageres.h:747
BLOCK_RES * prev_block() const
Definition: pageres.h:760
WERD_RES * restart_page_with_empties()
Definition: pageres.h:713
WERD_RES * forward_paragraph()
Definition: pageres.cpp:1700
ROW_RES * prev_row() const
Definition: pageres.h:757
WERD_RES * restart_row()
Definition: pageres.cpp:1683
ROW_RES * row() const
Definition: pageres.h:766
WERD_RES * forward_block()
Definition: pageres.cpp:1715
WERD_RES * word() const
Definition: pageres.h:763
BLOCK_RES * block() const
Definition: pageres.h:769
int cmp(const PAGE_RES_IT &other) const
Definition: pageres.cpp:1183
POLY_BLOCK * poly_block() const
Definition: pdblock.h:59
integer coordinate
Definition: points.h:36
void rotate(const FCOORD &vec)
Definition: points.h:511
TDimension y() const
access_function
Definition: points.h:62
TDimension x() const
access function
Definition: points.h:58
static ICOORDELT * deep_copy(const ICOORDELT *src)
Definition: points.h:180
float angle() const
find angle
Definition: points.h:246
void unrotate(const FCOORD &vec)
Definition: points.h:721
void rotate(const FCOORD vec)
Definition: points.h:712
float y() const
Definition: points.h:209
float x() const
Definition: points.h:206
PolyBlockType isA() const
Definition: polyblk.h:48
void rotate(FCOORD rotation)
Definition: polyblk.cpp:191
ICOORDELT_LIST * points()
Definition: polyblk.h:42
unsigned length() const
Definition: ratngs.h:283
std::string & unichar_string()
Definition: ratngs.h:515
TDimension left() const
Definition: rect.h:82
void rotate(const FCOORD &vec)
Definition: rect.h:210
TDimension top() const
Definition: rect.h:68
TBOX bounding_union(const TBOX &box) const
Definition: rect.cpp:128
void print() const
Definition: rect.h:289
TDimension right() const
Definition: rect.h:89
TDimension bottom() const
Definition: rect.h:75
C_BLOB_LIST * cblob_list()
Definition: werd.h:96
TBOX bounding_box() const
Definition: werd.cpp:155
TBOX restricted_bounding_box(bool upper_dots, bool lower_dots) const
Definition: werd.cpp:161