1 /*
2  *  Copyright (c) 2012 Dmitry Kazakov <dimula73@gmail.com>
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18 
19 #include "kis_filter_weights_applicator_test.h"
20 
21 #include <QTest>
22 
23 #include <KoColor.h>
24 #include <KoColorSpace.h>
25 #include <KoColorSpaceRegistry.h>
26 #include "kis_paint_device.h"
27 #include "kistest.h"
28 
29 #include <sstream>
30 
31 //#define DEBUG_ENABLED
32 #include "kis_filter_weights_applicator.h"
33 
debugSpan(const KisFilterWeightsApplicator::BlendSpan & span)34 void debugSpan(const KisFilterWeightsApplicator::BlendSpan &span)
35 {
36     qDebug() << ppVar(span.weights->centerIndex);
37     for (int i = 0; i < span.weights->span; i++) {
38         qDebug() << "Weights" << i << span.weights->weight[i];
39     }
40 
41     qDebug() << ppVar(span.firstBlendPixel);
42     qDebug() << ppVar(span.offset);
43     qDebug() << ppVar(span.offsetInc);
44 }
45 
testSpan(qreal scale,qreal dx,int dst_l,int expectedFirstPixel,qreal expectedOffset,qreal expectedOffsetInc)46 void testSpan(qreal scale, qreal dx, int dst_l,
47               int expectedFirstPixel,
48               qreal expectedOffset,
49               qreal expectedOffsetInc)
50 {
51     KisFilterStrategy *filter = new KisBilinearFilterStrategy();
52 
53     KisFilterWeightsBuffer buf(filter, qAbs(scale));
54     KisFilterWeightsApplicator applicator(0, 0, scale, 0.0, dx, false);
55     KisFilterWeightsApplicator::BlendSpan span;
56     span = applicator.calculateBlendSpan(dst_l, 0, &buf);
57 
58     //debugSpan(span);
59 
60     if (span.firstBlendPixel != expectedFirstPixel ||
61         span.offset != KisFixedPoint(expectedOffset) ||
62         span.offsetInc != KisFixedPoint(expectedOffsetInc)) {
63 
64         qDebug() << "Failed to generate a span:";
65         qDebug() << ppVar(scale) << ppVar(dx) << ppVar(dst_l);
66         qDebug() << ppVar(span.firstBlendPixel) << ppVar(expectedFirstPixel);
67         qDebug() << ppVar(span.offset) << ppVar(KisFixedPoint(expectedOffset));
68         qDebug() << ppVar(span.offsetInc) << ppVar(KisFixedPoint(expectedOffsetInc));
69         QFAIL("fail");
70     }
71 }
72 
testSpan_Scale_2_0_Aligned()73 void KisFilterWeightsApplicatorTest::testSpan_Scale_2_0_Aligned()
74 {
75     testSpan(2.0, 0.0, 0, -1, 0.25, 1.0);
76     testSpan(2.0, 0.0, 1, 0, 0.75, 1.0);
77     testSpan(2.0, 0.0, -1, -1, 0.75, 1.0);
78     testSpan(2.0, 0.0, -2, -2, 0.25, 1.0);
79 }
80 
testSpan_Scale_2_0_Shift_0_5()81 void KisFilterWeightsApplicatorTest::testSpan_Scale_2_0_Shift_0_5()
82 {
83     testSpan(2.0, 0.5, 0, -1, 0.5, 1.0);
84     testSpan(2.0, 0.5, 1, -1, 0.0, 1.0);
85     testSpan(2.0, 0.5, -1, -2, 0.0, 1.0);
86     testSpan(2.0, 0.5, -2, -2, 0.5, 1.0);
87 }
88 
testSpan_Scale_2_0_Shift_0_75()89 void KisFilterWeightsApplicatorTest::testSpan_Scale_2_0_Shift_0_75()
90 {
91     testSpan(2.0, 0.75, 0, -1, 0.625, 1.0);
92     testSpan(2.0, 0.75, 1, -1, 0.125, 1.0);
93     testSpan(2.0, 0.75, -1, -2, 0.125, 1.0);
94     testSpan(2.0, 0.75, -2, -2, 0.625, 1.0);
95 }
96 
testSpan_Scale_0_5_Aligned()97 void KisFilterWeightsApplicatorTest::testSpan_Scale_0_5_Aligned()
98 {
99     testSpan(0.5, 0.0, 0, -1, 0.25, 0.5);
100     testSpan(0.5, 0.0, 1, 1, 0.25, 0.5);
101     testSpan(0.5, 0.0, -1, -3, 0.25, 0.5);
102 }
103 
testSpan_Scale_0_5_Shift_0_5()104 void KisFilterWeightsApplicatorTest::testSpan_Scale_0_5_Shift_0_5()
105 {
106     testSpan(0.5, 0.5, 0, -2, 0.25, 0.5);
107     testSpan(0.5, 0.5, 1, 0, 0.25, 0.5);
108     testSpan(0.5, 0.5, -1, -4, 0.25, 0.5);
109 }
110 
testSpan_Scale_0_5_Shift_0_25()111 void KisFilterWeightsApplicatorTest::testSpan_Scale_0_5_Shift_0_25()
112 {
113     testSpan(0.5, 0.25, 0, -2, 0.0, 0.5);
114     testSpan(0.5, 0.25, 1, 0, 0.0, 0.5);
115     testSpan(0.5, 0.25, -1, -4, 0.0, 0.5);
116 }
117 
testSpan_Scale_0_5_Shift_0_375()118 void KisFilterWeightsApplicatorTest::testSpan_Scale_0_5_Shift_0_375()
119 {
120     testSpan(0.5, 0.375, 0, -2, 0.125, 0.5);
121     testSpan(0.5, 0.375, 1, 0, 0.125, 0.5);
122     testSpan(0.5, 0.375, -1, -4, 0.125, 0.5);
123 }
124 
testSpan_Scale_0_5_Shift_m0_5()125 void KisFilterWeightsApplicatorTest::testSpan_Scale_0_5_Shift_m0_5()
126 {
127     testSpan(0.5, -0.5, 0, 0, 0.25, 0.5);
128     testSpan(0.5, -0.5, 1, 2, 0.25, 0.5);
129     testSpan(0.5, -0.5, -1, -2, 0.25, 0.5);
130 }
131 
testSpan_Scale_0_5_Shift_m0_25()132 void KisFilterWeightsApplicatorTest::testSpan_Scale_0_5_Shift_m0_25()
133 {
134     testSpan(0.5, -0.25, 0, -1, 0.0, 0.5);
135     testSpan(0.5, -0.25, 1, 1, 0.0, 0.5);
136     testSpan(0.5, -0.25, -1, -3, 0.0, 0.5);
137 }
138 
testSpan_Scale_0_5_Shift_m0_375()139 void KisFilterWeightsApplicatorTest::testSpan_Scale_0_5_Shift_m0_375()
140 {
141     testSpan(0.5, -0.375, 0, 0, 0.375, 0.5);
142     testSpan(0.5, -0.375, 1, 2, 0.375, 0.5);
143     testSpan(0.5, -0.375, -1, -2, 0.375, 0.5);
144 }
145 
testSpan_Scale_1_0_Aligned_Mirrored()146 void KisFilterWeightsApplicatorTest::testSpan_Scale_1_0_Aligned_Mirrored()
147 {
148     testSpan(-1.0, 0.0, 0, -2, 0.0, 1.0);
149     testSpan(-1.0, 0.0, 1, -3, 0.0, 1.0);
150     testSpan(-1.0, 0.0, -1, -1, 0.0, 1.0);
151     testSpan(-1.0, 0.0, -2, 0, 0.0, 1.0);
152 }
153 
testSpan_Scale_0_5_Aligned_Mirrored()154 void KisFilterWeightsApplicatorTest::testSpan_Scale_0_5_Aligned_Mirrored()
155 {
156     testSpan(-0.5, 0.0, 0, -3, 0.25, 0.5);
157     testSpan(-0.5, 0.0, 1, -5, 0.25, 0.5);
158     testSpan(-0.5, 0.0, -1, -1, 0.25, 0.5);
159     testSpan(-0.5, 0.0, -2, 1, 0.25, 0.5);
160 }
161 
testSpan_Scale_0_5_Shift_0_125_Mirrored()162 void KisFilterWeightsApplicatorTest::testSpan_Scale_0_5_Shift_0_125_Mirrored()
163 {
164     testSpan(-0.5, 0.125, 0, -3, 0.125, 0.5);
165     testSpan(-0.5, 0.125, 1, -5, 0.125, 0.5);
166     testSpan(-0.5, 0.125, -1, -1, 0.125, 0.5);
167     testSpan(-0.5, 0.125, -2, 1, 0.125, 0.5);
168 }
169 
printPixels(KisPaintDeviceSP dev,int x0,int len,bool horizontal,bool dense=false)170 void printPixels(KisPaintDeviceSP dev, int x0, int len, bool horizontal, bool dense = false)
171 {
172     std::stringstream ss;
173     for (int i = x0; i < x0 + len; i++) {
174         QColor c;
175 
176         int x = horizontal ? i : 0;
177         int y = horizontal ? 0 : i;
178 
179         dev->pixel(x, y, &c);
180         if (dense){
181             ss << c.red() << " , " << c.alpha() << " | ";
182         } else {
183             qDebug() << "px" << x << y << "|" << c.red() << c.green() << c.blue() << c.alpha();
184         }
185     }
186 
187     if (dense) {
188         qDebug() << ss.str().c_str();
189     }
190 }
191 
checkRA(KisPaintDeviceSP dev,int x0,int len,quint8 r[],quint8 a[],bool horizontal)192 void checkRA(KisPaintDeviceSP dev, int x0, int len, quint8 r[], quint8 a[], bool horizontal)
193 {
194     bool failed = false;
195     for (int i = 0; i < len; i++) {
196         QColor c;
197 
198         int x = horizontal ? x0 + i : 0;
199         int y = horizontal ? 0 : x0 + i;
200 
201         dev->pixel(x, y, &c);
202 
203         if (c.red() != r[i] ||
204             c.alpha() != a[i]) {
205 
206             qDebug() << "Failed to compare RA channels:" << ppVar(x0 + i);
207             qDebug() << "Red:" << c.red() << "Expected:" << r[i];
208             qDebug() << "Alpha:" << c.alpha() << "Expected:" << a[i];
209             failed = true;
210         }
211     }
212 
213     if (failed) {
214         QFAIL("failed");
215     }
216 }
217 
testLineImpl(qreal scale,qreal dx,quint8 expR[],quint8 expA[],int x0,int len,bool clampToEdge,bool horizontal,KisFilterStrategy * filter=0,KisPaintDeviceSP dev=0)218 void testLineImpl(qreal scale, qreal dx, quint8 expR[], quint8 expA[], int x0, int len, bool clampToEdge, bool horizontal, KisFilterStrategy *filter = 0, KisPaintDeviceSP dev = 0)
219 {
220     int startPos = 0;
221     int endPos = 4;
222     const KoColorSpace *cs = KoColorSpaceRegistry::instance()->rgb8();
223     if (!filter) {
224         filter = new KisBilinearFilterStrategy();
225     }
226     if (!dev) {
227         dev = new KisPaintDevice(cs);
228 
229         for (int i = 0; i < 4; i++) {
230             int x = horizontal ? i : 0;
231             int y = horizontal ? 0 : i;
232             dev->setPixel(x,y,QColor(10 + i * 10, 20 + i * 10, 40 + i * 10));
233         }
234 
235         {
236             quint8 r[] = {  0, 10, 20, 30, 40,  0,  0};
237             quint8 a[] = {  0,255,255,255,255,  0,  0};
238             checkRA(dev, -1, 6, r, a, horizontal);
239         }
240 
241         startPos = 0;
242         endPos = 4;
243 
244     } else {
245         QRect rc = dev->exactBounds();
246         if (horizontal) {
247             startPos = rc.left();
248             endPos = rc.left() + rc.width();
249         } else {
250             startPos = rc.top();
251             endPos = rc.top() + rc.height();
252         }
253     }
254 
255     KisFilterWeightsBuffer buf(filter, qAbs(scale));
256     KisFilterWeightsApplicator applicator(dev, dev, scale, 0.0, dx, clampToEdge);
257 
258 
259     KisFilterWeightsApplicator::LinePos srcPos(startPos, endPos);
260     KisFilterWeightsApplicator::LinePos dstPos;
261 
262     if (horizontal) {
263         dstPos = applicator.processLine<KisHLineIteratorSP>(srcPos,0,&buf, filter->support(buf.weightsPositionScale().toFloat()));
264     } else {
265         dstPos = applicator.processLine<KisVLineIteratorSP>(srcPos,0,&buf, filter->support(buf.weightsPositionScale().toFloat()));
266     }
267 
268     QRect rc = dev->exactBounds();
269 
270     if (horizontal) {
271         QVERIFY(rc.left() >= dstPos.start());
272         QVERIFY(rc.left() + rc.width() <= dstPos.end());
273     } else {
274         QVERIFY(rc.top() >= dstPos.start());
275         QVERIFY(rc.top() + rc.height() <= dstPos.end());
276     }
277 
278     //printPixels(dev, x0, len, horizontal, true);
279     checkRA(dev, x0, len, expR, expA, horizontal);
280 }
281 
testLine(qreal scale,qreal dx,quint8 expR[],quint8 expA[],int x0,int len,bool clampToEdge=false,KisFilterStrategy * filter=0,KisPaintDeviceSP dev=0)282 void testLine(qreal scale, qreal dx, quint8 expR[], quint8 expA[], int x0, int len, bool clampToEdge = false, KisFilterStrategy* filter = 0, KisPaintDeviceSP dev = 0)
283 {
284     testLineImpl(scale, dx, expR, expA, x0, len, clampToEdge, true, filter, dev);
285     testLineImpl(scale, dx, expR, expA, x0, len, clampToEdge, false, filter, dev);
286 }
287 
testProcessLine_Scale_1_0_Aligned()288 void KisFilterWeightsApplicatorTest::testProcessLine_Scale_1_0_Aligned()
289 {
290     qreal scale = 1.0;
291     qreal dx = 0.0;
292 
293     quint8 r[] = {  0, 10, 20, 30, 40,  0,  0};
294     quint8 a[] = {  0,255,255,255,255,  0,  0};
295 
296     testLine(scale, dx, r, a, -1, 7);
297 }
298 
testProcessLine_Scale_1_0_Shift_0_5()299 void KisFilterWeightsApplicatorTest::testProcessLine_Scale_1_0_Shift_0_5()
300 {
301     qreal scale = 1.0;
302     qreal dx = 0.5;
303 
304     quint8 r[] = {  0, 10, 15, 25, 35, 40,  0};
305     quint8 a[] = {  0,128,255,255,255,127,  0};
306 
307     testLine(scale, dx, r, a, -1, 7);
308 }
309 
testProcessLine_Scale_1_0_Shift_m0_5()310 void KisFilterWeightsApplicatorTest::testProcessLine_Scale_1_0_Shift_m0_5()
311 {
312     qreal scale = 1.0;
313     qreal dx = -0.5;
314 
315     quint8 r[] = { 10, 15, 25, 35, 40,  0,  0};
316     quint8 a[] = {128,255,255,255,127,  0,  0};
317 
318     testLine(scale, dx, r, a, -1, 7);
319 }
320 
testProcessLine_Scale_1_0_Shift_0_25()321 void KisFilterWeightsApplicatorTest::testProcessLine_Scale_1_0_Shift_0_25()
322 {
323     qreal scale = 1.0;
324     qreal dx = 0.25;
325 
326     quint8 r[] = {  0, 10, 17, 27, 37, 40,  0};
327     quint8 a[] = {  0,191,255,255,255, 64,  0};
328 
329     testLine(scale, dx, r, a, -1, 7);
330 }
331 
testProcessLine_Scale_1_0_Shift_m0_25()332 void KisFilterWeightsApplicatorTest::testProcessLine_Scale_1_0_Shift_m0_25()
333 {
334     qreal scale = 1.0;
335     qreal dx = -0.25;
336 
337     quint8 r[] = { 10, 13, 23, 33, 40,  0,  0};
338     quint8 a[] = { 64,255,255,255,191,  0,  0};
339 
340     testLine(scale, dx, r, a, -1, 7);
341 }
342 
testProcessLine_Scale_0_5_Aligned()343 void KisFilterWeightsApplicatorTest::testProcessLine_Scale_0_5_Aligned()
344 {
345     qreal scale = 0.5;
346     qreal dx = 0.0;
347 
348     quint8 r[] = { 10, 17, 33, 40,  0,  0,  0};
349     quint8 a[] = { 32,223,223, 32,  0,  0,  0};
350 
351     testLine(scale, dx, r, a, -1, 7);
352 }
353 
testProcessLine_Scale_0_5_Shift_0_25()354 void KisFilterWeightsApplicatorTest::testProcessLine_Scale_0_5_Shift_0_25()
355 {
356     qreal scale = 0.5;
357     qreal dx = 0.25;
358 
359     quint8 r[] = {  0, 13, 30, 40,  0,  0,  0};
360     quint8 a[] = {  0,191,255, 64,  0,  0,  0};
361 
362     testLine(scale, dx, r, a, -1, 7);
363 }
364 
testProcessLine_Scale_2_0_Aligned()365 void KisFilterWeightsApplicatorTest::testProcessLine_Scale_2_0_Aligned()
366 {
367     qreal scale = 2.0;
368     qreal dx = 0.0;
369 
370     quint8 r[] = {  0, 10, 10, 13, 17, 23, 27, 33, 37, 40, 40,  0};
371     quint8 a[] = {  0, 64,191,255,255,255,255,255,255,191, 64,  0};
372 
373     testLine(scale, dx, r, a, -2, 12);
374 }
375 
testProcessLine_Scale_2_0_Shift_0_25()376 void KisFilterWeightsApplicatorTest::testProcessLine_Scale_2_0_Shift_0_25()
377 {
378     qreal scale = 2.0;
379     qreal dx = 0.25;
380 
381     quint8 r[] = {  0, 10, 10, 11, 16, 21, 26, 31, 36, 40, 40,  0};
382     quint8 a[] = {  0, 32,159,255,255,255,255,255,255,223, 96,  0};
383 
384     testLine(scale, dx, r, a, -2, 12);
385 }
386 
testProcessLine_Scale_2_0_Shift_0_5()387 void KisFilterWeightsApplicatorTest::testProcessLine_Scale_2_0_Shift_0_5()
388 {
389     qreal scale = 2.0;
390     qreal dx = 0.5;
391 
392     quint8 r[] = {  0,  0, 10, 10, 15, 20, 25, 30, 35, 40, 40,  0};
393     quint8 a[] = {  0,  0,128,255,255,255,255,255,255,255,127,  0};
394 
395     testLine(scale, dx, r, a, -2, 12);
396 }
397 
testProcessLine_Scale_1_0_Aligned_Clamped()398 void KisFilterWeightsApplicatorTest::testProcessLine_Scale_1_0_Aligned_Clamped()
399 {
400     qreal scale = 1.0;
401     qreal dx = 0.0;
402 
403     quint8 r[] = {  0, 10, 20, 30, 40,  0,  0};
404     quint8 a[] = {  0,255,255,255,255,  0,  0};
405 
406     testLine(scale, dx, r, a, -1, 7, true);
407 }
408 
testProcessLine_Scale_0_5_Aligned_Clamped()409 void KisFilterWeightsApplicatorTest::testProcessLine_Scale_0_5_Aligned_Clamped()
410 {
411     qreal scale = 0.5;
412     qreal dx = 0.0;
413 
414     quint8 r[] = {  0, 16, 34,  0,  0,  0,  0};
415     quint8 a[] = {  0,255,255,  0,  0,  0,  0};
416 
417     testLine(scale, dx, r, a, -1, 7, true);
418 }
419 
testProcessLine_Scale_2_0_Aligned_Clamped()420 void KisFilterWeightsApplicatorTest::testProcessLine_Scale_2_0_Aligned_Clamped()
421 {
422     qreal scale = 2.0;
423     qreal dx = 0.0;
424 
425     quint8 r[] = {  0,  0, 10, 13, 17, 23, 27, 33, 37, 40,  0,  0};
426     quint8 a[] = {  0,  0,255,255,255,255,255,255,255,255,  0,  0};
427 
428     testLine(scale, dx, r, a, -2, 12, true);
429 }
430 
testProcessLine_Scale_1_0_Aligned_Mirrored()431 void KisFilterWeightsApplicatorTest::testProcessLine_Scale_1_0_Aligned_Mirrored()
432 {
433     qreal scale = -1.0;
434     qreal dx = 0.0;
435 
436     quint8 r[] = {  0,  0, 40, 30, 20, 10,  0,  0,  0,  0};
437     quint8 a[] = {  0,  0,255,255,255,255,  0,  0,  0,  0};
438 
439     testLine(scale, dx, r, a, -6, 10);
440 }
441 
testProcessLine_Scale_1_0_Shift_0_25_Mirrored()442 void KisFilterWeightsApplicatorTest::testProcessLine_Scale_1_0_Shift_0_25_Mirrored()
443 {
444     qreal scale = -1.0;
445     qreal dx = 0.25;
446 
447     quint8 r[] = {  0,  0, 40, 33, 23, 13, 10,  0,  0,  0};
448     quint8 a[] = {  0,  0,191,255,255,255, 64,  0,  0,  0};
449 
450     testLine(scale, dx, r, a, -6, 10);
451 }
452 
testProcessLine_Scale_0_5_Aligned_Mirrored_Clamped()453 void KisFilterWeightsApplicatorTest::testProcessLine_Scale_0_5_Aligned_Mirrored_Clamped()
454 {
455     qreal scale = -0.5;
456     qreal dx = 0.0;
457 
458     quint8 r[] = {  0,  0,  0,  0, 34, 16,  0,  0,  0,  0};
459     quint8 a[] = {  0,  0,  0,  0,255,255,  0,  0,  0,  0};
460 
461     testLine(scale, dx, r, a, -6, 10, true);
462 }
463 
testProcessLine_Scale_0_5_Shift_0_125_Mirrored()464 void KisFilterWeightsApplicatorTest::testProcessLine_Scale_0_5_Shift_0_125_Mirrored()
465 {
466     qreal scale = -0.5;
467     qreal dx = 0.125;
468 
469     quint8 r[] = {  0,  0,  0, 40, 35, 19, 10,  0,  0,  0};
470     quint8 a[] = {  0,  0,  0, 16,207,239, 48,  0,  0,  0};
471 
472     testLine(scale, dx, r, a, -6, 10);
473 }
474 
testProcessLine_NearestNeighbourFilter_2x()475 void KisFilterWeightsApplicatorTest::testProcessLine_NearestNeighbourFilter_2x()
476 {
477     qreal scale = 2.0;
478     qreal dx = 0;
479 
480     quint8 r[] = {0,  10, 10,   20, 20,   30,  30,    40, 40, 0, 0};
481     quint8 a[] = {0,  255, 255, 255, 255, 255,  255,  255, 255, 0, 0};
482 
483     KisFilterStrategy* filter = new KisBoxFilterStrategy();
484     testLine(scale, dx, r, a, -1, 11, true, filter);
485 }
486 
testProcessLine_NearestNeighbourFilter_1x()487 void KisFilterWeightsApplicatorTest::testProcessLine_NearestNeighbourFilter_1x()
488 {
489 
490     qreal scale = 1.0;
491     qreal dx = 0;
492 
493     quint8 r[] = {  0, 10, 20, 30, 40,  0,  0};
494     quint8 a[] = {  0,255,255,255,255,  0,  0};
495 
496     KisFilterStrategy* filter = new KisBoxFilterStrategy();
497     testLine(scale, dx, r, a, -1, 7, false, filter);
498 }
499 
testProcessLine_NearestNeighbourFilter_05x()500 void KisFilterWeightsApplicatorTest::testProcessLine_NearestNeighbourFilter_05x()
501 {
502 
503     qreal scale = 0.5;
504     qreal dx = 0;
505 
506     quint8 r[] = {  0, 10, 30, 0, 0,  0,  0};
507     quint8 a[] = {  0,255,255, 0, 0,  0,  0};
508 
509     KisFilterStrategy* filter = new KisBoxFilterStrategy();
510     testLine(scale, dx, r, a, -1, 7, false, filter);
511 }
512 
513 
testProcessLine_NearestNeighbourFilter_077x()514 void KisFilterWeightsApplicatorTest::testProcessLine_NearestNeighbourFilter_077x()
515 {
516 
517     qreal scale = 0.77;
518     qreal dx = 0;
519 
520     quint8 r[] = {  0, 10, 20, 40, 0,  0,  0};
521     quint8 a[] = {  0,255,255, 255, 0,  0,  0};
522 
523     KisFilterStrategy* filter = new KisBoxFilterStrategy();
524     testLine(scale, dx, r, a, -1, 7, false, filter);
525 }
526 
testProcessLine_NearestNeighbourFilter_074x()527 void KisFilterWeightsApplicatorTest::testProcessLine_NearestNeighbourFilter_074x()
528 {
529 
530     qreal scale = 0.74;
531     qreal dx = 0;
532 
533     quint8 r[] = {  0, 10, 30, 40, 0,  0,  0};
534     quint8 a[] = {  0,255,255, 255, 0,  0,  0};
535 
536     KisFilterStrategy* filter = new KisBoxFilterStrategy();
537     testLine(scale, dx, r, a, -1, 7, false, filter);
538 }
539 
testProcessLine_NearestNeighbourFilter_075x()540 void KisFilterWeightsApplicatorTest::testProcessLine_NearestNeighbourFilter_075x()
541 {
542 
543     qreal scale = 0.75;
544     qreal dx = 0;
545 
546     quint8 r[] = {  0, 10, 20, 40, 0,  0,  0};
547     quint8 a[] = {  0,255,255, 255, 0,  0,  0};
548 
549     KisFilterStrategy* filter = new KisBoxFilterStrategy();
550     testLine(scale, dx, r, a, -1, 7, false, filter);
551 }
552 
testProcessLine_NearestNeighbourFilter_051x()553 void KisFilterWeightsApplicatorTest::testProcessLine_NearestNeighbourFilter_051x()
554 {
555 
556     qreal scale = 0.51;
557     qreal dx = 0;
558 
559     quint8 r[] = {  0, 10, 30, 0, 0,  0,  0};
560     quint8 a[] = {  0,255,255, 0, 0,  0,  0};
561 
562     KisFilterStrategy* filter = new KisBoxFilterStrategy();
563     testLine(scale, dx, r, a, -1, 7, false, filter);
564 }
565 
566 
567 
testProcessLine_NearestNeighbourFilter_15x()568 void KisFilterWeightsApplicatorTest::testProcessLine_NearestNeighbourFilter_15x()
569 {
570 
571     qreal scale = 1.5;
572     qreal dx = 0;
573 
574     quint8 r[] = {  0, 10, 10, 20, 30,  30,  40};
575     quint8 a[] = {  0,255,255, 255, 255,  255,  255};
576 
577     KisFilterStrategy* filter = new KisBoxFilterStrategy();
578     testLine(scale, dx, r, a, -1, 7, false, filter);
579 }
580 
581 
preparePixelData(quint8 * r,quint8 * a,int i)582 void preparePixelData(quint8* r, quint8* a, int i)
583 {
584     for (int j = 0; j < 7; j ++) {
585         r[j] = 0;
586         a[j] = 0;
587     }
588 
589     if (i < 13) {
590         // nothing to do
591     } else if (i < 17) {
592         r[1] = 40;
593         a[1] = 255;
594     } else if (i < 25) {
595         r[1] = 30;
596         a[1] = 255;
597     } else if (i < 38) {
598         r[1] = 20;
599         a[1] = 255;
600     } else if (i < 50) {
601         r[1] = 20;
602         r[2] = 40;
603         a[1] = 255;
604         a[2] = 255;
605     } else if (i < 63) {
606         r[1] = 10;
607         r[2] = 30;
608         a[1] = 255;
609         a[2] = 255;
610     } else if (i < 75) {
611         r[1] = 10;
612         r[2] = 30;
613         r[3] = 40;
614 
615         a[1] = 255;
616         a[2] = 255;
617         a[3] = 255;
618 
619     } else if (i < 84) {
620         r[1] = 10;
621         r[2] = 20;
622         r[3] = 40;
623 
624         a[1] = 255;
625         a[2] = 255;
626         a[3] = 255;
627 
628     } else if (i < 88) {
629         r[1] = 10;
630         r[2] = 20;
631         r[3] = 30;
632 
633         a[1] = 255;
634         a[2] = 255;
635         a[3] = 255;
636     } else {
637 
638         r[1] = 10;
639         r[2] = 20;
640         r[3] = 30;
641         r[4] = 40;
642 
643         a[1] = 255;
644         a[2] = 255;
645         a[3] = 255;
646         a[4] = 255;
647     }
648 
649 }
650 
651 
testProcessLine_NearestNeighbourFilter_all()652 void KisFilterWeightsApplicatorTest::testProcessLine_NearestNeighbourFilter_all()
653 {
654 
655     KisFilterStrategy* filter = new KisBoxFilterStrategy();
656 
657     for (int i = 1; i < 100; i++) {
658 
659         qreal scale = i/100.0;
660         qreal dx = 0;
661 
662         quint8 r[7];
663         quint8 a[7];
664 
665         preparePixelData(r, a, i);
666         testLine(scale, dx, r, a, -1, 7, false, filter);
667 
668     }
669 }
670 
671 
672 
673 
prepareUniformPaintDevice(int pixelsNumber,bool horizontal)674 KisPaintDeviceSP prepareUniformPaintDevice(int pixelsNumber, bool horizontal)
675 {
676     const KoColorSpace *cs = KoColorSpaceRegistry::instance()->rgb8();
677     KisPaintDeviceSP dev = new KisPaintDevice(cs);
678     for (int i = 0; i < pixelsNumber; i++) {
679         int x = horizontal ? i : 0;
680         int y = horizontal ? 0 : i;
681 
682         QColor c = QColor(10, 0, 0, 255);
683         dev->setPixel(x, y, c);
684     }
685 
686     return dev;
687 }
688 
prepareUniformPixels(quint8 r[],quint8 a[],int pixelsNumber,bool)689 void prepareUniformPixels(quint8 r[], quint8 a[], int pixelsNumber, bool /*horizontal*/)
690 {
691     for (int i = 0; i < pixelsNumber; i++) {
692 
693         QColor c = QColor(10, 0, 0, 255);
694         r[i] = c.red();
695         a[i] = c.alpha();
696     }
697 
698 }
699 
700 
701 
testProcessLine_NearestNeighbourFilter_0098x_horizontal()702 void KisFilterWeightsApplicatorTest::testProcessLine_NearestNeighbourFilter_0098x_horizontal()
703 {
704     int before = 5075;
705     int after = 500;
706 
707     qreal scale = before/after;
708     qreal dx = 0;
709 
710     bool horizontal = true;
711 
712     KisPaintDeviceSP dev = prepareUniformPaintDevice(before, horizontal);
713 
714     quint8 *r = new quint8[after];
715     quint8 *a = new quint8[after];
716 
717     prepareUniformPixels(r, a, after, horizontal);
718 
719     KisFilterStrategy* filter = new KisBoxFilterStrategy();
720     testLineImpl(scale, dx, r, a, 0, after, false, horizontal, filter, dev);
721 
722 }
723 
testProcessLine_NearestNeighbourFilter_0098x_vertical()724 void KisFilterWeightsApplicatorTest::testProcessLine_NearestNeighbourFilter_0098x_vertical()
725 {
726     int before = 4725;
727     int after = 466;
728 
729     qreal scale = before/after;
730     qreal dx = 0;
731 
732     bool horizontal = false;
733 
734     KisPaintDeviceSP dev = prepareUniformPaintDevice(before, horizontal);
735 
736     quint8 *r = new quint8[after];
737     quint8 *a = new quint8[after];
738 
739     prepareUniformPixels(r, a, after, horizontal);
740 
741     KisFilterStrategy* filter = new KisBoxFilterStrategy();
742     testLineImpl(scale, dx, r, a, 0, after, false, horizontal, filter, dev);
743 
744 }
745 
746 
benchmarkProcesssLine()747 void KisFilterWeightsApplicatorTest::benchmarkProcesssLine()
748 {
749     const KoColorSpace *cs = KoColorSpaceRegistry::instance()->rgb8();
750     KisPaintDeviceSP dev = new KisPaintDevice(cs);
751     KisFilterStrategy *filter = new KisBilinearFilterStrategy();
752 
753     const qreal scale = 0.873;
754     const qreal dx = 0.0387;
755 
756     KisFilterWeightsBuffer buf(filter, qAbs(scale));
757     KisFilterWeightsApplicator applicator(dev, dev, scale, 0.0, dx, false);
758 
759     for (int i = 0; i < 32767; i++) {
760         dev->setPixel(i,0,QColor(10 + i%240,20,40));
761     }
762 
763     KisFilterWeightsApplicator::LinePos linePos(0,32767);
764 
765     QBENCHMARK {
766         applicator.processLine<KisHLineIteratorSP>(linePos,0,&buf, filter->support(buf.weightsPositionScale().toFloat()));
767     }
768 }
769 
770 KISTEST_MAIN(KisFilterWeightsApplicatorTest)
771