void KisProjectionTest::testDirty() { KisImageSP image = new KisImage(0, 1000, 1000, 0, "layer tests"); // Two layers so the single-layer-is-rootlayer optimization doesn't kick in KisLayerSP layer = new KisPaintLayer(image, "layer 1", OPACITY_OPAQUE_U8); KisLayerSP layer2 = new KisPaintLayer(image, "layer 2", OPACITY_OPAQUE_U8); image->addNode(layer); image->addNode(layer2); KisFillPainter gc(layer2->paintDevice()); KoColor c(Qt::red, layer2->colorSpace()); gc.fillRect(0, 0, 1000, 1000, c); gc.end(); layer2->setDirty(gc.takeDirtyRegion()); // wait a little for the projection to finish QTest::qSleep(250); // Check that the projection is totally redistribute KisSequentialConstIterator it(image->projection(), QRect(0, 0, 1000, 1000)); do { QColor c; image->colorSpace()->toQColor(it.oldRawData(), &c, image->profile()); QVERIFY(c == Qt::red); } while (it.nextPixel()); }
void KisLayerTest::testMoveLayer() { const KoColorSpace * colorSpace = KoColorSpaceRegistry::instance()->colorSpace("RGBA", 0); KisImageSP image = new KisImage(0, 512, 512, colorSpace, "layer test"); KisLayerSP node1 = new TestLayer(image, "layer1", OPACITY_OPAQUE); KisLayerSP node2 = new TestLayer(image, "layer2", OPACITY_OPAQUE); KisLayerSP node3 = new TestLayer(image, "layer3", OPACITY_OPAQUE); node1->setName("node1"); node2->setName("node2"); node3->setName("node3"); QVERIFY(image->addNode(node1)); QVERIFY(image->addNode(node2)); QVERIFY(image->addNode(node3)); QVERIFY(image->root()->at(0) == node1.data()); QVERIFY(image->root()->at(1) == node2.data()); QVERIFY(image->root()->at(2) == node3.data()); QVERIFY(image->moveNode(node3, image->rootLayer(), node1)); QVERIFY(image->root()->at(0) == node1.data()); QVERIFY(image->root()->at(1) == node3.data()); QVERIFY(image->root()->at(2) == node2.data()); }
void KisAsyncMergerTest::debugObligeChild() { const KoColorSpace * colorSpace = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, 640, 441, colorSpace, "merger test"); QImage sourceImage1(QString(FILES_DATA_DIR) + QDir::separator() + "hakonepa.png"); KisPaintDeviceSP device1 = new KisPaintDevice(colorSpace); device1->convertFromQImage(sourceImage1, 0, 0, 0); KisLayerSP paintLayer1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8, device1); KisLayerSP groupLayer = new KisGroupLayer(image, "group", OPACITY_OPAQUE_U8); image->addNode(groupLayer, image->rootLayer()); image->addNode(paintLayer1, groupLayer); QRect testRect1(0,0,640,441); QRect cropRect(image->bounds()); KisMergeWalker walker(cropRect); KisAsyncMerger merger; walker.collectRects(paintLayer1, testRect1); merger.startMerge(walker); KisLayerSP rootLayer = image->rootLayer(); QVERIFY(rootLayer->original() == groupLayer->projection()); QVERIFY(groupLayer->original() == paintLayer1->projection()); }
void KisImageTest::testLayerComposition() { KisImageSP image = new KisImage(0, IMAGE_WIDTH, IMAGE_WIDTH, 0, "layer tests"); QVERIFY(image->rootLayer() != 0); QVERIFY(image->rootLayer()->firstChild() == 0); KisLayerSP layer = new KisPaintLayer(image, "layer 1", OPACITY_OPAQUE_U8); image->addNode(layer); KisLayerSP layer2 = new KisPaintLayer(image, "layer 2", OPACITY_OPAQUE_U8); image->addNode(layer2); QVERIFY(layer->visible()); QVERIFY(layer2->visible()); KisLayerComposition comp(image, "comp 1"); comp.store(); layer2->setVisible(false); QVERIFY(layer->visible()); QVERIFY(!layer2->visible()); KisLayerComposition comp2(image, "comp 2"); comp2.store(); comp.apply(); QVERIFY(layer->visible()); QVERIFY(layer2->visible()); comp2.apply(); QVERIFY(layer->visible()); QVERIFY(!layer2->visible()); }
void KisSimpleUpdateQueueTest::testChecksum() { QRect imageRect(0,0,512,512); QRect dirtyRect(100,100,100,100); const KoColorSpace * colorSpace = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, imageRect.width(), imageRect.height(), colorSpace, "test"); KisLayerSP paintLayer1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8); KisAdjustmentLayerSP adjustmentLayer = new KisAdjustmentLayer(image, "adj", 0, 0); image->lock(); image->addNode(paintLayer1, image->rootLayer()); image->addNode(adjustmentLayer, image->rootLayer()); image->unlock(); KisFilterSP filter = KisFilterRegistry::instance()->value("blur"); Q_ASSERT(filter); KisFilterConfiguration *configuration = filter->defaultConfiguration(0); KisTestableSimpleUpdateQueue queue; KisWalkersList& walkersList = queue.getWalkersList(); { TestUtil::LodOverride l(1, image); queue.addUpdateJob(adjustmentLayer, dirtyRect, imageRect, 1); QCOMPARE(walkersList[0]->checksumValid(), true); QCOMPARE(walkersList[0]->levelOfDetail(), 1); } adjustmentLayer->setFilter(configuration); { TestUtil::LodOverride l(1, image); QCOMPARE(walkersList[0]->checksumValid(), false); } QVector<KisUpdateJobItem*> jobs; KisTestableUpdaterContext context(2); { TestUtil::LodOverride l(1, image); queue.processQueue(context); } jobs = context.getJobs(); { TestUtil::LodOverride l(1, image); QCOMPARE(jobs[0]->walker()->checksumValid(), true); } }
void addLayers(const QVector<Layer> &layers, KisImageSP image, int depth) { for(int i = 0; i < layers.size(); i++) { const Layer &layer = layers[i]; if (layer.depth == depth) { KisGroupLayerSP group = (depth == 0 ? image->rootLayer() : findGroup(layers, layer, i)); image->addNode(layer.layer, group); if (layer.mask) { image->addNode(layer.mask, layer.layer); } } } }
void KisGmicTests::testGatherLayers() { const KoColorSpace * colorSpace = KoColorSpaceRegistry::instance()->rgb8(); QImage background(QString(FILES_DATA_DIR) + QDir::separator() + "00_BG.png"); QImage colorMarks(QString(FILES_DATA_DIR) + QDir::separator() + "01_ColorMarks.png"); QImage artLine(QString(FILES_DATA_DIR) + QDir::separator() + "02_Artline.png"); KisImageSP image = new KisImage(0, 2408, 3508, colorSpace, "filter test"); KisPaintDeviceSP device1 = new KisPaintDevice(colorSpace); KisPaintDeviceSP device2 = new KisPaintDevice(colorSpace); KisPaintDeviceSP device3 = new KisPaintDevice(colorSpace); device1->convertFromQImage(background, 0, 0, 0); device2->convertFromQImage(colorMarks, 0, 0, 0); device3->convertFromQImage(artLine, 0, 0, 0); KisLayerSP paintLayer1 = new KisPaintLayer(image, "background", OPACITY_OPAQUE_U8, device1); KisLayerSP paintLayer2 = new KisPaintLayer(image, "colorMarks", OPACITY_OPAQUE_U8, device2); KisLayerSP paintLayer3 = new KisPaintLayer(image, "artLine", OPACITY_OPAQUE_U8, device3); image->addNode(paintLayer1, image->rootLayer()); image->addNode(paintLayer2, image->rootLayer()); image->addNode(paintLayer3, image->rootLayer()); KisNodeSP activeNode = static_cast<KisNodeSP>(paintLayer2); KisNodeListSP result; KisInputOutputMapper mapper(image, activeNode); result = mapper.inputNodes(ACTIVE_LAYER); QCOMPARE(result->at(0)->name(), activeNode->name()); result = mapper.inputNodes(ACTIVE_LAYER_ABOVE_LAYER); QCOMPARE(result->size(), 2); QCOMPARE(result->at(0)->name(), activeNode->name()); QCOMPARE(result->at(1)->name(), paintLayer3->name()); result = mapper.inputNodes(ACTIVE_LAYER_BELOW_LAYER); QCOMPARE(result->size(), 2); QCOMPARE(result->at(0)->name(), activeNode->name()); QCOMPARE(result->at(1)->name(), paintLayer1->name()); result = mapper.inputNodes(ALL_LAYERS); QCOMPARE(result->size(), 3); QCOMPARE(result->at(0)->name(), paintLayer3->name()); QCOMPARE(result->at(1)->name(), paintLayer2->name()); QCOMPARE(result->at(2)->name(), paintLayer1->name()); }
void KisPrescaledProjectionTest::testScalingUndeferredSmoothing() { // Set up a nice image QImage qimage(QString(FILES_DATA_DIR) + QDir::separator() + "lena.png"); // Undo adapter not necessary const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, qimage.width(), qimage.height(), cs, "projection test"); // 300 dpi recalculated to pixels per point (of which there are 72 // to the inch) image->setResolution(100, 100); KisPaintLayerSP layer = new KisPaintLayer(image, "test", OPACITY_OPAQUE_U8, cs); image->addNode(layer.data(), image->rootLayer(), 0); layer->paintDevice()->convertFromQImage(qimage, 0); KisPrescaledProjection projection; KisCoordinatesConverter converter; converter.setImage(image); projection.setCoordinatesConverter(&converter); projection.setMonitorProfile(0, KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags()); projection.setImage(image); testProjectionScenario(projection, &converter, "120dpi"); }
void KisSimpleUpdateQueueTest::testMixingTypes() { QRect imageRect(0,0,1024,1024); const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, imageRect.width(), imageRect.height(), cs, "merge test"); KisPaintLayerSP paintLayer = new KisPaintLayer(image, "test", OPACITY_OPAQUE_U8); image->lock(); image->addNode(paintLayer); image->unlock(); QRect dirtyRect1(0,0,200,200); QRect dirtyRect2(0,0,200,200); QRect dirtyRect3(20,20,200,200); KisTestableSimpleUpdateQueue queue; KisWalkersList& walkersList = queue.getWalkersList(); queue.addUpdateJob(paintLayer, dirtyRect1, imageRect, 0); queue.addFullRefreshJob(paintLayer, dirtyRect2, imageRect, 0); queue.addFullRefreshJob(paintLayer, dirtyRect3, imageRect, 0); queue.addUpdateNoFilthyJob(paintLayer, dirtyRect1, imageRect, 0); QCOMPARE(walkersList.size(), 3); QVERIFY(checkWalker(walkersList[0], QRect(0,0,200,200))); QVERIFY(checkWalker(walkersList[1], QRect(0,0,220,220))); QVERIFY(checkWalker(walkersList[2], QRect(0,0,200,200))); QCOMPARE(walkersList[0]->type(), KisBaseRectsWalker::UPDATE); QCOMPARE(walkersList[1]->type(), KisBaseRectsWalker::FULL_REFRESH); QCOMPARE(walkersList[2]->type(), KisBaseRectsWalker::UPDATE_NO_FILTHY); }
void KisPasteNewActionFactory::run(KisViewManager *viewManager) { Q_UNUSED(viewManager); KisPaintDeviceSP clip = KisClipboard::instance()->clip(QRect(), true); if (!clip) return; QRect rect = clip->exactBounds(); if (rect.isEmpty()) return; KisDocument *doc = KisPart::instance()->createDocument(); KisImageSP image = new KisImage(doc->createUndoStore(), rect.width(), rect.height(), clip->colorSpace(), i18n("Pasted")); KisPaintLayerSP layer = new KisPaintLayer(image.data(), clip->objectName(), OPACITY_OPAQUE_U8, clip->colorSpace()); KisPainter::copyAreaOptimized(QPoint(), clip, layer->paintDevice(), rect); image->addNode(layer.data(), image->rootLayer()); doc->setCurrentImage(image); KisPart::instance()->addDocument(doc); KisMainWindow *win = viewManager->mainWindow(); win->addViewAndNotifyLoadingCompleted(doc); }
void KisPasteNewActionFactory::run(KisView2 *view) { Q_UNUSED(view); KisPaintDeviceSP clip = KisClipboard::instance()->clip(QRect(), true); if (!clip) return; QRect rect = clip->exactBounds(); if (rect.isEmpty()) return; KisDoc2 *doc = new KisDoc2(); if (!doc) return; KisImageSP image = new KisImage(doc->createUndoStore(), rect.width(), rect.height(), clip->colorSpace(), i18n("Pasted")); KisPaintLayerSP layer = new KisPaintLayer(image.data(), clip->objectName(), OPACITY_OPAQUE_U8, clip->colorSpace()); KisPainter p(layer->paintDevice()); p.setCompositeOp(COMPOSITE_COPY); p.bitBlt(0, 0, clip, rect.x(), rect.y(), rect.width(), rect.height()); p.end(); image->addNode(layer.data(), image->rootLayer()); doc->setCurrentImage(image); KoMainWindow *win = doc->documentPart()->createMainWindow(); win->show(); win->setRootDocument(doc); }
void KisSimpleUpdateQueueTest::testJobProcessing() { KisTestableUpdaterContext context(2); QRect imageRect(0,0,200,200); const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, imageRect.width(), imageRect.height(), cs, "merge test"); KisPaintLayerSP paintLayer = new KisPaintLayer(image, "test", OPACITY_OPAQUE_U8); image->lock(); image->addNode(paintLayer); image->unlock(); QRect dirtyRect1(0,0,50,100); QRect dirtyRect2(0,0,100,100); QRect dirtyRect3(50,0,50,100); QRect dirtyRect4(150,150,50,50); QRect dirtyRect5(dirtyRect4); // theoretically, should be merged with 4 QVector<KisUpdateJobItem*> jobs; KisWalkersList walkersList; /** * Process the queue and look what has been added into * the updater context */ KisTestableSimpleUpdateQueue queue; queue.addUpdateJob(paintLayer, dirtyRect1, imageRect, 0); queue.addUpdateJob(paintLayer, dirtyRect2, imageRect, 0); queue.addUpdateJob(paintLayer, dirtyRect3, imageRect, 0); queue.addUpdateJob(paintLayer, dirtyRect4, imageRect, 0); { TestUtil::LodOverride l(1, image); queue.addUpdateJob(paintLayer, dirtyRect5, imageRect, 1); } queue.processQueue(context); jobs = context.getJobs(); QVERIFY(checkWalker(jobs[0]->walker(), dirtyRect2)); QVERIFY(checkWalker(jobs[1]->walker(), dirtyRect4)); QCOMPARE(jobs.size(), 2); QCOMPARE(context.currentLevelOfDetail(), 0); walkersList = queue.getWalkersList(); QCOMPARE(walkersList.size(), 1); QVERIFY(checkWalker(walkersList[0], dirtyRect5, 1)); }
void KisPrescaledProjectionTest::benchmarkUpdate() { QImage referenceImage(QString(FILES_DATA_DIR) + QDir::separator() + "lena.png"); QRect imageRect = QRect(QPoint(0,0), referenceImage.size()); const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, imageRect.width(), imageRect.height(), cs, "projection test"); // set up 300dpi image->setResolution(300 / 72 , 300 / 72); KisPaintLayerSP layer = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8, cs); layer->paintDevice()->convertFromQImage(referenceImage, 0); image->addNode(layer, image->rootLayer(), 0); KisPrescaledProjection projection; KisCoordinatesConverter converter; converter.setImage(image); projection.setCoordinatesConverter(&converter); projection.setMonitorProfile(0, KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags()); projection.setImage(image); // Emulate "Use same aspect as pixels" converter.setResolution(image->xRes(), image->yRes()); converter.setZoom(1.0); KisUpdateInfoSP info = projection.updateCache(image->bounds()); projection.recalculateCache(info); QCOMPARE(imageRect, QRect(0,0,512,512)); QRect dirtyRect(0,0,20,20); const qint32 numShifts = 25; const QPoint offset(dirtyRect.width(),dirtyRect.height()); //CALLGRIND_START_INSTRUMENTATION; QBENCHMARK { for(qint32 i = 0; i < numShifts; i++) { KisUpdateInfoSP tempInfo = projection.updateCache(dirtyRect); projection.recalculateCache(tempInfo); dirtyRect.translate(offset); } } //CALLGRIND_STOP_INSTRUMENTATION; }
void KisImageTest::layerTests() { KisImageSP image = new KisImage(0, IMAGE_WIDTH, IMAGE_WIDTH, 0, "layer tests"); QVERIFY(image->rootLayer() != 0); QVERIFY(image->rootLayer()->firstChild() == 0); KisLayerSP layer = new KisPaintLayer(image, "layer 1", OPACITY_OPAQUE_U8); image->addNode(layer); QVERIFY(image->rootLayer()->firstChild()->objectName() == layer->objectName()); }
KisImageSP utils::createImage(KisUndoStore *undoStore, const QSize &imageSize) { QRect imageRect(0,0,imageSize.width(),imageSize.height()); const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(undoStore, imageRect.width(), imageRect.height(), cs, "stroke test"); KisPaintLayerSP paintLayer1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8); KisPaintLayerSP paintLayer2 = new KisPaintLayer(image, "paint2", OPACITY_OPAQUE_U8); KisPaintLayerSP paintLayer3 = new KisPaintLayer(image, "paint3", OPACITY_OPAQUE_U8); KisPaintLayerSP paintLayer4 = new KisPaintLayer(image, "paint4", OPACITY_OPAQUE_U8); KisPaintLayerSP paintLayer5 = new KisPaintLayer(image, "paint5", OPACITY_OPAQUE_U8); image->lock(); image->addNode(paintLayer1); image->addNode(paintLayer2); image->addNode(paintLayer3); image->addNode(paintLayer4); image->addNode(paintLayer5); image->unlock(); return image; }
KisDoc2 *createDocument(QList<KisNodeSP> nodes) { KisDoc2 *doc = new KisDoc2(); QRect rc; foreach(KisNodeSP node, nodes) { rc |= node->exactBounds(); } KisImageSP image = new KisImage(0, rc.width(), rc.height(), nodes.first()->colorSpace(), nodes.first()->name(), false); foreach(KisNodeSP node, nodes) { image->addNode(node->clone()); }
KisDocument *createDocument(QList<KisNodeSP> nodes) { KisDocument *doc = KisPart::instance()->createDocument(); QRect rc; Q_FOREACH (KisNodeSP node, nodes) { rc |= node->exactBounds(); } KisImageSP image = new KisImage(0, rc.width(), rc.height(), nodes.first()->colorSpace(), nodes.first()->name()); Q_FOREACH (KisNodeSP node, nodes) { image->addNode(node->clone()); }
void KisImageTest::testConvertImageColorSpace() { const KoColorSpace *cs8 = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, 1000, 1000, cs8, "stest"); KisPaintDeviceSP device1 = new KisPaintDevice(cs8); KisLayerSP paint1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8, device1); KisFilterSP filter = KisFilterRegistry::instance()->value("blur"); Q_ASSERT(filter); KisFilterConfiguration *configuration = filter->defaultConfiguration(0); Q_ASSERT(configuration); KisLayerSP blur1 = new KisAdjustmentLayer(image, "blur1", configuration, 0); image->addNode(paint1, image->root()); image->addNode(blur1, image->root()); image->refreshGraph(); const KoColorSpace *cs16 = KoColorSpaceRegistry::instance()->rgb16(); image->lock(); image->convertImageColorSpace(cs16, KoColorConversionTransformation::InternalRenderingIntent, KoColorConversionTransformation::InternalConversionFlags); image->unlock(); QVERIFY(*cs16 == *image->colorSpace()); QVERIFY(*cs16 == *image->root()->colorSpace()); QVERIFY(*cs16 == *paint1->colorSpace()); QVERIFY(*cs16 == *blur1->colorSpace()); QVERIFY(!image->root()->compositeOp()); QVERIFY(*cs16 == *paint1->compositeOp()->colorSpace()); QVERIFY(*cs16 == *blur1->compositeOp()->colorSpace()); image->refreshGraph(); }
void KisSimpleUpdateQueueTest::testSplit(bool useFullRefresh) { QRect imageRect(0,0,1024,1024); const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, imageRect.width(), imageRect.height(), cs, "merge test"); KisPaintLayerSP paintLayer = new KisPaintLayer(image, "test", OPACITY_OPAQUE_U8); image->lock(); image->addNode(paintLayer); image->unlock(); QRect dirtyRect1(0,0,1000,1000); KisTestableSimpleUpdateQueue queue; KisWalkersList& walkersList = queue.getWalkersList(); if(!useFullRefresh) { queue.addUpdateJob(paintLayer, dirtyRect1, imageRect, 0); } else { queue.addFullRefreshJob(paintLayer, dirtyRect1, imageRect, 0); } QCOMPARE(walkersList.size(), 4); QVERIFY(checkWalker(walkersList[0], QRect(0,0,512,512))); QVERIFY(checkWalker(walkersList[1], QRect(512,0,488,512))); QVERIFY(checkWalker(walkersList[2], QRect(0,512,512,488))); QVERIFY(checkWalker(walkersList[3], QRect(512,512,488,488))); queue.optimize(); //must change nothing QCOMPARE(walkersList.size(), 4); QVERIFY(checkWalker(walkersList[0], QRect(0,0,512,512))); QVERIFY(checkWalker(walkersList[1], QRect(512,0,488,512))); QVERIFY(checkWalker(walkersList[2], QRect(0,512,512,488))); QVERIFY(checkWalker(walkersList[3], QRect(512,512,488,488))); }
void KisPasteNewActionFactory::run(KisView2 *view) { Q_UNUSED(view); KisPaintDeviceSP clip = KisClipboard::instance()->clip(QPoint()); if (!clip) return; QRect rect = clip->exactBounds(); if (rect.isEmpty()) return; const QByteArray mimetype = KoServiceProvider::readNativeFormatMimeType(); KoDocumentEntry entry = KoDocumentEntry::queryByMimeType(mimetype); QString error; KisPart2* part = dynamic_cast<KisPart2*>(entry.createKoPart(&error)); if (!part) return; KisDoc2 *doc = new KisDoc2(part); if (!doc) return; part->setDocument(doc); KisImageSP image = new KisImage(doc->createUndoStore(), rect.width(), rect.height(), clip->colorSpace(), i18n("Pasted")); KisPaintLayerSP layer = new KisPaintLayer(image.data(), clip->objectName(), OPACITY_OPAQUE_U8, clip->colorSpace()); KisPainter p(layer->paintDevice()); p.setCompositeOp(COMPOSITE_COPY); p.bitBlt(0, 0, clip, rect.x(), rect.y(), rect.width(), rect.height()); p.end(); image->addNode(layer.data(), image->rootLayer()); doc->setCurrentImage(image); KoMainWindow *win = new KoMainWindow(part->componentData()); win->show(); win->setRootDocument(doc); }
KisImportExportFilter::ConversionStatus KisBMPImport::convert(const QByteArray& from, const QByteArray& to) { dbgFile << "BMP import! From:" << from << ", To:" << to << 0; if (to != "application/x-krita") return KisImportExportFilter::BadMimeType; KisDocument * doc = outputDocument(); if (!doc) return KisImportExportFilter::NoDocumentCreated; QString filename = inputFile(); doc->prepareForImport(); if (!filename.isEmpty()) { QFileInfo fi(filename); if (!fi.exists()) { return KisImportExportFilter::FileNotFound; } QImage img(filename); const KoColorSpace *colorSpace = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(doc->createUndoStore(), img.width(), img.height(), colorSpace, "imported from bmp"); KisPaintLayerSP layer = new KisPaintLayer(image, image->nextLayerName(), 255); layer->paintDevice()->convertFromQImage(img, 0, 0, 0); image->addNode(layer.data(), image->rootLayer().data()); doc->setCurrentImage(image); return KisImportExportFilter::OK; } return KisImportExportFilter::StorageCreationError; }
void KisAsyncMergerTest::testSubgraphingWithoutUpdatingParent() { const KoColorSpace *colorSpace = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, 128, 128, colorSpace, "clones test"); KisPaintDeviceSP device1 = new KisPaintDevice(colorSpace); device1->fill(image->bounds(), KoColor(Qt::white, colorSpace)); KisLayerSP paintLayer1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8, device1); KisPaintDeviceSP device2 = new KisPaintDevice(colorSpace); device2->fill(image->bounds(), KoColor(Qt::black, colorSpace)); KisLayerSP paintLayer2 = new KisPaintLayer(image, "paint2", 128, device2); image->addNode(paintLayer1, image->rootLayer()); image->addNode(paintLayer2, image->rootLayer()); image->initialRefreshGraph(); QImage refImage(QString(FILES_DATA_DIR) + QDir::separator() + "subgraphing_without_updating.png"); { QImage resultImage = image->projection()->convertToQImage(0); QCOMPARE(resultImage, refImage); } QRect cropRect(image->bounds()); KisRefreshSubtreeWalker walker(cropRect); KisAsyncMerger merger; walker.collectRects(paintLayer2, image->bounds()); merger.startMerge(walker); { QImage resultImage = image->projection()->convertToQImage(0); QCOMPARE(resultImage, refImage); } }
KisImageSP createImage(KisUndoStore *undoStore, KisPaintLayerSP &paintLayer1, KisPaintLayerSP &paintLayer2) { const KoColorSpace *cs = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(undoStore, 300, 300, cs, "test"); QRect fillRect1(50,50,100,100); QRect fillRect2(75,75,50,50); paintLayer1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8); paintLayer2 = new KisPaintLayer(image, "paint2", OPACITY_OPAQUE_U8); paintLayer1->paintDevice()->fill(fillRect1, KoColor(Qt::white, cs)); paintLayer2->paintDevice()->fill(fillRect2, KoColor(Qt::red, cs)); image->addNode(paintLayer1, image->rootLayer()); image->addNode(paintLayer2, image->rootLayer()); image->initialRefreshGraph(); return image; }
void KisLayerTest::testCreation() { const KoColorSpace * colorSpace = KoColorSpaceRegistry::instance()->colorSpace("RGBA", 0); KisImageSP image = new KisImage(0, 512, 512, colorSpace, "layer test"); KisLayerSP layer = new TestLayer(image, "test", OPACITY_OPAQUE); QCOMPARE(layer->name(), QString("test")); QCOMPARE(layer->opacity(), OPACITY_OPAQUE); QCOMPARE(layer->image(), image); QCOMPARE(layer->colorSpace(), image->colorSpace()); QCOMPARE(layer->visible(), true); QCOMPARE(layer->userLocked(), false); QCOMPARE(layer->temporary(), false); image->addNode(layer, image->rootLayer()); QBitArray channels(4); channels.fill(true); layer->setChannelFlags(channels); QVERIFY(layer->channelFlags().count() == 4); QCOMPARE(layer->channelFlags().at(0), true); QCOMPARE(layer->channelFlags().at(1), true); QCOMPARE(layer->channelFlags().at(2), true); QCOMPARE(layer->channelFlags().at(3), true); layer->setOpacity(OPACITY_TRANSPARENT); QCOMPARE(layer->opacity(), OPACITY_TRANSPARENT); layer->setPercentOpacity(100); QCOMPARE(layer->opacity(), OPACITY_OPAQUE); layer->setPercentOpacity(0); QCOMPARE(layer->opacity(), OPACITY_TRANSPARENT); }
KoFilter::ConversionStatus KisOpenEXRImport::convert(const QByteArray& from, const QByteArray& to) { if (from != "image/x-exr" || to != "application/x-krita") { return KoFilter::NotImplemented; } dbgFile << "\n\n\nKrita importing from OpenEXR"; KisDoc2 * doc = dynamic_cast<KisDoc2*>(m_chain -> outputDocument()); if (!doc) { return KoFilter::CreationError; } doc -> prepareForImport(); QString filename = m_chain -> inputFile(); if (filename.isEmpty()) { return KoFilter::FileNotFound; } RgbaInputFile file(QFile::encodeName(filename)); Box2i dataWindow = file.dataWindow(); Box2i displayWindow = file.displayWindow(); dbgFile << "Data window:" << QRect(dataWindow.min.x, dataWindow.min.y, dataWindow.max.x - dataWindow.min.x + 1, dataWindow.max.y - dataWindow.min.y + 1); dbgFile << "Display window:" << QRect(displayWindow.min.x, displayWindow.min.y, displayWindow.max.x - displayWindow.min.x + 1, displayWindow.max.y - displayWindow.min.y + 1); int imageWidth = displayWindow.max.x - displayWindow.min.x + 1; int imageHeight = displayWindow.max.y - displayWindow.min.y + 1; QString imageName = "Imported from OpenEXR"; int dataWidth = dataWindow.max.x - dataWindow.min.x + 1; int dataHeight = dataWindow.max.y - dataWindow.min.y + 1; const KoColorSpace *cs = static_cast<const KoColorSpace *>((KoColorSpaceRegistry::instance()->colorSpace(KoID("RgbAF16", ""), ""))); if (cs == 0) { return KoFilter::InternalError; } doc -> undoAdapter() -> setUndo(false); KisImageSP image = new KisImage(doc->undoAdapter(), imageWidth, imageHeight, cs, imageName); if (!image) { return KoFilter::CreationError; } image->lock(); KisPaintLayerSP layer = new KisPaintLayer(image, image->nextLayerName(), OPACITY_OPAQUE, cs); layer->setCompositeOp(COMPOSITE_OVER); if (!layer) { return KoFilter::CreationError; } Q3MemArray<Rgba> pixels(dataWidth); for (int y = 0; y < dataHeight; ++y) { file.setFrameBuffer(pixels.data() - dataWindow.min.x - (dataWindow.min.y + y) * dataWidth, 1, dataWidth); file.readPixels(dataWindow.min.y + y); KisHLineIterator it = layer->paintDevice()->createHLineIterator(dataWindow.min.x, dataWindow.min.y + y, dataWidth); Rgba *rgba = pixels.data(); while (!it.isDone()) { // XXX: For now unmultiply the alpha, though compositing will be faster if we // keep it premultiplied. half unmultipliedRed = rgba -> r; half unmultipliedGreen = rgba -> g; half unmultipliedBlue = rgba -> b; if (rgba -> a >= HALF_EPSILON) { unmultipliedRed /= rgba -> a; unmultipliedGreen /= rgba -> a; unmultipliedBlue /= rgba -> a; } setPixel(it.rawData(), unmultipliedRed, unmultipliedGreen, unmultipliedBlue, rgba -> a); ++it; ++rgba; } } image->addNode(layer.data(), image->rootLayer().data()); layer->setDirty(); doc -> setCurrentImage(image); doc -> undoAdapter() -> setUndo(true); doc -> setModified(false); image->unlock(); return KoFilter::OK; }
/** * This benchmark runs a series of huge strokes on a canvas with a * particular configuration of the swapper/pooler and history * management. After the test is done you can visualize the results * with the GNU Octave. Please use kis_low_memory_show_report.m file * for that. */ void KisLowMemoryBenchmark::benchmarkWideArea(const QString presetFileName, const QRectF &rect, qreal vstep, int numCycles, bool createTransaction, int hardLimitMiB, int softLimitMiB, int poolLimitMiB, int index) { KisPaintOpPresetSP preset = new KisPaintOpPreset(QString(FILES_DATA_DIR) + QDir::separator() + presetFileName); LOAD_PRESET_OR_RETURN(preset, presetFileName); /** * Initialize image and painter */ const KoColorSpace *colorSpace = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, HUGE_IMAGE_SIZE, HUGE_IMAGE_SIZE, colorSpace, "stroke sample image", true); KisLayerSP layer = new KisPaintLayer(image, "temporary for stroke sample", OPACITY_OPAQUE_U8, colorSpace); KisLayerSP layerExtra = new KisPaintLayer(image, "temporary for threading", OPACITY_OPAQUE_U8, colorSpace); image->addNode(layer, image->root()); image->addNode(layerExtra, image->root()); KisPainter *painter = new KisPainter(layer->paintDevice()); painter->setPaintColor(KoColor(Qt::black, colorSpace)); painter->setPaintOpPreset(preset, layer, image); /** * A simple adapter that will store all the transactions for us */ KisSurrogateUndoAdapter undoAdapter; /** * Reset configuration to the desired settings */ KisImageConfig config; qreal oldHardLimit = config.memoryHardLimitPercent(); qreal oldSoftLimit = config.memorySoftLimitPercent(); qreal oldPoolLimit = config.memoryPoolLimitPercent(); const qreal _MiB = 100.0 / KisImageConfig::totalRAM(); config.setMemoryHardLimitPercent(hardLimitMiB * _MiB); config.setMemorySoftLimitPercent(softLimitMiB * _MiB); config.setMemoryPoolLimitPercent(poolLimitMiB * _MiB); KisTileDataStore::instance()->testingRereadConfig(); /** * Create an empty the log file */ QString fileName; fileName = QString("log_%1_%2_%3_%4_%5.txt") .arg(createTransaction) .arg(hardLimitMiB) .arg(softLimitMiB) .arg(poolLimitMiB) .arg(index); QFile logFile(fileName); logFile.open(QFile::WriteOnly | QFile::Truncate); QTextStream logStream(&logFile); logStream.setFieldWidth(10); logStream.setFieldAlignment(QTextStream::AlignRight); /** * Start painting on the image */ QTime cycleTime; QTime lineTime; cycleTime.start(); lineTime.start(); qreal rectBottom = rect.y() + rect.height(); for (int i = 0; i < numCycles; i++) { cycleTime.restart(); QLineF line(rect.topLeft(), rect.topLeft() + QPointF(rect.width(), 0)); if (createTransaction) { painter->beginTransaction(); } KisDistanceInformation currentDistance; while(line.y1() < rectBottom) { lineTime.restart(); KisPaintInformation pi1(line.p1(), 0.0); KisPaintInformation pi2(line.p2(), 1.0); painter->paintLine(pi1, pi2, ¤tDistance); painter->device()->setDirty(painter->takeDirtyRegion()); logStream << "L 1" << i << lineTime.elapsed() << KisTileDataStore::instance()->numTilesInMemory() * 16 << KisTileDataStore::instance()->numTiles() * 16 << createTransaction << endl; line.translate(0, vstep); } painter->device()->setDirty(painter->takeDirtyRegion()); if (createTransaction) { painter->endTransaction(&undoAdapter); } // comment/uncomment to emulate user waiting after the stroke QTest::qSleep(1000); logStream << "C 2" << i << cycleTime.elapsed() << KisTileDataStore::instance()->numTilesInMemory() * 16 << KisTileDataStore::instance()->numTiles() * 16 << createTransaction << config.memoryHardLimitPercent() / _MiB << config.memorySoftLimitPercent() / _MiB << config.memoryPoolLimitPercent() / _MiB << endl; } config.setMemoryHardLimitPercent(oldHardLimit * _MiB); config.setMemorySoftLimitPercent(oldSoftLimit * _MiB); config.setMemoryPoolLimitPercent(oldPoolLimit * _MiB); delete painter; }
KisImportExportFilter::ConversionStatus KisXCFImport::loadFromDevice(QIODevice* device, KisDocument* doc) { dbgFile << "Start decoding file"; // Read the file into memory device->open(QIODevice::ReadOnly); QByteArray data = device->readAll(); xcf_file = (uint8_t*)data.data(); xcf_length = data.size(); device->close(); // Decode the data getBasicXcfInfo() ; initColormap(); dbgFile << XCF.version << "width = " << XCF.width << "height = " << XCF.height << "layers = " << XCF.numLayers; // Create the image KisImageSP image = new KisImage(doc->createUndoStore(), XCF.width, XCF.height, KoColorSpaceRegistry::instance()->rgb8(), "built image"); QVector<Layer> layers; uint maxDepth = 0; // Read layers for (int i = 0; i < XCF.numLayers; ++i) { Layer layer; xcfLayer& xcflayer = XCF.layers[i]; dbgFile << i << " name = " << xcflayer.name << " opacity = " << xcflayer.opacity << "group:" << xcflayer.isGroup << xcflayer.pathLength; dbgFile << ppVar(xcflayer.dim.width) << ppVar(xcflayer.dim.height) << ppVar(xcflayer.dim.tilesx) << ppVar(xcflayer.dim.tilesy) << ppVar(xcflayer.dim.ntiles) << ppVar(xcflayer.dim.c.t) << ppVar(xcflayer.dim.c.l) << ppVar(xcflayer.dim.c.r) << ppVar(xcflayer.dim.c.b); maxDepth = qMax(maxDepth, xcflayer.pathLength); bool isRgbA = false; // Select the color space const KoColorSpace* colorSpace = 0; switch (xcflayer.type) { case GIMP_INDEXED_IMAGE: case GIMP_INDEXEDA_IMAGE: case GIMP_RGB_IMAGE: case GIMP_RGBA_IMAGE: colorSpace = KoColorSpaceRegistry::instance()->rgb8(); isRgbA = true; break; case GIMP_GRAY_IMAGE: case GIMP_GRAYA_IMAGE: colorSpace = KoColorSpaceRegistry::instance()->colorSpace(GrayAColorModelID.id(), Integer8BitsColorDepthID.id(), ""); isRgbA = false; break; } // Create the layer KisLayerSP kisLayer; if (xcflayer.isGroup) { kisLayer = new KisGroupLayer(image, QString::fromUtf8(xcflayer.name), xcflayer.opacity); } else { kisLayer = new KisPaintLayer(image, QString::fromUtf8(xcflayer.name), xcflayer.opacity, colorSpace); } // Set some properties kisLayer->setCompositeOpId(layerModeG2K(xcflayer.mode)); kisLayer->setVisible(xcflayer.isVisible); kisLayer->disableAlphaChannel(xcflayer.mode != GIMP_NORMAL_MODE); layer.layer = kisLayer; layer.depth = xcflayer.pathLength; // Copy the data in the image initLayer(&xcflayer); int left = xcflayer.dim.c.l; int top = xcflayer.dim.c.t; if (!xcflayer.isGroup) { // Copy the data; for (unsigned int x = 0; x < xcflayer.dim.width; x += TILE_WIDTH) { for (unsigned int y = 0; y < xcflayer.dim.height; y += TILE_HEIGHT) { rect want; want.l = x + left; want.t = y + top; want.b = want.t + TILE_HEIGHT; want.r = want.l + TILE_WIDTH; Tile* tile = getMaskOrLayerTile(&xcflayer.dim, &xcflayer.pixels, want); KisHLineIteratorSP it = kisLayer->paintDevice()->createHLineIteratorNG(x, y, TILE_WIDTH); rgba* data = tile->pixels; for (int v = 0; v < TILE_HEIGHT; ++v) { if (isRgbA) { // RGB image do { KoBgrTraits<quint8>::setRed(it->rawData(), GET_RED(*data)); KoBgrTraits<quint8>::setGreen(it->rawData(), GET_GREEN(*data)); KoBgrTraits<quint8>::setBlue(it->rawData(), GET_BLUE(*data)); KoBgrTraits<quint8>::setOpacity(it->rawData(), quint8(GET_ALPHA(*data)), 1); ++data; } while (it->nextPixel()); } else { // Grayscale image do { it->rawData()[0] = GET_RED(*data); it->rawData()[1] = GET_ALPHA(*data); ++data; } while (it->nextPixel()); } it->nextRow(); } } } // Move the layer to its position kisLayer->paintDevice()->setX(left); kisLayer->paintDevice()->setY(top); } // Create the mask if (xcflayer.hasMask) { KisTransparencyMaskSP mask = new KisTransparencyMask(); layer.mask = mask; mask->initSelection(kisLayer); for (unsigned int x = 0; x < xcflayer.dim.width; x += TILE_WIDTH) { for (unsigned int y = 0; y < xcflayer.dim.height; y += TILE_HEIGHT) { rect want; want.l = x + left; want.t = y + top; want.b = want.t + TILE_HEIGHT; want.r = want.l + TILE_WIDTH; Tile* tile = getMaskOrLayerTile(&xcflayer.dim, &xcflayer.mask, want); KisHLineIteratorSP it = mask->paintDevice()->createHLineIteratorNG(x, y, TILE_WIDTH); rgba* data = tile->pixels; for (int v = 0; v < TILE_HEIGHT; ++v) { do { it->rawData()[0] = GET_ALPHA(*data); ++data; } while (it->nextPixel()); it->nextRow(); } } } mask->paintDevice()->setX(left); mask->paintDevice()->setY(top); image->addNode(mask, kisLayer); } dbgFile << xcflayer.pixels.tileptrs; layers.append(layer); } for (int i = 0; i <= maxDepth; ++i) { addLayers(layers, image, i); } doc->setCurrentImage(image); return KisImportExportFilter::OK; }
void KisSimpleUpdateQueueTest::testJobProcessing() { KisTestableUpdaterContext context(2); QRect imageRect(0,0,200,200); const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, imageRect.width(), imageRect.height(), cs, "merge test"); KisPaintLayerSP paintLayer = new KisPaintLayer(image, "test", OPACITY_OPAQUE_U8); image->lock(); image->addNode(paintLayer); image->unlock(); QRect dirtyRect1(0,0,50,100); QRect dirtyRect2(0,0,100,100); QRect dirtyRect3(50,0,50,100); QRect dirtyRect4(150,150,50,50); QVector<KisUpdateJobItem*> jobs; KisWalkersList walkersList; /** * Process the queue and look what has been added into * the updater context */ KisTestableSimpleUpdateQueue queue; queue.addJob(paintLayer, dirtyRect1, imageRect); queue.addJob(paintLayer, dirtyRect2, imageRect); queue.addJob(paintLayer, dirtyRect3, imageRect); queue.addJob(paintLayer, dirtyRect4, imageRect); queue.processQueue(context); jobs = context.getJobs(); QVERIFY(checkWalker(jobs[0]->walker(), dirtyRect2)); QVERIFY(checkWalker(jobs[1]->walker(), dirtyRect4)); QCOMPARE(jobs.size(), 2); walkersList = queue.getWalkersList(); QCOMPARE(walkersList.size(), 0); /** * Test blocking the process */ context.clear(); queue.blockProcessing(context); queue.addJob(paintLayer, dirtyRect1, imageRect); queue.addJob(paintLayer, dirtyRect2, imageRect); queue.addJob(paintLayer, dirtyRect3, imageRect); queue.addJob(paintLayer, dirtyRect4, imageRect); jobs = context.getJobs(); QCOMPARE(jobs[0]->walker(), KisBaseRectsWalkerSP(0)); QCOMPARE(jobs[1]->walker(), KisBaseRectsWalkerSP(0)); queue.startProcessing(context); jobs = context.getJobs(); QVERIFY(checkWalker(jobs[0]->walker(), dirtyRect2)); QVERIFY(checkWalker(jobs[1]->walker(), dirtyRect4)); }
void KisAsyncMergerTest::testFullRefreshWithClones() { const KoColorSpace *colorSpace = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, 128, 128, colorSpace, "clones test"); KisPaintDeviceSP device1 = new KisPaintDevice(colorSpace); device1->fill(image->bounds(), KoColor( Qt::white, colorSpace)); KisFilterSP filter = KisFilterRegistry::instance()->value("invert"); Q_ASSERT(filter); KisFilterConfiguration *configuration = filter->defaultConfiguration(0); Q_ASSERT(configuration); KisLayerSP paintLayer1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8, device1); KisFilterMaskSP invertMask1 = new KisFilterMask(); invertMask1->initSelection(0, paintLayer1); invertMask1->setFilter(configuration); KisLayerSP cloneLayer1 = new KisCloneLayer(paintLayer1, image, "clone_of_1", OPACITY_OPAQUE_U8); /** * The clone layer must have a projection to allow us * to read what it got from its source. Just shift it. */ cloneLayer1->setX(10); cloneLayer1->setY(10); image->addNode(cloneLayer1, image->rootLayer()); image->addNode(paintLayer1, image->rootLayer()); image->addNode(invertMask1, paintLayer1); QRect cropRect(image->bounds()); KisFullRefreshWalker walker(cropRect); KisAsyncMerger merger; walker.collectRects(image->rootLayer(), image->bounds()); merger.startMerge(walker); // Wait for additional jobs generated by the clone are finished image->waitForDone(); QRect filledRect(10, 10, image->width() - cloneLayer1->x(), image->height() - cloneLayer1->y()); const int pixelSize = device1->pixelSize(); const int numPixels = filledRect.width() * filledRect.height(); QByteArray bytes(numPixels * pixelSize, 13); cloneLayer1->projection()->readBytes((quint8*)bytes.data(), filledRect); KoColor desiredPixel(Qt::black, colorSpace); quint8 *srcPtr = (quint8*)bytes.data(); quint8 *dstPtr = desiredPixel.data(); for(int i = 0; i < numPixels; i++) { if(memcmp(srcPtr, dstPtr, pixelSize)) { qDebug() << "expected:" << dstPtr[0] << dstPtr[1] << dstPtr[2] << dstPtr[3]; qDebug() << "result: " << srcPtr[0] << srcPtr[1] << srcPtr[2] << srcPtr[3]; QFAIL("Failed to compare pixels"); } srcPtr += pixelSize; } }
void KisAsyncMergerTest::testMerger() { const KoColorSpace * colorSpace = KoColorSpaceRegistry::instance()->rgb8(); KisImageSP image = new KisImage(0, 640, 441, colorSpace, "merger test"); QImage sourceImage1(QString(FILES_DATA_DIR) + QDir::separator() + "hakonepa.png"); QImage sourceImage2(QString(FILES_DATA_DIR) + QDir::separator() + "inverted_hakonepa.png"); QImage referenceProjection(QString(FILES_DATA_DIR) + QDir::separator() + "merged_hakonepa.png"); KisPaintDeviceSP device1 = new KisPaintDevice(colorSpace); KisPaintDeviceSP device2 = new KisPaintDevice(colorSpace); device1->convertFromQImage(sourceImage1, 0, 0, 0); device2->convertFromQImage(sourceImage2, 0, 0, 0); KisFilterSP filter = KisFilterRegistry::instance()->value("blur"); Q_ASSERT(filter); KisFilterConfiguration *configuration = filter->defaultConfiguration(0); Q_ASSERT(configuration); KisLayerSP paintLayer1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8, device1); KisLayerSP paintLayer2 = new KisPaintLayer(image, "paint2", OPACITY_OPAQUE_U8, device2); KisLayerSP groupLayer = new KisGroupLayer(image, "group", 200/*OPACITY_OPAQUE*/); KisLayerSP blur1 = new KisAdjustmentLayer(image, "blur1", configuration, 0); image->addNode(paintLayer1, image->rootLayer()); image->addNode(groupLayer, image->rootLayer()); image->addNode(paintLayer2, groupLayer); image->addNode(blur1, groupLayer); QRect testRect1(0,0,100,441); QRect testRect2(100,0,400,441); QRect testRect3(500,0,140,441); QRect testRect4(580,381,40,40); QRect cropRect(image->bounds()); KisMergeWalker walker(cropRect); KisAsyncMerger merger; walker.collectRects(paintLayer2, testRect1); merger.startMerge(walker); walker.collectRects(paintLayer2, testRect2); merger.startMerge(walker); walker.collectRects(paintLayer2, testRect3); merger.startMerge(walker); walker.collectRects(paintLayer2, testRect4); merger.startMerge(walker); // Old style merging: has artefacts at x=100 and x=500 // And should be turned on inside KisLayer /* paintLayer2->setDirty(testRect1); QTest::qSleep(3000); paintLayer2->setDirty(testRect2); QTest::qSleep(3000); paintLayer2->setDirty(testRect3); QTest::qSleep(3000); paintLayer2->setDirty(testRect4); QTest::qSleep(3000); */ KisLayerSP rootLayer = image->rootLayer(); QVERIFY(rootLayer->exactBounds() == image->bounds()); QImage resultProjection = rootLayer->projection()->convertToQImage(0); resultProjection.save(QString(FILES_OUTPUT_DIR) + QDir::separator() + "actual_merge_result.png"); QPoint pt; QVERIFY(TestUtil::compareQImages(pt, resultProjection, referenceProjection, 1)); }