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