ZImageView.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "ZImageView.h"
00018
00019 #include <QPainter>
00020 #include <QMouseEvent>
00021
00022 #include <cmath>
00023
00024 #if QT_VERSION >= 0x040200
00025 #define CURSOR_NORMAL QCursor(Qt::OpenHandCursor)
00026 #define CURSOR_MOUSE_PRESS QCursor(Qt::ClosedHandCursor)
00027 #else
00028 #define CURSOR_NORMAL QCursor(Qt::CrossCursor)
00029 #define CURSOR_MOUSE_PRESS QCursor(Qt::SizeAllCursor)
00030 #endif
00031
00032
00033
00034 ZImageView::ZImageView(QWidget *parent)
00035 : QWidget(parent)
00036 {
00037
00038 _zoom = 0.0;
00039 _desiredX = 0.0;
00040 _desiredY = 0.0;
00041 _maxZoomFactor = 2.0;
00042 _padding = 60;
00043
00044 setCursor(CURSOR_NORMAL);
00045 updateViewport();
00046 resetZoomPoint();
00047 repaint();
00048 }
00049
00050
00051 void
00052 ZImageView::setImage(QImage& img)
00053 {
00054 _image = img.copy();
00055 updateViewport();
00056 resetZoomPoint();
00057
00058 if (isVisible()) {
00059 repaint();
00060 }
00061 }
00062
00063
00064 void
00065 ZImageView::drawScaledImage()
00066 {
00067 if (!isVisible()) {
00068 return;
00069 }
00070
00071 QBrush background(QColor("#fdfdfd"));
00072 if (_image.isNull()) {
00073 QPainter p(this);
00074 p.fillRect(rect(), background);
00075 return;
00076 }
00077
00078 QRect sRect = rect();
00079 QRect iRect = _image.rect();
00080 QRect r = _view;
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095 double scaleFactor = double(sRect.width()) / double(_view.width());
00096
00097
00098 if (r.top() < 0) {
00099 r.setTop(0);
00100 }
00101 if (iRect.bottom() < r.bottom()) {
00102 r.setBottom(iRect.bottom());
00103 }
00104 if (r.left() < 0) {
00105 r.setLeft(0);
00106 }
00107 if (iRect.right() < r.right()) {
00108 r.setRight(iRect.right());
00109 }
00110
00111
00112 QSize scaleTo(int(double(r.width()) * scaleFactor),
00113 int(double(r.height()) * scaleFactor));
00114
00115
00116 QImage i = _image.copy();
00117
00118
00119
00120 QPainter painter;
00121 painter.begin(&i);
00122 paintImage(&painter);
00123 painter.end();
00124
00125
00126 i = i.copy(r).scaled(scaleTo,
00127 Qt::KeepAspectRatioByExpanding,
00128 Qt::SmoothTransformation);
00129
00130 int extraWidth = int(double(sRect.width() - i.width()) / 2.0);
00131 int extraHeight = int(double(sRect.height() - i.height()) / 2.0);
00132
00133
00134
00135
00136
00137 QPainter p(this);
00138 if (extraWidth > 0) {
00139 p.fillRect(0, 0, extraWidth, sRect.height(), background);
00140 p.fillRect(sRect.width() - extraWidth, 0,
00141 sRect.width(), sRect.height(), background);
00142 }
00143
00144 if (extraHeight > 0) {
00145 p.fillRect(0, 0, sRect.width(), extraHeight, background);
00146 p.fillRect(0, sRect.height() - extraHeight,
00147 sRect.width(), sRect.height(), background);
00148 }
00149
00150
00151 p.drawImage(extraWidth, extraHeight, i);
00152 }
00153
00154
00155 void
00156 ZImageView::updateViewport(int screendx, int screendy)
00157 {
00158
00159
00160
00161
00162
00163 QRect sRect = rect();
00164 QRect iRect = _image.rect();
00165
00166 float sw = float(sRect.width());
00167 float sh = float(sRect.height());
00168 float iw = float(iRect.width());
00169 float ih = float(iRect.height());
00170
00171
00172
00173
00174 float maxw = float(std::max<int>(sRect.width(), iRect.width())) + _padding;
00175 float maxh = float(std::max<int>(sRect.height(), iRect.height())) + _padding;
00176 float minw = std::ceil(float(sRect.width()) / _maxZoomFactor);
00177 float minh = std::ceil(float(sRect.height()) / _maxZoomFactor);
00178
00179
00180
00181 float aspect = sw / sh;
00182
00183
00184 float newmaxh = maxh;
00185 float newmaxw = aspect * newmaxh;
00186 if (newmaxw < maxw) {
00187 newmaxw = maxw;
00188 newmaxh = maxw / aspect;
00189 }
00190
00191
00192 float newminh = minh;
00193 float newminw = aspect * newminh;
00194 if (minw < newminw) {
00195 newminw = minw;
00196 newminh = newminw / aspect;
00197 }
00198
00199
00200 float vw = (1.0f - _zoom) * (newmaxw - newminw) + newminw;
00201 float vh = (1.0f - _zoom) * (newmaxh - newminh) + newminh;
00202
00203 _view.setWidth(int(vw));
00204 _view.setHeight(int(vh));
00205
00206
00207
00208
00209 float vdx = vw * (float(screendx) / sw);
00210 float vdy = vh * (float(screendy) / sh);
00211
00212
00213 _desiredX = qBound(0.0f, _desiredX + vdx, iw);
00214 _desiredY = qBound(0.0f, _desiredY + vdy, ih);
00215 _view.moveCenter(QPoint(int(_desiredX), int(_desiredY)));
00216
00217 QPoint viewCenter = _view.center();
00218 float vx = viewCenter.x();
00219 float vy = viewCenter.y();
00220
00221
00222
00223
00224
00225
00226
00227 vdx = 0;
00228 vdy = 0;
00229
00230 if (iw <= vw) {
00231 vdx = (iw / 2.0f) - vx;
00232 } else {
00233
00234 float vl = float(_view.left());
00235 float vr = float(_view.right());
00236 if (vl < 0) {
00237 vdx = -vl;
00238 } else if (vr > iw) {
00239 vdx = iw - vr;
00240 }
00241 }
00242
00243 if (ih <= vh) {
00244 vdy = (ih / 2.0f) - vy;
00245 } else {
00246
00247 float vt = float(_view.top());
00248 float vb = float(_view.bottom());
00249 if (vt < 0) {
00250 vdy = -vt;
00251 } else if (vb > ih) {
00252 vdy = ih - vb;
00253 }
00254 }
00255
00256 _view.translate(int(vdx), int(vdy));
00257 }
00258
00259
00260 void
00261 ZImageView::resetZoomPoint()
00262 {
00263 QPoint viewCenter = _view.center();
00264 _desiredX = viewCenter.x();
00265 _desiredY = viewCenter.y();
00266 }
00267
00268
00269
00270 void
00271 ZImageView::paintEvent(QPaintEvent*)
00272 {
00273 updateViewport();
00274 drawScaledImage();
00275 }
00276
00277
00278
00279 void
00280 ZImageView::zoom(QPoint zoomAt, float pct)
00281 {
00282 _desiredX = zoomAt.x();
00283 _desiredY = zoomAt.y();
00284 zoom(pct);
00285 }
00286
00287
00288 void
00289 ZImageView::zoom(float pct)
00290 {
00291 _zoom = qBound(0.0f, pct, 1.0f);
00292 repaint();
00293 }
00294
00295
00296 void
00297 ZImageView::zoomIn()
00298 {
00299 zoom(_zoom + .1);
00300 }
00301
00302
00303 void
00304 ZImageView::zoomOut()
00305 {
00306 zoom(_zoom - .1);
00307 }
00308
00309
00310 void
00311 ZImageView::mousePressEvent(QMouseEvent *e)
00312 {
00313 e->accept();
00314 setCursor(CURSOR_MOUSE_PRESS);
00315 _mouseX = e->x();
00316 _mouseY = e->y();
00317 }
00318
00319
00320 void
00321 ZImageView::mouseReleaseEvent(QMouseEvent *e)
00322 {
00323 e->accept();
00324 setCursor(CURSOR_NORMAL);
00325 updateViewport();
00326 resetZoomPoint();
00327 }
00328
00329
00330
00331
00332 void
00333 ZImageView::mouseDoubleClickEvent(QMouseEvent *e)
00334 {
00335 e->accept();
00336
00337 QPoint center = rect().center();
00338 int dx = e->x() - center.x();
00339 int dy = e->y() - center.y();
00340 updateViewport(dx, dy);
00341 resetZoomPoint();
00342
00343 Qt::MouseButton btn = e->button();
00344 if (btn == Qt::LeftButton)
00345 zoomIn();
00346 else if (btn == Qt::RightButton)
00347 zoomOut();
00348 }
00349
00350
00351 void
00352 ZImageView::mouseMoveEvent(QMouseEvent *e)
00353 {
00354 e->accept();
00355 int dx = _mouseX - e->x();
00356 int dy = _mouseY - e->y();
00357 _mouseX = e->x();
00358 _mouseY = e->y();
00359
00360 updateViewport(dx, dy);
00361 if (0.001 <= _zoom) {
00362 repaint();
00363 }
00364 }
00365
00366 void
00367 ZImageView::wheelEvent(QWheelEvent *e)
00368 {
00369 if (e->delta() > 0) {
00370 zoomIn();
00371 } else {
00372 zoomOut();
00373 }
00374 }