Exemplo n.º 1
0
QRect KisFilterMask::decorateRect(KisPaintDeviceSP &src,
                                  KisPaintDeviceSP &dst,
                                  const QRect & rc,
                                  PositionToFilthy maskPos) const
{
    Q_UNUSED(maskPos);

    KisSafeFilterConfigurationSP filterConfig = filter();

    Q_ASSERT(nodeProgressProxy());
    Q_ASSERT_X(src != dst, "KisFilterMask::decorateRect",
               "src must be != dst, because we cant create transactions "
               "during merge, as it breaks reentrancy");

    if (!filterConfig) {
        return QRect();
    }

    KisFilterSP filter =
        KisFilterRegistry::instance()->value(filterConfig->name());

    if (!filter) {
        warnKrita << "Could not retrieve filter \"" << filterConfig->name() << "\"";
        return QRect();
    }

    KIS_ASSERT_RECOVER_NOOP(this->busyProgressIndicator());
    this->busyProgressIndicator()->update();

    filter->process(src, dst, 0, rc, filterConfig.data(), 0);

    QRect r = filter->changedRect(rc, filterConfig.data(), dst->defaultBounds()->currentLevelOfDetail());
    return r;
}
Exemplo n.º 2
0
void KisBContrastBenchmark::benchmarkFilter()
{
    KisFilterSP filter = KisFilterRegistry::instance()->value("brightnesscontrast");
    KisFilterConfigurationSP  kfc = filter->defaultConfiguration(m_device);

    // Get the predefined configuration from a file
    QFile file(QString(FILES_DATA_DIR) + QDir::separator() + filter->id() + ".cfg");
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        file.open(QIODevice::WriteOnly | QIODevice::Text);
        QTextStream out(&file);
        out.setCodec("UTF-8");
        out << kfc->toXML();
    } else {
        QString s;
        QTextStream in(&file);
        in.setCodec("UTF-8");
        s = in.readAll();
        kfc->fromXML(s);
    }

    QSize size = KritaUtils::optimalPatchSize();
    QVector<QRect> rects = KritaUtils::splitRectIntoPatches(QRect(0, 0, GMP_IMAGE_WIDTH,GMP_IMAGE_HEIGHT), size);

    QBENCHMARK{
        Q_FOREACH (const QRect &rc, rects) {
            filter->process(m_device, rc, kfc);
        }
    }
