1 /* -*-C-*-
2 ********************************************************************************
3 *
4 * File: choices.c (Formerly choices.c)
5 * Description: Handle the new ratings choices for Wise Owl
6 * Author: Mark Seaman, OCR Technology
7 * Created: Fri Sep 22 14:05:51 1989
8 * Modified: Wed May 22 14:12:34 1991 (Mark Seaman) marks@hpgrlt
9 * Language: C
10 * Package: N/A
11 * Status: Experimental (Do Not Distribute)
12 *
13 * (c) Copyright 1989, Hewlett-Packard Company.
14 ** Licensed under the Apache License, Version 2.0 (the "License");
15 ** you may not use this file except in compliance with the License.
16 ** You may obtain a copy of the License at
17 ** http://www.apache.org/licenses/LICENSE-2.0
18 ** Unless required by applicable law or agreed to in writing, software
19 ** distributed under the License is distributed on an "AS IS" BASIS,
20 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 ** See the License for the specific language governing permissions and
22 ** limitations under the License.
23 *
24 *********************************************************************************/
25 #include "choices.h"
26 #include "emalloc.h"
27 #include "globals.h"
28 #include "host.h"
29 #include "danerror.h"
30 #include "structures.h"
31 #include "tordvars.h"
32 #include "tprintf.h"
33 #include "unicharset.h"
34 #include "dict.h"
35 #include "image.h"
36
37 /*----------------------------------------------------------------------
38 Variables
39 ------------------------------------------------------------------------*/
40 #define CHOICEBLOCK 100 /* Cells per block */
41
42 makestructure (newchoice, oldchoice, printchoice, A_CHOICE,
43 freechoice, CHOICEBLOCK, "A_CHOICE", choicecount)
44 /*----------------------------------------------------------------------
45 F u n c t i o n s
46 ----------------------------------------------------------------------*/
47 /**********************************************************************
48 * append_char_choice
49 *
50 * Create a new choice record. Store the string value in a safe place.
51 * Add the new choice record to the list.
52 *
53 * NB - This is only used by matchers, so permuter is always NO_PERM
54 * SPC 16/9/92
55 **********************************************************************/
append_char_choice(CHOICES ratings,const char * string,const char * lengths,float rating,float certainty,inT8 config,int script_id)56 CHOICES append_char_choice(CHOICES ratings,
57 const char *string,
58 const char *lengths,
59 float rating,
60 float certainty,
61 inT8 config,
62 int script_id) {
63 A_CHOICE *this_choice;
64
65 this_choice = new_choice (string, lengths, rating, certainty,
66 config, script_id, NO_PERM, false, NULL);
67 ratings = push_last (ratings, (LIST) this_choice);
68 return (ratings);
69 }
70
71 /**********************************************************************
72 * copy_choices
73 *
74 * Copy a list of choices. This means that there will be two copies
75 * in memory.
76 **********************************************************************/
copy_choices(CHOICES choices)77 CHOICES copy_choices(CHOICES choices) {
78 CHOICES l;
79 CHOICES result = NIL;
80
81 iterate_list(l, choices) {
82 A_CHOICE *choice = (A_CHOICE *)(first_node(l));
83 result = push (result,
84 (LIST) new_choice (class_string(choice),
85 class_lengths(choice),
86 class_rating(choice),
87 class_certainty(choice),
88 class_config(choice),
89 class_script_id(choice),
90 class_permuter(choice),
91 class_fragment_mark(choice),
92 class_fragment_lengths(choice)));
93 }
94 return (reverse_d (result));
95 }
96
97 /**********************************************************************
98 * clone_choice
99 *
100 * Copy the contents of the given values to the corresponding values in
101 * a given choice replacing any previous values it might have had.
102 **********************************************************************/
clone_choice(A_CHOICE * choice,const char * string,const char * lengths,float rating,float certainty,inT8 permuter,bool fragment_mark,const char * fragment_lengths)103 void clone_choice(A_CHOICE *choice, const char *string,
104 const char *lengths, float rating, float certainty,
105 inT8 permuter, bool fragment_mark,
106 const char *fragment_lengths) {
107 if (choice->string) strfree (class_string (choice));
108 if (choice->lengths) strfree (class_lengths (choice));
109 if (choice->fragment_lengths) strfree(choice->fragment_lengths);
110
111 choice->string = strsave (string);
112 choice->lengths = strsave (lengths);
113 choice->rating = rating;
114 choice->certainty = certainty;
115 choice->permuter = permuter;
116 choice->fragment_mark = fragment_mark;
117 choice->fragment_lengths =
118 fragment_lengths ? strsave(fragment_lengths) : NULL;
119 }
120
121 /**********************************************************************
122 * clear_choice
123 *
124 * Set the fields in this choice to be defaulted bad initial values.
125 **********************************************************************/
clear_choice(A_CHOICE * choice)126 void clear_choice(A_CHOICE *choice) {
127 choice->string = NULL;
128 choice->lengths = NULL;
129 choice->rating = MAX_FLOAT32;
130 choice->certainty = -MAX_FLOAT32;
131 choice->fragment_mark = false;
132 choice->fragment_lengths = NULL;
133 }
134
135
136 /**********************************************************************
137 * free_choice
138 *
139 * Free up the memory taken by one choice rating.
140 **********************************************************************/
free_choice(void * arg)141 void free_choice(void *arg) { //LIST choice)
142 A_CHOICE *this_choice;
143 LIST choice = (LIST) arg;
144
145 this_choice = (A_CHOICE *) choice;
146 if (this_choice) {
147 if (this_choice->string)
148 strfree (this_choice->string);
149 if (this_choice->lengths)
150 strfree (this_choice->lengths);
151 if (this_choice->fragment_lengths)
152 strfree (this_choice->fragment_lengths);
153 oldchoice(this_choice);
154 }
155 }
156
157 /**********************************************************************
158 * get_best_free_other
159 *
160 * Returns the best of two choices and frees the other (worse) choice.
161 * A choice is better if it has a non-NULL string and has a lower rating
162 * than the other choice.
163 **********************************************************************/
get_best_free_other(A_CHOICE * choice_1,A_CHOICE * choice_2)164 A_CHOICE *get_best_free_other(A_CHOICE *choice_1, A_CHOICE *choice_2) {
165 if (!choice_1) return choice_2;
166 if (!choice_2) return choice_1;
167 if (class_rating (choice_1) < class_rating (choice_2) ||
168 class_string (choice_2) == NULL) {
169 free_choice(choice_2);
170 return choice_1;
171 } else {
172 free_choice(choice_1);
173 return choice_2;
174 }
175 }
176
177 /**********************************************************************
178 * new_choice
179 *
180 * Create a new choice record. Store the string value in a safe place.
181 **********************************************************************/
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)182 A_CHOICE *new_choice(const char *string,
183 const char *lengths,
184 float rating,
185 float certainty,
186 inT8 config,
187 int script_id,
188 char permuter,
189 bool fragment_mark,
190 const char *fragment_lengths) {
191 A_CHOICE *this_choice;
192
193 this_choice = newchoice();
194 this_choice->string = strsave(string);
195 this_choice->lengths = strsave(lengths);
196 this_choice->rating = rating;
197 this_choice->certainty = certainty;
198 this_choice->config = config;
199 this_choice->permuter = permuter;
200 this_choice->script_id = script_id;
201 this_choice->fragment_mark = fragment_mark;
202 this_choice->fragment_lengths =
203 fragment_lengths ? strsave(fragment_lengths) : NULL;
204
205 return (this_choice);
206 }
207
new_choice(const char * string,const char * lengths,float rating,float certainty,inT8 config,char permuter)208 A_CHOICE *new_choice(const char *string,
209 const char *lengths,
210 float rating,
211 float certainty,
212 inT8 config,
213 char permuter) {
214 return new_choice(string, lengths, rating, certainty,
215 config, -1, permuter, false, NULL);
216 }
217
218
219 /**********************************************************************
220 * print_choices
221 *
222 * Print the rating for a particular blob or word.
223 **********************************************************************/
224 namespace tesseract {
print_choices(const char * label,CHOICES choices)225 void Dict::print_choices(const char *label,
226 CHOICES choices) { // List of (A_CHOICE*).
227 tprintf("%s\n", label);
228 if (choices == NIL)
229 tprintf(" No rating ");
230
231 iterate(choices) {
232 tprintf("%.2f %.2f", best_rating(choices), best_certainty(choices));
233 print_word_string(best_string(choices));
234 }
235 tprintf("\n");
236 }
237
238 /**********************************************************************
239 * print_word_choice
240 *
241 * Print the string in a human-readable format and ratings for a word.
242 **********************************************************************/
print_word_choice(const char * label,A_CHOICE * choice)243 void Dict::print_word_choice(const char *label, A_CHOICE* choice) {
244 tprintf("%s : ", label);
245 if (choice == NULL) {
246 tprintf("No rating\n");
247 } else {
248 tprintf("%.2f %.2f", class_rating(choice), class_certainty(choice));
249 print_word_string(class_string(choice));
250 tprintf("\n");
251 }
252 }
253
254 /**********************************************************************
255 * print_word_string
256 *
257 * Print the string in a human-readable format.
258 * The output is not newline terminated.
259 **********************************************************************/
print_word_string(const char * str)260 void Dict::print_word_string(const char* str) {
261 int step = 1;
262 for (int i = 0; str[i] != '\0'; i += step) {
263 step = (getUnicharset().get_fragment(str) ?
264 strlen(str) : getUnicharset().step(str + i));
265 int unichar_id = getUnicharset().unichar_to_id(str + i, step);
266 tprintf(" : %s ", getUnicharset().debug_str(unichar_id).string());
267 }
268 }
269 } // namespace tesseract
270