1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29
30#include <QtTest/QtTest>
31#include <qpixmap.h>
32#include <private/qpixmapfilter_p.h>
33#include <qpainter.h>
34
35class tst_QPixmapFilter : public QObject
36{
37 Q_OBJECT
38
39private slots:
40 void colorizeSetColor();
41 void colorizeSetStrength();
42 void colorizeProcess();
43 void colorizeDraw();
44 void colorizeDrawStrength();
45 void colorizeDrawSubRect();
46 void colorizeProcessSubRect();
47 void convolutionBoundingRectFor();
48 void convolutionDrawSubRect();
49 void dropShadowBoundingRectFor();
50 void blurIndexed8();
51
52 void testDefaultImplementations();
53};
54
55class CustomFilter : public QPixmapFilter
56{
57public:
58 enum { Type = QPixmapFilter::UserFilter + 1 };
59
60 CustomFilter() : QPixmapFilter((QPixmapFilter::FilterType) Type, 0) { };
61
62 void draw(QPainter *p, const QPointF &pt, const QPixmap &src, const QRectF &srcRect = QRectF()) const {
63 p->drawPixmap(targetRect: QRectF(pt, srcRect.size()), pixmap: src, sourceRect: srcRect);
64 }
65};
66
67void tst_QPixmapFilter::testDefaultImplementations()
68{
69 CustomFilter filter;
70 QCOMPARE(filter.type(), (QPixmapFilter::FilterType) CustomFilter::Type);
71
72 QCOMPARE(filter.boundingRectFor(QRectF(1, 2, 4, 8)), QRectF(1, 2, 4, 8));
73
74 QPixmap src(10, 10);
75 src.fill(fillColor: Qt::blue);
76
77 QPixmap test(src.size());
78 QPainter p(&test);
79 filter.draw(p: &p, pt: QPointF(0, 0), src, srcRect: src.rect());
80 p.end();
81
82 QCOMPARE(test.toImage().pixel(0, 0), 0xff0000ff);
83}
84
85void tst_QPixmapFilter::colorizeSetColor()
86{
87 QPixmapColorizeFilter filter;
88 filter.setColor(QColor(50, 100, 200));
89 QCOMPARE(filter.color(), QColor(50, 100, 200));
90}
91
92void tst_QPixmapFilter::colorizeSetStrength()
93{
94 QPixmapColorizeFilter filter;
95 QCOMPARE(filter.strength(), qreal(1));
96 filter.setStrength(0.5);
97 QCOMPARE(filter.strength(), qreal(0.5));
98 filter.setStrength(0.0);
99 QCOMPARE(filter.strength(), qreal(0.0));
100}
101
102void tst_QPixmapFilter::colorizeProcess()
103{
104 QPixmapColorizeFilter filter;
105 filter.setColor(QColor(100, 100, 100));
106
107 QCOMPARE(filter.boundingRectFor(QRectF(0, 0, 50, 50)), QRectF(0, 0, 50, 50));
108 QCOMPARE(filter.boundingRectFor(QRectF(30, 20, 10, 40)), QRectF(30, 20, 10, 40));
109 QCOMPARE(filter.boundingRectFor(QRectF(2.2, 6.3, 11.4, 47.5)), QRectF(2.2, 6.3, 11.4, 47.5));
110
111 QPixmap source("noise.png");
112 QImage result(source.size(), QImage::Format_ARGB32_Premultiplied);
113 result.fill(pixel: 0);
114 QPainter p(&result);
115 filter.draw(painter: &p, dest: QPointF(0, 0), src: source);
116 p.end();
117 QImage resultImg = result;
118 for(int y = 0; y < resultImg.height(); y++)
119 {
120 for(int x = 0; x < resultImg.width(); x++)
121 {
122 QRgb pixel = resultImg.pixel(x,y);
123 QCOMPARE(qRed(pixel), qGreen(pixel));
124 QCOMPARE(qGreen(pixel), qBlue(pixel));
125 }
126 }
127}
128
129void tst_QPixmapFilter::colorizeDraw()
130{
131 QPixmapColorizeFilter filter;
132 filter.setColor(QColor(100, 100, 100));
133
134 QPixmap pixmap("noise.png");
135 QImage result(pixmap.size(), QImage::Format_ARGB32_Premultiplied);
136 QPainter painter(&result);
137 painter.setCompositionMode(QPainter::CompositionMode_Source);
138 painter.fillRect(result.rect(), color: QColor(128, 0, 0, 0));
139 painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
140 filter.draw(painter: &painter, dest: QPointF(0, 0), src: pixmap);
141 painter.end();
142
143 QImage resultImg = result;
144 for(int y = 0; y < resultImg.height(); y++)
145 {
146 for(int x = 0; x < resultImg.width(); x++)
147 {
148 QRgb pixel = resultImg.pixel(x,y);
149 QCOMPARE(qRed(pixel), qGreen(pixel));
150 QCOMPARE(qGreen(pixel), qBlue(pixel));
151 }
152 }
153}
154
155void tst_QPixmapFilter::colorizeDrawStrength()
156{
157 QPixmapColorizeFilter filter;
158 filter.setColor(Qt::blue);
159 filter.setStrength(0.3);
160
161 QImage source(256, 128, QImage::Format_ARGB32);
162 source.fill(pixel: qRgb(r: 255, g: 0, b: 0));
163 QPixmap pixmap = QPixmap::fromImage(image: source);
164
165 QImage result(pixmap.size(), QImage::Format_ARGB32_Premultiplied);
166 QPainter painter(&result);
167 painter.setCompositionMode(QPainter::CompositionMode_Source);
168 filter.draw(painter: &painter, dest: QPointF(0, 0), src: pixmap);
169 painter.end();
170
171 QImage resultImg = result;
172 for(int y = 0; y < resultImg.height(); y++)
173 {
174 for(int x = 0; x < resultImg.width(); x++)
175 {
176 QRgb pixel = resultImg.pixel(x,y);
177 QCOMPARE(qRed(pixel), 206);
178 QCOMPARE(qGreen(pixel), 26);
179 QCOMPARE(qBlue(pixel), 75);
180 }
181 }
182}
183
184void tst_QPixmapFilter::colorizeDrawSubRect()
185{
186 QPixmapColorizeFilter filter;
187 filter.setColor(QColor(255, 255, 255));
188
189 QPixmap pixmap("noise.png");
190 QImage result(pixmap.size(), QImage::Format_ARGB32_Premultiplied);
191 QPainter painter(&result);
192 painter.setCompositionMode(QPainter::CompositionMode_Source);
193 painter.fillRect(result.rect(), color: QColor(128, 0, 0, 255));
194 painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
195 filter.draw(painter: &painter, dest: QPointF(16, 16), src: pixmap, srcRect: QRectF(16, 16, 16, 16));
196 painter.end();
197
198 QImage resultImg = result;
199 QImage sourceImg = pixmap.toImage();
200 for(int y = 0; y < resultImg.height(); y++)
201 {
202 for(int x = 0; x < resultImg.width(); x++)
203 {
204 QRgb pixel = resultImg.pixel(x,y);
205 if(x>=16 && x<32 && y>=16 && y<32) {
206 QCOMPARE(qRed(pixel), qGreen(pixel));
207 QCOMPARE(qGreen(pixel), qBlue(pixel));
208 } else {
209 QCOMPARE(qRed(pixel), 128);
210 QCOMPARE(qGreen(pixel), 0);
211 QCOMPARE(qBlue(pixel), 0);
212 QCOMPARE(qAlpha(pixel), 255);
213 }
214 }
215 }
216}
217
218void tst_QPixmapFilter::colorizeProcessSubRect()
219{
220 QPixmapColorizeFilter filter;
221 filter.setColor(QColor(200, 200, 200));
222
223 QPixmap source("noise.png");
224 QImage result(QSize(16, 16), QImage::Format_ARGB32_Premultiplied);
225 result.fill(pixel: 0);
226 QPainter p(&result);
227 filter.draw(painter: &p, dest: QPointF(0, 0), src: source, srcRect: QRectF(16, 16, 16, 16));
228 p.end();
229
230 QImage resultImg = result;
231 for(int y = 0; y < resultImg.height(); y++)
232 {
233 for(int x = 0; x < resultImg.width(); x++)
234 {
235 QRgb pixel = resultImg.pixel(x,y);
236 QCOMPARE(qRed(pixel), qGreen(pixel));
237 QCOMPARE(qGreen(pixel), qBlue(pixel));
238 }
239 }
240}
241
242void tst_QPixmapFilter::convolutionBoundingRectFor()
243{
244 QPixmapConvolutionFilter filter;
245 QCOMPARE(filter.boundingRectFor(QRectF(0, 0, 50, 50)), QRectF(0, 0, 50, 50));
246 QCOMPARE(filter.boundingRectFor(QRectF(30, 20, 10, 40)), QRectF(30, 20, 10, 40));
247 QCOMPARE(filter.boundingRectFor(QRectF(2.2, 6.3, 11.4, 47.5)), QRectF(2.2, 6.3, 11.4, 47.5));
248 qreal kernel[] = {
249 0, 0, 0, 0,
250 0, 0, 0, 0,
251 0, 0, 0, 0,
252 0, 0, 0, 0
253 };
254 filter.setConvolutionKernel(matrix: kernel, rows: 2, columns: 2);
255 QCOMPARE(filter.boundingRectFor(QRectF(0, 0, 50, 50)), QRectF(-1, -1, 51, 51));
256 QCOMPARE(filter.boundingRectFor(QRectF(30, 20, 10, 40)), QRectF(29, 19, 11, 41));
257 QCOMPARE(filter.boundingRectFor(QRectF(2.2, 6.3, 11.4, 47.5)), QRectF(1.2, 5.3, 12.4, 48.5));
258
259 filter.setConvolutionKernel(matrix: kernel, rows: 3, columns: 3);
260 QCOMPARE(filter.boundingRectFor(QRectF(0, 0, 50, 50)), QRectF(-1, -1, 52, 52));
261 QCOMPARE(filter.boundingRectFor(QRectF(30, 20, 10, 40)), QRectF(29, 19, 12, 42));
262 QCOMPARE(filter.boundingRectFor(QRectF(2.2, 6.3, 11.4, 47.5)), QRectF(1.2, 5.3, 13.4, 49.5));
263
264 filter.setConvolutionKernel(matrix: kernel, rows: 4, columns: 4);
265 QCOMPARE(filter.boundingRectFor(QRectF(0, 0, 50, 50)), QRectF(-2, -2, 53, 53));
266 QCOMPARE(filter.boundingRectFor(QRectF(30, 20, 10, 40)), QRectF(28, 18, 13, 43));
267 QCOMPARE(filter.boundingRectFor(QRectF(2.2, 6.3, 11.4, 47.5)), QRectF(0.2, 4.3, 14.4, 50.5));
268}
269
270void tst_QPixmapFilter::convolutionDrawSubRect()
271{
272 QPixmapConvolutionFilter filter;
273 qreal kernel[] = {
274 0, 0, 0,
275 0, 0, 0,
276 0, 0, 1
277 };
278 filter.setConvolutionKernel(matrix: kernel, rows: 3, columns: 3);
279
280 QPixmap pixmap("noise.png");
281 QImage result(pixmap.size(), QImage::Format_ARGB32_Premultiplied);
282 QPainter painter(&result);
283 painter.setCompositionMode(QPainter::CompositionMode_Source);
284 painter.fillRect(result.rect(), color: QColor(128, 0, 0, 255));
285 painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
286 filter.draw(painter: &painter, dest: QPointF(16, 16), src: pixmap, srcRect: QRectF(16, 16, 16, 16));
287 painter.end();
288
289 QImage resultImg = result;
290 QImage sourceImg = pixmap.toImage();
291 for(int y = 0; y < resultImg.height()-1; y++)
292 {
293 for(int x = 0; x < resultImg.width()-1; x++)
294 {
295 QRgb pixel = resultImg.pixel(x,y);
296 QRgb srcPixel = sourceImg.pixel(x: x+1,y: y+1);
297 if(x>=15 && x<33 && y>=15 && y<33) {
298 QCOMPARE(pixel, srcPixel);
299 } else {
300 QCOMPARE(qRed(pixel), 128);
301 QCOMPARE(qGreen(pixel), 0);
302 QCOMPARE(qBlue(pixel), 0);
303 QCOMPARE(qAlpha(pixel), 255);
304 }
305 }
306 }
307
308
309 kernel[2] = 1;
310 kernel[8] = 0;
311 filter.setConvolutionKernel(matrix: kernel, rows: 3, columns: 3);
312
313 QPainter painter2(&result);
314 painter2.setCompositionMode(QPainter::CompositionMode_Source);
315 painter2.fillRect(result.rect(), color: QColor(128, 0, 0, 255));
316 painter2.setCompositionMode(QPainter::CompositionMode_SourceOver);
317 filter.draw(painter: &painter2, dest: QPointF(16, 16), src: pixmap, srcRect: QRectF(16, 16, 16, 16));
318 painter2.end();
319
320 resultImg = result;
321 sourceImg = pixmap.toImage();
322 for(int y = 1; y < resultImg.height(); y++)
323 {
324 for(int x = 0; x < resultImg.width()-1; x++)
325 {
326 QRgb pixel = resultImg.pixel(x,y);
327 QRgb srcPixel = sourceImg.pixel(x: x+1,y: y-1);
328 if(x>=15 && x<33 && y>=15 && y<33) {
329 QCOMPARE(pixel, srcPixel);
330 } else {
331 QCOMPARE(qRed(pixel), 128);
332 QCOMPARE(qGreen(pixel), 0);
333 QCOMPARE(qBlue(pixel), 0);
334 QCOMPARE(qAlpha(pixel), 255);
335 }
336 }
337 }
338
339}
340
341void tst_QPixmapFilter::dropShadowBoundingRectFor()
342{
343 QPixmapDropShadowFilter filter;
344 filter.setBlurRadius(0);
345
346 QCOMPARE(filter.blurRadius(), 0.);
347
348 const QRectF rect1(0, 0, 50, 50);
349 const QRectF rect2(30, 20, 10, 40);
350 const QRectF rect3(2.2, 6.3, 11.4, 47.5);
351
352 filter.setOffset(QPointF(0,0));
353 QCOMPARE(filter.boundingRectFor(rect1), rect1);
354 QCOMPARE(filter.boundingRectFor(rect2), rect2);
355 QCOMPARE(filter.boundingRectFor(rect3), rect3);
356
357 filter.setOffset(QPointF(1,1));
358 QCOMPARE(filter.offset(), QPointF(1, 1));
359 QCOMPARE(filter.boundingRectFor(rect1), rect1.adjusted(0, 0, 1, 1));
360 QCOMPARE(filter.boundingRectFor(rect2), rect2.adjusted(0, 0, 1, 1));
361 QCOMPARE(filter.boundingRectFor(rect3), rect3.adjusted(0, 0, 1, 1));
362
363 filter.setOffset(QPointF(-1,-1));
364 QCOMPARE(filter.boundingRectFor(rect1), rect1.adjusted(-1, -1, 0, 0));
365 QCOMPARE(filter.boundingRectFor(rect2), rect2.adjusted(-1, -1, 0, 0));
366 QCOMPARE(filter.boundingRectFor(rect3), rect3.adjusted(-1, -1, 0, 0));
367
368 filter.setBlurRadius(2);
369 filter.setOffset(QPointF(0,0));
370 qreal delta = 2;
371 QCOMPARE(filter.boundingRectFor(rect1), rect1.adjusted(-delta, -delta, delta, delta));
372 QCOMPARE(filter.boundingRectFor(rect2), rect2.adjusted(-delta, -delta, delta, delta));
373 QCOMPARE(filter.boundingRectFor(rect3), rect3.adjusted(-delta, -delta, delta, delta));
374
375 filter.setOffset(QPointF(1,1));
376 QCOMPARE(filter.boundingRectFor(rect1), rect1.adjusted(-delta + 1, -delta + 1, delta + 1, delta + 1));
377 QCOMPARE(filter.boundingRectFor(rect2), rect2.adjusted(-delta + 1, -delta + 1, delta + 1, delta + 1));
378 QCOMPARE(filter.boundingRectFor(rect3), rect3.adjusted(-delta + 1, -delta + 1, delta + 1, delta + 1));
379
380 filter.setOffset(QPointF(-10,-10));
381 QCOMPARE(filter.boundingRectFor(rect1), rect1.adjusted(-delta - 10, -delta - 10, 0, 0));
382 QCOMPARE(filter.boundingRectFor(rect2), rect2.adjusted(-delta - 10, -delta - 10, 0, 0));
383 QCOMPARE(filter.boundingRectFor(rect3), rect3.adjusted(-delta - 10, -delta - 10, 0, 0));
384}
385
386QT_BEGIN_NAMESPACE
387void qt_blurImage(QImage &blurImage, qreal radius, bool quality, int transposed);
388QT_END_NAMESPACE
389
390void tst_QPixmapFilter::blurIndexed8()
391{
392 QImage img(16, 32, QImage::Format_Indexed8);
393 img.setDevicePixelRatio(2);
394 img.setColorCount(256);
395 for (int i = 0; i < 256; ++i)
396 img.setColor(i, c: qRgb(r: i, g: i, b: i));
397
398 img.fill(pixel: 255);
399
400 QImage original = img;
401 qt_blurImage(blurImage&: img, radius: 10, quality: true, transposed: false);
402 QCOMPARE(original.size(), img.size());
403 QVERIFY2(qFuzzyCompare(img.devicePixelRatioF(), qreal(2)),
404 QByteArray::number(img.devicePixelRatioF()).constData());
405
406 original = img;
407 qt_blurImage(blurImage&: img, radius: 10, quality: true, transposed: true);
408 QVERIFY2(qFuzzyCompare(img.devicePixelRatioF(), qreal(2)),
409 QByteArray::number(img.devicePixelRatioF()).constData());
410 QCOMPARE(original.size(), QSize(img.height(), img.width()));
411}
412
413QTEST_MAIN(tst_QPixmapFilter)
414#include "tst_qpixmapfilter.moc"
415

source code of qtbase/tests/auto/widgets/effects/qpixmapfilter/tst_qpixmapfilter.cpp