blob: 61eecb4509ab747dcd66d8ae317ad94cdc833083 [file] [log] [blame]
/* -*-C-*-
********************************************************************************
*
* File: matchtab.c (Formerly matchtab.c)
* Description: Match table to retain blobs that were matched.
* Author: Mark Seaman, OCR Technology
* Created: Mon Jan 29 09:00:56 1990
* Modified: Tue Mar 19 15:09:06 1991 (Mark Seaman) marks@hpgrlt
* Language: C
* Package: N/A
* Status: Experimental (Do Not Distribute)
*
* (c) Copyright 1990, 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
----------------------------------------------------------------------*/
#include "matchtab.h"
#include "blobs.h"
#include "callcpp.h"
#include "elst.h"
#include "freelist.h"
#include "ratngs.h"
/*----------------------------------------------------------------------
T y p e s
----------------------------------------------------------------------*/
typedef struct _MATCH_
{
int topleft;
int botright;
BLOB_CHOICE_LIST *rating;
} MATCH;
/*----------------------------------------------------------------------
V a r i a b l e s
----------------------------------------------------------------------*/
MATCH *match_table;
//?int missed_count = 0;
/*----------------------------------------------------------------------
M a c r o s
----------------------------------------------------------------------*/
#define NUM_MATCH_ENTRIES 500 /* Entries in match_table */
/**********************************************************************
* blank_entry
*
* Test an element in the blob match table to see if it is blank.
* Return a non-zero value if it is blank.
**********************************************************************/
#define blank_entry(match_table,x) \
(! (match_table[x].topleft | match_table[x].botright))
/*----------------------------------------------------------------------
Public Function Code
----------------------------------------------------------------------*/
/**********************************************************************
* init_match_table
*
* Create and clear a match table to be used to speed up the splitter.
**********************************************************************/
static int been_initialized = 0;
void init_match_table() {
int x;
if (been_initialized) {
/* Reclaim old choices */
for (x = 0; x < NUM_MATCH_ENTRIES; x++) {
if ((!blank_entry (match_table, x)) && match_table[x].rating)
match_table[x].rating->clear();
delete match_table[x].rating;
}
}
else {
/* Allocate memory once */
been_initialized = 1;
match_table = new MATCH[NUM_MATCH_ENTRIES];
}
/* Initialize the table */
for (x = 0; x < NUM_MATCH_ENTRIES; x++) {
match_table[x].topleft = 0;
match_table[x].botright = 0;
match_table[x].rating = NULL;
}
}
void end_match_table() {
if (been_initialized) {
init_match_table();
delete[] match_table;
match_table = NULL;
been_initialized = 0;
}
}
/**********************************************************************
* put_match
*
* Put a new blob and its corresponding match ratings into the match
* table.
**********************************************************************/
void put_match(TBLOB *blob, BLOB_CHOICE_LIST *ratings) {
unsigned int topleft;
unsigned int botright;
unsigned int start;
TPOINT tp_topleft;
TPOINT tp_botright;
int x;
/* Hash into table */
blob_bounding_box(blob, &tp_topleft, &tp_botright);
topleft = *(unsigned int *) &tp_topleft;
botright = *(unsigned int *) &tp_botright;
start = (topleft * botright) % NUM_MATCH_ENTRIES;
/* Look for empty */
x = start;
do {
if (blank_entry (match_table, x)) {
/* Add this entry */
match_table[x].topleft = topleft;
match_table[x].botright = botright;
// Copy ratings to match_table[x].rating
match_table[x].rating = new BLOB_CHOICE_LIST();
match_table[x].rating->deep_copy(ratings);
return;
}
if (++x >= NUM_MATCH_ENTRIES)
x = 0;
}
while (x != start);
cprintf ("error: Match table is full\n");
}
/**********************************************************************
* get_match
*
* Look up this blob in the match table to see if it needs to be
* matched. If it is not present then NULL is returned.
**********************************************************************/
BLOB_CHOICE_LIST *get_match(TBLOB *blob) {
unsigned int topleft;
unsigned int botright;
TPOINT tp_topleft;
TPOINT tp_botright;
/* Do starting hash */
blob_bounding_box(blob, &tp_topleft, &tp_botright);
topleft = *(unsigned int *) &tp_topleft;
botright = *(unsigned int *) &tp_botright;
return (get_match_by_bounds (topleft, botright));
}
/**********************************************************************
* get_match_by_bounds
*
* Look up this blob in the match table to see if it needs to be
* matched. If it is not present then NULL is returned.
**********************************************************************/
BLOB_CHOICE_LIST *get_match_by_bounds(unsigned int topleft,
unsigned int botright) {
unsigned int start;
int x;
/* Do starting hash */
start = (topleft * botright) % NUM_MATCH_ENTRIES;
/* Search for match */
x = start;
do {
/* Not found when blank */
if (blank_entry (match_table, x))
break;
/* Is this the match ? */
if (match_table[x].topleft == topleft &&
match_table[x].botright == botright) {
BLOB_CHOICE_LIST *blist = new BLOB_CHOICE_LIST();
blist->deep_copy(match_table[x].rating);
return blist;
}
if (++x >= NUM_MATCH_ENTRIES)
x = 0;
}
while (x != start);
return NULL;
}