| /********************************************************************** |
| * File: blobbox.h (Formerly blobnbox.h) |
| * Description: Code for the textord blob class. |
| * Author: Ray Smith |
| * Created: Thu Jul 30 09:08:51 BST 1992 |
| * |
| * (C) Copyright 1992, Hewlett-Packard Ltd. |
| ** Licensed under the Apache License, Version 2.0 (the "License"); |
| ** you may not use this file except in compliance with the License. |
| ** You may obtain a copy of the License at |
| ** http://www.apache.org/licenses/LICENSE-2.0 |
| ** Unless required by applicable law or agreed to in writing, software |
| ** distributed under the License is distributed on an "AS IS" BASIS, |
| ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| ** See the License for the specific language governing permissions and |
| ** limitations under the License. |
| * |
| **********************************************************************/ |
| |
| #ifndef BLOBBOX_H |
| #define BLOBBOX_H |
| |
| #include "varable.h" |
| #include "clst.h" |
| #include "elst2.h" |
| #include "werd.h" |
| #include "ocrblock.h" |
| #include "statistc.h" |
| |
| extern double_VAR_H (textord_error_weight, 3, |
| "Weighting for error in believability"); |
| |
| enum PITCH_TYPE |
| { |
| PITCH_DUNNO, //insufficient data |
| PITCH_DEF_FIXED, //definitely fixed |
| PITCH_MAYBE_FIXED, //could be |
| PITCH_DEF_PROP, |
| PITCH_MAYBE_PROP, |
| PITCH_CORR_FIXED, |
| PITCH_CORR_PROP |
| }; |
| |
| class BLOBNBOX; |
| ELISTIZEH (BLOBNBOX) |
| class BLOBNBOX:public ELIST_LINK |
| { |
| public: |
| BLOBNBOX() { //empty |
| blob_ptr = NULL; |
| cblob_ptr = NULL; |
| joined = FALSE; |
| reduced = FALSE; |
| area = 0; |
| } |
| BLOBNBOX( //constructor |
| PBLOB *srcblob) { |
| blob_ptr = srcblob; |
| cblob_ptr = NULL; |
| box = srcblob->bounding_box (); |
| joined = FALSE; |
| reduced = FALSE; |
| area = (int) srcblob->area (); |
| } |
| BLOBNBOX( //constructor |
| C_BLOB *srcblob) { |
| blob_ptr = NULL; |
| cblob_ptr = srcblob; |
| box = srcblob->bounding_box (); |
| joined = FALSE; |
| reduced = FALSE; |
| area = (int) srcblob->area (); |
| } |
| |
| //get bounding box |
| const TBOX &bounding_box() const { |
| return box; |
| } |
| //get bounding box |
| const TBOX &reduced_box() const { |
| return red_box; |
| } |
| void set_reduced_box( //set other box |
| TBOX new_box) { |
| red_box = new_box; |
| reduced = TRUE; |
| } |
| inT32 enclosed_area() const { //get area |
| return area; |
| } |
| |
| void rotate_box( //just box |
| FCOORD vec) { |
| box.rotate (vec); |
| } |
| |
| BOOL8 joined_to_prev() const { //access function |
| return joined != 0; |
| } |
| BOOL8 red_box_set() const { //access function |
| return reduced != 0; |
| } |
| void merge( //merge with next |
| BLOBNBOX *nextblob); |
| void chop( //fake chop blob |
| BLOBNBOX_IT *start_it, //location of this |
| BLOBNBOX_IT *blob_it, //iterator |
| FCOORD rotation, //for landscape |
| float xheight); //line height |
| |
| PBLOB *blob() { //access function |
| return blob_ptr; |
| } |
| C_BLOB *cblob() { //access function |
| return cblob_ptr; |
| } |
| |
| #ifndef GRAPHICS_DISABLED |
| void plot( //draw one |
| ScrollView* window, //window to draw in |
| ScrollView::Color blob_colour, //for outer bits |
| ScrollView::Color child_colour) { //for holes |
| if (blob_ptr != NULL) |
| blob_ptr->plot (window, blob_colour, child_colour); |
| if (cblob_ptr != NULL) |
| cblob_ptr->plot (window, blob_colour, child_colour); |
| } |
| #endif |
| |
| NEWDELETE2 (BLOBNBOX) private: |
| int area:30; //enclosed area |
| int joined:1; //joined to prev |
| int reduced:1; //reduced box set |
| TBOX box; //bounding box |
| TBOX red_box; //bounding box |
| PBLOB *blob_ptr; //poly blob |
| C_BLOB *cblob_ptr; //edgestep blob |
| }; |
| |
| class TO_ROW:public ELIST2_LINK |
| { |
| public: |
| TO_ROW() { |
| } //empty |
| TO_ROW( //constructor |
| BLOBNBOX *blob, //from first blob |
| float top, //of row //target height |
| float bottom, |
| float row_size); |
| |
| float max_y() const { //access function |
| return y_max; |
| } |
| float min_y() const { |
| return y_min; |
| } |
| float mean_y() const { |
| return (y_min + y_max) / 2.0f; |
| } |
| float initial_min_y() const { |
| return initial_y_min; |
| } |
| float line_m() const { //access to line fit |
| return m; |
| } |
| float line_c() const { |
| return c; |
| } |
| float line_error() const { |
| return error; |
| } |
| float parallel_c() const { |
| return para_c; |
| } |
| float parallel_error() const { |
| return para_error; |
| } |
| float believability() const { //baseline goodness |
| return credibility; |
| } |
| float intercept() const { //real parallel_c |
| return y_origin; |
| } |
| void add_blob( //put in row |
| BLOBNBOX *blob, //blob to add |
| float top, //of row //target height |
| float bottom, |
| float row_size); |
| void insert_blob( //put in row in order |
| BLOBNBOX *blob); |
| |
| BLOBNBOX_LIST *blob_list() { //get list |
| return &blobs; |
| } |
| |
| void set_line( //set line spec |
| float new_m, //line to set |
| float new_c, |
| float new_error) { |
| m = new_m; |
| c = new_c; |
| error = new_error; |
| } |
| void set_parallel_line( //set fixed gradient line |
| float gradient, //page gradient |
| float new_c, |
| float new_error) { |
| para_c = new_c; |
| para_error = new_error; |
| credibility = |
| (float) (blobs.length () - textord_error_weight * new_error); |
| y_origin = (float) (new_c / sqrt (1 + gradient * gradient)); |
| //real intercept |
| } |
| void set_limits( //set min,max |
| float new_min, //bottom and |
| float new_max) { //top of row |
| y_min = new_min; |
| y_max = new_max; |
| } |
| void compute_vertical_projection(); |
| //get projection |
| |
| //true when dead |
| NEWDELETE2 (TO_ROW) BOOL8 merged; |
| BOOL8 all_caps; //had no ascenders |
| BOOL8 used_dm_model; //in guessing pitch |
| inT16 projection_left; //start of projection |
| inT16 projection_right; //start of projection |
| PITCH_TYPE pitch_decision; //how strong is decision |
| float fixed_pitch; //pitch or 0 |
| float fp_space; //sp if fixed pitch |
| float fp_nonsp; //nonsp if fixed pitch |
| float pr_space; //sp if prop |
| float pr_nonsp; //non sp if prop |
| float spacing; //to "next" row |
| float xheight; //of line |
| float ascrise; //ascenders |
| float descdrop; //descenders |
| inT32 min_space; //min size for real space |
| inT32 max_nonspace; //max size of non-space |
| inT32 space_threshold; //space vs nonspace |
| float kern_size; //average non-space |
| float space_size; //average space |
| WERD_LIST rep_words; //repeated chars |
| ICOORDELT_LIST char_cells; //fixed pitch cells |
| QSPLINE baseline; //curved baseline |
| STATS projection; //vertical projection |
| |
| private: |
| BLOBNBOX_LIST blobs; //blobs in row |
| float y_min; //coords |
| float y_max; |
| float initial_y_min; |
| float m, c; //line spec |
| float error; //line error |
| float para_c; //constrained fit |
| float para_error; |
| float y_origin; //rotated para_c; |
| float credibility; //baseline believability |
| }; |
| |
| ELIST2IZEH (TO_ROW) |
| class TO_BLOCK:public ELIST_LINK |
| { |
| public: |
| TO_BLOCK() { |
| } //empty |
| TO_BLOCK( //constructor |
| BLOCK *src_block); //real block |
| ~TO_BLOCK(); |
| |
| TO_ROW_LIST *get_rows() { //access function |
| return &row_list; |
| } |
| |
| void print_rows() { //debug info |
| TO_ROW_IT row_it = &row_list; |
| TO_ROW *row; |
| |
| for (row_it.mark_cycle_pt (); !row_it.cycled_list (); |
| row_it.forward ()) { |
| row = row_it.data (); |
| printf ("Row range (%g,%g), para_c=%g, blobcount=" INT32FORMAT |
| "\n", row->min_y (), row->max_y (), row->parallel_c (), |
| row->blob_list ()->length ()); |
| } |
| } |
| |
| BLOBNBOX_LIST blobs; //medium size |
| BLOBNBOX_LIST underlines; //underline blobs |
| BLOBNBOX_LIST noise_blobs; //very small |
| BLOBNBOX_LIST small_blobs; //fairly small |
| BLOBNBOX_LIST large_blobs; //big blobs |
| BLOCK *block; //real block |
| PITCH_TYPE pitch_decision; //how strong is decision |
| float line_spacing; //estimate |
| float line_size; //estimate |
| float max_blob_size; //line assignment limit |
| float baseline_offset; //phase shift |
| float xheight; //median blob size |
| float fixed_pitch; //pitch or 0 |
| float kern_size; //average non-space |
| float space_size; //average space |
| inT32 min_space; //min definite space |
| inT32 max_nonspace; //max definite |
| float fp_space; //sp if fixed pitch |
| float fp_nonsp; //nonsp if fixed pitch |
| float pr_space; //sp if prop |
| float pr_nonsp; //non sp if prop |
| TO_ROW *key_row; //starting row |
| |
| NEWDELETE2 (TO_BLOCK) private: |
| TO_ROW_LIST row_list; //temporary rows |
| }; |
| |
| ELISTIZEH (TO_BLOCK) |
| extern double_VAR_H (textord_error_weight, 3, |
| "Weighting for error in believability"); |
| void find_blob_limits( //get y limits |
| PBLOB *blob, //blob to search |
| float leftx, //x limits |
| float rightx, |
| FCOORD rotation, //for landscape |
| float &ymin, //output y limits |
| float &ymax); |
| void find_cblob_limits( //get y limits |
| C_BLOB *blob, //blob to search |
| float leftx, //x limits |
| float rightx, |
| FCOORD rotation, //for landscape |
| float &ymin, //output y limits |
| float &ymax); |
| void find_cblob_vlimits( //get y limits |
| C_BLOB *blob, //blob to search |
| float leftx, //x limits |
| float rightx, |
| float &ymin, //output y limits |
| float &ymax); |
| void find_cblob_hlimits( //get x limits |
| C_BLOB *blob, //blob to search |
| float bottomy, //y limits |
| float topy, |
| float &xmin, //output x limits |
| float &xymax); |
| PBLOB *rotate_blob( //get y limits |
| PBLOB *blob, //blob to search |
| FCOORD rotation //vector to rotate by |
| ); |
| PBLOB *rotate_cblob( //rotate it |
| C_BLOB *blob, //blob to search |
| float xheight, //for poly approx |
| FCOORD rotation //for landscape |
| ); |
| C_BLOB *crotate_cblob( //rotate it |
| C_BLOB *blob, //blob to search |
| FCOORD rotation //for landscape |
| ); |
| TBOX box_next( //get bounding box |
| BLOBNBOX_IT *it //iterator to blobds |
| ); |
| TBOX box_next_pre_chopped( //get bounding box |
| BLOBNBOX_IT *it //iterator to blobds |
| ); |
| void vertical_blob_projection( //project outlines |
| PBLOB *blob, //blob to project |
| STATS *stats //output |
| ); |
| //project outlines |
| void vertical_outline_projection(OUTLINE *outline, //outline to project |
| STATS *stats //output |
| ); |
| void vertical_cblob_projection( //project outlines |
| C_BLOB *blob, //blob to project |
| STATS *stats //output |
| ); |
| void vertical_coutline_projection( //project outlines |
| C_OUTLINE *outline, //outline to project |
| STATS *stats //output |
| ); |
| #endif |