textord/scanedg.cpp

Go to the documentation of this file.
00001 
00020 #include          "mfcpch.h"
00021 #include          "edgloop.h"
00022 //#include                                      "dirtab.h"
00023 #include          "scanedg.h"
00024 
00025 #ifdef TEXT_VERBOSE
00026 #include           "../cutil/callcpp.h"
00027 #endif
00028 
00030 #define WHITE_PIX     1
00032 #define BLACK_PIX     0
00033 
00034 #define FLIP_COLOUR(pix)  (1-(pix))
00035 
00036 #define EWSIZE        4
00038 #define XMARGIN       2
00040 #define YMARGIN       3
00041 
00043 static CRACKEDGE *free_cracks = NULL;
00044 
00055 DLLSYM void block_edges(
00056                         IMAGE *t_image,
00057                         PDBLK *block,
00058                         ICOORD page_tr
00059                        ) {
00060   UINT8 margin;                  //margin colour
00061   INT16 x;                       //line coords
00062   INT16 y;                       //current line
00063   ICOORD bleft;                  //bounding box
00064   ICOORD tright;
00065   ICOORD block_bleft;            //bounding box
00066   ICOORD block_tright;
00067   int xindex;                    //index to pixel
00068   BLOCK_LINE_IT line_it = block; //line iterator
00069   IMAGELINE bwline;              //thresholded line
00070                                  //lines in progress
00071   CRACKEDGE *ptrlinemem[MAXIMAGEWIDTH];
00072   CRACKEDGE **ptrline = ptrlinemem;
00073 
00074   if (t_image->get_xsize()+1 > MAXIMAGEWIDTH) {
00075     ptrline = new CRACKEDGE*[t_image->get_xsize()+1];
00076   }
00077 
00078                                  //block box
00079   block->bounding_box (bleft, tright);
00080   block_bleft = bleft;
00081   block_tright = tright;
00082   for (x = tright.x () - bleft.x (); x >= 0; x--)
00083     ptrline[x] = NULL;           //no lines in progress
00084 
00085   bwline.init (t_image->get_xsize());
00086 
00087   margin = WHITE;
00088 
00089   for (y = tright.y () - 1; y >= bleft.y () - 1; y--) {
00090     if (y >= block_bleft.y () && y < block_tright.y ()) {
00091       t_image->get_line (bleft.x (), y, tright.x () - bleft.x (), &bwline,
00092         0);
00093       make_margins (block, &line_it, bwline.pixels, margin, bleft.x (),
00094         tright.x (), y);
00095     }
00096     else {
00097       x = tright.x () - bleft.x ();
00098       for (xindex = 0; xindex < x; xindex++)
00099         bwline.pixels[xindex] = margin;
00100     }
00101     line_edges (bleft.x (), y, tright.x () - bleft.x (),
00102       margin, bwline.pixels, ptrline);
00103   }
00104 
00105   free_crackedges(free_cracks);  //really free them
00106   free_cracks = NULL;
00107   if (ptrline != ptrlinemem) {
00108     delete [] ptrline;
00109   }
00110 }
00111 
00112 
00118 void make_margins(                         //get a line
00119                   PDBLK *block,            //block in image
00120                   BLOCK_LINE_IT *line_it,  //for old style
00121                   UINT8 *pixels,           //pixels to strip
00122                   UINT8 margin,            //white-out pixel
00123                   INT16 left,              //block edges
00124                   INT16 right,
00125                   INT16 y                  //line coord
00126                  ) {
00127   PB_LINE_IT *lines;
00128   ICOORDELT_LIST *segments;      //bits of a line
00129   ICOORDELT_IT seg_it;
00130   INT32 start;                   //of segment
00131   INT16 xext;                    //of segment
00132   int xindex;                    //index to pixel
00133 
00134   if (block->poly_block () != NULL) {
00135     lines = new PB_LINE_IT (block->poly_block ());
00136     segments = lines->get_line (y);
00137     if (!segments->empty ()) {
00138       seg_it.set_to_list (segments);
00139       seg_it.mark_cycle_pt ();
00140       start = seg_it.data ()->x ();
00141       xext = seg_it.data ()->y ();
00142       for (xindex = left; xindex < right; xindex++) {
00143         if (xindex >= start && !seg_it.cycled_list ()) {
00144           xindex = start + xext - 1;
00145           seg_it.forward ();
00146           start = seg_it.data ()->x ();
00147           xext = seg_it.data ()->y ();
00148         }
00149         else
00150           pixels[xindex - left] = margin;
00151       }
00152     }
00153     else {
00154       for (xindex = left; xindex < right; xindex++)
00155         pixels[xindex - left] = margin;
00156     }
00157     delete segments;
00158     delete lines;
00159   }
00160   else {
00161     start = line_it->get_line (y, xext);
00162     for (xindex = left; xindex < start; xindex++)
00163       pixels[xindex - left] = margin;
00164     for (xindex = start + xext; xindex < right; xindex++)
00165       pixels[xindex - left] = margin;
00166   }
00167 }
00168 
00169 
00175 void whiteout_block(                 //clean it
00176                     IMAGE *t_image,  //threshold image
00177                     PDBLK *block     //block in image
00178                    ) {
00179   INT16 x;                       //line coords
00180   INT16 y;                       //current line
00181   INT16 xext;                    //line width
00182   int xindex;                    //index to pixel
00183   UINT8 *dest;                   //destination pixel
00184   BOX block_box;                 //bounding box
00185   BLOCK_LINE_IT line_it = block; //line iterator
00186   IMAGELINE bwline;              //thresholded line
00187 
00188   block_box = block->bounding_box ();
00189   for (y = block_box.bottom (); y < block_box.top (); y++) {
00190                                  //find line limits
00191     x = line_it.get_line (y, xext);
00192     t_image->get_line (x, y, xext, &bwline, 0);
00193     dest = bwline.pixels;        //destination pixel
00194     for (xindex = 0; xindex < xext; xindex++)
00195       *dest++ = 1;
00196     t_image->put_line (x, y, xext, &bwline, 0);
00197   }
00198 }
00199 
00200 
00218 void line_edges (
00219    INT16 x,
00220    INT16 y,
00221    INT16 xext,
00222    UINT8 uppercolour,
00223    UINT8 * bwpos,
00224    CRACKEDGE ** prevline
00225 ) {
00226   int xpos;                      //current x coord
00227   int xmax;                      //max x coord
00228   int colour;                    //of current pixel
00229   int prevcolour;                //of previous pixel
00230   CRACKEDGE *current;            //current h edge
00231   CRACKEDGE *newcurrent;         //new h edge
00232 
00233 #if defined(TEXT_VERBOSE)
00234 #if defined(TV_FOCUSE)
00235   cprintf("\n"); // breaks up copious output into rows
00236 #endif
00237   cprintf("e"); // gets a 'e', see ccmain/tessvars.h
00238 #endif
00239   xmax = x + xext;               //max allowable coord
00240   prevcolour = uppercolour;      //forced plain margin
00241   current = NULL;                //nothing yet
00242 
00243                                  //do each pixel
00244   for (xpos = x; xpos < xmax; xpos++, prevline++) {
00245     colour = *bwpos++;           //current pixel
00246     if (*prevline != NULL) {
00247                                  //changed above
00248                                  //change colour
00249       uppercolour = FLIP_COLOUR (uppercolour);
00250       if (colour == prevcolour) {
00251         if (colour == uppercolour) {
00252                                  //finish a line
00253           join_edges(current, *prevline);
00254           current = NULL;        //no edge now
00255 #if defined(TEXT_VERBOSE) && defined(TV_FOCUSE)
00256   cprintf("C"); // check under 'e' in ccmain/tessvars.h
00257 #endif
00258         }
00259         else {
00260                                  //new horiz edge
00261           current = h_edge (xpos, y, uppercolour - colour, *prevline);
00262 #if defined(TEXT_VERBOSE) && defined(TV_FOCUSE)
00263   cprintf("L"); // check under 'e' in ccmain/tessvars.h
00264 #endif
00265       }
00266         *prevline = NULL;        //no change this time
00267       }
00268       else {
00269         if (colour == uppercolour) {
00270           *prevline = v_edge (xpos, y, colour - prevcolour, *prevline);
00271 #if defined(TEXT_VERBOSE) && defined(TV_FOCUSE)
00272   cprintf("K"); // check under 'e' in ccmain/tessvars.h
00273 #endif
00274       }
00275                                  //8 vs 4 connection
00276         else if (colour == WHITE_PIX) {
00277           join_edges(current, *prevline);
00278           current = h_edge (xpos, y, uppercolour - colour, NULL);
00279           *prevline = v_edge (xpos, y, colour - prevcolour, current);
00280 #if defined(TEXT_VERBOSE) && defined(TV_FOCUSE)
00281   cprintf("J"); // check under 'e' in ccmain/tessvars.h
00282 #endif
00283         }
00284         else {
00285           newcurrent = h_edge (xpos, y, uppercolour - colour, *prevline);
00286           *prevline = v_edge (xpos, y, colour - prevcolour, current);
00287           current = newcurrent;  //right going h edge
00288 #if defined(TEXT_VERBOSE) && defined(TV_FOCUSE)
00289   cprintf("H"); // check under 'e' in ccmain/tessvars.h
00290 #endif
00291         }
00292         prevcolour = colour;     //remember new colour
00293       }
00294     }
00295     else {
00296       if (colour != prevcolour) {
00297         *prevline = current =
00298           v_edge (xpos, y, colour - prevcolour, current);
00299         prevcolour = colour;
00300 #if defined(TEXT_VERBOSE) && defined(TV_FOCUSE)
00301   cprintf("D"); // check under 'e' in ccmain/tessvars.h
00302 #endif
00303       }
00304       if (colour != uppercolour) {
00305         current = h_edge (xpos, y, uppercolour - colour, current);
00306 #if defined(TEXT_VERBOSE) && defined(TV_FOCUSE)
00307   cprintf("E"); // check under 'e' in ccmain/tessvars.h
00308 #endif
00309      }
00310       else {
00311         current = NULL;          //no edge now
00312 #if defined(TEXT_VERBOSE) && defined(TV_FOCUSE)
00313   cprintf("="); // check under 'e' in ccmain/tessvars.h
00314 #endif
00315      }
00316     }
00317   }//for xpos
00318   if (current != NULL) {
00319                                  //out of block
00320     if (*prevline != NULL) {     //got one to join to?
00321       join_edges(current, *prevline);
00322       *prevline = NULL;          //tidy now
00323 #if defined(TEXT_VERBOSE) && defined(TV_FOCUSE)
00324   cprintf("M"); // check under 'e' in ccmain/tessvars.h
00325 #endif
00326     }
00327     else {
00328                                  //fake vertical
00329       *prevline = v_edge (xpos, y, FLIP_COLOUR(prevcolour)-prevcolour, current);
00330 #if defined(TEXT_VERBOSE) && defined(TV_FOCUSE)
00331   cprintf("N"); // check under 'e' in ccmain/tessvars.h
00332 #endif
00333     }
00334   }
00335   else if (*prevline != NULL) {
00336                                  //continue fake
00337     *prevline = v_edge (xpos, y, FLIP_COLOUR(prevcolour)-prevcolour, *prevline);
00338 #if defined(TEXT_VERBOSE) && defined(TV_FOCUSE)
00339   cprintf("O"); // check under 'e' in ccmain/tessvars.h
00340 #endif
00341   }
00342 }
00343 
00344 
00350 CRACKEDGE *
00351 h_edge (                         //horizontal edge
00352 INT16 x,                         //xposition
00353 INT16 y,                         //y position
00354 INT8 sign,                       //sign of edge
00355 CRACKEDGE * join                 //edge to join to
00356 ) {
00357   CRACKEDGE *newpt;              //return value
00358 
00359   //      check_mem("h_edge",JUSTCHECKS);
00360   if (free_cracks != NULL) {
00361     newpt = free_cracks;
00362     free_cracks = newpt->next;   //get one fast
00363 #if defined(TEXT_VERBOSE) && defined(TV_FOCUSC)
00364   cprintf("a"); // check under 'e' in ccmain/tessvars.h
00365 #endif
00366   }
00367   else {
00368     newpt = new CRACKEDGE;
00369 #if defined(TEXT_VERBOSE) && defined(TV_FOCUSC)
00370   cprintf("b"); // check under 'e' in ccmain/tessvars.h
00371 #endif
00372   }
00373   newpt->pos.set_y (y + 1);      //coords of pt
00374   newpt->stepy = 0;              //edge is horizontal
00375 
00376   if (sign > 0) {
00377     newpt->pos.set_x (x + 1);    //start location
00378     newpt->stepx = -1;
00379     newpt->stepdir = 0;
00380 #if defined(TEXT_VERBOSE) && defined(TV_FOCUSC)
00381   cprintf("c"); // check under 'e' in ccmain/tessvars.h
00382 #endif
00383   }
00384   else {
00385     newpt->pos.set_x (x);        //start location
00386     newpt->stepx = 1;
00387     newpt->stepdir = 2;
00388 #if defined(TEXT_VERBOSE) && defined(TV_FOCUSC)
00389   cprintf("d"); // check under 'e' in ccmain/tessvars.h
00390 #endif
00391   }
00392 
00393   if (join == NULL) {
00394     newpt->next = newpt;         //ptrs to other ends
00395     newpt->prev = newpt;
00396 #if defined(TEXT_VERBOSE) && defined(TV_FOCUSC)
00397   cprintf("f"); // check under 'e' in ccmain/tessvars.h
00398 #endif
00399   }
00400   else {
00401     if (newpt->pos.x () + newpt->stepx == join->pos.x ()
00402     && newpt->pos.y () == join->pos.y ()) {
00403       newpt->prev = join->prev;  //update other ends
00404       newpt->prev->next = newpt;
00405       newpt->next = join;        //join up
00406       join->prev = newpt;
00407 #if defined(TEXT_VERBOSE) && defined(TV_FOCUSC)
00408   cprintf("g"); // check under 'e' in ccmain/tessvars.h
00409 #endif
00410     }
00411     else {
00412       newpt->next = join->next;  //update other ends
00413       newpt->next->prev = newpt;
00414       newpt->prev = join;        //join up
00415       join->next = newpt;
00416 #if defined(TEXT_VERBOSE) && defined(TV_FOCUSC)
00417   cprintf("h"); // check under 'e' in ccmain/tessvars.h
00418 #endif
00419     }
00420   }
00421   return newpt;
00422 }
00423 
00424 
00430 CRACKEDGE *
00431 v_edge (                         //vertical edge
00432 INT16 x,                         //xposition
00433 INT16 y,                         //y position
00434 INT8 sign,                       //sign of edge
00435 CRACKEDGE * join                 //edge to join to
00436 ) {
00437   CRACKEDGE *newpt;              //return value
00438 
00439   if (free_cracks != NULL) {
00440     newpt = free_cracks;
00441     free_cracks = newpt->next;   //get one fast
00442 #if defined(TEXT_VERBOSE) && defined(TV_FOCUSD)
00443   cprintf("j"); // check under 'e' in ccmain/tessvars.h
00444 #endif
00445   }
00446   else {
00447     newpt = new CRACKEDGE;
00448 #if defined(TEXT_VERBOSE) && defined(TV_FOCUSD)
00449   cprintf("k"); // check under 'e' in ccmain/tessvars.h
00450 #endif
00451   }
00452   newpt->pos.set_x (x);          //coords of pt
00453   newpt->stepx = 0;              //edge is vertical
00454 
00455   if (sign > 0) {
00456     newpt->pos.set_y (y);        //start location
00457     newpt->stepy = 1;
00458     newpt->stepdir = 3;
00459 #if defined(TEXT_VERBOSE) && defined(TV_FOCUSD)
00460   cprintf("l"); // check under 'e' in ccmain/tessvars.h
00461 #endif
00462   }
00463   else {
00464     newpt->pos.set_y (y + 1);    //start location
00465     newpt->stepy = -1;
00466     newpt->stepdir = 1;
00467 #if defined(TEXT_VERBOSE) && defined(TV_FOCUSD)
00468   cprintf("m"); // check under 'e' in ccmain/tessvars.h
00469 #endif
00470   }
00471 
00472   if (join == NULL) {
00473     newpt->next = newpt;         //ptrs to other ends
00474     newpt->prev = newpt;
00475 #if defined(TEXT_VERBOSE) && defined(TV_FOCUSD)
00476   cprintf("n"); // check under 'e' in ccmain/tessvars.h
00477 #endif
00478   }
00479   else {
00480     if (newpt->pos.x () == join->pos.x ()
00481     && newpt->pos.y () + newpt->stepy == join->pos.y ()) {
00482       newpt->prev = join->prev;  //update other ends
00483       newpt->prev->next = newpt;
00484       newpt->next = join;        //join up
00485       join->prev = newpt;
00486 #if defined(TEXT_VERBOSE) && defined(TV_FOCUSD)
00487   cprintf("o"); // check under 'e' in ccmain/tessvars.h
00488 #endif
00489     }
00490     else {
00491       newpt->next = join->next;  //update other ends
00492       newpt->next->prev = newpt;
00493       newpt->prev = join;        //join up
00494       join->next = newpt;
00495 #if defined(TEXT_VERBOSE) && defined(TV_FOCUSD)
00496   cprintf("p"); // check under 'e' in ccmain/tessvars.h
00497 #endif
00498     }
00499   }
00500   return newpt;
00501 }
00502 
00503 
00510 void join_edges(                   //join edge fragments
00511                 CRACKEDGE *edge1,  //edges to join
00512                 CRACKEDGE *edge2   //no specific order
00513                ) {
00514   CRACKEDGE *tempedge;           //for exchanging
00515 
00516   if (edge1->pos.x () + edge1->stepx != edge2->pos.x ()
00517   || edge1->pos.y () + edge1->stepy != edge2->pos.y ()) {
00518     tempedge = edge1;
00519     edge1 = edge2;               //swap around
00520     edge2 = tempedge;
00521   }
00522 
00523   //      tprintf("Joining %x=(%d,%d)+(%d,%d)->%x<-%x ",
00524   //              edge1,edge1->pos.x(),edge1->pos.y(),edge1->stepx,edge1->stepy,
00525   //              edge1->next,edge1->prev);
00526   //      tprintf("to %x=(%d,%d)+(%d,%d)->%x<-%x\n",
00527   //              edge2,edge2->pos.x(),edge2->pos.y(),edge2->stepx,edge2->stepy,
00528   //              edge2->next,edge2->prev);
00529   if (edge1->next == edge2) {
00530 #if defined(TEXT_VERBOSE) && !defined(TV_FOCUSE)
00531   cprintf("c"); // gets a 'e', see ccmain/tessvars.h
00532 #endif
00533                                  //already closed
00534     complete_edge(edge1);  //approximate it
00535                                  //attach freelist to end
00536     edge1->prev->next = free_cracks;
00537     free_cracks = edge1;         //and free list
00538   }
00539   else {
00540                                  //update opposite ends
00541     edge2->prev->next = edge1->next;
00542     edge1->next->prev = edge2->prev;
00543     edge1->next = edge2;         //make joins
00544     edge2->prev = edge1;
00545   }
00546 }
00547 
00548 
00554 void free_crackedges(                  //really free them
00555                      CRACKEDGE *start  //start of loop
00556                     ) {
00557   CRACKEDGE *current;            //current edge to free
00558   CRACKEDGE *next;               //next one to free
00559 
00560   for (current = start; current != NULL; current = next) {
00561     next = current->next;
00562     delete current;              //delete them all
00563   }
00564 }

Generated on Wed Feb 28 19:49:12 2007 for Tesseract by  doxygen 1.5.1