Tesseract 3.02

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
paramsd.cpp
Go to the documentation of this file.
1
2 // File: paramsd.cpp
3 // Description: Tesseract parameter Editor
4 // Author: Joern Wanke
5 // Created: Wed Jul 18 10:05:01 PDT 2007
6 //
7 // (C) Copyright 2007, Google Inc.
8 // Licensed under the Apache License, Version 2.0 (the "License");
9 // you may not use this file except in compliance with the License.
10 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
12 // Unless required by applicable law or agreed to in writing, software
13 // distributed under the License is distributed on an "AS IS" BASIS,
14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 // See the License for the specific language governing permissions and
16 // limitations under the License.
17 //
19 //
20 // The parameters editor is used to edit all the parameters used within
21 // tesseract from the ui.
22 #ifdef _WIN32
23 #else
24 #include <stdlib.h>
25 #include <stdio.h>
26 #endif
27
28 #include <map>
29
30 // Include automatically generated configuration file if running autoconf.
31 #ifdef HAVE_CONFIG_H
32 #include "config_auto.h"
33 #endif
34
35 #ifndef GRAPHICS_DISABLED
36 #include "paramsd.h"
37
38
39 #include "params.h"
40 #include "scrollview.h"
41 #include "svmnode.h"
42
43
44 #define VARDIR "configs/" /*parameters files */
45 #define MAX_ITEMS_IN_SUBMENU 30
46
47 // The following variables should remain static globals, since they
48 // are used by debug editor, which uses a single Tesseract instance.
49 //
50 // Contains the mappings from unique VC ids to their actual pointers.
51 static std::map<int, ParamContent*> vcMap;
52 static int nrParams = 0;
53 static int writeCommands[2];
54
55 ELISTIZE(ParamContent)
56
57 // Constructors for the various ParamTypes.
58 ParamContent::ParamContent(tesseract::StringParam* it) {
59 my_id_ = nrParams;
60 nrParams++;
61 param_type_ = VT_STRING;
62 sIt = it;
63 vcMap[my_id_] = this;
64 }
65 // Constructors for the various ParamTypes.
66 ParamContent::ParamContent(tesseract::IntParam* it) {
67 my_id_ = nrParams;
68 nrParams++;
69 param_type_ = VT_INTEGER;
70 iIt = it;
71 vcMap[my_id_] = this;
72 }
73 // Constructors for the various ParamTypes.
74 ParamContent::ParamContent(tesseract::BoolParam* it) {
75 my_id_ = nrParams;
76 nrParams++;
77 param_type_ = VT_BOOLEAN;
78 bIt = it;
79 vcMap[my_id_] = this;
80 }
81 // Constructors for the various ParamTypes.
82 ParamContent::ParamContent(tesseract::DoubleParam* it) {
83 my_id_ = nrParams;
84 nrParams++;
85 param_type_ = VT_DOUBLE;
86 dIt = it;
87 vcMap[my_id_] = this;
88 }
89
90 // Gets a VC object identified by its ID.
91 ParamContent* ParamContent::GetParamContentById(int id) {
92 return vcMap[id];
93 }
94
95 // Copy the first N words from the source string to the target string.
96 // Words are delimited by "_".
97 void ParamsEditor::GetFirstWords(
98 const char *s, // source string
99 int n, // number of words
100 char *t // target string
101 ) {
102 int full_length = strlen(s);
103 int reqd_len = 0; // No. of chars requird
104 const char *next_word = s;
105
106 while ((n > 0) && reqd_len < full_length) {
107 reqd_len += strcspn(next_word, "_") + 1;
108 next_word += reqd_len;
109 n--;
110 }
111 strncpy(t, s, reqd_len);
112 t[reqd_len] = '\0'; // ensure null terminal
113 }
114
115 // Getter for the name.
116 const char* ParamContent::GetName() const {
117 if (param_type_ == VT_INTEGER) { return iIt->name_str(); }
118 else if (param_type_ == VT_BOOLEAN) { return bIt->name_str(); }
119 else if (param_type_ == VT_DOUBLE) { return dIt->name_str(); }
120 else if (param_type_ == VT_STRING) { return sIt->name_str(); }
121 else
122 return "ERROR: ParamContent::GetName()";
123 }
124
125 // Getter for the description.
126 const char* ParamContent::GetDescription() const {
127 if (param_type_ == VT_INTEGER) { return iIt->info_str(); }
128 else if (param_type_ == VT_BOOLEAN) { return bIt->info_str(); }
129 else if (param_type_ == VT_DOUBLE) { return dIt->info_str(); }
130 else if (param_type_ == VT_STRING) { return sIt->info_str(); }
131 else return NULL;
132 }
133
134 // Getter for the value.
135 const char* ParamContent::GetValue() const {
136 char* msg = new char[1024];
137 if (param_type_ == VT_INTEGER) {
138 sprintf(msg, "%d", ((inT32) *(iIt)));
139 } else if (param_type_ == VT_BOOLEAN) {
140 sprintf(msg, "%d", ((BOOL8) * (bIt)));
141 } else if (param_type_ == VT_DOUBLE) {
142 sprintf(msg, "%g", ((double) * (dIt)));
143 } else if (param_type_ == VT_STRING) {
144 if (((STRING) * (sIt)).string() != NULL) {
145 sprintf(msg, "%s", ((STRING) * (sIt)).string());
146 } else {
147 sprintf(msg, "Null");
148 }
149 }
150 return msg;
151 }
152
153 // Setter for the value.
154 void ParamContent::SetValue(const char* val) {
155 // TODO (wanke) Test if the values actually are properly converted.
156 // (Quickly visible impacts?)
157 changed_ = TRUE;
158 if (param_type_ == VT_INTEGER) {
159 iIt->set_value(atoi(val));
160 } else if (param_type_ == VT_BOOLEAN) {
161 bIt->set_value(atoi(val));
162 } else if (param_type_ == VT_DOUBLE) {
163 dIt->set_value(strtod(val, NULL));
164 } else if (param_type_ == VT_STRING) {
165 sIt->set_value(val);
166 }
167 }
168
169 // Gets the up to the first 3 prefixes from s (split by _).
170 // For example, tesseract_foo_bar will be split into tesseract,foo and bar.
171 void ParamsEditor::GetPrefixes(const char* s, STRING* level_one,
172 STRING* level_two,
173 STRING* level_three) {
174 char* p = new char[1024];
175 GetFirstWords(s, 1, p);
176 *level_one = p;
177 GetFirstWords(s, 2, p);
178 *level_two = p;
179 GetFirstWords(s, 3, p);
180 *level_three = p;
181 delete[] p;
182 }
183
184 // Compare two VC objects by their name.
185 int ParamContent::Compare(const void* v1, const void* v2) {
186 const ParamContent* one =
187 *reinterpret_cast<const ParamContent* const *>(v1);
188 const ParamContent* two =
189 *reinterpret_cast<const ParamContent* const *>(v2);
190 return strcmp(one->GetName(), two->GetName());
191 }
192
193 // Find all editable parameters used within tesseract and create a
194 // SVMenuNode tree from it.
195 // TODO (wanke): This is actually sort of hackish.
196 SVMenuNode* ParamsEditor::BuildListOfAllLeaves(tesseract::Tesseract *tess) {
197 SVMenuNode* mr = new SVMenuNode();
198 ParamContent_LIST vclist;
199 ParamContent_IT vc_it(&vclist);
200 // Amount counts the number of entries for a specific char*.
201 // TODO(rays) get rid of the use of std::map.
202 std::map<const char*, int> amount;
203
204 // Add all parameters to a list.
205 int v, i;
206 int num_iterations = (tess->params() == NULL) ? 1 : 2;
207 for (v = 0; v < num_iterations; ++v) {
208 tesseract::ParamsVectors *vec = (v == 0) ? GlobalParams() : tess->params();
209 for (i = 0; i < vec->int_params.size(); ++i) {
210 vc_it.add_after_then_move(new ParamContent(vec->int_params[i]));
211 }
212 for (i = 0; i < vec->bool_params.size(); ++i) {
213 vc_it.add_after_then_move(new ParamContent(vec->bool_params[i]));
214 }
215 for (i = 0; i < vec->string_params.size(); ++i) {
216 vc_it.add_after_then_move(new ParamContent(vec->string_params[i]));
217 }
218 for (i = 0; i < vec->double_params.size(); ++i) {
219 vc_it.add_after_then_move(new ParamContent(vec->double_params[i]));
220 }
221 }
222
223 // Count the # of entries starting with a specific prefix.
224 for (vc_it.mark_cycle_pt(); !vc_it.cycled_list(); vc_it.forward()) {
225 ParamContent* vc = vc_it.data();
226 STRING tag;
227 STRING tag2;
228 STRING tag3;
229
230 GetPrefixes(vc->GetName(), &tag, &tag2, &tag3);
231 amount[tag.string()]++;
232 amount[tag2.string()]++;
233 amount[tag3.string()]++;
234 }
235
236 vclist.sort(ParamContent::Compare); // Sort the list alphabetically.
237
238 SVMenuNode* other = mr->AddChild("OTHER");
239
240 // go through the list again and this time create the menu structure.
241 vc_it.move_to_first();
242 for (vc_it.mark_cycle_pt(); !vc_it.cycled_list(); vc_it.forward()) {
243 ParamContent* vc = vc_it.data();
244 STRING tag;
245 STRING tag2;
246 STRING tag3;
247 GetPrefixes(vc->GetName(), &tag, &tag2, &tag3);
248
249 if (amount[tag.string()] == 1) { other->AddChild(vc->GetName(), vc->GetId(),
250 vc->GetValue(),
251 vc->GetDescription());
252 } else { // More than one would use this submenu -> create submenu.
253 SVMenuNode* sv = mr->AddChild(tag.string());
254 if ((amount[tag.string()] <= MAX_ITEMS_IN_SUBMENU) ||
255 (amount[tag2.string()] <= 1)) {
256 sv->AddChild(vc->GetName(), vc->GetId(),
257 vc->GetValue(), vc->GetDescription());
258 } else { // Make subsubmenus.
259 SVMenuNode* sv2 = sv->AddChild(tag2.string());
260 sv2->AddChild(vc->GetName(), vc->GetId(),
261 vc->GetValue(), vc->GetDescription());
262 }
263 }
264 }
265 return mr;
266 }
267
268 // Event listener. Waits for SVET_POPUP events and processes them.
269 void ParamsEditor::Notify(const SVEvent* sve) {
270 if (sve->type == SVET_POPUP) { // only catch SVET_POPUP!
271 char* param = sve->parameter;
272 if (sve->command_id == writeCommands[0]) {
273 WriteParams(param, false);
274 } else if (sve->command_id == writeCommands[1]) {
275 WriteParams(param, true);
276 } else {
277 ParamContent* vc = ParamContent::GetParamContentById(
278 sve->command_id);
279 vc->SetValue(param);
280 sv_window_->AddMessage("Setting %s to %s",
281 vc->GetName(), vc->GetValue());
282 }
283 }
284 }
285
286 // Integrate the parameters editor as popupmenu into the existing scrollview
287 // window (usually the pg editor). If sv == null, create a new empty
288 // empty window and attach the parameters editor to that window (ugly).
289 ParamsEditor::ParamsEditor(tesseract::Tesseract* tess,
290 ScrollView* sv) {
291 if (sv == NULL) {
292 const char* name = "ParamEditorMAIN";
293 sv = new ScrollView(name, 1, 1, 200, 200, 300, 200);
294 }
295
296 sv_window_ = sv;
297
298 //Only one event handler per window.
299 //sv->AddEventHandler((SVEventHandler*) this);
300
301 SVMenuNode* svMenuRoot = BuildListOfAllLeaves(tess);
302
303 STRING paramfile;
304 paramfile = tess->datadir;
305 paramfile += VARDIR; // parameters dir
306 paramfile += "edited"; // actual name
307
308 SVMenuNode* std_menu = svMenuRoot->AddChild ("Build Config File");
309
310 writeCommands[0] = nrParams+1;
311 std_menu->AddChild("All Parameters", writeCommands[0],
312 paramfile.string(), "Config file name?");
313
314 writeCommands[1] = nrParams+2;
315 std_menu->AddChild ("changed_ Parameters Only", writeCommands[1],
316 paramfile.string(), "Config file name?");
317
318 svMenuRoot->BuildMenu(sv, false);
319 }
320
321
322 // Write all (changed_) parameters to a config file.
323 void ParamsEditor::WriteParams(char *filename,
324 bool changes_only) {
325 FILE *fp; // input file
326 char msg_str[255];
327 // if file exists
328 if ((fp = fopen (filename, "rb")) != NULL) {
329 fclose(fp);
330 sprintf (msg_str, "Overwrite file " "%s" "? (Y/N)", filename);
331 int a = sv_window_->ShowYesNoDialog(msg_str);
332 if (a == 'n') { return; } // dont write
333 }
334
335
336 fp = fopen (filename, "wb"); // can we write to it?
337 if (fp == NULL) {
338 sv_window_->AddMessage("Cant write to file " "%s" "", filename);
339 return;
340 }
341
342 for (std::map<int, ParamContent*>::iterator iter = vcMap.begin();
343 iter != vcMap.end();
344 ++iter) {
345 ParamContent* cur = iter->second;
346 if (!changes_only || cur->HasChanged()) {
347 fprintf (fp, "%-25s %-12s # %s\n",
348 cur->GetName(), cur->GetValue(), cur->GetDescription());
349 }
350 }
351 fclose(fp);
352 }
353 #endif