Tesseract 3.02

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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 * Created: Thu Oct 10 16:25:24 BST 1991
6 *
7 *(C) Copyright 1991, Hewlett-Packard Ltd.
8 ** Licensed under the Apache License, Version 2.0(the "License");
9 ** you may not use this file except in compliance with the License.
10 ** You may obtain a copy of the License at
11 ** http:// www.apache.org/licenses/LICENSE-2.0
12 ** Unless required by applicable law or agreed to in writing, software
13 ** distributed under the License is distributed on an "AS IS" BASIS,
14 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 ** See the License for the specific language governing permissions and
16 ** limitations under the License.
17 *
18 **********************************************************************/
19
20 #ifdef _MSC_VER
21 #pragma warning(disable:4244) // Conversion warnings
22 #endif
23
24 // Include automatically generated configuration file if running autoconf.
25 #ifdef HAVE_CONFIG_H
26 #include "config_auto.h"
27 #endif
28
29 #include "pgedit.h"
30
31 #include <ctype.h>
32 #include <math.h>
33
34 #include "blread.h"
35 #include "control.h"
36 #include "svshowim.h"
37 #include "paramsd.h"
38 #include "pageres.h"
39 #include "tordmain.h"
40 #include "scrollview.h"
41 #include "svmnode.h"
42 #include "statistc.h"
43 #include "tesseractclass.h"
44
45 #ifndef GRAPHICS_DISABLED
46 #define ASC_HEIGHT (2 * kBlnBaselineOffset + kBlnXHeight)
47 #define X_HEIGHT (kBlnBaselineOffset + kBlnXHeight)
48 #define BL_HEIGHT kBlnBaselineOffset
49 #define DESC_HEIGHT 0
50 #define MAXSPACING 128 /*max expected spacing in pix */
51
52 const ERRCODE EMPTYBLOCKLIST = "No blocks to edit";
53
54 enum CMD_EVENTS
55 {
56 NULL_CMD_EVENT,
57 CHANGE_DISP_CMD_EVENT,
58 DUMP_WERD_CMD_EVENT,
59 SHOW_POINT_CMD_EVENT,
60 SHOW_BLN_WERD_CMD_EVENT,
61 DEBUG_WERD_CMD_EVENT,
62 BLAMER_CMD_EVENT,
63 BOUNDING_BOX_CMD_EVENT,
64 CORRECT_TEXT_CMD_EVENT,
65 POLYGONAL_CMD_EVENT,
66 BL_NORM_CMD_EVENT,
67 BITMAP_CMD_EVENT,
68 IMAGE_CMD_EVENT,
69 BLOCKS_CMD_EVENT,
70 BASELINES_CMD_EVENT,
71 UNIFORM_DISP_CMD_EVENT,
72 REFRESH_CMD_EVENT,
73 QUIT_CMD_EVENT,
74 RECOG_WERDS,
75 RECOG_PSEUDO,
76 SHOW_SUBSCRIPT_CMD_EVENT,
77 SHOW_SUPERSCRIPT_CMD_EVENT,
78 SHOW_ITALIC_CMD_EVENT,
79 SHOW_BOLD_CMD_EVENT,
80 SHOW_UNDERLINE_CMD_EVENT,
81 SHOW_FIXEDPITCH_CMD_EVENT,
82 SHOW_SERIF_CMD_EVENT,
83 SHOW_SMALLCAPS_CMD_EVENT,
84 SHOW_DROPCAPS_CMD_EVENT,
85 };
86
87 enum ColorationMode {
88 CM_RAINBOW,
89 CM_SUBSCRIPT,
90 CM_SUPERSCRIPT,
91 CM_ITALIC,
92 CM_BOLD,
93 CM_UNDERLINE,
94 CM_FIXEDPITCH,
95 CM_SERIF,
96 CM_SMALLCAPS,
97 CM_DROPCAPS
98 };
99
100 /*
101 *
102 * Some global data
103 *
104 */
105
106 ScrollView* image_win;
107 ParamsEditor* pe;
108 bool stillRunning = false;
109
110 #ifdef __UNIX__
111 FILE *debug_window = NULL; // opened on demand
112 #endif
113 ScrollView* bln_word_window = NULL; // baseline norm words
114
115 CMD_EVENTS mode = CHANGE_DISP_CMD_EVENT; // selected words op
116
117 bool recog_done = false; // recog_all_words was called
118
119 // These variables should remain global, since they are only used for the
120 // debug mode (in which only a single Tesseract thread/instance will be exist).
121 BITS16 word_display_mode;
122 static ColorationMode color_mode = CM_RAINBOW;
123 BOOL8 display_image = FALSE;
124 BOOL8 display_blocks = FALSE;
125 BOOL8 display_baselines = FALSE;
126
127 PAGE_RES *current_page_res = NULL;
128
129 STRING_VAR(editor_image_win_name, "EditorImage",
130 "Editor image window name");
131 INT_VAR(editor_image_xpos, 590, "Editor image X Pos");
132 INT_VAR(editor_image_ypos, 10, "Editor image Y Pos");
133 INT_VAR(editor_image_menuheight, 50, "Add to image height for menu bar");
134 INT_VAR(editor_image_word_bb_color, ScrollView::BLUE,
135 "Word bounding box colour");
136 INT_VAR(editor_image_blob_bb_color, ScrollView::YELLOW,
137 "Blob bounding box colour");
138 INT_VAR(editor_image_text_color, ScrollView::WHITE,
139 "Correct text colour");
140
141 STRING_VAR(editor_dbwin_name, "EditorDBWin",
142 "Editor debug window name");
143 INT_VAR(editor_dbwin_xpos, 50, "Editor debug window X Pos");
144 INT_VAR(editor_dbwin_ypos, 500, "Editor debug window Y Pos");
145 INT_VAR(editor_dbwin_height, 24, "Editor debug window height");
146 INT_VAR(editor_dbwin_width, 80, "Editor debug window width");
147
148 STRING_VAR(editor_word_name, "BlnWords", "BL normalized word window");
149 INT_VAR(editor_word_xpos, 60, "Word window X Pos");
150 INT_VAR(editor_word_ypos, 510, "Word window Y Pos");
151 INT_VAR(editor_word_height, 240, "Word window height");
152 INT_VAR(editor_word_width, 655, "Word window width");
153
154 STRING_VAR(editor_debug_config_file, "", "Config file to apply to single words");
155
156 class BlnEventHandler : public SVEventHandler {
157 public:
158 void Notify(const SVEvent* sv_event) {
159 if (sv_event->type == SVET_DESTROY)
160 bln_word_window = NULL;
161 else if (sv_event->type == SVET_CLICK)
162 show_point(current_page_res, sv_event->x, sv_event->y);
163 }
164 };
165
171 ScrollView* bln_word_window_handle() { // return handle
172 // not opened yet
173 if (bln_word_window == NULL) {
174 pgeditor_msg("Creating BLN word window...");
175 bln_word_window = new ScrollView(editor_word_name.string(),
176 editor_word_xpos, editor_word_ypos, editor_word_width,
177 editor_word_height, 4000, 4000, true);
178 BlnEventHandler* a = new BlnEventHandler();
179 bln_word_window->AddEventHandler(a);
180 pgeditor_msg("Creating BLN word window...Done");
181 }
182 return bln_word_window;
183 }
184
192 void build_image_window(int width, int height) {
193 if (image_win != NULL) { delete image_win; }
194 image_win = new ScrollView(editor_image_win_name.string(),
195 editor_image_xpos, editor_image_ypos,
196 width + 1,
197 height + editor_image_menuheight + 1,
198 width,
199 height,
200 true);
201 }
202
209 void display_bln_lines(ScrollView* window,
210 ScrollView::Color colour,
211 float scale_factor,
212 float y_offset,
213 float minx,
214 float maxx) {
215 window->Pen(colour);
216 window->Line(minx, y_offset + scale_factor * DESC_HEIGHT,
217 maxx, y_offset + scale_factor * DESC_HEIGHT);
218 window->Line(minx, y_offset + scale_factor * BL_HEIGHT,
219 maxx, y_offset + scale_factor * BL_HEIGHT);
220 window->Line(minx, y_offset + scale_factor * X_HEIGHT,
221 maxx, y_offset + scale_factor * X_HEIGHT);
222 window->Line(minx, y_offset + scale_factor * ASC_HEIGHT,
223 maxx, y_offset + scale_factor * ASC_HEIGHT);
224 }
225
234 void PGEventHandler::Notify(const SVEvent* event) {
235 char myval = '0';
236 if (event->type == SVET_POPUP) {
237 pe->Notify(event);
238 } // These are handled by ParamsEditor
239 else if (event->type == SVET_EXIT) { stillRunning = false; }
240 else if (event->type == SVET_MENU) {
241 if (strcmp(event->parameter, "true") == 0) { myval = 'T'; }
242 else if (strcmp(event->parameter, "false") == 0) { myval = 'F'; }
243 tess_->process_cmd_win_event(event->command_id, &myval);
244 }
245 else {
246 tess_->process_image_event(*event);
247 }
248 }
249
255 namespace tesseract {
256 SVMenuNode *Tesseract::build_menu_new() {
257 SVMenuNode* parent_menu;
258 SVMenuNode* root_menu_item = new SVMenuNode();
259
260 SVMenuNode* modes_menu_item = root_menu_item->AddChild("MODES");
261
262 modes_menu_item->AddChild("Change Display", CHANGE_DISP_CMD_EVENT);
263 modes_menu_item->AddChild("Dump Word", DUMP_WERD_CMD_EVENT);
264 modes_menu_item->AddChild("Show Point", SHOW_POINT_CMD_EVENT);
265 modes_menu_item->AddChild("Show BL Norm Word", SHOW_BLN_WERD_CMD_EVENT);
266 modes_menu_item->AddChild("Config Words", DEBUG_WERD_CMD_EVENT);
267 modes_menu_item->AddChild("Recog Words", RECOG_WERDS);
268 modes_menu_item->AddChild("Recog Blobs", RECOG_PSEUDO);
269
270 parent_menu = root_menu_item->AddChild("DISPLAY");
271
272 parent_menu->AddChild("Blamer", BLAMER_CMD_EVENT, FALSE);
273 parent_menu->AddChild("Bounding Boxes", BOUNDING_BOX_CMD_EVENT, FALSE);
274 parent_menu->AddChild("Correct Text", CORRECT_TEXT_CMD_EVENT, FALSE);
275 parent_menu->AddChild("Polygonal Approx", POLYGONAL_CMD_EVENT, FALSE);
276 parent_menu->AddChild("Baseline Normalized", BL_NORM_CMD_EVENT, FALSE);
277 parent_menu->AddChild("Edge Steps", BITMAP_CMD_EVENT, TRUE);
278 parent_menu->AddChild("Subscripts", SHOW_SUBSCRIPT_CMD_EVENT);
279 parent_menu->AddChild("Superscripts", SHOW_SUPERSCRIPT_CMD_EVENT);
280 parent_menu->AddChild("Italics", SHOW_ITALIC_CMD_EVENT);
281 parent_menu->AddChild("Bold", SHOW_BOLD_CMD_EVENT);
282 parent_menu->AddChild("Underline", SHOW_UNDERLINE_CMD_EVENT);
283 parent_menu->AddChild("FixedPitch", SHOW_FIXEDPITCH_CMD_EVENT);
284 parent_menu->AddChild("Serifs", SHOW_SERIF_CMD_EVENT);
285 parent_menu->AddChild("SmallCaps", SHOW_SMALLCAPS_CMD_EVENT);
286 parent_menu->AddChild("DropCaps", SHOW_DROPCAPS_CMD_EVENT);
287
288
289 parent_menu = root_menu_item->AddChild("OTHER");
290
291 parent_menu->AddChild("Quit", QUIT_CMD_EVENT);
292 parent_menu->AddChild("Show Image", IMAGE_CMD_EVENT, FALSE);
293 parent_menu->AddChild("ShowBlock Outlines", BLOCKS_CMD_EVENT, FALSE);
294 parent_menu->AddChild("Show Baselines", BASELINES_CMD_EVENT, FALSE);
295 parent_menu->AddChild("Uniform Display", UNIFORM_DISP_CMD_EVENT);
296 parent_menu->AddChild("Refresh Display", REFRESH_CMD_EVENT);
297
298 return root_menu_item;
299 }
300
306 void Tesseract::do_re_display(
307 BOOL8 (tesseract::Tesseract::*word_painter)(BLOCK* block,
308 ROW* row,
309 WERD_RES* word_res)) {
310 PAGE_RES_IT pr_it(current_page_res);
311 int block_count = 1;
312
313 image_win->Clear();
314 if (display_image != 0) {
315 image_win->Image(pix_binary_, 0, 0);
316 }
317
318 for (WERD_RES* word = pr_it.word(); word != NULL; word = pr_it.forward()) {
319 (this->*word_painter)(pr_it.block()->block, pr_it.row()->row, word);
320 if (display_baselines && pr_it.row() != pr_it.prev_row())
321 pr_it.row()->row->plot_baseline(image_win, ScrollView::GREEN);
322 if (display_blocks && pr_it.block() != pr_it.prev_block())
323 pr_it.block()->block->plot(image_win, block_count++, ScrollView::RED);
324 }
325 image_win->Update();
326 }
327
336 void Tesseract::pgeditor_main(int width, int height, PAGE_RES *page_res) {
337 current_page_res = page_res;
338 if (current_page_res->block_res_list.empty())
339 return;
340
341 recog_done = false;
342 stillRunning = true;
343
344 build_image_window(width, height);
345 word_display_mode.turn_on_bit(DF_EDGE_STEP);
346 do_re_display(&tesseract::Tesseract::word_set_display);
347 #ifndef GRAPHICS_DISABLED
348 pe = new ParamsEditor(this, image_win);
349 #endif
350 PGEventHandler pgEventHandler(this);
351
352 image_win->AddEventHandler(&pgEventHandler);
353 image_win->AddMessageBox();
354
355 SVMenuNode* svMenuRoot = build_menu_new();
356
357 svMenuRoot->BuildMenu(image_win);
358 image_win->SetVisible(true);
359
360 image_win->AwaitEvent(SVET_DESTROY);
361 image_win->AddEventHandler(NULL);
362 }
363 } // namespace tesseract
364
365
372 void pgeditor_msg( // message display
373 const char *msg) {
374 image_win->AddMessage(msg);
375 }
376
383 void pgeditor_show_point( // display coords
384 SVEvent *event) {
385 image_win->AddMessage("Pointing at(%d, %d)", event->x, event->y);
386 }
387
395 namespace tesseract {
396 BOOL8 Tesseract::process_cmd_win_event( // UI command semantics
397 inT32 cmd_event, // which menu item?
398 char *new_value // any prompt data
399 ) {
400 char msg[160];
401 BOOL8 exit = FALSE;
402
403 color_mode = CM_RAINBOW;
404
405 // Run recognition on the full page if needed.
406 switch (cmd_event) {
407 case BLAMER_CMD_EVENT:
408 case SHOW_SUBSCRIPT_CMD_EVENT:
409 case SHOW_SUPERSCRIPT_CMD_EVENT:
410 case SHOW_ITALIC_CMD_EVENT:
411 case SHOW_BOLD_CMD_EVENT:
412 case SHOW_UNDERLINE_CMD_EVENT:
413 case SHOW_FIXEDPITCH_CMD_EVENT:
414 case SHOW_SERIF_CMD_EVENT:
415 case SHOW_SMALLCAPS_CMD_EVENT:
416 case SHOW_DROPCAPS_CMD_EVENT:
417 if (!recog_done) {
418 recog_all_words(current_page_res, NULL, NULL, NULL, 0);
419 recog_done = true;
420 }
421 break;
422 default:
423 break;
424 }
425
426 switch (cmd_event) {
427 case NULL_CMD_EVENT:
428 break;
429
430 case CHANGE_DISP_CMD_EVENT:
431 case DUMP_WERD_CMD_EVENT:
432 case SHOW_POINT_CMD_EVENT:
433 case SHOW_BLN_WERD_CMD_EVENT:
434 case RECOG_WERDS:
435 case RECOG_PSEUDO:
436 mode =(CMD_EVENTS) cmd_event;
437 break;
438 case DEBUG_WERD_CMD_EVENT:
439 mode = DEBUG_WERD_CMD_EVENT;
440 word_config_ = image_win->ShowInputDialog("Config File Name");
441 break;
442 case BOUNDING_BOX_CMD_EVENT:
443 if (new_value[0] == 'T')
444 word_display_mode.turn_on_bit(DF_BOX);
445 else
446 word_display_mode.turn_off_bit(DF_BOX);
447 mode = CHANGE_DISP_CMD_EVENT;
448 break;
449 case BLAMER_CMD_EVENT:
450 if (new_value[0] == 'T')
451 word_display_mode.turn_on_bit(DF_BLAMER);
452 else
453 word_display_mode.turn_off_bit(DF_BLAMER);
454 do_re_display(&tesseract::Tesseract::word_display);
455 mode = CHANGE_DISP_CMD_EVENT;
456 break;
457 case CORRECT_TEXT_CMD_EVENT:
458 if (new_value[0] == 'T')
459 word_display_mode.turn_on_bit(DF_TEXT);
460 else
461 word_display_mode.turn_off_bit(DF_TEXT);
462 mode = CHANGE_DISP_CMD_EVENT;
463 break;
464 case POLYGONAL_CMD_EVENT:
465 if (new_value[0] == 'T')
466 word_display_mode.turn_on_bit(DF_POLYGONAL);
467 else
468 word_display_mode.turn_off_bit(DF_POLYGONAL);
469 mode = CHANGE_DISP_CMD_EVENT;
470 break;
471 case BL_NORM_CMD_EVENT:
472 if (new_value[0] == 'T')
473 word_display_mode.turn_on_bit(DF_BN_POLYGONAL);
474 else
475 word_display_mode.turn_off_bit(DF_BN_POLYGONAL);
476 mode = CHANGE_DISP_CMD_EVENT;
477 break;
478 case BITMAP_CMD_EVENT:
479 if (new_value[0] == 'T')
480 word_display_mode.turn_on_bit(DF_EDGE_STEP);
481 else
482 word_display_mode.turn_off_bit(DF_EDGE_STEP);
483 mode = CHANGE_DISP_CMD_EVENT;
484 break;
485 case UNIFORM_DISP_CMD_EVENT:
486 do_re_display(&tesseract::Tesseract::word_set_display);
487 break;
488 case IMAGE_CMD_EVENT:
489 display_image =(new_value[0] == 'T');
490 do_re_display(&tesseract::Tesseract::word_display);
491 break;
492 case BLOCKS_CMD_EVENT:
493 display_blocks =(new_value[0] == 'T');
494 do_re_display(&tesseract::Tesseract::word_display);
495 break;
496 case BASELINES_CMD_EVENT:
497 display_baselines =(new_value[0] == 'T');
498 do_re_display(&tesseract::Tesseract::word_display);
499 break;
500 case SHOW_SUBSCRIPT_CMD_EVENT:
501 color_mode = CM_SUBSCRIPT;
502 do_re_display(&tesseract::Tesseract::word_display);
503 break;
504 case SHOW_SUPERSCRIPT_CMD_EVENT:
505 color_mode = CM_SUPERSCRIPT;
506 do_re_display(&tesseract::Tesseract::word_display);
507 break;
508 case SHOW_ITALIC_CMD_EVENT:
509 color_mode = CM_ITALIC;
510 do_re_display(&tesseract::Tesseract::word_display);
511 break;
512 case SHOW_BOLD_CMD_EVENT:
513 color_mode = CM_BOLD;
514 do_re_display(&tesseract::Tesseract::word_display);
515 break;
516 case SHOW_UNDERLINE_CMD_EVENT:
517 color_mode = CM_UNDERLINE;
518 do_re_display(&tesseract::Tesseract::word_display);
519 break;
520 case SHOW_FIXEDPITCH_CMD_EVENT:
521 color_mode = CM_FIXEDPITCH;
522 do_re_display(&tesseract::Tesseract::word_display);
523 break;
524 case SHOW_SERIF_CMD_EVENT:
525 color_mode = CM_SERIF;
526 do_re_display(&tesseract::Tesseract::word_display);
527 break;
528 case SHOW_SMALLCAPS_CMD_EVENT:
529 color_mode = CM_SMALLCAPS;
530 do_re_display(&tesseract::Tesseract::word_display);
531 break;
532 case SHOW_DROPCAPS_CMD_EVENT:
533 color_mode = CM_DROPCAPS;
534 do_re_display(&tesseract::Tesseract::word_display);
535 break;
536 case REFRESH_CMD_EVENT:
537 do_re_display(&tesseract::Tesseract::word_display);
538 break;
539 case QUIT_CMD_EVENT:
540 exit = TRUE;
541 ScrollView::Exit();
542 break;
543
544 default:
545 sprintf(msg, "Unrecognised event " INT32FORMAT "(%s)",
546 cmd_event, new_value);
547 image_win->AddMessage(msg);
548 break;
549 }
550 return exit;
551 }
552
553
563 void Tesseract::process_image_event( // action in image win
564 const SVEvent &event) {
565 // The following variable should remain static, since it is used by
566 // debug editor, which uses a single Tesseract instance.
567 static ICOORD down;
568 ICOORD up;
569 TBOX selection_box;
570 char msg[80];
571
572 switch(event.type) {
573
574 case SVET_SELECTION:
575 if (event.type == SVET_SELECTION) {
576 down.set_x(event.x + event.x_size);
577 down.set_y(event.y + event.y_size);
578 if (mode == SHOW_POINT_CMD_EVENT)
579 show_point(current_page_res, event.x, event.y);
580 }
581
582 up.set_x(event.x);
583 up.set_y(event.y);
584
585 selection_box = TBOX(down, up);
586
587 switch(mode) {
588 case CHANGE_DISP_CMD_EVENT:
589 process_selected_words(
590 current_page_res,
591 selection_box,
592 &tesseract::Tesseract::word_blank_and_set_display);
593 break;
594 case DUMP_WERD_CMD_EVENT:
595 process_selected_words(current_page_res,
596 selection_box,
597 &tesseract::Tesseract::word_dumper);
598 break;
599 case SHOW_BLN_WERD_CMD_EVENT:
600 process_selected_words(current_page_res,
601 selection_box,
602 &tesseract::Tesseract::word_bln_display);
603 break;
604 case DEBUG_WERD_CMD_EVENT:
605 debug_word(current_page_res, selection_box);
606 break;
607 case SHOW_POINT_CMD_EVENT:
608 break; // ignore up event
609
610 case RECOG_WERDS:
611 image_win->AddMessage("Recogging selected words");
612 this->process_selected_words(current_page_res,
613 selection_box,
614 &Tesseract::recog_interactive);
615 break;
616 case RECOG_PSEUDO:
617 image_win->AddMessage("Recogging selected blobs");
618 recog_pseudo_word(current_page_res, selection_box);
619 break;
620
621 default:
622 sprintf(msg, "Mode %d not yet implemented", mode);
623 image_win->AddMessage(msg);
624 break;
625 }
626 default:
627 break;
628 }
629 }
630
636 void Tesseract::debug_word(PAGE_RES* page_res, const TBOX &selection_box) {
637 ResetAdaptiveClassifier();
638 recog_all_words(page_res, NULL, &selection_box, word_config_.string(), 0);
639 }
640 } // namespace tesseract
641
642
650 void show_point(PAGE_RES* page_res, float x, float y) {
651 FCOORD pt(x, y);
652 PAGE_RES_IT pr_it(page_res);
653
654 char msg[160];
655 char *msg_ptr = msg;
656
657 msg_ptr += sprintf(msg_ptr, "Pt:(%0.3f, %0.3f) ", x, y);
658
659 for (WERD_RES* word = pr_it.word(); word != NULL; word = pr_it.forward()) {
660 if (pr_it.row() != pr_it.prev_row() &&
661 pr_it.row()->row->bounding_box().contains(pt)) {
662 msg_ptr += sprintf(msg_ptr, "BL(x)=%0.3f ",
663 pr_it.row()->row->base_line(x));
664 }
665 if (word->word->bounding_box().contains(pt)) {
666 TBOX box = word->word->bounding_box();
667 msg_ptr += sprintf(msg_ptr, "Wd(%d, %d)/(%d, %d) ",
668 box.left(), box.bottom(),
669 box.right(), box.top());
670 C_BLOB_IT cblob_it(word->word->cblob_list());
671 for (cblob_it.mark_cycle_pt();
672 !cblob_it.cycled_list();
673 cblob_it.forward()) {
674 C_BLOB* cblob = cblob_it.data();
675 box = cblob->bounding_box();
676 if (box.contains(pt)) {
677 msg_ptr += sprintf(msg_ptr,
678 "CBlb(%d, %d)/(%d, %d) ",
679 box.left(), box.bottom(),
680 box.right(), box.top());
681 }
682 }
683 }
684 }
685 image_win->AddMessage(msg);
686 }
687
688
689 /**********************************************************************
690 * WERD PROCESSOR FUNCTIONS
691 * ========================
692 *
693 * These routines are invoked by one or more of:
694 * process_all_words()
695 * process_selected_words()
696 * or
697 * process_all_words_it()
698 * process_selected_words_it()
699 * for each word to be processed
700 **********************************************************************/
701
708 #endif // GRAPHICS_DISABLED
709 namespace tesseract {
710 #ifndef GRAPHICS_DISABLED
711 BOOL8 Tesseract:: word_blank_and_set_display(BLOCK* block, ROW* row,
712 WERD_RES* word_res) {
713 word_res->word->bounding_box().plot(image_win, ScrollView::BLACK,
714 ScrollView::BLACK);
715 return word_set_display(block, row, word_res);
716 }
717
718
724 BOOL8 Tesseract::word_bln_display(BLOCK* block, ROW* row, WERD_RES* word_res) {
725 TWERD *bln_word = word_res->chopped_word;
726 if (bln_word == NULL) {
727 word_res->SetupForTessRecognition(unicharset, this, BestPix(), false,
728 this->textord_use_cjk_fp_model,
729 row, block);
730 bln_word = word_res->chopped_word;
731 }
732 bln_word_window_handle()->Clear();
733 display_bln_lines(bln_word_window_handle(), ScrollView::CYAN,
734 1.0, 0.0f, -1000.0f, 1000.0f);
735 bln_word->plot(bln_word_window_handle());
736 bln_word_window_handle()->Update();
737 return TRUE;
738 }
739
740
741
747 BOOL8 Tesseract::word_display(BLOCK* block, ROW* row, WERD_RES* word_res) {
748 WERD* word = word_res->word;
749 TBOX word_bb; // word bounding box
750 int word_height; // ht of word BB
751 BOOL8 displayed_something = FALSE;
752 float shift; // from bot left
753 C_BLOB_IT c_it; // cblob iterator
754
755 if (color_mode != CM_RAINBOW && word_res->box_word != NULL) {
756 BoxWord* box_word = word_res->box_word;
757 int length = box_word->length();
758 if (word_res->fontinfo == NULL) return false;
759 const FontInfo& font_info = *word_res->fontinfo;
760 for (int i = 0; i < length; ++i) {
761 ScrollView::Color color = ScrollView::GREEN;
762 switch (color_mode) {
763 case CM_SUBSCRIPT:
764 if (box_word->BlobPosition(i) == SP_SUBSCRIPT)
765 color = ScrollView::RED;
766 break;
767 case CM_SUPERSCRIPT:
768 if (box_word->BlobPosition(i) == SP_SUPERSCRIPT)
769 color = ScrollView::RED;
770 break;
771 case CM_ITALIC:
772 if (font_info.is_italic())
773 color = ScrollView::RED;
774 break;
775 case CM_BOLD:
776 if (font_info.is_bold())
777 color = ScrollView::RED;
778 break;
779 case CM_FIXEDPITCH:
780 if (font_info.is_fixed_pitch())
781 color = ScrollView::RED;
782 break;
783 case CM_SERIF:
784 if (font_info.is_serif())
785 color = ScrollView::RED;
786 break;
787 case CM_SMALLCAPS:
788 if (word_res->small_caps)
789 color = ScrollView::RED;
790 break;
791 case CM_DROPCAPS:
792 if (box_word->BlobPosition(i) == SP_DROPCAP)
793 color = ScrollView::RED;
794 break;
795 // TODO(rays) underline is currently completely unsupported.
796 case CM_UNDERLINE:
797 default:
798 break;
799 }
800 image_win->Pen(color);
801 TBOX box = box_word->BlobBox(i);
802 image_win->Rectangle(box.left(), box.bottom(), box.right(), box.top());
803 }
804 return true;
805 }
806 /*
807 Note the double coercions of(COLOUR)((inT32)editor_image_word_bb_color)
808 etc. are to keep the compiler happy.
809 */
810 // display bounding box
811 if (word->display_flag(DF_BOX)) {
812 word->bounding_box().plot(image_win,
813 (ScrollView::Color)((inT32)
814 editor_image_word_bb_color),
815 (ScrollView::Color)((inT32)
816 editor_image_word_bb_color));
817
818 ScrollView::Color c = (ScrollView::Color)
819 ((inT32) editor_image_blob_bb_color);
820 image_win->Pen(c);
821 c_it.set_to_list(word->cblob_list());
822 for (c_it.mark_cycle_pt(); !c_it.cycled_list(); c_it.forward())
823 c_it.data()->bounding_box().plot(image_win);
824 displayed_something = TRUE;
825 }
826
827 // display edge steps
828 if (word->display_flag(DF_EDGE_STEP)) { // edgesteps available
829 word->plot(image_win); // rainbow colors
830 displayed_something = TRUE;
831 }
832
833 // display poly approx
834 if (word->display_flag(DF_POLYGONAL)) {
835 // need to convert
836 TWERD* tword = TWERD::PolygonalCopy(word);
837 tword->plot(image_win);
838 delete tword;
839 displayed_something = TRUE;
840 }
841
842 // Display correct text and blamer information.
843 STRING text;
844 STRING blame;
845 if (word->display_flag(DF_TEXT) && word->text() != NULL) {
846 text = word->text();
847 }
848 if (word->display_flag(DF_BLAMER) &&
849 !(word_res->blamer_bundle != NULL &&
850 word_res->blamer_bundle->incorrect_result_reason == IRR_CORRECT)) {
851 text = "";
852 const BlamerBundle *blamer_bundle = word_res->blamer_bundle;
853 if (blamer_bundle == NULL) {
854 text += "NULL";
855 } else {
856 for (int i = 0; i < blamer_bundle->truth_text.length(); ++i) {
857 text += blamer_bundle->truth_text[i];
858 }
859 }
860 text += " -> ";
861 STRING best_choice_str;
862 if (word_res->best_choice == NULL) {
863 best_choice_str = "NULL";
864 } else {
865 word_res->best_choice->string_and_lengths(&best_choice_str, NULL);
866 }
867 text += best_choice_str;
868 IncorrectResultReason reason = (blamer_bundle == NULL) ?
869 IRR_PAGE_LAYOUT : blamer_bundle->incorrect_result_reason;
870 ASSERT_HOST(reason < IRR_NUM_REASONS)
871 blame += " [";
872 blame += BlamerBundle::IncorrectReasonName(reason);
873 blame += "]";
874 }
875 if (text.length() > 0) {
876 word_bb = word->bounding_box();
877 image_win->Pen(ScrollView::RED);
878 word_height = word_bb.height();
879 int text_height = 0.50 * word_height;
880 if (text_height > 20) text_height = 20;
881 image_win->TextAttributes("Arial", text_height, false, false, false);
882 shift = (word_height < word_bb.width()) ? 0.25 * word_height : 0.0f;
883 image_win->Text(word_bb.left() + shift,
884 word_bb.bottom() + 0.25 * word_height, text.string());
885 if (blame.length() > 0) {
886 image_win->Text(word_bb.left() + shift,
887 word_bb.bottom() + 0.25 * word_height - text_height,
888 blame.string());
889 }
890
891 displayed_something = TRUE;
892 }
893
894 if (!displayed_something) // display BBox anyway
895 word->bounding_box().plot(image_win,
896 (ScrollView::Color)((inT32) editor_image_word_bb_color),
897 (ScrollView::Color)((inT32)
898 editor_image_word_bb_color));
899 return TRUE;
900 }
901 #endif // GRAPHICS_DISABLED
902
908 BOOL8 Tesseract::word_dumper(BLOCK* block, ROW* row, WERD_RES* word_res) {
909 if (block != NULL) {
910 tprintf("\nBlock data...\n");
911 block->print(NULL, FALSE);
912 }
913 tprintf("\nRow data...\n");
914 row->print(NULL);
915 tprintf("\nWord data...\n");
916 word_res->word->print();
917 if (word_res->blamer_bundle != NULL && wordrec_debug_blamer &&
918 word_res->blamer_bundle->incorrect_result_reason != IRR_CORRECT) {
919 tprintf("Current blamer debug: %s\n",
920 word_res->blamer_bundle->debug.string());
921 }
922 return TRUE;
923 }
924
925 #ifndef GRAPHICS_DISABLED
926
931 BOOL8 Tesseract::word_set_display(BLOCK* block, ROW* row, WERD_RES* word_res) {
932 WERD* word = word_res->word;
933 word->set_display_flag(DF_BOX, word_display_mode.bit(DF_BOX));
934 word->set_display_flag(DF_TEXT, word_display_mode.bit(DF_TEXT));
935 word->set_display_flag(DF_POLYGONAL, word_display_mode.bit(DF_POLYGONAL));
936 word->set_display_flag(DF_EDGE_STEP, word_display_mode.bit(DF_EDGE_STEP));
937 word->set_display_flag(DF_BN_POLYGONAL,
938 word_display_mode.bit(DF_BN_POLYGONAL));
939 word->set_display_flag(DF_BLAMER, word_display_mode.bit(DF_BLAMER));
940 return word_display(block, row, word_res);
941 }
942 #endif // GRAPHICS_DISABLED
943
944 } // namespace tesseract
945
946
947