Warning, file /graphics/krita/sdk/tests/qimage_based_test.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002  *  SPDX-FileCopyrightText: 2011 Dmitry Kazakov <dimula73@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #ifndef __QIMAGE_BASED_TEST_H
0008 #define __QIMAGE_BASED_TEST_H
0009 
0010 #ifndef USE_DOCUMENT
0011 #define USE_DOCUMENT 1
0012 #endif /* USE_DOCUMENT */
0013 
0014 #include <testutil.h>
0015 
0016 
0017 #include <KoColorSpace.h>
0018 #include <KoColorSpaceRegistry.h>
0019 
0020 #include <KoShapeContainer.h>
0021 #include <KoShapeRegistry.h>
0022 #include <KoShapeFactoryBase.h>
0023 
0024 #if USE_DOCUMENT
0025 #include "KisDocument.h"
0026 #include "kis_shape_layer.h"
0027 #endif /* USE_DOCUMENT */
0028 
0029 #include "kis_undo_stores.h"
0030 #include "kis_image.h"
0031 #include "kis_selection.h"
0032 #include "kis_paint_layer.h"
0033 #include "kis_adjustment_layer.h"
0034 #include "kis_transparency_mask.h"
0035 #include "kis_clone_layer.h"
0036 #include <KisGlobalResourcesInterface.h>
0037 
0038 #include "filter/kis_filter.h"
0039 #include "filter/kis_filter_registry.h"
0040 #include "kis_filter_configuration.h"
0041 
0042 #include "commands/kis_selection_commands.h"
0043 
0044 
0045 namespace TestUtil
0046 {
0047 
0048 class QImageBasedTest
0049 {
0050 public:
0051     QImageBasedTest(const QString &directoryName)
0052         : m_directoryName(directoryName)
0053     {
0054     }
0055 
0056     // you need to declare your own test function
0057     // See KisProcessingTest for example
0058 
0059 protected:
0060 
0061     /**
0062      * Creates a complex image connected to a surrogate undo store
0063      */
0064     KisImageSP createImage(KisSurrogateUndoStore *undoStore) {
0065         QImage sourceImage(fetchDataFileLazy("hakonepa.png"));
0066 
0067         QRect imageRect = QRect(QPoint(0,0), sourceImage.size());
0068 
0069         QRect transpRect(50,50,300,300);
0070         QRect blurRect(66,66,300,300);
0071         QPoint blurShift(34,34);
0072         QPoint cloneShift(75,75);
0073 
0074         const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8();
0075         KisImageSP image = new KisImage(undoStore, imageRect.width(), imageRect.height(), cs, "merge test");
0076 
0077         KisFilterSP filter = KisFilterRegistry::instance()->value("blur");
0078         Q_ASSERT(filter);
0079         KisFilterConfigurationSP configuration = filter->defaultConfiguration(KisGlobalResourcesInterface::instance());
0080         Q_ASSERT(configuration);
0081 
0082         /**
0083          * HACK ALERT: before this commit a07ef143f6 the meaning of
0084          * 'strength' was different. After that, to make the tests
0085          * run correctly we should manually set the old value (it is
0086          * not available via GUI anymore).
0087          */
0088         configuration->setProperty("strength", 500);
0089 
0090         KisAdjustmentLayerSP blur1 = new KisAdjustmentLayer(image, "blur1", configuration->cloneWithResourcesSnapshot(), 0);
0091         blur1->internalSelection()->clear();
0092         blur1->internalSelection()->pixelSelection()->select(blurRect);
0093         blur1->setX(blurShift.x());
0094         blur1->setY(blurShift.y());
0095 
0096         KisPaintLayerSP paintLayer1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8);
0097         paintLayer1->paintDevice()->convertFromQImage(sourceImage, 0, 0, 0);
0098 
0099         KisCloneLayerSP cloneLayer1 =
0100             new KisCloneLayer(paintLayer1, image, "clone1", OPACITY_OPAQUE_U8);
0101         cloneLayer1->setX(cloneShift.x());
0102         cloneLayer1->setY(cloneShift.y());
0103 
0104         image->addNode(cloneLayer1);
0105         image->addNode(blur1);
0106         image->addNode(paintLayer1);
0107 
0108         KisTransparencyMaskSP transparencyMask1 = new KisTransparencyMask(image, "tmask1");
0109         transparencyMask1->testingInitSelection(transpRect, paintLayer1);
0110 
0111         image->addNode(transparencyMask1, paintLayer1);
0112 
0113         return image;
0114     }
0115 
0116     /**
0117      * Creates a simple image with one empty layer and connects it to
0118      * a surrogate undo store
0119      */
0120     KisImageSP createTrivialImage(KisSurrogateUndoStore *undoStore) {
0121         QRect imageRect = QRect(0, 0, 640, 441);
0122 
0123         const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8();
0124         KisImageSP image = new KisImage(undoStore, imageRect.width(), imageRect.height(), cs, "merge test");
0125 
0126         KisPaintLayerSP paintLayer1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8);
0127         image->addNode(paintLayer1);
0128 
0129         return image;
0130     }
0131 
0132     void addGlobalSelection(KisImageSP image) {
0133         QRect selectionRect(40,40,300,300);
0134 
0135         KisSelectionSP selection = new KisSelection(new KisDefaultBounds(image));
0136         KisPixelSelectionSP pixelSelection = selection->pixelSelection();
0137         pixelSelection->select(selectionRect);
0138 
0139         KUndo2Command *cmd = new KisSetGlobalSelectionCommand(image, selection);
0140         image->undoAdapter()->addCommand(cmd);
0141     }
0142 
0143 #if USE_DOCUMENT
0144 
0145     void addShapeLayer(KisDocument *doc, KisImageSP image) {
0146 
0147         KisShapeLayerSP shapeLayer = new KisShapeLayer(doc->shapeController(), image.data(), "shape", OPACITY_OPAQUE_U8);
0148         image->addNode(shapeLayer);
0149 
0150         KoShapeFactoryBase *f1 = KoShapeRegistry::instance()->get("StarShape");
0151         KoShapeFactoryBase *f2 = KoShapeRegistry::instance()->get("RectangleShape");
0152 
0153         KoShape *shape1 = f1->createDefaultShape();
0154         KoShape *shape2 = f2->createDefaultShape();
0155 
0156         shape1->setPosition(QPointF(100,100));
0157         shape2->setPosition(QPointF(200,200));
0158 
0159         shapeLayer->addShape(shape1);
0160         shapeLayer->addShape(shape2);
0161 
0162         QApplication::processEvents();
0163     }
0164 
0165 #endif /* USE_DOCUMENT*/
0166 
0167     bool checkLayersInitial(KisImageWSP image, int baseFuzzyness = 0) {
0168         QString prefix = "initial_with_selection";
0169         QString prefix2 = findNode(image->root(), "shape") ? "_with_shape" : "";
0170         return checkLayers(image, prefix + prefix2, baseFuzzyness);
0171     }
0172 
0173     bool checkLayersInitialRootOnly(KisImageWSP image, int baseFuzzyness = 0) {
0174         QString prefix = "initial_with_selection";
0175         QString prefix2 = findNode(image->root(), "shape") ? "_with_shape" : "";
0176         return checkLayers(image, prefix + prefix2, baseFuzzyness, false);
0177     }
0178 
0179     /**
0180      * Checks the content of image's layers against the set of
0181      * QImages stored in @p prefix subfolder
0182      */
0183     bool checkLayers(KisImageWSP image, const QString &prefix, int baseFuzzyness = 0, bool recursive = true) {
0184         QVector<QImage> images;
0185         QVector<QString> names;
0186 
0187         fillNamesImages(image->root(), image->bounds(), images, names, recursive);
0188 
0189         bool valid = true;
0190 
0191         const int stackSize = images.size();
0192         for(int i = 0; i < stackSize; i++) {
0193             if(!checkOneQImage(images[i], prefix, names[i], baseFuzzyness)) {
0194                 valid = false;
0195             }
0196         }
0197 
0198         return valid;
0199     }
0200 
0201     /**
0202      * Checks the content of one image's layer against the QImage
0203      * stored in @p prefix subfolder
0204      */
0205     bool checkOneLayer(KisImageWSP image, KisNodeSP node,  const QString &prefix, int baseFuzzyness = 0) {
0206         QVector<QImage> images;
0207         QVector<QString> names;
0208 
0209         fillNamesImages(node, image->bounds(), images, names);
0210 
0211         return checkOneQImage(images.first(), prefix, names.first(), baseFuzzyness);
0212     }
0213 
0214     // add default bounds param
0215     bool checkOneDevice(KisPaintDeviceSP device,
0216                         const QString &prefix,
0217                         const QString &name,
0218                         int baseFuzzyness = 0)
0219     {
0220         QImage image = device->convertToQImage(0);
0221         return checkOneQImage(image, prefix, name, baseFuzzyness);
0222     }
0223 
0224     KisNodeSP findNode(KisNodeSP root, const QString &name) {
0225         return TestUtil::findNode(root, name);
0226     }
0227 
0228 private:
0229     bool checkOneQImage(const QImage &image,
0230                         const QString &prefix,
0231                         const QString &name,
0232                         int baseFuzzyness)
0233     {
0234         QString realName = prefix + "_" + name + ".png";
0235         QString expectedName = prefix + "_" + name + "_expected.png";
0236 
0237         bool valid = true;
0238 
0239         QString fullPath = fetchDataFileLazy(m_directoryName + '/' +
0240                                              prefix + '/' + realName);
0241 
0242         if (fullPath.isEmpty()) {
0243             // Try without the testname subdirectory
0244             fullPath = fetchDataFileLazy(prefix + '/' +
0245                                          realName);
0246         }
0247 
0248         if (fullPath.isEmpty()) {
0249             // Try without the prefix subdirectory
0250             fullPath = fetchDataFileLazy(m_directoryName + '/' +
0251                                          realName);
0252         }
0253 
0254         QImage ref(fullPath);
0255 
0256         QPoint temp;
0257         int fuzzy = baseFuzzyness;
0258 
0259         {
0260             QStringList terms = name.split('_');
0261             if(terms[0] == "root" ||
0262                terms[0] == "blur1" ||
0263                terms[0] == "shape") {
0264 
0265                 fuzzy++;
0266             }
0267         }
0268 
0269         if(ref != image &&
0270            !TestUtil::compareQImages(temp, ref, image, fuzzy, fuzzy)) {
0271 
0272 
0273             dbgKrita << "--- Wrong image:" << realName;
0274             valid = false;
0275 
0276             image.save(QString(FILES_OUTPUT_DIR) + '/' + realName);
0277             ref.save(QString(FILES_OUTPUT_DIR) + '/' + expectedName);
0278         }
0279 
0280         return valid;
0281     }
0282 
0283     void fillNamesImages(KisNodeSP node, const QRect &rc,
0284                          QVector<QImage> &images,
0285                          QVector<QString> &names,
0286                          bool recursive = true) {
0287 
0288         while (node) {
0289             if(node->paintDevice()) {
0290                 names.append(node->name() + "_paintDevice");
0291                 images.append(node->paintDevice()->
0292                               convertToQImage(0, rc.x(), rc.y(),
0293                                               rc.width(), rc.height()));
0294             }
0295 
0296             if(node->original() && node->original() != node->paintDevice()) {
0297                 names.append(node->name() + "_original");
0298                 images.append(node->original()->
0299                               convertToQImage(0, rc.x(), rc.y(),
0300                                               rc.width(), rc.height()));
0301             }
0302 
0303             if(node->projection() && node->projection() != node->paintDevice()) {
0304                 names.append(node->name() + "_projection");
0305                 images.append(node->projection()->
0306                               convertToQImage(0, rc.x(), rc.y(),
0307                                               rc.width(), rc.height()));
0308             }
0309 
0310             if (recursive) {
0311                 fillNamesImages(node->firstChild(), rc, images, names);
0312             }
0313             node = node->nextSibling();
0314         }
0315     }
0316 
0317 private:
0318     QString m_directoryName;
0319 
0320 };
0321 
0322 }
0323 
0324 #endif /* __QIMAGE_BASED_TEST_H */