00001
00020 #include "mfcpch.h"
00021 #include "charcut.h"
00022 #include "imgs.h"
00023 #include "showim.h"
00024 #include "evnts.h"
00025 #include "notdll.h"
00026
00027 #define LARGEST(a,b) ( (a) > (b) ? (a) : (b) )
00028 #define SMALLEST(a,b) ( (a) > (b) ? (b) : (a) )
00029 #define BUG_OFFSET 1
00030
00031 #define EXTERN
00032
00035 EXTERN INT_VAR (pix_word_margin, 3, "How far outside word BB to grow");
00036
00037 extern IMAGE page_image;
00040 ELISTIZE (PIXROW)
00049 PIXROW::PIXROW(INT16 pos, INT16 count, PBLOB *blob) {
00050 OUTLINE_LIST *outline_list;
00051 OUTLINE_IT outline_it;
00052 POLYPT_LIST *pts_list;
00053 POLYPT_IT pts_it;
00054 INT16 i;
00055 FCOORD pt;
00056 FCOORD vec;
00057 float y_coord;
00058 INT16 x_coord;
00059
00060 row_offset = pos;
00061 row_count = count;
00062 min = (INT16 *) alloc_mem (count * sizeof (INT16));
00063 max = (INT16 *) alloc_mem (count * sizeof (INT16));
00064 outline_list = blob->out_list ();
00065 outline_it.set_to_list (outline_list);
00066
00067 for (i = 0; i < count; i++) {
00068 min[i] = MAX_INT16 - 1;
00069 max[i] = -MAX_INT16 + 1;
00070 y_coord = row_offset + i + 0.5;
00071 for (outline_it.mark_cycle_pt ();
00072 !outline_it.cycled_list (); outline_it.forward ()) {
00073 pts_list = outline_it.data ()->polypts ();
00074 pts_it.set_to_list (pts_list);
00075 for (pts_it.mark_cycle_pt ();
00076 !pts_it.cycled_list (); pts_it.forward ()) {
00077 pt = pts_it.data ()->pos;
00078 vec = pts_it.data ()->vec;
00079 if ((vec.y () != 0) &&
00080 (((pt.y () <= y_coord) && (pt.y () + vec.y () >= y_coord))
00081 || ((pt.y () >= y_coord)
00082 && (pt.y () + vec.y () <= y_coord)))) {
00083
00084 x_coord = (INT16) floor ((y_coord -
00085 pt.y ()) * vec.x () / vec.y () +
00086 pt.x () + 0.5);
00087 if (x_coord < min[i])
00088 min[i] = x_coord;
00089 x_coord--;
00090 if (x_coord > max[i])
00091 max[i] = x_coord;
00092 }
00093 }
00094 }
00095 }
00096 }
00097
00098
00105 #ifndef GRAPHICS_DISABLED
00106 void PIXROW::plot(WINDOW fd
00107 ) const {
00108 INT16 i;
00109 INT16 y_coord;
00110
00111 for (i = 0; i < row_count; i++) {
00112 y_coord = row_offset + i;
00113 if (min[i] <= max[i]) {
00114 rectangle (fd, min[i], y_coord, max[i] + 1, y_coord + 1);
00115 }
00116 }
00117 }
00118 #endif
00119
00127 bool PIXROW::bad_box(
00128 int xsize,
00129 int ysize) const {
00130 BOX bbox = bounding_box ();
00131 if (bbox.left () < 0 || bbox.right () > xsize
00132 || bbox.top () > ysize || bbox.bottom () < 0) {
00133 tprintf("Box (%d,%d)->(%d,%d) bad compared to %d,%d\n",
00134 bbox.left(),bbox.bottom(), bbox.right(), bbox.top(),
00135 xsize, ysize);
00136 return true;
00137 }
00138 return false;
00139 }
00140
00141
00147 BOX PIXROW::bounding_box() const {
00148 INT16 i;
00149 INT16 y_coord;
00150 INT16 min_x = MAX_INT16 - 1;
00151 INT16 min_y = MAX_INT16 - 1;
00152 INT16 max_x = -MAX_INT16 + 1;
00153 INT16 max_y = -MAX_INT16 + 1;
00154
00155 for (i = 0; i < row_count; i++) {
00156 y_coord = row_offset + i;
00157 if (min[i] <= max[i]) {
00158 if (y_coord < min_y)
00159 min_y = y_coord;
00160 if (y_coord + 1 > max_y)
00161 max_y = y_coord + 1;
00162 if (min[i] < min_x)
00163 min_x = min[i];
00164 if (max[i] + 1 > max_x)
00165 max_x = max[i] + 1;
00166 }
00167 }
00168 if (min_x > max_x || min_y > max_y)
00169 return BOX ();
00170 else
00171 return BOX (ICOORD (min_x, min_y), ICOORD (max_x, max_y));
00172 }
00173
00174
00183 void PIXROW::contract(
00184 IMAGELINE *imlines,
00185 INT16 x_offset,
00186 INT16 foreground_colour
00187 ) {
00188 INT16 i;
00189 UINT8 *line_pixels;
00190
00191 for (i = 0; i < row_count; i++) {
00192 if (min[i] > max[i])
00193 continue;
00194
00195 line_pixels = imlines[i].pixels;
00196 while (line_pixels[min[i] - x_offset] != foreground_colour) {
00197 if (min[i] == max[i]) {
00198 min[i] = MAX_INT16 - 1;
00199 max[i] = -MAX_INT16 + 1;
00200 goto nextline;
00201 }
00202 else
00203 min[i]++;
00204 }
00205 while (line_pixels[max[i] - x_offset] != foreground_colour) {
00206 if (min[i] == max[i]) {
00207 min[i] = MAX_INT16 - 1;
00208 max[i] = -MAX_INT16 + 1;
00209 goto nextline;
00210 }
00211 else
00212 max[i]--;
00213 }
00214 nextline:;
00215
00216 }
00217 }
00218
00219
00230 BOOL8 PIXROW::extend(
00231 IMAGELINE *imlines,
00232 BOX &imbox,
00233 PIXROW *prev,
00234 PIXROW *next,
00235 INT16 foreground_colour) {
00236 INT16 i;
00237 INT16 x_offset = imbox.left ();
00238 INT16 limit;
00239 INT16 left_limit;
00240 INT16 right_limit;
00241 UINT8 *pixels = NULL;
00242 UINT8 *pixels_below = NULL;
00243 UINT8 *pixels_above = NULL;
00244 BOOL8 changed = FALSE;
00245
00246 pixels_above = imlines[0].pixels;
00247 for (i = 0; i < row_count; i++) {
00248 pixels_below = pixels;
00249 pixels = pixels_above;
00250 if (i < (row_count - 1))
00251 pixels_above = imlines[i + 1].pixels;
00252 else
00253 pixels_above = NULL;
00254
00255
00256 if (prev == NULL || prev->max[i] < prev->min[i])
00257 limit = imbox.left ();
00258 else
00259 limit = prev->max[i] + 1;
00260 if ((min[i] <= max[i]) &&
00261 (min[i] > limit) &&
00262 (pixels[min[i] - 1 - x_offset] == foreground_colour)) {
00263 min[i]--;
00264 changed = TRUE;
00265 }
00266
00267
00268 if (next == NULL || next->min[i] > next->max[i])
00269 limit = imbox.right () - 1;
00270 else
00271 limit = next->min[i] - 1;
00272 if ((min[i] <= max[i]) &&
00273 (max[i] < limit) &&
00274 (pixels[max[i] + 1 - x_offset] == foreground_colour)) {
00275 max[i]++;
00276 changed = TRUE;
00277 }
00278
00279
00280 if (pixels_below != NULL) {
00281 if (min[i] < min[i - 1]) {
00282 if (prev == NULL || prev->max[i - 1] < prev->min[i - 1])
00283 left_limit = min[i];
00284 else
00285 left_limit = LARGEST (min[i], prev->max[i - 1] + 1);
00286 }
00287 else
00288 left_limit = min[i - 1];
00289
00290 if (max[i] > max[i - 1]) {
00291 if (next == NULL || next->min[i - 1] > next->max[i - 1])
00292 right_limit = max[i];
00293 else
00294 right_limit = SMALLEST (max[i], next->min[i - 1] - 1);
00295 }
00296 else
00297 right_limit = max[i - 1];
00298
00299 while ((left_limit <= right_limit) &&
00300 (pixels_below[left_limit - x_offset] != foreground_colour))
00301 left_limit++;
00302
00303 if ((left_limit <= right_limit) && (left_limit < min[i - 1])) {
00304 min[i - 1] = left_limit;
00305 changed = TRUE;
00306 }
00307
00308 while ((left_limit <= right_limit) &&
00309 (pixels_below[right_limit - x_offset] != foreground_colour))
00310 right_limit--;
00311
00312 if ((left_limit <= right_limit) && (right_limit > max[i - 1])) {
00313 max[i - 1] = right_limit;
00314 changed = TRUE;
00315 }
00316 }
00317
00318
00319 if (pixels_above != NULL) {
00320 if (min[i] < min[i + 1]) {
00321 if (prev == NULL || prev->min[i + 1] > prev->max[i + 1])
00322 left_limit = min[i];
00323 else
00324 left_limit = LARGEST (min[i], prev->max[i + 1] + 1);
00325 }
00326 else
00327 left_limit = min[i + 1];
00328
00329 if (max[i] > max[i + 1]) {
00330 if (next == NULL || next->min[i + 1] > next->max[i + 1])
00331 right_limit = max[i];
00332 else
00333 right_limit = SMALLEST (max[i], next->min[i + 1] - 1);
00334 }
00335 else
00336 right_limit = max[i + 1];
00337
00338 while ((left_limit <= right_limit) &&
00339 (pixels_above[left_limit - x_offset] != foreground_colour))
00340 left_limit++;
00341
00342 if ((left_limit <= right_limit) && (left_limit < min[i + 1])) {
00343 min[i + 1] = left_limit;
00344 changed = TRUE;
00345 }
00346
00347 while ((left_limit <= right_limit) &&
00348 (pixels_above[right_limit - x_offset] != foreground_colour))
00349 right_limit--;
00350
00351 if ((left_limit <= right_limit) && (right_limit > max[i + 1])) {
00352 max[i + 1] = right_limit;
00353 changed = TRUE;
00354 }
00355 }
00356 }
00357 return changed;
00358 }
00359
00360
00371 void PIXROW::char_clip_image(
00372 IMAGELINE *imlines,
00373 BOX &im_box,
00374 ROW *row,
00375 IMAGE &clip_image,
00376 float &baseline_pos
00377 ) {
00378 INT16 clip_image_xsize;
00379 INT16 clip_image_ysize;
00384 INT16 x_shift;
00390 INT16 y_shift;
00391 BOX char_pix_box;
00392 INT16 y_dest;
00393 INT16 x_min;
00394 INT16 x_max;
00395 INT16 x_min_dest;
00396 INT16 x_max_dest;
00397 INT16 x_width;
00398 INT16 y;
00399
00400 clip_image_xsize = clip_image.get_xsize ();
00401 clip_image_ysize = clip_image.get_ysize ();
00402
00403 char_pix_box = bounding_box ();
00404 y_shift = char_pix_box.bottom () - row_offset -
00405 (INT16) floor ((clip_image_ysize - char_pix_box.height () + 0.5) / 2);
00406
00407 x_shift = char_pix_box.left () -
00408 (INT16) floor ((clip_image_xsize - char_pix_box.width () + 0.5) / 2);
00409
00410 for (y = 0; y < row_count; y++) {
00411
00412
00413
00414
00415 y_dest = y - y_shift;
00416 if ((min[y] <= max[y]) && (y_dest >= 0) && (y_dest < clip_image_ysize)) {
00417 x_min = min[y];
00418 x_min_dest = x_min - x_shift;
00419 if (x_min_dest < 0) {
00420 x_min = x_min - x_min_dest;
00421 x_min_dest = 0;
00422 }
00423 x_max = max[y];
00424 x_max_dest = x_max - x_shift;
00425 if (x_max_dest > clip_image_xsize - 1) {
00426 x_max = x_max - (x_max_dest - (clip_image_xsize - 1));
00427 x_max_dest = clip_image_xsize - 1;
00428 }
00429 x_width = x_max - x_min + 1;
00430 if (x_width > 0) {
00431 x_min -= im_box.left ();
00432
00433 imlines[y].pixels += x_min;
00434 clip_image.put_line (x_min_dest, y_dest, x_width, imlines + y,
00435 0);
00436 imlines[y].init ();
00437 }
00438 }
00439 }
00440
00441
00442
00443
00444
00445
00446 if (row == NULL)
00447 baseline_pos = 0;
00448 else
00449 baseline_pos = row->base_line ((char_pix_box.left () +
00450 char_pix_box.right ()) / 2.0)
00451 - char_pix_box.bottom ()
00452 + ((clip_image_ysize - char_pix_box.height ()) / 2);
00453 }
00454
00455
00468 void char_clip_word(
00469 WERD *word,
00470 IMAGE &bin_image,
00471 PIXROW_LIST *&pixrow_list,
00472 IMAGELINE *&imlines,
00473 BOX &pix_box
00474 ) {
00475 BOX word_box = word->bounding_box ();
00476 PBLOB_LIST *blob_list;
00477 PBLOB_IT blob_it;
00478 PIXROW_IT pixrow_it;
00479 INT16 pix_offset;
00480 INT16 row_height;
00481 INT16 imlines_x_offset;
00482 PIXROW *prev;
00483 PIXROW *next;
00484 PIXROW *current;
00485 BOOL8 changed;
00486 BOOL8 just_changed;
00487 INT16 iteration_count = 0;
00488 INT16 foreground_colour;
00489
00490 if (word->flag (W_INVERSE))
00491 foreground_colour = 1;
00492 else
00493 foreground_colour = 0;
00494
00495
00496 pix_box = word_box;
00497 pix_box.move_bottom_edge (-pix_word_margin);
00498 pix_box.move_top_edge (pix_word_margin);
00499 pix_box.move_left_edge (-pix_word_margin);
00500 pix_box.move_right_edge (pix_word_margin);
00501 pix_box -= BOX (ICOORD (0, 0 + BUG_OFFSET),
00502 ICOORD (bin_image.get_xsize (),
00503 bin_image.get_ysize () - BUG_OFFSET));
00504
00505
00506
00507 pix_offset = pix_box.bottom ();
00508 row_height = pix_box.height ();
00509 blob_list = word->blob_list ();
00510 blob_it.set_to_list (blob_list);
00511
00512 pixrow_list = new PIXROW_LIST;
00513 pixrow_it.set_to_list (pixrow_list);
00514
00515 for (blob_it.mark_cycle_pt (); !blob_it.cycled_list (); blob_it.forward ()) {
00516 PIXROW *row = new PIXROW (pix_offset, row_height, blob_it.data ());
00517 ASSERT_HOST (!row->
00518 bad_box (bin_image.get_xsize (), bin_image.get_ysize ()));
00519 pixrow_it.add_after_then_move (row);
00520 }
00521
00522 imlines = generate_imlines (bin_image, pix_box);
00523
00524
00525
00526 imlines_x_offset = pix_box.left ();
00527
00528 pixrow_it.move_to_first ();
00529 for (pixrow_it.mark_cycle_pt ();
00530 !pixrow_it.cycled_list (); pixrow_it.forward ()) {
00531 ASSERT_HOST (!pixrow_it.data ()->
00532 bad_box (bin_image.get_xsize (), bin_image.get_ysize ()));
00533 pixrow_it.data ()->contract (imlines, imlines_x_offset,
00534 foreground_colour);
00535 ASSERT_HOST (!pixrow_it.data ()->
00536 bad_box (bin_image.get_xsize (), bin_image.get_ysize ()));
00537 }
00538
00539
00540 do {
00541 changed = FALSE;
00542 pixrow_it.move_to_first ();
00543 prev = NULL;
00544 current = NULL;
00545 next = pixrow_it.data ();
00546 for (pixrow_it.mark_cycle_pt ();
00547 !pixrow_it.cycled_list (); pixrow_it.forward ()) {
00548 prev = current;
00549 current = next;
00550 if (pixrow_it.at_last ())
00551 next = NULL;
00552 else
00553 next = pixrow_it.data_relative (1);
00554 just_changed = current->extend (imlines, pix_box, prev, next,
00555 foreground_colour);
00556 ASSERT_HOST (!current->
00557 bad_box (bin_image.get_xsize (),
00558 bin_image.get_ysize ()));
00559 changed = changed || just_changed;
00560 }
00561 iteration_count++;
00562 }
00563 while (changed);
00564 }
00565
00566
00574 IMAGELINE *generate_imlines(
00575 IMAGE &bin_image,
00576 BOX &pix_box) {
00577 IMAGELINE *imlines;
00578 int i;
00579
00580 imlines = new IMAGELINE[pix_box.height ()];
00581 for (i = 0; i < pix_box.height (); i++) {
00582 imlines[i].init (pix_box.width ());
00583
00584 bin_image.fast_get_line (pix_box.left (),
00585 pix_box.bottom () + i + BUG_OFFSET,
00586
00587 pix_box.width (),
00588 imlines + i);
00589 }
00590 return imlines;
00591 }
00592
00593
00603 #ifndef GRAPHICS_DISABLED
00604 WINDOW display_clip_image(WERD *word,
00605 IMAGE &bin_image,
00606 PIXROW_LIST *pixrow_list,
00607 BOX &pix_box
00608 ) {
00609 WINDOW clip_window;
00610 BOX word_box = word->bounding_box ();
00611 int border = word_box.height () / 2;
00612 BOX display_box = word_box;
00613
00614 display_box.move_bottom_edge (-border);
00615 display_box.move_top_edge (border);
00616 display_box.move_left_edge (-border);
00617 display_box.move_right_edge (border);
00618 display_box -= BOX (ICOORD (0, 0 - BUG_OFFSET),
00619 ICOORD (bin_image.get_xsize (),
00620 bin_image.get_ysize () - BUG_OFFSET));
00621
00622 pgeditor_msg ("Creating Clip window...");
00623 clip_window =
00624 create_window ("Clipped Blobs",
00625 SCROLLINGWIN,
00626 editor_word_xpos, editor_word_ypos,
00627 3 * (word_box.width () + 2 * border),
00628 3 * (word_box.height () + 2 * border),
00629
00630
00631 display_box.left (), display_box.right (),
00632 display_box.bottom () - BUG_OFFSET,
00633 display_box.top () - BUG_OFFSET,
00634
00635 TRUE, FALSE, FALSE, TRUE);
00636 pgeditor_msg ("Creating Clip window...Done");
00637
00638 clear_view_surface(clip_window);
00639 show_sub_image (&bin_image,
00640 display_box.left (),
00641 display_box.bottom (),
00642 display_box.width (),
00643 display_box.height (),
00644 clip_window,
00645 display_box.left (), display_box.bottom () - BUG_OFFSET);
00646
00647 word->plot (clip_window, RED);
00648 word_box.plot (clip_window, INT_HOLLOW, TRUE, BLUE, BLUE);
00649 pix_box.plot (clip_window, INT_HOLLOW, TRUE, BLUE, BLUE);
00650 plot_pixrows(pixrow_list, clip_window);
00651 overlap_picture_ops(TRUE);
00652 return clip_window;
00653 }
00654
00655
00660 void display_images(IMAGE &clip_image, IMAGE &scaled_image) {
00661 WINDOW clip_im_window;
00662 WINDOW scale_im_window;
00663 INT16 i;
00664 GRAPHICS_EVENT event;
00665
00666
00667 clip_im_window = create_window ("Clipped Blob", SCROLLINGWIN,
00668 editor_word_xpos - 20, editor_word_ypos - 100,
00669 5 * clip_image.get_xsize (), 5 * clip_image.get_ysize (),
00670 0, clip_image.get_xsize (), 0, clip_image.get_ysize (),
00671 TRUE, FALSE, FALSE, TRUE);
00672
00673 clear_view_surface(clip_im_window);
00674 show_sub_image (&clip_image,
00675 0, 0,
00676 clip_image.get_xsize (), clip_image.get_ysize (),
00677 clip_im_window, 0, 0);
00678
00679 line_color_index(clip_im_window, RED);
00680 for (i = 1; i < clip_image.get_xsize (); i++) {
00681 move2d (clip_im_window, i, 0);
00682 draw2d (clip_im_window, i, clip_image.get_xsize ());
00683 }
00684 for (i = 1; i < clip_image.get_ysize (); i++) {
00685 move2d (clip_im_window, 0, i);
00686 draw2d (clip_im_window, clip_image.get_xsize (), i);
00687 }
00688
00689
00690 scale_im_window = create_window ("Scaled Blob", SCROLLINGWIN,
00691 editor_word_xpos + 300, editor_word_ypos - 100,
00692 5 * scaled_image.get_xsize (), 5 * scaled_image.get_ysize (),
00693 0, scaled_image.get_xsize (), 0, scaled_image.get_ysize (),
00694 TRUE, FALSE, FALSE, TRUE);
00695
00696 clear_view_surface(scale_im_window);
00697 show_sub_image (&scaled_image,
00698 0, 0,
00699 scaled_image.get_xsize (), scaled_image.get_ysize (),
00700 scale_im_window, 0, 0);
00701
00702 line_color_index(scale_im_window, RED);
00703 for (i = 1; i < scaled_image.get_xsize (); i++) {
00704 move2d (scale_im_window, i, 0);
00705 draw2d (scale_im_window, i, scaled_image.get_xsize ());
00706 }
00707 for (i = 1; i < scaled_image.get_ysize (); i++) {
00708 move2d (scale_im_window, 0, i);
00709 draw2d (scale_im_window, scaled_image.get_xsize (), i);
00710 }
00711
00712 overlap_picture_ops(TRUE);
00713 await_event(scale_im_window, TRUE, ANY_EVENT, &event);
00714 destroy_window(clip_im_window);
00715 destroy_window(scale_im_window);
00716 }
00717
00718
00722 void plot_pixrows(
00723 PIXROW_LIST *pixrow_list,
00724 WINDOW win) {
00725 PIXROW_IT pixrow_it(pixrow_list);
00726 INT16 colour = RED;
00727
00728 for (pixrow_it.mark_cycle_pt ();
00729 !pixrow_it.cycled_list (); pixrow_it.forward ()) {
00730 if (colour > RED + 7)
00731 colour = RED;
00732
00733 perimeter_color_index (win, (COLOUR) colour);
00734 interior_style(win, INT_HOLLOW, TRUE);
00735 pixrow_it.data ()->plot (win);
00736 colour++;
00737 }
00738 }
00739 #endif // GRAPHICS_DISABLED