Exemplo n.º 3
0
void KisFilterTest::testDifferentSrcAndDst()
{
    const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8();

    QImage qimage(QString(FILES_DATA_DIR) + QDir::separator() + "hakonepa.png");
    QImage inverted(QString(FILES_DATA_DIR) + QDir::separator() + "inverted_hakonepa.png");
    KisPaintDeviceSP src = new KisPaintDevice(cs);
    KisPaintDeviceSP dst = new KisPaintDevice(cs);
    KisSelectionSP sel = new KisSelection(new KisSelectionDefaultBounds(src));
    sel->getOrCreatePixelSelection()->invert(); // select everything
    sel->updateProjection();

    src->convertFromQImage(qimage, 0, 0, 0);

    KisFilterSP f = KisFilterRegistry::instance()->value("invert");
    Q_ASSERT(f);

    KisFilterConfiguration * kfc = f->defaultConfiguration(0);
    Q_ASSERT(kfc);

    f->process(src, dst, sel, QRect(QPoint(0,0), qimage.size()), kfc);

    QPoint errpoint;
    if (!TestUtil::compareQImages(errpoint, inverted, dst->convertToQImage(0, 0, 0, qimage.width(), qimage.height()))) {
        dst->convertToQImage(0, 0, 0, qimage.width(), qimage.height()).save("filtertest.png");
        QFAIL(QString("Failed to create inverted image, first different pixel: %1,%2 ").arg(errpoint.x()).arg(errpoint.y()).toLatin1());
    }
}
Exemplo n.º 4
0
KisNodeSP KisKraLoader::loadAdjustmentLayer(const KoXmlElement& element, KisImageWSP image,
        const QString& name, const KoColorSpace* cs, quint32 opacity)
{
    // XXX: do something with filterversion?
    Q_UNUSED(cs);
    QString attr;
    KisAdjustmentLayer* layer;
    QString filtername;

    if ((filtername = element.attribute(FILTER_NAME)).isNull()) {
        // XXX: Invalid adjustmentlayer! We should warn about it!
        warnFile << "No filter in adjustment layer";
        return 0;
    }

    KisFilterSP f = KisFilterRegistry::instance()->value(filtername);
    if (!f) {
        warnFile << "No filter for filtername" << filtername << "";
        return 0; // XXX: We don't have this filter. We should warn about it!
    }

    KisFilterConfiguration * kfc = f->defaultConfiguration(0);

    // We'll load the configuration and the selection later.
    layer = new KisAdjustmentLayer(image, name, kfc, 0);
    Q_CHECK_PTR(layer);

    layer->setOpacity(opacity);

    return layer;

}
Exemplo n.º 5
0
QRect KisFilterMask::needRect(const QRect& rect, PositionToFilthy pos) const
{
    Q_UNUSED(pos);

    /**
     * FIXME: This check of the emptiness should be done
     * on the higher/lower level
     */

    if(rect.isEmpty()) return rect;

    KisSafeFilterConfigurationSP filterConfig = filter();
    if (!filterConfig) return rect;

    KisNodeSP parent = this->parent();
    const int lod = parent && parent->projection() ?
        parent->projection()->defaultBounds()->currentLevelOfDetail() : 0;

    KisFilterSP filter = KisFilterRegistry::instance()->value(filterConfig->name());

    /**
     * If we need some additional pixels even outside of a selection
     * for accurate layer filtering, we'll get them!
     * And no KisMask::needRect will prevent us from doing this! ;)
     * That's why simply we do not call KisMask::needRect here :)
     */
    return filter->neededRect(rect, filterConfig.data(), lod);
}
bool applyFilter(const KoColorSpace * cs,  KisFilterSP f)
{

    QImage qimage(QString(FILES_DATA_DIR) + QDir::separator() + "lena.png");

    KisPaintDeviceSP dev = new KisPaintDevice(cs);
//    dev->fill(0, 0, 100, 100, dev->defaultPixel());
    dev->convertFromQImage(qimage, "", 0, 0);

    // Get the predefined configuration from a file
    KisFilterConfiguration * kfc = f->defaultConfiguration(dev);

    QFile file(QString(FILES_DATA_DIR) + QDir::separator() + f->id() + ".cfg");
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qDebug() << "creating new file for " << f->id();
        file.open(QIODevice::WriteOnly | QIODevice::Text);
        QTextStream out(&file);
        out << kfc->toXML();
    } else {
        QString s;
        QTextStream in(&file);
        s = in.readAll();
        kfc->fromXML(s);
    }
    qDebug() << f->id() << ", " << cs->id() << ", " << cs->profile()->name();// << kfc->toXML() << "\n";

    KisConstProcessingInformation src(dev,  QPoint(0, 0), 0);
    KisProcessingInformation dst(dev, QPoint(0, 0), 0);

    f->process(src, dst, qimage.size(), kfc);

    return true;

}
Exemplo n.º 7
0
KisNodeSP KisKraLoader::loadFilterMask(const KoXmlElement& element, KisNodeSP parent)
{
    Q_UNUSED(parent);
    QString attr;
    KisFilterMask* mask;
    QString filtername;

    // XXX: should we check the version?

    if ((filtername = element.attribute(FILTER_NAME)).isNull()) {
        // XXX: Invalid filter layer! We should warn about it!
        warnFile << "No filter in filter layer";
        return 0;
    }

    KisFilterSP f = KisFilterRegistry::instance()->value(filtername);
    if (!f) {
        warnFile << "No filter for filtername" << filtername << "";
        return 0; // XXX: We don't have this filter. We should warn about it!
    }

    KisFilterConfiguration * kfc = f->defaultConfiguration(0);

    // We'll load the configuration and the selection later.
    mask = new KisFilterMask();
    mask->setFilter(kfc);
    Q_CHECK_PTR(mask);

    return mask;
}
Exemplo n.º 8
0
/**
 * FIXME: try to cache filter pointer inside a Private block
 */
