Tesseract  3.02
tesseract-ocr/ccmain/pgedit.cpp
Go to the documentation of this file.
00001 /**********************************************************************
00002  * File:        pgedit.cpp (Formerly pgeditor.c)
00003  * Description: Page structure file editor
00004  * Author:      Phil Cheatle
00005  * Created:     Thu Oct 10 16:25:24 BST 1991
00006  *
00007  *(C) Copyright 1991, Hewlett-Packard Ltd.
00008  ** Licensed under the Apache License, Version 2.0(the "License");
00009  ** you may not use this file except in compliance with the License.
00010  ** You may obtain a copy of the License at
00011  ** http:// www.apache.org/licenses/LICENSE-2.0
00012  ** Unless required by applicable law or agreed to in writing, software
00013  ** distributed under the License is distributed on an "AS IS" BASIS,
00014  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015  ** See the License for the specific language governing permissions and
00016  ** limitations under the License.
00017  *
00018  **********************************************************************/
00019 
00020 #ifdef _MSC_VER
00021 #pragma warning(disable:4244)  // Conversion warnings
00022 #endif
00023 
00024 // Include automatically generated configuration file if running autoconf.
00025 #ifdef HAVE_CONFIG_H
00026 #include "config_auto.h"
00027 #endif
00028 
00029 #include          "pgedit.h"
00030 
00031 #include          <ctype.h>
00032 #include          <math.h>
00033 
00034 #include "blread.h"
00035 #include "control.h"
00036 #include "svshowim.h"
00037 #include "paramsd.h"
00038 #include "pageres.h"
00039 #include "tordmain.h"
00040 #include "scrollview.h"
00041 #include "svmnode.h"
00042 #include "statistc.h"
00043 #include "tesseractclass.h"
00044 
00045 #ifndef GRAPHICS_DISABLED
00046 #define ASC_HEIGHT     (2 * kBlnBaselineOffset + kBlnXHeight)
00047 #define X_HEIGHT       (kBlnBaselineOffset + kBlnXHeight)
00048 #define BL_HEIGHT     kBlnBaselineOffset
00049 #define DESC_HEIGHT     0
00050 #define MAXSPACING      128      /*max expected spacing in pix */
00051 
00052 const ERRCODE EMPTYBLOCKLIST = "No blocks to edit";
00053 
00054 enum CMD_EVENTS
00055 {
00056   NULL_CMD_EVENT,
00057   CHANGE_DISP_CMD_EVENT,
00058   DUMP_WERD_CMD_EVENT,
00059   SHOW_POINT_CMD_EVENT,
00060   SHOW_BLN_WERD_CMD_EVENT,
00061   DEBUG_WERD_CMD_EVENT,
00062   BLAMER_CMD_EVENT,
00063   BOUNDING_BOX_CMD_EVENT,
00064   CORRECT_TEXT_CMD_EVENT,
00065   POLYGONAL_CMD_EVENT,
00066   BL_NORM_CMD_EVENT,
00067   BITMAP_CMD_EVENT,
00068   IMAGE_CMD_EVENT,
00069   BLOCKS_CMD_EVENT,
00070   BASELINES_CMD_EVENT,
00071   UNIFORM_DISP_CMD_EVENT,
00072   REFRESH_CMD_EVENT,
00073   QUIT_CMD_EVENT,
00074   RECOG_WERDS,
00075   RECOG_PSEUDO,
00076   SHOW_SUBSCRIPT_CMD_EVENT,
00077   SHOW_SUPERSCRIPT_CMD_EVENT,
00078   SHOW_ITALIC_CMD_EVENT,
00079   SHOW_BOLD_CMD_EVENT,
00080   SHOW_UNDERLINE_CMD_EVENT,
00081   SHOW_FIXEDPITCH_CMD_EVENT,
00082   SHOW_SERIF_CMD_EVENT,
00083   SHOW_SMALLCAPS_CMD_EVENT,
00084   SHOW_DROPCAPS_CMD_EVENT,
00085 };
00086 
00087 enum ColorationMode {
00088   CM_RAINBOW,
00089   CM_SUBSCRIPT,
00090   CM_SUPERSCRIPT,
00091   CM_ITALIC,
00092   CM_BOLD,
00093   CM_UNDERLINE,
00094   CM_FIXEDPITCH,
00095   CM_SERIF,
00096   CM_SMALLCAPS,
00097   CM_DROPCAPS
00098 };
00099 
00100 /*
00101  *
00102  *  Some global data
00103  *
00104  */
00105 
00106 ScrollView* image_win;
00107 ParamsEditor* pe;
00108 bool stillRunning = false;
00109 
00110 #ifdef __UNIX__
00111 FILE *debug_window = NULL;                // opened on demand
00112 #endif
00113 ScrollView* bln_word_window = NULL;       // baseline norm words
00114 
00115 CMD_EVENTS mode = CHANGE_DISP_CMD_EVENT;  // selected words op
00116 
00117 bool recog_done = false;                  // recog_all_words was called
00118 
00119 // These variables should remain global, since they are only used for the
00120 // debug mode (in which only a single Tesseract thread/instance will be exist).
00121 BITS16 word_display_mode;
00122 static ColorationMode color_mode = CM_RAINBOW;
00123 BOOL8 display_image = FALSE;
00124 BOOL8 display_blocks = FALSE;
00125 BOOL8 display_baselines = FALSE;
00126 
00127 PAGE_RES *current_page_res = NULL;
00128 
00129 STRING_VAR(editor_image_win_name, "EditorImage",
00130            "Editor image window name");
00131 INT_VAR(editor_image_xpos, 590, "Editor image X Pos");
00132 INT_VAR(editor_image_ypos, 10, "Editor image Y Pos");
00133 INT_VAR(editor_image_menuheight, 50, "Add to image height for menu bar");
00134 INT_VAR(editor_image_word_bb_color, ScrollView::BLUE,
00135         "Word bounding box colour");
00136 INT_VAR(editor_image_blob_bb_color, ScrollView::YELLOW,
00137         "Blob bounding box colour");
00138 INT_VAR(editor_image_text_color, ScrollView::WHITE,
00139         "Correct text colour");
00140 
00141 STRING_VAR(editor_dbwin_name, "EditorDBWin",
00142            "Editor debug window name");
00143 INT_VAR(editor_dbwin_xpos, 50, "Editor debug window X Pos");
00144 INT_VAR(editor_dbwin_ypos, 500, "Editor debug window Y Pos");
00145 INT_VAR(editor_dbwin_height, 24, "Editor debug window height");
00146 INT_VAR(editor_dbwin_width, 80, "Editor debug window width");
00147 
00148 STRING_VAR(editor_word_name, "BlnWords", "BL normalized word window");
00149 INT_VAR(editor_word_xpos, 60, "Word window X Pos");
00150 INT_VAR(editor_word_ypos, 510, "Word window Y Pos");
00151 INT_VAR(editor_word_height, 240, "Word window height");
00152 INT_VAR(editor_word_width, 655, "Word window width");
00153 
00154 STRING_VAR(editor_debug_config_file, "", "Config file to apply to single words");
00155 
00156 class BlnEventHandler : public SVEventHandler {
00157  public:
00158   void Notify(const SVEvent* sv_event) {
00159     if (sv_event->type == SVET_DESTROY)
00160       bln_word_window = NULL;
00161     else if (sv_event->type == SVET_CLICK)
00162       show_point(current_page_res, sv_event->x, sv_event->y);
00163   }
00164 };
00165 
00171 ScrollView* bln_word_window_handle() {  // return handle
00172                                  // not opened yet
00173   if (bln_word_window == NULL) {
00174     pgeditor_msg("Creating BLN word window...");
00175     bln_word_window = new ScrollView(editor_word_name.string(),
00176       editor_word_xpos, editor_word_ypos, editor_word_width,
00177       editor_word_height, 4000, 4000, true);
00178     BlnEventHandler* a = new BlnEventHandler();
00179     bln_word_window->AddEventHandler(a);
00180     pgeditor_msg("Creating BLN word window...Done");
00181   }
00182   return bln_word_window;
00183 }
00184 
00192 void build_image_window(int width, int height) {
00193   if (image_win != NULL) { delete image_win; }
00194   image_win = new ScrollView(editor_image_win_name.string(),
00195                              editor_image_xpos, editor_image_ypos,
00196                              width + 1,
00197                              height + editor_image_menuheight + 1,
00198                              width,
00199                              height,
00200                              true);
00201 }
00202 
00209 void display_bln_lines(ScrollView* window,
00210                        ScrollView::Color colour,
00211                        float scale_factor,
00212                        float y_offset,
00213                        float minx,
00214                        float maxx) {
00215   window->Pen(colour);
00216   window->Line(minx, y_offset + scale_factor * DESC_HEIGHT,
00217                maxx, y_offset + scale_factor * DESC_HEIGHT);
00218   window->Line(minx, y_offset + scale_factor * BL_HEIGHT,
00219                maxx, y_offset + scale_factor * BL_HEIGHT);
00220   window->Line(minx, y_offset + scale_factor * X_HEIGHT,
00221                maxx, y_offset + scale_factor * X_HEIGHT);
00222   window->Line(minx, y_offset + scale_factor * ASC_HEIGHT,
00223                maxx, y_offset + scale_factor * ASC_HEIGHT);
00224 }
00225 
00234 void PGEventHandler::Notify(const SVEvent* event) {
00235   char myval = '0';
00236   if (event->type == SVET_POPUP) {
00237     pe->Notify(event);
00238   } // These are handled by ParamsEditor
00239   else if (event->type == SVET_EXIT) { stillRunning = false; }
00240   else if (event->type == SVET_MENU) {
00241      if (strcmp(event->parameter, "true") == 0) { myval = 'T'; }
00242      else if (strcmp(event->parameter, "false") == 0) { myval = 'F'; }
00243      tess_->process_cmd_win_event(event->command_id, &myval);
00244   }
00245   else {
00246     tess_->process_image_event(*event);
00247   }
00248 }
00249 
00255 namespace tesseract {
00256 SVMenuNode *Tesseract::build_menu_new() {
00257   SVMenuNode* parent_menu;
00258   SVMenuNode* root_menu_item = new SVMenuNode();
00259 
00260   SVMenuNode* modes_menu_item = root_menu_item->AddChild("MODES");
00261 
00262   modes_menu_item->AddChild("Change Display", CHANGE_DISP_CMD_EVENT);
00263   modes_menu_item->AddChild("Dump Word", DUMP_WERD_CMD_EVENT);
00264   modes_menu_item->AddChild("Show Point", SHOW_POINT_CMD_EVENT);
00265   modes_menu_item->AddChild("Show BL Norm Word", SHOW_BLN_WERD_CMD_EVENT);
00266   modes_menu_item->AddChild("Config Words", DEBUG_WERD_CMD_EVENT);
00267   modes_menu_item->AddChild("Recog Words", RECOG_WERDS);
00268   modes_menu_item->AddChild("Recog Blobs", RECOG_PSEUDO);
00269 
00270   parent_menu = root_menu_item->AddChild("DISPLAY");
00271 
00272   parent_menu->AddChild("Blamer", BLAMER_CMD_EVENT, FALSE);
00273   parent_menu->AddChild("Bounding Boxes", BOUNDING_BOX_CMD_EVENT, FALSE);
00274   parent_menu->AddChild("Correct Text", CORRECT_TEXT_CMD_EVENT, FALSE);
00275   parent_menu->AddChild("Polygonal Approx", POLYGONAL_CMD_EVENT, FALSE);
00276   parent_menu->AddChild("Baseline Normalized", BL_NORM_CMD_EVENT, FALSE);
00277   parent_menu->AddChild("Edge Steps", BITMAP_CMD_EVENT, TRUE);
00278   parent_menu->AddChild("Subscripts", SHOW_SUBSCRIPT_CMD_EVENT);
00279   parent_menu->AddChild("Superscripts", SHOW_SUPERSCRIPT_CMD_EVENT);
00280   parent_menu->AddChild("Italics", SHOW_ITALIC_CMD_EVENT);
00281   parent_menu->AddChild("Bold", SHOW_BOLD_CMD_EVENT);
00282   parent_menu->AddChild("Underline", SHOW_UNDERLINE_CMD_EVENT);
00283   parent_menu->AddChild("FixedPitch", SHOW_FIXEDPITCH_CMD_EVENT);
00284   parent_menu->AddChild("Serifs", SHOW_SERIF_CMD_EVENT);
00285   parent_menu->AddChild("SmallCaps", SHOW_SMALLCAPS_CMD_EVENT);
00286   parent_menu->AddChild("DropCaps", SHOW_DROPCAPS_CMD_EVENT);
00287 
00288 
00289   parent_menu = root_menu_item->AddChild("OTHER");
00290 
00291   parent_menu->AddChild("Quit", QUIT_CMD_EVENT);
00292   parent_menu->AddChild("Show Image", IMAGE_CMD_EVENT, FALSE);
00293   parent_menu->AddChild("ShowBlock Outlines", BLOCKS_CMD_EVENT, FALSE);
00294   parent_menu->AddChild("Show Baselines", BASELINES_CMD_EVENT, FALSE);
00295   parent_menu->AddChild("Uniform Display", UNIFORM_DISP_CMD_EVENT);
00296   parent_menu->AddChild("Refresh Display", REFRESH_CMD_EVENT);
00297 
00298   return root_menu_item;
00299 }
00300 
00306 void Tesseract::do_re_display(
00307     BOOL8 (tesseract::Tesseract::*word_painter)(BLOCK* block,
00308                                                 ROW* row,
00309                                                 WERD_RES* word_res)) {
00310   PAGE_RES_IT pr_it(current_page_res);
00311   int block_count = 1;
00312 
00313   image_win->Clear();
00314   if (display_image != 0) {
00315     image_win->Image(pix_binary_, 0, 0);
00316   }
00317 
00318   for (WERD_RES* word = pr_it.word(); word != NULL; word = pr_it.forward()) {
00319     (this->*word_painter)(pr_it.block()->block, pr_it.row()->row, word);
00320     if (display_baselines && pr_it.row() != pr_it.prev_row())
00321       pr_it.row()->row->plot_baseline(image_win, ScrollView::GREEN);
00322     if (display_blocks && pr_it.block() != pr_it.prev_block())
00323       pr_it.block()->block->plot(image_win, block_count++, ScrollView::RED);
00324   }
00325   image_win->Update();
00326 }
00327 
00336 void Tesseract::pgeditor_main(int width, int height, PAGE_RES *page_res) {
00337   current_page_res = page_res;
00338   if (current_page_res->block_res_list.empty())
00339     return;
00340 
00341   recog_done = false;
00342   stillRunning = true;
00343 
00344   build_image_window(width, height);
00345   word_display_mode.turn_on_bit(DF_EDGE_STEP);
00346   do_re_display(&tesseract::Tesseract::word_set_display);
00347 #ifndef GRAPHICS_DISABLED
00348   pe = new ParamsEditor(this, image_win);
00349 #endif
00350   PGEventHandler pgEventHandler(this);
00351 
00352   image_win->AddEventHandler(&pgEventHandler);
00353   image_win->AddMessageBox();
00354 
00355   SVMenuNode* svMenuRoot = build_menu_new();
00356 
00357   svMenuRoot->BuildMenu(image_win);
00358   image_win->SetVisible(true);
00359 
00360   image_win->AwaitEvent(SVET_DESTROY);
00361   image_win->AddEventHandler(NULL);
00362 }
00363 }  // namespace tesseract
00364 
00365 
00372 void pgeditor_msg( // message display
00373                   const char *msg) {
00374     image_win->AddMessage(msg);
00375 }
00376 
00383 void pgeditor_show_point( // display coords
00384                          SVEvent *event) {
00385   image_win->AddMessage("Pointing at(%d, %d)", event->x, event->y);
00386 }
00387 
00395 namespace tesseract {
00396 BOOL8 Tesseract::process_cmd_win_event(                 // UI command semantics
00397                                        inT32 cmd_event,  // which menu item?
00398                                        char *new_value   // any prompt data
00399                                       ) {
00400   char msg[160];
00401   BOOL8 exit = FALSE;
00402 
00403   color_mode = CM_RAINBOW;
00404 
00405   // Run recognition on the full page if needed.
00406   switch (cmd_event) {
00407     case BLAMER_CMD_EVENT:
00408     case SHOW_SUBSCRIPT_CMD_EVENT:
00409     case SHOW_SUPERSCRIPT_CMD_EVENT:
00410     case SHOW_ITALIC_CMD_EVENT:
00411     case SHOW_BOLD_CMD_EVENT:
00412     case SHOW_UNDERLINE_CMD_EVENT:
00413     case SHOW_FIXEDPITCH_CMD_EVENT:
00414     case SHOW_SERIF_CMD_EVENT:
00415     case SHOW_SMALLCAPS_CMD_EVENT:
00416     case SHOW_DROPCAPS_CMD_EVENT:
00417       if (!recog_done) {
00418         recog_all_words(current_page_res, NULL, NULL, NULL, 0);
00419         recog_done = true;
00420       }
00421       break;
00422     default:
00423       break;
00424   }
00425 
00426   switch (cmd_event) {
00427     case NULL_CMD_EVENT:
00428       break;
00429 
00430     case CHANGE_DISP_CMD_EVENT:
00431     case DUMP_WERD_CMD_EVENT:
00432     case SHOW_POINT_CMD_EVENT:
00433     case SHOW_BLN_WERD_CMD_EVENT:
00434     case RECOG_WERDS:
00435     case RECOG_PSEUDO:
00436       mode =(CMD_EVENTS) cmd_event;
00437       break;
00438     case DEBUG_WERD_CMD_EVENT:
00439       mode = DEBUG_WERD_CMD_EVENT;
00440       word_config_ = image_win->ShowInputDialog("Config File Name");
00441       break;
00442     case BOUNDING_BOX_CMD_EVENT:
00443       if (new_value[0] == 'T')
00444         word_display_mode.turn_on_bit(DF_BOX);
00445       else
00446         word_display_mode.turn_off_bit(DF_BOX);
00447       mode = CHANGE_DISP_CMD_EVENT;
00448       break;
00449     case BLAMER_CMD_EVENT:
00450       if (new_value[0] == 'T')
00451         word_display_mode.turn_on_bit(DF_BLAMER);
00452       else
00453         word_display_mode.turn_off_bit(DF_BLAMER);
00454       do_re_display(&tesseract::Tesseract::word_display);
00455       mode = CHANGE_DISP_CMD_EVENT;
00456       break;
00457     case CORRECT_TEXT_CMD_EVENT:
00458       if (new_value[0] == 'T')
00459         word_display_mode.turn_on_bit(DF_TEXT);
00460       else
00461         word_display_mode.turn_off_bit(DF_TEXT);
00462       mode = CHANGE_DISP_CMD_EVENT;
00463       break;
00464     case POLYGONAL_CMD_EVENT:
00465       if (new_value[0] == 'T')
00466         word_display_mode.turn_on_bit(DF_POLYGONAL);
00467       else
00468         word_display_mode.turn_off_bit(DF_POLYGONAL);
00469       mode = CHANGE_DISP_CMD_EVENT;
00470       break;
00471     case BL_NORM_CMD_EVENT:
00472       if (new_value[0] == 'T')
00473         word_display_mode.turn_on_bit(DF_BN_POLYGONAL);
00474       else
00475         word_display_mode.turn_off_bit(DF_BN_POLYGONAL);
00476       mode = CHANGE_DISP_CMD_EVENT;
00477       break;
00478     case BITMAP_CMD_EVENT:
00479       if (new_value[0] == 'T')
00480         word_display_mode.turn_on_bit(DF_EDGE_STEP);
00481       else
00482         word_display_mode.turn_off_bit(DF_EDGE_STEP);
00483       mode = CHANGE_DISP_CMD_EVENT;
00484       break;
00485     case UNIFORM_DISP_CMD_EVENT:
00486       do_re_display(&tesseract::Tesseract::word_set_display);
00487       break;
00488     case IMAGE_CMD_EVENT:
00489       display_image =(new_value[0] == 'T');
00490       do_re_display(&tesseract::Tesseract::word_display);
00491       break;
00492     case BLOCKS_CMD_EVENT:
00493       display_blocks =(new_value[0] == 'T');
00494       do_re_display(&tesseract::Tesseract::word_display);
00495       break;
00496     case BASELINES_CMD_EVENT:
00497       display_baselines =(new_value[0] == 'T');
00498       do_re_display(&tesseract::Tesseract::word_display);
00499       break;
00500     case SHOW_SUBSCRIPT_CMD_EVENT:
00501       color_mode = CM_SUBSCRIPT;
00502       do_re_display(&tesseract::Tesseract::word_display);
00503       break;
00504     case SHOW_SUPERSCRIPT_CMD_EVENT:
00505       color_mode = CM_SUPERSCRIPT;
00506       do_re_display(&tesseract::Tesseract::word_display);
00507       break;
00508     case SHOW_ITALIC_CMD_EVENT:
00509       color_mode = CM_ITALIC;
00510       do_re_display(&tesseract::Tesseract::word_display);
00511       break;
00512     case SHOW_BOLD_CMD_EVENT:
00513       color_mode = CM_BOLD;
00514       do_re_display(&tesseract::Tesseract::word_display);
00515       break;
00516     case SHOW_UNDERLINE_CMD_EVENT:
00517       color_mode = CM_UNDERLINE;
00518       do_re_display(&tesseract::Tesseract::word_display);
00519       break;
00520     case SHOW_FIXEDPITCH_CMD_EVENT:
00521       color_mode = CM_FIXEDPITCH;
00522       do_re_display(&tesseract::Tesseract::word_display);
00523       break;
00524     case SHOW_SERIF_CMD_EVENT:
00525       color_mode = CM_SERIF;
00526       do_re_display(&tesseract::Tesseract::word_display);
00527       break;
00528     case SHOW_SMALLCAPS_CMD_EVENT:
00529       color_mode = CM_SMALLCAPS;
00530       do_re_display(&tesseract::Tesseract::word_display);
00531       break;
00532     case SHOW_DROPCAPS_CMD_EVENT:
00533       color_mode = CM_DROPCAPS;
00534       do_re_display(&tesseract::Tesseract::word_display);
00535       break;
00536     case REFRESH_CMD_EVENT:
00537       do_re_display(&tesseract::Tesseract::word_display);
00538       break;
00539     case QUIT_CMD_EVENT:
00540       exit = TRUE;
00541       ScrollView::Exit();
00542       break;
00543 
00544     default:
00545       sprintf(msg, "Unrecognised event " INT32FORMAT "(%s)",
00546                cmd_event, new_value);
00547       image_win->AddMessage(msg);
00548     break;
00549   }
00550   return exit;
00551 }
00552 
00553 
00563 void Tesseract::process_image_event( // action in image win
00564                                     const SVEvent &event) {
00565    // The following variable should remain static, since it is used by
00566    // debug editor, which uses a single Tesseract instance.
00567   static ICOORD down;
00568   ICOORD up;
00569   TBOX selection_box;
00570   char msg[80];
00571 
00572   switch(event.type) {
00573 
00574     case SVET_SELECTION:
00575       if (event.type == SVET_SELECTION) {
00576         down.set_x(event.x + event.x_size);
00577         down.set_y(event.y + event.y_size);
00578         if (mode == SHOW_POINT_CMD_EVENT)
00579           show_point(current_page_res, event.x, event.y);
00580       }
00581 
00582       up.set_x(event.x);
00583       up.set_y(event.y);
00584 
00585       selection_box = TBOX(down, up);
00586 
00587       switch(mode) {
00588         case CHANGE_DISP_CMD_EVENT:
00589           process_selected_words(
00590               current_page_res,
00591               selection_box,
00592               &tesseract::Tesseract::word_blank_and_set_display);
00593           break;
00594        case DUMP_WERD_CMD_EVENT:
00595           process_selected_words(current_page_res,
00596                                  selection_box,
00597                                  &tesseract::Tesseract::word_dumper);
00598           break;
00599         case SHOW_BLN_WERD_CMD_EVENT:
00600           process_selected_words(current_page_res,
00601                                  selection_box,
00602                                  &tesseract::Tesseract::word_bln_display);
00603           break;
00604         case DEBUG_WERD_CMD_EVENT:
00605           debug_word(current_page_res, selection_box);
00606           break;
00607         case SHOW_POINT_CMD_EVENT:
00608           break;                 // ignore up event
00609 
00610         case RECOG_WERDS:
00611           image_win->AddMessage("Recogging selected words");
00612           this->process_selected_words(current_page_res,
00613                                        selection_box,
00614                                        &Tesseract::recog_interactive);
00615           break;
00616         case RECOG_PSEUDO:
00617           image_win->AddMessage("Recogging selected blobs");
00618           recog_pseudo_word(current_page_res, selection_box);
00619           break;
00620 
00621         default:
00622           sprintf(msg, "Mode %d not yet implemented", mode);
00623           image_win->AddMessage(msg);
00624           break;
00625       }
00626     default:
00627       break;
00628   }
00629 }
00630 
00636 void Tesseract::debug_word(PAGE_RES* page_res, const TBOX &selection_box) {
00637   ResetAdaptiveClassifier();
00638   recog_all_words(page_res, NULL, &selection_box, word_config_.string(), 0);
00639 }
00640 }  // namespace tesseract
00641 
00642 
00650 void show_point(PAGE_RES* page_res, float x, float y) {
00651   FCOORD pt(x, y);
00652   PAGE_RES_IT pr_it(page_res);
00653 
00654   char msg[160];
00655   char *msg_ptr = msg;
00656 
00657   msg_ptr += sprintf(msg_ptr, "Pt:(%0.3f, %0.3f) ", x, y);
00658 
00659   for (WERD_RES* word = pr_it.word(); word != NULL; word = pr_it.forward()) {
00660     if (pr_it.row() != pr_it.prev_row() &&
00661         pr_it.row()->row->bounding_box().contains(pt)) {
00662       msg_ptr += sprintf(msg_ptr, "BL(x)=%0.3f ",
00663                          pr_it.row()->row->base_line(x));
00664     }
00665     if (word->word->bounding_box().contains(pt)) {
00666       TBOX box = word->word->bounding_box();
00667       msg_ptr += sprintf(msg_ptr, "Wd(%d, %d)/(%d, %d) ",
00668                          box.left(), box.bottom(),
00669                          box.right(), box.top());
00670       C_BLOB_IT cblob_it(word->word->cblob_list());
00671       for (cblob_it.mark_cycle_pt();
00672            !cblob_it.cycled_list();
00673            cblob_it.forward()) {
00674         C_BLOB* cblob = cblob_it.data();
00675         box = cblob->bounding_box();
00676         if (box.contains(pt)) {
00677           msg_ptr += sprintf(msg_ptr,
00678                              "CBlb(%d, %d)/(%d, %d) ",
00679                              box.left(), box.bottom(),
00680                              box.right(), box.top());
00681         }
00682       }
00683     }
00684   }
00685   image_win->AddMessage(msg);
00686 }
00687 
00688 
00689 /**********************************************************************
00690  * WERD PROCESSOR FUNCTIONS
00691  * ========================
00692  *
00693  * These routines are invoked by one or more of:
00694  *    process_all_words()
00695  *    process_selected_words()
00696  * or
00697  *    process_all_words_it()
00698  *    process_selected_words_it()
00699  * for each word to be processed
00700  **********************************************************************/
00701 
00708 #endif  // GRAPHICS_DISABLED
00709 namespace tesseract {
00710 #ifndef GRAPHICS_DISABLED
00711 BOOL8 Tesseract:: word_blank_and_set_display(BLOCK* block, ROW* row,
00712                                              WERD_RES* word_res) {
00713   word_res->word->bounding_box().plot(image_win, ScrollView::BLACK,
00714                                       ScrollView::BLACK);
00715   return word_set_display(block, row, word_res);
00716 }
00717 
00718 
00724 BOOL8 Tesseract::word_bln_display(BLOCK* block, ROW* row, WERD_RES* word_res) {
00725   TWERD *bln_word = word_res->chopped_word;
00726   if (bln_word == NULL) {
00727     word_res->SetupForTessRecognition(unicharset, this, BestPix(), false,
00728                                       this->textord_use_cjk_fp_model,
00729                                       row, block);
00730     bln_word = word_res->chopped_word;
00731   }
00732   bln_word_window_handle()->Clear();
00733   display_bln_lines(bln_word_window_handle(), ScrollView::CYAN,
00734                      1.0, 0.0f, -1000.0f, 1000.0f);
00735   bln_word->plot(bln_word_window_handle());
00736   bln_word_window_handle()->Update();
00737   return TRUE;
00738 }
00739 
00740 
00741 
00747 BOOL8 Tesseract::word_display(BLOCK* block, ROW* row, WERD_RES* word_res) {
00748   WERD* word = word_res->word;
00749   TBOX word_bb;                   // word bounding box
00750   int word_height;               // ht of word BB
00751   BOOL8 displayed_something = FALSE;
00752   float shift;                   // from bot left
00753   C_BLOB_IT c_it;                // cblob iterator
00754 
00755   if (color_mode != CM_RAINBOW && word_res->box_word != NULL) {
00756     BoxWord* box_word = word_res->box_word;
00757     int length = box_word->length();
00758     if (word_res->fontinfo == NULL) return false;
00759     const FontInfo& font_info = *word_res->fontinfo;
00760     for (int i = 0; i < length; ++i) {
00761       ScrollView::Color color = ScrollView::GREEN;
00762       switch (color_mode) {
00763         case CM_SUBSCRIPT:
00764           if (box_word->BlobPosition(i) == SP_SUBSCRIPT)
00765             color = ScrollView::RED;
00766           break;
00767         case CM_SUPERSCRIPT:
00768           if (box_word->BlobPosition(i) == SP_SUPERSCRIPT)
00769             color = ScrollView::RED;
00770           break;
00771         case CM_ITALIC:
00772           if (font_info.is_italic())
00773             color = ScrollView::RED;
00774           break;
00775         case CM_BOLD:
00776           if (font_info.is_bold())
00777             color = ScrollView::RED;
00778           break;
00779         case CM_FIXEDPITCH:
00780           if (font_info.is_fixed_pitch())
00781             color = ScrollView::RED;
00782           break;
00783         case CM_SERIF:
00784           if (font_info.is_serif())
00785             color = ScrollView::RED;
00786           break;
00787         case CM_SMALLCAPS:
00788           if (word_res->small_caps)
00789             color = ScrollView::RED;
00790           break;
00791         case CM_DROPCAPS:
00792           if (box_word->BlobPosition(i) == SP_DROPCAP)
00793             color = ScrollView::RED;
00794           break;
00795           // TODO(rays) underline is currently completely unsupported.
00796         case CM_UNDERLINE:
00797         default:
00798           break;
00799       }
00800       image_win->Pen(color);
00801       TBOX box = box_word->BlobBox(i);
00802       image_win->Rectangle(box.left(), box.bottom(), box.right(), box.top());
00803     }
00804     return true;
00805   }
00806   /*
00807     Note the double coercions of(COLOUR)((inT32)editor_image_word_bb_color)
00808     etc. are to keep the compiler happy.
00809   */
00810                                  // display bounding box
00811   if (word->display_flag(DF_BOX)) {
00812     word->bounding_box().plot(image_win,
00813      (ScrollView::Color)((inT32)
00814       editor_image_word_bb_color),
00815      (ScrollView::Color)((inT32)
00816       editor_image_word_bb_color));
00817 
00818     ScrollView::Color c = (ScrollView::Color)
00819        ((inT32) editor_image_blob_bb_color);
00820     image_win->Pen(c);
00821     c_it.set_to_list(word->cblob_list());
00822     for (c_it.mark_cycle_pt(); !c_it.cycled_list(); c_it.forward())
00823       c_it.data()->bounding_box().plot(image_win);
00824     displayed_something = TRUE;
00825   }
00826 
00827                                  // display edge steps
00828   if (word->display_flag(DF_EDGE_STEP)) {     // edgesteps available
00829     word->plot(image_win);      // rainbow colors
00830     displayed_something = TRUE;
00831   }
00832 
00833                                  // display poly approx
00834   if (word->display_flag(DF_POLYGONAL)) {
00835                                  // need to convert
00836     TWERD* tword = TWERD::PolygonalCopy(word);
00837     tword->plot(image_win);
00838     delete tword;
00839     displayed_something = TRUE;
00840   }
00841 
00842   // Display correct text and blamer information.
00843   STRING text;
00844   STRING blame;
00845   if (word->display_flag(DF_TEXT) && word->text() != NULL) {
00846     text = word->text();
00847   }
00848   if (word->display_flag(DF_BLAMER) &&
00849       !(word_res->blamer_bundle != NULL &&
00850         word_res->blamer_bundle->incorrect_result_reason == IRR_CORRECT)) {
00851     text = "";
00852     const BlamerBundle *blamer_bundle = word_res->blamer_bundle;
00853     if (blamer_bundle == NULL) {
00854       text += "NULL";
00855     } else {
00856       for (int i = 0; i < blamer_bundle->truth_text.length(); ++i) {
00857         text += blamer_bundle->truth_text[i];
00858       }
00859     }
00860     text += " -> ";
00861     STRING best_choice_str;
00862     if (word_res->best_choice == NULL) {
00863       best_choice_str = "NULL";
00864     } else {
00865       word_res->best_choice->string_and_lengths(&best_choice_str, NULL);
00866     }
00867     text += best_choice_str;
00868     IncorrectResultReason reason = (blamer_bundle == NULL) ?
00869         IRR_PAGE_LAYOUT : blamer_bundle->incorrect_result_reason;
00870     ASSERT_HOST(reason < IRR_NUM_REASONS)
00871     blame += " [";
00872     blame += BlamerBundle::IncorrectReasonName(reason);
00873     blame += "]";
00874   }
00875   if (text.length() > 0) {
00876     word_bb = word->bounding_box();
00877     image_win->Pen(ScrollView::RED);
00878     word_height = word_bb.height();
00879     int text_height = 0.50 * word_height;
00880     if (text_height > 20) text_height = 20;
00881     image_win->TextAttributes("Arial", text_height, false, false, false);
00882     shift = (word_height < word_bb.width()) ? 0.25 * word_height : 0.0f;
00883     image_win->Text(word_bb.left() + shift,
00884                     word_bb.bottom() + 0.25 * word_height, text.string());
00885     if (blame.length() > 0) {
00886       image_win->Text(word_bb.left() + shift,
00887                       word_bb.bottom() + 0.25 * word_height - text_height,
00888                       blame.string());
00889     }
00890 
00891     displayed_something = TRUE;
00892   }
00893 
00894   if (!displayed_something)      // display BBox anyway
00895     word->bounding_box().plot(image_win,
00896      (ScrollView::Color)((inT32) editor_image_word_bb_color),
00897      (ScrollView::Color)((inT32)
00898       editor_image_word_bb_color));
00899   return TRUE;
00900 }
00901 #endif  // GRAPHICS_DISABLED
00902 
00908 BOOL8 Tesseract::word_dumper(BLOCK* block, ROW* row, WERD_RES* word_res) {
00909   if (block != NULL) {
00910     tprintf("\nBlock data...\n");
00911     block->print(NULL, FALSE);
00912   }
00913   tprintf("\nRow data...\n");
00914   row->print(NULL);
00915   tprintf("\nWord data...\n");
00916   word_res->word->print();
00917   if (word_res->blamer_bundle != NULL && wordrec_debug_blamer &&
00918       word_res->blamer_bundle->incorrect_result_reason != IRR_CORRECT) {
00919     tprintf("Current blamer debug: %s\n",
00920             word_res->blamer_bundle->debug.string());
00921   }
00922   return TRUE;
00923 }
00924 
00925 #ifndef GRAPHICS_DISABLED
00926 
00931 BOOL8 Tesseract::word_set_display(BLOCK* block, ROW* row, WERD_RES* word_res) {
00932   WERD* word = word_res->word;
00933   word->set_display_flag(DF_BOX, word_display_mode.bit(DF_BOX));
00934   word->set_display_flag(DF_TEXT, word_display_mode.bit(DF_TEXT));
00935   word->set_display_flag(DF_POLYGONAL, word_display_mode.bit(DF_POLYGONAL));
00936   word->set_display_flag(DF_EDGE_STEP, word_display_mode.bit(DF_EDGE_STEP));
00937   word->set_display_flag(DF_BN_POLYGONAL,
00938     word_display_mode.bit(DF_BN_POLYGONAL));
00939   word->set_display_flag(DF_BLAMER, word_display_mode.bit(DF_BLAMER));
00940   return word_display(block, row, word_res);
00941 }
00942 #endif  // GRAPHICS_DISABLED
00943 
00944 }  // namespace tesseract
00945 
00946 
00947