Tesseract
3.02
|
00001 00002 // File: paramsd.cpp 00003 // Description: Tesseract parameter Editor 00004 // Author: Joern Wanke 00005 // Created: Wed Jul 18 10:05:01 PDT 2007 00006 // 00007 // (C) Copyright 2007, Google Inc. 00008 // Licensed under the Apache License, Version 2.0 (the "License"); 00009 // you may not use this file except in compliance with the License. 00010 // You may obtain a copy of the License at 00011 // http://www.apache.org/licenses/LICENSE-2.0 00012 // Unless required by applicable law or agreed to in writing, software 00013 // distributed under the License is distributed on an "AS IS" BASIS, 00014 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00015 // See the License for the specific language governing permissions and 00016 // limitations under the License. 00017 // 00019 // 00020 // The parameters editor is used to edit all the parameters used within 00021 // tesseract from the ui. 00022 #ifdef _WIN32 00023 #else 00024 #include <stdlib.h> 00025 #include <stdio.h> 00026 #endif 00027 00028 #include <map> 00029 00030 // Include automatically generated configuration file if running autoconf. 00031 #ifdef HAVE_CONFIG_H 00032 #include "config_auto.h" 00033 #endif 00034 00035 #ifndef GRAPHICS_DISABLED 00036 #include "paramsd.h" 00037 00038 00039 #include "params.h" 00040 #include "scrollview.h" 00041 #include "svmnode.h" 00042 00043 00044 #define VARDIR "configs/" /*parameters files */ 00045 #define MAX_ITEMS_IN_SUBMENU 30 00046 00047 // The following variables should remain static globals, since they 00048 // are used by debug editor, which uses a single Tesseract instance. 00049 // 00050 // Contains the mappings from unique VC ids to their actual pointers. 00051 static std::map<int, ParamContent*> vcMap; 00052 static int nrParams = 0; 00053 static int writeCommands[2]; 00054 00055 ELISTIZE(ParamContent) 00056 00057 // Constructors for the various ParamTypes. 00058 ParamContent::ParamContent(tesseract::StringParam* it) { 00059 my_id_ = nrParams; 00060 nrParams++; 00061 param_type_ = VT_STRING; 00062 sIt = it; 00063 vcMap[my_id_] = this; 00064 } 00065 // Constructors for the various ParamTypes. 00066 ParamContent::ParamContent(tesseract::IntParam* it) { 00067 my_id_ = nrParams; 00068 nrParams++; 00069 param_type_ = VT_INTEGER; 00070 iIt = it; 00071 vcMap[my_id_] = this; 00072 } 00073 // Constructors for the various ParamTypes. 00074 ParamContent::ParamContent(tesseract::BoolParam* it) { 00075 my_id_ = nrParams; 00076 nrParams++; 00077 param_type_ = VT_BOOLEAN; 00078 bIt = it; 00079 vcMap[my_id_] = this; 00080 } 00081 // Constructors for the various ParamTypes. 00082 ParamContent::ParamContent(tesseract::DoubleParam* it) { 00083 my_id_ = nrParams; 00084 nrParams++; 00085 param_type_ = VT_DOUBLE; 00086 dIt = it; 00087 vcMap[my_id_] = this; 00088 } 00089 00090 // Gets a VC object identified by its ID. 00091 ParamContent* ParamContent::GetParamContentById(int id) { 00092 return vcMap[id]; 00093 } 00094 00095 // Copy the first N words from the source string to the target string. 00096 // Words are delimited by "_". 00097 void ParamsEditor::GetFirstWords( 00098 const char *s, // source string 00099 int n, // number of words 00100 char *t // target string 00101 ) { 00102 int full_length = strlen(s); 00103 int reqd_len = 0; // No. of chars requird 00104 const char *next_word = s; 00105 00106 while ((n > 0) && reqd_len < full_length) { 00107 reqd_len += strcspn(next_word, "_") + 1; 00108 next_word += reqd_len; 00109 n--; 00110 } 00111 strncpy(t, s, reqd_len); 00112 t[reqd_len] = '\0'; // ensure null terminal 00113 } 00114 00115 // Getter for the name. 00116 const char* ParamContent::GetName() const { 00117 if (param_type_ == VT_INTEGER) { return iIt->name_str(); } 00118 else if (param_type_ == VT_BOOLEAN) { return bIt->name_str(); } 00119 else if (param_type_ == VT_DOUBLE) { return dIt->name_str(); } 00120 else if (param_type_ == VT_STRING) { return sIt->name_str(); } 00121 else 00122 return "ERROR: ParamContent::GetName()"; 00123 } 00124 00125 // Getter for the description. 00126 const char* ParamContent::GetDescription() const { 00127 if (param_type_ == VT_INTEGER) { return iIt->info_str(); } 00128 else if (param_type_ == VT_BOOLEAN) { return bIt->info_str(); } 00129 else if (param_type_ == VT_DOUBLE) { return dIt->info_str(); } 00130 else if (param_type_ == VT_STRING) { return sIt->info_str(); } 00131 else return NULL; 00132 } 00133 00134 // Getter for the value. 00135 const char* ParamContent::GetValue() const { 00136 char* msg = new char[1024]; 00137 if (param_type_ == VT_INTEGER) { 00138 sprintf(msg, "%d", ((inT32) *(iIt))); 00139 } else if (param_type_ == VT_BOOLEAN) { 00140 sprintf(msg, "%d", ((BOOL8) * (bIt))); 00141 } else if (param_type_ == VT_DOUBLE) { 00142 sprintf(msg, "%g", ((double) * (dIt))); 00143 } else if (param_type_ == VT_STRING) { 00144 if (((STRING) * (sIt)).string() != NULL) { 00145 sprintf(msg, "%s", ((STRING) * (sIt)).string()); 00146 } else { 00147 sprintf(msg, "Null"); 00148 } 00149 } 00150 return msg; 00151 } 00152 00153 // Setter for the value. 00154 void ParamContent::SetValue(const char* val) { 00155 // TODO (wanke) Test if the values actually are properly converted. 00156 // (Quickly visible impacts?) 00157 changed_ = TRUE; 00158 if (param_type_ == VT_INTEGER) { 00159 iIt->set_value(atoi(val)); 00160 } else if (param_type_ == VT_BOOLEAN) { 00161 bIt->set_value(atoi(val)); 00162 } else if (param_type_ == VT_DOUBLE) { 00163 dIt->set_value(strtod(val, NULL)); 00164 } else if (param_type_ == VT_STRING) { 00165 sIt->set_value(val); 00166 } 00167 } 00168 00169 // Gets the up to the first 3 prefixes from s (split by _). 00170 // For example, tesseract_foo_bar will be split into tesseract,foo and bar. 00171 void ParamsEditor::GetPrefixes(const char* s, STRING* level_one, 00172 STRING* level_two, 00173 STRING* level_three) { 00174 char* p = new char[1024]; 00175 GetFirstWords(s, 1, p); 00176 *level_one = p; 00177 GetFirstWords(s, 2, p); 00178 *level_two = p; 00179 GetFirstWords(s, 3, p); 00180 *level_three = p; 00181 delete[] p; 00182 } 00183 00184 // Compare two VC objects by their name. 00185 int ParamContent::Compare(const void* v1, const void* v2) { 00186 const ParamContent* one = 00187 *reinterpret_cast<const ParamContent* const *>(v1); 00188 const ParamContent* two = 00189 *reinterpret_cast<const ParamContent* const *>(v2); 00190 return strcmp(one->GetName(), two->GetName()); 00191 } 00192 00193 // Find all editable parameters used within tesseract and create a 00194 // SVMenuNode tree from it. 00195 // TODO (wanke): This is actually sort of hackish. 00196 SVMenuNode* ParamsEditor::BuildListOfAllLeaves(tesseract::Tesseract *tess) { 00197 SVMenuNode* mr = new SVMenuNode(); 00198 ParamContent_LIST vclist; 00199 ParamContent_IT vc_it(&vclist); 00200 // Amount counts the number of entries for a specific char*. 00201 // TODO(rays) get rid of the use of std::map. 00202 std::map<const char*, int> amount; 00203 00204 // Add all parameters to a list. 00205 int v, i; 00206 int num_iterations = (tess->params() == NULL) ? 1 : 2; 00207 for (v = 0; v < num_iterations; ++v) { 00208 tesseract::ParamsVectors *vec = (v == 0) ? GlobalParams() : tess->params(); 00209 for (i = 0; i < vec->int_params.size(); ++i) { 00210 vc_it.add_after_then_move(new ParamContent(vec->int_params[i])); 00211 } 00212 for (i = 0; i < vec->bool_params.size(); ++i) { 00213 vc_it.add_after_then_move(new ParamContent(vec->bool_params[i])); 00214 } 00215 for (i = 0; i < vec->string_params.size(); ++i) { 00216 vc_it.add_after_then_move(new ParamContent(vec->string_params[i])); 00217 } 00218 for (i = 0; i < vec->double_params.size(); ++i) { 00219 vc_it.add_after_then_move(new ParamContent(vec->double_params[i])); 00220 } 00221 } 00222 00223 // Count the # of entries starting with a specific prefix. 00224 for (vc_it.mark_cycle_pt(); !vc_it.cycled_list(); vc_it.forward()) { 00225 ParamContent* vc = vc_it.data(); 00226 STRING tag; 00227 STRING tag2; 00228 STRING tag3; 00229 00230 GetPrefixes(vc->GetName(), &tag, &tag2, &tag3); 00231 amount[tag.string()]++; 00232 amount[tag2.string()]++; 00233 amount[tag3.string()]++; 00234 } 00235 00236 vclist.sort(ParamContent::Compare); // Sort the list alphabetically. 00237 00238 SVMenuNode* other = mr->AddChild("OTHER"); 00239 00240 // go through the list again and this time create the menu structure. 00241 vc_it.move_to_first(); 00242 for (vc_it.mark_cycle_pt(); !vc_it.cycled_list(); vc_it.forward()) { 00243 ParamContent* vc = vc_it.data(); 00244 STRING tag; 00245 STRING tag2; 00246 STRING tag3; 00247 GetPrefixes(vc->GetName(), &tag, &tag2, &tag3); 00248 00249 if (amount[tag.string()] == 1) { other->AddChild(vc->GetName(), vc->GetId(), 00250 vc->GetValue(), 00251 vc->GetDescription()); 00252 } else { // More than one would use this submenu -> create submenu. 00253 SVMenuNode* sv = mr->AddChild(tag.string()); 00254 if ((amount[tag.string()] <= MAX_ITEMS_IN_SUBMENU) || 00255 (amount[tag2.string()] <= 1)) { 00256 sv->AddChild(vc->GetName(), vc->GetId(), 00257 vc->GetValue(), vc->GetDescription()); 00258 } else { // Make subsubmenus. 00259 SVMenuNode* sv2 = sv->AddChild(tag2.string()); 00260 sv2->AddChild(vc->GetName(), vc->GetId(), 00261 vc->GetValue(), vc->GetDescription()); 00262 } 00263 } 00264 } 00265 return mr; 00266 } 00267 00268 // Event listener. Waits for SVET_POPUP events and processes them. 00269 void ParamsEditor::Notify(const SVEvent* sve) { 00270 if (sve->type == SVET_POPUP) { // only catch SVET_POPUP! 00271 char* param = sve->parameter; 00272 if (sve->command_id == writeCommands[0]) { 00273 WriteParams(param, false); 00274 } else if (sve->command_id == writeCommands[1]) { 00275 WriteParams(param, true); 00276 } else { 00277 ParamContent* vc = ParamContent::GetParamContentById( 00278 sve->command_id); 00279 vc->SetValue(param); 00280 sv_window_->AddMessage("Setting %s to %s", 00281 vc->GetName(), vc->GetValue()); 00282 } 00283 } 00284 } 00285 00286 // Integrate the parameters editor as popupmenu into the existing scrollview 00287 // window (usually the pg editor). If sv == null, create a new empty 00288 // empty window and attach the parameters editor to that window (ugly). 00289 ParamsEditor::ParamsEditor(tesseract::Tesseract* tess, 00290 ScrollView* sv) { 00291 if (sv == NULL) { 00292 const char* name = "ParamEditorMAIN"; 00293 sv = new ScrollView(name, 1, 1, 200, 200, 300, 200); 00294 } 00295 00296 sv_window_ = sv; 00297 00298 //Only one event handler per window. 00299 //sv->AddEventHandler((SVEventHandler*) this); 00300 00301 SVMenuNode* svMenuRoot = BuildListOfAllLeaves(tess); 00302 00303 STRING paramfile; 00304 paramfile = tess->datadir; 00305 paramfile += VARDIR; // parameters dir 00306 paramfile += "edited"; // actual name 00307 00308 SVMenuNode* std_menu = svMenuRoot->AddChild ("Build Config File"); 00309 00310 writeCommands[0] = nrParams+1; 00311 std_menu->AddChild("All Parameters", writeCommands[0], 00312 paramfile.string(), "Config file name?"); 00313 00314 writeCommands[1] = nrParams+2; 00315 std_menu->AddChild ("changed_ Parameters Only", writeCommands[1], 00316 paramfile.string(), "Config file name?"); 00317 00318 svMenuRoot->BuildMenu(sv, false); 00319 } 00320 00321 00322 // Write all (changed_) parameters to a config file. 00323 void ParamsEditor::WriteParams(char *filename, 00324 bool changes_only) { 00325 FILE *fp; // input file 00326 char msg_str[255]; 00327 // if file exists 00328 if ((fp = fopen (filename, "rb")) != NULL) { 00329 fclose(fp); 00330 sprintf (msg_str, "Overwrite file " "%s" "? (Y/N)", filename); 00331 int a = sv_window_->ShowYesNoDialog(msg_str); 00332 if (a == 'n') { return; } // dont write 00333 } 00334 00335 00336 fp = fopen (filename, "wb"); // can we write to it? 00337 if (fp == NULL) { 00338 sv_window_->AddMessage("Cant write to file " "%s" "", filename); 00339 return; 00340 } 00341 00342 for (std::map<int, ParamContent*>::iterator iter = vcMap.begin(); 00343 iter != vcMap.end(); 00344 ++iter) { 00345 ParamContent* cur = iter->second; 00346 if (!changes_only || cur->HasChanged()) { 00347 fprintf (fp, "%-25s %-12s # %s\n", 00348 cur->GetName(), cur->GetValue(), cur->GetDescription()); 00349 } 00350 } 00351 fclose(fp); 00352 } 00353 #endif