2 Gwenview: an image viewer
3 Copyright 2007 Aurélien Gâteau <aurelien.gateau@free.fr>
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 #include "imagescaler.moc"
30 #include <lib/document/document.h>
31 #include <lib/paintutils.h>
37 #define LOG(x) kDebug() << x
44 // Amount of pixels to keep so that smooth scale is correct
45 static const int SMOOTH_MARGIN
= 3;
47 struct ImageScalerPrivate
{
48 Qt::TransformationMode mTransformationMode
;
49 Document::Ptr mDocument
;
54 ImageScaler::ImageScaler(QObject
* parent
)
56 , d(new ImageScalerPrivate
) {
57 d
->mTransformationMode
= Qt::FastTransformation
;
61 ImageScaler::~ImageScaler() {
65 void ImageScaler::setDocument(Document::Ptr document
) {
67 disconnect(d
->mDocument
.data(), 0, this, 0);
69 d
->mDocument
= document
;
70 connect(d
->mDocument
.data(), SIGNAL(downSampledImageReady()),
74 void ImageScaler::setZoom(qreal zoom
) {
78 void ImageScaler::setTransformationMode(Qt::TransformationMode mode
) {
79 d
->mTransformationMode
= mode
;
82 void ImageScaler::setDestinationRegion(const QRegion
& region
) {
85 if (d
->mRegion
.isEmpty()) {
89 if (d
->mDocument
&& d
->mZoom
> 0) {
95 void ImageScaler::doScale() {
96 if (d
->mZoom
< Document::maxDownSampledZoom()) {
97 if (!d
->mDocument
->prepareDownSampledImageForZoom(d
->mZoom
)) {
98 LOG("Asked for a down sampled image");
101 } else if (d
->mDocument
->image().isNull()) {
102 LOG("Asked for the full image");
103 d
->mDocument
->loadFullImage();
108 Q_FOREACH(const QRect
& rect
, d
->mRegion
.rects()) {
116 void ImageScaler::scaleRect(const QRect
& rect
) {
117 const qreal REAL_DELTA
= 0.001;
118 if (qAbs(d
->mZoom
- 1.0) < REAL_DELTA
) {
119 QImage tmp
= d
->mDocument
->image().copy(rect
);
120 tmp
.convertToFormat(QImage::Format_ARGB32_Premultiplied
);
121 scaledRect(rect
.left(), rect
.top(), tmp
);
127 if (d
->mZoom
< Document::maxDownSampledZoom()) {
128 image
= d
->mDocument
->downSampledImageForZoom(d
->mZoom
);
129 Q_ASSERT(!image
.isNull());
130 qreal zoom1
= qreal(image
.width()) / d
->mDocument
->width();
131 zoom
= d
->mZoom
/ zoom1
;
133 image
= d
->mDocument
->image();
136 // If rect contains "half" pixels, make sure sourceRect includes them
141 rect
.height() / zoom
);
143 sourceRectF
= sourceRectF
.intersected(image
.rect());
144 QRect sourceRect
= PaintUtils::containingRect(sourceRectF
);
145 if (sourceRect
.isEmpty()) {
149 // Compute smooth margin
150 bool needsSmoothMargins
= d
->mTransformationMode
== Qt::SmoothTransformation
;
152 int sourceLeftMargin
, sourceRightMargin
, sourceTopMargin
, sourceBottomMargin
;
153 int destLeftMargin
, destRightMargin
, destTopMargin
, destBottomMargin
;
154 if (needsSmoothMargins
) {
155 sourceLeftMargin
= qMin(sourceRect
.left(), SMOOTH_MARGIN
);
156 sourceTopMargin
= qMin(sourceRect
.top(), SMOOTH_MARGIN
);
157 sourceRightMargin
= qMin(image
.rect().right() - sourceRect
.right(), SMOOTH_MARGIN
);
158 sourceBottomMargin
= qMin(image
.rect().bottom() - sourceRect
.bottom(), SMOOTH_MARGIN
);
164 destLeftMargin
= int(sourceLeftMargin
* zoom
);
165 destTopMargin
= int(sourceTopMargin
* zoom
);
166 destRightMargin
= int(sourceRightMargin
* zoom
);
167 destBottomMargin
= int(sourceBottomMargin
* zoom
);
169 sourceLeftMargin
= sourceRightMargin
= sourceTopMargin
= sourceBottomMargin
= 0;
170 destLeftMargin
= destRightMargin
= destTopMargin
= destBottomMargin
= 0;
173 // destRect is almost like rect, but it contains only "full" pixels
174 QRectF destRectF
= QRectF(
175 sourceRect
.left() * zoom
,
176 sourceRect
.top() * zoom
,
177 sourceRect
.width() * zoom
,
178 sourceRect
.height() * zoom
180 QRect destRect
= PaintUtils::containingRect(destRectF
);
183 tmp
= image
.copy(sourceRect
);
184 tmp
.convertToFormat(QImage::Format_ARGB32_Premultiplied
);
188 Qt::IgnoreAspectRatio
, // Do not use KeepAspectRatio, it can lead to skipped rows or columns
189 d
->mTransformationMode
);
191 if (needsSmoothMargins
) {
193 destLeftMargin
, destTopMargin
,
194 destRect
.width() - (destLeftMargin
+ destRightMargin
),
195 destRect
.height() - (destTopMargin
+ destBottomMargin
)
199 scaledRect(destRect
.left() + destLeftMargin
, destRect
.top() + destTopMargin
, tmp
);