Exemplo n.º 1
0
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 &xmax) {
  inT16 stepindex;               //current point
  ICOORD pos;                    //current coords
  ICOORD vec;                    //rotated step
  C_OUTLINE *outline;            //current outline
                                 //outlines
  C_OUTLINE_IT out_it = blob->out_list ();

  xmin = (float) MAX_INT32;
  xmax = (float) -MAX_INT32;
  for (out_it.mark_cycle_pt (); !out_it.cycled_list (); out_it.forward ()) {
    outline = out_it.data ();
    pos = outline->start_pos (); //get coords
    for (stepindex = 0; stepindex < outline->pathlength (); stepindex++) {
                                 //inside
      if (pos.y () >= bottomy && pos.y () <= topy) {
        UpdateRange(pos.x(), &xmin, &xmax);
      }
      vec = outline->step (stepindex);
      pos += vec;                //move to next
    }
  }
}
Exemplo n.º 2
0
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) {
  INT16 stepindex;               //current point
  ICOORD pos;                    //current coords
  ICOORD vec;                    //rotated step
  C_OUTLINE *outline;            //current outline
                                 //outlines
  C_OUTLINE_IT out_it = blob->out_list ();

  ymin = (float) MAX_INT32;
  ymax = (float) -MAX_INT32;
  for (out_it.mark_cycle_pt (); !out_it.cycled_list (); out_it.forward ()) {
    outline = out_it.data ();
    pos = outline->start_pos (); //get coords
    for (stepindex = 0; stepindex < outline->pathlength (); stepindex++) {
                                 //inside
      if (pos.x () >= leftx && pos.x () <= rightx) {
        if (pos.y () > ymax)
          ymax = pos.y ();
        if (pos.y () < ymin)
          ymin = pos.y ();
      }
      vec = outline->step (stepindex);
      pos += vec;                //move to next
    }
  }
}
Exemplo n.º 3
0
inT32 C_OUTLINE::area() {  //winding number
  int stepindex;                 //current step
  inT32 total_steps;             //steps to do
  inT32 total;                   //total area
  ICOORD pos;                    //position of point
  ICOORD next_step;              //step to next pix
  C_OUTLINE_IT it = child ();

  pos = start_pos ();
  total_steps = pathlength ();
  total = 0;
  for (stepindex = 0; stepindex < total_steps; stepindex++) {
                                 //all intersected
    next_step = step (stepindex);
    if (next_step.x () < 0)
      total += pos.y ();
    else if (next_step.x () > 0)
      total -= pos.y ();
    pos += next_step;
  }
  for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ())
    total += it.data ()->area ();//add areas of children

  return total;
}
Exemplo n.º 4
0
void POLY_BLOCK::compute_bb() {  //constructor
  ICOORD ibl, itr;               //integer bb
  ICOORD botleft;                //bounding box
  ICOORD topright;
  ICOORD pos;                    //current pos;
  ICOORDELT_IT pts = &vertices;  //iterator

  botleft = *pts.data ();
  topright = botleft;
  do {
    pos = *pts.data ();
    if (pos.x () < botleft.x ())
                                 //get bounding box
      botleft = ICOORD (pos.x (), botleft.y ());
    if (pos.y () < botleft.y ())
      botleft = ICOORD (botleft.x (), pos.y ());
    if (pos.x () > topright.x ())
      topright = ICOORD (pos.x (), topright.y ());
    if (pos.y () > topright.y ())
      topright = ICOORD (topright.x (), pos.y ());
    pts.forward ();
  }
  while (!pts.at_first ());
  ibl = ICOORD (botleft.x (), botleft.y ());
  itr = ICOORD (topright.x (), topright.y ());
  box = TBOX (ibl, itr);
}
Exemplo n.º 5
0
void C_OUTLINE::plot(                //draw it
                     ScrollView* window,       // window to draw in
                     ScrollView::Color colour  // colour to draw in
                    ) const {
  inT16 stepindex;               // index to cstep
  ICOORD pos;                    // current position
  DIR128 stepdir;                // direction of step

  pos = start;                   // current position
  window->Pen(colour);
  if (stepcount == 0) {
    window->Rectangle(box.left(), box.top(), box.right(), box.bottom());
    return;
  }
  window->SetCursor(pos.x(), pos.y());

  stepindex = 0;
  while (stepindex < stepcount) {
    pos += step(stepindex);    // step to next
    stepdir = step_dir(stepindex);
    stepindex++;               // count steps
    // merge straight lines
    while (stepindex < stepcount &&
           stepdir.get_dir() == step_dir(stepindex).get_dir()) {
      pos += step(stepindex);
      stepindex++;
    }
    window->DrawTo(pos.x(), pos.y());
  }
}
Exemplo n.º 6
0
void save_chop_cfragment(                            //chop the outline
                         int16_t head_index,           //head of fragment
                         ICOORD head_pos,            //head of fragment
                         int16_t tail_index,           //tail of fragment
                         ICOORD tail_pos,            //tail of fragment
                         C_OUTLINE *srcline,         //source of edgesteps
                         C_OUTLINE_FRAG_LIST *frags  //fragment list
                        ) {
  int16_t jump;                    //gap across end
  int16_t stepcount;               //total steps
  C_OUTLINE_FRAG *head;          //head of fragment
  C_OUTLINE_FRAG *tail;          //tail of fragment
  int16_t tail_y;                  //ycoord of tail

  ASSERT_HOST (tail_pos.x () == head_pos.x ());
  ASSERT_HOST (tail_index != head_index);
  stepcount = tail_index - head_index;
  if (stepcount < 0)
    stepcount += srcline->pathlength ();
  jump = tail_pos.y () - head_pos.y ();
  if (jump < 0)
    jump = -jump;
  if (jump == stepcount)
    return;                      //its a nop
  tail_y = tail_pos.y ();
  head = new C_OUTLINE_FRAG (head_pos, tail_pos, srcline,
    head_index, tail_index);
  tail = new C_OUTLINE_FRAG (head, tail_y);
  head->other_end = tail;
  add_frag_to_list(head, frags);
  add_frag_to_list(tail, frags);
}
Exemplo n.º 7
0
void vertical_coutline_projection(                     //project outlines
                                  C_OUTLINE *outline,  //outline to project
                                  STATS *stats         //output
                                 ) {
  ICOORD pos;                    //current point
  ICOORD step;                   //edge step
  inT32 length;                  //of outline
  inT16 stepindex;               //current step
  C_OUTLINE_IT out_it = outline->child ();

  pos = outline->start_pos ();
  length = outline->pathlength ();
  for (stepindex = 0; stepindex < length; stepindex++) {
    step = outline->step (stepindex);
    if (step.x () > 0) {
     stats->add (pos.x (), -pos.y ());
    } else if (step.x () < 0) {
      stats->add (pos.x () - 1, pos.y ());
    }
    pos += step;
  }

  for (out_it.mark_cycle_pt (); !out_it.cycled_list (); out_it.forward ()) {
    vertical_coutline_projection (out_it.data (), stats);
  }
}
Exemplo n.º 8
0
inT32 C_OUTLINE::area() const {
  int stepindex;                 //current step
  inT32 total_steps;             //steps to do
  inT32 total;                   //total area
  ICOORD pos;                    //position of point
  ICOORD next_step;              //step to next pix
  // We aren't going to modify the list, or its contents, but there is
  // no const iterator.
  C_OUTLINE_IT it(const_cast<C_OUTLINE_LIST*>(&children));

  pos = start_pos ();
  total_steps = pathlength ();
  total = 0;
  for (stepindex = 0; stepindex < total_steps; stepindex++) {
                                 //all intersected
    next_step = step (stepindex);
    if (next_step.x () < 0)
      total += pos.y ();
    else if (next_step.x () > 0)
      total -= pos.y ();
    pos += next_step;
  }
  for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ())
    total += it.data ()->area ();//add areas of children

  return total;
}
Exemplo n.º 9
0
OL_BUCKETS::OL_BUCKETS(
ICOORD bleft,                    // corners
ICOORD tright):         bl(bleft), tr(tright) {
  bxdim =(tright.x() - bleft.x()) / BUCKETSIZE + 1;
  bydim =(tright.y() - bleft.y()) / BUCKETSIZE + 1;
                                 // make array
  buckets = new C_OUTLINE_LIST[bxdim * bydim];
  index = 0;
}
Exemplo n.º 10
0
// (Re)Initialize the grid. The gridsize is the size in pixels of each cell,
// and bleft, tright are the bounding box of everything to go in it.
void GridBase::Init(int gridsize, const ICOORD& bleft, const ICOORD& tright) {
  gridsize_ = gridsize;
  bleft_ = bleft;
  tright_ = tright;
  if (gridsize_ == 0)
    gridsize_ = 1;
  gridwidth_ = (tright.x() - bleft.x() + gridsize_ - 1) / gridsize_;
  gridheight_ = (tright.y() - bleft.y() + gridsize_ - 1) / gridsize_;
  gridbuckets_ = gridwidth_ * gridheight_;
}
Exemplo n.º 11
0
/**********************************************************************
 * C_OUTLINE::C_OUTLINE
 *
 * Constructor to build a C_OUTLINE from a C_OUTLINE_FRAG.
 **********************************************************************/
