tesseract  4.1.0
pgedit.cpp
Go to the documentation of this file.
1 /**********************************************************************
2  * File: pgedit.cpp (Formerly pgeditor.c)
3  * Description: Page structure file editor
4  * Author: Phil Cheatle
5  *
6  *(C) Copyright 1991, Hewlett-Packard Ltd.
7  ** Licensed under the Apache License, Version 2.0(the "License");
8  ** you may not use this file except in compliance with the License.
9  ** You may obtain a copy of the License at
10  ** http:// www.apache.org/licenses/LICENSE-2.0
11  ** Unless required by applicable law or agreed to in writing, software
12  ** distributed under the License is distributed on an "AS IS" BASIS,
13  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  ** See the License for the specific language governing permissions and
15  ** limitations under the License.
16  *
17  **********************************************************************/
18 
19 // Include automatically generated configuration file if running autoconf.
20 #ifdef HAVE_CONFIG_H
21 #include "config_auto.h"
22 #endif
23 
24 #include "pgedit.h"
25 
26 #include <cctype>
27 #include <cmath>
28 
29 #include "blread.h"
30 #include "control.h"
31 #include "paramsd.h"
32 #include "pageres.h"
33 #include "tordmain.h"
34 #include "scrollview.h"
35 #include "svmnode.h"
36 #include "statistc.h"
37 #include "tesseractclass.h"
38 #include "werdit.h"
39 
40 #ifndef GRAPHICS_DISABLED
41 #define ASC_HEIGHT (2 * kBlnBaselineOffset + kBlnXHeight)
42 #define X_HEIGHT (kBlnBaselineOffset + kBlnXHeight)
43 #define BL_HEIGHT kBlnBaselineOffset
44 #define DESC_HEIGHT 0
45 
47 {
78 };
79 
91 };
92 
93 /*
94  *
95  * Some global data
96  *
97  */
98 
99 static ScrollView* image_win;
100 static ParamsEditor* pe;
101 static bool stillRunning = false;
102 
103 static ScrollView* bln_word_window = nullptr; // baseline norm words
104 
105 static CMD_EVENTS mode = CHANGE_DISP_CMD_EVENT; // selected words op
106 
107 static bool recog_done = false; // recog_all_words was called
108 
109 // These variables should remain global, since they are only used for the
110 // debug mode (in which only a single Tesseract thread/instance will exist).
111 static BITS16 word_display_mode;
112 static ColorationMode color_mode = CM_RAINBOW;
113 static bool display_image = false;
114 static bool display_blocks = false;
115 static bool display_baselines = false;
116 
117 static PAGE_RES *current_page_res = nullptr;
118 
119 STRING_VAR(editor_image_win_name, "EditorImage",
120  "Editor image window name");
121 INT_VAR(editor_image_xpos, 590, "Editor image X Pos");
122 INT_VAR(editor_image_ypos, 10, "Editor image Y Pos");
123 static INT_VAR(editor_image_menuheight, 50, "Add to image height for menu bar");
125  "Word bounding box colour");
127  "Blob bounding box colour");
129  "Correct text colour");
130 
131 STRING_VAR(editor_dbwin_name, "EditorDBWin",
132  "Editor debug window name");
133 INT_VAR(editor_dbwin_xpos, 50, "Editor debug window X Pos");
134 INT_VAR(editor_dbwin_ypos, 500, "Editor debug window Y Pos");
135 INT_VAR(editor_dbwin_height, 24, "Editor debug window height");
136 INT_VAR(editor_dbwin_width, 80, "Editor debug window width");
137 
138 STRING_VAR(editor_word_name, "BlnWords", "BL normalized word window");
139 INT_VAR(editor_word_xpos, 60, "Word window X Pos");
140 INT_VAR(editor_word_ypos, 510, "Word window Y Pos");
141 INT_VAR(editor_word_height, 240, "Word window height");
142 INT_VAR(editor_word_width, 655, "Word window width");
143 
144 static STRING_VAR(editor_debug_config_file, "", "Config file to apply to single words");
145 
153 static void show_point(PAGE_RES* page_res, float x, float y) {
154  FCOORD pt(x, y);
155  PAGE_RES_IT pr_it(page_res);
156 
157  const int kBufsize = 512;
158  char msg[kBufsize];
159  char *msg_ptr = msg;
160 
161  msg_ptr += sprintf(msg_ptr, "Pt:(%0.3f, %0.3f) ", x, y);
162 
163  for (WERD_RES* word = pr_it.word(); word != nullptr; word = pr_it.forward()) {
164  if (pr_it.row() != pr_it.prev_row() &&
165  pr_it.row()->row->bounding_box().contains(pt)) {
166  msg_ptr += sprintf(msg_ptr, "BL(x)=%0.3f ",
167  pr_it.row()->row->base_line(x));
168  }
169  if (word->word->bounding_box().contains(pt)) {
170  TBOX box = word->word->bounding_box();
171  msg_ptr += sprintf(msg_ptr, "Wd(%d, %d)/(%d, %d) ",
172  box.left(), box.bottom(),
173  box.right(), box.top());
174  C_BLOB_IT cblob_it(word->word->cblob_list());
175  for (cblob_it.mark_cycle_pt();
176  !cblob_it.cycled_list();
177  cblob_it.forward()) {
178  C_BLOB* cblob = cblob_it.data();
179  box = cblob->bounding_box();
180  if (box.contains(pt)) {
181  msg_ptr += sprintf(msg_ptr,
182  "CBlb(%d, %d)/(%d, %d) ",
183  box.left(), box.bottom(),
184  box.right(), box.top());
185  }
186  }
187  }
188  }
189  image_win->AddMessage(msg);
190 }
191 
198 static void pgeditor_msg( // message display
199  const char *msg) {
200  image_win->AddMessage(msg);
201 }
202 
204  public:
205  void Notify(const SVEvent* sv_event) override {
206  if (sv_event->type == SVET_DESTROY)
207  bln_word_window = nullptr;
208  else if (sv_event->type == SVET_CLICK)
209  show_point(current_page_res, sv_event->x, sv_event->y);
210  }
211 };
212 
218 static ScrollView* bln_word_window_handle() { // return handle
219  // not opened yet
220  if (bln_word_window == nullptr) {
221  pgeditor_msg("Creating BLN word window...");
222  bln_word_window = new ScrollView(editor_word_name.string(),
224  editor_word_height, 4000, 4000, true);
225  auto* a = new BlnEventHandler();
226  bln_word_window->AddEventHandler(a);
227  pgeditor_msg("Creating BLN word window...Done");
228  }
229  return bln_word_window;
230 }
231 
239 static void build_image_window(int width, int height) {
240  delete image_win;
241  image_win = new ScrollView(editor_image_win_name.string(),
243  width + 1,
244  height + editor_image_menuheight + 1,
245  width,
246  height,
247  true);
248 }
249 
256 static void display_bln_lines(ScrollView* window, ScrollView::Color colour,
257  float scale_factor, float y_offset,
258  float minx, float maxx) {
259  window->Pen(colour);
260  window->Line(minx, y_offset + scale_factor * DESC_HEIGHT,
261  maxx, y_offset + scale_factor * DESC_HEIGHT);
262  window->Line(minx, y_offset + scale_factor * BL_HEIGHT,
263  maxx, y_offset + scale_factor * BL_HEIGHT);
264  window->Line(minx, y_offset + scale_factor * X_HEIGHT,
265  maxx, y_offset + scale_factor * X_HEIGHT);
266  window->Line(minx, y_offset + scale_factor * ASC_HEIGHT,
267  maxx, y_offset + scale_factor * ASC_HEIGHT);
268 }
269 
278 void PGEventHandler::Notify(const SVEvent* event) {
279  char myval = '0';
280  if (event->type == SVET_POPUP) {
281  pe->Notify(event);
282  } // These are handled by ParamsEditor
283  else if (event->type == SVET_EXIT) { stillRunning = false; }
284  else if (event->type == SVET_MENU) {
285  if (strcmp(event->parameter, "true") == 0) { myval = 'T'; }
286  else if (strcmp(event->parameter, "false") == 0) { myval = 'F'; }
287  tess_->process_cmd_win_event(event->command_id, &myval);
288  }
289  else {
290  tess_->process_image_event(*event);
291  }
292 }
293 
299 namespace tesseract {
300 SVMenuNode *Tesseract::build_menu_new() {
301  SVMenuNode* parent_menu;
302  auto* root_menu_item = new SVMenuNode();
303 
304  SVMenuNode* modes_menu_item = root_menu_item->AddChild("MODES");
305 
306  modes_menu_item->AddChild("Change Display", CHANGE_DISP_CMD_EVENT);
307  modes_menu_item->AddChild("Dump Word", DUMP_WERD_CMD_EVENT);
308  modes_menu_item->AddChild("Show Point", SHOW_POINT_CMD_EVENT);
309  modes_menu_item->AddChild("Show BL Norm Word", SHOW_BLN_WERD_CMD_EVENT);
310  modes_menu_item->AddChild("Config Words", DEBUG_WERD_CMD_EVENT);
311  modes_menu_item->AddChild("Recog Words", RECOG_WERDS);
312  modes_menu_item->AddChild("Recog Blobs", RECOG_PSEUDO);
313  modes_menu_item->AddChild("Show Blob Features", SHOW_BLOB_FEATURES);
314 
315  parent_menu = root_menu_item->AddChild("DISPLAY");
316 
317  parent_menu->AddChild("Blamer", BLAMER_CMD_EVENT, false);
318  parent_menu->AddChild("Bounding Boxes", BOUNDING_BOX_CMD_EVENT, false);
319  parent_menu->AddChild("Correct Text", CORRECT_TEXT_CMD_EVENT, false);
320  parent_menu->AddChild("Polygonal Approx", POLYGONAL_CMD_EVENT, false);
321  parent_menu->AddChild("Baseline Normalized", BL_NORM_CMD_EVENT, false);
322  parent_menu->AddChild("Edge Steps", BITMAP_CMD_EVENT, true);
323  parent_menu->AddChild("Subscripts", SHOW_SUBSCRIPT_CMD_EVENT);
324  parent_menu->AddChild("Superscripts", SHOW_SUPERSCRIPT_CMD_EVENT);
325  parent_menu->AddChild("Italics", SHOW_ITALIC_CMD_EVENT);
326  parent_menu->AddChild("Bold", SHOW_BOLD_CMD_EVENT);
327  parent_menu->AddChild("Underline", SHOW_UNDERLINE_CMD_EVENT);
328  parent_menu->AddChild("FixedPitch", SHOW_FIXEDPITCH_CMD_EVENT);
329  parent_menu->AddChild("Serifs", SHOW_SERIF_CMD_EVENT);
330  parent_menu->AddChild("SmallCaps", SHOW_SMALLCAPS_CMD_EVENT);
331  parent_menu->AddChild("DropCaps", SHOW_DROPCAPS_CMD_EVENT);
332 
333 
334  parent_menu = root_menu_item->AddChild("OTHER");
335 
336  parent_menu->AddChild("Quit", QUIT_CMD_EVENT);
337  parent_menu->AddChild("Show Image", IMAGE_CMD_EVENT, false);
338  parent_menu->AddChild("ShowBlock Outlines", BLOCKS_CMD_EVENT, false);
339  parent_menu->AddChild("Show Baselines", BASELINES_CMD_EVENT, false);
340  parent_menu->AddChild("Uniform Display", UNIFORM_DISP_CMD_EVENT);
341  parent_menu->AddChild("Refresh Display", REFRESH_CMD_EVENT);
342 
343  return root_menu_item;
344 }
345 
351 void Tesseract::do_re_display(
352  bool (tesseract::Tesseract::* word_painter)(PAGE_RES_IT* pr_it)) {
353  int block_count = 1;
354 
355  image_win->Clear();
356  if (display_image) {
357  image_win->Image(pix_binary_, 0, 0);
358  }
359 
360  image_win->Brush(ScrollView::NONE);
361  PAGE_RES_IT pr_it(current_page_res);
362  for (WERD_RES* word = pr_it.word(); word != nullptr; word = pr_it.forward()) {
363  (this->*word_painter)(&pr_it);
364  if (display_baselines && pr_it.row() != pr_it.prev_row())
365  pr_it.row()->row->plot_baseline(image_win, ScrollView::GREEN);
366  if (display_blocks && pr_it.block() != pr_it.prev_block())
367  pr_it.block()->block->pdblk.plot(image_win, block_count++, ScrollView::RED);
368  }
369  image_win->Update();
370 }
371 
380 void Tesseract::pgeditor_main(int width, int height, PAGE_RES *page_res) {
381  current_page_res = page_res;
382  if (current_page_res->block_res_list.empty())
383  return;
384 
385  recog_done = false;
386  stillRunning = true;
387 
388  build_image_window(width, height);
389  word_display_mode.turn_on_bit(DF_EDGE_STEP);
391 #ifndef GRAPHICS_DISABLED
392  pe = new ParamsEditor(this, image_win);
393 #endif
394  PGEventHandler pgEventHandler(this);
395 
396  image_win->AddEventHandler(&pgEventHandler);
397  image_win->AddMessageBox();
398 
399  SVMenuNode* svMenuRoot = build_menu_new();
400 
401  svMenuRoot->BuildMenu(image_win);
402  image_win->SetVisible(true);
403 
404  image_win->AwaitEvent(SVET_DESTROY);
405  image_win->AddEventHandler(nullptr);
406 }
407 } // namespace tesseract
408 
416 namespace tesseract {
417 bool Tesseract::process_cmd_win_event( // UI command semantics
418  int32_t cmd_event, // which menu item?
419  char* new_value // any prompt data
420 ) {
421  char msg[160];
422  bool exit = false;
423 
424  color_mode = CM_RAINBOW;
425 
426  // Run recognition on the full page if needed.
427  switch (cmd_event) {
428  case BLAMER_CMD_EVENT:
432  case SHOW_BOLD_CMD_EVENT:
438  if (!recog_done) {
439  recog_all_words(current_page_res, nullptr, nullptr, nullptr, 0);
440  recog_done = true;
441  }
442  break;
443  default:
444  break;
445  }
446 
447  char* parameter;
448 
449  switch (cmd_event) {
450  case NULL_CMD_EVENT:
451  break;
452 
454  case DUMP_WERD_CMD_EVENT:
457  case RECOG_WERDS:
458  case RECOG_PSEUDO:
459  case SHOW_BLOB_FEATURES:
460  mode =static_cast<CMD_EVENTS>(cmd_event);
461  break;
463  mode = DEBUG_WERD_CMD_EVENT;
464  parameter = image_win->ShowInputDialog("Config File Name");
465  word_config_ = parameter;
466  delete[] parameter;
467  break;
469  if (new_value[0] == 'T')
470  word_display_mode.turn_on_bit(DF_BOX);
471  else
472  word_display_mode.turn_off_bit(DF_BOX);
473  mode = CHANGE_DISP_CMD_EVENT;
474  break;
475  case BLAMER_CMD_EVENT:
476  if (new_value[0] == 'T')
477  word_display_mode.turn_on_bit(DF_BLAMER);
478  else
479  word_display_mode.turn_off_bit(DF_BLAMER);
480  do_re_display(&tesseract::Tesseract::word_display);
481  mode = CHANGE_DISP_CMD_EVENT;
482  break;
484  if (new_value[0] == 'T')
485  word_display_mode.turn_on_bit(DF_TEXT);
486  else
487  word_display_mode.turn_off_bit(DF_TEXT);
488  mode = CHANGE_DISP_CMD_EVENT;
489  break;
490  case POLYGONAL_CMD_EVENT:
491  if (new_value[0] == 'T')
492  word_display_mode.turn_on_bit(DF_POLYGONAL);
493  else
494  word_display_mode.turn_off_bit(DF_POLYGONAL);
495  mode = CHANGE_DISP_CMD_EVENT;
496  break;
497  case BL_NORM_CMD_EVENT:
498  if (new_value[0] == 'T')
499  word_display_mode.turn_on_bit(DF_BN_POLYGONAL);
500  else
501  word_display_mode.turn_off_bit(DF_BN_POLYGONAL);
502  mode = CHANGE_DISP_CMD_EVENT;
503  break;
504  case BITMAP_CMD_EVENT:
505  if (new_value[0] == 'T')
506  word_display_mode.turn_on_bit(DF_EDGE_STEP);
507  else
508  word_display_mode.turn_off_bit(DF_EDGE_STEP);
509  mode = CHANGE_DISP_CMD_EVENT;
510  break;
513  break;
514  case IMAGE_CMD_EVENT:
515  display_image =(new_value[0] == 'T');
516  do_re_display(&tesseract::Tesseract::word_display);
517  break;
518  case BLOCKS_CMD_EVENT:
519  display_blocks =(new_value[0] == 'T');
520  do_re_display(&tesseract::Tesseract::word_display);
521  break;
522  case BASELINES_CMD_EVENT:
523  display_baselines =(new_value[0] == 'T');
524  do_re_display(&tesseract::Tesseract::word_display);
525  break;
527  color_mode = CM_SUBSCRIPT;
528  do_re_display(&tesseract::Tesseract::word_display);
529  break;
531  color_mode = CM_SUPERSCRIPT;
532  do_re_display(&tesseract::Tesseract::word_display);
533  break;
535  color_mode = CM_ITALIC;
536  do_re_display(&tesseract::Tesseract::word_display);
537  break;
538  case SHOW_BOLD_CMD_EVENT:
539  color_mode = CM_BOLD;
540  do_re_display(&tesseract::Tesseract::word_display);
541  break;
543  color_mode = CM_UNDERLINE;
544  do_re_display(&tesseract::Tesseract::word_display);
545  break;
547  color_mode = CM_FIXEDPITCH;
548  do_re_display(&tesseract::Tesseract::word_display);
549  break;
551  color_mode = CM_SERIF;
552  do_re_display(&tesseract::Tesseract::word_display);
553  break;
555  color_mode = CM_SMALLCAPS;
556  do_re_display(&tesseract::Tesseract::word_display);
557  break;
559  color_mode = CM_DROPCAPS;
560  do_re_display(&tesseract::Tesseract::word_display);
561  break;
562  case REFRESH_CMD_EVENT:
563  do_re_display(&tesseract::Tesseract::word_display);
564  break;
565  case QUIT_CMD_EVENT:
566  exit = true;
568  break;
569 
570  default:
571  snprintf(msg, sizeof(msg), "Unrecognised event %" PRId32 "(%s)",
572  cmd_event, new_value);
573  image_win->AddMessage(msg);
574  break;
575  }
576  return exit;
577 }
578 
579 
589 void Tesseract::process_image_event( // action in image win
590  const SVEvent &event) {
591  // The following variable should remain static, since it is used by
592  // debug editor, which uses a single Tesseract instance.
593  static ICOORD down;
594  ICOORD up;
595  TBOX selection_box;
596  char msg[80];
597 
598  switch(event.type) {
599 
600  case SVET_SELECTION:
601  if (event.type == SVET_SELECTION) {
602  down.set_x(event.x + event.x_size);
603  down.set_y(event.y + event.y_size);
604  if (mode == SHOW_POINT_CMD_EVENT)
605  show_point(current_page_res, event.x, event.y);
606  }
607 
608  up.set_x(event.x);
609  up.set_y(event.y);
610 
611  selection_box = TBOX(down, up);
612 
613  switch(mode) {
615  process_selected_words(
616  current_page_res,
617  selection_box,
619  break;
620  case DUMP_WERD_CMD_EVENT:
621  process_selected_words(current_page_res,
622  selection_box,
624  break;
626  process_selected_words(current_page_res,
627  selection_box,
629  break;
631  debug_word(current_page_res, selection_box);
632  break;
634  break; // ignore up event
635 
636  case RECOG_WERDS:
637  #ifndef DISABLED_LEGACY_ENGINE
638  image_win->AddMessage("Recogging selected words");
639  this->process_selected_words(current_page_res,
640  selection_box,
641  &Tesseract::recog_interactive);
642  #endif // ndef DISABLED_LEGACY_ENGINE
643  break;
644  case RECOG_PSEUDO:
645  image_win->AddMessage("Recogging selected blobs");
646  recog_pseudo_word(current_page_res, selection_box);
647  break;
648  case SHOW_BLOB_FEATURES:
649  blob_feature_display(current_page_res, selection_box);
650  break;
651 
652  default:
653  sprintf(msg, "Mode %d not yet implemented", mode);
654  image_win->AddMessage(msg);
655  break;
656  }
657  default:
658  break;
659  }
660 }
661 
667 void Tesseract::debug_word(PAGE_RES* page_res, const TBOX &selection_box) {
668 #ifndef DISABLED_LEGACY_ENGINE
669  ResetAdaptiveClassifier();
670 #endif
671  recog_all_words(page_res, nullptr, &selection_box, word_config_.string(), 0);
672 }
673 } // namespace tesseract
674 
675 
676 /**********************************************************************
677  * WERD PROCESSOR FUNCTIONS
678  * ========================
679  *
680  * These routines are invoked by one or more of:
681  * process_all_words()
682  * process_selected_words()
683  * or
684  * process_all_words_it()
685  * process_selected_words_it()
686  * for each word to be processed
687  **********************************************************************/
688 
695 #endif // GRAPHICS_DISABLED
696 namespace tesseract {
697 #ifndef GRAPHICS_DISABLED
698 bool Tesseract::word_blank_and_set_display(PAGE_RES_IT* pr_it) {
699  pr_it->word()->word->bounding_box().plot(image_win, ScrollView::BLACK,
701  return word_set_display(pr_it);
702 }
703 
704 
710 bool Tesseract::word_bln_display(PAGE_RES_IT* pr_it) {
711  WERD_RES* word_res = pr_it->word();
712  if (word_res->chopped_word == nullptr) {
713  // Setup word normalization parameters.
714  word_res->SetupForRecognition(unicharset, this, BestPix(),
715  tessedit_ocr_engine_mode, nullptr,
716  classify_bln_numeric_mode,
717  textord_use_cjk_fp_model,
718  poly_allow_detailed_fx,
719  pr_it->row()->row, pr_it->block()->block);
720  }
721  bln_word_window_handle()->Clear();
722  display_bln_lines(bln_word_window_handle(), ScrollView::CYAN,
723  1.0, 0.0f, -1000.0f, 1000.0f);
724  C_BLOB_IT it(word_res->word->cblob_list());
726  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
727  it.data()->plot_normed(word_res->denorm, color, ScrollView::BROWN,
728  bln_word_window_handle());
729  color = WERD::NextColor(color);
730  }
731  bln_word_window_handle()->Update();
732  return true;
733 }
734 
735 
736 
742 bool Tesseract::word_display(PAGE_RES_IT* pr_it) {
743  WERD_RES* word_res = pr_it->word();
744  WERD* word = word_res->word;
745  TBOX word_bb; // word bounding box
746  int word_height; // ht of word BB
747  bool displayed_something = false;
748  float shift; // from bot left
749 
750  if (color_mode != CM_RAINBOW && word_res->box_word != nullptr) {
751  BoxWord* box_word = word_res->box_word;
752  WERD_CHOICE* best_choice = word_res->best_choice;
753  int length = box_word->length();
754  if (word_res->fontinfo == nullptr) return false;
755  const FontInfo& font_info = *word_res->fontinfo;
756  for (int i = 0; i < length; ++i) {
758  switch (color_mode) {
759  case CM_SUBSCRIPT:
760  if (best_choice->BlobPosition(i) == SP_SUBSCRIPT)
761  color = ScrollView::RED;
762  break;
763  case CM_SUPERSCRIPT:
764  if (best_choice->BlobPosition(i) == SP_SUPERSCRIPT)
765  color = ScrollView::RED;
766  break;
767  case CM_ITALIC:
768  if (font_info.is_italic())
769  color = ScrollView::RED;
770  break;
771  case CM_BOLD:
772  if (font_info.is_bold())
773  color = ScrollView::RED;
774  break;
775  case CM_FIXEDPITCH:
776  if (font_info.is_fixed_pitch())
777  color = ScrollView::RED;
778  break;
779  case CM_SERIF:
780  if (font_info.is_serif())
781  color = ScrollView::RED;
782  break;
783  case CM_SMALLCAPS:
784  if (word_res->small_caps)
785  color = ScrollView::RED;
786  break;
787  case CM_DROPCAPS:
788  if (best_choice->BlobPosition(i) == SP_DROPCAP)
789  color = ScrollView::RED;
790  break;
791  // TODO(rays) underline is currently completely unsupported.
792  case CM_UNDERLINE:
793  default:
794  break;
795  }
796  image_win->Pen(color);
797  TBOX box = box_word->BlobBox(i);
798  image_win->Rectangle(box.left(), box.bottom(), box.right(), box.top());
799  }
800  return true;
801  }
802  /*
803  Note the double coercions of(COLOUR)((int32_t)editor_image_word_bb_color)
804  etc. are to keep the compiler happy.
805  */
806  // display bounding box
807  if (word->display_flag(DF_BOX)) {
808  word->bounding_box().plot(image_win,
809  static_cast<ScrollView::Color>((int32_t)
811  static_cast<ScrollView::Color>((int32_t)
812  editor_image_word_bb_color));
813 
814  auto c = static_cast<ScrollView::Color>((int32_t) editor_image_blob_bb_color);
815  image_win->Pen(c);
816  // cblob iterator
817  C_BLOB_IT c_it(word->cblob_list());
818  for (c_it.mark_cycle_pt(); !c_it.cycled_list(); c_it.forward())
819  c_it.data()->bounding_box().plot(image_win);
820  displayed_something = true;
821  }
822 
823  // display edge steps
824  if (word->display_flag(DF_EDGE_STEP)) { // edgesteps available
825  word->plot(image_win); // rainbow colors
826  displayed_something = true;
827  }
828 
829  // display poly approx
830  if (word->display_flag(DF_POLYGONAL)) {
831  // need to convert
832  TWERD* tword = TWERD::PolygonalCopy(poly_allow_detailed_fx, word);
833  tword->plot(image_win);
834  delete tword;
835  displayed_something = true;
836  }
837 
838  // Display correct text and blamer information.
839  STRING text;
840  STRING blame;
841  if (word->display_flag(DF_TEXT) && word->text() != nullptr) {
842  text = word->text();
843  }
844  if (word->display_flag(DF_BLAMER) &&
845  !(word_res->blamer_bundle != nullptr &&
847  text = "";
848  const BlamerBundle *blamer_bundle = word_res->blamer_bundle;
849  if (blamer_bundle == nullptr) {
850  text += "NULL";
851  } else {
852  text = blamer_bundle->TruthString();
853  }
854  text += " -> ";
855  STRING best_choice_str;
856  if (word_res->best_choice == nullptr) {
857  best_choice_str = "NULL";
858  } else {
859  word_res->best_choice->string_and_lengths(&best_choice_str, nullptr);
860  }
861  text += best_choice_str;
862  IncorrectResultReason reason = (blamer_bundle == nullptr) ?
863  IRR_PAGE_LAYOUT : blamer_bundle->incorrect_result_reason();
864  ASSERT_HOST(reason < IRR_NUM_REASONS);
865  blame += " [";
866  blame += BlamerBundle::IncorrectReasonName(reason);
867  blame += "]";
868  }
869  if (text.length() > 0) {
870  word_bb = word->bounding_box();
871  image_win->Pen(ScrollView::RED);
872  word_height = word_bb.height();
873  int text_height = 0.50 * word_height;
874  if (text_height > 20) text_height = 20;
875  image_win->TextAttributes("Arial", text_height, false, false, false);
876  shift = (word_height < word_bb.width()) ? 0.25 * word_height : 0.0f;
877  image_win->Text(word_bb.left() + shift,
878  word_bb.bottom() + 0.25 * word_height, text.string());
879  if (blame.length() > 0) {
880  image_win->Text(word_bb.left() + shift,
881  word_bb.bottom() + 0.25 * word_height - text_height,
882  blame.string());
883  }
884 
885  displayed_something = true;
886  }
887 
888  if (!displayed_something) // display BBox anyway
889  word->bounding_box().plot(image_win,
890  static_cast<ScrollView::Color>((int32_t) editor_image_word_bb_color),
891  static_cast<ScrollView::Color>((int32_t)
892  editor_image_word_bb_color));
893  return true;
894 }
895 #endif // GRAPHICS_DISABLED
896 
902 bool Tesseract::word_dumper(PAGE_RES_IT* pr_it) {
903  if (pr_it->block()->block != nullptr) {
904  tprintf("\nBlock data...\n");
905  pr_it->block()->block->print(nullptr, false);
906  }
907  tprintf("\nRow data...\n");
908  pr_it->row()->row->print(nullptr);
909  tprintf("\nWord data...\n");
910  WERD_RES* word_res = pr_it->word();
911  word_res->word->print();
912  if (word_res->blamer_bundle != nullptr && wordrec_debug_blamer &&
914  tprintf("Current blamer debug: %s\n",
915  word_res->blamer_bundle->debug().string());
916  }
917  return true;
918 }
919 
920 #ifndef GRAPHICS_DISABLED
921 
926 bool Tesseract::word_set_display(PAGE_RES_IT* pr_it) {
927  WERD* word = pr_it->word()->word;
928  word->set_display_flag(DF_BOX, word_display_mode.bit(DF_BOX));
929  word->set_display_flag(DF_TEXT, word_display_mode.bit(DF_TEXT));
930  word->set_display_flag(DF_POLYGONAL, word_display_mode.bit(DF_POLYGONAL));
931  word->set_display_flag(DF_EDGE_STEP, word_display_mode.bit(DF_EDGE_STEP));
933  word_display_mode.bit(DF_BN_POLYGONAL));
934  word->set_display_flag(DF_BLAMER, word_display_mode.bit(DF_BLAMER));
935  return word_display(pr_it);
936 }
937 
938 
939 // page_res is non-const because the iterator doesn't know if you are going
940 // to change the items it points to! Really a const here though.
941 void Tesseract::blob_feature_display(PAGE_RES* page_res,
942  const TBOX& selection_box) {
943 #ifndef DISABLED_LEGACY_ENGINE
944  PAGE_RES_IT* it = make_pseudo_word(page_res, selection_box);
945  if (it != nullptr) {
946  WERD_RES* word_res = it->word();
947  word_res->x_height = it->row()->row->x_height();
948  word_res->SetupForRecognition(unicharset, this, BestPix(),
949  tessedit_ocr_engine_mode, nullptr,
950  classify_bln_numeric_mode,
951  textord_use_cjk_fp_model,
952  poly_allow_detailed_fx,
953  it->row()->row, it->block()->block);
954  TWERD* bln_word = word_res->chopped_word;
955  TBLOB* bln_blob = bln_word->blobs[0];
956  INT_FX_RESULT_STRUCT fx_info;
959  Classify::ExtractFeatures(*bln_blob, classify_nonlinear_norm, &bl_features,
960  &cn_features, &fx_info, nullptr);
961  // Display baseline features.
962  ScrollView* bl_win = CreateFeatureSpaceWindow("BL Features", 512, 0);
964  for (int f = 0; f < bl_features.size(); ++f)
965  RenderIntFeature(bl_win, &bl_features[f], ScrollView::GREEN);
966  bl_win->Update();
967  // Display cn features.
968  ScrollView* cn_win = CreateFeatureSpaceWindow("CN Features", 512, 0);
970  for (int f = 0; f < cn_features.size(); ++f)
971  RenderIntFeature(cn_win, &cn_features[f], ScrollView::GREEN);
972  cn_win->Update();
973 
974  it->DeleteCurrentWord();
975  delete it;
976  }
977 #endif // ndef DISABLED_LEGACY_ENGINE
978 }
979 
980 
981 #endif // GRAPHICS_DISABLED
982 
983 } // namespace tesseract
void Notify(const SVEvent *sv_event) override
Definition: pgedit.cpp:205
Definition: werd.h:56
void BuildMenu(ScrollView *sv, bool menu_bar=true)
Definition: svmnode.cpp:120
int editor_image_xpos
Definition: pgedit.cpp:121
int editor_image_ypos
Definition: pgedit.cpp:122
STRING TruthString() const
Definition: blamer.h:112
void print(FILE *fp, bool dump)
dump whole table
Definition: ocrblock.cpp:191
bool word_display(PAGE_RES_IT *pr_it)
Definition: pgedit.cpp:742
BLOCK * block
Definition: pageres.h:116
int16_t top() const
Definition: rect.h:58
int editor_word_width
Definition: pgedit.cpp:142
SVMenuNode * AddChild(const char *txt)
Definition: svmnode.cpp:58
void Text(int x, int y, const char *mystring)
Definition: scrollview.cpp:652
void Notify(const SVEvent *sve) override
Definition: paramsd.cpp:271
int editor_word_height
Definition: pgedit.cpp:141
float x_height() const
Definition: ocrrow.h:64
static TWERD * PolygonalCopy(bool allow_detailed_fx, WERD *src)
Definition: blobs.cpp:780
Definition: rect.h:34
int command_id
Definition: scrollview.h:70
static void Exit()
Definition: scrollview.cpp:583
void SetVisible(bool visible)
Definition: scrollview.cpp:549
Definition: blobs.h:397
void Image(struct Pix *image, int x_pos, int y_pos)
Definition: scrollview.cpp:765
bool SetupForRecognition(const UNICHARSET &unicharset_in, tesseract::Tesseract *tesseract, Pix *pix, int norm_mode, const TBOX *norm_box, bool numeric_mode, bool use_body_size, bool allow_detailed_fx, ROW *row, const BLOCK *block)
Definition: pageres.cpp:306
Definition: strngs.h:45
GenericVector< TBLOB * > blobs
Definition: blobs.h:438
Definition: points.h:188
void Rectangle(int x1, int y1, int x2, int y2)
Definition: scrollview.cpp:600
void set_x(int16_t xin)
rewrite function
Definition: points.h:61
int editor_word_ypos
Definition: pgedit.cpp:140
IncorrectResultReason
Definition: blamer.h:49
#define INT_VAR(name, val, comment)
Definition: params.h:303
bool is_italic() const
Definition: fontinfo.h:111
ROW_RES * prev_row() const
Definition: pageres.h:749
bool word_blank_and_set_display(PAGE_RES_IT *pr_its)
Definition: pgedit.cpp:698
ROW_RES * row() const
Definition: pageres.h:758
int editor_image_word_bb_color
Definition: pgedit.cpp:125
int32_t length() const
Definition: strngs.cpp:189
Correct ascii.
Definition: werd.h:47
int x_size
Definition: scrollview.h:68
void Notify(const SVEvent *sve) override
Definition: pgedit.cpp:278
BLOCK_RES * block() const
Definition: pageres.h:761
void ClearFeatureSpaceWindow(NORM_METHOD norm_method, ScrollView *window)
Definition: intproto.cpp:987
void set_display_flag(uint8_t flag, bool value)
Definition: werd.h:121
static ScrollView::Color NextColor(ScrollView::Color colour)
Definition: werd.cpp:292
integer coordinate
Definition: points.h:31
char * ShowInputDialog(const char *msg)
Definition: scrollview.cpp:733
bool word_set_display(PAGE_RES_IT *pr_it)
Definition: pgedit.cpp:926
bool contains(const FCOORD pt) const
Definition: rect.h:333
Definition: blobs.h:263
void set_y(int16_t yin)
rewrite function
Definition: points.h:65
const TBOX & BlobBox(int index) const
Definition: boxword.h:84
int editor_dbwin_height
Definition: pgedit.cpp:135
char * editor_image_win_name
Definition: pgedit.cpp:120
bool bit(uint8_t bit_num) const
Definition: bits16.h:51
TBOX bounding_box() const
Definition: stepblob.cpp:253
void AddMessageBox()
Definition: scrollview.cpp:578
int x
Definition: scrollview.h:66
bool word_dumper(PAGE_RES_IT *pr_it)
Definition: pgedit.cpp:902
int editor_dbwin_ypos
Definition: pgedit.cpp:134
void plot(ScrollView *window)
Definition: blobs.cpp:901
#define ASC_HEIGHT
Definition: pgedit.cpp:41
int length() const
Definition: boxword.h:83
int editor_dbwin_xpos
Definition: pgedit.cpp:133
void Brush(Color color)
Definition: scrollview.cpp:725
#define X_HEIGHT
Definition: pgedit.cpp:42
SVEvent * AwaitEvent(SVEventType type)
Definition: scrollview.cpp:443
Blamer information.
Definition: werd.h:51
ColorationMode
Definition: pgedit.cpp:80
int16_t height() const
Definition: rect.h:108
int y
Definition: scrollview.h:67
void plot_baseline(ScrollView *window, ScrollView::Color colour)
Definition: ocrrow.h:137
Edge steps.
Definition: werd.h:49
void string_and_lengths(STRING *word_str, STRING *word_lengths_str) const
Definition: ratngs.cpp:449
void print()
Definition: werd.cpp:253
void turn_off_bit(uint8_t bit_num)
Definition: bits16.h:37
static void Update()
Definition: scrollview.cpp:709
void TextAttributes(const char *font, int pixel_size, bool bold, bool italic, bool underlined)
Definition: scrollview.cpp:635
void plot(ScrollView *fd) const
Definition: rect.h:286
char * parameter
Definition: scrollview.h:71
ScrollView * CreateFeatureSpaceWindow(const char *name, int xpos, int ypos)
Definition: intproto.cpp:1763
bool word_bln_display(PAGE_RES_IT *pr_it)
Definition: pgedit.cpp:710
IncorrectResultReason incorrect_result_reason() const
Definition: blamer.h:118
CMD_EVENTS
Definition: pgedit.cpp:46
#define STRING_VAR(name, val, comment)
Definition: params.h:309
void AddEventHandler(SVEventHandler *listener)
Add an Event Listener to this ScrollView Window.
Definition: scrollview.cpp:414
BLOCK_RES * prev_block() const
Definition: pageres.h:752
Polyg approx.
Definition: werd.h:48
bool small_caps
Definition: pageres.h:298
void Pen(Color color)
Definition: scrollview.cpp:719
const FontInfo * fontinfo
Definition: pageres.h:303
const char * string() const
Definition: strngs.cpp:194
DLLSYM void tprintf(const char *format,...)
Definition: tprintf.cpp:36
const STRING & debug() const
Definition: blamer.h:128
void Clear()
Definition: scrollview.cpp:589
PAGE_RES_IT * make_pseudo_word(PAGE_RES *page_res, const TBOX &selection_box)
Definition: werdit.cpp:35
tesseract::BoxWord * box_word
Definition: pageres.h:265
WERD_RES * word() const
Definition: pageres.h:755
WERD_RES * forward()
Definition: pageres.h:735
int16_t width() const
Definition: rect.h:115
PDBLK pdblk
Page Description Block.
Definition: ocrblock.h:191
bool display_flag(uint8_t flag) const
Definition: werd.h:120
#define BL_HEIGHT
Definition: pgedit.cpp:43
bool is_fixed_pitch() const
Definition: fontinfo.h:113
int16_t right() const
Definition: rect.h:79
int16_t bottom() const
Definition: rect.h:65
void turn_on_bit(uint8_t bit_num)
Definition: bits16.h:32
TBOX bounding_box() const
Definition: werd.cpp:148
Definition: bits16.h:25
void plot(ScrollView *window, ScrollView::Color colour)
Definition: werd.cpp:283
int editor_image_text_color
Definition: pgedit.cpp:129
WERD_CHOICE * best_choice
Definition: pageres.h:234
#define ASSERT_HOST(x)
Definition: errcode.h:88
int16_t left() const
Definition: rect.h:72
int editor_image_blob_bb_color
Definition: pgedit.cpp:127
TWERD * chopped_word
Definition: pageres.h:214
void Line(int x1, int y1, int x2, int y2)
Definition: scrollview.cpp:532
Bounding box.
Definition: werd.h:46
bool is_serif() const
Definition: fontinfo.h:114
void plot(ScrollView *window, int32_t serial, ScrollView::Color colour)
Definition: pdblock.cpp:180
int editor_word_xpos
Definition: pgedit.cpp:139
int y_size
Definition: scrollview.h:69
void AddMessage(const char *format,...)
Definition: scrollview.cpp:561
const char * text() const
Definition: werd.h:114
tesseract::ScriptPos BlobPosition(int index) const
Definition: ratngs.h:322
#define DESC_HEIGHT
Definition: pgedit.cpp:44
int editor_dbwin_width
Definition: pgedit.cpp:136
int size() const
Definition: genericvector.h:70
SVEventType type
Definition: scrollview.h:64
ROW * row
Definition: pageres.h:142
char * editor_word_name
Definition: pgedit.cpp:138
char * editor_dbwin_name
Definition: pgedit.cpp:132
float x_height
Definition: pageres.h:310
bool is_bold() const
Definition: fontinfo.h:112
BLOCK_RES_LIST block_res_list
Definition: pageres.h:80
WERD * word
Definition: pageres.h:188
DENORM denorm
Definition: pageres.h:203
BL normalisd polyapx.
Definition: werd.h:50
static const char * IncorrectReasonName(IncorrectResultReason irr)
Definition: blamer.cpp:61
void print(FILE *fp)
Definition: ocrrow.cpp:166
void DeleteCurrentWord()
Definition: pageres.cpp:1487
void RenderIntFeature(ScrollView *window, const INT_FEATURE_STRUCT *Feature, ScrollView::Color color)
Definition: intproto.cpp:1602
BlamerBundle * blamer_bundle
Definition: pageres.h:245
C_BLOB_LIST * cblob_list()
Definition: werd.h:95