1 /*
2  * Copyright (c) 2005-2019 Libor Pecháček.
3  * Copyright 2020 Kai Pastor
4  *
5  * This file is part of CoVe
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU Lesser General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this program. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 #include "ImageView.h"
22 
23 #include <cmath>
24 
25 #include <QAction>
26 #include <QBitmap>
27 #include <QBrush>
28 #include <QColor>
29 #include <QCursor>
30 #include <QFlags>
31 #include <QGuiApplication>
32 #include <QImage>
33 #include <QMouseEvent>
34 #include <QPaintEvent>
35 #include <QPainter>
36 #include <QRgb>
37 #include <QScrollBar>
38 #include <QSize>
39 #include <QVector>
40 #include <QWheelEvent>
41 #include <QWidget>
42 #include <Qt>
43 
44 class QMouseEvent;
45 class QWheelEvent;
46 
47 namespace cove {
48 //@{
49 //! \ingroup gui
50 
51 /*! \class ImageWidget
52   \brief QWidget that draws a QImage on its face.
53  */
54 
55 /*! \var const QImage* ImageWidget::dispImage
56   QImage to be displayed.
57   \sa setImage
58 */
59 
60 /*! \var float ImageWidget::dispMagnification
61   Magnification factor of image display.
62   \sa setMagnification
63 */
64 
65 /*! \var bool ImageWidget::scalingSmooth
66   Whether the Qt::SmoothTransformation options should be used when scaling
67   image.
68   \sa setSmoothScaling
69 */
70 
71 /*! \var bool ImageWidget::dispRealPaintEnabled
72   Do or don't do real paint when moving the image.  Real paint is disabled as
73   long as the user moves the image.
74   \sa setRealPaintEnabled
75 */
76 
77 /*! \var QRect ImageWidget::drect
78   Rectangle that is displayed when doing zoom-in operation.
79 */
80 
81 //! Default constructor.
ImageWidget(QWidget * parent)82 ImageWidget::ImageWidget(QWidget* parent)
83 	: QWidget(parent)
84 {}
85 
86 //! Destructor.
87 ImageWidget::~ImageWidget() = default;
88 
89 //! Painting event handler.
paintEvent(QPaintEvent * pe)90 void ImageWidget::paintEvent(QPaintEvent* pe)
91 {
92 	if (!dispRealPaintEnabled) return;
93 	QPainter p(this);
94 	QRect r = pe->rect();
95 
96 	// if there is an dispImage and is not a null dispImage draw it
97 	if (dispImage && !dispImage->isNull())
98 	{
99 		// 1-bit deep dispImages are drawn in different way by painter.  Their
100 		// native
101 		// colors are ignored.
102 		if (dispImage->depth() == 1)
103 		{
104 			p.setBackground(QBrush(dispImage->color(0)));
105 			p.setPen(dispImage->color(1));
106 		}
107 
108 		// adjust coordinates
109 		int w = int(std::ceil(r.width() / dispMagnification)) + 1,
110 			h = int(std::ceil(r.height() / dispMagnification)) + 1,
111 			x = int(std::floor(r.x() / dispMagnification)),
112 			y = int(std::floor(r.y() / dispMagnification));
113 
114 		// create cut of the original dispImage
115 		// Workaround Qt4 bug in copy(QRect(...))
116 		if (y + h > dispImage->height()) h = dispImage->height() - y;
117 		QImage copy = dispImage->copy(QRect(x, y, w, h));
118 
119 		if (!copy.isNull())
120 		{
121 			// Gray out the image when widget is disabled.
122 			if (!isEnabled())
123 			{
124 				// copy = copy.convertToFormat(copy.format(),
125 				// Qt::MonoOnly|Qt::AvoidDither);
126 				// Qt 4 workaround - MonoOnly doesn't work
127 				if (copy.depth() == 32)
128 				{
129 					int p = copy.width() * copy.height();
130 					QRgb* b = reinterpret_cast<QRgb*>(copy.bits());
131 					while (p--)
132 					{
133 						int I = qGray(*b);
134 						*b++ = qRgb(I, I, I);
135 					}
136 				}
137 				else
138 				{
139 					QVector<QRgb> ct = copy.colorTable();
140 					for (auto& color : ct)
141 					{
142 						auto const gray = qGray(color);
143 						color = qRgb(gray, gray, gray);
144 					}
145 					copy.setColorTable(ct);
146 				}
147 			}
148 
149 			// scale it
150 			if (dispMagnification != 1)
151 			{
152 				copy = copy.scaled(int(w * dispMagnification),
153 								   int(h * dispMagnification),
154 								   Qt::IgnoreAspectRatio,
155 								   scalingSmooth ? Qt::SmoothTransformation
156 												 : Qt::FastTransformation);
157 			}
158 
159 			// and draw the copy onto widget
160 			p.drawImage(
161 				QPoint(int(x * dispMagnification), int(y * dispMagnification)),
162 				copy);
163 		}
164 	}
165 
166 	if (!drect.isNull())
167 	{
168 		p.setPen(QColor(Qt::magenta));
169 		p.setBrush(QColor(255, 128, 255, 64));
170 		p.drawRect(drect);
171 	}
172 }
173 
174 //! What dispImage should be viewed.
setImage(const QImage * im)175 void ImageWidget::setImage(const QImage* im)
176 {
177 	dispImage = im;
178 	setMagnification(magnification());
179 	update();
180 }
181 
182 /*! \fn const QImage* ImageWidget::image() const
183  * Returns pointer to currently displayed bitmap.
184  */
185 
186 
187 //! What dispMagnification should be used. 1 == no dispMagnification, < 1 size
188 //! reduction.
setMagnification(qreal mag)189 void ImageWidget::setMagnification(qreal mag)
190 {
191 	if (dispImage)
192 	{
193 		int w = static_cast<int>(mag * dispImage->width()),
194 			h = static_cast<int>(mag * dispImage->height());
195 		setMinimumSize(w, h);
196 		resize(w, h);
197 	}
198 	dispMagnification = mag;
199 }
200 
201 /*! \fn qreal ImageWidget::magnification() const
202  * Returns current magnification used.
203  * \sa setMagnification
204  */
205 
206 
207 /*! Use smooth scaling (QImage::smoothScale).
208  \sa scalingSmooth */
setSmoothScaling(bool ss)209 void ImageWidget::setSmoothScaling(bool ss)
210 {
211 	bool doupdate = scalingSmooth ^ ss;
212 	scalingSmooth = ss;
213 	if (doupdate) update();
214 }
215 
216 /*! \fn bool ImageWidget::smoothScaling() const
217  * Returns value of the scalingSmooth flag.
218  * \sa setSmoothScaling
219  */
220 
221 
222 /*! Do or do not real do painting.  When set to false, paints only background.
223  \sa dispRealPaintEnabled */
setRealPaintEnabled(bool ss)224 void ImageWidget::setRealPaintEnabled(bool ss)
225 {
226 	dispRealPaintEnabled = ss;
227 	if (dispRealPaintEnabled) update();
228 }
229 
230 /*! \fn bool ImageWidget::realPaintEnabled() const
231  * Returns value of the scalingSmooth flag.
232  * \sa setRealPaintEnabled
233  */
234 
235 
236 /*! Sets displayed zoom-in rectangle.
237   \sa drect */
displayRect(const QRect & r)238 void ImageWidget::displayRect(const QRect& r)
239 {
240 	QRect updreg = r.adjusted(-1, -1, 2, 2);
241 
242 	if (drect.isValid()) updreg |= drect.adjusted(-1, -1, 2, 2);
243 
244 	drect = r;
245 	update(updreg);
246 }
247 
248 /*! \class ImageView
249  * \brief Provides scrollable view of an QImage.
250  *
251  * Invariant: After construction and before destruction, the widget() is
252  * assumed to be an ImageWidget. Do not call setWidget() with another
253  * type.
254  */
255 
256 /*! \var QPoint ImageView::dragStartPos
257  Point where dragging started when zooming in. */
258 /*! \var QPoint ImageView::dragCurPos
259  Current point where dragging is when zooming in. */
260 /*! \var QRect ImageView::zoomRect
261  THe light magenta semitransparent rectangle used when zoming in. */
262 /*! \var OperatingMode ImageView::opMode
263  Current operation mode as selected in context menu. */
264 /*! \var int ImageView::lastSliderHPos
265  Value of horizontal slider used when moving image. */
266 /*! \var int ImageView::lastSliderVPos
267  Value of vertical slider used when moving image. */
268 /*! \enum ImageView::OperatingMode
269   Operation mode as selected in context menu.
270   \sa opMode */
271 /*! \var ImageView::OperatingMode ImageView::MOVE
272  Move mode. */
273 /*! \var ImageView::OperatingMode ImageView::ZOOM_IN
274  Zoom in mode. */
275 /*! \var ImageView::OperatingMode ImageView::ZOOM_OUT
276  Zoom out mode. */
277 /*! \fn void ImageView::magnificationChanged(float oldmag, float mag)
278   Signal emitted when zoom ratio changes. */
279 
280 //! Default constructor.
ImageView(QWidget * parent)281 ImageView::ImageView(QWidget* parent)
282     : ImageView(new ImageWidget(), parent)
283 {}
284 
285 //! Constructs an image view for the given image_widget.
ImageView(ImageWidget * image_widget,QWidget * parent)286 ImageView::ImageView(ImageWidget* image_widget, QWidget* parent)
287 	: QScrollArea(parent)
288 {
289 	setWidget(image_widget);
290 	reset();
291 	QAction* a;
292 	addAction(a = new QAction(tr("Move"), this));
293 	connect(a, SIGNAL(triggered(bool)), this, SLOT(setMoveMode()));
294 	addAction(a = new QAction(tr("Zoom in"), this));
295 	connect(a, SIGNAL(triggered(bool)), this, SLOT(setZoomInMode()));
296 	addAction(a = new QAction(tr("Zoom out"), this));
297 	connect(a, SIGNAL(triggered(bool)), this, SLOT(setZoomOutMode()));
298 	addAction(a = new QAction(this));
299 	a->setSeparator(true);
300 	addAction(a = new QAction(tr("Original size"), this));
301 	connect(a, SIGNAL(triggered(bool)), this, SLOT(setOrigSize()));
302 	addAction(a = new QAction(tr("Smooth scaling"), this));
303 	a->setCheckable(true);
304 	connect(a, SIGNAL(toggled(bool)), this, SLOT(setSmoothScaling(bool)));
305 	setContextMenuPolicy(Qt::ActionsContextMenu);
306 }
307 
308 ImageView::~ImageView() = default;
309 
310 //! Resets QImaeView into its initial state.  I.e. move mode, magnification 1,
311 //! scrollbars 0.
reset()312 void ImageView::reset()
313 {
314 	setMoveMode();
315 	setMagnification(1);
316 	horizontalScrollBar()->setValue(0);
317 	verticalScrollBar()->setValue(0);
318 }
319 
320 //! Mouse wheel based zooming.
wheelEvent(QWheelEvent * event)321 void ImageView::wheelEvent(QWheelEvent* event)
322 {
323 	static QPoint accumulator;
324 	static int stepsize = 8 * 15 * 2;
325 
326 	accumulator += event->angleDelta();
327 	if (abs(accumulator.y()) >= stepsize)
328 	{
329 		int sgn = accumulator.y() / abs(accumulator.y());
330 		accumulator.ry() -= stepsize * sgn;
331 		double nm = magnification() * pow(2, sgn);
332 		if (nm < 32 && nm > 1 / 32) setMagnification(nm);
333 	}
334 }
335 
336 //! Handles mouse click.
mousePressEvent(QMouseEvent * event)337 void ImageView::mousePressEvent(QMouseEvent* event)
338 {
339 	if (event->button() != Qt::LeftButton) return;
340 
341 	auto* iw = imageWidget();
342 
343 	if (opMode == ZOOM_IN ||
344 		(opMode == MOVE &&
345 		 QGuiApplication::keyboardModifiers() == Qt::ControlModifier))
346 	{
347 		dragStartPos = event->pos();
348 	}
349 	else if (opMode == MOVE)
350 	{
351 		dragStartPos = event->pos();
352 		iw->setRealPaintEnabled(false);
353 		lastSliderHPos = horizontalScrollBar()->value();
354 		lastSliderVPos = verticalScrollBar()->value();
355 	}
356 	else if (opMode == ZOOM_OUT)
357 	{
358 		double mwm = viewport()->width() / iw->width();
359 		double mhm = viewport()->height() / iw->height();
360 		double nm = magnification() / 2;
361 		if (nm > 1 / 32 && (nm <= 1 || nm >= mwm || nm >= mhm))
362 			setMagnification(nm);
363 	}
364 }
365 
366 //! Handles mouse drag when moving image or zooming in.
mouseMoveEvent(QMouseEvent * event)367 void ImageView::mouseMoveEvent(QMouseEvent* event)
368 {
369 	if (!(event->buttons() & Qt::LeftButton)) return;
370 
371 	auto* iw = imageWidget();
372 
373 	if (opMode == ZOOM_IN ||
374 		(opMode == MOVE &&
375 		 QGuiApplication::keyboardModifiers() == Qt::ControlModifier))
376 	{
377 		if ((event->pos() - dragStartPos).manhattanLength() > 5)
378 		{
379 			dragCurPos = event->pos();
380 
381 			QRect vportrect = viewport()->rect();
382 			if (!vportrect.contains(dragCurPos))
383 			{
384 				int dx = 0, dy = 0, t;
385 				if ((t = dragCurPos.x() - vportrect.right()) > 0)
386 					dx -= t;
387 				else if ((t = dragCurPos.x() - vportrect.left()) < 0)
388 					dx -= t;
389 
390 				if ((t = dragCurPos.y() - vportrect.bottom()) > 0)
391 					dy -= t;
392 				else if ((t = dragCurPos.y() - vportrect.top()) < 0)
393 					dy -= t;
394 
395 				QPoint d = iw->pos() + QPoint(dx, dy);
396 				if (d.x() < (t = viewport()->width() - iw->width()))
397 					d.setX(t);
398 				else if (d.x() > 0)
399 					d.setX(0);
400 				if (d.y() < (t = viewport()->height() - iw->height()))
401 					d.setY(t);
402 				else if (d.y() > 0)
403 					d.setY(0);
404 				dragStartPos += d - iw->pos();
405 				iw->move(d);
406 			}
407 
408 			QPoint dist = dragStartPos - dragCurPos;
409 			int x, y, w, h;
410 
411 			if (dist.x() > 0)
412 			{
413 				x = dragCurPos.x();
414 				w = dist.x();
415 			}
416 			else
417 			{
418 				x = dragStartPos.x();
419 				w = -dist.x();
420 			}
421 
422 			if (dist.y() > 0)
423 			{
424 				y = dragCurPos.y();
425 				h = dist.y();
426 			}
427 			else
428 			{
429 				y = dragStartPos.y();
430 				h = -dist.y();
431 			}
432 
433 			zoomRect = QRect(QPoint(x, y) - iw->pos(), QSize(w, h))
434 						   .intersected(iw->rect().adjusted(0, 0, -1, -1));
435 			iw->displayRect(zoomRect);
436 		}
437 	}
438 	else if (opMode == MOVE)
439 	{
440 		QPoint pixmapOffset = event->pos() - dragStartPos;
441 		verticalScrollBar()->setValue(lastSliderVPos - pixmapOffset.y());
442 		horizontalScrollBar()->setValue(lastSliderHPos - pixmapOffset.x());
443 	}
444 }
445 
446 //! Handles end-of-drag.
mouseReleaseEvent(QMouseEvent * event)447 void ImageView::mouseReleaseEvent(QMouseEvent* event)
448 {
449 	if (event->button() != Qt::LeftButton) return;
450 
451 	auto* iw = imageWidget();
452 
453 	if (opMode == ZOOM_IN ||
454 		(opMode == MOVE &&
455 		 QGuiApplication::keyboardModifiers() == Qt::ControlModifier))
456 	{
457 		int dx, dy;
458 		if ((event->pos() - dragStartPos).manhattanLength() > 5 &&
459 			zoomRect.width() && zoomRect.height())
460 		{
461 			double m = viewport()->width() / zoomRect.width(),
462 				   n = viewport()->height() / zoomRect.height(),
463 				   rmag = m > n ? n : m; // minimum of those two
464 			// max possible 2^n magnif. with n integer
465 			double magmul = pow(2, trunc(log(rmag) / log(2)));
466 			if (floor(magmul) == 0.0) magmul = 1;
467 			if (magnification() * magmul > 16) magmul = 16.0 / magnification();
468 			rmag = magnification() * magmul;
469 			QPoint zrc = zoomRect.center() + iw->pos();
470 			dx = int(magmul * (zrc.x() - viewport()->size().width() / 2));
471 			dy = int(magmul * (zrc.y() - viewport()->size().height() / 2));
472 			iw->displayRect(QRect());
473 			setMagnification(rmag);
474 		}
475 		else
476 		{
477 			int magmul = magnification() < 16 ? 2 : 1;
478 			setMagnification(magnification() * magmul);
479 			dx = magmul * (event->pos().x() - viewport()->size().width() / 2);
480 			dy = magmul * (event->pos().y() - viewport()->size().height() / 2);
481 		}
482 		verticalScrollBar()->setValue(verticalScrollBar()->value() + dy);
483 		horizontalScrollBar()->setValue(horizontalScrollBar()->value() + dx);
484 	}
485 	else if (opMode == MOVE)
486 	{
487 		QPoint pixmapOffset = event->pos() - dragStartPos;
488 		iw->setRealPaintEnabled(true);
489 		verticalScrollBar()->setValue(lastSliderVPos - pixmapOffset.y());
490 		horizontalScrollBar()->setValue(lastSliderHPos - pixmapOffset.x());
491 	}
492 }
493 
494 //! What dispImage should be viewed.
setImage(const QImage * im)495 void ImageView::setImage(const QImage* im)
496 {
497 	imageWidget()->setImage(im);
498 }
499 
500 //! return pointer to currently displayed bitmap.
image() const501 const QImage* ImageView::image() const
502 {
503 	return imageWidget()->image();
504 }
505 
506 //! What dispMagnification should be used. 1 == no dispMagnification, < 1 size
507 //! reduction.
setMagnification(qreal mag)508 void ImageView::setMagnification(qreal mag)
509 {
510 	auto* iw = imageWidget();
511 
512 	double oldmag = iw->magnification(), magratio = mag / oldmag,
513 		   oneMmagratio = 1 - magratio;
514 	int w = viewport()->size().width(), h = viewport()->size().height();
515 	int dx = (int)((iw->pos().x() - w / 2.0) * oneMmagratio),
516 		dy = (int)((iw->pos().y() - h / 2.0) * oneMmagratio);
517 	iw->setMagnification(mag);
518 	verticalScrollBar()->setValue(verticalScrollBar()->value() + dy);
519 	horizontalScrollBar()->setValue(horizontalScrollBar()->value() + dx);
520 	if (oldmag != mag) emit magnificationChanged(oldmag, mag);
521 }
522 
523 //! Current magnification used.
magnification() const524 qreal ImageView::magnification() const
525 {
526 	return imageWidget()->magnification();
527 }
528 
529 //! Use smooth scaling (QImage::smoothScale).
setSmoothScaling(bool ss)530 void ImageView::setSmoothScaling(bool ss)
531 {
532 	imageWidget()->setSmoothScaling(ss);
533 }
534 
535 //! Returns true when smooth scaling is enabled.
smoothScaling() const536 bool ImageView::smoothScaling() const
537 {
538 	return imageWidget()->smoothScaling();
539 }
540 
541 //! Slot for context menu.
setMoveMode()542 void ImageView::setMoveMode()
543 {
544 	widget()->setCursor(QCursor(Qt::SizeAllCursor));
545 	opMode = MOVE;
546 }
547 
548 //! Slot for context menu.
setZoomInMode()549 void ImageView::setZoomInMode()
550 {
551 #define zoomin_width 32
552 #define zoomin_height 32
553 	static unsigned char zoomin_bits[] = {
554 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
555 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
556 		0x00, 0x38, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00,
557 		0x80, 0x00, 0x02, 0x00, 0x40, 0x10, 0x04, 0x00, 0x40, 0x10, 0x04, 0x00,
558 		0x20, 0x10, 0x08, 0x00, 0x20, 0xfe, 0x08, 0x00, 0x20, 0x10, 0x08, 0x00,
559 		0x40, 0x10, 0x04, 0x00, 0x40, 0x10, 0x04, 0x00, 0x80, 0x00, 0x02, 0x00,
560 		0x00, 0x01, 0x07, 0x00, 0x00, 0xc6, 0x0e, 0x00, 0x00, 0x38, 0x1c, 0x00,
561 		0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0xe0, 0x00,
562 		0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00,
563 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
564 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
565 
566 #define zoomin_mask_width 32
567 #define zoomin_mask_height 32
568 	static unsigned char zoomin_mask_bits[] = {
569 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
570 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00,
571 		0x00, 0xfe, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x80, 0xc7, 0x03, 0x00,
572 		0xc0, 0x11, 0x07, 0x00, 0xe0, 0x38, 0x0e, 0x00, 0xe0, 0x38, 0x0e, 0x00,
573 		0x70, 0xfe, 0x1c, 0x00, 0x70, 0xff, 0x1d, 0x00, 0x70, 0xfe, 0x1c, 0x00,
574 		0xe0, 0x38, 0x0e, 0x00, 0xe0, 0x38, 0x0e, 0x00, 0xc0, 0x11, 0x07, 0x00,
575 		0x80, 0xc7, 0x0f, 0x00, 0x00, 0xff, 0x1f, 0x00, 0x00, 0xfe, 0x3e, 0x00,
576 		0x00, 0x38, 0x7c, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0xf0, 0x01,
577 		0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x80, 0x01,
578 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
579 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
580 
581 	widget()->setCursor(
582 		QCursor(QBitmap::fromData(QSize(zoomin_width, zoomin_height),
583 								  zoomin_bits, QImage::Format_MonoLSB),
584 				QBitmap::fromData(QSize(zoomin_mask_width, zoomin_mask_height),
585 								  zoomin_mask_bits, QImage::Format_MonoLSB),
586 				13, 13));
587 	opMode = ZOOM_IN;
588 }
589 
590 //! Slot for context menu.
setZoomOutMode()591 void ImageView::setZoomOutMode()
592 {
593 #define zoomout_width 32
594 #define zoomout_height 32
595 	static unsigned char zoomout_bits[] = {
596 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
597 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
598 		0x00, 0x38, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00,
599 		0x80, 0x00, 0x02, 0x00, 0x40, 0x00, 0x04, 0x00, 0x40, 0x00, 0x04, 0x00,
600 		0x20, 0x00, 0x08, 0x00, 0x20, 0xfe, 0x08, 0x00, 0x20, 0x00, 0x08, 0x00,
601 		0x40, 0x00, 0x04, 0x00, 0x40, 0x00, 0x04, 0x00, 0x80, 0x00, 0x02, 0x00,
602 		0x00, 0x01, 0x07, 0x00, 0x00, 0xc6, 0x0e, 0x00, 0x00, 0x38, 0x1c, 0x00,
603 		0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0xe0, 0x00,
604 		0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00,
605 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
606 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
607 
608 #define zoomout_mask_width 32
609 #define zoomout_mask_height 32
610 	static unsigned char zoomout_mask_bits[] = {
611 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
612 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00,
613 		0x00, 0xfe, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x80, 0xc7, 0x03, 0x00,
614 		0xc0, 0x01, 0x07, 0x00, 0xe0, 0x00, 0x0e, 0x00, 0xe0, 0x00, 0x0e, 0x00,
615 		0x70, 0xfe, 0x1c, 0x00, 0x70, 0xff, 0x1d, 0x00, 0x70, 0xfe, 0x1c, 0x00,
616 		0xe0, 0x00, 0x0e, 0x00, 0xe0, 0x00, 0x0e, 0x00, 0xc0, 0x01, 0x07, 0x00,
617 		0x80, 0xc7, 0x0f, 0x00, 0x00, 0xff, 0x1f, 0x00, 0x00, 0xfe, 0x3e, 0x00,
618 		0x00, 0x38, 0x7c, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0xf0, 0x01,
619 		0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x80, 0x01,
620 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
621 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
622 
623 	widget()->setCursor(QCursor(
624 		QBitmap::fromData(QSize(zoomout_width, zoomout_height), zoomout_bits,
625 						  QImage::Format_MonoLSB),
626 		QBitmap::fromData(QSize(zoomout_mask_width, zoomout_mask_height),
627 						  zoomout_mask_bits, QImage::Format_MonoLSB),
628 		13, 13));
629 	opMode = ZOOM_OUT;
630 }
631 
632 //! Slot for context menu. Sets magnification to 1.
setOrigSize()633 void ImageView::setOrigSize()
634 {
635 	setMagnification(1);
636 }
637 } // cove
638 
639 //@}
640