Changeset View
Changeset View
Standalone View
Standalone View
libs/image/tests/kis_mask_similarity_test.cpp
- This file was added.
1 | /* | ||||
---|---|---|---|---|---|
2 | * Copyright (c) 2018 Iván Santa María <ghevan@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_mask_similarity_test.h" | ||||
20 | | ||||
21 | #include <QTest> | ||||
22 | #include <QPointF> | ||||
23 | | ||||
24 | #include <KoColor.h> | ||||
25 | #include <testutil.h> | ||||
26 | | ||||
27 | #include "kis_brush_mask_applicator_base.h" | ||||
28 | #include "kis_mask_generator.h" | ||||
29 | #include "kis_cubic_curve.h" | ||||
30 | #include "krita_utils.h" | ||||
31 | | ||||
32 | #include "config-limit-long-tests.h" | ||||
33 | | ||||
34 | #ifdef LIMIT_LONG_TESTS | ||||
35 | #define RATIO_STEP 50 | ||||
36 | #define FADE_STEP 25 | ||||
37 | #else /* LIMIT_LONG_TESTS */ | ||||
38 | #define RATIO_STEP 20 | ||||
39 | #define FADE_STEP 5 | ||||
40 | #endif /* LIMIT_LONG_TESTS */ | ||||
41 | | ||||
42 | | ||||
43 | enum MaskType { | ||||
44 | DEFAULT, CIRC_GAUSS, CIRC_SOFT, RECT, RECT_GAUSS, RECT_SOFT, STAMP | ||||
45 | }; | ||||
46 | | ||||
47 | class KisMaskSimilarityTester | ||||
48 | { | ||||
49 | | ||||
50 | public: | ||||
51 | KisMaskSimilarityTester(KisBrushMaskApplicatorBase *_legacy, KisBrushMaskApplicatorBase *_vectorized, QRect _bounds, MaskType type) | ||||
52 | : legacy(_legacy) | ||||
53 | , vectorized(_vectorized) | ||||
54 | , m_bounds(_bounds) | ||||
55 | { | ||||
56 | KisFixedPaintDeviceSP m_paintDev = new KisFixedPaintDevice(m_colorSpace); | ||||
57 | m_paintDev->setRect(m_bounds); | ||||
58 | m_paintDev->initialize(255); | ||||
59 | | ||||
60 | MaskProcessingData data(m_paintDev, m_colorSpace, | ||||
61 | 0.0, 1.0, | ||||
62 | m_bounds.width() / 2.0, m_bounds.height() / 2.0,0); | ||||
63 | | ||||
64 | // Start legacy scalar processing | ||||
65 | legacy->initializeData(&data); | ||||
66 | legacy->process(m_bounds); | ||||
67 | | ||||
68 | QImage scalarImage(m_paintDev->convertToQImage(m_colorSpace->profile())); | ||||
69 | scalarImage.invertPixels(); // Make pixel color black | ||||
70 | | ||||
71 | // Start vector processing | ||||
72 | m_paintDev->initialize(255); | ||||
73 | vectorized->initializeData(&data); | ||||
74 | vectorized->process(m_bounds); | ||||
75 | | ||||
76 | QImage vectorImage(m_paintDev->convertToQImage(m_colorSpace->profile())); | ||||
77 | vectorImage.invertPixels(); // Make pixel color black | ||||
78 | | ||||
79 | // Check for differences, max errors: 0 | ||||
80 | QPoint tmpPt; | ||||
81 | if (!TestUtil::compareQImages(tmpPt,scalarImage, vectorImage, 0, 2, 0)) { | ||||
82 | scalarImage.save(QString(getTypeName(type) + "_scalar_mask.png"),"PNG"); | ||||
83 | vectorImage.save(QString(getTypeName(type) + "_vector_mask.png"),"PNG"); | ||||
84 | | ||||
85 | QFAIL(QString("Masks differ! first different pixel: %1,%2 \n").arg(tmpPt.x()).arg(tmpPt.y()).toLatin1()); | ||||
86 | } | ||||
87 | | ||||
88 | } | ||||
89 | | ||||
90 | | ||||
91 | static bool exahustiveTest(QRect bounds, MaskType type) { | ||||
92 | // Exahustive test | ||||
93 | | ||||
94 | for (size_t i = 0; i <= 100; i += FADE_STEP){ | ||||
95 | for (size_t j = 0; j <= 100; j += FADE_STEP){ | ||||
96 | for (size_t k = 0; k <= 100; k += RATIO_STEP){ | ||||
97 | | ||||
98 | switch (type) { | ||||
99 | case CIRC_GAUSS: | ||||
100 | { | ||||
101 | KisGaussCircleMaskGenerator bCircVectr(499.5, k/100.f, i/100.f, j/100.f, 2, true); | ||||
102 | bCircVectr.setDiameter(499.5); | ||||
103 | KisGaussCircleMaskGenerator bCircScalar(bCircVectr); | ||||
104 | bCircScalar.resetMaskApplicator(true); // Force usage of scalar backend | ||||
105 | | ||||
106 | KisMaskSimilarityTester(bCircScalar.applicator(), bCircVectr.applicator(), bounds,type); | ||||
107 | break; | ||||
108 | } | ||||
109 | case CIRC_SOFT: | ||||
110 | { | ||||
111 | KisCubicCurve pointsCurve; | ||||
112 | pointsCurve.fromString(QString("0,1;1,0")); | ||||
113 | KisCurveCircleMaskGenerator bCircVectr(499.5, k/100.f, i/100.f, j/100.f, 2, pointsCurve, true); | ||||
114 | bCircVectr.setDiameter(499.5); | ||||
115 | KisCurveCircleMaskGenerator bCircScalar(bCircVectr); | ||||
116 | bCircScalar.resetMaskApplicator(true); // Force usage of scalar backend | ||||
117 | | ||||
118 | KisMaskSimilarityTester(bCircScalar.applicator(), bCircVectr.applicator(), bounds,type); | ||||
119 | break; | ||||
120 | } | ||||
121 | case RECT: | ||||
122 | { | ||||
123 | KisRectangleMaskGenerator bCircVectr(499.5, k/100.f, i/100.f, j/100.f, 2, true); | ||||
124 | KisRectangleMaskGenerator bCircScalar(bCircVectr); | ||||
125 | bCircScalar.resetMaskApplicator(true); // Force usage of scalar backend | ||||
126 | | ||||
127 | KisMaskSimilarityTester(bCircScalar.applicator(), bCircVectr.applicator(), bounds,type); | ||||
128 | break; | ||||
129 | | ||||
130 | } | ||||
131 | case RECT_GAUSS: | ||||
132 | { | ||||
133 | KisGaussRectangleMaskGenerator bCircVectr(499.5, k/100.f, i/100.f, j/100.f, 2, true); | ||||
134 | KisGaussRectangleMaskGenerator bCircScalar(bCircVectr); | ||||
135 | bCircScalar.resetMaskApplicator(true); // Force usage of scalar backend | ||||
136 | | ||||
137 | KisMaskSimilarityTester(bCircScalar.applicator(), bCircVectr.applicator(), bounds,type); | ||||
138 | break; | ||||
139 | | ||||
140 | } | ||||
141 | case RECT_SOFT: | ||||
142 | { | ||||
143 | KisCubicCurve pointsCurve; | ||||
144 | pointsCurve.fromString(QString("0,1;1,0")); | ||||
145 | KisCurveRectangleMaskGenerator bCircVectr(499.5, k/100.f, i/100.f, j/100.f, 2, pointsCurve, true); | ||||
146 | KisCurveRectangleMaskGenerator bCircScalar(bCircVectr); | ||||
147 | bCircScalar.resetMaskApplicator(true); // Force usage of scalar backend | ||||
148 | | ||||
149 | KisMaskSimilarityTester(bCircScalar.applicator(), bCircVectr.applicator(), bounds,type); | ||||
150 | break; | ||||
151 | } | ||||
152 | default: | ||||
153 | { | ||||
154 | break; | ||||
155 | } | ||||
156 | } | ||||
157 | | ||||
158 | if (QTest::currentTestFailed()) { | ||||
159 | QWARN(QString("Mask features: Ratio=%1, hfade=%2, vfade=%3 \n") | ||||
160 | .arg(k/100.f,0,'g',2).arg(i/100.f,0,'g',2).arg(j/100.f,0,'g',2).toLatin1()); | ||||
161 | return false; | ||||
162 | } | ||||
163 | | ||||
164 | } } } // end for | ||||
165 | return true; | ||||
166 | } | ||||
167 | | ||||
168 | template <typename MaskGenerator> | ||||
169 | static void runMaskGenTest(MaskGenerator& generator, MaskType type) { | ||||
170 | QRect bounds(0,0,700,700); | ||||
171 | generator.setDiameter(499.5); | ||||
172 | MaskGenerator scalarGenerator(generator); | ||||
173 | | ||||
174 | scalarGenerator.resetMaskApplicator(true); // Force usage of scalar backend | ||||
175 | KisMaskSimilarityTester(scalarGenerator.applicator(), generator.applicator(), bounds, type); | ||||
176 | | ||||
177 | // KisMaskSimilarityTester::exahustiveTest(bounds,type); | ||||
178 | } | ||||
179 | | ||||
180 | private: | ||||
181 | QString getTypeName(MaskType type) { | ||||
182 | | ||||
183 | QString strName; | ||||
184 | switch (type) { | ||||
185 | case CIRC_GAUSS: | ||||
186 | strName = "CircGauss"; | ||||
187 | break; | ||||
188 | case CIRC_SOFT: | ||||
189 | strName = "CircSoft"; | ||||
190 | break; | ||||
191 | case RECT: | ||||
192 | strName = "Rect"; | ||||
193 | break; | ||||
194 | case RECT_GAUSS: | ||||
195 | strName = "RectGauss"; | ||||
196 | break; | ||||
197 | case RECT_SOFT: | ||||
198 | strName = "RectSoft"; | ||||
199 | break; | ||||
200 | case STAMP: | ||||
201 | strName = "Stamp"; | ||||
202 | break; | ||||
203 | default: | ||||
204 | strName = "Default"; | ||||
205 | break; | ||||
206 | } | ||||
207 | return strName; | ||||
208 | } | ||||
209 | | ||||
210 | protected: | ||||
211 | const KoColorSpace *m_colorSpace = KoColorSpaceRegistry::instance()->rgb8(); | ||||
212 | | ||||
213 | KisBrushMaskApplicatorBase *legacy; | ||||
214 | KisBrushMaskApplicatorBase *vectorized; | ||||
215 | QRect m_bounds; | ||||
216 | KisFixedPaintDeviceSP m_paintDev; | ||||
217 | }; | ||||
218 | | ||||
219 | | ||||
220 | void KisMaskSimilarityTest::testCircleMask() | ||||
221 | { | ||||
222 | KisCircleMaskGenerator generator(499.5, 0.2, 0.5, 0.5, 2, true); | ||||
223 | qDebug() << generator.id() << generator.name(); | ||||
224 | KisMaskSimilarityTester::runMaskGenTest(generator,DEFAULT); | ||||
225 | } | ||||
226 | | ||||
227 | void KisMaskSimilarityTest::testGaussCircleMask() | ||||
228 | { | ||||
229 | KisGaussCircleMaskGenerator generator(499.5, 0.2, 1, 1, 2, true); | ||||
230 | KisMaskSimilarityTester::runMaskGenTest(generator,CIRC_GAUSS); | ||||
231 | } | ||||
232 | | ||||
233 | void KisMaskSimilarityTest::testSoftCircleMask() | ||||
234 | { | ||||
235 | KisCubicCurve pointsCurve; | ||||
236 | pointsCurve.fromString(QString("0,1;1,0")); | ||||
237 | KisCurveCircleMaskGenerator generator(499.5, 0.2, 0.5, 0.5, 2, pointsCurve,true); | ||||
238 | KisMaskSimilarityTester::runMaskGenTest(generator,CIRC_SOFT); | ||||
239 | } | ||||
240 | | ||||
241 | void KisMaskSimilarityTest::testRectMask() | ||||
242 | { | ||||
243 | KisRectangleMaskGenerator generator(499.5, 0.1, 0.5, 0.5, 2, false); | ||||
244 | KisMaskSimilarityTester::runMaskGenTest(generator,RECT); | ||||
245 | } | ||||
246 | | ||||
247 | void KisMaskSimilarityTest::testGaussRectMask() | ||||
248 | { | ||||
249 | KisGaussRectangleMaskGenerator generator(499.5, 0.2, 0.5, 0.2, 2, true); | ||||
250 | KisMaskSimilarityTester::runMaskGenTest(generator,RECT_GAUSS); | ||||
251 | } | ||||
252 | | ||||
253 | void KisMaskSimilarityTest::testSoftRectMask() | ||||
254 | { | ||||
255 | KisCubicCurve pointsCurve; | ||||
256 | pointsCurve.fromString(QString("0,1;1,0")); | ||||
257 | KisCurveRectangleMaskGenerator generator(499.5, 0.2, 0.5, 0.2, 2, pointsCurve, true); | ||||
258 | KisMaskSimilarityTester::runMaskGenTest(generator,RECT_SOFT); | ||||
259 | } | ||||
260 | | ||||
261 | QTEST_MAIN(KisMaskSimilarityTest) |