ratio_layouted_frame.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2011, Dirk Thomas, TU Darmstadt
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  *   * Redistributions of source code must retain the above copyright
00010  *     notice, this list of conditions and the following disclaimer.
00011  *   * Redistributions in binary form must reproduce the above
00012  *     copyright notice, this list of conditions and the following
00013  *     disclaimer in the documentation and/or other materials provided
00014  *     with the distribution.
00015  *   * Neither the name of the TU Darmstadt nor the names of its
00016  *     contributors may be used to endorse or promote products derived
00017  *     from this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00020  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00021  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00022  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00023  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00024  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00025  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00026  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00027  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00028  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00029  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00030  * POSSIBILITY OF SUCH DAMAGE.
00031  */
00032 
00033 #include <rqt_image_view/ratio_layouted_frame.h>
00034 
00035 #include <assert.h>
00036 #include <QMouseEvent>
00037 
00038 namespace rqt_image_view {
00039 
00040 RatioLayoutedFrame::RatioLayoutedFrame(QWidget* parent, Qt::WindowFlags flags)
00041   : QFrame()
00042   , outer_layout_(NULL)
00043   , aspect_ratio_(4, 3)
00044   , smoothImage_(false)
00045 {
00046   connect(this, SIGNAL(delayed_update()), this, SLOT(update()), Qt::QueuedConnection);
00047 }
00048 
00049 RatioLayoutedFrame::~RatioLayoutedFrame()
00050 {
00051 }
00052 
00053 const QImage& RatioLayoutedFrame::getImage() const
00054 {
00055   return qimage_;
00056 }
00057 
00058 QImage RatioLayoutedFrame::getImageCopy() const
00059 {
00060   QImage img;
00061   qimage_mutex_.lock();
00062   img = qimage_.copy();
00063   qimage_mutex_.unlock();
00064   return img;
00065 }
00066 
00067 void RatioLayoutedFrame::setImage(const QImage& image)//, QMutex* image_mutex)
00068 {
00069   qimage_mutex_.lock();
00070   qimage_ = image.copy();
00071   setAspectRatio(qimage_.width(), qimage_.height());
00072   qimage_mutex_.unlock();
00073   emit delayed_update();
00074 }
00075 
00076 void RatioLayoutedFrame::resizeToFitAspectRatio()
00077 {
00078   QRect rect = contentsRect();
00079 
00080   // reduce longer edge to aspect ration
00081   double width;
00082   double height;
00083 
00084   if (outer_layout_)
00085   {
00086     width = outer_layout_->contentsRect().width();
00087     height = outer_layout_->contentsRect().height();
00088   }
00089   else
00090   {
00091     // if outer layout isn't available, this will use the old
00092     // width and height, but this can shrink the display image if the
00093     // aspect ratio changes.
00094     width = rect.width();
00095     height = rect.height();
00096   }
00097 
00098   double layout_ar = width / height;
00099   const double image_ar = double(aspect_ratio_.width()) / double(aspect_ratio_.height());
00100   if (layout_ar > image_ar)
00101   {
00102     // too large width
00103     width = height * image_ar;
00104   }
00105   else
00106   {
00107     // too large height
00108     height = width / image_ar;
00109   }
00110   rect.setWidth(int(width + 0.5));
00111   rect.setHeight(int(height + 0.5));
00112 
00113   // resize taking the border line into account
00114   int border = lineWidth();
00115   resize(rect.width() + 2 * border, rect.height() + 2 * border);
00116 }
00117 
00118 void RatioLayoutedFrame::setOuterLayout(QHBoxLayout* outer_layout)
00119 {
00120   outer_layout_ = outer_layout;
00121 }
00122 
00123 void RatioLayoutedFrame::setInnerFrameMinimumSize(const QSize& size)
00124 {
00125   int border = lineWidth();
00126   QSize new_size = size;
00127   new_size += QSize(2 * border, 2 * border);
00128   setMinimumSize(new_size);
00129   emit delayed_update();
00130 }
00131 
00132 void RatioLayoutedFrame::setInnerFrameMaximumSize(const QSize& size)
00133 {
00134   int border = lineWidth();
00135   QSize new_size = size;
00136   new_size += QSize(2 * border, 2 * border);
00137   setMaximumSize(new_size);
00138   emit delayed_update();
00139 }
00140 
00141 void RatioLayoutedFrame::setInnerFrameFixedSize(const QSize& size)
00142 {
00143   setInnerFrameMinimumSize(size);
00144   setInnerFrameMaximumSize(size);
00145 }
00146 
00147 void RatioLayoutedFrame::setAspectRatio(unsigned short width, unsigned short height)
00148 {
00149   int divisor = greatestCommonDivisor(width, height);
00150   if (divisor != 0) {
00151     aspect_ratio_.setWidth(width / divisor);
00152     aspect_ratio_.setHeight(height / divisor);
00153   }
00154 }
00155 
00156 void RatioLayoutedFrame::paintEvent(QPaintEvent* event)
00157 {
00158   QPainter painter(this);
00159   qimage_mutex_.lock();
00160   if (!qimage_.isNull())
00161   {
00162     resizeToFitAspectRatio();
00163     // TODO: check if full draw is really necessary
00164     //QPaintEvent* paint_event = dynamic_cast<QPaintEvent*>(event);
00165     //painter.drawImage(paint_event->rect(), qimage_);
00166     if (!smoothImage_) {
00167       painter.drawImage(contentsRect(), qimage_);
00168     } else {
00169       if (contentsRect().width() == qimage_.width()) {
00170         painter.drawImage(contentsRect(), qimage_);
00171       } else {
00172         QImage image = qimage_.scaled(contentsRect().width(), contentsRect().height(),
00173                                       Qt::KeepAspectRatio, Qt::SmoothTransformation);
00174         painter.drawImage(contentsRect(), image);
00175       }
00176     }
00177   } else {
00178     // default image with gradient
00179     QLinearGradient gradient(0, 0, frameRect().width(), frameRect().height());
00180     gradient.setColorAt(0, Qt::white);
00181     gradient.setColorAt(1, Qt::black);
00182     painter.setBrush(gradient);
00183     painter.drawRect(0, 0, frameRect().width() + 1, frameRect().height() + 1);
00184   }
00185   qimage_mutex_.unlock();
00186 }
00187 
00188 int RatioLayoutedFrame::greatestCommonDivisor(int a, int b)
00189 {
00190   if (b==0)
00191   {
00192     return a;
00193   }
00194   return greatestCommonDivisor(b, a % b);
00195 }
00196 
00197 void RatioLayoutedFrame::mousePressEvent(QMouseEvent * mouseEvent)
00198 {
00199   if(mouseEvent->button() == Qt::LeftButton)
00200   {
00201     emit mouseLeft(mouseEvent->x(), mouseEvent->y());
00202   }
00203   QFrame::mousePressEvent(mouseEvent);
00204 }
00205 
00206 void RatioLayoutedFrame::onSmoothImageChanged(bool checked) {
00207   smoothImage_ = checked;
00208 }
00209 
00210 }


rqt_image_view
Author(s): Dirk Thomas
autogenerated on Thu Aug 3 2017 02:22:23