PARP Research Group University of Murcia, Spain


src/qvgui/qvcanvas.cpp

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



QVision framework. PARP research group, copyright 2007, 2008.