tesseract  5.0.0-alpha-619-ge9db
paramsd.cpp
Go to the documentation of this file.
1 // 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 <tesseract/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.
51 static std::map<int, ParamContent*> vcMap;
52 static int nrParams = 0;
53 static int writeCommands[2];
54 
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.
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 "_".
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 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)).c_str() != nullptr) {
145  result = sIt->c_str();
146  } else {
147  result = "Null";
148  }
149  }
150  return result;
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  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.
176 void 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.
189 int 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.
198 SVMenuNode* 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.c_str()]++;
234  amount[tag2.c_str()]++;
235  amount[tag3.c_str()]++;
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.c_str()] == 1) {
252  other->AddChild(vc->GetName(), vc->GetId(), vc->GetValue().c_str(),
253  vc->GetDescription());
254  } else { // More than one would use this submenu -> create submenu.
255  SVMenuNode* sv = mr->AddChild(tag.c_str());
256  if ((amount[tag.c_str()] <= MAX_ITEMS_IN_SUBMENU) ||
257  (amount[tag2.c_str()] <= 1)) {
258  sv->AddChild(vc->GetName(), vc->GetId(),
259  vc->GetValue().c_str(), vc->GetDescription());
260  } else { // Make subsubmenus.
261  SVMenuNode* sv2 = sv->AddChild(tag2.c_str());
262  sv2->AddChild(vc->GetName(), vc->GetId(),
263  vc->GetValue().c_str(), vc->GetDescription());
264  }
265  }
266  }
267  return mr;
268 }
269 
270 // Event listener. Waits for SVET_POPUP events and processes them.
271 void ParamsEditor::Notify(const SVEvent* sve) {
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().c_str());
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.c_str(), "Config file name?");
315 
316  writeCommands[1] = nrParams+2;
317  std_menu->AddChild ("changed_ Parameters Only", writeCommands[1],
318  paramfile.c_str(), "Config file name?");
319 
320  svMenuRoot->BuildMenu(sv, false);
321 }
322 
323 
324 // Write all (changed_) parameters to a config file.
325 void 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().c_str(), cur->GetDescription());
354  }
355  }
356  fclose(fp);
357 }
358 #endif // GRAPHICS_DISABLED
tesseract::BoolParam::set_value
void set_value(bool value)
Definition: params.h:198
ScrollView
Definition: scrollview.h:97
tesseract::CCUtil::datadir
STRING datadir
Definition: ccutil.h:53
tesseract::StringParam::c_str
const char * c_str() const
Definition: params.h:230
ParamContent::dIt
tesseract::DoubleParam * dIt
Definition: paramsd.h:90
STRING::add_str_int
void add_str_int(const char *str, int number)
Definition: strngs.cpp:370
ScrollView::AddMessage
void AddMessage(const char *format,...)
Definition: scrollview.cpp:560
tesseract::IntParam
Definition: params.h:152
VT_INTEGER
Definition: paramsd.h:42
tesseractclass.h
SVET_POPUP
Definition: scrollview.h:53
SVMenuNode::AddChild
SVMenuNode * AddChild(const char *txt)
Definition: svmnode.cpp:58
ParamContent::ParamContent
ParamContent()=default
params.h
tesseract::DoubleParam::set_value
void set_value(double value)
Definition: params.h:267
VT_STRING
Definition: paramsd.h:44
tesseract::Tesseract
Definition: tesseractclass.h:172
ParamContent::GetParamContentById
static ParamContent * GetParamContentById(int id)
Definition: paramsd.cpp:91
tesseract::IntParam::set_value
void set_value(int32_t value)
Definition: params.h:165
STRING
Definition: strngs.h:45
tesseract::ParamsVectors::int_params
GenericVector< IntParam * > int_params
Definition: params.h:57
ParamContent::bIt
tesseract::BoolParam * bIt
Definition: paramsd.h:89
ParamContent
Definition: paramsd.h:53
tesseract::ParamsVectors::double_params
GenericVector< DoubleParam * > double_params
Definition: params.h:60
ParamsEditor::Notify
void Notify(const SVEvent *sve) override
Definition: paramsd.cpp:271
genericvector.h
VT_DOUBLE
Definition: paramsd.h:45
svmnode.h
tesseract::Param::name_str
const char * name_str() const
Definition: params.h:127
tesseract::ParamsVectors::string_params
GenericVector< StringParam * > string_params
Definition: params.h:59
SVEvent::parameter
char * parameter
Definition: scrollview.h:65
ParamContent::GetName
const char * GetName() const
Definition: paramsd.cpp:116
STRING::c_str
const char * c_str() const
Definition: strngs.cpp:192
ParamContent::sIt
tesseract::StringParam * sIt
Definition: paramsd.h:87
ParamContent::SetValue
void SetValue(const char *val)
Definition: paramsd.cpp:154
tesseract::ParamsVectors
Definition: params.h:56
VT_BOOLEAN
Definition: paramsd.h:43
GlobalParams
tesseract::ParamsVectors * GlobalParams()
Definition: params.cpp:32
tesseract
Definition: baseapi.h:65
ParamContent::GetValue
STRING GetValue() const
Definition: paramsd.cpp:135
tesseract::CCUtil::params
ParamsVectors * params()
Definition: ccutil.h:51
SVEvent::type
SVEventType type
Definition: scrollview.h:63
MAX_ITEMS_IN_SUBMENU
#define MAX_ITEMS_IN_SUBMENU
Definition: paramsd.cpp:45
VARDIR
#define VARDIR
Definition: paramsd.cpp:44
tesseract::Param::info_str
const char * info_str() const
Definition: params.h:128
ParamContent::iIt
tesseract::IntParam * iIt
Definition: paramsd.h:88
SVMenuNode::BuildMenu
void BuildMenu(ScrollView *sv, bool menu_bar=true)
Definition: svmnode.cpp:120
ParamContent::GetId
int GetId()
Definition: paramsd.h:75
tesseract::DoubleParam
Definition: params.h:254
SVMenuNode
Definition: svmnode.h:35
ParamsEditor::ParamsEditor
ParamsEditor(tesseract::Tesseract *, ScrollView *sv=nullptr)
Definition: paramsd.cpp:291
SVEvent
Definition: scrollview.h:60
STRING::add_str_double
void add_str_double(const char *str, double number)
Definition: strngs.cpp:380
SVEvent::command_id
int command_id
Definition: scrollview.h:70
paramsd.h
ParamContent::Compare
static int Compare(const void *v1, const void *v2)
Definition: paramsd.cpp:189
tesseract::BoolParam
Definition: params.h:185
ParamContent::GetDescription
const char * GetDescription() const
Definition: paramsd.cpp:126
ScrollView::ShowYesNoDialog
int ShowYesNoDialog(const char *msg)
Definition: scrollview.cpp:743
scrollview.h
ParamContent::HasChanged
bool HasChanged()
Definition: paramsd.h:76
ELISTIZE
#define ELISTIZE(CLASSNAME)
Definition: elst.h:919
tesseract::StringParam::set_value
void set_value(const STRING &value)
Definition: params.h:234
tesseract::ParamsVectors::bool_params
GenericVector< BoolParam * > bool_params
Definition: params.h:58