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;
}
Example #2
0
void KisUnsharpFilter::processImpl(KisPaintDeviceSP device,
                                   const QRect& applyRect,
                                   const KisFilterConfiguration* config,
                                   KoUpdater* progressUpdater
                                   ) const
{

    QPointer<KoUpdater> filterUpdater = 0;
    QPointer<KoUpdater> convolutionUpdater = 0;
    KoProgressUpdater* updater = 0;

    if (progressUpdater) {
        updater = new KoProgressUpdater(progressUpdater);
        updater->start(100, i18n("Unsharp Mask"));
        // Two sub-sub tasks that each go from 0 to 100.
        convolutionUpdater = updater->startSubtask();
        filterUpdater = updater->startSubtask();
    }

    if (!config) config = new KisFilterConfiguration(id().id(), 1);

    QVariant value;

    KisLodTransformScalar t(device);

    const qreal halfSize = t.scale(config->getProperty("halfSize", value) ? value.toDouble() : 1.0);
    const qreal amount = (config->getProperty("amount", value)) ? value.toDouble() : 25;
    const uint threshold = (config->getProperty("threshold", value)) ? value.toUInt() : 0;
    const uint lightnessOnly = (config->getProperty("lightnessOnly", value)) ? value.toBool() : true;

    QBitArray channelFlags = config->channelFlags();
    KisGaussianKernel::applyGaussian(device, applyRect,
                                     halfSize, halfSize,
                                     channelFlags,
                                     progressUpdater);

    if (progressUpdater && progressUpdater->interrupted()) {
        return;
    }

    qreal weights[2];
    qreal factor = 128;

    weights[0] = factor * (1. + amount);
    weights[1] = -factor * amount;

    if (lightnessOnly) {
        processLightnessOnly(device, applyRect, threshold, weights, factor, channelFlags);
    } else {
        processRaw(device, applyRect, threshold, weights, factor, channelFlags);
    }

    delete updater;

    if (progressUpdater) progressUpdater->setProgress(100);
}
void KisUnsharpFilter::process(KisPaintDeviceSP device,
                              const QRect& applyRect,
                              const KisFilterConfiguration* config,
                              KoUpdater* progressUpdater
                              ) const
{

    QPointer<KoUpdater> filterUpdater = 0;
    QPointer<KoUpdater> convolutionUpdater = 0;
    KoProgressUpdater* updater = 0;

    if (progressUpdater) {
        updater = new KoProgressUpdater(progressUpdater);
        updater->start();
        // Two sub-sub tasks that each go from 0 to 100.
        convolutionUpdater = updater->startSubtask();
        filterUpdater = updater->startSubtask();
    }

    if (!config) config = new KisFilterConfiguration(id().id(), 1);

    QVariant value;
    uint halfSize = (config->getProperty("halfSize", value)) ? value.toUInt() : 5;
    uint brushsize = 2 * halfSize + 1;
    double amount = (config->getProperty("amount", value)) ? value.toDouble() : 0.5;
    uint threshold = (config->getProperty("threshold", value)) ? value.toUInt() : 10;

    KisCircleMaskGenerator* kas = new KisCircleMaskGenerator(brushsize, 1, halfSize, halfSize, 2);

    KisConvolutionKernelSP kernel = KisConvolutionKernel::fromMaskGenerator(kas);

    KisPaintDeviceSP interm = new KisPaintDevice(*device);
    const KoColorSpace * cs = interm->colorSpace();
    KoConvolutionOp * convolutionOp = cs->convolutionOp();

    KisConvolutionPainter painter(interm);   // TODO no need for a full copy and then a transaction
    if (progressUpdater) {
        painter.setProgress(convolutionUpdater);
    }
    QBitArray channelFlags = config->channelFlags();
    if (channelFlags.isEmpty()) {
        channelFlags = cs->channelFlags();
    }
    painter.setChannelFlags(channelFlags);
    painter.beginTransaction("convolution step");
    painter.applyMatrix(kernel, interm, applyRect.topLeft(), applyRect.topLeft(), applyRect.size(), BORDER_REPEAT);
    painter.deleteTransaction();

    if (progressUpdater && progressUpdater->interrupted()) {
        return;
    }

    KisHLineIteratorSP dstIt = device->createHLineIteratorNG(applyRect.x(), applyRect.y(), applyRect.width());
    KisHLineConstIteratorSP intermIt = interm->createHLineConstIteratorNG(applyRect.x(), applyRect.y(), applyRect.width());

    int cdepth = cs -> pixelSize();
    quint8 *colors[2];
    colors[0] = new quint8[cdepth];
    colors[1] = new quint8[cdepth];

    int pixelsProcessed = 0;
    qreal weights[2];
    qreal factor = 128;

    // XXX: Added static cast to avoid warning
    weights[0] = static_cast<qreal>(factor * (1. + amount));
    weights[1] = static_cast<qreal>(-factor * amount);

    int steps = 100 / applyRect.width() * applyRect.height();

    for (int j = 0; j < applyRect.height(); j++) {
        do {
            quint8 diff = cs->difference(dstIt->oldRawData(), intermIt->oldRawData());
            if (diff > threshold) {
                memcpy(colors[0], dstIt->oldRawData(), cdepth);
                memcpy(colors[1], intermIt->oldRawData(), cdepth);
                convolutionOp->convolveColors(colors, weights, dstIt->rawData(), factor, 0, 2.0, channelFlags);
            } else {
                memcpy(dstIt->rawData(), dstIt->oldRawData(), cdepth);
            }
            ++pixelsProcessed;
            if (progressUpdater) filterUpdater->setProgress(steps * pixelsProcessed);
            intermIt->nextPixel();
        } while (dstIt->nextPixel());

        if (progressUpdater && progressUpdater->interrupted()) {
            return;
        }
        dstIt->nextRow();
        intermIt->nextRow();
    }
    delete colors[0];
    delete colors[1];
    delete updater;

    if (progressUpdater) progressUpdater->setProgress(100);
}