QtImageFrame.qt.C

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