QRect KisFilterMask::changeRect(const QRect &rect, PositionToFilthy pos) const
{
    /**
     * FIXME: This check of the emptiness should be done
     * on the higher/lower level
     */
    if(rect.isEmpty()) return rect;

    QRect filteredRect = rect;

    KisSafeFilterConfigurationSP filterConfig = filter();
    if (filterConfig) {
        KisNodeSP parent = this->parent();
        const int lod = parent && parent->projection() ?
            parent->projection()->defaultBounds()->currentLevelOfDetail() : 0;

        KisFilterSP filter = KisFilterRegistry::instance()->value(filterConfig->name());
        filteredRect = filter->changedRect(rect, filterConfig.data(), lod);
    }

    /**
     * We can't paint outside a selection, that is why we call
     * KisMask::changeRect to crop actual change area in the end
     */
    filteredRect = KisMask::changeRect(filteredRect, pos);
    /**
     * FIXME: Think over this solution
     * Union of rects means that changeRect returns NOT the rect
     * changed by this very layer, but an accumulated rect changed
     * by all underlying layers. Just take into account and change
     * documentation accordingly
     */
    return rect | filteredRect;
}
Exemplo n.º 9
0
void KisDlgFilter::filterSelectionChanged()
{
    KisFilterSP filter = d->uiFilterDialog.filterSelection->currentFilter();
    setDialogTitle(filter);
    d->uiFilterDialog.pushButtonCreateMaskEffect->setEnabled(filter.isNull() ? false : filter->supportsAdjustmentLayers());
    updatePreview();
}
Exemplo n.º 10
0
bool KisCrashFilterTest::applyFilter(const KoColorSpace * cs,  KisFilterSP f)
{

    QImage qimage(QString(FILES_DATA_DIR) + QDir::separator() + "carrot.png");

    KisPaintDeviceSP dev = new KisPaintDevice(cs);
//    dev->fill(0, 0, 100, 100, dev->defaultPixel());
    dev->convertFromQImage(qimage, 0, 0, 0);

    // Get the predefined configuration from a file
    KisFilterConfigurationSP  kfc = f->defaultConfiguration(dev);

    QFile file(QString(FILES_DATA_DIR) + QDir::separator() + f->id() + ".cfg");
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        dbgKrita << "creating new file for " << f->id();
        file.open(QIODevice::WriteOnly | QIODevice::Text);
        QTextStream out(&file);
        out.setCodec("UTF-8");
        out << kfc->toXML();
    } else {
        QString s;
        QTextStream in(&file);
        in.setCodec("UTF-8");
        s = in.readAll();
        kfc->fromXML(s);
    }
    dbgKrita << f->id() << ", " << cs->id() << ", " << cs->profile()->name();// << kfc->toXML() << "\n";

    f->process(dev, QRect(QPoint(0,0), qimage.size()), kfc);

    return true;

}
Exemplo n.º 11
0
void KisFilterTest::testWithProgressUpdater()
{
    TestUtil::TestProgressBar * bar = new TestUtil::TestProgressBar();
    KoProgressUpdater* pu = new KoProgressUpdater(bar);
    KoUpdaterPtr updater = pu->startSubtask();

    const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8();

    QImage qimage(QString(FILES_DATA_DIR) + QDir::separator() + "hakonepa.png");
    QImage inverted(QString(FILES_DATA_DIR) + QDir::separator() + "inverted_hakonepa.png");
    KisPaintDeviceSP dev = new KisPaintDevice(cs);
    dev->convertFromQImage(qimage, 0, 0, 0);

    KisFilterSP f = KisFilterRegistry::instance()->value("invert");
    Q_ASSERT(f);

    KisFilterConfiguration * kfc = f->defaultConfiguration(0);
    Q_ASSERT(kfc);

    f->process(dev, QRect(QPoint(0,0), qimage.size()), kfc, updater);

    QPoint errpoint;
    if (!TestUtil::compareQImages(errpoint, inverted, dev->convertToQImage(0, 0, 0, qimage.width(), qimage.height()))) {
        dev->convertToQImage(0, 0, 0, qimage.width(), qimage.height()).save("filtertest.png");
        QFAIL(QString("Failed to create inverted image, first different pixel: %1,%2 ").arg(errpoint.x()).arg(errpoint.y()).toLatin1());
    }
    delete pu;
    delete bar;
}
Exemplo n.º 12
0
KisFilterOption::KisFilterOption()
    : KisPaintOpOption(KisPaintOpOption::FILTER, true)
{
    setObjectName("KisFilterOption");

    m_checkable = false;

    m_filterOptionWidget = new KisFilterOptionWidget();
    m_filterOptionWidget->hide();
    setConfigurationPage(m_filterOptionWidget);

    m_layout = new QGridLayout(m_filterOptionWidget->grpFilterOptions);

    // Check which filters support painting
    QList<QString> l = KisFilterRegistry::instance()->keys();
    QList<KoID> l2;
    QList<QString>::iterator it;
    for (it = l.begin(); it !=  l.end(); ++it) {
        KisFilterSP f = KisFilterRegistry::instance()->value((*it));
        if (f->supportsPainting()) {
            l2.push_back(KoID(*it, f->name()));
        }
    }
    m_filterOptionWidget->filtersList->setIDList(l2);
    connect(m_filterOptionWidget->filtersList, SIGNAL(activated(const KoID &)), SLOT(setCurrentFilter(const KoID &)));
    if (!l2.empty()) {
        setCurrentFilter(l2.first());
    }

    connect(m_filterOptionWidget->checkBoxSmudgeMode, SIGNAL(stateChanged(int)), this, SLOT(emitSettingChanged()));
}
Exemplo n.º 13
0
void KisLevelFilterBenchmark::benchmarkFilter()
{
    KisFilterSP filter = KisFilterRegistry::instance()->value("levels");
    //KisFilterConfigurationSP  kfc = filter->defaultConfiguration(m_device);

    KisColorTransformationConfiguration * kfc= new KisColorTransformationConfiguration("levels", 1);

    kfc->setProperty("blackvalue", 75);
    kfc->setProperty("whitevalue", 231);
    kfc->setProperty("gammavalue", 1.0);
    kfc->setProperty("outblackvalue", 0);
    kfc->setProperty("outwhitevalue", 255);
    // Get the predefined configuration from a file
    QFile file(QString(FILES_DATA_DIR) + QDir::separator() + filter->id() + ".cfg");
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        file.open(QIODevice::WriteOnly | QIODevice::Text);
        QTextStream out(&file);
        out.setCodec("UTF-8");
        out << kfc->toXML();
    } else {
        QString s;
        QTextStream in(&file);
        in.setCodec("UTF-8");
        s = in.readAll();
        kfc->fromXML(s);
    }

    QSize size = KritaUtils::optimalPatchSize();
    QVector<QRect> rects = KritaUtils::splitRectIntoPatches(QRect(0, 0, GMP_IMAGE_WIDTH,GMP_IMAGE_HEIGHT), size);

    QBENCHMARK{
        Q_FOREACH (const QRect &rc, rects) {
            filter->process(m_device, rc, kfc);
        }
    }