C_OUTLINE::C_OUTLINE (
//constructor
                                 //steps to copy
ICOORD startpt, DIR128 * new_steps,
inT16 length                     //length of loop
):start (startpt), offsets(NULL) {
  inT8 dirdiff;                  //direction difference
  DIR128 prevdir;                //previous direction
  DIR128 dir;                    //current direction
  DIR128 lastdir;                //dir of last step
  TBOX new_box;                   //easy bounding
  inT16 stepindex;               //index to step
  inT16 srcindex;                //source steps
  ICOORD pos;                    //current position

  pos = startpt;
  stepcount = length;            // No. of steps.
  ASSERT_HOST(length >= 0);
  steps = reinterpret_cast<uinT8*>(alloc_mem(step_mem()));  // Get memory.
  memset(steps, 0, step_mem());

  lastdir = new_steps[length - 1];
  prevdir = lastdir;
  for (stepindex = 0, srcindex = 0; srcindex < length;
  stepindex++, srcindex++) {
    new_box = TBOX (pos, pos);
    box += new_box;
                                 //copy steps
    dir = new_steps[srcindex];
    set_step(stepindex, dir);
    dirdiff = dir - prevdir;
    pos += step (stepindex);
    if ((dirdiff == 64 || dirdiff == -64) && stepindex > 0) {
      stepindex -= 2;            //cancel there-and-back
      prevdir = stepindex >= 0 ? step_dir (stepindex) : lastdir;
    }
    else
      prevdir = dir;
  }
  ASSERT_HOST (pos.x () == startpt.x () && pos.y () == startpt.y ());
  do {
    dirdiff = step_dir (stepindex - 1) - step_dir (0);
    if (dirdiff == 64 || dirdiff == -64) {
      start += step (0);
      stepindex -= 2;            //cancel there-and-back
      for (int i = 0; i < stepindex; ++i)
        set_step(i, step_dir(i + 1));
    }
  }
  while (stepindex > 1 && (dirdiff == 64 || dirdiff == -64));
  stepcount = stepindex;
  ASSERT_HOST (stepcount >= 4);
}
Exemplo n.º 12
0
void PDBLK::plot(                //draw outline
                 ScrollView* window,  //window to draw in
                 inT32 serial,   //serial number
                 ScrollView::Color colour   //colour to draw in
                ) {
  ICOORD startpt;                //start of outline
  ICOORD endpt;                  //end of outline
  ICOORD prevpt;                 //previous point
  ICOORDELT_IT it = &leftside;   //iterator

                                 //set the colour
  window->Pen(colour);
  window->TextAttributes("Times", BLOCK_LABEL_HEIGHT, false, false, false);

  if (hand_poly != NULL) {
    hand_poly->plot(window, serial);
  } else if (!leftside.empty ()) {
    startpt = *(it.data ());     //bottom left corner
    //              tprintf("Block %d bottom left is (%d,%d)\n",
    //                      serial,startpt.x(),startpt.y());
    char temp_buff[34];
    #ifdef __UNIX__
    sprintf(temp_buff, INT32FORMAT, serial);
    #else
    ultoa (serial, temp_buff, 10);
    #endif
    window->Text(startpt.x (), startpt.y (), temp_buff);

    window->SetCursor(startpt.x (), startpt.y ());
    do {
      prevpt = *(it.data ());    //previous point
      it.forward ();             //move to next point
                                 //draw round corner
    window->DrawTo(prevpt.x (), it.data ()->y ());
    window->DrawTo(it.data ()->x (), it.data ()->y ());
    }
    while (!it.at_last ());      //until end of list
    endpt = *(it.data ());       //end point

                                 //other side of boundary
    window->SetCursor(startpt.x (), startpt.y ());
    it.set_to_list (&rightside);
    prevpt = startpt;
    for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
                                 //draw round corner
    window->DrawTo(prevpt.x (), it.data ()->y ());
    window->DrawTo(it.data ()->x (), it.data ()->y ());
      prevpt = *(it.data ());    //previous point
    }
                                 //close boundary
    window->DrawTo(endpt.x(), endpt.y());
  }
}
Exemplo n.º 13
0
// Renders the outline to the given pix, with left and top being
// the coords of the upper-left corner of the pix.
void C_OUTLINE::render(int left, int top, Pix* pix) const {
  ICOORD pos = start;
  for (int stepindex = 0; stepindex < stepcount; ++stepindex) {
    ICOORD next_step = step(stepindex);
    if (next_step.y() < 0) {
      pixRasterop(pix, 0, top - pos.y(), pos.x() - left, 1,
                  PIX_NOT(PIX_DST), NULL, 0, 0);
    } else if (next_step.y() > 0) {
      pixRasterop(pix, 0, top - pos.y() - 1, pos.x() - left, 1,
                  PIX_NOT(PIX_DST), NULL, 0, 0);
    }
    pos += next_step;
  }
}
Exemplo n.º 14
0
TBOX::TBOX(                   //construtor
         const ICOORD pt1,  //one corner
         const ICOORD pt2   //the other corner
        ) {
  if (pt1.x () <= pt2.x ()) {
    if (pt1.y () <= pt2.y ()) {
      bot_left = pt1;
      top_right = pt2;
    }
    else {
      bot_left = ICOORD (pt1.x (), pt2.y ());
      top_right = ICOORD (pt2.x (), pt1.y ());
    }
  }
  else {
    if (pt1.y () <= pt2.y ()) {
      bot_left = ICOORD (pt2.x (), pt1.y ());
      top_right = ICOORD (pt1.x (), pt2.y ());
    }
    else {
      bot_left = pt2;
      top_right = pt1;
    }
  }
}
Exemplo n.º 15
0
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) {
  int16_t stepindex;               //current point
  ICOORD pos;                    //current coords
  ICOORD vec;                    //rotated step
  C_OUTLINE *outline;            //current outline
                                 //outlines
  C_OUTLINE_IT out_it = blob->out_list ();

  ymin = (float) INT32_MAX;
  ymax = (float) -INT32_MAX;
  for (out_it.mark_cycle_pt (); !out_it.cycled_list (); out_it.forward ()) {
    outline = out_it.data ();
    pos = outline->start_pos (); //get coords
    pos.rotate (rotation);
    for (stepindex = 0; stepindex < outline->pathlength (); stepindex++) {
                                 //inside
      if (pos.x () >= leftx && pos.x () <= rightx) {
        UpdateRange(pos.y(), &ymin, &ymax);
      }
      vec = outline->step (stepindex);
      vec.rotate (rotation);
      pos += vec;                //move to next
    }
  }
}
Exemplo n.º 16
0
BOOL8 PDBLK::contains(           //test containment
                      ICOORD pt  //point to test
                     ) {
  BLOCK_RECT_IT it = this;       //rectangle iterator
  ICOORD bleft, tright;          //corners of rectangle

  for (it.start_block (); !it.cycled_rects (); it.forward ()) {
                                 //get rectangle
    it.bounding_box (bleft, tright);
                                 //inside rect
    if (pt.x () >= bleft.x () && pt.x () <= tright.x ()
      && pt.y () >= bleft.y () && pt.y () <= tright.y ())
      return TRUE;               //is inside
  }
  return FALSE;                  //not inside
}
Exemplo n.º 17
0
// As TraceOutlineOnReducedPix above, but on a BLOCK instead of a C_OUTLINE.
Pix* TraceBlockOnReducedPix(BLOCK* block, int gridsize,
                            ICOORD bleft, int* left, int* bottom) {
  TBOX box = block->bounding_box();
  Pix* pix = GridReducedPix(box, gridsize, bleft, left, bottom);
  int wpl = pixGetWpl(pix);
  l_uint32* data = pixGetData(pix);
  ICOORDELT_IT it(block->poly_block()->points());
  for (it.mark_cycle_pt(); !it.cycled_list();) {
    ICOORD pos = *it.data();
    it.forward();
    ICOORD next_pos = *it.data();
    ICOORD line_vector = next_pos - pos;
    int major, minor;
    ICOORD major_step, minor_step;
    line_vector.setup_render(&major_step, &minor_step, &major, &minor);
    int accumulator = major / 2;
    while (pos != next_pos) {
      int grid_x = (pos.x() - bleft.x()) / gridsize - *left;
      int grid_y = (pos.y() - bleft.y()) / gridsize - *bottom;
      SET_DATA_BIT(data + grid_y * wpl, grid_x);
      pos += major_step;
      accumulator += minor;
      if (accumulator >= major) {
        accumulator -= major;
        pos += minor_step;
      }
    }
  }
  return pix;
}
Exemplo n.º 18
0
C_OUTLINE_FRAG::C_OUTLINE_FRAG(                     //record fragment
                               ICOORD start_pt,     //start coord
                               ICOORD end_pt,       //end coord
                               C_OUTLINE *outline,  //source of steps
                               int16_t start_index,
                               int16_t end_index) {
  start = start_pt;
  end = end_pt;
  ycoord = start_pt.y ();
  stepcount = end_index - start_index;
  if (stepcount < 0)
    stepcount += outline->pathlength ();
  ASSERT_HOST (stepcount > 0);
  steps = new DIR128[stepcount];
  if (end_index > start_index) {
    for (int i = start_index; i < end_index; ++i)
      steps[i - start_index] = outline->step_dir(i);
  }
  else {
    int len = outline->pathlength();
    int i = start_index;
    for (; i < len; ++i)
      steps[i - start_index] = outline->step_dir(i);
    if (end_index > 0)
      for (; i < end_index + len; ++i)
        steps[i - start_index] = outline->step_dir(i - len);
  }
  other_end = nullptr;
  delete close();
}
Exemplo n.º 19
0
// Renders just the outline to the given pix (no fill), with left and top
// being the coords of the upper-left corner of the pix.
void C_OUTLINE::render_outline(int left, int top, Pix* pix) const {
  ICOORD pos = start;
  for (int stepindex = 0; stepindex < stepcount; ++stepindex) {
    ICOORD next_step = step(stepindex);
    if (next_step.y() < 0) {
      pixSetPixel(pix, pos.x() - left, top - pos.y(), 1);
    } else if (next_step.y() > 0) {
      pixSetPixel(pix, pos.x() - left - 1, top - pos.y() - 1, 1);
    } else if (next_step.x() < 0) {
      pixSetPixel(pix, pos.x() - left - 1, top - pos.y(), 1);
    } else if (next_step.x() > 0) {
      pixSetPixel(pix, pos.x() - left, top - pos.y() - 1, 1);
    }
    pos += next_step;
  }
}
DLLSYM void block_edges(                      //get edges in a block
                        IMAGE *t_image,       //threshold image
                        PDBLK *block,         //block in image
                        ICOORD page_tr        //corner of page
                       ) {
  uinT8 margin;                  //margin colour
  inT16 x;                       //line coords
  inT16 y;                       //current line
  ICOORD bleft;                  //bounding box
  ICOORD tright;
  ICOORD block_bleft;            //bounding box
  ICOORD block_tright;
  int xindex;                    //index to pixel
  BLOCK_LINE_IT line_it = block; //line iterator
  IMAGELINE bwline;              //thresholded line
                                 //lines in progress
  CRACKEDGE **ptrline = new CRACKEDGE*[t_image->get_xsize()+1];
  block->bounding_box (bleft, tright); // block box
  block_bleft = bleft;
  block_tright = tright;
  for (x = tright.x () - bleft.x (); x >= 0; x--)
    ptrline[x] = NULL;           //no lines in progress

  bwline.init (t_image->get_xsize());

  margin = WHITE_PIX;

  for (y = tright.y () - 1; y >= bleft.y () - 1; y--) {
    if (y >= block_bleft.y () && y < block_tright.y ()) {
      t_image->get_line (bleft.x (), y, tright.x () - bleft.x (), &bwline,
        0);
      make_margins (block, &line_it, bwline.pixels, margin, bleft.x (),
        tright.x (), y);
    }
    else {
      x = tright.x () - bleft.x ();
      for (xindex = 0; xindex < x; xindex++)
        bwline.pixels[xindex] = margin;
    }
    line_edges (bleft.x (), y, tright.x () - bleft.x (),
      margin, bwline.pixels, ptrline);
  }

  free_crackedges(free_cracks);  //really free them
  free_cracks = NULL;
    delete [] ptrline;
  }
