2007-03-08 04:03:40 +08:00
|
|
|
/* -*-C-*-
|
|
|
|
********************************************************************************
|
|
|
|
*
|
|
|
|
* File: makechop.c (Formerly makechop.c)
|
|
|
|
* Description:
|
|
|
|
* Author: Mark Seaman, OCR Technology
|
|
|
|
* Created: Fri Oct 16 14:37:00 1987
|
|
|
|
* Modified: Mon Jul 29 15:50:42 1991 (Mark Seaman) marks@hpgrlt
|
|
|
|
* Language: C
|
|
|
|
* Package: N/A
|
|
|
|
* Status: Reusable Software Component
|
|
|
|
*
|
|
|
|
* (c) Copyright 1987, Hewlett-Packard Company.
|
|
|
|
** Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
** you may not use this file except in compliance with the License.
|
|
|
|
** You may obtain a copy of the License at
|
|
|
|
** http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
** Unless required by applicable law or agreed to in writing, software
|
|
|
|
** distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
** See the License for the specific language governing permissions and
|
|
|
|
** limitations under the License.
|
|
|
|
*
|
|
|
|
*********************************************************************************/
|
|
|
|
/*----------------------------------------------------------------------
|
|
|
|
I n c l u d e s
|
|
|
|
----------------------------------------------------------------------*/
|
2010-05-28 20:03:45 +08:00
|
|
|
|
|
|
|
// Include automatically generated configuration file if running autoconf.
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config_auto.h"
|
|
|
|
#endif
|
|
|
|
|
2007-03-08 04:03:40 +08:00
|
|
|
#include "makechop.h"
|
|
|
|
#include "render.h"
|
|
|
|
#include "structures.h"
|
|
|
|
#ifdef __UNIX__
|
|
|
|
#include <assert.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------------
|
|
|
|
Public Function Code
|
|
|
|
----------------------------------------------------------------------*/
|
|
|
|
/**********************************************************************
|
|
|
|
* apply_seam
|
|
|
|
*
|
|
|
|
* Split this blob into two blobs by applying the splits included in
|
|
|
|
* the seam description.
|
|
|
|
**********************************************************************/
|
2007-07-18 08:55:02 +08:00
|
|
|
void apply_seam(TBLOB *blob, TBLOB *other_blob, SEAM *seam) {
|
|
|
|
check_outline_mem();
|
2007-03-08 04:03:40 +08:00
|
|
|
if (seam->split1 == NULL) {
|
|
|
|
divide_blobs (blob, other_blob, seam->location);
|
|
|
|
}
|
|
|
|
else if (seam->split2 == NULL) {
|
2007-07-18 08:55:02 +08:00
|
|
|
make_split_blobs(blob, other_blob, seam);
|
2007-03-08 04:03:40 +08:00
|
|
|
}
|
|
|
|
else if (seam->split3 == NULL) {
|
2007-07-18 08:55:02 +08:00
|
|
|
make_double_split(blob, other_blob, seam);
|
2007-03-08 04:03:40 +08:00
|
|
|
}
|
|
|
|
else {
|
2007-07-18 08:55:02 +08:00
|
|
|
make_triple_split(blob, other_blob, seam);
|
2007-03-08 04:03:40 +08:00
|
|
|
}
|
|
|
|
|
2007-07-18 08:55:02 +08:00
|
|
|
check_outline_mem();
|
2007-03-08 04:03:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
* divide_blobs
|
|
|
|
*
|
|
|
|
* Create two blobs by grouping the outlines in the appropriate blob.
|
|
|
|
* The outlines that are beyond the location point are moved to the
|
|
|
|
* other blob. The ones whose x location is less than that point are
|
|
|
|
* retained in the original blob.
|
|
|
|
**********************************************************************/
|
2008-04-22 08:35:16 +08:00
|
|
|
void divide_blobs(TBLOB *blob, TBLOB *other_blob, inT32 location) {
|
2007-03-08 04:03:40 +08:00
|
|
|
TESSLINE *outline;
|
|
|
|
TESSLINE *outline1 = NULL;
|
|
|
|
TESSLINE *outline2 = NULL;
|
|
|
|
|
|
|
|
outline = blob->outlines;
|
|
|
|
blob->outlines = NULL;
|
|
|
|
|
|
|
|
while (outline != NULL) {
|
|
|
|
if ((outline->topleft.x + outline->botright.x) / 2 < location) {
|
|
|
|
/* Outline is in 1st blob */
|
|
|
|
if (outline1) {
|
|
|
|
outline1->next = outline;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
blob->outlines = outline;
|
|
|
|
}
|
|
|
|
outline1 = outline;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* Outline is in 2nd blob */
|
|
|
|
if (outline2) {
|
|
|
|
outline2->next = outline;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
other_blob->outlines = outline;
|
|
|
|
}
|
|
|
|
outline2 = outline;
|
|
|
|
}
|
|
|
|
|
|
|
|
outline = outline->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (outline1)
|
|
|
|
outline1->next = NULL;
|
|
|
|
if (outline2)
|
|
|
|
outline2->next = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
* form_two_blobs
|
|
|
|
*
|
|
|
|
* Group the outlines from the first blob into both of them. Do so
|
|
|
|
* according to the information about the split.
|
|
|
|
**********************************************************************/
|
2008-04-22 08:35:16 +08:00
|
|
|
void form_two_blobs(TBLOB *blob, TBLOB *other_blob, inT32 location) {
|
2007-07-18 08:55:02 +08:00
|
|
|
setup_blob_outlines(blob);
|
2007-03-08 04:03:40 +08:00
|
|
|
|
2007-07-18 08:55:02 +08:00
|
|
|
divide_blobs(blob, other_blob, location);
|
2007-03-08 04:03:40 +08:00
|
|
|
|
2007-07-18 08:55:02 +08:00
|
|
|
eliminate_duplicate_outlines(blob);
|
|
|
|
eliminate_duplicate_outlines(other_blob);
|
2007-03-08 04:03:40 +08:00
|
|
|
|
2007-07-18 08:55:02 +08:00
|
|
|
correct_blob_order(blob, other_blob);
|
2007-03-08 04:03:40 +08:00
|
|
|
|
|
|
|
#ifndef GRAPHICS_DISABLED
|
2007-07-18 08:55:02 +08:00
|
|
|
if (chop_debug > 2) {
|
|
|
|
display_blob(blob, Red);
|
2007-03-08 04:03:40 +08:00
|
|
|
#ifdef __UNIX__
|
|
|
|
sleep (1);
|
|
|
|
#endif
|
2007-07-18 08:55:02 +08:00
|
|
|
display_blob(other_blob, Cyan);
|
2007-03-08 04:03:40 +08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
* make_double_split
|
|
|
|
*
|
|
|
|
* Create two blobs out of one by splitting the original one in half.
|
|
|
|
* Return the resultant blobs for classification.
|
|
|
|
**********************************************************************/
|
2007-07-18 08:55:02 +08:00
|
|
|
void make_double_split(TBLOB *blob, TBLOB *other_blob, SEAM *seam) {
|
2007-03-08 04:03:40 +08:00
|
|
|
make_single_split (blob->outlines, seam->split1);
|
|
|
|
make_single_split (blob->outlines, seam->split2);
|
|
|
|
form_two_blobs (blob, other_blob, seam->location);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
* make_single_split
|
|
|
|
*
|
|
|
|
* Create two outlines out of one by splitting the original one in half.
|
|
|
|
* Return the resultant outlines.
|
|
|
|
**********************************************************************/
|
2007-07-18 08:55:02 +08:00
|
|
|
void make_single_split(TESSLINE *outlines, SPLIT *split) {
|
2007-03-08 04:03:40 +08:00
|
|
|
assert (outlines != NULL);
|
|
|
|
|
|
|
|
split_outline (split->point1, split->point2);
|
|
|
|
|
|
|
|
while (outlines->next != NULL)
|
|
|
|
outlines = outlines->next;
|
|
|
|
|
|
|
|
outlines->next = newoutline ();
|
|
|
|
outlines->next->loop = split->point1;
|
|
|
|
outlines->next->child = NULL;
|
|
|
|
setup_outline (outlines->next);
|
|
|
|
|
|
|
|
outlines = outlines->next;
|
|
|
|
|
|
|
|
outlines->next = newoutline ();
|
|
|
|
outlines->next->loop = split->point2;
|
|
|
|
outlines->next->child = NULL;
|
|
|
|
setup_outline (outlines->next);
|
|
|
|
|
|
|
|
outlines->next->next = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
* make_split_blobs
|
|
|
|
*
|
|
|
|
* Create two blobs out of one by splitting the original one in half.
|
|
|
|
* Return the resultant blobs for classification.
|
|
|
|
**********************************************************************/
|
2007-07-18 08:55:02 +08:00
|
|
|
void make_split_blobs(TBLOB *blob, TBLOB *other_blob, SEAM *seam) {
|
2007-03-08 04:03:40 +08:00
|
|
|
make_single_split (blob->outlines, seam->split1);
|
|
|
|
|
|
|
|
form_two_blobs (blob, other_blob, seam->location);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
* make_triple_split
|
|
|
|
*
|
|
|
|
* Create two blobs out of one by splitting the original one in half.
|
|
|
|
* This splitting is accomplished by applying three separate splits on
|
|
|
|
* the outlines. Three of the starting outlines will produce two ending
|
|
|
|
* outlines. Return the resultant blobs for classification.
|
|
|
|
**********************************************************************/
|
2007-07-18 08:55:02 +08:00
|
|
|
void make_triple_split(TBLOB *blob, TBLOB *other_blob, SEAM *seam) {
|
2007-03-08 04:03:40 +08:00
|
|
|
make_single_split (blob->outlines, seam->split1);
|
|
|
|
make_single_split (blob->outlines, seam->split2);
|
|
|
|
make_single_split (blob->outlines, seam->split3);
|
|
|
|
|
|
|
|
form_two_blobs (blob, other_blob, seam->location);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
* undo_seam
|
|
|
|
*
|
|
|
|
* Remove the seam between these two blobs. Produce one blob as a
|
|
|
|
* result. The seam may consist of one, two, or three splits. Each
|
|
|
|
* of these split must be removed from the outlines.
|
|
|
|
**********************************************************************/
|
2007-07-18 08:55:02 +08:00
|
|
|
void undo_seam(TBLOB *blob, TBLOB *other_blob, SEAM *seam) {
|
2007-03-08 04:03:40 +08:00
|
|
|
TESSLINE *outline;
|
|
|
|
|
|
|
|
if (!seam)
|
|
|
|
return; /* Append other blob outlines */
|
|
|
|
if (blob->outlines == NULL) {
|
|
|
|
blob->outlines = other_blob->outlines;
|
|
|
|
other_blob->outlines = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
outline = blob->outlines;
|
|
|
|
while (outline->next)
|
|
|
|
outline = outline->next;
|
|
|
|
outline->next = other_blob->outlines;
|
2007-07-18 08:55:02 +08:00
|
|
|
oldblob(other_blob);
|
2007-03-08 04:03:40 +08:00
|
|
|
|
|
|
|
if (seam->split1 == NULL) {
|
|
|
|
}
|
|
|
|
else if (seam->split2 == NULL) {
|
|
|
|
undo_single_split (blob, seam->split1);
|
|
|
|
}
|
|
|
|
else if (seam->split3 == NULL) {
|
|
|
|
undo_single_split (blob, seam->split1);
|
|
|
|
undo_single_split (blob, seam->split2);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
undo_single_split (blob, seam->split3);
|
|
|
|
undo_single_split (blob, seam->split2);
|
|
|
|
undo_single_split (blob, seam->split1);
|
|
|
|
}
|
|
|
|
|
2007-07-18 08:55:02 +08:00
|
|
|
setup_blob_outlines(blob);
|
|
|
|
eliminate_duplicate_outlines(blob);
|
2007-03-08 04:03:40 +08:00
|
|
|
|
2007-07-18 08:55:02 +08:00
|
|
|
check_outline_mem();
|
2007-03-08 04:03:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
* undo_single_split
|
|
|
|
*
|
|
|
|
* Undo a seam that is made by a single split. Perform the correct
|
|
|
|
* magic to reconstruct the appropriate set of outline data structures.
|
|
|
|
**********************************************************************/
|
2007-07-18 08:55:02 +08:00
|
|
|
void undo_single_split(TBLOB *blob, SPLIT *split) {
|
2007-03-08 04:03:40 +08:00
|
|
|
TESSLINE *outline1;
|
|
|
|
TESSLINE *outline2;
|
|
|
|
/* Modify edge points */
|
|
|
|
unsplit_outlines (split->point1, split->point2);
|
|
|
|
|
|
|
|
outline1 = newoutline ();
|
|
|
|
outline1->next = blob->outlines;
|
|
|
|
blob->outlines = outline1;
|
|
|
|
outline1->loop = split->point1;
|
|
|
|
outline1->child = NULL;
|
|
|
|
|
|
|
|
outline2 = newoutline ();
|
|
|
|
outline2->next = blob->outlines;
|
|
|
|
blob->outlines = outline2;
|
|
|
|
outline2->loop = split->point2;
|
|
|
|
outline2->child = NULL;
|
|
|
|
}
|