blob: 5e6a7d6cfd75dfccedb6a31e58fb69d0a7694330 [file] [log] [blame]
/* -*-C-*-
********************************************************************************
*
* File: choices.c (Formerly choices.c)
* Description: Handle the new ratings choices for Wise Owl
* Author: Mark Seaman, OCR Technology
* Created: Fri Sep 22 14:05:51 1989
* Modified: Wed May 22 14:12:34 1991 (Mark Seaman) marks@hpgrlt
* Language: C
* Package: N/A
* Status: Experimental (Do Not Distribute)
*
* (c) Copyright 1989, 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.
*
*********************************************************************************/
#include "choices.h"
#include "emalloc.h"
#include "globals.h"
#include "host.h"
#include "danerror.h"
#include "structures.h"
#include "tordvars.h"
#include "tprintf.h"
#include "unicharset.h"
#include "dict.h"
#include "image.h"
/*----------------------------------------------------------------------
Variables
------------------------------------------------------------------------*/
#define CHOICEBLOCK 100 /* Cells per block */
makestructure (newchoice, oldchoice, printchoice, A_CHOICE,
freechoice, CHOICEBLOCK, "A_CHOICE", choicecount)
/*----------------------------------------------------------------------
F u n c t i o n s
----------------------------------------------------------------------*/
/**********************************************************************
* append_char_choice
*
* Create a new choice record. Store the string value in a safe place.
* Add the new choice record to the list.
*
* NB - This is only used by matchers, so permuter is always NO_PERM
* SPC 16/9/92
**********************************************************************/
CHOICES append_char_choice(CHOICES ratings,
const char *string,
const char *lengths,
float rating,
float certainty,
inT8 config,
int script_id) {
A_CHOICE *this_choice;
this_choice = new_choice (string, lengths, rating, certainty,
config, script_id, NO_PERM, false, NULL);
ratings = push_last (ratings, (LIST) this_choice);
return (ratings);
}
/**********************************************************************
* copy_choices
*
* Copy a list of choices. This means that there will be two copies
* in memory.
**********************************************************************/
CHOICES copy_choices(CHOICES choices) {
CHOICES l;
CHOICES result = NIL;
iterate_list(l, choices) {
A_CHOICE *choice = (A_CHOICE *)(first_node(l));
result = push (result,
(LIST) new_choice (class_string(choice),
class_lengths(choice),
class_rating(choice),
class_certainty(choice),
class_config(choice),
class_script_id(choice),
class_permuter(choice),
class_fragment_mark(choice),
class_fragment_lengths(choice)));
}
return (reverse_d (result));
}
/**********************************************************************
* clone_choice
*
* Copy the contents of the given values to the corresponding values in
* a given choice replacing any previous values it might have had.
**********************************************************************/
void clone_choice(A_CHOICE *choice, const char *string,
const char *lengths, float rating, float certainty,
inT8 permuter, bool fragment_mark,
const char *fragment_lengths) {
if (choice->string) strfree (class_string (choice));
if (choice->lengths) strfree (class_lengths (choice));
if (choice->fragment_lengths) strfree(choice->fragment_lengths);
choice->string = strsave (string);
choice->lengths = strsave (lengths);
choice->rating = rating;
choice->certainty = certainty;
choice->permuter = permuter;
choice->fragment_mark = fragment_mark;
choice->fragment_lengths =
fragment_lengths ? strsave(fragment_lengths) : NULL;
}
/**********************************************************************
* clear_choice
*
* Set the fields in this choice to be defaulted bad initial values.
**********************************************************************/
void clear_choice(A_CHOICE *choice) {
choice->string = NULL;
choice->lengths = NULL;
choice->rating = MAX_FLOAT32;
choice->certainty = -MAX_FLOAT32;
choice->fragment_mark = false;
choice->fragment_lengths = NULL;
}
/**********************************************************************
* free_choice
*
* Free up the memory taken by one choice rating.
**********************************************************************/
void free_choice(void *arg) { //LIST choice)
A_CHOICE *this_choice;
LIST choice = (LIST) arg;
this_choice = (A_CHOICE *) choice;
if (this_choice) {
if (this_choice->string)
strfree (this_choice->string);
if (this_choice->lengths)
strfree (this_choice->lengths);
if (this_choice->fragment_lengths)
strfree (this_choice->fragment_lengths);
oldchoice(this_choice);
}
}
/**********************************************************************
* get_best_free_other
*
* Returns the best of two choices and frees the other (worse) choice.
* A choice is better if it has a non-NULL string and has a lower rating
* than the other choice.
**********************************************************************/
A_CHOICE *get_best_free_other(A_CHOICE *choice_1, A_CHOICE *choice_2) {
if (!choice_1) return choice_2;
if (!choice_2) return choice_1;
if (class_rating (choice_1) < class_rating (choice_2) ||
class_string (choice_2) == NULL) {
free_choice(choice_2);
return choice_1;
} else {
free_choice(choice_1);
return choice_2;
}
}
/**********************************************************************
* new_choice
*
* Create a new choice record. Store the string value in a safe place.
**********************************************************************/
A_CHOICE *new_choice(const char *string,
const char *lengths,
float rating,
float certainty,
inT8 config,
int script_id,
char permuter,
bool fragment_mark,
const char *fragment_lengths) {
A_CHOICE *this_choice;
this_choice = newchoice();
this_choice->string = strsave(string);
this_choice->lengths = strsave(lengths);
this_choice->rating = rating;
this_choice->certainty = certainty;
this_choice->config = config;
this_choice->permuter = permuter;
this_choice->script_id = script_id;
this_choice->fragment_mark = fragment_mark;
this_choice->fragment_lengths =
fragment_lengths ? strsave(fragment_lengths) : NULL;
return (this_choice);
}
A_CHOICE *new_choice(const char *string,
const char *lengths,
float rating,
float certainty,
inT8 config,
char permuter) {
return new_choice(string, lengths, rating, certainty,
config, -1, permuter, false, NULL);
}
/**********************************************************************
* print_choices
*
* Print the rating for a particular blob or word.
**********************************************************************/
namespace tesseract {
void Dict::print_choices(const char *label,
CHOICES choices) { // List of (A_CHOICE*).
tprintf("%s\n", label);
if (choices == NIL)
tprintf(" No rating ");
iterate(choices) {
tprintf("%.2f %.2f", best_rating(choices), best_certainty(choices));
print_word_string(best_string(choices));
}
tprintf("\n");
}
/**********************************************************************
* print_word_choice
*
* Print the string in a human-readable format and ratings for a word.
**********************************************************************/
void Dict::print_word_choice(const char *label, A_CHOICE* choice) {
tprintf("%s : ", label);
if (choice == NULL) {
tprintf("No rating\n");
} else {
tprintf("%.2f %.2f", class_rating(choice), class_certainty(choice));
print_word_string(class_string(choice));
tprintf("\n");
}
}
/**********************************************************************
* print_word_string
*
* Print the string in a human-readable format.
* The output is not newline terminated.
**********************************************************************/
void Dict::print_word_string(const char* str) {
int step = 1;
for (int i = 0; str[i] != '\0'; i += step) {
step = (getUnicharset().get_fragment(str) ?
strlen(str) : getUnicharset().step(str + i));
int unichar_id = getUnicharset().unichar_to_id(str + i, step);
tprintf(" : %s ", getUnicharset().debug_str(unichar_id).string());
}
}
} // namespace tesseract