Exemplo n.º 21
0
// Helper function to compute a fictitious end point that is on a line
// of a given gradient through the given start.
ICOORD ComputeEndFromGradient(const ICOORD& start, double m) {
  if (m > 1.0 || m < -1.0) {
    // dy dominates. Force it to have the opposite sign of start.y() and
    // compute dx based on dy being as large as possible
    int dx = static_cast<int>(floor(MAX_INT16 / m));
    if (dx < 0) ++dx;  // Truncate towards 0.
    if (start.y() > 0) dx = - dx;  // Force dy to be opposite to start.y().
    // Constrain dx so the result fits in an inT16.
    while (start.x() + dx > MAX_INT16 || start.x() + dx < -MAX_INT16)
      dx /= 2;
    if (-1 <= dx && dx <= 1) {
      return ICOORD(start.x(), start.y() + 1);  // Too steep for anything else.
    }
    int y = start.y() + static_cast<int>(floor(dx * m + 0.5));
    ASSERT_HOST(-MAX_INT16 <= y && y <= MAX_INT16);
    return ICOORD(start.x() + dx, y);
  } else {
    // dx dominates. Force it to have the opposite sign of start.x() and
    // compute dy based on dx being as large as possible.
    int dy = static_cast<int>(floor(MAX_INT16 * m));
    if (dy < 0) ++dy;  // Truncate towards 0.
    if (start.x() > 0) dy = - dy;  // Force dx to be opposite to start.x().
    // Constrain dy so the result fits in an inT16.
    while (start.y() + dy > MAX_INT16 || start.y() + dy < -MAX_INT16)
      dy /= 2;
    if (-1 <= dy && dy <= 1) {
      return ICOORD(start.x() + 1, start.y());  // Too flat for anything else.
    }
    int x = start.x() + static_cast<int>(floor(dy / m + 0.5));
    ASSERT_HOST(-MAX_INT16 <= x && x <= MAX_INT16);
    return ICOORD(x, start.y() + dy);
  }
}
Exemplo n.º 22
0
inT16 POLY_BLOCK::winding_number(const ICOORD &point) {
  inT16 count;                   //winding count
  ICOORD pt;                     //current point
  ICOORD vec;                    //point to current point
  ICOORD vvec;                   //current point to next point
  inT32 cross;                   //cross product
  ICOORDELT_IT it = &vertices;   //iterator

  count = 0;
  do {
    pt = *it.data ();
    vec = pt - point;
    vvec = *it.data_relative (1) - pt;
                                 //crossing the line
    if (vec.y () <= 0 && vec.y () + vvec.y () > 0) {
      cross = vec * vvec;        //cross product
      if (cross > 0)
        count++;                 //crossing right half
      else if (cross == 0)
        return INTERSECTING;     //going through point
    }
    else if (vec.y () > 0 && vec.y () + vvec.y () <= 0) {
      cross = vec * vvec;
      if (cross < 0)
        count--;                 //crossing back
      else if (cross == 0)
        return INTERSECTING;     //illegal
    }
    else if (vec.y () == 0 && vec.x () == 0)
      return INTERSECTING;
    it.forward ();
  }
  while (!it.at_first ());
  return count;                  //winding number
}
Exemplo n.º 23
0
// Moves by the given vec in place.
void TESSLINE::Move(const ICOORD vec) {
  EDGEPT* pt = loop;
  do {
    pt->pos.x += vec.x();
    pt->pos.y += vec.y();
    pt = pt->next;
  } while (pt != loop);
  SetupFromPos();
}
Exemplo n.º 24
0
void block_edges(Pix *t_pix,           // thresholded image
                 PDBLK *block,         // block in image
                 C_OUTLINE_IT* outline_it) {
  ICOORD bleft;                  // bounding box
  ICOORD tright;
  BLOCK_LINE_IT line_it = block; // line iterator

  int width = pixGetWidth(t_pix);
  int height = pixGetHeight(t_pix);
  int wpl = pixGetWpl(t_pix);
                                 // lines in progress
  CRACKEDGE **ptrline = new CRACKEDGE*[width + 1];
  CRACKEDGE *free_cracks = NULL;

  block->bounding_box(bleft, tright);  // block box
  int block_width = tright.x() - bleft.x();
  for (int x = block_width; x >= 0; x--)
    ptrline[x] = NULL;           //  no lines in progress

  uinT8* bwline = new uinT8[width];

  uinT8 margin = WHITE_PIX;

  for (int y = tright.y() - 1; y >= bleft.y() - 1; y--) {
    if (y >= bleft.y() && y < tright.y()) {
      // Get the binary pixels from the image.
      l_uint32* line = pixGetData(t_pix) + wpl * (height - 1 - y);
      for (int x = 0; x < block_width; ++x) {
        bwline[x] = GET_DATA_BIT(line, x + bleft.x()) ^ 1;
      }
      make_margins(block, &line_it, bwline, margin, bleft.x(), tright.x(), y);
    } else {
      memset(bwline, margin, block_width * sizeof(bwline[0]));
    }
    line_edges(bleft.x(), y, block_width,
               margin, bwline, ptrline, &free_cracks, outline_it);
  }

  free_crackedges(free_cracks);  // really free them
  delete[] ptrline;
  delete[] bwline;
}
Exemplo n.º 25
0
inT16 loop_bounding_box(                    //get bounding box
                        CRACKEDGE *&start,  //edge loop
                        ICOORD &botleft,    //bounding box
                        ICOORD &topright) {
  inT16 length;                  //length of loop
  inT16 leftmost;                //on top row
  CRACKEDGE *edgept;             //current point
  CRACKEDGE *realstart;          //topleft start

  edgept = start;
  realstart = start;
  botleft = topright = ICOORD (edgept->pos.x (), edgept->pos.y ());
  leftmost = edgept->pos.x ();
  length = 0;                    //coutn length
  do {
    edgept = edgept->next;
    if (edgept->pos.x () < botleft.x ())
                                 //get bounding box
      botleft.set_x (edgept->pos.x ());
    else if (edgept->pos.x () > topright.x ())
      topright.set_x (edgept->pos.x ());
    if (edgept->pos.y () < botleft.y ())
                                 //get bounding box
      botleft.set_y (edgept->pos.y ());
    else if (edgept->pos.y () > topright.y ()) {
      realstart = edgept;
      leftmost = edgept->pos.x ();
      topright.set_y (edgept->pos.y ());
    }
    else if (edgept->pos.y () == topright.y ()
    && edgept->pos.x () < leftmost) {
                                 //leftmost on line
      leftmost = edgept->pos.x ();
      realstart = edgept;
    }
    length++;                    //count elements
  }
  while (edgept != start);
  start = realstart;             //shift it to topleft
  return length;
}
Exemplo n.º 26
0
// Adds sub-pixel resolution EdgeOffsets for the outline using only
// a binary image source.
// Runs a sliding window of 5 edge steps over the outline, maintaining a count
// of the number of steps in each of the 4 directions in the window, and a
// sum of the x or y position of each step (as appropriate to its direction.)
// Ignores single-count steps EXCEPT the sharp U-turn and smoothes out the
// perpendicular direction. Eg
// ___              ___       Chain code from the left:
//    |___    ___   ___|      222122212223221232223000
//        |___|  |_|          Corresponding counts of each direction:
//                          0   00000000000000000123
//                          1   11121111001111100000
//                          2   44434443443333343321
//                          3   00000001111111112111
// Count of direction at center 41434143413313143313
// Step gets used?              YNYYYNYYYNYYNYNYYYyY (y= U-turn exception)
// Path redrawn showing only the used points:
// ___              ___
//     ___    ___   ___|
//         ___    _
// Sub-pixel edge position cannot be shown well with ASCII-art, but each
// horizontal step's y position is the mean of the y positions of the steps
// in the same direction in the sliding window, which makes a much smoother
// outline, without losing important detail.
void C_OUTLINE::ComputeBinaryOffsets() {
  delete [] offsets;
  offsets = new EdgeOffset[stepcount];
  // Count of the number of steps in each direction in the sliding window.
  int dir_counts[4];
  // Sum of the positions (y for a horizontal step, x for vertical) in each
  // direction in the sliding window.
  int pos_totals[4];
  memset(dir_counts, 0, sizeof(dir_counts));
  memset(pos_totals, 0, sizeof(pos_totals));
  ICOORD pos = start;
  ICOORD tail_pos = pos;
  // tail_pos is the trailing position, with the next point to be lost from
  // the window.
  tail_pos -= step(stepcount - 1);
  tail_pos -= step(stepcount - 2);
  // head_pos is the leading position, with the next point to be added to the
  // window.
  ICOORD head_pos = tail_pos;
  // Set up the initial window with 4 points in [-2, 2)
  for (int s = -2; s < 2; ++s) {
    increment_step(s, 1, &head_pos, dir_counts, pos_totals);
  }
  for (int s = 0; s < stepcount; pos += step(s++)) {
    // At step s, s in in the middle of [s-2, s+2].
    increment_step(s + 2, 1, &head_pos, dir_counts, pos_totals);
    int dir_index = chain_code(s);
    ICOORD step_vec = step(s);
    int best_diff = 0;
    int offset = 0;
    // Use only steps that have a count of >=2 OR the strong U-turn with a
    // single d and 2 at d-1 and 2 at d+1 (mod 4).
    if (dir_counts[dir_index] >= 2 || (dir_counts[dir_index] == 1 &&
        dir_counts[Modulo(dir_index - 1, 4)] == 2 &&
        dir_counts[Modulo(dir_index + 1, 4)] == 2)) {
      // Valid step direction.
      best_diff = dir_counts[dir_index];
      int edge_pos = step_vec.x() == 0 ? pos.x() : pos.y();
      // The offset proposes that the actual step should be positioned at
      // the mean position of the steps in the window of the same direction.
      // See ASCII art above.
      offset = pos_totals[dir_index] - best_diff * edge_pos;
    }
    offsets[s].offset_numerator =
        static_cast<inT8>(ClipToRange(offset, -MAX_INT8, MAX_INT8));
    offsets[s].pixel_diff = static_cast<uinT8>(ClipToRange(best_diff, 0 ,
                                                           MAX_UINT8));
    // The direction is just the vector from start to end of the window.
    FCOORD direction(head_pos.x() - tail_pos.x(), head_pos.y() - tail_pos.y());
    offsets[s].direction = direction.to_direction();
    increment_step(s - 2, -1, &tail_pos, dir_counts, pos_totals);
  }
}
Exemplo n.º 27
0
inT16 BLOCK_LINE_IT::get_line(             //get a line
                              inT16 y,     //line to get
                              inT16 &xext  //output extent
                             ) {
  ICOORD bleft;                  //bounding box
  ICOORD tright;                 //of block & rect

                                 //get block box
  block->bounding_box (bleft, tright);
  if (y < bleft.y () || y >= tright.y ()) {
    //              block->print(stderr,FALSE);
    BADBLOCKLINE.error ("BLOCK_LINE_IT::get_line", ABORT, "Y=%d", y);
  }

                                 //get rectangle box
  rect_it.bounding_box (bleft, tright);
                                 //inside rectangle
  if (y >= bleft.y () && y < tright.y ()) {
                                 //width of line
    xext = tright.x () - bleft.x ();
    return bleft.x ();           //start of line
  }
  for (rect_it.start_block (); !rect_it.cycled_rects (); rect_it.forward ()) {
                                 //get rectangle box
    rect_it.bounding_box (bleft, tright);
                                 //inside rectangle
    if (y >= bleft.y () && y < tright.y ()) {
                                 //width of line
      xext = tright.x () - bleft.x ();
      return bleft.x ();         //start of line
    }
  }
  LOSTBLOCKLINE.error ("BLOCK_LINE_IT::get_line", ABORT, "Y=%d", y);
  return 0;                      //dummy to stop warning
}
Exemplo n.º 28
0
inT16 C_OUTLINE::winding_number(              //winding number
                                ICOORD point  //point to wind around
                               ) const {
  inT16 stepindex;               //index to cstep
  inT16 count;                   //winding count
  ICOORD vec;                    //to current point
  ICOORD stepvec;                //step vector
  inT32 cross;                   //cross product

  vec = start - point;           //vector to it
  count = 0;
  for (stepindex = 0; stepindex < stepcount; stepindex++) {
    stepvec = step (stepindex);  //get the step
                                 //crossing the line
    if (vec.y () <= 0 && vec.y () + stepvec.y () > 0) {
      cross = vec * stepvec;     //cross product
      if (cross > 0)
        count++;                 //crossing right half
      else if (cross == 0)
        return INTERSECTING;     //going through point
    }
    else if (vec.y () > 0 && vec.y () + stepvec.y () <= 0) {
      cross = vec * stepvec;
      if (cross < 0)
        count--;                 //crossing back
      else if (cross == 0)
        return INTERSECTING;     //illegal
    }
    vec += stepvec;              //sum vectors
  }
  return count;                  //winding number
}
Exemplo n.º 29
0
inT32 C_OUTLINE::outer_area() const {
  int stepindex;                 //current step
  inT32 total_steps;             //steps to do
  inT32 total;                   //total area
  ICOORD pos;                    //position of point
  ICOORD next_step;              //step to next pix

  pos = start_pos ();
  total_steps = pathlength ();
  if (total_steps == 0)
    return box.area();
  total = 0;
  for (stepindex = 0; stepindex < total_steps; stepindex++) {
                                 //all intersected
    next_step = step (stepindex);
    if (next_step.x () < 0)
      total += pos.y ();
    else if (next_step.x () > 0)
      total -= pos.y ();
    pos += next_step;
  }

  return total;
}
Exemplo n.º 30
0
// Helper function to return a scaled Pix with one pixel per grid cell,
// set (black) where the given outline enters the corresponding grid cell,
// and clear where the outline does not touch the grid cell.
// Also returns the grid coords of the bottom-left of the Pix, in *left
// and *bottom, which corresponds to (0, 0) on the Pix.
// Note that the Pix is used upside-down, with (0, 0) being the bottom-left.
Pix* TraceOutlineOnReducedPix(C_OUTLINE* outline, int gridsize,
                              ICOORD bleft, int* left, int* bottom) {
  TBOX box = outline->bounding_box();
  Pix* pix = GridReducedPix(box, gridsize, bleft, left, bottom);
  int wpl = pixGetWpl(pix);
  l_uint32* data = pixGetData(pix);
  int length = outline->pathlength();
  ICOORD pos = outline->start_pos();
  for (int i = 0; i < length; ++i) {
    int grid_x = (pos.x() - bleft.x()) / gridsize - *left;
    int grid_y = (pos.y() - bleft.y()) / gridsize - *bottom;
    SET_DATA_BIT(data + grid_y * wpl, grid_x);
    pos += outline->step(i);
  }
  return pix;
}