00001 /*!@file GUI/GeneralGUI.C A utility to create general guis */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00005 // University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: Lior Elazary <elazary@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/GUI/GeneralGUI.C $ 00035 // $Id: GeneralGUI.C 10794 2009-02-08 06:21:09Z itti $ 00036 // 00037 00038 #include "GUI/GeneralGUI.H" 00039 #include "Component/ModelOptionDef.H" 00040 #include "Component/ModelParam.H" 00041 #include "Image/CutPaste.H" 00042 #include "GUI/DebugWin.H" 00043 #include "Media/FrameSeries.H" 00044 #include "Transport/FrameInfo.H" 00045 00046 #include "Util/JobWithSemaphore.H" 00047 #include "Util/StringUtil.H" 00048 #include "Util/WorkThreadServer.H" 00049 #include "Util/sformat.H" 00050 #include "rutz/compat_snprintf.h" 00051 00052 #include <ctype.h> 00053 #include <deque> 00054 #include <iterator> 00055 #include <stdlib.h> // for atoi(), malloc(), free() 00056 #include <string.h> 00057 #include <sys/resource.h> 00058 #include <time.h> 00059 #include <vector> 00060 00061 00062 namespace 00063 { 00064 class GeneralGUILoop : public JobWithSemaphore 00065 { 00066 public: 00067 GeneralGUILoop(GeneralGUI* genGUI) 00068 : 00069 itsGeneralGUI(genGUI), 00070 itsPriority(1), 00071 itsJobType("GUI Loop") 00072 {} 00073 00074 virtual ~GeneralGUILoop() {} 00075 00076 virtual void run() 00077 { 00078 ASSERT(itsGeneralGUI); 00079 while(1) 00080 { 00081 itsGeneralGUI->update(); 00082 usleep(10000); 00083 } 00084 } 00085 00086 virtual const char* jobType() const 00087 { return itsJobType.c_str(); } 00088 00089 virtual int priority() const 00090 { return itsPriority; } 00091 00092 private: 00093 GeneralGUI* itsGeneralGUI; 00094 const int itsPriority; 00095 const std::string itsJobType; 00096 }; 00097 } 00098 00099 00100 00101 00102 00103 // ###################################################################### 00104 GeneralGUI::GeneralGUI(OptionManager& mgr, 00105 const std::string& descrName, 00106 const std::string& tagName, 00107 Dims d): 00108 ModelComponent(mgr, descrName, tagName), 00109 itsPWins(0), 00110 itsWinDims(d), 00111 itsModelComponent(NULL), 00112 itsMeters(0) 00113 00114 { 00115 00116 } 00117 00118 // ###################################################################### 00119 GeneralGUI::~GeneralGUI() 00120 { 00121 for(unsigned int i=0; i<itsPWins.size(); i++) 00122 if (itsPWins[i] != NULL) 00123 delete itsPWins[i]; 00124 } 00125 00126 void GeneralGUI::start2() 00127 { 00128 } 00129 00130 void GeneralGUI::startThread(nub::soft_ref<OutputFrameSeries> &ofs) 00131 { 00132 LINFO("Starting Gui thread"); 00133 //start a worker thread 00134 itsThreadServer.reset(new WorkThreadServer("GuiThread",1)); //start a single worker thread 00135 itsThreadServer->setFlushBeforeStopping(false); 00136 rutz::shared_ptr<GeneralGUILoop> j(new GeneralGUILoop(this)); 00137 itsThreadServer->enqueueJob(j); 00138 00139 itsOfs = ofs; 00140 } 00141 00142 void GeneralGUI::stopThread() 00143 { 00144 for(unsigned int i=0; i<itsPWins.size(); i++) 00145 if (itsPWins[i] != NULL) 00146 delete itsPWins[i]; 00147 //TODO stop threads 00148 00149 } 00150 00151 00152 00153 00154 void GeneralGUI::setupGUI(ModelComponent* comp, bool recurse) 00155 { 00156 PrefsWindow* pWin = new PrefsWindow("Control", SimpleFont::FIXED(8)); 00157 ASSERT(pWin); 00158 pWin->setValueNumChars(16); 00159 pWin->addPrefsForComponent(comp, false); 00160 00161 itsPWins.push_back(pWin); 00162 00163 } 00164 00165 void GeneralGUI::update() 00166 { 00167 for (unsigned int i=0; i<itsPWins.size(); i++) 00168 if (itsPWins[i] != NULL) 00169 itsPWins[i]->update(); // handle pending preference window events 00170 00171 Image<PixRGB<byte> > disp(itsWinDims, ZEROS); 00172 Image<PixRGB<byte> > meters = 00173 makeMeters(2, Dims(disp.getDims().w() / 2, 13)); 00174 inplacePaste(disp, meters, Point2D<int>(0,0)); 00175 00176 for(unsigned int i=0; i<itsImages.size(); i++) { 00177 const size_t ax = i % 2; 00178 const size_t ay = i / 2; 00179 Point2D<int> pasteLoc(Point2D<int>(256*ax, 00180 meters.getHeight()+ (ay * itsImages[i]->getHeight()))); 00181 00182 inplacePaste(disp, *itsImages[i], pasteLoc); 00183 } 00184 00185 itsOfs->writeRGB(disp, "GUIDisplay", 00186 FrameInfo("GeneralGUI Display", SRC_POS)); 00187 00188 00189 } 00190 00191 void GeneralGUI::addMeter(const int* valPtr, const std::string label, 00192 const int valMax, const PixRGB<byte> color) 00193 { 00194 00195 if (valPtr != NULL) 00196 { 00197 const MeterInfo minfo = {valPtr, label, valMax, color}; 00198 itsMeters.push_back(minfo); 00199 } 00200 } 00201 00202 void GeneralGUI::addImage(const Image<PixRGB<byte> > *imgPtr) 00203 { 00204 if (imgPtr != NULL) 00205 itsImages.push_back(imgPtr); 00206 } 00207 00208 00209 00210 Image<PixRGB<byte> > GeneralGUI::makeMeters(const size_t nx, 00211 const Dims& meterdims) 00212 { 00213 if (itsMeters.size() == 0) 00214 return Image<PixRGB<byte> >(); 00215 00216 ASSERT(meterdims.w() > 0); 00217 ASSERT(meterdims.h() > 0); 00218 00219 size_t maxlabelsize = itsMeters[0].label.size(); 00220 for(unsigned int i=0; i<itsMeters.size(); i++) 00221 if (itsMeters[i].label.size() > maxlabelsize) 00222 maxlabelsize = itsMeters[i].label.size(); 00223 00224 const SimpleFont f = SimpleFont::fixedMaxHeight(meterdims.h()); 00225 00226 const int meterx = f.w() * (maxlabelsize + 7); 00227 const int maxmeterlen = meterdims.w() - meterx; 00228 00229 const size_t ny = (itsMeters.size() + nx-1) / nx; 00230 00231 Image<PixRGB<byte> > result(meterdims.w() * nx, meterdims.h() * ny, ZEROS); 00232 00233 for (unsigned int i = 0; i < itsMeters.size(); ++i) 00234 { 00235 const size_t ay = i % ny; 00236 const size_t ax = i / ny; 00237 00238 const std::string txt = 00239 sformat("%*s %i", 00240 int(maxlabelsize), 00241 itsMeters[i].label.c_str(), 00242 *itsMeters[i].valPtr); 00243 00244 writeText(result, Point2D<int>(meterdims.w() * ax, meterdims.h() * ay), 00245 txt.c_str(), 00246 PixRGB<byte>(255), PixRGB<byte>(0), f); 00247 00248 int meterlen = 00249 clampValue(int(maxmeterlen * abs(*itsMeters[i].valPtr) / abs(itsMeters[i].valmax)), 00250 1, maxmeterlen); 00251 //if (itsMeters[i].valmax < 0) meterlen += (maxmeterlen/2); 00252 00253 Image<PixRGB<byte> >::iterator itr = 00254 result.beginw() 00255 + meterdims.w()*ax + meterx + ay*meterdims.h()*result.getWidth(); 00256 00257 const int rowskip = result.getWidth() - maxmeterlen; 00258 00259 const PixRGB<byte> c1(itsMeters[i].color); 00260 const PixRGB<byte> c2(c1/2); 00261 const PixRGB<byte> c3(c2/3); 00262 const PixRGB<byte> c4(c3/2); 00263 00264 for (int y = 0; y < meterdims.h()-1; ++y) 00265 { 00266 for (int x = 0; x < meterlen; ++x) 00267 *itr++ = (x & 1) ? c2 : c1; 00268 for (int x = meterlen; x < maxmeterlen; ++x) 00269 *itr++ = (x & 1) ? c4 : c3; 00270 itr += rowskip; 00271 } 00272 } 00273 00274 return result; 00275 } 00276 00277 00278 00279 // ###################################################################### 00280 /* So things look consistent in everyone's emacs... */ 00281 /* Local Variables: */ 00282 /* indent-tabs-mode: nil */ 00283 /* End: */