Use Leptonica API to access internals of Box

Signed-off-by: Stefan Weil <sw@weilnetz.de>
This commit is contained in:
Stefan Weil 2022-06-23 11:54:10 +02:00
parent 0df584e65d
commit 8ecaad56e3
4 changed files with 97 additions and 48 deletions

View File

@ -84,8 +84,10 @@ void BoxChar::TranslateBoxes(int xshift, int yshift, std::vector<BoxChar *> *box
for (auto &boxe : *boxes) {
Box *box = boxe->box_;
if (box != nullptr) {
box->x += xshift;
box->y += yshift;
int32_t box_x;
int32_t box_y;
boxGetGeometry(box, &box_x, &box_y, nullptr, nullptr);
boxSetGeometry(box, box_x + xshift, box_y + yshift, -1, -1);
}
}
}
@ -129,10 +131,18 @@ void BoxChar::InsertNewlines(bool rtl_rules, bool vertical_rules, std::vector<Bo
continue;
}
if (prev_i != SIZE_MAX) {
int32_t box_x;
int32_t box_y;
boxGetGeometry(box, &box_x, &box_y, nullptr, nullptr);
Box *prev_box = (*boxes)[prev_i]->box_;
int shift = box->x - prev_box->x;
int32_t prev_box_x;
int32_t prev_box_y;
int32_t prev_box_w;
int32_t prev_box_h;
boxGetGeometry(prev_box, &prev_box_x, &prev_box_y, &prev_box_w, &prev_box_h);
int shift = box_x - prev_box_x;
if (vertical_rules) {
shift = box->y - prev_box->y;
shift = box_y - prev_box_y;
} else if (rtl_rules) {
shift = -shift;
}
@ -142,15 +152,15 @@ void BoxChar::InsertNewlines(bool rtl_rules, bool vertical_rules, std::vector<Bo
// a box outside the image by making the width and height 1.
int width = 1;
int height = 1;
int x = prev_box->x + prev_box->w;
int y = prev_box->y;
int x = prev_box_x + prev_box_w;
int y = prev_box_y;
if (vertical_rules) {
x = prev_box->x;
y = prev_box->y + prev_box->h;
x = prev_box_x;
y = prev_box_y + prev_box_h;
} else if (rtl_rules) {
x = prev_box->x - width;
x = prev_box_x - width;
if (x < 0) {
tprintf("prev x = %d, width=%d\n", prev_box->x, width);
tprintf("prev x = %d, width=%d\n", prev_box_x, width);
x = 0;
}
}
@ -184,27 +194,38 @@ void BoxChar::InsertSpaces(bool rtl_rules, bool vertical_rules, std::vector<BoxC
if (box == nullptr) {
Box *prev = (*boxes)[i - 1]->box_;
Box *next = (*boxes)[i + 1]->box_;
int32_t prev_x;
int32_t prev_y;
int32_t prev_w;
int32_t prev_h;
int32_t next_x;
int32_t next_y;
int32_t next_w;
int32_t next_h;
ASSERT_HOST(prev != nullptr && next != nullptr);
int top = std::min(prev->y, next->y);
int bottom = std::max(prev->y + prev->h, next->y + next->h);
int left = prev->x + prev->w;
int right = next->x;
boxGetGeometry(prev, &prev_x, &prev_y, &prev_w, &prev_h);
boxGetGeometry(next, &next_x, &next_y, &next_w, &next_h);
int top = std::min(prev_y, next_y);
int bottom = std::max(prev_y + prev_h, next_y + next_h);
int left = prev_x + prev_w;
int right = next_x;
if (vertical_rules) {
top = prev->y + prev->h;
bottom = next->y;
left = std::min(prev->x, next->x);
right = std::max(prev->x + prev->w, next->x + next->w);
top = prev_y + prev_h;
bottom = next_y;
left = std::min(prev_x, next_x);
right = std::max(prev_x + prev_w, next_x + next_w);
} else if (rtl_rules) {
// With RTL we have to account for BiDi.
// Right becomes the min left of all prior boxes back to the first
// space or newline.
right = prev->x;
left = next->x + next->w;
right = prev_x;
left = next_x + next_w;
for (int j = i - 2; j >= 0 && (*boxes)[j]->ch_ != " " && (*boxes)[j]->ch_ != "\t"; --j) {
prev = (*boxes)[j]->box_;
ASSERT_HOST(prev != nullptr);
if (prev->x < right) {
right = prev->x;
boxGetGeometry(prev, &prev_x, nullptr, nullptr, nullptr);
if (prev_x < right) {
right = prev_x;
}
}
// Left becomes the max right of all next boxes forward to the first
@ -212,8 +233,9 @@ void BoxChar::InsertSpaces(bool rtl_rules, bool vertical_rules, std::vector<BoxC
for (size_t j = i + 2;
j < boxes->size() && (*boxes)[j]->box_ != nullptr && (*boxes)[j]->ch_ != "\t"; ++j) {
next = (*boxes)[j]->box_;
if (next->x + next->w > left) {
left = next->x + next->w;
boxGetGeometry(next, &next_x, nullptr, &next_w, nullptr);
if (next_x + next_w > left) {
left = next_x + next_w;
}
}
}
@ -275,8 +297,14 @@ bool BoxChar::MostlyVertical(const std::vector<BoxChar *> &boxes) {
for (size_t i = 1; i < boxes.size(); ++i) {
if (boxes[i - 1]->box_ != nullptr && boxes[i]->box_ != nullptr &&
boxes[i - 1]->page_ == boxes[i]->page_) {
int dx = boxes[i]->box_->x - boxes[i - 1]->box_->x;
int dy = boxes[i]->box_->y - boxes[i - 1]->box_->y;
int32_t x0;
int32_t y0;
boxGetGeometry(boxes[i]->box_, &x0, &y0, nullptr, nullptr);
int32_t x1;
int32_t y1;
boxGetGeometry(boxes[i - 1]->box_, &x1, &y1, nullptr, nullptr);
int dx = x0 - x1;
int dy = y0 - y1;
if (abs(dx) > abs(dy) * kMinNewlineRatio || abs(dy) > abs(dx) * kMinNewlineRatio) {
total_dx += dx * dx;
total_dy += dy * dy;
@ -337,8 +365,14 @@ std::string BoxChar::GetTesseractBoxStr(int height, const std::vector<BoxChar *>
tprintf("Error: Call PrepareToWrite before WriteTesseractBoxFile!!\n");
return "";
}
int nbytes = snprintf(buffer, kMaxLineLength, "%s %d %d %d %d %d\n", boxe->ch_.c_str(), box->x,
height - box->y - box->h, box->x + box->w, height - box->y, boxe->page_);
int32_t box_x;
int32_t box_y;
int32_t box_w;
int32_t box_h;
boxGetGeometry(const_cast<Box *>(box), &box_x, &box_y, &box_w, &box_h);
int nbytes = snprintf(buffer, kMaxLineLength, "%s %d %d %d %d %d\n",
boxe->ch_.c_str(), box_x, height - box_y - box_h,
box_x + box_w, height - box_y, boxe->page_);
output.append(buffer, nbytes);
}
return output;

View File

@ -26,9 +26,6 @@
#include <vector>
#include <allheaders.h> // for Leptonica API
#if (LIBLEPT_MAJOR_VERSION == 1 && LIBLEPT_MINOR_VERSION >= 83) || LIBLEPT_MAJOR_VERSION > 1
#include <pix_internal.h> // for fast access to Box geometry
#endif
#include <tesseract/export.h>
namespace tesseract {
@ -79,7 +76,11 @@ public:
if (other.box_ == nullptr) {
return false;
}
return box_->x < other.box_->x;
int32_t box_x;
int32_t other_box_x;
boxGetGeometry(box_, &box_x, nullptr, nullptr, nullptr);
boxGetGeometry(other.box_, &other_box_x, nullptr, nullptr, nullptr);
return box_x < other_box_x;
}
// Increments *num_rtl and *num_ltr according to the directionality of
// characters in the box.

View File

@ -428,15 +428,25 @@ static void MergeBoxCharsToWords(std::vector<BoxChar *> *boxchars) {
BoxChar *last_boxchar = result.back();
// Compute bounding box union
const Box *box = boxchar->box();
int32_t box_x;
int32_t box_y;
int32_t box_w;
int32_t box_h;
boxGetGeometry(const_cast<Box *>(box), &box_x, &box_y, &box_w, &box_h);
Box *last_box = last_boxchar->mutable_box();
int left = std::min(last_box->x, box->x);
int right = std::max(last_box->x + last_box->w, box->x + box->w);
int top = std::min(last_box->y, box->y);
int bottom = std::max(last_box->y + last_box->h, box->y + box->h);
int32_t last_box_x;
int32_t last_box_y;
int32_t last_box_w;
int32_t last_box_h;
boxGetGeometry(last_box, &last_box_x, &last_box_y, &last_box_w, &last_box_h);
int left = std::min(last_box_x, box_x);
int right = std::max(last_box_x + last_box_w, box_x + box_w);
int top = std::min(last_box_y, box_y);
int bottom = std::max(last_box_y + last_box_h, box_y + box_h);
// Conclude that the word was broken to span multiple lines based on the
// size of the merged bounding box in relation to those of the individual
// characters seen so far.
if (right - left > last_box->w + 5 * box->w) {
if (right - left > last_box_w + 5 * box_w) {
tlog(1, "Found line break after '%s'", last_boxchar->ch().c_str());
// Insert a fake interword space and start a new word with the current
// boxchar.
@ -447,10 +457,7 @@ static void MergeBoxCharsToWords(std::vector<BoxChar *> *boxchars) {
}
// Append to last word
last_boxchar->mutable_ch()->append(boxchar->ch());
last_box->x = left;
last_box->w = right - left;
last_box->y = top;
last_box->h = bottom - top;
boxSetGeometry(last_box, left, top, right - left, bottom - top);
delete boxchar;
boxchar = nullptr;
}

View File

@ -282,12 +282,18 @@ static void ExtractFontProperties(const std::string &utf8_text, StringRenderer *
if (IsWhitespaceBox(boxes[b + 1])) {
continue;
}
int xgap = (boxes[b + 1]->box()->x - (boxes[b]->box()->x + boxes[b]->box()->w));
int32_t box_x;
int32_t box_w;
boxGetGeometry(const_cast<Box *>(boxes[b]->box()), &box_x, nullptr, &box_w, nullptr);
int32_t box1_x;
int32_t box1_w;
boxGetGeometry(const_cast<Box *>(boxes[b + 1]->box()), &box1_x, nullptr, &box1_w, nullptr);
int xgap = (box1_x - (box_x + box_w));
spacing_map_it0 = spacing_map.find(ch0);
int ok_count = 0;
if (spacing_map_it0 == spacing_map.end() &&
render->font().GetSpacingProperties(ch0, &x_bearing, &x_advance)) {
spacing_map[ch0] = SpacingProperties(x_bearing, x_advance - x_bearing - boxes[b]->box()->w);
spacing_map[ch0] = SpacingProperties(x_bearing, x_advance - x_bearing - box_w);
spacing_map_it0 = spacing_map.find(ch0);
++ok_count;
}
@ -297,7 +303,7 @@ static void ExtractFontProperties(const std::string &utf8_text, StringRenderer *
if (spacing_map_it1 == spacing_map.end() &&
render->font().GetSpacingProperties(ch1, &x_bearing, &x_advance)) {
spacing_map[ch1] =
SpacingProperties(x_bearing, x_advance - x_bearing - boxes[b + 1]->box()->w);
SpacingProperties(x_bearing, x_advance - x_bearing - box1_w);
spacing_map_it1 = spacing_map.find(ch1);
++ok_count;
}
@ -356,10 +362,11 @@ static bool MakeIndividualGlyphs(Image pix, const std::vector<BoxChar *> &vbox,
if (!b) {
continue;
}
const int x = b->x;
const int y = b->y;
const int w = b->w;
const int h = b->h;
int32_t x;
int32_t y;
int32_t w;
int32_t h;
boxGetGeometry(b, &x, &y, &w, &h);
// Check present tiff page (for multipage tiff)
if (y < y_previous - pixGetHeight(pix) / 10) {
tprintf("ERROR: Wrap-around encountered, at i=%d\n", i);