⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fpchop.cpp

📁 一OCR的相关资料。.希望对研究OCR的朋友有所帮助.
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/********************************************************************** * File:        fpchop.cpp  (Formerly fp_chop.c) * Description: Code to chop fixed pitch text into character cells. * Author:		Ray Smith * Created:		Thu Sep 16 11:14:15 BST 1993 * * (C) Copyright 1993, 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. * **********************************************************************/#include "mfcpch.h"#ifdef __UNIX__#include          <assert.h>#endif#include          "stderr.h"#include          "blobbox.h"#include          "lmedsq.h"#include          "statistc.h"#include          "drawtord.h"#include          "tovars.h"#include          "topitch.h"#include          "fpchop.h"#include          "notdll.h"#define EXTERNEXTERN INT_VAR (textord_fp_chop_error, 2,"Max allowed bending of chop cells");EXTERN double_VAR (textord_fp_chop_snap, 0.5,"Max distance of chop pt from vertex");ELISTIZE (OUTLINE_FRAG) ELISTIZE (C_OUTLINE_FRAG)//#undef ASSERT_HOST//#define ASSERT_HOST(x) if (!(x)) AfxMessageBox(#x);/********************************************************************** * fixed_pitch_words * * Make a ROW from a fixed pitch TO_ROW. **********************************************************************/ROW *fixed_pitch_words(                 //find lines                       TO_ROW *row,     //row to do                       FCOORD rotation  //for drawing                      ) {  BOOL8 bol;                     //start of line  UINT8 blanks;                  //in front of word  UINT8 new_blanks;              //blanks in empty cell  INT16 chop_coord;              //chop boundary  INT16 prev_chop_coord;         //start of cell  INT16 rep_left;                //left edge of rep word  ROW *real_row;                 //output row  OUTLINE_LIST left_outlines;    //in current blob  OUTLINE_LIST right_outlines;   //for next blob  C_OUTLINE_LIST left_coutlines;  C_OUTLINE_LIST right_coutlines;  PBLOB_LIST blobs;              //blobs in word  C_BLOB_LIST cblobs;  PBLOB_IT blob_it = &blobs;     //iterator  C_BLOB_IT cblob_it = &cblobs;  WERD_LIST words;  WERD_IT word_it = &words;      //new words                                 //repeated blobs  WERD_IT rep_it = &row->rep_words;  WERD *word;                    //new word  INT32 xstarts[2];              //row ends  double coeffs[3];              //quadratic  INT32 prev_x;                  //end of prev blob                                 //iterator  BLOBNBOX_IT box_it = row->blob_list ();                                 //boundaries  ICOORDELT_IT cell_it = &row->char_cells;#ifndef GRAPHICS_DISABLED  if (textord_show_page_cuts && to_win != NO_WINDOW) {    plot_row_cells (to_win, RED, row, 0, &row->char_cells);  }#endif  prev_x = -MAX_INT16;  bol = TRUE;  blanks = 0;  if (rep_it.empty ())    rep_left = MAX_INT16;  else    rep_left = rep_it.data ()->bounding_box ().left ();  if (box_it.empty ())    return NULL;                 //empty row  xstarts[0] = box_it.data ()->bounding_box ().left ();  if (rep_left < xstarts[0]) {    xstarts[0] = rep_left;  }  if (cell_it.empty () || row->char_cells.singleton ()) {    tprintf ("Row without enough char cells!\n");    tprintf ("Leftmost blob is at (%d,%d)\n",      box_it.data ()->bounding_box ().left (),      box_it.data ()->bounding_box ().bottom ());    return NULL;  }  ASSERT_HOST (!cell_it.empty () && !row->char_cells.singleton ());  prev_chop_coord = cell_it.data ()->x ();  word = NULL;  while (rep_left < cell_it.data ()->x ()) {    word = add_repeated_word (&rep_it, rep_left, prev_chop_coord,      blanks, row->fixed_pitch, &word_it);  }  cell_it.mark_cycle_pt ();  if (prev_chop_coord >= cell_it.data ()->x ())    cell_it.forward ();  for (; !cell_it.cycled_list (); cell_it.forward ()) {    chop_coord = cell_it.data ()->x ();    while (!box_it.empty ()    && box_it.data ()->bounding_box ().left () <= chop_coord) {      if (box_it.data ()->bounding_box ().right () > prev_x)        prev_x = box_it.data ()->bounding_box ().right ();      split_to_blob (box_it.extract (), chop_coord,        textord_fp_chop_error + 0.5f,        &left_outlines, &left_coutlines,        &right_outlines, &right_coutlines);      box_it.forward ();      while (!box_it.empty ()        && box_it.data ()->blob () == NULL      && box_it.data ()->cblob () == NULL) {        delete box_it.extract ();        box_it.forward ();      }    }    if ((!right_outlines.empty () || !right_coutlines.empty ())      && left_outlines.empty () && left_coutlines.empty ())      split_to_blob (NULL, chop_coord,        textord_fp_chop_error + 0.5f,        &left_outlines, &left_coutlines,        &right_outlines, &right_coutlines);    if (!left_outlines.empty ())      blob_it.add_after_then_move (new PBLOB (&left_outlines));    else if (!left_coutlines.empty ())      cblob_it.add_after_then_move (new C_BLOB (&left_coutlines));    else {      if (rep_left < chop_coord) {        if (rep_left > prev_chop_coord)          new_blanks = (UINT8) floor ((rep_left - prev_chop_coord)            / row->fixed_pitch + 0.5);        else          new_blanks = 0;      }      else {        if (chop_coord > prev_chop_coord)          new_blanks = (UINT8) floor ((chop_coord - prev_chop_coord)            / row->fixed_pitch + 0.5);        else          new_blanks = 0;      }      if (!blob_it.empty () || !cblob_it.empty ()) {        if (blanks < 1 && word != NULL && !word->flag (W_REP_CHAR))          blanks = 1;        if (!blob_it.empty ()) {                                 //make real word          word = new WERD (&blobs, blanks, NULL);          blob_it.set_to_list (&blobs);        }        else {          word = new WERD (&cblobs, blanks, NULL);          cblob_it.set_to_list (&cblobs);        }        word->set_flag (W_DONT_CHOP, TRUE);        word_it.add_after_then_move (word);        if (bol) {          word->set_flag (W_BOL, TRUE);          bol = FALSE;        }        blanks = new_blanks;      }      else        blanks += new_blanks;      while (rep_left < chop_coord) {        word = add_repeated_word (&rep_it, rep_left, prev_chop_coord,          blanks, row->fixed_pitch, &word_it);      }    }    if (prev_chop_coord < chop_coord)      prev_chop_coord = chop_coord;  }  if (!blob_it.empty () || !cblob_it.empty ()) {    if (!blob_it.empty ())                                 //last word on line      word = new WERD (&blobs, blanks, NULL);    else      word = new WERD (&cblobs, blanks, NULL);    word->set_flag (W_DONT_CHOP, TRUE);    word_it.add_after_then_move (word);    if (bol)      word->set_flag (W_BOL, TRUE);  }  ASSERT_HOST (word != NULL);  while (!rep_it.empty ()) {    add_repeated_word (&rep_it, rep_left, prev_chop_coord,      blanks, row->fixed_pitch, &word_it);  }                                 //at end of line  word_it.data ()->set_flag (W_EOL, TRUE);  if (prev_chop_coord > prev_x)    prev_x = prev_chop_coord;  xstarts[1] = prev_x + 1;  coeffs[0] = 0;  coeffs[1] = row->line_m ();  coeffs[2] = row->line_c ();  real_row = new ROW (row, (INT16) row->kern_size, (INT16) row->space_size);  word_it.set_to_list (real_row->word_list ());                                 //put words in row  word_it.add_list_after (&words);  real_row->recalc_bounding_box ();  return real_row;}/********************************************************************** * add_repeated_word * * Add repeated word into the row at the given point. **********************************************************************/WERD *add_repeated_word(                         //move repeated word                        WERD_IT *rep_it,         //repeated words                        INT16 &rep_left,         //left edge of word                        INT16 &prev_chop_coord,  //previous word end                        UINT8 &blanks,           //no of blanks                        float pitch,             //char cell size                        WERD_IT *word_it         //list of words                       ) {  WERD *word;                    //word to move  INT16 new_blanks;              //extra blanks  if (rep_left > prev_chop_coord) {    new_blanks = (UINT8) floor ((rep_left - prev_chop_coord) / pitch + 0.5);    blanks += new_blanks;  }  word = rep_it->extract ();  prev_chop_coord = word->bounding_box ().right ();  word_it->add_after_then_move (word);  word->set_blanks (blanks);  rep_it->forward ();  if (rep_it->empty ())    rep_left = MAX_INT16;  else    rep_left = rep_it->data ()->bounding_box ().left ();  blanks = 0;  return word;}/********************************************************************** * split_to_blob * * Split a BLOBNBOX across a vertical chop line and put the pieces * into a left outline list and a right outline list. **********************************************************************/void split_to_blob(                                 //split the blob                   BLOBNBOX *blob,                  //blob to split                   INT16 chop_coord,                //place to chop                   float pitch_error,               //allowed deviation                   OUTLINE_LIST *left_outlines,     //left half of chop                   C_OUTLINE_LIST *left_coutlines,  //for cblobs                   OUTLINE_LIST *right_outlines,    //right half of chop                   C_OUTLINE_LIST *right_coutlines) {  PBLOB *real_blob;              //blob to chop  C_BLOB *real_cblob;            //cblob to chop  if (blob != NULL) {    real_blob = blob->blob ();    real_cblob = blob->cblob ();  }  else {    real_blob = NULL;    real_cblob = NULL;  }  if (!right_outlines->empty () || real_blob != NULL)    fixed_chop_blob(real_blob,                    chop_coord,                    pitch_error,                    left_outlines,                    right_outlines);  else if (!right_coutlines->empty () || real_cblob != NULL)    fixed_chop_cblob(real_cblob,                     chop_coord,                     pitch_error,                     left_coutlines,                     right_coutlines);  if (blob != NULL)    delete blob;                 //free it}/********************************************************************** * fixed_chop_blob * * Chop the given blob (if any) and the existing right outlines to * produce a list of outlines left of the chop point and more to the right. **********************************************************************/void fixed_chop_blob(                              //split the blob                     PBLOB *blob,                  //blob to split                     INT16 chop_coord,             //place to chop                     float pitch_error,            //allowed deviation                     OUTLINE_LIST *left_outlines,  //left half of chop                     OUTLINE_LIST *right_outlines  //right half of chop                    ) {  OUTLINE *old_right;            //already there  OUTLINE_LIST new_outlines;     //new right ones                                 //ouput iterator  OUTLINE_IT left_it = left_outlines;                                 //in/out iterator  OUTLINE_IT right_it = right_outlines;  OUTLINE_IT new_it = &new_outlines;  OUTLINE_IT blob_it;            //outlines in blob  if (!right_it.empty ()) {    while (!right_it.empty ()) {      old_right = right_it.extract ();      right_it.forward ();      fixed_split_outline(old_right,                          chop_coord,                          pitch_error,                          &left_it,                          &new_it);    }    right_it.add_list_before (&new_outlines);  }  if (blob != NULL) {    blob_it.set_to_list (blob->out_list ());    for (blob_it.mark_cycle_pt (); !blob_it.cycled_list ();      blob_it.forward ())    fixed_split_outline (blob_it.extract (), chop_coord, pitch_error,        &left_it, &right_it);    delete blob;  }}/********************************************************************** * fixed_split_outline * * Chop the given outline (if necessary) placing the fragments which * fall either side of the chop line into the appropriate list. **********************************************************************/void fixed_split_outline(                      //chop the outline                         OUTLINE *srcline,     //source outline                         INT16 chop_coord,     //place to chop                         float pitch_error,    //allowed deviation                         OUTLINE_IT *left_it,  //left half of chop                         OUTLINE_IT *right_it  //right half of chop                        ) {  OUTLINE *child;                //child outline  BOX srcbox;                    //box of outline  OUTLINE_LIST left_ch;          //left children  OUTLINE_LIST right_ch;         //right children  OUTLINE_FRAG_LIST left_frags;  //chopped fragments  OUTLINE_FRAG_LIST right_frags;;  OUTLINE_IT left_ch_it = &left_ch;                                 //for whole children  OUTLINE_IT right_ch_it = &right_ch;                                 //for holes  OUTLINE_IT child_it = srcline->child ();  srcbox = srcline->bounding_box ();                                 //left of line  if (srcbox.left () + srcbox.right () <= chop_coord * 2                                 //and not far over    && srcbox.right () < chop_coord + pitch_error)                                 //stick whole in left    left_it->add_after_then_move (srcline);  else if (srcbox.left () + srcbox.right () > chop_coord * 2    && srcbox.left () > chop_coord - pitch_error)                                 //stick whole in right    right_it->add_before_stay_put (srcline);  else {                                 //needs real chopping    if (fixed_chop_outline (srcline, chop_coord, pitch_error,    &left_frags, &right_frags)) {      for (child_it.mark_cycle_pt (); !child_it.cycled_list ();      child_it.forward ()) {        child = child_it.extract ();        srcbox = child->bounding_box ();        if (srcbox.right () < chop_coord)          left_ch_it.add_after_then_move (child);        else if (srcbox.left () > chop_coord)          right_ch_it.add_after_then_move (child);        else {          if (fixed_chop_outline (child, chop_coord, pitch_error,            &left_frags, &right_frags))            delete child;          else {            if (srcbox.left () + srcbox.right () <= chop_coord * 2)              left_ch_it.add_after_then_move (child);            else              right_ch_it.add_after_then_move (child);          }        }      }      close_chopped_fragments(&left_frags, &left_ch, left_it);       close_chopped_fragments(&right_frags, &right_ch, right_it);       ASSERT_HOST (left_ch.empty () && right_ch.empty ());      //no children left

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -