21#include <allheaders.h>
52 inverse_ = src.inverse_;
53 predecessor_ = src.predecessor_;
56 if (src.rotation_ ==
nullptr) {
59 rotation_ =
new FCOORD(*src.rotation_);
61 x_origin_ = src.x_origin_;
62 y_origin_ = src.y_origin_;
63 x_scale_ = src.x_scale_;
64 y_scale_ = src.y_scale_;
65 final_xshift_ = src.final_xshift_;
66 final_yshift_ = src.final_yshift_;
100 const DENORM *predecessor,
float x_origin,
float y_origin,
101 float x_scale,
float y_scale,
float final_xshift,
102 float final_yshift) {
105 if (rotation ==
nullptr) {
108 rotation_ =
new FCOORD(*rotation);
111 x_origin_ = x_origin;
112 y_origin_ = y_origin;
115 final_xshift_ = final_xshift;
116 final_yshift_ = final_yshift;
158static void ComputeRunlengthImage(
const TBOX &box,
159 const std::vector<std::vector<int>> &x_coords,
160 const std::vector<std::vector<int>> &y_coords,
162 int width = box.
width();
163 int height = box.
height();
167 for (
int ix = 0; ix < width; ++ix) {
169 for (
auto y_coord : y_coords[ix]) {
171 int gap = y_edge -
y;
174 (*minruns)(ix,
y) = gap;
179 int gap = height -
y;
181 (*minruns)(ix,
y) = gap;
186 for (
int iy = 0; iy < height; ++iy) {
188 for (
auto x_coord : x_coords[iy]) {
190 int gap = x_edge -
x;
192 if (gap < (*minruns)(
x, iy)) {
193 (*minruns)(
x, iy) = gap;
200 if (gap < (*minruns)(
x, iy)) {
201 (*minruns)(
x, iy) = gap;
227static void ComputeEdgeDensityProfiles(
const TBOX &box,
const GENERIC_2D_ARRAY<int> &minruns,
228 std::vector<float> &hx, std::vector<float> &hy) {
229 int width = box.width();
230 int height = box.height();
232 hx.resize(width + 1);
234 hy.resize(height + 1);
236 for (
int iy = 0; iy < height; ++iy) {
237 for (
int ix = 0; ix < width; ++ix) {
238 int run = minruns(ix, iy);
242 float density = 1.0f / run;
250 for (
int ix = 0; ix < width; ++ix) {
253 for (
int iy = 0; iy < height; ++iy) {
274 float target_height,
float final_xshift,
float final_yshift,
275 const std::vector<std::vector<int>> &x_coords,
276 const std::vector<std::vector<int>> &y_coords) {
282 x_map_ =
new std::vector<float>;
283 y_map_ =
new std::vector<float>;
285 int width = box.
width();
286 int height = box.
height();
288 ComputeRunlengthImage(box, x_coords, y_coords, &minruns);
291 ComputeEdgeDensityProfiles(box, minruns, *x_map_, *y_map_);
294 (*x_map_)[width] = target_width;
295 for (
int x = width - 1;
x >= 0; --
x) {
296 (*x_map_)[
x] = (*x_map_)[
x + 1] - (*x_map_)[
x] * target_width;
298 (*y_map_)[height] = target_height;
299 for (
int y = height - 1;
y >= 0; --
y) {
300 (*y_map_)[
y] = (*y_map_)[
y + 1] - (*y_map_)[
y] * target_height;
302 x_origin_ = box.
left();
304 final_xshift_ = final_xshift;
305 final_yshift_ = final_yshift;
318 FCOORD translated(pt.
x() - x_origin_, pt.
y() - y_origin_);
319 if (x_map_ !=
nullptr && y_map_ !=
nullptr) {
321 translated.
set_x((*x_map_)[
x]);
323 translated.
set_y((*y_map_)[
y]);
325 translated.
set_x(translated.
x() * x_scale_);
326 translated.
set_y(translated.
y() * y_scale_);
327 if (rotation_ !=
nullptr) {
328 translated.
rotate(*rotation_);
331 transformed->
set_x(translated.
x() + final_xshift_);
332 transformed->
set_y(translated.
y() + final_yshift_);
349 if (first_norm !=
this) {
350 if (predecessor_ !=
nullptr) {
352 }
else if (block_ !=
nullptr) {
354 src_pt.
rotate(fwd_rotation);
371 FCOORD rotated(pt.
x() - final_xshift_, pt.
y() - final_yshift_);
372 if (x_map_ !=
nullptr && y_map_ !=
nullptr) {
373 auto pos = std::upper_bound(x_map_->begin(), x_map_->end(), rotated.
x());
374 if (pos > x_map_->begin()) {
377 auto x = pos - x_map_->begin();
378 original->
set_x(
x + x_origin_);
379 pos = std::upper_bound(y_map_->begin(), y_map_->end(), rotated.
y());
380 if (pos > y_map_->begin()) {
383 auto y = pos - y_map_->begin();
384 original->
set_y(
y + y_origin_);
386 if (rotation_ !=
nullptr) {
387 FCOORD inverse_rotation(rotation_->
x(), -rotation_->
y());
388 rotated.
rotate(inverse_rotation);
390 original->
set_x(rotated.
x() / x_scale_ + x_origin_);
410 if (last_denorm !=
this) {
411 if (predecessor_ !=
nullptr) {
413 }
else if (block_ !=
nullptr) {
423 blob->
Move(translation);
424 if (y_scale_ != 1.0f) {
425 blob->
Scale(y_scale_);
427 if (rotation_ !=
nullptr) {
432 blob->
Move(translation);
440 float *min_xht,
float *max_xht,
float *yshift)
const {
461 int min_bottom, max_bottom, min_top, max_top;
462 unicharset.
get_top_bottom(unichar_id, &min_bottom, &max_bottom, &min_top, &max_top);
465 double midx = (bbox.
left() + bbox.
right()) / 2.0;
466 double ydiff = (bbox.
top() - bbox.
bottom()) + 2.0;
468 FCOORD mid_high(midx, bbox.
bottom() + ydiff), tmid_high;
476 int bln_yshift = 0, bottom_shift = 0, top_shift = 0;
477 if (bottom < min_bottom - tolerance) {
478 bottom_shift = bottom - min_bottom;
479 }
else if (bottom > max_bottom + tolerance) {
480 bottom_shift = bottom - max_bottom;
482 if (top < min_top - tolerance) {
483 top_shift = top - min_top;
484 }
else if (top > max_top + tolerance) {
485 top_shift = top - max_top;
487 if ((top_shift >= 0 && bottom_shift > 0) || (top_shift < 0 && bottom_shift < 0)) {
488 bln_yshift = (top_shift + bottom_shift) / 2;
490 *yshift = bln_yshift * yscale;
507 float result = height *
kBlnXHeight * yscale / min_height;
509 result = height *
kBlnXHeight * yscale / max_height;
516 if (pix_ !=
nullptr) {
517 tprintf(
"Pix dimensions %d x %d x %d\n", pixGetWidth(pix_), pixGetHeight(pix_),
526 tprintf(
"Input Origin = (%g, %g)\n", x_origin_, y_origin_);
527 if (x_map_ !=
nullptr && y_map_ !=
nullptr) {
529 for (
auto x : *x_map_) {
533 for (
auto y : *y_map_) {
538 tprintf(
"Scale = (%g, %g)\n", x_scale_, y_scale_);
539 if (rotation_ !=
nullptr) {
540 tprintf(
"Rotation = (%g, %g)\n", rotation_->
x(), rotation_->
y());
543 tprintf(
"Final Origin = (%g, %g)\n", final_xshift_, final_xshift_);
544 if (predecessor_ !=
nullptr) {
546 predecessor_->
Print();
553void DENORM::Clear() {
568 predecessor_ =
nullptr;
575 final_xshift_ = 0.0f;
const int kSloppyTolerance
void tprintf(const char *format,...)
int IntCastRounded(double x)
const float kFinalPixelTolerance
T ClipToRange(const T &x, const T &lower_bound, const T &upper_bound)
const int kBlnBaselineOffset
void Move(const ICOORD vec)
void Rotate(const FCOORD rotation)
const DENORM * predecessor() const
void SetupNormalization(const BLOCK *block, const FCOORD *rotation, const DENORM *predecessor, float x_origin, float y_origin, float x_scale, float y_scale, float final_xshift, float final_yshift)
void NormTransform(const DENORM *first_norm, const TPOINT &pt, TPOINT *transformed) const
void XHeightRange(int unichar_id, const UNICHARSET &unicharset, const TBOX &bbox, float *min_xht, float *max_xht, float *yshift) const
void DenormTransform(const DENORM *last_denorm, const TPOINT &pt, TPOINT *original) const
void SetupNonLinear(const DENORM *predecessor, const TBOX &box, float target_width, float target_height, float final_xshift, float final_yshift, const std::vector< std::vector< int > > &x_coords, const std::vector< std::vector< int > > &y_coords)
void LocalDenormTransform(const TPOINT &pt, TPOINT *original) const
void LocalNormTransform(const TPOINT &pt, TPOINT *transformed) const
void LocalNormBlob(TBLOB *blob) const
const BLOCK * block() const
DENORM & operator=(const DENORM &)
FCOORD re_rotation() const
void set_x(TDimension xin)
rewrite function
void set_y(TDimension yin)
rewrite function
void set_y(float yin)
rewrite function
float pt_to_pt_dist(const FCOORD &pt) const
Distance between pts.
void set_x(float xin)
rewrite function
void rotate(const FCOORD vec)
TDimension height() const
TDimension bottom() const
bool script_has_upper_lower() const
void get_top_bottom(UNICHAR_ID unichar_id, int *min_bottom, int *max_bottom, int *min_top, int *max_top) const
bool top_bottom_useful() const