/* -*-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