Exemplo n.º 14
0
void KisFilterMaskTest::testProjectionSelected()
{
    KisImageSP image;
    KisPaintLayerSP layer;

    const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8();

    QImage qimage(QString(FILES_DATA_DIR) + QDir::separator() + "hakonepa.png");
    QImage inverted(QString(FILES_DATA_DIR) + QDir::separator() + "inverted_hakonepa.png");

    KisFilterSP f = KisFilterRegistry::instance()->value("invert");
    Q_ASSERT(f);
    KisFilterConfiguration * kfc = f->defaultConfiguration(0);
    Q_ASSERT(kfc);

    KisFilterMaskSP mask = new KisFilterMask();
    mask->setFilter(kfc);
    mask->createNodeProgressProxy();

    KisPaintDeviceSP projection = new KisPaintDevice(cs);
    initImage(image, layer, projection, mask);
    projection->convertFromQImage(qimage, 0, 0, 0);

    mask->initSelection(layer);
    mask->select(qimage.rect(), MAX_SELECTED);
    mask->apply(projection, qimage.rect(), qimage.rect(), KisNode::N_FILTHY);
    QCOMPARE(mask->exactBounds(), QRect(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT));

    QPoint errpoint;
    if (!TestUtil::compareQImages(errpoint, inverted, projection->convertToQImage(0, 0, 0, qimage.width(), qimage.height()))) {
        projection->convertToQImage(0, 0, 0, qimage.width(), qimage.height()).save("filtermasktest2.png");
        QFAIL(QString("Failed to create inverted image, first different pixel: %1,%2 ").arg(errpoint.x()).arg(errpoint.y()).toLatin1());
    }

}
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);
    }
}
Exemplo n.º 16
0
void KisFilterTest::testOldDataApiAfterCopy()
{
    QRect updateRect(0,0,63,63);

    const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8();
    quint8 *whitePixel = new quint8[cs->pixelSize()];
    cs->fromQColor(Qt::white, whitePixel);
    cs->setOpacity(whitePixel, OPACITY_OPAQUE_U8, 1);

    KisPaintDeviceSP tmp = new KisPaintDevice(cs);

    KisPaintDeviceSP src = new KisPaintDevice(cs);
    src->fill(0, 0, 50, 50, whitePixel);

    /**
     * Make a full copy here to catch the bug.
     * Buggy memento manager would make a commit
     * that is not good.
     */
    KisPaintDeviceSP dst = new KisPaintDevice(*src);

    /**
     * This would write go to a new revision in a buggy
     * memento manager
     */
    dst->clear(updateRect);

    KisFilterSP f = KisFilterRegistry::instance()->value("invert");
    Q_ASSERT(f);
    KisFilterConfiguration * kfc = f->defaultConfiguration(0);
    Q_ASSERT(kfc);

    /**
     * This filter reads from oldRawData, so if we have some
     * weirdness with transactions it will read from old and non-cleared
     * version of the device and we will see a black square instead
     * of empty device in tmp
     */
    f->process(dst, tmp, 0, updateRect, kfc);

    /**
     * In theory, both devices: dst and tmp must be empty by now
     */
    KisPaintDeviceSP reference = new KisPaintDevice(cs);

    QImage refImage = reference->convertToQImage(0,0,0,63,63);
    QImage dstImage = dst->convertToQImage(0,0,0,63,63);
    QImage tmpImage = tmp->convertToQImage(0,0,0,63,63);

    QPoint pt;
    QVERIFY(TestUtil::compareQImages(pt, refImage, dstImage));
    QVERIFY(TestUtil::compareQImages(pt, refImage, tmpImage));

}
KisFilterConfiguration* KisFilterOpSettings::filterConfig() const
{
    if (hasProperty(FILTER_ID)) {
        KisFilterSP filter = KisFilterRegistry::instance()->get(getString(FILTER_ID));
        if (filter) {
            KisFilterConfiguration* configuration = filter->factoryConfiguration(0);
            configuration->fromXML(getString(FILTER_CONFIGURATION));
            return configuration;
        }
    }
    return 0;
}
Exemplo n.º 18
0
    KisStrokeStrategy* createStroke(bool indirectPainting,
                                    KisResourcesSnapshotSP resources,
                                    KisImageWSP image) {
        Q_UNUSED(image);
        Q_UNUSED(indirectPainting);

        KisFilterSP filter = KisFilterRegistry::instance()->value(m_filterName);
        Q_ASSERT(filter);
        KisFilterConfiguration *filterConfig = filter->defaultConfiguration(0);
        Q_ASSERT(filterConfig);

        return new KisFilterStrokeStrategy(filter, KisSafeFilterConfigurationSP(filterConfig), resources);
    }
