tesseract 4.1.1
Loading...
Searching...
No Matches
paramsd.cpp
Go to the documentation of this file.
1
2// File: paramsd.cpp
3// Description: Tesseract parameter Editor
4// Author: Joern Wanke
5//
6// (C) Copyright 2007, Google Inc.
7// Licensed under the Apache License, Version 2.0 (the "License");
8// you may not use this file except in compliance with the License.
9// You may obtain a copy of the License at
10// http://www.apache.org/licenses/LICENSE-2.0
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16//
18//
19// The parameters editor is used to edit all the parameters used within
20// tesseract from the ui.
21
22// Include automatically generated configuration file if running autoconf.
23#ifdef HAVE_CONFIG_H
24#include "config_auto.h"
25#endif
26
27#ifndef GRAPHICS_DISABLED
28
29#include "paramsd.h"
30#include <cstdio> // for fclose, fopen, fprintf, sprintf, FILE
31#include <cstdlib> // for atoi
32#include <cstring> // for strcmp, strcspn, strlen, strncpy
33#include <locale> // for std::locale::classic
34#include <map> // for map, _Rb_tree_iterator, map<>::iterator
35#include <memory> // for unique_ptr
36#include <sstream> // for std::stringstream
37#include <utility> // for pair
38#include "genericvector.h" // for GenericVector
39#include "params.h" // for ParamsVectors, StringParam, BoolParam
40#include "scrollview.h" // for SVEvent, ScrollView, SVET_POPUP
41#include "svmnode.h" // for SVMenuNode
42#include "tesseractclass.h" // for Tesseract
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.
51static std::map<int, ParamContent*> vcMap;
52static int nrParams = 0;
53static int writeCommands[2];
54
56
57// Constructors for the various ParamTypes.
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.
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.
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.
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.
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 "_".
97void 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.
116const 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.
126const 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 nullptr;
132}
133
134// Getter for the value.
136 STRING result;
137 if (param_type_ == VT_INTEGER) {
138 result.add_str_int("", *iIt);
139 } else if (param_type_ == VT_BOOLEAN) {
140 result.add_str_int("", *bIt);
141 } else if (param_type_ == VT_DOUBLE) {
142 result.add_str_double("", *dIt);
143 } else if (param_type_ == VT_STRING) {
144 if (STRING(*(sIt)).string() != nullptr) {
145 result = sIt->string();
146 } else {
147 result = "Null";
148 }
149 }
150 return result;
151}
152
153// Setter for the value.
154void 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 std::stringstream stream(val);
164 // Use "C" locale for reading double value.
165 stream.imbue(std::locale::classic());
166 double d = 0;
167 stream >> d;
168 dIt->set_value(d);
169 } else if (param_type_ == VT_STRING) {
170 sIt->set_value(val);
171 }
172}
173
174// Gets the up to the first 3 prefixes from s (split by _).
175// For example, tesseract_foo_bar will be split into tesseract,foo and bar.
176void ParamsEditor::GetPrefixes(const char* s, STRING* level_one,
177 STRING* level_two,
178 STRING* level_three) {
179 std::unique_ptr<char[]> p(new char[1024]);
180 GetFirstWords(s, 1, p.get());
181 *level_one = p.get();
182 GetFirstWords(s, 2, p.get());
183 *level_two = p.get();
184 GetFirstWords(s, 3, p.get());
185 *level_three = p.get();
186}
187
188// Compare two VC objects by their name.
189int ParamContent::Compare(const void* v1, const void* v2) {
190 const ParamContent* one = *static_cast<const ParamContent* const*>(v1);
191 const ParamContent* two = *static_cast<const ParamContent* const*>(v2);
192 return strcmp(one->GetName(), two->GetName());
193}
194
195// Find all editable parameters used within tesseract and create a
196// SVMenuNode tree from it.
197// TODO (wanke): This is actually sort of hackish.
198SVMenuNode* ParamsEditor::BuildListOfAllLeaves(tesseract::Tesseract *tess) {
199 auto* mr = new SVMenuNode();
200 ParamContent_LIST vclist;
201 ParamContent_IT vc_it(&vclist);
202 // Amount counts the number of entries for a specific char*.
203 // TODO(rays) get rid of the use of std::map.
204 std::map<const char*, int> amount;
205
206 // Add all parameters to a list.
207 int v, i;
208 int num_iterations = (tess->params() == nullptr) ? 1 : 2;
209 for (v = 0; v < num_iterations; ++v) {
210 tesseract::ParamsVectors *vec = (v == 0) ? GlobalParams() : tess->params();
211 for (i = 0; i < vec->int_params.size(); ++i) {
212 vc_it.add_after_then_move(new ParamContent(vec->int_params[i]));
213 }
214 for (i = 0; i < vec->bool_params.size(); ++i) {
215 vc_it.add_after_then_move(new ParamContent(vec->bool_params[i]));
216 }
217 for (i = 0; i < vec->string_params.size(); ++i) {
218 vc_it.add_after_then_move(new ParamContent(vec->string_params[i]));
219 }
220 for (i = 0; i < vec->double_params.size(); ++i) {
221 vc_it.add_after_then_move(new ParamContent(vec->double_params[i]));
222 }
223 }
224
225 // Count the # of entries starting with a specific prefix.
226 for (vc_it.mark_cycle_pt(); !vc_it.cycled_list(); vc_it.forward()) {
227 ParamContent* vc = vc_it.data();
228 STRING tag;
229 STRING tag2;
230 STRING tag3;
231
232 GetPrefixes(vc->GetName(), &tag, &tag2, &tag3);
233 amount[tag.string()]++;
234 amount[tag2.string()]++;
235 amount[tag3.string()]++;
236 }
237
238 vclist.sort(ParamContent::Compare); // Sort the list alphabetically.
239
240 SVMenuNode* other = mr->AddChild("OTHER");
241
242 // go through the list again and this time create the menu structure.
243 vc_it.move_to_first();
244 for (vc_it.mark_cycle_pt(); !vc_it.cycled_list(); vc_it.forward()) {
245 ParamContent* vc = vc_it.data();
246 STRING tag;
247 STRING tag2;
248 STRING tag3;
249 GetPrefixes(vc->GetName(), &tag, &tag2, &tag3);
250
251 if (amount[tag.string()] == 1) {
252 other->AddChild(vc->GetName(), vc->GetId(), vc->GetValue().string(),
253 vc->GetDescription());
254 } else { // More than one would use this submenu -> create submenu.
255 SVMenuNode* sv = mr->AddChild(tag.string());
256 if ((amount[tag.string()] <= MAX_ITEMS_IN_SUBMENU) ||
257 (amount[tag2.string()] <= 1)) {
258 sv->AddChild(vc->GetName(), vc->GetId(),
259 vc->GetValue().string(), vc->GetDescription());
260 } else { // Make subsubmenus.
261 SVMenuNode* sv2 = sv->AddChild(tag2.string());
262 sv2->AddChild(vc->GetName(), vc->GetId(),
263 vc->GetValue().string(), vc->GetDescription());
264 }
265 }
266 }
267 return mr;
268}
269
270// Event listener. Waits for SVET_POPUP events and processes them.
272 if (sve->type == SVET_POPUP) { // only catch SVET_POPUP!
273 char* param = sve->parameter;
274 if (sve->command_id == writeCommands[0]) {
275 WriteParams(param, false);
276 } else if (sve->command_id == writeCommands[1]) {
277 WriteParams(param, true);
278 } else {
280 sve->command_id);
281 vc->SetValue(param);
282 sv_window_->AddMessage("Setting %s to %s",
283 vc->GetName(), vc->GetValue().string());
284 }
285 }
286}
287
288// Integrate the parameters editor as popupmenu into the existing scrollview
289// window (usually the pg editor). If sv == null, create a new empty
290// empty window and attach the parameters editor to that window (ugly).
292 ScrollView* sv) {
293 if (sv == nullptr) {
294 const char* name = "ParamEditorMAIN";
295 sv = new ScrollView(name, 1, 1, 200, 200, 300, 200);
296 }
297
298 sv_window_ = sv;
299
300 //Only one event handler per window.
301 //sv->AddEventHandler((SVEventHandler*) this);
302
303 SVMenuNode* svMenuRoot = BuildListOfAllLeaves(tess);
304
305 STRING paramfile;
306 paramfile = tess->datadir;
307 paramfile += VARDIR; // parameters dir
308 paramfile += "edited"; // actual name
309
310 SVMenuNode* std_menu = svMenuRoot->AddChild ("Build Config File");
311
312 writeCommands[0] = nrParams+1;
313 std_menu->AddChild("All Parameters", writeCommands[0],
314 paramfile.string(), "Config file name?");
315
316 writeCommands[1] = nrParams+2;
317 std_menu->AddChild ("changed_ Parameters Only", writeCommands[1],
318 paramfile.string(), "Config file name?");
319
320 svMenuRoot->BuildMenu(sv, false);
321}
322
323
324// Write all (changed_) parameters to a config file.
325void ParamsEditor::WriteParams(char *filename,
326 bool changes_only) {
327 FILE *fp; // input file
328 char msg_str[255];
329 // if file exists
330 if ((fp = fopen (filename, "rb")) != nullptr) {
331 fclose(fp);
332 sprintf (msg_str, "Overwrite file " "%s" "? (Y/N)", filename);
333 int a = sv_window_->ShowYesNoDialog(msg_str);
334 if (a == 'n') {
335 return;
336 } // don't write
337 }
338
339
340 fp = fopen (filename, "wb"); // can we write to it?
341 if (fp == nullptr) {
342 sv_window_->AddMessage(
343 "Can't write to file "
344 "%s"
345 "",
346 filename);
347 return;
348 }
349 for (auto& iter : vcMap) {
350 ParamContent* cur = iter.second;
351 if (!changes_only || cur->HasChanged()) {
352 fprintf(fp, "%-25s %-12s # %s\n",
353 cur->GetName(), cur->GetValue().string(), cur->GetDescription());
354 }
355 }
356 fclose(fp);
357}
358#endif // GRAPHICS_DISABLED
#define VARDIR
Definition: paramsd.cpp:44
#define MAX_ITEMS_IN_SUBMENU
Definition: paramsd.cpp:45
@ VT_DOUBLE
Definition: paramsd.h:45
@ VT_INTEGER
Definition: paramsd.h:42
@ VT_STRING
Definition: paramsd.h:44
@ VT_BOOLEAN
Definition: paramsd.h:43
#define ELISTIZE(CLASSNAME)
Definition: elst.h:931
tesseract::ParamsVectors * GlobalParams()
Definition: params.cpp:32
@ SVET_POPUP
Definition: scrollview.h:54
bool HasChanged()
Definition: paramsd.h:76
tesseract::StringParam * sIt
Definition: paramsd.h:87
int GetId()
Definition: paramsd.h:75
const char * GetDescription() const
Definition: paramsd.cpp:126
static ParamContent * GetParamContentById(int id)
Definition: paramsd.cpp:91
STRING GetValue() const
Definition: paramsd.cpp:135
const char * GetName() const
Definition: paramsd.cpp:116
tesseract::DoubleParam * dIt
Definition: paramsd.h:90
static int Compare(const void *v1, const void *v2)
Definition: paramsd.cpp:189
tesseract::IntParam * iIt
Definition: paramsd.h:88
void SetValue(const char *val)
Definition: paramsd.cpp:154
ParamContent()=default
tesseract::BoolParam * bIt
Definition: paramsd.h:89
void Notify(const SVEvent *sve) override
Definition: paramsd.cpp:271
ParamsEditor(tesseract::Tesseract *, ScrollView *sv=nullptr)
Definition: paramsd.cpp:291
ParamsVectors * params()
Definition: ccutil.h:67
STRING datadir
Definition: ccutil.h:69
GenericVector< IntParam * > int_params
Definition: params.h:43
GenericVector< DoubleParam * > double_params
Definition: params.h:46
GenericVector< BoolParam * > bool_params
Definition: params.h:44
GenericVector< StringParam * > string_params
Definition: params.h:45
const char * name_str() const
Definition: params.h:113
const char * info_str() const
Definition: params.h:114
void set_value(int32_t value)
Definition: params.h:151
void set_value(bool value)
Definition: params.h:184
void set_value(const STRING &value)
Definition: params.h:221
const char * string() const
Definition: params.h:216
void set_value(double value)
Definition: params.h:254
Definition: strngs.h:45
void add_str_int(const char *str, int number)
Definition: strngs.cpp:377
void add_str_double(const char *str, double number)
Definition: strngs.cpp:387
const char * string() const
Definition: strngs.cpp:194
SVEventType type
Definition: scrollview.h:64
char * parameter
Definition: scrollview.h:66
int command_id
Definition: scrollview.h:71
int ShowYesNoDialog(const char *msg)
Definition: scrollview.cpp:745
void AddMessage(const char *format,...)
Definition: scrollview.cpp:561
SVMenuNode * AddChild(const char *txt)
Definition: svmnode.cpp:58
void BuildMenu(ScrollView *sv, bool menu_bar=true)
Definition: svmnode.cpp:120