25 #include "allheaders.h" 50 inverse_ = src.inverse_;
51 predecessor_ = src.predecessor_;
54 if (src.rotation_ ==
nullptr)
57 rotation_ =
new FCOORD(*src.rotation_);
58 x_origin_ = src.x_origin_;
59 y_origin_ = src.y_origin_;
60 x_scale_ = src.x_scale_;
61 y_scale_ = src.y_scale_;
62 final_xshift_ = src.final_xshift_;
63 final_yshift_ = src.final_yshift_;
99 float x_origin,
float y_origin,
100 float x_scale,
float y_scale,
101 float final_xshift,
float final_yshift) {
104 if (rotation ==
nullptr)
107 rotation_ =
new FCOORD(*rotation);
109 x_origin_ = x_origin;
110 y_origin_ = y_origin;
113 final_xshift_ = final_xshift;
114 final_yshift_ = final_yshift;
156 static void ComputeRunlengthImage(
161 int width = box.
width();
162 int height = box.
height();
166 for (
int ix = 0; ix < width; ++ix) {
168 for (
int i = 0; i < y_coords[ix].size(); ++i) {
169 int y_edge =
ClipToRange(y_coords[ix][i], 0, height);
170 int gap = y_edge - y;
173 (*minruns)(ix, y) = gap;
178 int gap = height - y;
180 (*minruns)(ix, y) = gap;
185 for (
int iy = 0; iy < height; ++iy) {
187 for (
int i = 0; i < x_coords[iy].size(); ++i) {
188 int x_edge =
ClipToRange(x_coords[iy][i], 0, width);
189 int gap = x_edge - x;
191 if (gap < (*minruns)(x, iy))
192 (*minruns)(x, iy) = gap;
198 if (gap < (*minruns)(x, iy))
199 (*minruns)(x, iy) = gap;
224 static void ComputeEdgeDensityProfiles(
const TBOX& box,
228 int width = box.
width();
229 int height = box.
height();
233 for (
int iy = 0; iy < height; ++iy) {
234 for (
int ix = 0; ix < width; ++ix) {
235 int run = minruns(ix, iy);
236 if (run == 0) run = 1;
237 float density = 1.0f / run;
238 (*hx)[ix] += density;
239 (*hy)[iy] += density;
245 for (
int ix = 0; ix < width; ++ix) {
248 for (
int iy = 0; iy < height; ++iy) {
254 (*hy)[height] = 1.0f;
269 const DENORM* predecessor,
const TBOX& box,
float target_width,
270 float target_height,
float final_xshift,
float final_yshift,
281 int width = box.
width();
282 int height = box.
height();
284 ComputeRunlengthImage(box, x_coords, y_coords, &minruns);
287 ComputeEdgeDensityProfiles(box, minruns, x_map_, y_map_);
290 (*x_map_)[width] = target_width;
291 for (
int x = width - 1; x >= 0; --x) {
292 (*x_map_)[x] = (*x_map_)[x + 1] - (*x_map_)[x] * target_width;
294 (*y_map_)[height] = target_height;
295 for (
int y = height - 1; y >= 0; --y) {
296 (*y_map_)[y] = (*y_map_)[y + 1] - (*y_map_)[y] * target_height;
298 x_origin_ = box.
left();
300 final_xshift_ = final_xshift;
301 final_yshift_ = final_yshift;
314 FCOORD translated(pt.
x() - x_origin_, pt.
y() - y_origin_);
315 if (x_map_ !=
nullptr && y_map_ !=
nullptr) {
317 translated.set_x((*x_map_)[x]);
319 translated.set_y((*y_map_)[y]);
321 translated.set_x(translated.x() * x_scale_);
322 translated.set_y(translated.y() * y_scale_);
323 if (rotation_ !=
nullptr)
324 translated.rotate(*rotation_);
326 transformed->
set_x(translated.x() + final_xshift_);
327 transformed->
set_y(translated.y() + final_yshift_);
336 TPOINT* transformed)
const {
344 FCOORD* transformed)
const {
346 if (first_norm !=
this) {
347 if (predecessor_ !=
nullptr) {
349 }
else if (block_ !=
nullptr) {
352 src_pt.
rotate(fwd_rotation);
368 FCOORD rotated(pt.
x() - final_xshift_, pt.
y() - final_yshift_);
369 if (x_map_ !=
nullptr && y_map_ !=
nullptr) {
371 original->
set_x(x + x_origin_);
373 original->
set_y(y + y_origin_);
375 if (rotation_ !=
nullptr) {
376 FCOORD inverse_rotation(rotation_->
x(), -rotation_->
y());
377 rotated.
rotate(inverse_rotation);
379 original->
set_x(rotated.x() / x_scale_ + x_origin_);
401 if (last_denorm !=
this) {
402 if (predecessor_ !=
nullptr) {
404 }
else if (block_ !=
nullptr) {
415 blob->
Move(translation);
416 if (y_scale_ != 1.0f)
417 blob->
Scale(y_scale_);
418 if (rotation_ !=
nullptr)
422 blob->
Move(translation);
431 float* min_xht,
float* max_xht,
float* yshift)
const {
450 int min_bottom, max_bottom, min_top, max_top;
455 double midx = (bbox.
left() + bbox.
right()) / 2.0;
456 double ydiff = (bbox.
top() - bbox.
bottom()) + 2.0;
458 FCOORD mid_high(midx, bbox.
bottom() + ydiff), tmid_high;
463 double yscale = tmid_high.pt_to_pt_dist(tmid_bot) / ydiff;
466 int bln_yshift = 0, bottom_shift = 0, top_shift = 0;
467 if (bottom < min_bottom - tolerance) {
468 bottom_shift = bottom - min_bottom;
469 }
else if (bottom > max_bottom + tolerance) {
470 bottom_shift = bottom - max_bottom;
472 if (top < min_top - tolerance) {
473 top_shift = top - min_top;
474 }
else if (top > max_top + tolerance) {
475 top_shift = top - max_top;
477 if ((top_shift >= 0 && bottom_shift > 0) ||
478 (top_shift < 0 && bottom_shift < 0)) {
479 bln_yshift = (top_shift + bottom_shift) / 2;
481 *yshift = bln_yshift * yscale;
498 float result = height *
kBlnXHeight * yscale / min_height;
500 result = height *
kBlnXHeight * yscale / max_height;
507 if (pix_ !=
nullptr) {
508 tprintf(
"Pix dimensions %d x %d x %d\n",
509 pixGetWidth(pix_), pixGetHeight(pix_), pixGetDepth(pix_));
514 tprintf(
"Block rotation %g, %g\n",
517 tprintf(
"Input Origin = (%g, %g)\n", x_origin_, y_origin_);
518 if (x_map_ !=
nullptr && y_map_ !=
nullptr) {
520 for (
int x = 0; x < x_map_->
size(); ++x) {
524 for (
int y = 0; y < y_map_->
size(); ++y) {
529 tprintf(
"Scale = (%g, %g)\n", x_scale_, y_scale_);
530 if (rotation_ !=
nullptr)
531 tprintf(
"Rotation = (%g, %g)\n", rotation_->
x(), rotation_->
y());
533 tprintf(
"Final Origin = (%g, %g)\n", final_xshift_, final_xshift_);
534 if (predecessor_ !=
nullptr) {
536 predecessor_->
Print();
544 void DENORM::Clear() {
554 void DENORM::Init() {
559 predecessor_ =
nullptr;
566 final_xshift_ = 0.0f;
void NormTransform(const DENORM *first_norm, const TPOINT &pt, TPOINT *transformed) 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 LocalNormBlob(TBLOB *blob) const
bool script_has_upper_lower() const
void LocalDenormTransform(const TPOINT &pt, TPOINT *original) const
FCOORD re_rotation() const
void set_x(int16_t xin)
rewrite function
void SetupNonLinear(const DENORM *predecessor, const TBOX &box, float target_width, float target_height, float final_xshift, float final_yshift, const GenericVector< GenericVector< int > > &x_coords, const GenericVector< GenericVector< int > > &y_coords)
void rotate(const FCOORD vec)
const BLOCK * block() const
const int kBlnBaselineOffset
void set_x(float xin)
rewrite function
DENORM & operator=(const DENORM &)
void XHeightRange(int unichar_id, const UNICHARSET &unicharset, const TBOX &bbox, float *min_xht, float *max_xht, float *yshift) const
void LocalNormTransform(const TPOINT &pt, TPOINT *transformed) const
void DenormTransform(const DENORM *last_denorm, const TPOINT &pt, TPOINT *original) const
void get_top_bottom(UNICHAR_ID unichar_id, int *min_bottom, int *max_bottom, int *min_top, int *max_top) const
void init_to_size(int size, const T &t)
int IntCastRounded(double x)
void Rotate(const FCOORD rotation)
DLLSYM void tprintf(const char *format,...)
TBOX bounding_box() const
const DENORM * predecessor() const
const float kFinalPixelTolerance
int binary_search(const T &target) const
const int kSloppyTolerance
T ClipToRange(const T &x, const T &lower_bound, const T &upper_bound)
void set_y(int16_t yin)
rewrite function
void set_y(float yin)
rewrite function
bool top_bottom_useful() const
void Move(const ICOORD vec)