src/qvgui/qvcanvas.cpp

Go to the documentation of this file.
00001 /*
00002  *      Copyright (C) 2007, 2008. PARP Research Group.
00003  *      <http://perception.inf.um.es>
00004  *      University of Murcia, Spain.
00005  *
00006  *      This file is part of the QVision library.
00007  *
00008  *      QVision is free software: you can redistribute it and/or modify
00009  *      it under the terms of the GNU Lesser General Public License as
00010  *      published by the Free Software Foundation, version 3 of the License.
00011  *
00012  *      QVision is distributed in the hope that it will be useful,
00013  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  *      GNU Lesser General Public License for more details.
00016  *
00017  *      You should have received a copy of the GNU Lesser General Public
00018  *      License along with QVision. If not, see <http://www.gnu.org/licenses/>.
00019  */
00020 
00024 
00025 #include <math.h>
00026 #include <iostream>
00027 
00028 #include <QMouseEvent>
00029 #include <QPainter>
00030 #include <QScrollArea>
00031 #include <QScrollBar>
00032 #include <QGLWidget>
00033 #include <QToolButton>
00034 #include <QStatusBar>
00035 #include <QHBoxLayout>
00036 #include <QGridLayout>
00037 
00038 #include <qwt_scale_widget.h>
00039 #include <qwt_scale_engine.h>
00040 #include <qwt_scale_div.h>
00041 #include <math.h>
00042 
00043 #include <QVImage>
00044 #include <qvgui/qvcanvas.h>
00045 
00046 void QVPainter::drawQVImage(QVGenericImage *image,bool adaptSize,float low,float high)
00047 {
00048         imageArea->drawQVImage(image,adaptSize,low,high);
00049 }
00050 
00051 
00052 void QVPainter::drawTextUnscaled(const QPointF & position, const QString & text)
00053 {
00054         save();
00055         resetMatrix();
00056         translate(-imageArea->topLeft);
00057         drawText(imageArea->zoom*position,text);
00058         restore();
00059 }
00060 
00061 void QVPainter::drawTextUnscaled(const QPoint & position, const QString & text)
00062 {
00063         save();
00064         resetMatrix();
00065         translate(-imageArea->topLeft);
00066         drawText(imageArea->zoom*position,text);
00067         restore();
00068 }
00069 
00070 void QVPainter::drawTextUnscaled(const QRectF & rectangle, int flags,
00071                                           const QString & text, QRectF * boundingRect)
00072 {
00073         save();
00074         resetMatrix();
00075         translate(-imageArea->topLeft);
00076         drawText(QRectF(imageArea->zoom*rectangle.topLeft(),
00077                                     imageArea->zoom*rectangle.size()),flags,text,boundingRect);
00078         if(boundingRect != 0)
00079                 *boundingRect = QRectF(imageArea->zoom*boundingRect->topLeft(),
00080                                                            imageArea->zoom*boundingRect->size());
00081         restore();
00082 }
00083 
00084 void QVPainter::drawTextUnscaled(const QRect & rectangle, int flags,
00085                                           const QString & text, QRect * boundingRect)
00086 {
00087         save();
00088         resetMatrix();
00089         translate(-imageArea->topLeft);
00090         drawText(QRect(imageArea->zoom*rectangle.topLeft(),
00091                                    imageArea->zoom*rectangle.size()),flags,text,boundingRect);
00092         if(boundingRect != 0)
00093                 *boundingRect = QRect(imageArea->zoom*boundingRect->topLeft(),
00094                                                           imageArea->zoom*boundingRect->size());
00095         restore();
00096 }
00097 
00098 void QVPainter::drawTextUnscaled(int x, int y, const QString & text)
00099 {
00100         save();
00101         resetMatrix();
00102         translate(-imageArea->topLeft);
00103         drawText(imageArea->zoom*x,imageArea->zoom*y,text);
00104         restore();
00105 }
00106 
00107 void QVPainter::drawTextUnscaled(int x, int y, int width, int height, int flags,
00108                                           const QString & text, QRect * boundingRect)
00109 {
00110         save();
00111         resetMatrix();
00112         translate(-imageArea->topLeft);
00113         drawText(imageArea->zoom*x,imageArea->zoom*y,imageArea->zoom*width,
00114                          imageArea->zoom*height,flags,text,boundingRect);
00115         if(boundingRect != 0)
00116                 *boundingRect = QRect(imageArea->zoom*boundingRect->topLeft(),
00117                                                           imageArea->zoom*boundingRect->size());
00118         restore();
00119 }
00120 
00121 void QVPainter::drawTextUnscaled(const QRectF & rectangle, const QString & text,
00122                                           const QTextOption & option)
00123 {
00124         save();
00125         resetMatrix();
00126         translate(-imageArea->topLeft);
00127         drawText(QRectF(imageArea->zoom*rectangle.topLeft(),
00128                                     imageArea->zoom*rectangle.size()),text,option);
00129         restore();
00130 }
00131 
00132 
00133 void QVImageArea::initObject(int w, int h)
00134 {
00135         zoom = 1;
00136         origwidth = w;
00137         origheight = h;
00138         topLeft = QPoint(0,0);
00139         selRect = QRect();
00140         zoomRect = QRect();
00141         setAttribute(Qt::WA_NoSystemBackground);
00142         setMouseTracking(TRUE);
00143         setMinimumSize(qMin(w,max_zoom),qMin(h,max_zoom));
00144         setMaximumSize(w,h);
00145         resize(w,h);
00146         mouseMode = NONE;
00147         polyMode = LINE;
00148         dragging = FALSE;
00149         emit newGeometry(origwidth,origheight,topLeft.x(),topLeft.y(),width(),height(),zoom);
00150 }
00151 
00152 QVImageArea::QVImageArea(int w, int h,QWidget *parent)
00153         : QGLWidget(QGLFormat(QGL::DoubleBuffer|QGL::NoDepthBuffer|
00154                 QGL::DirectRendering|QGL::HasOverlay), parent), max_zoom(128)
00155 {
00156         initObject(w,h);
00157 }
00158 
00159 QVImageArea::QVImageArea(int w, int h,QWidget *parent,QGLWidget *other)
00160         : QGLWidget(parent,other), max_zoom(128)
00161 {
00162         initObject(w,h);
00163 }
00164 
00165 QList<QVImageArea::QVImageArea *> image_areas;
00166 
00167 void QVImageArea::centerZoom(int zoom)
00168 {
00169         if((zoom != this->zoom) and (zoom >= 1) and (zoom <= max_zoom)) {
00170                 int old_zoom = this->zoom;
00171                 this->zoom = zoom;
00172                 setMaximumSize(zoom*origwidth,zoom*origheight);
00173                 QPoint newTopLeft = zoom*(topLeft+QPoint(width(),height())/2)/old_zoom
00174                                                         - QPoint(width(),height())/2;
00175                 if(newTopLeft.x() < 0)
00176                         newTopLeft.setX(0);
00177                 if(newTopLeft.y() < 0)
00178                         newTopLeft.setY(0);
00179                 if(newTopLeft.x()+width() > origwidth*zoom)
00180                         newTopLeft.setX(origwidth*zoom-width());
00181                 if(newTopLeft.y()+height() > origheight*zoom)
00182                         newTopLeft.setY(origheight*zoom-height());
00183                 topLeft = newTopLeft;
00184                 update();
00185                 emit newGeometry(origwidth,origheight,topLeft.x(),topLeft.y(),width(),height(),zoom);
00186         }
00187 }
00188 
00189 void QVImageArea::resizeGL(int width, int height)
00190 {
00191         QPoint newTopLeft = topLeft,newBottomRight = topLeft+QPoint(width,height);
00192         if(newBottomRight.x() > origwidth*zoom)
00193                 newTopLeft.setX(origwidth*zoom-width);
00194         if(newBottomRight.y() > origheight*zoom)
00195                 newTopLeft.setY(origheight*zoom-height);
00196         topLeft = newTopLeft;
00197         update();
00198         emit newGeometry(origwidth,origheight,topLeft.x(),topLeft.y(),width,height,zoom);
00199 }
00200 
00201 
00202 void QVImageArea::wheelEvent(QWheelEvent *event)
00203 {
00204     if (event->delta() > 0) {
00205                 centerZoom(2*zoom);
00206         } else {
00207                 centerZoom(zoom/2);
00208         }
00209 }
00210 
00211 // Auxiliary function to draw rects that draw themselves "intuitively" at the
00212 // borders:
00213 QRectF QVImageArea::intuitiveRect(QRect rect)
00214 {
00215         return QRectF(rect.x(),rect.y()+1.0/zoom,
00216                                   rect.width()-1.0/zoom,rect.height()-1.0/zoom);
00217 }
00218 
00219 
00220 QRect QVImageArea::innerRect()
00221 {
00222         QPoint q1(static_cast<int>(ceilf(static_cast<float>(topLeft.x())/zoom)),
00223                                 static_cast<int>(ceilf(static_cast<float>(topLeft.y())/zoom))),
00224                         q2(static_cast<int>(floor(static_cast<float>((topLeft.x()+width()))/zoom)-1),
00225                                 (static_cast<int>(floor(static_cast<float>(topLeft.y()+height()))/zoom))-1);
00226         return QRect(q1,q2);
00227 }
00228 
00229 QRect QVImageArea::outerRect()
00230 {
00231         QPoint q1(static_cast<int>(ceilf(static_cast<float>(topLeft.x())/zoom)-1),
00232                                 static_cast<int>(ceilf(static_cast<float>(topLeft.y())/zoom))-1),
00233                    q2(static_cast<int>(floor(static_cast<float>((topLeft.x()+width()))/zoom)),
00234                                 (static_cast<int>(floor(static_cast<float>(topLeft.y()+height()))/zoom)));
00235 
00236         return QRect(q1,q2) & QRect(0,0,origwidth,origheight);
00237 }
00238 
00239 void QVImageArea::paintEvent(QPaintEvent *event)
00240 {
00241         Q_UNUSED(event);
00242 
00243         painter = new QVPainter(this);
00244 
00245         painter->begin(this);
00246         //painter->setRenderHint(QPainter::TextAntialiasing);
00247 
00248         painter->setViewport(0,0,width(),height());
00249         painter->resetMatrix();
00250         painter->translate(-topLeft);
00251         painter->scale(zoom,zoom);
00252 
00253         // Now we call the user painting function:
00254         QVCanvas *image_viewer = qobject_cast<QVCanvas *>(parent());
00255         if(image_viewer == 0) {
00256                 qFatal("Error interno de QVision: El padre de una QVImageArea debería ser un QVCanvas");
00257         } else {
00258                 glClearColor(0,0,1,0);
00259                 glClear(GL_COLOR_BUFFER_BIT); // Blue background
00260                 image_viewer->viewer();
00261         }
00262 
00263         // Now, we render the selection (red) and zoom (blue) rectangles:
00264         if(selRect != QRect()) {
00265                 painter->setPen(QColor(Qt::red));
00266                 // Dirty trick for more intuitive behaviour of rectangle in the borders
00267                 // of the window:
00268                 painter->drawRect(intuitiveRect(selRect));
00269         }
00270         if(zoomRect != QRect()) {
00271                 painter->setPen(QColor(Qt::blue));
00272                 // Dirty trick for more intuitive behaviour of rectangle in the borders
00273                 // of the window:
00274                 painter->drawRect(intuitiveRect(zoomRect));
00275         }
00276 
00277         // Finally, if zoom is big enough, draw numbers with pixel values:
00278         if(zoom >= 32) {
00279                 painter->setPen(QColor(Qt::green));
00280                 QRect outer = outerRect();
00281                 for(int j=outer.y();j<outer.y()+outer.height();j++) {
00282                         for(int i=outer.x();i<outer.x()+outer.width();i++) {
00283                                 if(not imageList.isEmpty()) {
00284                                         QString value_string;
00285                                         int k;
00286                                         for(k=0;k<imageList.size();k++) {
00287                                                 QRect img_rect = QRect(imageList[k]->getAnchor()+imageList[k]->getROI().topLeft(),
00288                                                           QSize(imageList[k]->getROI().width(),imageList[k]->getROI().height()));       
00289                                                 if(i>=img_rect.left() and i<=img_rect.right() and j>=img_rect.top() and j<=img_rect.bottom()) {
00290                                                         //value_string = QString("-%1-").arg(k);
00292                                                         if(imageList[k]->isCompatibleWith("QVImage<uChar,1>")) {
00293                                                                 if(zoom >= 64) {
00294                                                                         value_string =  QString("%1").arg((*(QVImage<uChar,1>*)imageList[k])(i-img_rect.topLeft().x()+imageList[k]->getROI().topLeft().x(),j-img_rect.topLeft().y()+imageList[k]->getROI().topLeft().y()));
00295                                                                 }
00296                                                         }
00297                                                         else if(imageList[k]->isCompatibleWith("QVImage<uShort,1>")) {
00298                                                                 if(zoom >= 64) {
00299                                                                         value_string =  QString("%1").arg((*(QVImage<uShort,1>*)imageList[k])(i-img_rect.topLeft().x()+imageList[k]->getROI().topLeft().x(),j-img_rect.topLeft().y()+imageList[k]->getROI().topLeft().y()));
00300                                                                 }
00301                                                         }
00302                                                         else if(imageList[k]->isCompatibleWith("QVImage<sShort,1>")) {
00303                                                                 if(zoom >= 64) {
00304                                                                         value_string =  QString("%1").arg((*(QVImage<sShort,1>*)imageList[k])(i-img_rect.topLeft().x()+imageList[k]->getROI().topLeft().x(),j-img_rect.topLeft().y()+imageList[k]->getROI().topLeft().y()));
00305                                                                 }
00306                                                         }
00307                                                         else if(imageList[k]->isCompatibleWith("QVImage<sInt,1>")) {
00308                                                                 if(zoom >= 64) {
00309                                                                         value_string =  QString("%1").arg((*(QVImage<sInt,1>*)imageList[k])(i-img_rect.topLeft().x()+imageList[k]->getROI().topLeft().x(),j-img_rect.topLeft().y()+imageList[k]->getROI().topLeft().y()));
00310                                                                 }
00311                                                         }
00312                                                         else if(imageList[k]->isCompatibleWith("QVImage<sFloat,1>")) {
00313                                                                 if(zoom >= 64) {
00314                                                                         value_string =  QString("%1").arg((*(QVImage<sFloat,1>*)imageList[k])(i-img_rect.topLeft().x()+imageList[k]->getROI().topLeft().x(),j-img_rect.topLeft().y()+imageList[k]->getROI().topLeft().y()));
00315                                                                 }
00316                                                         }
00317                                                         else if(imageList[k]->isCompatibleWith("QVImage<uChar,3>")) {
00318                                                                 int red,green,blue;
00319                                                                 if(zoom >= 64) {
00320                                                                         red = (*(QVImage<uChar,3>*)imageList[k])(i-img_rect.topLeft().x()+imageList[k]->getROI().topLeft().x(),j-img_rect.topLeft().y()+imageList[k]->getROI().topLeft().y(),0);
00321                                                                         green = (*(QVImage<uChar,3>*)imageList[k])(i-img_rect.topLeft().x()+imageList[k]->getROI().topLeft().x(),j-img_rect.topLeft().y()+imageList[k]->getROI().topLeft().y(),1);
00322                                                                         blue = (*(QVImage<uChar,3>*)imageList[k])(i-img_rect.topLeft().x()+imageList[k]->getROI().topLeft().x(),j-img_rect.topLeft().y()+imageList[k]->getROI().topLeft().y(),2);
00323                                                                         value_string =  QString("R:%1\nG:%2\nB:%3").arg(red).arg(green).arg(blue);
00324                                                                 }
00325                                                         }
00326                                                         else if(imageList[k]->isCompatibleWith("QVImage<uShort,3>")) {
00327                                                                 int red,green,blue;
00328                                                                 if(zoom >= 64) {
00329                                                                         red = (*(QVImage<uShort,3>*)imageList[k])(i-img_rect.topLeft().x()+imageList[k]->getROI().topLeft().x(),j-img_rect.topLeft().y()+imageList[k]->getROI().topLeft().y(),0);
00330                                                                         green = (*(QVImage<uShort,3>*)imageList[k])(i-img_rect.topLeft().x()+imageList[k]->getROI().topLeft().x(),j-img_rect.topLeft().y()+imageList[k]->getROI().topLeft().y(),1);
00331                                                                         blue = (*(QVImage<uShort,3>*)imageList[k])(i-img_rect.topLeft().x()+imageList[k]->getROI().topLeft().x(),j-img_rect.topLeft().y()+imageList[k]->getROI().topLeft().y(),2);
00332                                                                         value_string =  QString("R:%1\nG:%2\nB:%3").arg(red).arg(green).arg(blue);
00333                                                                 }
00334                                                         }
00335                                                         else if(imageList[k]->isCompatibleWith("QVImage<sShort,3>")) {
00336                                                                 int red,green,blue;
00337                                                                 if(zoom >= 64) {
00338                                                                         red = (*(QVImage<sShort,3>*)imageList[k])(i-img_rect.topLeft().x()+imageList[k]->getROI().topLeft().x(),j-img_rect.topLeft().y()+imageList[k]->getROI().topLeft().y(),0);
00339                                                                         green = (*(QVImage<sShort,3>*)imageList[k])(i-img_rect.topLeft().x()+imageList[k]->getROI().topLeft().x(),j-img_rect.topLeft().y()+imageList[k]->getROI().topLeft().y(),1);
00340                                                                         blue = (*(QVImage<sShort,3>*)imageList[k])(i-img_rect.topLeft().x()+imageList[k]->getROI().topLeft().x(),j-img_rect.topLeft().y()+imageList[k]->getROI().topLeft().y(),2);
00341                                                                         value_string =  QString("R:%1\nG:%2\nB:%3").arg(red).arg(green).arg(blue);
00342                                                                 }
00343                                                         }
00344                                                         else if(imageList[k]->isCompatibleWith("QVImage<sInt,3>")) {
00345                                                                 int red,green,blue;
00346                                                                 if(zoom >= 64) {
00347                                                                         red = (*(QVImage<sInt,3>*)imageList[k])(i-img_rect.topLeft().x()+imageList[k]->getROI().topLeft().x(),j-img_rect.topLeft().y()+imageList[k]->getROI().topLeft().y(),0);
00348                                                                         green = (*(QVImage<sInt,3>*)imageList[k])(i-img_rect.topLeft().x()+imageList[k]->getROI().topLeft().x(),j-img_rect.topLeft().y()+imageList[k]->getROI().topLeft().y(),1);
00349                                                                         blue = (*(QVImage<sInt,3>*)imageList[k])(i-img_rect.topLeft().x()+imageList[k]->getROI().topLeft().x(),j-img_rect.topLeft().y()+imageList[k]->getROI().topLeft().y(),2);
00350                                                                         value_string =  QString("R:%1\nG:%2\nB:%3").arg(red).arg(green).arg(blue);
00351                                                                 }
00352                                                         }
00353                                                         else if(imageList[k]->isCompatibleWith("QVImage<sFloat,3>")) {
00354                                                                 float red,green,blue;
00355                                                                 if(zoom >= 64) {
00356                                                                         red = (*(QVImage<sFloat,3>*)imageList[k])(i-img_rect.topLeft().x()+imageList[k]->getROI().topLeft().x(),j-img_rect.topLeft().y()+imageList[k]->getROI().topLeft().y(),0);
00357                                                                         green = (*(QVImage<sFloat,3>*)imageList[k])(i-img_rect.topLeft().x()+imageList[k]->getROI().topLeft().x(),j-img_rect.topLeft().y()+imageList[k]->getROI().topLeft().y(),1);
00358                                                                         blue = (*(QVImage<sFloat,3>*)imageList[k])(i-img_rect.topLeft().x()+imageList[k]->getROI().topLeft().x(),j-img_rect.topLeft().y()+imageList[k]->getROI().topLeft().y(),2);
00359                                                                         value_string =  QString("R:%1\nG:%2\nB:%3").arg(red).arg(green).arg(blue);
00360                                                                 }
00361                                                         }
00362                                                         else {
00363                                                                 // alternate code for that type of image ...
00364                                                                 qFatal("Type of QVGenericImage still not supported in paintEvent");
00365                                                         }
00366                                                         break;
00367                                                 }
00368                                         }
00369                                         if(k==imageList.size()) {
00370                                                 value_string = QString("X");
00371                                         }
00372 
00373                                         /* Alternative 1 (renderText):
00374                                         renderText((i*zoom-topLeft.x()), ((j+1)*zoom-topLeft.y()),
00375                                                            value_string);*/
00376 
00377                                         /* Alternative 2 (drawText with painter manipulation):*/
00378                                         /*painter->resetMatrix();
00379                                         painter->translate(-topLeft);
00380                                         painter->drawText(
00381                                                 QRect(zoom*QPoint(i,j),zoom*QPoint(i+1,j+1)),
00382                                                                   Qt::AlignCenter|Qt::TextDontClip,value_string);
00383                                         painter->scale(zoom,zoom);*/
00384 
00385                                         /* Alternative 3 (drawTextUnscaled, with QRectF):*/
00386                                         /*painter->drawTextUnscaled(
00387                                                 QRectF(QPointF(i,j),QSize(1,1)),
00388                                                           Qt::AlignCenter|Qt::TextDontClip,value_string);*/
00389 
00390                                         /* Alternative 4 (drawTextUnscaled, with QRect): */
00391                                         // OJO, (!) error de QT (poco importante) en construcción de
00392                                         // rectangulos del tipo QRect(QPoint(x,y),QPoint(x+1,y+1)).
00393                                         painter->drawTextUnscaled(
00394                                                 QRect(QPoint(i,j),QSize(1,1)),
00395                                                           Qt::AlignCenter|Qt::TextDontClip,value_string);
00396                                 }
00397                         }
00398                 }
00399         }
00400 
00401         // End of painting:
00402         painter->end();
00403         delete painter;
00404 
00405         //imageList.clear();
00406         while (!imageList.isEmpty())
00407          delete imageList.takeFirst();
00408 }
00409 
00410 void QVImageArea::resizeImageArea(int w,int h)
00411 {
00412         if(w != origwidth or h != origheight) {
00413                 zoom = 1;
00414                 origwidth = w;
00415                 origheight = h;
00416                 topLeft = QPoint(0,0);
00417                 selRect = QRect();
00418                 zoomRect = QRect();
00419                 setMinimumSize(qMin(w,max_zoom),qMin(h,max_zoom));
00420                 setMaximumSize(w,h);
00421                 resize(w,h);
00422                 emit newGeometry(origwidth,origheight,topLeft.x(),topLeft.y(),width(),height(),zoom);
00423         }
00424 }
00425 
00426 void QVImageArea::drawQVImage(QVGenericImage *image,bool adaptSize,float low, float high)
00427 {
00428 
00429         QVGenericImage *imagecopy=NULL;
00430         if(image->isCompatibleWith("QVImage<uChar,1>")) {
00431                 imagecopy = new QVImage<uChar,1>;
00432                 *(dynamic_cast<QVImage<uChar,1>*>(imagecopy)) = *(dynamic_cast<QVImage<uChar,1>*>(image));
00433         }
00434         else if(image->isCompatibleWith("QVImage<uShort,1>")) {
00435                 imagecopy = new QVImage<uShort,1>;
00436                 *(dynamic_cast<QVImage<uShort,1>*>(imagecopy)) = *(dynamic_cast<QVImage<uShort,1>*>(image));
00437         }
00438         else if(image->isCompatibleWith("QVImage<sShort,1>")) {
00439                 imagecopy = new QVImage<sShort,1>;
00440                 *(dynamic_cast<QVImage<sShort,1>*>(imagecopy)) = *(dynamic_cast<QVImage<sShort,1>*>(image));
00441         }
00442         else if(image->isCompatibleWith("QVImage<sInt,1>")) {
00443                 imagecopy = new QVImage<sInt,1>;
00444                 *(dynamic_cast<QVImage<sInt,1>*>(imagecopy)) = *(dynamic_cast<QVImage<sInt,1>*>(image));
00445         }
00446         else if(image->isCompatibleWith("QVImage<sFloat,1>")) {
00447                 imagecopy = new QVImage<sFloat,1>;
00448                 *(dynamic_cast<QVImage<sFloat,1>*>(imagecopy)) = *(dynamic_cast<QVImage<sFloat,1>*>(image));
00449         }
00450         else if(image->isCompatibleWith("QVImage<uChar,3>")) {
00451                 imagecopy = new QVImage<uChar,3>;
00452                 *(dynamic_cast<QVImage<uChar,3>*>(imagecopy)) = *(dynamic_cast<QVImage<uChar,3>*>(image));
00453         }
00454         else if(image->isCompatibleWith("QVImage<uShort,3>")) {
00455                 imagecopy = new QVImage<uShort,3>;
00456                 *(dynamic_cast<QVImage<uShort,3>*>(imagecopy)) = *(dynamic_cast<QVImage<uShort,3>*>(image));
00457         }
00458         else if(image->isCompatibleWith("QVImage<sShort,3>")) {
00459                 imagecopy = new QVImage<sShort,3>;
00460                 *(dynamic_cast<QVImage<sShort,3>*>(imagecopy)) = *(dynamic_cast<QVImage<sShort,3>*>(image));
00461         }
00462         else if(image->isCompatibleWith("QVImage<sInt,3>")) {
00463                 imagecopy = new QVImage<sInt,3>;
00464                 *(dynamic_cast<QVImage<sInt,3>*>(imagecopy)) = *(dynamic_cast<QVImage<sInt,3>*>(image));
00465         }
00466         else if(image->isCompatibleWith("QVImage<sFloat,3>")) {
00467                 imagecopy = new QVImage<sFloat,3>;
00468                 *(dynamic_cast<QVImage<sFloat,3>*>(imagecopy)) = *(dynamic_cast<QVImage<sFloat,3>*>(image));
00469         }
00470         else {
00471         // alternate code for that type of image ...
00472                 qFatal("Type of QVGenericImage still not supported in drawQVImage");
00473         }
00474 
00475         // Image to the top of the stack (front of the list)
00476         imageList.push_front(imagecopy);
00477 
00478 
00480         if(adaptSize) {
00481                 this->resizeImageArea(image->getAnchor().x()+image->getROI().x()+image->getROI().width(),image->getAnchor().y()+image->getROI().y()+image->getROI().height());
00482         }
00483 
00484         // Push the current OpenGL projection and modelview matrices onto their
00485         // respective stacks:
00486         glPushAttrib(GL_ALL_ATTRIB_BITS);
00487         glPushClientAttrib(GL_ALL_ATTRIB_BITS);
00488         glMatrixMode(GL_PROJECTION);
00489         glPushMatrix();
00490         glMatrixMode(GL_MODELVIEW);
00491         glPushMatrix();
00492 
00493         // Set the correct viewport and perspective and model transformation
00494         // for native OpenGL calls:
00495         glViewport(0,0,width(),height());
00496         glMatrixMode(GL_PROJECTION);
00497         glLoadIdentity();
00498         glOrtho(topLeft.x(),topLeft.x()+width(),
00499                         topLeft.y()+height(),topLeft.y(),-1,1);
00500         glMatrixMode(GL_MODELVIEW);
00501         glLoadIdentity();
00502 
00503         // Intersection of current window viewport and image rectangles:
00504         QRect final_rect,outer_rect = outerRect(),
00505                   img_rect = QRect(imagecopy->getAnchor()+imagecopy->getROI().topLeft(),
00506                                                   QSize(imagecopy->getROI().width(),imagecopy->getROI().height()));
00507         final_rect = outer_rect & img_rect;
00508 
00509         // Now, render the image using OpenGL calls:
00510 
00511         // First, WHERE to draw...
00512         QPoint where,dirty; // Dirty trick for offset (bitmap trick).
00513         if(outer_rect.topLeft().x() >= img_rect.topLeft().x()) {
00514                 where.setX(outer_rect.topLeft().x());
00515                 dirty.setX(1);
00516         } else {
00517                 where.setX(img_rect.topLeft().x());
00518                 dirty.setX(0);
00519         }
00520         if(outer_rect.topLeft().y() >= img_rect.topLeft().y()) {
00521                 where.setY(outer_rect.topLeft().y());
00522                 dirty.setY(1);
00523         } else {
00524                 where.setY(img_rect.topLeft().y());
00525                 dirty.setY(0);
00526         }
00527         // Now the dirty trick for offset, using glBitmap:
00528         glRasterPos2f(zoom*(where.x()+dirty.x()+0.0001),zoom*(where.y()+dirty.y()+0.0001));
00529         glBitmap(0, 0, 0, 0, -zoom*dirty.x(), +zoom*dirty.y(), NULL); 
00530 
00531         // ... and second, WHAT to draw:
00532         QRect what;
00533         int img_step = imagecopy->getStep();
00534         glPixelZoom(zoom,-zoom);
00535         if(outer_rect.topLeft().x() >= img_rect.topLeft().x()) {
00536                 what.setX(outer_rect.topLeft().x() - img_rect.topLeft().x() + imagecopy->getROI().topLeft().x());
00537         } else {
00538                 what.setX(imagecopy->getROI().topLeft().x());
00539         }
00540         what.setWidth(final_rect.width());
00541         if(outer_rect.topLeft().y() >= img_rect.topLeft().y()) {
00542                 what.setY(outer_rect.topLeft().y() - img_rect.topLeft().y() + imagecopy->getROI().topLeft().y());
00543         } else {
00544                 what.setY(imagecopy->getROI().topLeft().y());
00545         }
00546         what.setHeight(final_rect.height());
00547 
00548         if(image->isCompatibleWith("QVImage<uChar,1>")) {
00549                 glPixelStorei(GL_UNPACK_ROW_LENGTH,img_step);
00550                 glDrawPixels(what.width(),what.height(),
00551                                          GL_LUMINANCE,GL_UNSIGNED_BYTE,
00552                                          static_cast<QVImage<uchar,1> *>(imagecopy)->getReadData() +
00553                                          what.y()*img_step+what.x());
00554         }
00555         else if(image->isCompatibleWith("QVImage<uShort,1>")) {
00556                 glPixelStorei(GL_UNPACK_ROW_LENGTH,img_step/sizeof(uShort));
00557                 glDrawPixels(what.width(),what.height(),
00558                                          GL_LUMINANCE,GL_UNSIGNED_SHORT,
00559                                          static_cast<QVImage<uShort,1> *>(imagecopy)->getReadData() +
00560                                          what.y()*img_step/sizeof(uShort)+what.x());
00561         }
00562         else if(image->isCompatibleWith("QVImage<sShort,1>")) {
00563                 glPixelStorei(GL_UNPACK_ROW_LENGTH,img_step/sizeof(sShort));
00564 
00565                 float scale=1.0/(high-low),bias=-low*scale;
00566                 glPixelTransferf(GL_RED_BIAS,bias);
00567                 glPixelTransferf(GL_GREEN_BIAS,bias);
00568                 glPixelTransferf(GL_BLUE_BIAS,bias);
00569                 glPixelTransferf(GL_RED_SCALE,scale);
00570                 glPixelTransferf(GL_GREEN_SCALE,scale);
00571                 glPixelTransferf(GL_BLUE_SCALE,scale);
00572 
00573                 glDrawPixels(what.width(),what.height(),
00574                                          GL_LUMINANCE,GL_SHORT,
00575                                          static_cast<QVImage<sShort,1> *>(imagecopy)->getReadData() +
00576                                          what.y()*img_step/sizeof(sShort)+what.x());
00577         }
00578         else if(image->isCompatibleWith("QVImage<sInt,1>")) {
00579                 glPixelStorei(GL_UNPACK_ROW_LENGTH,img_step/sizeof(sInt));
00580 
00581                 float scale=1.0/(high-low),bias=-low*scale;
00582                 glPixelTransferf(GL_RED_BIAS,bias);
00583                 glPixelTransferf(GL_GREEN_BIAS,bias);
00584                 glPixelTransferf(GL_BLUE_BIAS,bias);
00585                 glPixelTransferf(GL_RED_SCALE,scale);
00586                 glPixelTransferf(GL_GREEN_SCALE,scale);
00587                 glPixelTransferf(GL_BLUE_SCALE,scale);
00588 
00589                 glDrawPixels(what.width(),what.height(),
00590                                          GL_LUMINANCE,GL_INT,
00591                                          static_cast<QVImage<sInt,1> *>(imagecopy)->getReadData() +
00592                                          what.y()*img_step/sizeof(sInt)+what.x());
00593         }
00594         else if(image->isCompatibleWith("QVImage<sFloat,1>")) {
00595                 glPixelStorei(GL_UNPACK_ROW_LENGTH,img_step/sizeof(sFloat));
00596 
00597                 float scale=1.0/(high-low),bias=-low*scale;
00598                 //float scale = 1.0/ (high-low),bias=0;
00599                 glPixelTransferf(GL_RED_BIAS,bias);
00600                 glPixelTransferf(GL_GREEN_BIAS,bias);
00601                 glPixelTransferf(GL_BLUE_BIAS,bias);
00602                 glPixelTransferf(GL_RED_SCALE,scale);
00603                 glPixelTransferf(GL_GREEN_SCALE,scale);
00604                 glPixelTransferf(GL_BLUE_SCALE,scale);
00605 
00606 /*              glPixelTransferf(GL_RED_SCALE,float(1.0)/(float)127.0);
00607                 glPixelTransferf(GL_GREEN_SCALE,float(1.0)/(float)127.0);
00608                 glPixelTransferf(GL_BLUE_SCALE,float(1.0)/(float)127.0);*/
00609                 // Take care with last parameter (pointer) in this call: it works
00610                 // because of the float* arithmetic:
00611                 glDrawPixels(what.width(),what.height(),
00612                                          GL_LUMINANCE,GL_FLOAT,
00613                                          static_cast<QVImage<sFloat,1> *>(imagecopy)->getReadData() +
00614                                          what.y()*img_step/sizeof(sFloat)+what.x());
00615         }
00616         else if(image->isCompatibleWith("QVImage<uChar,3>")) {
00617                 glPixelStorei(GL_UNPACK_ROW_LENGTH,img_step/3);
00618                 glDrawPixels(what.width(),what.height(),
00619                                         GL_RGB,GL_UNSIGNED_BYTE,
00620                                         static_cast<QVImage<uchar,3> *>(imagecopy)->getReadData() +
00621                                         what.y()*img_step+3*what.x());
00622         }
00623         else if(image->isCompatibleWith("QVImage<uShort,3>")) {
00624                 glPixelStorei(GL_UNPACK_ROW_LENGTH,img_step/(sizeof(uShort)*3));
00625                 glDrawPixels(what.width(),what.height(),
00626                                         GL_RGB,GL_UNSIGNED_SHORT,
00627                                         static_cast<QVImage<uShort,3> *>(imagecopy)->getReadData() +
00628                                         what.y()*img_step/sizeof(uShort)+3*what.x());
00629         }
00630         else if(image->isCompatibleWith("QVImage<sShort,3>")) {
00631                 glPixelStorei(GL_UNPACK_ROW_LENGTH,img_step/(sizeof(sShort)*3));
00632 
00633                 float scale=1.0/(high-low),bias=-low*scale;
00634                 glPixelTransferf(GL_RED_BIAS,bias);
00635                 glPixelTransferf(GL_GREEN_BIAS,bias);
00636                 glPixelTransferf(GL_BLUE_BIAS,bias);
00637                 glPixelTransferf(GL_RED_SCALE,scale);
00638                 glPixelTransferf(GL_GREEN_SCALE,scale);
00639                 glPixelTransferf(GL_BLUE_SCALE,scale);
00640 
00641                 glDrawPixels(what.width(),what.height(),
00642                                         GL_RGB,GL_SHORT,
00643                                         static_cast<QVImage<sShort,3> *>(imagecopy)->getReadData() +
00644                                         what.y()*img_step/sizeof(sShort)+3*what.x());
00645         }
00646         else if(image->isCompatibleWith("QVImage<sInt,3>")) {
00647                 glPixelStorei(GL_UNPACK_ROW_LENGTH,img_step/(sizeof(sInt)*3));
00648 
00649                 float scale=1.0/(high-low),bias=-low*scale;
00650                 glPixelTransferf(GL_RED_BIAS,bias);
00651                 glPixelTransferf(GL_GREEN_BIAS,bias);
00652                 glPixelTransferf(GL_BLUE_BIAS,bias);
00653                 glPixelTransferf(GL_RED_SCALE,scale);
00654                 glPixelTransferf(GL_GREEN_SCALE,scale);
00655                 glPixelTransferf(GL_BLUE_SCALE,scale);
00656 
00657                 glDrawPixels(what.width(),what.height(),
00658                                          GL_RGB,GL_INT,
00659                                          static_cast<QVImage<sInt,3> *>(imagecopy)->getReadData() +
00660                                          what.y()*img_step/sizeof(sInt)+3*what.x());
00661         }
00662         else if(image->isCompatibleWith("QVImage<sFloat,3>")) {
00663                 glPixelStorei(GL_UNPACK_ROW_LENGTH,img_step/(sizeof(sFloat)*3));
00664 
00665                 float scale=1.0/(high-low),bias=-low*scale;
00666                 glPixelTransferf(GL_RED_BIAS,bias);
00667                 glPixelTransferf(GL_GREEN_BIAS,bias);
00668                 glPixelTransferf(GL_BLUE_BIAS,bias);
00669                 glPixelTransferf(GL_RED_SCALE,scale);
00670                 glPixelTransferf(GL_GREEN_SCALE,scale);
00671                 glPixelTransferf(GL_BLUE_SCALE,scale);
00672 
00673                 glDrawPixels(what.width(),what.height(),
00674                                          GL_RGB,GL_FLOAT,
00675                                          static_cast<QVImage<sFloat,3> *>(imagecopy)->getReadData() +
00676                                          what.y()*img_step/sizeof(sFloat)+3*what.x());
00677         }
00678         else {
00679         // alternate code for that type of image ...
00680                 qFatal("Type of QVGenericImage still not supported in drawQVImage");
00681         }
00682 
00683         // Pop the OpenGL projection and modelview matrices off their respective
00684         // stacks. Pop the OpenGL attributes off the attribute stack.
00685     glPopClientAttrib();
00686     glPopAttrib();
00687     glMatrixMode(GL_MODELVIEW);
00688     glPopMatrix();
00689     glMatrixMode(GL_PROJECTION);
00690     glPopMatrix();
00691 }
00692 
00693 void QVImageArea::mousePressEvent(QMouseEvent *event)
00694 {
00695         firstPos = event->pos();
00696         dragging = TRUE;
00697         if(mouseMode == DRAG) {
00698                 //setCursor(Qt::ClosedHandCursor);
00699         }
00700 
00701         if ( (mouseMode == SEL) && (event->button() == Qt::RightButton) )
00702                 emit rectSelected(QRect());
00703 
00704         // add a new point to the polyline
00705         if (mouseMode == POLY) {
00706                 if (event->button() == Qt::RightButton) {
00707                         (polyMode == CIRCLE) ? emit circleSelected(QPoint(), 0.0) : emit polySelected(QPoint(), true, polyMode);
00708                         }
00709                 else if (polyMode != CIRCLE) {
00710                         QPoint pos = event->pos();
00711                         QPoint point(qRound(static_cast<float>(pos.x()+topLeft.x())/zoom), qRound(static_cast<float>(pos.y()+topLeft.y())/zoom));
00712                         emit polySelected(point, false, polyMode);
00713                 }
00714         }
00715 }
00716 
00717 void QVImageArea::mouseMoveEvent(QMouseEvent *event)
00718 {
00719         if(dragging) {
00720                 lastPos = event->pos();
00721                 switch(mouseMode) {
00722                 case DRAG: {
00723                         QPoint minDesp = -topLeft,
00724                                 maxDesp = QPoint(origwidth*zoom,origheight*zoom) -
00725                                                         (topLeft + QPoint(width(),height()));
00726                         QPoint desp = firstPos-lastPos,
00727                                 boundDesp = QPoint(qBound(minDesp.x(),desp.x(),maxDesp.x()),
00728                                                                         qBound(minDesp.y(),desp.y(),maxDesp.y()));
00729                         if(boundDesp != QPoint(0,0)) {
00730                                 topLeft = topLeft+boundDesp;
00731                                 update();
00732                                 emit newGeometry(origwidth,origheight,topLeft.x(),topLeft.y(),width(),height(),zoom);
00733                         }
00734                         firstPos = lastPos;
00735                         emit mouseLeavesImageArea(FALSE);
00736                         emit newMousePosition(static_cast<float>(event->x()+topLeft.x())/zoom,static_cast<float>(event->y()+topLeft.y())/zoom);
00737                         break;
00738                         }
00739                 case ZOOM: {
00740                         QPoint p1(qRound(static_cast<float>(firstPos.x()+topLeft.x())/zoom),
00741                                         qRound(static_cast<float>(firstPos.y()+topLeft.y())/zoom)),
00742                                 p2(qRound(static_cast<float>(lastPos.x()+topLeft.x())/zoom)-1,
00743                                         qRound(static_cast<float>(lastPos.y()+topLeft.y())/zoom)-1);
00744 
00745                         // Warning: QT (lesser) error when constructing rectangles of type QRect(QPoint(x,y),QPoint(x-1,y')),
00746                         // as well QRect(QPoint(x,y),QPoint(x',y-1)). In practice, it is not important, so we won't
00747                         // blur the code.
00748                         zoomRect = QRect(p1,p2) & innerRect(); // Intersection
00749                         emit mouseLeavesImageArea(FALSE);
00750                         emit newMousePosition(lastPos.x()>firstPos.x()?zoomRect.right():zoomRect.left(), lastPos.y()>firstPos.y()?zoomRect.bottom():zoomRect.top());
00751                         update();
00752                         break;
00753                         }
00754                 case SEL: {
00755                         QPoint p1(qRound(static_cast<float>(firstPos.x()+topLeft.x())/zoom),
00756                                         qRound(static_cast<float>(firstPos.y()+topLeft.y())/zoom)),
00757                                 p2(qRound(static_cast<float>(lastPos.x()+topLeft.x())/zoom)-1,
00758                                         qRound(static_cast<float>(lastPos.y()+topLeft.y())/zoom)-1);
00759 
00760                         selRect = QRect(p1,p2) & innerRect(); // Intersection
00761                         emit rectSelected(selRect);
00762                         emit mouseLeavesImageArea(FALSE);
00763                         emit newMousePosition(lastPos.x()>firstPos.x()?selRect.right():selRect.left(), lastPos.y()>firstPos.y()?selRect.bottom():selRect.top());
00764                         update();
00765                         break;
00766                         }
00767                 case POLY: {
00768                         if (polyMode == CIRCLE) {
00769                                 QPoint p1(qRound(static_cast<float>(firstPos.x()+topLeft.x())/zoom),
00770                                                 qRound(static_cast<float>(firstPos.y()+topLeft.y())/zoom)),
00771                                         p2(qRound(static_cast<float>(lastPos.x()+topLeft.x())/zoom)-1,
00772                                                 qRound(static_cast<float>(lastPos.y()+topLeft.y())/zoom)-1);
00773 
00774                                 float cat1 = p1.x() - p2.x(), cat2 = p1.y() - p2.y();
00775                                 float radio = sqrt(cat1*cat1 + cat2*cat2);
00776                                 emit circleSelected(p1, radio);
00777                         }
00778                         break;
00779                         }
00780                 case NONE: {
00781                         break;
00782                         }
00783                 }
00784         } else {
00785                 emit mouseLeavesImageArea(FALSE);
00786                 emit newMousePosition(static_cast<float>(event->x()+topLeft.x())/zoom,static_cast<float>(event->y()+topLeft.y())/zoom);
00787         }
00788 }
00789 
00790 
00791 void QVImageArea::mouseReleaseEvent(QMouseEvent *event)
00792 {
00793         //Q_UNUSED(event);
00794         if(mouseMode == DRAG) {
00795                 //setCursor(Qt::OpenHandCursor);
00796         }
00797         dragging = FALSE;
00798         lastPos = event->pos();
00799         switch(mouseMode) {
00800           case DRAG: {
00801                 break;
00802           }
00803           case ZOOM: {
00804                 int newzoom = zoom;
00805 
00806                 if (zoomRect.width() < 1 or zoomRect.height() < 1) // if the rect is too small, the newzoom must be too great
00807                         newzoom = max_zoom + 1;
00808                 else {
00809                         do {
00810                                 if (newzoom < 2) newzoom++; // in order to grown always
00811                                 else newzoom = 2*newzoom;
00812                         }
00813                         while(newzoom*zoomRect.width() < minimumWidth() or newzoom*zoomRect.height() < minimumHeight());
00814                 }
00815 
00816                 if(newzoom <= max_zoom) {
00817                         zoom = newzoom;
00818                         topLeft = zoom*zoomRect.topLeft();
00819                         setMaximumSize(zoom*origwidth,zoom*origheight);
00820                         resize(zoom*zoomRect.width(),zoom*zoomRect.height());
00821                         zoomRect = QRect();
00822                         update();
00823                         emit newGeometry(origwidth,origheight,topLeft.x(),topLeft.y(),width(),height(),zoom);
00824                 } else {
00825                         zoomRect = QRect();
00826                         update();
00827                 }
00828                 break;
00829           }
00830           case SEL: {
00831                 if(event->button() == Qt::RightButton) {
00832                         selRect = QRect();
00833                         update();
00834                 }
00835                 break;
00836           }
00837           case POLY: {
00838                 break;
00839           }
00840           case NONE: {
00841                 break;
00842           }
00843         }
00844 }
00845 
00846 void QVImageArea::leaveEvent(QEvent *event)
00847 {
00848         Q_UNUSED(event);
00849         emit mouseLeavesImageArea(TRUE);
00850 }
00851 
00852 
00853 /******************************************************************************/
00854 
00855 void QVCanvas::resizeEvent(QResizeEvent *event)
00856 {
00857         QFontMetrics fm(font());
00858 
00859         int w = event->size().width() - scaleWidgetsFixedWidth - 1;
00860         int h = event->size().height() - scaleWidgetsFixedWidth - statusBarWidgetFixedHeight - 1;
00861         imageArea->setGeometry(scaleWidgetsFixedWidth,scaleWidgetsFixedWidth,w,h);
00862 }
00863 
00864 QString QVCanvas::statusMessage()
00865 {
00866         if(mouseIsOut) {
00867                 return QString("z=%1").arg(imageArea->zoom);
00868         } else {
00869                 return QString("(%1,%2) z=%3").arg(mousePosX).arg(mousePosY).arg(imageArea->zoom);
00870         }
00871 }
00872 
00873 QVCanvas::QVCanvas(QWidget *parent) : QWidget(parent)
00874 {
00875         mouseIsOut = TRUE;
00876         int w = 1, h = 1;
00877         // Scale widgets fixed width proportional to font height:
00878         QFontMetrics fm(font());
00879         scaleWidgetsFixedWidth = 5*fm.height()/3;
00880 
00881         // Scale widgets creation:
00882         scaleWidgetX = new QwtScaleWidget(QwtScaleDraw::TopScale,this);
00883         //scaleWidgetX->setLabelRotation(0.0);
00884         scaleWidgetX->setLabelAlignment(Qt::AlignHCenter|Qt::AlignTop);
00885         scaleWidgetX->setMargin(1);
00886         // Left and right (top & bottom) scaleWidgetsFixedWidth for scale widgets
00887         // (Otherwise, setBorderDist does not work!);
00888         //scaleWidgetX->setBorderDist(scaleWidgetsFixedWidth,0);
00889         scaleWidgetX->setBorderDist(scaleWidgetsFixedWidth,scaleWidgetsFixedWidth);
00890         
00891         scaleWidgetY = new QwtScaleWidget(QwtScaleDraw::LeftScale,this);
00892         scaleWidgetY->setLabelRotation(-90.0);
00893         scaleWidgetY->setLabelAlignment(Qt::AlignVCenter|Qt::AlignTop);
00894         scaleWidgetY->setMargin(1);
00895         // Left and right (top & bottom) scaleWidgetsFixedWidth for scale widgets
00896         // (Otherwise, setBorderDist does not work!);
00897         //scaleWidgetY->setBorderDist(scaleWidgetsFixedWidth,0);
00898         scaleWidgetY->setBorderDist(scaleWidgetsFixedWidth,scaleWidgetsFixedWidth);
00899 
00900         // Scale engines creation:
00901         scaleEngineX = new QwtLinearScaleEngine;
00902         scaleEngineY = new QwtLinearScaleEngine;
00903 
00904         // QVImageArea creation: if there are others image areas, the new image area will share its contex with the first, in order not to slow down the application
00905         if(image_areas.isEmpty()) {
00906                 // If first instance, create widget with brand new context:
00907                 imageArea = new QVImageArea(w,h,this);
00908         }
00909         else {
00910                 // For the rest of instances, create with the initial context: first (not deleted) imageArea's context
00911                 imageArea = new QVImageArea(w,h,this,image_areas.first());
00912         }
00913         // appends its reference, in the image_areas list (in case it becomes the first image area, the new imageAreas can shared its context)
00914         image_areas.append(imageArea);
00915 
00916         statusBar = new QStatusBar(this);
00917         statusBar->addPermanentWidget(buttonZoomIn = new QToolButton(statusBar));
00918         statusBar->addPermanentWidget(buttonZoomOut = new QToolButton(statusBar));
00919         statusBar->addPermanentWidget(buttonZoomOriginal = new QToolButton(statusBar));
00920         statusBar->addPermanentWidget(buttonZoomRect = new QToolButton(statusBar));
00921         statusBar->addPermanentWidget(buttonSelPoli = new QToolButton(statusBar));
00922         statusBar->addPermanentWidget(buttonSelRect = new QToolButton(statusBar));
00923         statusBar->addPermanentWidget(buttonDrag = new QToolButton(statusBar));
00924         buttonZoomIn->setCheckable(FALSE);
00925         buttonZoomIn->setIcon(QIcon(":/images/zoom-in.png"));
00926         buttonZoomOut->setCheckable(FALSE);
00927         buttonZoomOut->setIcon(QIcon(":/images/zoom-out.png"));
00928         buttonZoomOriginal->setCheckable(FALSE);
00929         buttonZoomOriginal->setIcon(QIcon(":/images/zoom-original.png"));
00930         buttonZoomRect->setCheckable(TRUE);
00931         buttonZoomRect->setIcon(QIcon(":/images/zoom-best-fit.png"));
00932         buttonSelPoli->setCheckable(TRUE);
00933         buttonSelPoli->setIcon(QIcon(":/images/poly.png"));
00934         menuSelPoli = new QMenu();
00935         menuSelPoli->addAction(QIcon(":/images/poly.png"), "polyline", this, SLOT(selPoliChangedToLine()));
00936         menuSelPoli->addAction(QIcon(":/images/list.png"), "points", this, SLOT(selPoliChangedToList()));
00937         menuSelPoli->addAction(QIcon(":/images/circle.png"), "circle", this, SLOT(selPoliChangedToCircle()));
00938         buttonSelPoli->setMenu(menuSelPoli);
00939         polyMode = LINE;
00940         buttonSelRect->setCheckable(TRUE);
00941         buttonSelRect->setIcon(QIcon(":/images/select.png"));
00942         buttonDrag->setCheckable(TRUE);
00943         buttonDrag->setIcon(QIcon(":/images/hand.png"));
00944 
00945         statusBar->showMessage(statusMessage());
00946         statusBarWidgetFixedHeight = statusBar->height();
00947 
00948         setMinimumSize(scaleWidgetsFixedWidth + imageArea->minimumWidth() + 1,
00949                                    scaleWidgetsFixedWidth + imageArea->minimumHeight() + 1 +
00950                                    statusBarWidgetFixedHeight);
00951         setMaximumSize(scaleWidgetsFixedWidth + w + 1,
00952                                    scaleWidgetsFixedWidth + h + 1 +
00953                                    statusBarWidgetFixedHeight);
00954         resize(scaleWidgetsFixedWidth + w + 1,
00955                    scaleWidgetsFixedWidth + h + 1 +
00956                    statusBarWidgetFixedHeight);
00957         connect(imageArea,SIGNAL(newGeometry(int,int,int,int,int,int,int)),
00958                         this,SLOT(setGeometry(int,int,int,int,int,int,int)));
00959         connect(imageArea,SIGNAL(newMousePosition(float,float)),
00960                         this,SLOT(newMousePositionSlot(float,float)));
00961         connect(imageArea,SIGNAL(mouseLeavesImageArea(bool)),
00962                         this,SLOT(mouseLeavesImageAreaSlot(bool)));
00963         connect(imageArea, SIGNAL(rectSelected(QRect)),
00964                         this, SLOT(rectSelectedSlot(QRect)));
00965         connect(imageArea, SIGNAL(polySelected(QPoint,bool,TPolyMode)),
00966                         this, SLOT(polySelectedSlot(QPoint,bool,TPolyMode)));
00967         connect(imageArea, SIGNAL(circleSelected(QPoint,float)),
00968                         this, SLOT(circleSelectedSlot(QPoint,float)));
00969         connect(buttonZoomRect,SIGNAL(clicked(bool)),this,SLOT(zoomRectClicked(bool)));
00970         connect(buttonSelPoli,SIGNAL(clicked(bool)),this,SLOT(selPoliClicked(bool)));
00971         connect(buttonSelRect,SIGNAL(clicked(bool)),this,SLOT(selRectClicked(bool)));
00972         connect(buttonDrag,SIGNAL(clicked(bool)),this,SLOT(dragClicked(bool)));
00973         connect(buttonZoomIn,SIGNAL(clicked()),this,SLOT(zoomInClicked()));
00974         connect(buttonZoomOut,SIGNAL(clicked()),this,SLOT(zoomOutClicked()));
00975         connect(buttonZoomOriginal,SIGNAL(clicked()),this,SLOT(zoomOriginalClicked()));
00976 
00977 }
00978 
00979 void QVCanvas::zoomInClicked() {
00980         imageArea->centerZoom(2*imageArea->zoom);
00981 }
00982 
00983 void QVCanvas::zoomOutClicked() {
00984         imageArea->centerZoom(imageArea->zoom/2);
00985 }
00986 
00987 void QVCanvas::zoomOriginalClicked() {
00988         // (Tricky) force redraw at initial size:
00989         int w = imageArea->origwidth, h = imageArea->origheight;
00990         imageArea->origwidth = imageArea->origheight = 0;
00991         QRect saveSelRect = imageArea->selRect;
00992         imageArea->resizeImageArea(w,h);
00993         imageArea->selRect = saveSelRect;
00994 }
00995 
00996 
00997 void QVCanvas::zoomRectClicked(bool checked) {
00998         if(checked)
00999                 imageArea->setCursor(Qt::CrossCursor);
01000         else
01001                 imageArea->setCursor(Qt::ArrowCursor);
01002         imageArea->mouseMode = (checked ? QVImageArea::ZOOM : QVImageArea::NONE);
01003         buttonSelPoli->setChecked(false);
01004         buttonSelRect->setChecked(false);
01005         buttonDrag->setChecked(false);
01006 }
01007 
01008 void QVCanvas::selPoliClicked(bool checked) {
01009         if(checked)
01010                 imageArea->setCursor(Qt::CrossCursor);
01011         else
01012                 imageArea->setCursor(Qt::ArrowCursor);
01013 
01014         if (!checked) {
01015                 switch (imageArea->polyMode) {
01016                         case LINE:
01017                         case LIST: {
01018                                 imageArea->polyMode = polyMode;
01019                                 emit imageArea->polySelected(QPoint(), true, polyMode);
01020                                 break;
01021                         }
01022                         case CIRCLE: {
01023                                 imageArea->polyMode = polyMode;
01024                                 emit imageArea->circleSelected(QPoint(), 0.0);
01025                                 break;
01026                         }
01027                 }
01028                 imageArea->mouseMode = QVImageArea::NONE;
01029         }
01030         else {
01031                 imageArea->mouseMode = QVImageArea::POLY;
01032                 imageArea->polyMode = polyMode;
01033         }
01034         buttonZoomRect->setChecked(false);
01035         buttonSelRect->setChecked(false);
01036         buttonDrag->setChecked(false);
01037 }
01038 
01039 void QVCanvas::selPoliChangedToLine() {
01040         polyMode = LINE;
01041         if (imageArea->mouseMode == QVImageArea::POLY)
01042                 switch (imageArea->polyMode) {
01043                         case LIST: {
01044                                 imageArea->polyMode = polyMode;
01045                                 emit imageArea->polySelected(QPoint(), true, polyMode);
01046                                 break;
01047                         }
01048                         case CIRCLE: {
01049                                 imageArea->polyMode = polyMode;
01050                                 emit imageArea->circleSelected(QPoint(), 0.0);
01051                                 break;
01052                         }
01053                         case LINE: {
01054                                 break;
01055                         }
01056                 }
01057         buttonSelPoli->setIcon(QIcon(":/images/poly.png"));
01058 }
01059 
01060 void QVCanvas::selPoliChangedToList() {
01061         polyMode = LIST;
01062         if (imageArea->mouseMode == QVImageArea::POLY)
01063                 switch (imageArea->polyMode) {
01064                         case LINE: {
01065                                 imageArea->polyMode = polyMode;
01066                                 emit imageArea->polySelected(QPoint(), true, polyMode);
01067                                 break;
01068                         }
01069                         case CIRCLE: {
01070                                 imageArea->polyMode = polyMode;
01071                                 emit imageArea->circleSelected(QPoint(), 0.0);
01072                                 break;
01073                         }
01074                         case LIST: {
01075                                 break;
01076                         }
01077                 }
01078         buttonSelPoli->setIcon(QIcon(":/images/list.png"));
01079 }
01080 
01081 void QVCanvas::selPoliChangedToCircle() {
01082         polyMode = CIRCLE;
01083         if (imageArea->mouseMode == QVImageArea::POLY)
01084                 switch (imageArea->polyMode) {
01085                         case LIST:
01086                         case LINE: {
01087                                 imageArea->polyMode = polyMode;
01088                                 emit imageArea->polySelected(QPoint(), true, polyMode);
01089                                 break;
01090                         }
01091                         case CIRCLE: {
01092                                 break;
01093                         }
01094                 }
01095         buttonSelPoli->setIcon(QIcon(":/images/circle.png"));
01096 }
01097 
01098 void QVCanvas::selRectClicked(bool checked) {
01099         if(checked)
01100                 imageArea->setCursor(Qt::CrossCursor);
01101         else
01102                 imageArea->setCursor(Qt::ArrowCursor);
01103         imageArea->mouseMode = (checked ? QVImageArea::SEL : QVImageArea::NONE);
01104         buttonZoomRect->setChecked(false);
01105         buttonSelPoli->setChecked(false);
01106         buttonDrag->setChecked(false);
01107         if (!checked) {
01108                 imageArea->selRect = QRect();
01109                 emit imageArea->rectSelected(imageArea->selRect);
01110         }
01111 }
01112 
01113 void QVCanvas::dragClicked(bool checked) {
01114         if(checked)
01115                 ;//imageArea->setCursor(Qt::OpenHandCursor);
01116         else
01117                 imageArea->setCursor(Qt::ArrowCursor);
01118 
01119         imageArea->mouseMode = (checked ? QVImageArea::DRAG : QVImageArea::NONE);
01120         buttonSelPoli->setChecked(false);
01121         buttonSelRect->setChecked(false);
01122         buttonZoomRect->setChecked(false);
01123 }
01124 
01125 
01126 void QVCanvas::newMousePositionSlot(float x,float y) {
01127         mousePosX = x;
01128         mousePosY = y;
01129         statusBar->showMessage(statusMessage());
01130 }
01131 
01132 void QVCanvas::mouseLeavesImageAreaSlot(bool leaves) {
01133 /*      if(leaves)
01134                 std::cout << "SALGO-----------------------------" << std::endl;
01135         else
01136                 std::cout << "ENTRO-----------------------------" << std::endl;*/
01137         mouseIsOut = leaves;
01138         statusBar->showMessage(statusMessage());
01139 }
01140 
01141 
01142 QVCanvas::~QVCanvas()
01143 {
01144         delete scaleEngineX;
01145         delete scaleEngineY;
01146 
01147         // It remove its reference of the image areas list
01148         image_areas.removeAll(imageArea);
01149 
01150         delete imageArea;
01151 }
01152 
01153 void QVCanvas::refreshImageArea()
01154 {
01155         imageArea->update();
01156 }
01157 
01158 
01159 void QVCanvas::setGeometry(int origwidth,int origheight,int topleftx,int toplefty,int width,int height, int zoom)
01160 {
01161         Q_UNUSED(origwidth);
01162         Q_UNUSED(origheight);
01163 
01164         QFontMetrics fm(font());
01165 
01166         // virtual QwtScaleDiv divideScale(double x1, double x2,
01167         //     int numMajorSteps, int numMinorSteps, double stepSize=0.0) const
01168         QwtScaleDiv scaleDivX = scaleEngineX->divideScale(
01169                                         ((double)topleftx)/zoom,((double)(topleftx+width))/zoom,
01170                                         qMin(width/zoom+1,static_cast<int>(width/(fm.width("999")))),
01171                                         10,0);
01172         scaleWidgetX->setScaleDiv(scaleEngineX->transformation(),scaleDivX);
01173 
01174         QwtScaleDiv scaleDivY = scaleEngineY->divideScale(
01175                                         ((double)toplefty+height)/zoom,((double)(toplefty))/zoom,
01176                                         qMin(height/zoom+1,static_cast<int>(height/(fm.width("999")))),
01177                                         10,0);
01178         scaleWidgetY->setScaleDiv(scaleEngineY->transformation(),scaleDivY);
01179 
01180 
01181         setMinimumSize(scaleWidgetsFixedWidth + imageArea->minimumWidth() + 1,
01182                                    scaleWidgetsFixedWidth + imageArea->minimumHeight() + 1 +
01183                                    statusBarWidgetFixedHeight);
01184 
01185 
01186 
01187         setMaximumSize(scaleWidgetsFixedWidth+zoom*imageArea->origwidth + 1,
01188                                    scaleWidgetsFixedWidth+zoom*imageArea->origheight + 1 +
01189                                    statusBarWidgetFixedHeight);
01190 
01191         resize(scaleWidgetsFixedWidth+width+1,
01192                         scaleWidgetsFixedWidth+height+1+statusBarWidgetFixedHeight);
01193 
01194         // Left and right (top & bottom) scaleWidgetsFixedWidth for scale widgets
01195         // (Otherwise, setBorderDist does not work!);
01196 
01197         scaleWidgetX->setGeometry(0,0,
01198                 2*scaleWidgetsFixedWidth+width+1,scaleWidgetsFixedWidth);
01199         scaleWidgetY->setGeometry(0,0,
01200                 scaleWidgetsFixedWidth,2*scaleWidgetsFixedWidth+height+1);
01201 
01202         statusBar->setGeometry(
01203                 0,scaleWidgetsFixedWidth+height+1,
01204                 scaleWidgetsFixedWidth+width+1,statusBarWidgetFixedHeight);
01205 
01206         statusBar->showMessage(statusMessage());
01207 
01208 
01209 }