QtImageFrame.Q

Go to the documentation of this file.
00001 /*!@file GUI/QtImageFrame.Q */
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005   //
00005 // by the 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: Rob Peters <rjpeters at usc dot edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/GUI/QtImageFrame.Q $
00035 // $Id: QtImageFrame.Q 14314 2010-12-16 00:02:44Z lior $
00036 //
00037 
00038 #ifndef GUI_QTIMAGEFRAME_Q_DEFINED
00039 #define GUI_QTIMAGEFRAME_Q_DEFINED
00040 
00041 #ifdef INVT_HAVE_QT3
00042 
00043 #include "GUI/QtImageFrame.H"
00044 
00045 #include "Image/ColorOps.H"
00046 #include "Image/FilterOps.H"
00047 #include "Image/Image.H"
00048 #include "Image/MathOps.H"
00049 #include "Image/Normalize.H"
00050 #include "Image/Pixels.H"
00051 #include "Image/Range.H"
00052 #include "Image/ShapeOps.H"
00053 #include "QtUtil/ImageConvert.H"
00054 #include "Raster/GenericFrame.H"
00055 #include "Raster/Raster.H"
00056 #include "Transport/FrameInfo.H"
00057 #include "Util/MathFunctions.H"
00058 #include "Util/sformat.H"
00059 #include "rutz/demangle.h"
00060 #include "rutz/trace.h"
00061 
00062 #include <qerrormessage.h>
00063 #include <qfiledialog.h>
00064 #include <qlabel.h>
00065 #include <qpushbutton.h>
00066 #include <qspinbox.h>
00067 #include <typeinfo>
00068 
00069 namespace
00070 {
00071   const int MAXZOOM = 6;
00072   const int MINZOOM = -6;
00073 
00074   // escape any characters from the given string so that it will
00075   // render cleanly as Qt::RichText
00076   static std::string richTextEncode(const std::string& s)
00077   {
00078     std::string result;
00079 
00080     for (std::string::size_type i = 0; i < s.size(); ++i)
00081       {
00082         switch (s[i])
00083           {
00084           case '<': result += "&lt;"; break;
00085           default:  result += s[i];   break;
00086           }
00087       }
00088 
00089     return result;
00090   }
00091 
00092   static std::string buildTitle(const GenericFrame& img,
00093                                 const std::string& title,
00094                                 const int frameNumber,
00095                                 const FrameInfo& auxinfo)
00096   {
00097     std::string result;
00098 
00099     if (auxinfo.description.length() > 0)
00100       result += sformat("<b>%s</b>", auxinfo.description.c_str());
00101 
00102     result += "<br>";
00103 
00104     result +=
00105       sformat("<b>%s</b> [frame #%06d]"
00106               "<br><i>%dx%d %s</i>",
00107               title.c_str(), frameNumber,
00108               img.getDims().w(), img.getDims().h(),
00109               richTextEncode(img.nativeTypeName()).c_str());
00110 
00111     result += "<br>";
00112 
00113     if (auxinfo.srcpos.m_file_name != 0)
00114       result += sformat("from %s:%d",
00115                         auxinfo.srcpos.m_file_name,
00116                         auxinfo.srcpos.m_line_no);
00117 
00118     result += "<br>";
00119 
00120     if (img.nativeType() == GenericFrame::GRAY_F32)
00121       {
00122         Range<float> r = rangeOf(img.asFloat());
00123         result += sformat("range=[%g .. %g]", r.min(), r.max());
00124       }
00125     else if (img.nativeType() == GenericFrame::RGB_F32)
00126       {
00127         float mi, ma;
00128         getMinMaxC(img.asRgbF32(), mi, ma);
00129         result += sformat("range=[%g .. %g]", mi, ma);
00130       }
00131 
00132     return result;
00133   }
00134 }
00135 
00136 struct QtImageFrame::Impl
00137 {
00138   Impl()
00139     :
00140     title(0),
00141     zoom(0),
00142     frame(0),
00143     genFrame(),
00144     titlestring(),
00145     preferredDims(),
00146     preferredMaxDims(),
00147     doInitialDims(true),
00148     isUpdated(false)
00149   {}
00150 
00151   QLabel* title;
00152   QSpinBox* zoom;
00153   QFrame* frame;
00154 
00155   GenericFrame genFrame;
00156   std::string shortname;
00157   std::string titlestring;
00158   Dims preferredDims;
00159   Dims preferredMaxDims;
00160   bool doInitialDims;
00161 
00162   bool isUpdated;
00163 
00164   Dims rawDims() const
00165   {
00166     return this->genFrame.getDims();
00167   }
00168 
00169   Dims scaledDims() const
00170   {
00171     const Dims raw = this->rawDims();
00172 
00173     if (raw.isEmpty())
00174       return raw;
00175 
00176     else if (this->zoom->value() >= 0)
00177       return Dims(raw.w() << this->zoom->value(),
00178                   raw.h() << this->zoom->value());
00179 
00180     // else...
00181     return Dims(raw.w() >> -(this->zoom->value()),
00182                 raw.h() >> -(this->zoom->value()));
00183   }
00184 
00185   void setInitialDims()
00186   {
00187     if (this->doInitialDims)
00188       {
00189         if (this->preferredDims.isNonEmpty())
00190           {
00191             Dims dims = this->scaledDims();
00192 
00193             while (dims.w() < this->preferredDims.w() &&
00194                    dims.h() < this->preferredDims.h() &&
00195                    this->zoom->value() < this->zoom->maxValue())
00196               {
00197                 this->zoom->blockSignals(true);
00198                 this->zoom->stepUp();
00199                 this->zoom->blockSignals(false);
00200                 dims = this->scaledDims();
00201               }
00202           }
00203 
00204         if (this->preferredMaxDims.isNonEmpty())
00205           {
00206             Dims dims = this->scaledDims();
00207 
00208             while (dims.w() > this->preferredMaxDims.w() ||
00209                    dims.h() > this->preferredMaxDims.h())
00210               {
00211                 this->zoom->blockSignals(true);
00212                 this->zoom->stepDown();
00213                 this->zoom->blockSignals(false);
00214                 dims = this->scaledDims();
00215               }
00216           }
00217 
00218         this->doInitialDims = false;
00219       }
00220   }
00221 
00222   void updateSize()
00223   {
00224     this->setInitialDims();
00225 
00226     const Dims dims = this->scaledDims();
00227 
00228     if (dims.isNonEmpty())
00229       this->frame->setFixedSize(dims.w(), dims.h());
00230   }
00231 
00232   template <class T>
00233   Image<T> scaleImage(const Image<T>& img)
00234   {
00235     if (this->zoom->value() >= 0)
00236       return zoomXY(img, (1 << this->zoom->value()), (1 << this->zoom->value()));
00237     else
00238       {
00239         Image<T> result = img;
00240         for (int i = 0; i < -this->zoom->value(); ++i)
00241           result = decXY(lowPass3(result));
00242         return result;
00243       }
00244   }
00245 
00246   void update()
00247   {
00248     if (this->isUpdated)
00249       return;
00250 
00251     GVX_TRACE(__PRETTY_FUNCTION__);
00252 
00253     this->setInitialDims();
00254 
00255     QPixmap pixmap;
00256 
00257     switch (this->genFrame.nativeType())
00258       {
00259       case GenericFrame::NONE:
00260         break;
00261 
00262       case GenericFrame::RGB_U8:
00263       case GenericFrame::RGB_F32:
00264       case GenericFrame::VIDEO:
00265         pixmap = convertToQPixmap(scaleImage(this->genFrame.asRgbU8()));
00266         break;
00267 
00268       case GenericFrame::GRAY_U8:
00269       case GenericFrame::GRAY_F32:
00270         pixmap = convertToQPixmap(scaleImage(this->genFrame.asGrayU8()));
00271         break;
00272 
00273       case GenericFrame::RGB_U16:
00274         break;
00275       case GenericFrame::GRAY_U16:
00276         break;
00277       case GenericFrame::RGBD:
00278         break;
00279       }
00280 
00281     this->title->setText(titlestring.c_str());
00282     this->title->setTextFormat(Qt::RichText);
00283     this->title->setAlignment(Qt::AlignAuto | Qt::AlignVCenter |
00284                               ExpandTabs | Qt::SingleLine);
00285     this->frame->setPaletteBackgroundPixmap(pixmap);
00286 
00287     this->updateSize();
00288 
00289     this->isUpdated = true;
00290   }
00291 };
00292 
00293 QtImageFrame::QtImageFrame(QWidget* parent, const Dims& preferredDims,
00294                            const Dims& preferredMaxDims)
00295   :
00296   QVBox(parent, "QtImageFrame", (WFlags) 0),
00297   rep(new Impl)
00298 {
00299   this->setFrameShape(QFrame::Panel);
00300   this->setFrameShadow(QFrame::Sunken);
00301   this->setLineWidth(2);
00302   this->setMargin(2);
00303 
00304   rep->preferredDims = preferredDims;
00305   rep->preferredMaxDims = preferredMaxDims;
00306 
00307   QVBox* header = new QVBox(this);
00308   rep->title = new QLabel(header);
00309   QHBox* spingroup = new QHBox(header);
00310   QLabel* spinlabel = new QLabel("zoom:", spingroup);
00311   rep->zoom = new QSpinBox(MINZOOM, MAXZOOM, 1, spingroup);
00312   rep->zoom->setButtonSymbols(QSpinBox::PlusMinus);
00313   rep->zoom->setValue(0);
00314   rep->zoom->setPrefix("pow(2, ");
00315   rep->zoom->setSuffix(")");
00316   QFrame* hdummy = new QFrame(spingroup);
00317   spingroup->setStretchFactor(spinlabel, 0);
00318   spingroup->setStretchFactor(rep->zoom, 0);
00319   spingroup->setStretchFactor(hdummy, 1);
00320   spingroup->setSpacing(4);
00321 
00322   header->setStretchFactor(rep->title, 0);
00323   header->setStretchFactor(spingroup, 0);
00324   header->setSpacing(4);
00325 
00326   QHBox* buttons = new QHBox(this);
00327   QPushButton* savebutton = new QPushButton(buttons);
00328   savebutton->setText("Save this image");
00329   QFrame* hspacer = new QFrame(buttons);
00330   buttons->setStretchFactor(savebutton, 0);
00331   buttons->setStretchFactor(hspacer, 1);
00332 
00333   this->connect(savebutton, SIGNAL(clicked()),
00334                 this, SLOT(saveImage()));
00335 
00336   QFrame* hline = new QFrame(this);
00337   rep->frame = new QFrame(this);
00338   QFrame* vdummy = new QFrame(this);
00339 
00340   hline->setFrameShape(QFrame::HLine);
00341   hline->setFrameShadow(QFrame::Raised);
00342   hline->setLineWidth(2);
00343 
00344   this->setStretchFactor(header, 0);
00345   this->setStretchFactor(buttons, 0);
00346   this->setStretchFactor(hline, 0);
00347   this->setStretchFactor(vdummy, 1);
00348   this->setSpacing(4);
00349 
00350   this->connect(rep->zoom, SIGNAL(valueChanged(int)),
00351                 this, SLOT(setZoom(int)));
00352 }
00353 
00354 QtImageFrame::~QtImageFrame()
00355 {
00356   delete rep;
00357 }
00358 
00359 void QtImageFrame::setFrame(const GenericFrame& frame,
00360                             const std::string& title,
00361                             const int frameNumber,
00362                             const FrameInfo& auxinfo)
00363 {
00364   rep->genFrame = frame;
00365   rep->genFrame.setFloatFlags(frame.floatFlags() | FLOAT_NORM_0_255);
00366 
00367   rep->shortname = sformat("%s%06d", title.c_str(), frameNumber);
00368   rep->titlestring = buildTitle(frame, title, frameNumber, auxinfo);
00369 
00370   rep->isUpdated = false;
00371 
00372   if (this->isVisible())
00373     rep->update();
00374   else
00375     rep->updateSize();
00376 }
00377 
00378 void QtImageFrame::setZoom(int z)
00379 {
00380   rep->isUpdated = false;
00381 
00382   if (this->isVisible())
00383     rep->update();
00384 }
00385 
00386 void QtImageFrame::saveImage()
00387 {
00388   QString s = QFileDialog::getSaveFileName
00389     (sformat("./%s.png", rep->shortname.c_str()),
00390      QString::null, /* e.g., "Images (*.png *.xpm *.jpg)" */
00391      this,
00392      "save file dialog",
00393      "Choose a filename to save under");
00394 
00395   if (!s.isEmpty())
00396     {
00397       try
00398         {
00399           Raster::WriteFrame(rep->genFrame, s);
00400         }
00401       catch (std::exception& e)
00402         {
00403           QErrorMessage* dlg = new QErrorMessage(this);
00404           dlg->message(e.what());
00405         }
00406     }
00407 }
00408 
00409 void QtImageFrame::showEvent(QShowEvent* event)
00410 {
00411   rep->update();
00412 }
00413 
00414 #endif // INVT_HAVE_QT3
00415 
00416 // ######################################################################
00417 /* So things look consistent in everyone's emacs... */
00418 /* Local Variables: */
00419 /* mode: c++ */
00420 /* indent-tabs-mode: nil */
00421 /* End: */
00422 
00423 #endif // GUI_QTIMAGEFRAME_Q_DEFINED
Generated on Sun May 8 08:40:41 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3