File indexing completed on 2024-12-22 04:08:46
0001 /* 0002 * SPDX-FileCopyrightText: 2007 Boudewijn Rempt boud @valdyas.org 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "kis_gbr_brush_test.h" 0008 0009 #include <simpletest.h> 0010 #include <QString> 0011 #include <QDir> 0012 #include <KoColor.h> 0013 #include <KoColorSpace.h> 0014 #include <KoColorSpaceRegistry.h> 0015 #include <testutil.h> 0016 #include "../kis_gbr_brush.h" 0017 #include "kis_types.h" 0018 #include "kis_paint_device.h" 0019 #include "brushengine/kis_paint_information.h" 0020 #include <kis_fixed_paint_device.h> 0021 #include "kis_qimage_pyramid.h" 0022 #include <KisGlobalResourcesInterface.h> 0023 0024 void KisGbrBrushTest::testMaskGenerationSingleColor() 0025 { 0026 QScopedPointer<KisGbrBrush> brush(new KisGbrBrush(QString(FILES_DATA_DIR) + '/' + "brush.gbr")); 0027 brush->load(KisGlobalResourcesInterface::instance()); 0028 Q_ASSERT(brush->valid()); 0029 const KoColorSpace* cs = KoColorSpaceRegistry::instance()->rgb8(); 0030 0031 KisPaintInformation info(QPointF(100.0, 100.0), 0.5); 0032 0033 // check masking an existing paint device 0034 KisFixedPaintDeviceSP fdev = new KisFixedPaintDevice(cs); 0035 fdev->setRect(QRect(0, 0, 100, 100)); 0036 fdev->initialize(); 0037 cs->setOpacity(fdev->data(), OPACITY_OPAQUE_U8, 100 * 100); 0038 0039 // Check creating a mask dab with a single color 0040 fdev = new KisFixedPaintDevice(cs); 0041 brush->mask(fdev, KoColor(Qt::black, cs), KisDabShape(), info); 0042 0043 QPoint errpoint; 0044 QImage result = QImage(QString(FILES_DATA_DIR) + '/' + "result_brush_3.png"); 0045 QImage image = fdev->convertToQImage(0); 0046 if (!TestUtil::compareQImages(errpoint, image, result)) { 0047 image.save("kis_gbr_brush_test_3.png"); 0048 QFAIL(QString("Failed to create identical image, first different pixel: %1,%2 \n").arg(errpoint.x()).arg(errpoint.y()).toLatin1()); 0049 } 0050 } 0051 0052 void KisGbrBrushTest::testMaskGenerationDevColor() 0053 { 0054 QScopedPointer<KisGbrBrush> brush(new KisGbrBrush(QString(FILES_DATA_DIR) + '/' + "brush.gbr")); 0055 brush->load(KisGlobalResourcesInterface::instance()); 0056 Q_ASSERT(brush->valid()); 0057 const KoColorSpace* cs = KoColorSpaceRegistry::instance()->rgb8(); 0058 0059 KisPaintInformation info(QPointF(100.0, 100.0), 0.5); 0060 0061 // check masking an existing paint device 0062 KisFixedPaintDeviceSP fdev = new KisFixedPaintDevice(cs); 0063 fdev->setRect(QRect(0, 0, 100, 100)); 0064 fdev->initialize(); 0065 cs->setOpacity(fdev->data(), OPACITY_OPAQUE_U8, 100 * 100); 0066 0067 // Check creating a mask dab with a color taken from a paint device 0068 KoColor red(Qt::red, cs); 0069 cs->setOpacity(red.data(), quint8(128), 1); 0070 KisPaintDeviceSP dev = new KisPaintDevice(cs); 0071 dev->fill(0, 0, 100, 100, red.data()); 0072 0073 fdev = new KisFixedPaintDevice(cs); 0074 brush->mask(fdev, dev, KisDabShape(), info); 0075 0076 QPoint errpoint; 0077 QImage result = QImage(QString(FILES_DATA_DIR) + '/' + "result_brush_4.png"); 0078 QImage image = fdev->convertToQImage(0); 0079 if (!TestUtil::compareQImages(errpoint, image, result)) { 0080 image.save("kis_gbr_brush_test_4.png"); 0081 QFAIL(QString("Failed to create identical image, first different pixel: %1,%2 \n").arg(errpoint.x()).arg(errpoint.y()).toLatin1()); 0082 } 0083 } 0084 0085 void KisGbrBrushTest::testImageGeneration() 0086 { 0087 QScopedPointer<KisGbrBrush> brush(new KisGbrBrush(QString(FILES_DATA_DIR) + '/' + "testing_brush_512_bars.gbr")); 0088 bool res = brush->load(KisGlobalResourcesInterface::instance()); 0089 Q_UNUSED(res); 0090 Q_ASSERT(res); 0091 QVERIFY(!brush->brushTipImage().isNull()); 0092 qsrand(1); 0093 0094 const KoColorSpace* cs = KoColorSpaceRegistry::instance()->rgb8(); 0095 KisPaintInformation info(QPointF(100.0, 100.0), 0.5); 0096 KisFixedPaintDeviceSP dab; 0097 0098 for (int i = 0; i < 200; i++) { 0099 qreal scale = qreal(qrand()) / RAND_MAX * 2.0; 0100 qreal rotation = qreal(qrand()) / RAND_MAX * 2 * M_PI; 0101 qreal subPixelX = qreal(qrand()) / RAND_MAX * 0.5; 0102 QString testName = 0103 QString("brush_%1_sc_%2_rot_%3_sub_%4") 0104 .arg(i).arg(scale).arg(rotation).arg(subPixelX); 0105 0106 dab = brush->paintDevice(cs, KisDabShape(scale, 1.0, rotation), info, subPixelX); 0107 0108 /** 0109 * Compare first 10 images. Others are tested for asserts only 0110 */ 0111 if (i < 10) { 0112 QImage result = dab->convertToQImage(0); 0113 TestUtil::checkQImage(result, "brush_masks", "", testName); 0114 } 0115 } 0116 } 0117 0118 #include "kis_qimage_pyramid.h" 0119 0120 void KisGbrBrushTest::benchmarkPyramidCreation() 0121 { 0122 QScopedPointer<KisGbrBrush> brush(new KisGbrBrush(QString(FILES_DATA_DIR) + '/' + "testing_brush_512_bars.gbr")); 0123 brush->load(KisGlobalResourcesInterface::instance()); 0124 QVERIFY(!brush->brushTipImage().isNull()); 0125 0126 QBENCHMARK { 0127 KisQImagePyramid pyramid(brush->brushTipImage()); 0128 qreal temp = 0.0; 0129 QVERIFY(!pyramid.getClosest(QTransform(), &temp).isNull()); // avoid compiler elimination of unused code! 0130 } 0131 } 0132 0133 void KisGbrBrushTest::benchmarkScaling() 0134 { 0135 QScopedPointer<KisGbrBrush> brush(new KisGbrBrush(QString(FILES_DATA_DIR) + '/' + "testing_brush_512_bars.gbr")); 0136 brush->load(KisGlobalResourcesInterface::instance()); 0137 QVERIFY(!brush->brushTipImage().isNull()); 0138 qsrand(1); 0139 0140 const KoColorSpace* cs = KoColorSpaceRegistry::instance()->rgb8(); 0141 KisPaintInformation info(QPointF(100.0, 100.0), 0.5); 0142 KisFixedPaintDeviceSP dab; 0143 0144 { 0145 // warm up the pyramid! 0146 dab = brush->paintDevice(cs, KisDabShape(qreal(qrand()) / RAND_MAX * 2.0, 1.0, 0.0), info); 0147 QVERIFY(dab); // avoid compiler elimination of unused code! 0148 dab.clear(); 0149 } 0150 0151 QBENCHMARK { 0152 dab = brush->paintDevice(cs, KisDabShape(qreal(qrand()) / RAND_MAX * 2.0, 1.0, 0.0), info); 0153 //dab->convertToQImage(0).save(QString("dab_%1_new_smooth.png").arg(i++)); 0154 } 0155 } 0156 0157 void KisGbrBrushTest::benchmarkRotation() 0158 { 0159 QScopedPointer<KisGbrBrush> brush(new KisGbrBrush(QString(FILES_DATA_DIR) + '/' + "testing_brush_512_bars.gbr")); 0160 brush->load(KisGlobalResourcesInterface::instance()); 0161 QVERIFY(!brush->brushTipImage().isNull()); 0162 qsrand(1); 0163 0164 const KoColorSpace* cs = KoColorSpaceRegistry::instance()->rgb8(); 0165 KisPaintInformation info(QPointF(100.0, 100.0), 0.5); 0166 KisFixedPaintDeviceSP dab; 0167 0168 QBENCHMARK { 0169 dab = brush->paintDevice(cs, KisDabShape(1.0, 1.0, qreal(qrand()) / RAND_MAX * 2 * M_PI), info); 0170 } 0171 } 0172 0173 void KisGbrBrushTest::benchmarkMaskScaling() 0174 { 0175 QScopedPointer<KisGbrBrush> brush(new KisGbrBrush(QString(FILES_DATA_DIR) + '/' + "testing_brush_512_bars.gbr")); 0176 brush->load(KisGlobalResourcesInterface::instance()); 0177 QVERIFY(!brush->brushTipImage().isNull()); 0178 qsrand(1); 0179 0180 const KoColorSpace* cs = KoColorSpaceRegistry::instance()->rgb8(); 0181 KisPaintInformation info(QPointF(100.0, 100.0), 0.5); 0182 KisFixedPaintDeviceSP dab = new KisFixedPaintDevice(cs); 0183 0184 QBENCHMARK { 0185 KoColor c(Qt::black, cs); 0186 qreal scale = qreal(qrand()) / RAND_MAX * 2.0; 0187 brush->mask(dab, c, KisDabShape(scale, 1.0, 0.0), info, 0.0, 0.0, 1.0); 0188 } 0189 } 0190 0191 void KisGbrBrushTest::testPyramidLevelRounding() 0192 { 0193 QSize imageSize(41, 41); 0194 QImage image(imageSize, QImage::Format_ARGB32); 0195 image.fill(0); 0196 0197 KisQImagePyramid pyramid(image); 0198 0199 qreal baseScale; 0200 int baseLevel; 0201 0202 baseLevel = pyramid.findNearestLevel(1.0, &baseScale); 0203 QCOMPARE(baseScale, 1.0); 0204 QCOMPARE(baseLevel, 3); 0205 0206 baseLevel = pyramid.findNearestLevel(2.0, &baseScale); 0207 QCOMPARE(baseScale, 2.0); 0208 QCOMPARE(baseLevel, 2); 0209 0210 baseLevel = pyramid.findNearestLevel(4.0, &baseScale); 0211 QCOMPARE(baseScale, 4.0); 0212 QCOMPARE(baseLevel, 1); 0213 0214 baseLevel = pyramid.findNearestLevel(0.5, &baseScale); 0215 QCOMPARE(baseScale, 0.5); 0216 QCOMPARE(baseLevel, 4); 0217 0218 baseLevel = pyramid.findNearestLevel(0.25, &baseScale); 0219 QCOMPARE(baseScale, 0.25); 0220 QCOMPARE(baseLevel, 5); 0221 0222 baseLevel = pyramid.findNearestLevel(0.25 + 1e-7, &baseScale); 0223 QCOMPARE(baseScale, 0.25); 0224 QCOMPARE(baseLevel, 5); 0225 } 0226 0227 static QSize dabTransformHelper(KisDabShape const& shape) 0228 { 0229 QSize const testSize(150, 150); 0230 qreal const subPixelX = 0.0, 0231 subPixelY = 0.0; 0232 return KisQImagePyramid::imageSize(testSize, shape, subPixelX, subPixelY); 0233 } 0234 0235 void KisGbrBrushTest::testPyramidDabTransform() 0236 { 0237 QCOMPARE(dabTransformHelper(KisDabShape(1.0, 1.0, 0.0)), QSize(150, 150)); 0238 QCOMPARE(dabTransformHelper(KisDabShape(1.0, 0.5, 0.0)), QSize(150, 75)); 0239 QCOMPARE(dabTransformHelper(KisDabShape(1.0, 1.0, M_PI / 4)), QSize(213, 213)); 0240 QCOMPARE(dabTransformHelper(KisDabShape(1.0, 0.5, M_PI / 4)), QSize(160, 160)); 0241 } 0242 0243 // see comment in KisQImagePyramid::appendPyramidLevel 0244 void KisGbrBrushTest::testQPainterTransformationBorder() 0245 { 0246 QImage image1(10, 10, QImage::Format_ARGB32); 0247 QImage image2(12, 12, QImage::Format_ARGB32); 0248 0249 image1.fill(0); 0250 image2.fill(0); 0251 0252 { 0253 QPainter gc(&image1); 0254 gc.fillRect(QRect(0, 0, 10, 10), Qt::black); 0255 } 0256 0257 { 0258 QPainter gc(&image2); 0259 gc.fillRect(QRect(1, 1, 10, 10), Qt::black); 0260 } 0261 0262 image1.save("src1.png"); 0263 image2.save("src2.png"); 0264 0265 { 0266 QImage canvas(100, 100, QImage::Format_ARGB32); 0267 canvas.fill(0); 0268 QPainter gc(&canvas); 0269 QTransform transform; 0270 transform.rotate(15); 0271 gc.setTransform(transform); 0272 gc.setRenderHints(QPainter::SmoothPixmapTransform); 0273 gc.drawImage(QPointF(50, 50), image1); 0274 gc.end(); 0275 canvas.save("canvas1.png"); 0276 } 0277 { 0278 QImage canvas(100, 100, QImage::Format_ARGB32); 0279 canvas.fill(0); 0280 QPainter gc(&canvas); 0281 QTransform transform; 0282 transform.rotate(15); 0283 gc.setTransform(transform); 0284 gc.setRenderHints(QPainter::SmoothPixmapTransform); 0285 gc.drawImage(QPointF(50, 50), image2); 0286 gc.end(); 0287 canvas.save("canvas2.png"); 0288 } 0289 } 0290 0291 SIMPLE_TEST_MAIN(KisGbrBrushTest)