mirror of
https://github.com/tesseract-ocr/tesseract.git
synced 2024-12-24 15:47:48 +08:00
192 lines
6.1 KiB
C++
192 lines
6.1 KiB
C++
|
/* -*-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 "freelist.h"
|
||
|
#include "callcpp.h"
|
||
|
#include "blobs.h"
|
||
|
|
||
|
/*----------------------------------------------------------------------
|
||
|
T y p e s
|
||
|
----------------------------------------------------------------------*/
|
||
|
typedef struct _MATCH_
|
||
|
{
|
||
|
int topleft;
|
||
|
int botright;
|
||
|
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)
|
||
|
destroy_nodes (match_table[x].rating, free_choice);
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
/* Allocate memory once */
|
||
|
been_initialized = 1;
|
||
|
match_table = (MATCH *) memalloc (sizeof (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();
|
||
|
memfree(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, CHOICES 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;
|
||
|
match_table[x].rating = copy_choices (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.
|
||
|
**********************************************************************/
|
||
|
CHOICES 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.
|
||
|
**********************************************************************/
|
||
|
CHOICES 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) {
|
||
|
return (copy_choices (match_table[x].rating));
|
||
|
}
|
||
|
if (++x >= NUM_MATCH_ENTRIES)
|
||
|
x = 0;
|
||
|
}
|
||
|
while (x != start);
|
||
|
|
||
|
return (NIL);
|
||
|
}
|