mirror of
https://github.com/tesseract-ocr/tesseract.git
synced 2024-11-24 19:19:05 +08:00
fdd4ffe85e
git-svn-id: https://tesseract-ocr.googlecode.com/svn/trunk@649 d0cd1f9f-072b-0410-8dd7-cf729c803f20
275 lines
6.7 KiB
C++
275 lines
6.7 KiB
C++
/* -*-C-*-
|
|
********************************************************************************
|
|
*
|
|
* File: states.c (Formerly states.c)
|
|
* Description: Representations of search states
|
|
* Author: Mark Seaman, OCR Technology
|
|
* Created: Wed May 16 15:49:34 1990
|
|
* Modified: Mon Jun 17 17:54:41 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 "states.h"
|
|
#include "structures.h"
|
|
#include "callcpp.h"
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Variables
|
|
--------------------------------------------------------------------------*/
|
|
makestructure(newstate, free_state, STATE);
|
|
|
|
/*----------------------------------------------------------------------
|
|
F u n c t i o n s
|
|
----------------------------------------------------------------------*/
|
|
/**
|
|
* @name bin_to_chunks
|
|
*
|
|
* Convert a representation of the search state in "STATE" form to one
|
|
* in "SEARCH_STATE" form. Create the memory required to hold the
|
|
* resultant state value.
|
|
*
|
|
* @param state The state to convert
|
|
*/
|
|
SEARCH_STATE bin_to_chunks(STATE *state, int num_joints) {
|
|
int x;
|
|
unsigned int mask;
|
|
int depth;
|
|
int pieces = 0;
|
|
SEARCH_STATE s;
|
|
|
|
s = memalloc (sizeof (int) * (ones_in_state (state, num_joints) + 1));
|
|
|
|
depth = 1;
|
|
mask = 1 << (num_joints - 1 - 32);
|
|
for (x = num_joints; x > 32; x--) {
|
|
if (state->part1 & mask) {
|
|
s[depth++] = pieces;
|
|
pieces = 0;
|
|
}
|
|
else {
|
|
pieces++;
|
|
}
|
|
mask >>= 1;
|
|
}
|
|
|
|
if (num_joints > 32)
|
|
mask = 1 << 31;
|
|
else
|
|
mask = 1 << (num_joints - 1);
|
|
|
|
while (x--) {
|
|
if (state->part2 & mask) {
|
|
s[depth++] = pieces;
|
|
pieces = 0;
|
|
}
|
|
else {
|
|
pieces++;
|
|
}
|
|
mask >>= 1;
|
|
}
|
|
s[0] = depth - 1;
|
|
|
|
return (s);
|
|
}
|
|
|
|
|
|
/**
|
|
* bin_to_pieces
|
|
*
|
|
* Convert the binary (bit vector) format of a search state to an array
|
|
* of piece counts. This array has a zero element after the last valid
|
|
* character.
|
|
*/
|
|
void bin_to_pieces(STATE *state, int num_joints, PIECES_STATE pieces) {
|
|
int x;
|
|
unsigned int mask; /* Bit mask */
|
|
inT16 num_pieces = 0;
|
|
/* Preset mask */
|
|
mask = ((num_joints > 32) ?
|
|
(1 << (num_joints - 1 - 32)) : (1 << (num_joints - 1)));
|
|
|
|
pieces[num_pieces] = 0;
|
|
|
|
for (x = num_joints - 1; x >= 0; x--) {
|
|
/* Iterate all bits */
|
|
pieces[num_pieces]++;
|
|
|
|
if ((x < 32) ? /* Test for 1 bit */
|
|
((state->part2 & mask) ? TRUE : FALSE) :
|
|
((state->part1 & mask) ? TRUE : FALSE)) {
|
|
pieces[++num_pieces] = 0;
|
|
}
|
|
/* Next mask value */
|
|
mask = ((mask == 1) ? (1 << 31) : (mask >> 1));
|
|
}
|
|
pieces[num_pieces]++;
|
|
pieces[++num_pieces] = 0;
|
|
ASSERT_HOST (num_pieces < MAX_NUM_CHUNKS + 2);
|
|
}
|
|
|
|
|
|
/**
|
|
* insert_new_chunk
|
|
*
|
|
* Add a new chunk division into this state vector at the location
|
|
* requested.
|
|
*/
|
|
void insert_new_chunk(register STATE *state,
|
|
register int index,
|
|
register int num_joints) {
|
|
register unsigned int mask;
|
|
register unsigned int result;
|
|
|
|
index = (num_joints - index);
|
|
if (index < 32) {
|
|
mask = ~0;
|
|
mask <<= index;
|
|
result = (mask & state->part2) << 1;
|
|
result |= (~mask & state->part2);
|
|
state->part1 <<= 1;
|
|
if (state->part2 & 0x80000000)
|
|
state->part1 |= 1;
|
|
state->part2 = result;
|
|
}
|
|
else {
|
|
mask = ~0;
|
|
mask <<= index - 32;
|
|
result = (mask & state->part1) << 1;
|
|
result |= (~mask & state->part1);
|
|
state->part1 = result;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* new_state
|
|
*
|
|
* Create a memory space for a new state variable. Set its initial
|
|
* value according to the parameters.
|
|
*/
|
|
STATE *new_state(STATE *oldstate) {
|
|
STATE *this_state;
|
|
|
|
this_state = newstate ();
|
|
this_state->part1 = oldstate->part1;
|
|
this_state->part2 = oldstate->part2;
|
|
return (this_state);
|
|
}
|
|
|
|
|
|
/**
|
|
* ones_in_state
|
|
*
|
|
* Return the number of ones that are in this state.
|
|
*/
|
|
int ones_in_state(STATE *state, int num_joints) {
|
|
inT8 num_ones = 0;
|
|
inT8 x;
|
|
unsigned int mask;
|
|
|
|
if (num_joints > 32) /* Preset mask */
|
|
mask = 1 << (num_joints - 1 - 32);
|
|
else
|
|
mask = 1 << (num_joints - 1);
|
|
|
|
for (x = num_joints - 1; x >= 0; x--) {
|
|
/* Iterate all bits */
|
|
|
|
if (x < 32)
|
|
num_ones += ((state->part2 & mask) ? 1 : 0);
|
|
else
|
|
num_ones += ((state->part1 & mask) ? 1 : 0);
|
|
|
|
if (mask == 1) /* Next mask value */
|
|
mask = 1 << 31;
|
|
else
|
|
mask >>= 1;
|
|
}
|
|
|
|
return (num_ones);
|
|
}
|
|
|
|
|
|
/**
|
|
* print_state
|
|
*
|
|
* Print out the current state variable on a line with a label.
|
|
*/
|
|
void print_state(const char *label, STATE *state, int num_joints) {
|
|
int x;
|
|
unsigned int mask; /* Bit mask */
|
|
|
|
if (num_joints > 32) /* Preset mask */
|
|
mask = 1 << (num_joints - 1 - 32);
|
|
else
|
|
mask = 1 << (num_joints - 1);
|
|
|
|
cprintf ("%s ", label);
|
|
|
|
for (x = num_joints - 1; x >= 0; x--) {
|
|
/* Iterate all bits */
|
|
|
|
if (x < 32)
|
|
cprintf ("%d", ((state->part2 & mask) ? 1 : 0));
|
|
else
|
|
cprintf ("%d", ((state->part1 & mask) ? 1 : 0));
|
|
if (x % 4 == 0)
|
|
cprintf (" ");
|
|
|
|
if (mask == 1) /* Next mask value */
|
|
mask = 1 << 31;
|
|
else
|
|
mask >>= 1;
|
|
}
|
|
|
|
new_line();
|
|
}
|
|
|
|
// Prints out the number of fragments in each segment in a state to
|
|
// toappend.
|
|
void print_state(STATE *state, int num_joints, STRING *toappend) {
|
|
PIECES_STATE pieces;
|
|
bin_to_pieces(state, num_joints, pieces);
|
|
for (int i = 0; pieces[i] > 0; i++) {
|
|
if (i > 0) {
|
|
toappend->add_str_int(" ", pieces[i]);
|
|
} else {
|
|
toappend->add_str_int("", pieces[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* set_n_ones
|
|
*
|
|
* Set the first n bits in a state.
|
|
*/
|
|
void set_n_ones(STATE *state, int n) {
|
|
if (n < 32) {
|
|
state->part2 = ~0;
|
|
state->part2 >>= 32 - n;
|
|
state->part1 = 0;
|
|
}
|
|
else {
|
|
state->part2 = ~0;
|
|
state->part1 = ~0;
|
|
state->part1 >>= 64 - n;
|
|
}
|
|
}
|