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 */