void KisFilterOpSettings::fromXML(const QDomElement& e)
{
    KisPaintOpSettings::fromXML(e);
    QDomElement element = e.firstChildElement("filterconfig");
    if (hasProperty(FILTER_ID)) {
        KisFilterSP filter = KisFilterRegistry::instance()->get(getString(FILTER_ID));
        if (filter) {
            KisFilterConfiguration* configuration = filter->factoryConfiguration(0);
            configuration->fromXML(element);
            setProperty(FILTER_CONFIGURATION, configuration->toXML());
            delete configuration;
        }
    }
}
Exemplo n.º 20
0
void KisFilterDialog::setFilter(KisFilterSP f)
{
    Q_ASSERT(f);
    setWindowTitle(f->name());
    d->currentFilter = f;
    d->uiFilterDialog.filterSelection->setFilter(f);
    updatePreview();
}
Exemplo n.º 21
0
void KisDlgFilter::setFilter(KisFilterSP f)
{
    Q_ASSERT(f);
    setDialogTitle(f);
    d->uiFilterDialog.filterSelection->setFilter(f);
    d->uiFilterDialog.pushButtonCreateMaskEffect->setEnabled(f->supportsAdjustmentLayers());
    updatePreview();
}
Exemplo n.º 22
0
KisRecordedAction* KisRecordedFilterActionFactory::fromXML(const QDomElement& elt, const KisRecordedActionLoadContext*)
{
    QString name = elt.attribute("name");
    KisNodeQueryPath pathnode = KisNodeQueryPath::fromString(elt.attribute("path"));
    const KisFilterSP filter = KisFilterRegistry::instance()->get(elt.attribute("filter"));
    if (filter) {
        KisFilterConfiguration* config = filter->defaultConfiguration(0);
        QDomElement paramsElt = elt.firstChildElement("Params");
        if (config && !paramsElt.isNull()) {
            config->fromXML(paramsElt);
        }
        KisRecordedFilterAction* rfa = new KisRecordedFilterAction(name, pathnode, filter, config);
        delete config;
        return rfa;
    } else {
        return 0;
    }
}
Exemplo n.º 23
0
void KisFilterTest::testBlurFilterApplicationRect()
{
    QRect filterRect(10,10,40,40);
    QRect src1Rect(5,5,50,50);
    QRect src2Rect(0,0,60,60);

    const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8();
    quint8 *whitePixel = new quint8[cs->pixelSize()];
    cs->fromQColor(Qt::white, whitePixel);
    cs->setOpacity(whitePixel, OPACITY_OPAQUE_U8, 1);

    KisPaintDeviceSP src1 = new KisPaintDevice(cs);
    src1->fill(src1Rect.left(),src1Rect.top(),src1Rect.width(),src1Rect.height(), whitePixel);

    KisPaintDeviceSP src2 = new KisPaintDevice(cs);
    src2->fill(src2Rect.left(),src2Rect.top(),src2Rect.width(),src2Rect.height(), whitePixel);

    KisPaintDeviceSP dst1 = new KisPaintDevice(cs);
    KisPaintDeviceSP dst2 = new KisPaintDevice(cs);

    KisFilterSP f = KisFilterRegistry::instance()->value("blur");
    Q_ASSERT(f);
    KisFilterConfiguration * kfc = f->defaultConfiguration(0);
    Q_ASSERT(kfc);

    f->process(src1, dst1, 0, filterRect, kfc);
    f->process(src2, dst2, 0, filterRect, kfc);

    KisPaintDeviceSP reference = new KisPaintDevice(cs);
    reference->fill(filterRect.left(),filterRect.top(),filterRect.width(),filterRect.height(), whitePixel);

    QImage refImage = reference->convertToQImage(0,10,10,40,40);
    QImage dst1Image = dst1->convertToQImage(0,10,10,40,40);
    QImage dst2Image = dst2->convertToQImage(0,10,10,40,40);

    //dst1Image.save("DST1.png");
    //dst2Image.save("DST2.png");

    QPoint pt;
    QVERIFY(TestUtil::compareQImages(pt, refImage, dst1Image));
    QVERIFY(TestUtil::compareQImages(pt, refImage, dst2Image));
}
Exemplo n.º 24
0
void KisBlurBenchmark::benchmarkFilter()
{
    KisFilterSP filter = KisFilterRegistry::instance()->value("blur");
    KisFilterConfiguration * kfc = filter->defaultConfiguration(m_device);
    // Get the predefined configuration from a file
    QFile file(QString(FILES_DATA_DIR) + QDir::separator() + filter->id() + ".cfg");
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        file.open(QIODevice::WriteOnly | QIODevice::Text);
        QTextStream out(&file);
        out << kfc->toXML();
    } else {
        QString s;
        QTextStream in(&file);
        s = in.readAll();
        kfc->fromXML(s);
    }

    QBENCHMARK{
        filter->process(m_device, QRect(0, 0, GMP_IMAGE_WIDTH,GMP_IMAGE_HEIGHT), kfc);
    }
}
Exemplo n.º 25
0
bool KisColorSpaceConvertVisitor::visit(KisAdjustmentLayer * layer)
{
    // XXX: Make undoable!
    if (layer->filter()->name() == "perchannel") {
        // Per-channel filters need to be reset because of different number
        // of channels. This makes undo very tricky, but so be it.
        // XXX: Make this more generic for after 1.6, when we'll have many
        // channel-specific filters.
        KisFilterSP f = KisFilterRegistry::instance()->value("perchannel");
        layer->setFilter(f->defaultConfiguration(0));
    }

    KisLayerPropsCommand* propsCommand = new KisLayerPropsCommand(layer,
                                                                  layer->opacity(), layer->opacity(),
                                                                  layer->compositeOpId(), layer->compositeOpId(),
                                                                  layer->name(), layer->name(),
                                                                  m_emptyChannelFlags, m_emptyChannelFlags, false);
    m_image->undoAdapter()->addCommand(propsCommand);

    layer->resetCache();
    return true;
}
Exemplo n.º 26
0
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();
}
KisFilterStrokeStrategy::KisFilterStrokeStrategy(KisFilterSP filter,
                                                 KisSafeFilterConfigurationSP filterConfig,
                                                 KisResourcesSnapshotSP resources)
    : KisPainterBasedStrokeStrategy("FILTER_STROKE", filter->name(), resources,
                                    QVector<PainterInfo*>()),
      m_d(new Private())
{
    m_d->filter = filter;
    m_d->filterConfig = filterConfig;
    m_d->node = resources->currentNode();
    m_d->updatesFacade = resources->image().data();
    m_d->cancelSilently = false;
    m_d->secondaryTransaction = 0;

    enableJob(KisSimpleStrokeStrategy::JOB_DOSTROKE);
}
Exemplo n.º 28
0
void KisFilterOp::paintAt(const KisPaintInformation& info)
{
    if (!painter()) {
        return;
    }

    KisFilterSP filter = settings->filter();
    if (!filter) {
        return;
    }

    if (!source()) {
        return;
    }

    KisBrushSP brush = m_brush;;
    if (!brush) return;

    KisPaintInformation adjustedInfo = settings->m_optionsWidget->m_sizeOption->apply(info);
    if (! brush->canPaintFor(adjustedInfo))
        return;

    double pScale = KisPaintOp::scaleForPressure(adjustedInfo.pressure());   // TODO: why is there scale and pScale that seems to contains the same things ?
    QPointF hotSpot = brush->hotSpot(pScale, pScale);
    QPointF pt = info.pos() - hotSpot;


    // Split the coordinates into integer plus fractional parts. The integer
    // is where the dab will be positioned and the fractional part determines
    // the sub-pixel positioning.
    qint32 x;
    double xFraction;
    qint32 y;
    double yFraction;

    splitCoordinate(pt.x(), &x, &xFraction);
    splitCoordinate(pt.y(), &y, &yFraction);

    double scale = KisPaintOp::scaleForPressure(adjustedInfo.pressure());

    qint32 maskWidth = brush->maskWidth(scale, 0.0);
    qint32 maskHeight = brush->maskHeight(scale, 0.0);

    // Filter the paint device
    filter->process(KisConstProcessingInformation(source(), QPoint(x, y)),
                    KisProcessingInformation(m_tmpDevice, QPoint(0, 0)),
                    QSize(maskWidth, maskHeight),
                    settings->filterConfig(), 0);

    // Apply the mask on the paint device (filter before mask because edge pixels may be important)

    KisFixedPaintDeviceSP fixedDab = new KisFixedPaintDevice(m_tmpDevice->colorSpace());
    fixedDab->setRect(m_tmpDevice->extent());
    fixedDab->initialize();

    m_tmpDevice->readBytes(fixedDab->data(), fixedDab->bounds());
    brush->mask(fixedDab, scale, scale, 0.0, info, xFraction, yFraction);
    m_tmpDevice->writeBytes(fixedDab->data(), fixedDab->bounds());

    if (!settings->ignoreAlpha()) {
        KisHLineIteratorPixel itTmpDev = m_tmpDevice->createHLineIterator(0, 0, maskWidth);
        KisHLineIteratorPixel itSrc = source()->createHLineIterator(x, y, maskWidth);
        const KoColorSpace* cs = m_tmpDevice->colorSpace();
        for (int y = 0; y < maskHeight; ++y) {
            while (!itTmpDev.isDone()) {
                quint8 alphaTmpDev = cs->alpha(itTmpDev.rawData());
                quint8 alphaSrc = cs->alpha(itSrc.rawData());

                cs->setAlpha(itTmpDev.rawData(), qMin(alphaTmpDev, alphaSrc), 1);
                ++itTmpDev;
                ++itSrc;
            }
            itTmpDev.nextRow();
            itSrc.nextRow();
        }
    }

    // Blit the paint device onto the layer
    QRect dabRect = QRect(0, 0, maskWidth, maskHeight);
    QRect dstRect = QRect(x, y, dabRect.width(), dabRect.height());

    if (painter()->bounds().isValid()) {
        dstRect &= painter()->bounds();
    }
    if (dstRect.isNull() || dstRect.isEmpty() || !dstRect.isValid()) return;

    qint32 sx = dstRect.x() - x;
    qint32 sy = dstRect.y() - y;
    qint32 sw = dstRect.width();
    qint32 sh = dstRect.height();

    painter()->bitBlt(dstRect.x(), dstRect.y(), m_tmpDevice, sx, sy, sw, sh);

}
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));
}