C++程序  |  270行  |  9.48 KB

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