diff --git a/krita/image/kis_grid_interpolation_tools.h b/krita/image/kis_grid_interpolation_tools.h index adfc2eb295a3d2acf9696606549eaf0f0a85ad35..24de41b212ad7b69034e733ad555e2d1cef3ee6b 100644 --- a/krita/image/kis_grid_interpolation_tools.h +++ b/krita/image/kis_grid_interpolation_tools.h @@ -531,6 +531,26 @@ struct AlwaysCompletePolygonPolicy { } }; +/** + * There is a weird problem in fetching correct bounds of the polygon. + * If the rightmost (bottommost) point of the polygon is integral, then + * QRectF() will end exactly on it, but when converting into QRect the last + * point will not be taken into account. It happens due to the difference + * between center-point/topleft-point point representation. In many cases + * the latter is expected, but we don't work with it in Qt/Krita. + */ +inline void adjustAlignedPolygon(QPolygonF &polygon) +{ + static const qreal eps = 1e-5; + static const QPointF p1(eps, 0.0); + static const QPointF p2(eps, eps); + static const QPointF p3(0.0, eps); + + polygon[1] += p1; + polygon[2] += p2; + polygon[3] += p3; +} + template
class IncompletePolygonPolicy, class PolygonOp, class IndexesOp> @@ -566,6 +586,9 @@ void iterateThroughGrid(PolygonOp &polygonOp, dstPolygon << transformedPoints[index]; } + adjustAlignedPolygon(srcPolygon); + adjustAlignedPolygon(dstPolygon); + polygonOp(srcPolygon, dstPolygon); } } diff --git a/krita/image/kis_paint_device.cc b/krita/image/kis_paint_device.cc index dbb4be27f84c1ce4e2e41ff875d6be46e040d278..43fff50e3b47cfda518db13a1f58a8127d5ea7bb 100644 --- a/krita/image/kis_paint_device.cc +++ b/krita/image/kis_paint_device.cc @@ -723,6 +723,16 @@ QImage KisPaintDevice::convertToQImage(const KoColorProfile *dstProfile, KoColor return convertToQImage(dstProfile, x1, y1, w, h, renderingIntent, conversionFlags); } +QImage KisPaintDevice::convertToQImage(const KoColorProfile *dstProfile, + const QRect &rc, + KoColorConversionTransformation::Intent renderingIntent, + KoColorConversionTransformation::ConversionFlags conversionFlags) const +{ + return convertToQImage(dstProfile, + rc.x(), rc.y(), rc.width(), rc.height(), + renderingIntent, conversionFlags); +} + QImage KisPaintDevice::convertToQImage(const KoColorProfile * dstProfile, qint32 x1, qint32 y1, qint32 w, qint32 h, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags) const { diff --git a/krita/image/kis_paint_device.h b/krita/image/kis_paint_device.h index f6a6c8da17d1cc181418b965def8fc13b61bb145..efc04cb8c710348f493a51eb55da921f854b7b62 100644 --- a/krita/image/kis_paint_device.h +++ b/krita/image/kis_paint_device.h @@ -445,6 +445,14 @@ public: KoColorConversionTransformation::Intent renderingIntent = KoColorConversionTransformation::InternalRenderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags = KoColorConversionTransformation::InternalConversionFlags) const; + /** + * Overridden method for convenience + */ + QImage convertToQImage(const KoColorProfile *dstProfile, + const QRect &rc, + KoColorConversionTransformation::Intent renderingIntent = KoColorConversionTransformation::InternalRenderingIntent, + KoColorConversionTransformation::ConversionFlags conversionFlags = KoColorConversionTransformation::InternalConversionFlags) const; + /** * Create an RGBA QImage from a rectangle in the paint device. The * rectangle is defined by the parent image's bounds. diff --git a/krita/image/tests/kis_liquify_transform_worker_test.cpp b/krita/image/tests/kis_liquify_transform_worker_test.cpp index 180efac720797094d8e270ccbbd275b6f09c4557..9444efb679f3d50211774318e391c6cf454f1b26 100644 --- a/krita/image/tests/kis_liquify_transform_worker_test.cpp +++ b/krita/image/tests/kis_liquify_transform_worker_test.cpp @@ -20,112 +20,14 @@ #include +#include #include #include "testutil.h" - #include - -#include -#include - #include -void testCage(bool clockwise, bool unityTransform, bool benchmarkPrepareOnly = false, int pixelPrecision = 8, bool testQImage = false) -{ - TestUtil::TestProgressBar bar; - KoProgressUpdater pu(&bar); - KoUpdaterPtr updater = pu.startSubtask(); - - const KoColorSpace *cs = KoColorSpaceRegistry::instance()->rgb8(); - QImage image(TestUtil::fetchDataFileLazy("test_cage_transform.png")); - - KisPaintDeviceSP dev = new KisPaintDevice(cs); - dev->convertFromQImage(image, 0); - - QVector origPoints; - QVector transfPoints; - - QRectF bounds(dev->exactBounds()); - - origPoints << bounds.topLeft(); - origPoints << 0.5 * (bounds.topLeft() + bounds.topRight()); - origPoints << 0.5 * (bounds.topLeft() + bounds.bottomRight()); - origPoints << 0.5 * (bounds.topRight() + bounds.bottomRight()); - origPoints << bounds.bottomRight(); - origPoints << bounds.bottomLeft(); - - if (!clockwise) { - std::reverse(origPoints.begin(), origPoints.end()); - } - - if (unityTransform) { - transfPoints = origPoints; - } else { - transfPoints << bounds.topLeft(); - transfPoints << 0.5 * (bounds.topLeft() + bounds.topRight()); - transfPoints << 0.5 * (bounds.bottomLeft() + bounds.bottomRight()); - transfPoints << 0.5 * (bounds.bottomLeft() + bounds.bottomRight()) + - (bounds.bottomLeft() - bounds.topLeft()); - transfPoints << bounds.bottomLeft() + - (bounds.bottomLeft() - bounds.topLeft()); - transfPoints << bounds.bottomLeft(); - - if (!clockwise) { - std::reverse(transfPoints.begin(), transfPoints.end()); - } - } - - KisCageTransformWorker worker(dev, - origPoints, - updater, - pixelPrecision); - - QImage result; - QPointF srcQImageOffset(0, 0); - QPointF dstQImageOffset; - - QBENCHMARK_ONCE { - if (!testQImage) { - worker.prepareTransform(); - if (!benchmarkPrepareOnly) { - worker.setTransformedCage(transfPoints); - worker.run(); - - } - } else { - QImage srcImage(image); - image = QImage(image.size(), QImage::Format_ARGB32); - QPainter gc(&image); - gc.drawImage(QPoint(), srcImage); - - image.convertToFormat(QImage::Format_ARGB32); - - KisCageTransformWorker qimageWorker(image, - srcQImageOffset, - origPoints, - updater, - pixelPrecision); - qimageWorker.prepareTransform(); - qimageWorker.setTransformedCage(transfPoints); - result = qimageWorker.runOnQImage(&dstQImageOffset); - } - } - - QString testName = QString("%1_%2") - .arg(clockwise ? "clk" : "cclk") - .arg(unityTransform ? "unity" : "normal"); - - if (testQImage) { - QVERIFY(TestUtil::checkQImage(result, "cage_transform_test", "cage_qimage", testName)); - } else if (!benchmarkPrepareOnly && pixelPrecision == 8) { - - result = dev->convertToQImage(0); - QVERIFY(TestUtil::checkQImage(result, "cage_transform_test", "cage", testName)); - } -} - void KisLiquifyTransformWorkerTest::testPoints() { TestUtil::TestProgressBar bar; @@ -226,4 +128,29 @@ void KisLiquifyTransformWorkerTest::testPointsQImage() TestUtil::checkQImage(result, "liquify_transform_test", "liquify_qimage", "resultImage"); } +void KisLiquifyTransformWorkerTest::testIdentityTransform() +{ + TestUtil::TestProgressBar bar; + KoProgressUpdater pu(&bar); + KoUpdaterPtr updater = pu.startSubtask(); + + const KoColorSpace *cs = KoColorSpaceRegistry::instance()->rgb8(); + + QRect rc(0,0,13,23); + + KisPaintDeviceSP dev = new KisPaintDevice(cs); + dev->fill(rc, KoColor(Qt::blue, cs)); + + const int pixelPrecision = 8; + + KisLiquifyTransformWorker worker(dev->exactBounds(), + updater, + pixelPrecision); + + worker.run(dev); + + QImage result = dev->convertToQImage(0, rc); + TestUtil::checkQImage(result, "liquify_transform_test", "liquify_dev", "identity"); +} + QTEST_KDEMAIN(KisLiquifyTransformWorkerTest, GUI) diff --git a/krita/image/tests/kis_liquify_transform_worker_test.h b/krita/image/tests/kis_liquify_transform_worker_test.h index 64a0c2044285326bccf1a5f6525654caebd3426e..e38302eec474934002f10089fe9764a8dc96b9c7 100644 --- a/krita/image/tests/kis_liquify_transform_worker_test.h +++ b/krita/image/tests/kis_liquify_transform_worker_test.h @@ -27,6 +27,7 @@ class KisLiquifyTransformWorkerTest : public QObject private slots: void testPoints(); void testPointsQImage(); + void testIdentityTransform(); }; #endif /* __KIS_LIQUIFY_TRANSFORM_WORKER_TEST_H */