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