Exemple #1
0
void KisSmallTilesFilter::processImpl(KisPaintDeviceSP device,
                                      const QRect& /*applyRect*/,
                                      const KisFilterConfiguration* config,
                                      KoUpdater* progressUpdater
                                      ) const
{
    Q_ASSERT(!device.isNull());

    //read the filter configuration values from the KisFilterConfiguration object
    quint32 numberOfTiles = config->getInt("numberOfTiles", 2);

    QRect srcRect = device->exactBounds();

    int w = static_cast<int>(srcRect.width() / numberOfTiles);
    int h = static_cast<int>(srcRect.height() / numberOfTiles);

    KisPaintDeviceSP tile = device->createThumbnailDevice(srcRect.width() / numberOfTiles, srcRect.height() / numberOfTiles);
    if (tile.isNull()) return;

    KisPainter gc(device);
    gc.setCompositeOp(COMPOSITE_COPY);

    if (progressUpdater) {
        progressUpdater->setRange(0, numberOfTiles);
    }

    for (uint y = 0; y < numberOfTiles; ++y) {
        for (uint x = 0; x < numberOfTiles; ++x) {
            gc.bitBlt(w * x, h * y, tile, 0, 0, w, h);
        }
        if (progressUpdater) progressUpdater->setValue(y);
    }
    gc.end();
}
void KisSmallTilesFilter::process(KisConstProcessingInformation srcInfo,
                                  KisProcessingInformation dstInfo,
                                  const QSize& size,
                                  const KisFilterConfiguration* config,
                                  KoUpdater* progressUpdater
                                 ) const
{
    const KisPaintDeviceSP src = srcInfo.paintDevice();
    KisPaintDeviceSP dst = dstInfo.paintDevice();
    QPoint dstTopLeft = dstInfo.topLeft();
    QPoint srcTopLeft = srcInfo.topLeft();
    Q_ASSERT(!src.isNull());
    Q_ASSERT(!dst.isNull());

    //read the filter configuration values from the KisFilterConfiguration object
    quint32 numberOfTiles = config->getInt("numberOfTiles", 2);

    QRect srcRect = src->exactBounds();

    int w = static_cast<int>(srcRect.width() / numberOfTiles);
    int h = static_cast<int>(srcRect.height() / numberOfTiles);

    KisPaintDeviceSP tile = KisPaintDeviceSP(0);
    if (srcInfo.selection()) {
        KisPaintDeviceSP tmp = new KisPaintDevice(src->colorSpace());
        KisPainter gc(tmp);
        gc.setCompositeOp(COMPOSITE_COPY);
        gc.bitBlt(0, 0, src, srcTopLeft.x(), srcTopLeft.y(), size.width(), size.height());
        tile = tmp->createThumbnailDevice(srcRect.width() / numberOfTiles, srcRect.height() / numberOfTiles);
    } else {
        tile = src->createThumbnailDevice(srcRect.width() / numberOfTiles, srcRect.height() / numberOfTiles);
    }
    if (tile.isNull()) return;

    KisPainter gc(dst);
    gc.setCompositeOp(COMPOSITE_COPY);

    if (progressUpdater) {
        progressUpdater->setRange(0, numberOfTiles);
    }

    if (srcInfo.selection()) {
        gc.setSelection(srcInfo.selection());
    }

    for (uint y = 0; y < numberOfTiles; ++y) {
        for (uint x = 0; x < numberOfTiles; ++x) {
            gc.bitBlt(w * x, h * y, tile, 0, 0, w, h);
        }
        if (progressUpdater) progressUpdater->setValue(y);
    }
    gc.end();
}
void ShivaGenerator::generate(KisProcessingInformation dstInfo,
                              const QSize& size,
                              const KisFilterConfiguration* config,
                              KoUpdater* progressUpdater) const
{
    Q_UNUSED(progressUpdater);
    KisPaintDeviceSP dst = dstInfo.paintDevice();
    QPoint dstTopLeft = dstInfo.topLeft();

    UpdaterProgressReport* report = 0;
    if (progressUpdater) {
        progressUpdater->setRange(0, size.height());
        report = new UpdaterProgressReport(progressUpdater);
    }
    
    Q_ASSERT(!dst.isNull());
//     Q_ASSERT(config);
    // TODO implement the generating of pixel
    OpenShiva::Kernel kernel;
    kernel.setSource(*m_source);

    if (config) {
        QMap<QString, QVariant> map = config->getProperties();
        for (QMap<QString, QVariant>::iterator it = map.begin(); it != map.end(); ++it) {
            const GTLCore::Metadata::Entry* entry = kernel.metadata()->parameter(it.key().toAscii().data());
            if (entry && entry->asParameterEntry()) {
#if OPENSHIVA_12
                GTLCore::Value val = qvariantToValue(it.value(), entry->asParameterEntry()->valueType());
#else
                GTLCore::Value val = qvariantToValue(it.value(), entry->asParameterEntry()->type());
#endif
                if(val.isValid())
                {
                    kernel.setParameter(it.key().toAscii().data(), val);
                }
            }
        }
    }
    {
        QMutexLocker l(shivaMutex);
        kernel.compile();
    }
    if (kernel.isCompiled()) {
        PaintDeviceImage pdi(dst);
#if OPENSHIVA_12
        std::list< GTLCore::AbstractImage* > inputs;
        GTLCore::Region region(dstTopLeft.x(), dstTopLeft.y() , size.width(), size.height());
        kernel.evaluatePixeles(region, inputs, &pdi, report );
#else
        std::list< const GTLCore::AbstractImage* > inputs;
        GTLCore::RegionI region(dstTopLeft.x(), dstTopLeft.y() , size.width(), size.height());
        kernel.evaluatePixels(region, inputs, &pdi, report );
#endif
    }
#if OPENSHIVA_13_OR_MORE
    else {
        dbgPlugins << "Error: " << kernel.compilationMessages().toString().c_str();
    }
#endif
}
Exemple #4
0
void KoPatternGenerator::generate(KisProcessingInformation dstInfo,
                                 const QSize& size,
                                 const KisFilterConfiguration* config,
                                 KoUpdater* progressUpdater) const
{
    KisPaintDeviceSP dst = dstInfo.paintDevice();

    Q_ASSERT(!dst.isNull());
    Q_ASSERT(config);

    if (!config) return;
    QString patternName = config->getString("pattern", "Grid01.pat");
    KoResourceServer<KoPattern> *rserver = KoResourceServerProvider::instance()->patternServer();
    KoPattern *pattern = rserver->resourceByName(patternName);

//    KoColor c = config->getColor("color");

    KisFillPainter gc(dst);
    gc.setPattern(pattern);
//    gc.setPaintColor(c);
    gc.setProgress(progressUpdater);
    gc.setChannelFlags(config->channelFlags());
    gc.setOpacity(OPACITY_OPAQUE_U8);
    gc.setSelection(dstInfo.selection());
    gc.setWidth(size.width());
    gc.setHeight(size.height());
    gc.setFillStyle(KisFillPainter::FillStylePattern);
    gc.fillRect(QRect(dstInfo.topLeft(), size), pattern);
    gc.end();

}
Exemple #5
0
void KisFilterRandomPick::processImpl(KisPaintDeviceSP device,
                                      const QRect& applyRect,
                                      const KisFilterConfigurationSP config,
                                      KoUpdater* progressUpdater
                                      ) const
{
    Q_UNUSED(config);
    Q_ASSERT(!device.isNull());

    if (progressUpdater) {
        progressUpdater->setRange(0, applyRect.width() * applyRect.height());
    }
    int count = 0;

    const KoColorSpace * cs = device->colorSpace();

    QVariant value;
    int level = (config && config->getProperty("level", value)) ? value.toInt() : 50;
    int opacity = (config && config->getProperty("opacity", value)) ? value.toInt() : 100;
    double windowsize = (config && config->getProperty("windowsize", value)) ? value.toDouble() : 2.5;

    int seedThreshold = rand();
    int seedH = rand();
    int seedV = rand();

    if (config) {
        seedThreshold = config->getInt("seedThreshold", seedThreshold);
        seedH = config->getInt("seedH", seedH);
        seedV = config->getInt("seedV", seedV);
    }
    KisRandomGenerator randT(seedThreshold);
    KisRandomGenerator randH(seedH);
    KisRandomGenerator randV(seedV);

    KisSequentialIterator dstIt(device, applyRect);
    KisRandomConstAccessorSP srcRA = device->createRandomConstAccessorNG(0, 0);

    double threshold = (100 - level) / 100.0;

    qint16 weights[2];
    weights[0] = (255 * opacity) / 100; weights[1] = 255 - weights[0];
    const quint8* pixels[2];
    KoMixColorsOp * mixOp = cs->mixColorsOp();
    do{
        if (randT.doubleRandomAt(dstIt.x(), dstIt.y()) > threshold) {
            int x = static_cast<int>(dstIt.x() + windowsize * (randH.doubleRandomAt(dstIt.x(), dstIt.y()) - 0.5));
            int y = static_cast<int>(dstIt.y() +  windowsize * (randV.doubleRandomAt(dstIt.x(), dstIt.y()) -0.5));
            srcRA->moveTo(x, y);
            pixels[0] = srcRA->oldRawData();
            pixels[1] = dstIt.oldRawData();
            mixOp->mixColors(pixels, weights, 2, dstIt.rawData());
        }
        if (progressUpdater) progressUpdater->setValue(++count);
    } while(dstIt.nextPixel());

}
// gmic assumes float rgba in 0.0 - 255.0, thus default value
void KisGmicSimpleConvertor::convertToGmicImage(KisPaintDeviceSP dev, gmic_image<float>& gmicImage, QRect rc)
{
    Q_ASSERT(!dev.isNull());
    Q_ASSERT(gmicImage._spectrum == 4); // rgba

    if (rc.isEmpty())
    {
        rc = QRect(0,0,gmicImage._width, gmicImage._height);
    }

    const KoColorSpace *rgbaFloat32bitcolorSpace = KoColorSpaceRegistry::instance()->colorSpace(RGBAColorModelID.id(),
                                                                                                Float32BitsColorDepthID.id(),
                                                                                                KoColorSpaceRegistry::instance()->rgb8()->profile());
    Q_CHECK_PTR(rgbaFloat32bitcolorSpace);

    int greenOffset = gmicImage._width * gmicImage._height;
    int blueOffset = greenOffset * 2;
    int alphaOffset = greenOffset * 3;

    KoColorConversionTransformation::Intent renderingIntent = KoColorConversionTransformation::internalRenderingIntent();
    KoColorConversionTransformation::ConversionFlags conversionFlags = KoColorConversionTransformation::internalConversionFlags();

    const KoColorSpace * colorSpace = dev->colorSpace();
    KisRandomConstAccessorSP it = dev->createRandomConstAccessorNG(0,0);

    int optimalBufferSize = 64; // most common numContiguousColumns, tile size?
    quint8 * floatRGBApixel = new quint8[rgbaFloat32bitcolorSpace->pixelSize() * optimalBufferSize];
    quint32 pixelSize = rgbaFloat32bitcolorSpace->pixelSize();
    int pos = 0;
    for (int y = 0; y < rc.height(); y++)
    {
        int x = 0;
        while (x < rc.width())
        {
            it->moveTo(x, y);
            qint32 numContiguousColumns = qMin(it->numContiguousColumns(x), optimalBufferSize);
            numContiguousColumns = qMin(numContiguousColumns, rc.width() - x);

            colorSpace->convertPixelsTo(it->rawDataConst(), floatRGBApixel, rgbaFloat32bitcolorSpace, numContiguousColumns, renderingIntent, conversionFlags);

            pos = y * gmicImage._width + x;
            for (qint32 bx = 0; bx < numContiguousColumns; bx++)
            {
                memcpy(gmicImage._data + pos                  ,floatRGBApixel + bx * pixelSize   , 4);
                memcpy(gmicImage._data + pos + greenOffset    ,floatRGBApixel + bx * pixelSize + 4, 4);
                memcpy(gmicImage._data + pos + blueOffset     ,floatRGBApixel + bx * pixelSize + 8, 4);
                memcpy(gmicImage._data + pos + alphaOffset    ,floatRGBApixel + bx * pixelSize + 12, 4);
                pos++;
            }

            x += numContiguousColumns;
        }
    }
    delete [] floatRGBApixel;
}
Exemple #7
0
void ShivaFilter::processImpl(KisPaintDeviceSP dev,
                              const QRect& size,
                              const KisFilterConfiguration* config,
                              KoUpdater* progressUpdater
                              ) const
{
    Q_UNUSED(progressUpdater);
    QPoint dstTopLeft = size.topLeft();

    UpdaterProgressReport* report = 0;
    if (progressUpdater) {
        progressUpdater->setRange(0, size.height());
        report = new UpdaterProgressReport(progressUpdater);
    }
    
    Q_ASSERT(!dev.isNull());
//     Q_ASSERT(config);
    // TODO support for selection
    OpenShiva::Kernel kernel;
    kernel.setSource(*m_source);
    if (config) {
        QMap<QString, QVariant> map = config->getProperties();
        for (QMap<QString, QVariant>::iterator it = map.begin(); it != map.end(); ++it) {
            dbgPlugins << it.key() << " " << it.value();
            const GTLCore::Metadata::Entry* entry = kernel.metadata()->parameter(it.key().toLatin1().constData());
            if (entry && entry->asParameterEntry()) {
                GTLCore::Value val = qvariantToValue(it.value(), entry->asParameterEntry()->type());
                if(val.isValid())
                {
                    kernel.setParameter(it.key().toLatin1().constData(), val);
                }
            }
        }
    }
    
    kernel.setParameter(OpenShiva::Kernel::IMAGE_WIDTH, float(dev->defaultBounds()->bounds().width()));
    kernel.setParameter(OpenShiva::Kernel::IMAGE_HEIGHT, float(dev->defaultBounds()->bounds().height()));
    
    KisGtlLocker gtlLocker;
    {
        dbgPlugins << "Compile: " << m_source->name().c_str();
        QMutexLocker l(shivaMutex);
        kernel.compile();
    }
    if (kernel.isCompiled()) {
        ConstPaintDeviceImage pdisrc(dev);
        PaintDeviceImage pdi(dev);
        std::list< const GTLCore::AbstractImage* > inputs;
        GTLCore::RegionI region(dstTopLeft.x(), dstTopLeft.y() , size.width(), size.height());
        inputs.push_back(&pdisrc);
        dbgPlugins << "Run: " << m_source->name().c_str() << " " <<  dstTopLeft << " " << size;
        kernel.evaluatePixels(region, inputs, &pdi, report );

        }
}
void KisOilPaintFilter::processImpl(KisPaintDeviceSP device,
                                    const QRect& applyRect,
                                    const KisFilterConfiguration* config,
                                    KoUpdater* progressUpdater
                                    ) const
{
    QPoint srcTopLeft = applyRect.topLeft();
    Q_ASSERT(!device.isNull());

    qint32 width = applyRect.width();
    qint32 height = applyRect.height();

    //read the filter configuration values from the KisFilterConfiguration object
    quint32 brushSize = config ? config->getInt("brushSize", 1) : 1;
    quint32 smooth = config ? config->getInt("smooth", 30) : 30;

    OilPaint(device, device, srcTopLeft, applyRect.topLeft(), width, height, brushSize, smooth, progressUpdater);
}
void KisGmicSimpleConvertor::convertFromGmicImage(gmic_image<float>& gmicImage, KisPaintDeviceSP dst, float gmicMaxChannelValue)
{
    Q_ASSERT(!dst.isNull());
    const KoColorSpace *rgbaFloat32bitcolorSpace = KoColorSpaceRegistry::instance()->colorSpace(RGBAColorModelID.id(),
                                                                                                Float32BitsColorDepthID.id(),
                                                                                                KoColorSpaceRegistry::instance()->rgb8()->profile());
    const KoColorSpace *dstColorSpace = dst->colorSpace();
    if (dstColorSpace == 0)
    {
        dstColorSpace = rgbaFloat32bitcolorSpace;
    }

    KisPaintDeviceSP dev = dst;
    int greenOffset = gmicImage._width * gmicImage._height;
    int blueOffset = greenOffset * 2;
    int alphaOffset = greenOffset * 3;
    QRect rc(0,0,gmicImage._width, gmicImage._height);

    KisRandomAccessorSP it = dev->createRandomAccessorNG(0,0);
    int pos;
    float r,g,b,a;

    int optimalBufferSize = 64; // most common numContiguousColumns, tile size?
    quint8 * floatRGBApixel = new quint8[rgbaFloat32bitcolorSpace->pixelSize() * optimalBufferSize];
    quint32 pixelSize = rgbaFloat32bitcolorSpace->pixelSize();

    KoColorConversionTransformation::Intent renderingIntent = KoColorConversionTransformation::internalRenderingIntent();
    KoColorConversionTransformation::ConversionFlags conversionFlags = KoColorConversionTransformation::internalConversionFlags();

    // Krita needs rgba in 0.0...1.0
    float multiplied = KoColorSpaceMathsTraits<float>::unitValue / gmicMaxChannelValue;

    switch (gmicImage._spectrum)
    {
        case 1:
        {
            // convert grayscale to rgba
            for (int y = 0; y < rc.height(); y++)
            {
                int x = 0;
                while (x < rc.width())
                {
                    it->moveTo(x, y);
                    qint32 numContiguousColumns = qMin(it->numContiguousColumns(x), optimalBufferSize);
                    numContiguousColumns = qMin(numContiguousColumns, rc.width() - x);

                    pos = y * gmicImage._width + x;
                    for (qint32 bx = 0; bx < numContiguousColumns; bx++)
                    {
                            r = g = b = gmicImage._data[pos] * multiplied;
                            a = KoColorSpaceMathsTraits<float>::unitValue;

                            memcpy(floatRGBApixel + bx * pixelSize,      &r,4);
                            memcpy(floatRGBApixel + bx * pixelSize + 4,  &g,4);
                            memcpy(floatRGBApixel + bx * pixelSize + 8,  &b,4);
                            memcpy(floatRGBApixel + bx * pixelSize + 12, &a,4);
                            pos++;
                    }
                    rgbaFloat32bitcolorSpace->convertPixelsTo(floatRGBApixel, it->rawData(), dstColorSpace, numContiguousColumns,renderingIntent, conversionFlags);
                    x += numContiguousColumns;
                }
            }
            break;
        }
        case 2:
        {
            // convert grayscale alpha to rgba
            for (int y = 0; y < rc.height(); y++)
            {
                int x = 0;
                while (x < rc.width())
                {
                    it->moveTo(x, y);
                    qint32 numContiguousColumns = qMin(it->numContiguousColumns(x), optimalBufferSize);
                    numContiguousColumns = qMin(numContiguousColumns, rc.width() - x);

                    pos = y * gmicImage._width + x;
                    for (qint32 bx = 0; bx < numContiguousColumns; bx++)
                    {
                            r = g = b = gmicImage._data[pos] * multiplied;
                            a = gmicImage._data[pos + greenOffset] * multiplied;

                            memcpy(floatRGBApixel + bx * pixelSize,      &r,4);
                            memcpy(floatRGBApixel + bx * pixelSize + 4,  &g,4);
                            memcpy(floatRGBApixel + bx * pixelSize + 8,  &b,4);
                            memcpy(floatRGBApixel + bx * pixelSize + 12, &a,4);
                            pos++;
                    }
                    rgbaFloat32bitcolorSpace->convertPixelsTo(floatRGBApixel, it->rawData(), dstColorSpace, numContiguousColumns,renderingIntent, conversionFlags);
                    x += numContiguousColumns;
                }
            }
            break;
        }
        case 3:
        {
            // convert rgb -> rgba
            for (int y = 0; y < rc.height(); y++)
            {
                int x = 0;
                while (x < rc.width())
                {
                    it->moveTo(x, y);
                    qint32 numContiguousColumns = qMin(it->numContiguousColumns(x), optimalBufferSize);
                    numContiguousColumns = qMin(numContiguousColumns, rc.width() - x);

                    pos = y * gmicImage._width + x;
                    for (qint32 bx = 0; bx < numContiguousColumns; bx++)
                    {
                            r = gmicImage._data[pos] * multiplied;
                            g = gmicImage._data[pos + greenOffset] * multiplied;
                            b = gmicImage._data[pos + blueOffset ] * multiplied;
                            a = gmicMaxChannelValue * multiplied;

                            memcpy(floatRGBApixel + bx * pixelSize,      &r,4);
                            memcpy(floatRGBApixel + bx * pixelSize + 4,  &g,4);
                            memcpy(floatRGBApixel + bx * pixelSize + 8,  &b,4);
                            memcpy(floatRGBApixel + bx * pixelSize + 12, &a,4);
                            pos++;
                    }
                    rgbaFloat32bitcolorSpace->convertPixelsTo(floatRGBApixel, it->rawData(), dstColorSpace, numContiguousColumns,renderingIntent, conversionFlags);
                    x += numContiguousColumns;
                }
            }
            break;
        }
        case 4:
        {
            for (int y = 0; y < rc.height(); y++)
            {
                int x = 0;
                while (x < rc.width())
                {
                    it->moveTo(x, y);
                    qint32 numContiguousColumns = qMin(it->numContiguousColumns(x), optimalBufferSize);
                    numContiguousColumns = qMin(numContiguousColumns, rc.width() - x);

                    pos = y * gmicImage._width + x;
                    for (qint32 bx = 0; bx < numContiguousColumns; bx++)
                    {
                            r = gmicImage._data[pos] * multiplied;
                            g = gmicImage._data[pos + greenOffset] * multiplied;
                            b = gmicImage._data[pos + blueOffset ] * multiplied;
                            a = gmicImage._data[pos + alphaOffset] * multiplied;

                            memcpy(floatRGBApixel + bx * pixelSize,      &r,4);
                            memcpy(floatRGBApixel + bx * pixelSize + 4,  &g,4);
                            memcpy(floatRGBApixel + bx * pixelSize + 8,  &b,4);
                            memcpy(floatRGBApixel + bx * pixelSize + 12, &a,4);
                            pos++;
                    }
                    rgbaFloat32bitcolorSpace->convertPixelsTo(floatRGBApixel, it->rawData(), dstColorSpace, numContiguousColumns,renderingIntent, conversionFlags);
                    x += numContiguousColumns;
                }
            }
            break;
        }

        default:
        {
            dbgPlugins << "Unsupported gmic output format : " <<  gmicImage._width << gmicImage._height << gmicImage._depth << gmicImage._spectrum;
        }
    }
}
Exemple #10
0
void KisFilterNoise::processImpl(KisPaintDeviceSP device,
                                 const QRect& applyRect,
                                 const KisFilterConfiguration* config,
                                 KoUpdater* progressUpdater
                                ) const
{
    Q_ASSERT(!device.isNull());

    if (progressUpdater) {
        progressUpdater->setRange(0, applyRect.width() * applyRect.height());
    }
    int count = 0;

    const KoColorSpace * cs = device->colorSpace();

    QVariant value;
    int level = (config && config->getProperty("level", value)) ? value.toInt() : 50;
    int opacity = (config && config->getProperty("opacity", value)) ? value.toInt() : 100;

    KisSequentialIterator it(device, applyRect);

    quint8* interm = new quint8[cs->pixelSize()];
    double threshold = (100.0 - level) * 0.01;

    qint16 weights[2];
    weights[0] = (255 * opacity) / 100;
    weights[1] = 255 - weights[0];

    const quint8* pixels[2];
    pixels[0] = interm;

    KoMixColorsOp * mixOp = cs->mixColorsOp();

    int seedThreshold = rand();
    int seedRed = rand();
    int seedGreen = rand();
    int seedBlue = rand();

    if (config) {
        seedThreshold = config->getInt("seedThreshold", seedThreshold);
        seedRed = config->getInt("seedRed", seedRed);
        seedGreen = config->getInt("seedGreen", seedGreen);
        seedBlue = config->getInt("seedBlue", seedBlue);
    }

    KisRandomGenerator randt(seedThreshold);
    KisRandomGenerator randr(seedRed);
    KisRandomGenerator randg(seedGreen);
    KisRandomGenerator randb(seedBlue);

    do {
        if (randt.doubleRandomAt(it.x(), it.y()) > threshold) {
            // XXX: Added static_cast to get rid of warnings
            QColor c = qRgb(static_cast<int>((double)randr.doubleRandomAt(it.x(), it.y()) * 255),
                            static_cast<int>((double)randg.doubleRandomAt(it.x(), it.y()) * 255),
                            static_cast<int>((double)randb.doubleRandomAt(it.x(), it.y()) * 255));
            cs->fromQColor(c, interm, 0);
            pixels[1] = it.oldRawData();
            mixOp->mixColors(pixels, weights, 2, it.rawData());
        }
        if (progressUpdater) progressUpdater->setValue(++count);
    } while (it.nextPixel() && !(progressUpdater && progressUpdater->interrupted()));

    delete [] interm;
}
void KisRainDropsFilter::process(KisConstProcessingInformation srcInfo,
                                 KisProcessingInformation dstInfo,
                                 const QSize& size,
                                 const KisFilterConfiguration* config,
                                 KoUpdater* progressUpdater
                                ) const
{

    const KisPaintDeviceSP src = srcInfo.paintDevice();
    KisPaintDeviceSP dst = dstInfo.paintDevice();
    QPoint dstTopLeft = dstInfo.topLeft();
    QPoint srcTopLeft = srcInfo.topLeft();
    Q_UNUSED(config);
    Q_ASSERT(!src.isNull());
    Q_ASSERT(!dst.isNull());

    //read the filter configuration values from the KisFilterConfiguration object
    quint32 DropSize = config->getInt("dropSize", 80);
    quint32 number = config->getInt("number", 80);
    quint32 fishEyes = config->getInt("fishEyes", 30);

    if (progressUpdater) {
        progressUpdater->setRange(0, size.width() * size.height());
    }
    int count = 0;

    if (fishEyes <= 0) fishEyes = 1;

    if (fishEyes > 100) fishEyes = 100;

    int Width = size.width();
    int Height = size.height();

    bool** BoolMatrix = CreateBoolArray(Width, Height);

    int       i, j, k, l, m, n;                 // loop variables
    int       Bright;                           // Bright value for shadows and highlights
    int       x, y;                             // center coordinates
    int       Counter = 0;                      // Counter (duh !)
    int       NewSize;                          // Size of current raindrop
    int       halfSize;                         // Half of the current raindrop
    int       Radius;                           // Maximum radius for raindrop
    int       BlurRadius;                       // Blur Radius
    int       BlurPixels;

    double    r, a;                             // polar coordinates
    double    OldRadius;                        // Radius before processing
    double    NewfishEyes = (double)fishEyes * 0.01;  // FishEye fishEyesicients
    double    s;
    double    R, G, B;

    bool      FindAnother = false;              // To search for good coordinates

    const KoColorSpace * cs = src->colorSpace();


    // XXX: move the seed to the config, so the filter can be used as
    // and adjustment filter (boud).
    // And use a thread-safe random number generator
    QDateTime dt = QDateTime::currentDateTime();
    QDateTime Y2000(QDate(2000, 1, 1), QTime(0, 0, 0));

    srand((uint) dt.secsTo(Y2000));

    // Init booleen Matrix.

    for (i = 0 ; (i < Width) && !(progressUpdater && progressUpdater->interrupted()) ; ++i) {
        for (j = 0 ; (j < Height) && !(progressUpdater && progressUpdater->interrupted()); ++j) {
            BoolMatrix[i][j] = false;
        }
    }

    KisRandomAccessorSP dstAccessor = dst->createRandomAccessorNG(dstTopLeft.x(), dstTopLeft.y());
    KisRandomConstAccessorSP srcAccessor = src->createRandomConstAccessorNG(dstTopLeft.x(), dstTopLeft.y());
    
    for (uint NumBlurs = 0; (NumBlurs <= number) && !(progressUpdater && progressUpdater->interrupted()); ++NumBlurs) {
        NewSize = (int)(rand() * ((double)(DropSize - 5) / RAND_MAX) + 5);
        halfSize = NewSize / 2;
        Radius = halfSize;
        s = Radius / log(NewfishEyes * Radius + 1);

        Counter = 0;

        do {
            FindAnother = false;
            y = (int)(rand() * ((double)(Width - 1) / RAND_MAX));
            x = (int)(rand() * ((double)(Height - 1) / RAND_MAX));

            if (BoolMatrix[y][x])
                FindAnother = true;
            else
                for (i = x - halfSize ; (i <= x + halfSize) && !(progressUpdater && progressUpdater->interrupted()); i++)
                    for (j = y - halfSize ; (j <= y + halfSize) && !(progressUpdater && progressUpdater->interrupted()); j++)
                        if ((i >= 0) && (i < Height) && (j >= 0) && (j < Width))
                            if (BoolMatrix[j][i])
                                FindAnother = true;

            Counter++;
        } while ((FindAnother && (Counter < 10000) && !(progressUpdater && progressUpdater->interrupted())));

        if (Counter >= 10000) {
            NumBlurs = number;
            break;
        }

        for (i = -1 * halfSize ; (i < NewSize - halfSize) && !(progressUpdater && progressUpdater->interrupted()); i++) {
            for (j = -1 * halfSize ; (j < NewSize - halfSize) && !(progressUpdater && progressUpdater->interrupted()); j++) {
                r = sqrt(i * i + j * j);
                a = atan2(static_cast<double>(i), static_cast<double>(j));

                if (r <= Radius) {
                    OldRadius = r;
                    r = (exp(r / s) - 1) / NewfishEyes;

                    k = x + (int)(r * sin(a));
                    l = y + (int)(r * cos(a));

                    m = x + i;
                    n = y + j;

                    if ((k >= 0) && (k < Height) && (l >= 0) && (l < Width)) {
                        if ((m >= 0) && (m < Height) && (n >= 0) && (n < Width)) {
                            Bright = 0;

                            if (OldRadius >= 0.9 * Radius) {
                                if ((a <= 0) && (a > -2.25))
                                    Bright = -80;
                                else if ((a <= -2.25) && (a > -2.5))
                                    Bright = -40;
                                else if ((a <= 0.25) && (a > 0))
                                    Bright = -40;
                            }

                            else if (OldRadius >= 0.8 * Radius) {
                                if ((a <= -0.75) && (a > -1.50))
                                    Bright = -40;
                                else if ((a <= 0.10) && (a > -0.75))
                                    Bright = -30;
                                else if ((a <= -1.50) && (a > -2.35))
                                    Bright = -30;
                            }

                            else if (OldRadius >= 0.7 * Radius) {
                                if ((a <= -0.10) && (a > -2.0))
                                    Bright = -20;
                                else if ((a <= 2.50) && (a > 1.90))
                                    Bright = 60;
                            }

                            else if (OldRadius >= 0.6 * Radius) {
                                if ((a <= -0.50) && (a > -1.75))
                                    Bright = -20;
                                else if ((a <= 0) && (a > -0.25))
                                    Bright = 20;
                                else if ((a <= -2.0) && (a > -2.25))
                                    Bright = 20;
                            }

                            else if (OldRadius >= 0.5 * Radius) {
                                if ((a <= -0.25) && (a > -0.50))
                                    Bright = 30;
                                else if ((a <= -1.75) && (a > -2.0))
                                    Bright = 30;
                            }

                            else if (OldRadius >= 0.4 * Radius) {
                                if ((a <= -0.5) && (a > -1.75))
                                    Bright = 40;
                            }

                            else if (OldRadius >= 0.3 * Radius) {
                                if ((a <= 0) && (a > -2.25))
                                    Bright = 30;
                            }

                            else if (OldRadius >= 0.2 * Radius) {
                                if ((a <= -0.5) && (a > -1.75))
                                    Bright = 20;
                            }

                            BoolMatrix[n][m] = true;

                            QColor originalColor;

                            srcAccessor->moveTo(srcTopLeft.x() + l, srcTopLeft.y() + k);
                            cs->toQColor(srcAccessor->oldRawData(), &originalColor);

                            int newRed = CLAMP(originalColor.red() + Bright, 0, quint8_MAX);
                            int newGreen = CLAMP(originalColor.green() + Bright, 0, quint8_MAX);
                            int newBlue = CLAMP(originalColor.blue() + Bright, 0, quint8_MAX);

                            QColor newColor;
                            newColor.setRgb(newRed, newGreen, newBlue);

                            dstAccessor->moveTo(dstTopLeft.x() + n, dstTopLeft.y() + m);
                            cs->fromQColor(newColor, dstAccessor->rawData());
                        }
                    }
                }
            }
        }

        BlurRadius = NewSize / 25 + 1;

        for (i = -1 * halfSize - BlurRadius ; (i < NewSize - halfSize + BlurRadius) && !(progressUpdater && progressUpdater->interrupted()) ; i++) {
            for (j = -1 * halfSize - BlurRadius;
                    ((j < NewSize - halfSize + BlurRadius) && !(progressUpdater && progressUpdater->interrupted()));
                    ++j) {
                r = sqrt(i * i + j * j);

                if (r <= Radius * 1.1) {
                    R = G = B = 0;
                    BlurPixels = 0;

                    for (k = -1 * BlurRadius; k < BlurRadius + 1; k++)
                        for (l = -1 * BlurRadius; l < BlurRadius + 1; l++) {
                            m = x + i + k;
                            n = y + j + l;

                            if ((m >= 0) && (m < Height) && (n >= 0) && (n < Width)) {
                                QColor color;
                                dstAccessor->moveTo(dstTopLeft.x() + n, dstTopLeft.y() + m);
                                cs->toQColor(dstAccessor->rawData(), &color);

                                R += color.red();
                                G += color.green();
                                B += color.blue();
                                BlurPixels++;
                            }
                        }

                    m = x + i;
                    n = y + j;

                    if ((m >= 0) && (m < Height) && (n >= 0) && (n < Width)) {
                        QColor color;

                        color.setRgb((int)(R / BlurPixels), (int)(G / BlurPixels), (int)(B / BlurPixels));
                        dstAccessor->moveTo(dstTopLeft.x() + n, dstTopLeft.y() + m);
                        cs->fromQColor(color, dstAccessor->rawData());
                    }
                }
            }
        }

        if (progressUpdater) progressUpdater->setValue(++count);
    }

    FreeBoolArray(BoolMatrix, Width);
}
void KisWaveletNoiseReduction::process(KisConstProcessingInformation srcInfo,
                                       KisProcessingInformation dstInfo,
                                       const QSize& areaSize,
                                       const KisFilterConfiguration* config,
                                       KoUpdater* progressUpdater
                                      ) const
{
    const KisPaintDeviceSP src = srcInfo.paintDevice();
    KisPaintDeviceSP dst = dstInfo.paintDevice();
    QPoint dstTopLeft = dstInfo.topLeft();
    QPoint srcTopLeft = srcInfo.topLeft();
    Q_ASSERT(!src.isNull());
    Q_ASSERT(!dst.isNull());
    // TODO take selections into account
    float threshold;

    if (!config) {
        config = defaultConfiguration(src);
    }

    threshold = config->getDouble("threshold", BEST_WAVELET_THRESHOLD_VALUE);

    qint32 depth = src->colorSpace()->colorChannelCount();

    int size;
    int maxrectsize = qMax(areaSize.width(), areaSize.height());
    for (size = 2; size < maxrectsize; size *= 2) ;

    KisMathToolbox* mathToolbox = KisMathToolboxRegistry::instance()->get(src->colorSpace()->mathToolboxId().id());
    QRect srcRect(srcTopLeft, areaSize);

    if (progressUpdater) {
        progressUpdater->setRange(0, mathToolbox->fastWaveletTotalSteps(srcRect) * 2 + size*size*depth);
    }
    int count = 0;
//     connect(mathToolbox, SIGNAL(nextStep()), this, SLOT(incProgress()));


//     dbgFilters << size <<"" << maxrectsize <<"" << srcTopLeft.x() <<"" << srcTopLeft.y();

//     dbgFilters <<"Transforming...";
//     setProgressStage( i18n("Fast wavelet transformation") ,progress());
    KisMathToolbox::KisWavelet* buff = 0;
    KisMathToolbox::KisWavelet* wav = 0;

    try {
        buff = mathToolbox->initWavelet(src, srcRect);
    } catch (std::bad_alloc) {
        if (buff) delete buff;
        return;
    }
    try {
        wav = mathToolbox->fastWaveletTransformation(src, srcRect, buff);
    } catch (std::bad_alloc) {
        if (wav) delete wav;
        return;
    }

//     dbgFilters <<"Thresholding...";
    float* fin = wav->coeffs + wav->depth * wav->size * wav->size;

    for (float* it = wav->coeffs + wav->depth; it < fin; it++) {
        if (*it > threshold) {
            *it -= threshold;
        } else if (*it < -threshold) {
            *it += threshold;
        } else {
            *it = 0.;
        }
        if (progressUpdater) progressUpdater->setValue(++count);
    }

//     dbgFilters <<"Untransforming...";

    mathToolbox->fastWaveletUntransformation(dst, QRect(dstTopLeft, areaSize), wav, buff);

    delete wav;
    delete buff;
//     disconnect(mathToolbox, SIGNAL(nextStep()), this, SLOT(incProgress()));
}
void KisRoundCornersFilter::processImpl(KisPaintDeviceSP device,
                                        const QRect& applyRect,
                                        const KisFilterConfiguration* config,
                                        KoUpdater* progressUpdater
                                        ) const
{
    Q_UNUSED(config);
    Q_ASSERT(!device.isNull());

    if (!device || !config) {
        warnKrita << "Invalid parameters for round corner filter";
        dbgPlugins << device << " " << config;
        return;
    }

    //read the filter configuration values from the KisFilterConfiguration object
    qint32 radius = qMax(1, config->getInt("radius" , 30));

    if (progressUpdater) {
        progressUpdater->setRange(0, applyRect.height());
    }

    qint32 width = applyRect.width();

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

    const KoColorSpace* cs = device->colorSpace();

    QRect bounds = device->defaultBounds()->bounds();
    for (qint32 y = applyRect.y(); y < applyRect.y() + applyRect.height(); y++) {
        qint32 x = applyRect.x();
        do {
            if (x <= radius && y <= radius) {
                double dx = radius - x;
                double dy = radius - y;
                double dradius = static_cast<double>(radius);
                if (dx >= sqrt(dradius*dradius - dy*dy)) {
                    cs->setOpacity(dstIt->rawData(), OPACITY_TRANSPARENT_U8, 1);
                }
            } else if (x >= bounds.width() - radius && y <= radius) {
                double dx = x + radius - bounds.width();
                double dy = radius - y;
                double dradius = static_cast<double>(radius);
                if (dx >= sqrt(dradius*dradius - dy*dy)) {
                    cs->setOpacity(dstIt->rawData(), OPACITY_TRANSPARENT_U8, 1);
                }
            } else if (x <= radius && y >= bounds.height() - radius) {
                double dx = radius - x;
                double dy = y + radius - bounds.height();
                double dradius = static_cast<double>(radius);
                if (dx >= sqrt(dradius*dradius - dy*dy)) {
                    cs->setOpacity(dstIt->rawData(), OPACITY_TRANSPARENT_U8, 1);
                }
            } else if (x >= bounds.width()  - radius && y >= bounds.height() - radius) {

                double dx = x + radius - bounds.width() ;
                double dy = y + radius - bounds.height();
                double dradius = static_cast<double>(radius);
                if (dx >= sqrt(dradius*dradius - dy*dy)) {
                    cs->setOpacity(dstIt->rawData(), OPACITY_TRANSPARENT_U8, 1);
                }
            }
            ++x;
        } while(dstIt->nextPixel());
        dstIt->nextRow();
        if (progressUpdater) progressUpdater->setValue(y);
    }
}
void KisSobelFilter::process(KisPaintDeviceSP device,
                            const QRect& applyRect,
                            const KisFilterConfiguration* configuration,
                            KoUpdater* progressUpdater
                            ) const
{
    QPoint srcTopLeft = applyRect.topLeft();
    Q_ASSERT(!device.isNull());

    //read the filter configuration values from the KisFilterConfiguration object
    bool doHorizontal = configuration->getBool("doHorizontally", true);
    bool doVertical = configuration->getBool("doVertically", true);
    bool keepSign = configuration->getBool("keepSign", true);
    bool makeOpaque = configuration->getBool("makeOpaque", true);

    quint32 width = applyRect.width();
    quint32 height = applyRect.height();
    quint32 pixelSize = device->pixelSize();

    int cost = applyRect.height();

    /*  allocate row buffers  */
    quint8* prevRow = new quint8[(width + 2) * pixelSize];
    Q_CHECK_PTR(prevRow);
    quint8* curRow = new quint8[(width + 2) * pixelSize];
    Q_CHECK_PTR(curRow);
    quint8* nextRow = new quint8[(width + 2) * pixelSize];
    Q_CHECK_PTR(nextRow);
    quint8* dest = new quint8[ width  * pixelSize];
    Q_CHECK_PTR(dest);

    quint8* pr = prevRow + pixelSize;
    quint8* cr = curRow + pixelSize;
    quint8* nr = nextRow + pixelSize;

    prepareRow(device, pr, srcTopLeft.x(), srcTopLeft.y() - 1, width, height);
    prepareRow(device, cr, srcTopLeft.x(), srcTopLeft.y(), width, height);

    quint32 counter = 0;
    quint8* d;
    quint8* tmp;
    qint32 gradient, horGradient, verGradient;
    // loop through the rows, applying the sobel convolution

    KisHLineIteratorSP dstIt = device->createHLineIteratorNG(srcTopLeft.x(), srcTopLeft.y(), width);

    for (quint32 row = 0; row < height; row++) {

        // prepare the next row
        prepareRow(device, nr, srcTopLeft.x(), srcTopLeft.y() + row + 1, width, height);
        d = dest;

        for (quint32 col = 0; col < width * pixelSize; col++) {
            int positive = col + pixelSize;
            int negative = col - pixelSize;
            horGradient = (doHorizontal ?
                           ((pr[negative] +  2 * pr[col] + pr[positive]) -
                            (nr[negative] + 2 * nr[col] + nr[positive]))
                           : 0);

            verGradient = (doVertical ?
                           ((pr[negative] + 2 * cr[negative] + nr[negative]) -
                            (pr[positive] + 2 * cr[positive] + nr[positive]))
                           : 0);
            gradient = (qint32)((doVertical && doHorizontal) ?
                                (ROUND(RMS(horGradient, verGradient)) / 5.66)   // always >0
                                : (keepSign ? (127 + (ROUND((horGradient + verGradient) / 8.0)))
                                   : (ROUND(qAbs(horGradient + verGradient) / 4.0))));

            *d++ = gradient;
            if (gradient > 10) counter ++;
        }

        //  shuffle the row pointers
        tmp = pr;
        pr = cr;
        cr = nr;
        nr = tmp;

        //store the dest
        device->writeBytes(dest, srcTopLeft.x(), row, width, 1);

        if (makeOpaque) {
            do {
                device->colorSpace()->setOpacity(dstIt->rawData(), OPACITY_OPAQUE_U8, 1);
            } while(dstIt->nextPixel());
            dstIt->nextRow();
        }
        if (progressUpdater) progressUpdater->setProgress(row / cost);
    }

    delete[] prevRow;
    delete[] curRow;
    delete[] nextRow;
    delete[] dest;
}