void copyFromDevice(KisViewManager *view, KisPaintDeviceSP device, bool makeSharpClip = false)
    {
        KisImageWSP image = view->image();
        if (!image) return;

        KisSelectionSP selection = view->selection();

        QRect rc = (selection) ? selection->selectedExactRect() : image->bounds();

        KisPaintDeviceSP clip = new KisPaintDevice(device->colorSpace());
        Q_CHECK_PTR(clip);

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

        // TODO if the source is linked... copy from all linked layers?!?

        // Copy image data
        KisPainter::copyAreaOptimized(QPoint(), device, clip, rc);

        if (selection) {
            // Apply selection mask.
            KisPaintDeviceSP selectionProjection = selection->projection();
            KisHLineIteratorSP layerIt = clip->createHLineIteratorNG(0, 0, rc.width());
            KisHLineConstIteratorSP selectionIt = selectionProjection->createHLineIteratorNG(rc.x(), rc.y(), rc.width());

            const KoColorSpace *selCs = selection->projection()->colorSpace();

            for (qint32 y = 0; y < rc.height(); y++) {

                for (qint32 x = 0; x < rc.width(); x++) {

                    /**
                     * Sharp method is an exact reverse of COMPOSITE_OVER
                     * so if you cover the cut/copied piece over its source
                     * you get an exactly the same image without any seams
                     */
                    if (makeSharpClip) {
                        qreal dstAlpha = cs->opacityF(layerIt->rawData());
                        qreal sel = selCs->opacityF(selectionIt->oldRawData());
                        qreal newAlpha = sel * dstAlpha / (1.0 - dstAlpha + sel * dstAlpha);
                        float mask = newAlpha / dstAlpha;

                        cs->applyAlphaNormedFloatMask(layerIt->rawData(), &mask, 1);
                    } else {
                        cs->applyAlphaU8Mask(layerIt->rawData(), selectionIt->oldRawData(), 1);
                    }

                    layerIt->nextPixel();
                    selectionIt->nextPixel();
                }
                layerIt->nextRow();
                selectionIt->nextRow();
            }
        }

        KisClipboard::instance()->setClip(clip, rc.topLeft());
    }
示例#2
0
void KisUnsharpFilter::processRaw(KisPaintDeviceSP device,
                                  const QRect &rect,
                                  quint8 threshold,
                                  qreal weights[2],
                                  qreal factor,
                                  const QBitArray &channelFlags) const
{
    const KoColorSpace *cs = device->colorSpace();
    const int pixelSize = cs->pixelSize();
    KoConvolutionOp * convolutionOp = cs->convolutionOp();
    KisHLineIteratorSP dstIt = device->createHLineIteratorNG(rect.x(), rect.y(), rect.width());

    quint8 *colors[2];
    colors[0] = new quint8[pixelSize];
    colors[1] = new quint8[pixelSize];

    for (int j = 0; j < rect.height(); j++) {
        do {
            quint8 diff = cs->difference(dstIt->oldRawData(), dstIt->rawDataConst());
            if (diff > threshold) {
                memcpy(colors[0], dstIt->oldRawData(), pixelSize);
                memcpy(colors[1], dstIt->rawDataConst(), pixelSize);
                convolutionOp->convolveColors(colors, weights, dstIt->rawData(), factor, 0, 2, channelFlags);
            } else {
                memcpy(dstIt->rawData(), dstIt->oldRawData(), pixelSize);
            }
        } while (dstIt->nextPixel());
        dstIt->nextRow();
    }

    delete colors[0];
    delete colors[1];
}
void KisSimpleNoiseReducer::processImpl(KisPaintDeviceSP device,
                                        const QRect& applyRect,
                                        const KisFilterConfiguration* config,
                                        KoUpdater* progressUpdater
                                        ) const
{
    QPoint srcTopLeft = applyRect.topLeft();
    Q_ASSERT(device);

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

    threshold = config->getInt("threshold", 15);
    windowsize = config->getInt("windowsize", 1);

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

    // Compute the blur mask
    KisCircleMaskGenerator* kas = new KisCircleMaskGenerator(2*windowsize + 1, 1, windowsize, windowsize, 2);

    KisConvolutionKernelSP kernel = KisConvolutionKernel::fromMaskGenerator(kas);
    delete kas;

    KisPaintDeviceSP interm = new KisPaintDevice(*device); // TODO no need for a full copy and then a transaction
    KisConvolutionPainter painter(interm);
    painter.beginTransaction("bouuh");
    painter.applyMatrix(kernel, interm, srcTopLeft, srcTopLeft, applyRect.size(), BORDER_REPEAT);
    painter.deleteTransaction();

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


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

    for (int j = 0; j < applyRect.height() && !(progressUpdater && progressUpdater->interrupted()); j++) {
        do {
                quint8 diff = cs->difference(dstIt->oldRawData(), intermIt->oldRawData());
                if (diff > threshold) {
                    memcpy(dstIt->rawData(), intermIt->oldRawData(), cs->pixelSize());
                }
            if (progressUpdater) progressUpdater->setValue(++count);
            intermIt->nextPixel();
        } while (dstIt->nextPixel() && !(progressUpdater && progressUpdater->interrupted()));
        dstIt->nextRow();
        intermIt->nextRow();
    }

}
    void copyFromDevice(KisView2 *view, KisPaintDeviceSP device) {
        KisImageWSP image = view->image();
        KisSelectionSP selection = view->selection();

        QRect rc = (selection) ? selection->selectedExactRect() : image->bounds();

        KisPaintDeviceSP clip = new KisPaintDevice(device->colorSpace());
        Q_CHECK_PTR(clip);

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

        // TODO if the source is linked... copy from all linked layers?!?

        // Copy image data
        KisPainter gc;
        gc.begin(clip);
        gc.setCompositeOp(COMPOSITE_COPY);
        gc.bitBlt(0, 0, device, rc.x(), rc.y(), rc.width(), rc.height());
        gc.end();

        if (selection) {
            // Apply selection mask.
            KisPaintDeviceSP selectionProjection = selection->projection();
            KisHLineIteratorSP layerIt = clip->createHLineIteratorNG(0, 0, rc.width());
            KisHLineConstIteratorSP selectionIt = selectionProjection->createHLineIteratorNG(rc.x(), rc.y(), rc.width());

            for (qint32 y = 0; y < rc.height(); y++) {

                for (qint32 x = 0; x < rc.width(); x++) {

                    cs->applyAlphaU8Mask(layerIt->rawData(), selectionIt->oldRawData(), 1);

                    layerIt->nextPixel();
                    selectionIt->nextPixel();
                }
                layerIt->nextRow();
                selectionIt->nextRow();
            }
        }

        KisClipboard::instance()->setClip(clip, rc.topLeft());
    }
示例#5
0
void KisUnsharpFilter::processLightnessOnly(KisPaintDeviceSP device,
                                            const QRect &rect,
                                            quint8 threshold,
                                            qreal weights[2],
                                            qreal factor,
                                            const QBitArray & /*channelFlags*/) const
{
    const KoColorSpace *cs = device->colorSpace();
    const int pixelSize = cs->pixelSize();
    KisHLineIteratorSP dstIt = device->createHLineIteratorNG(rect.x(), rect.y(), rect.width());

    quint16 labColorSrc[4];
    quint16 labColorDst[4];

    const int posL = 0;
    const int posAplha = 3;

    const qreal factorInv = 1.0 / factor;

    for (int j = 0; j < rect.height(); j++) {
        do {
            quint8 diff = cs->differenceA(dstIt->oldRawData(), dstIt->rawDataConst());
            if (diff > threshold) {
                cs->toLabA16(dstIt->oldRawData(), (quint8*)labColorSrc, 1);
                cs->toLabA16(dstIt->rawDataConst(), (quint8*)labColorDst, 1);

                qint32 valueL = (labColorSrc[posL] * weights[0] + labColorDst[posL] * weights[1]) * factorInv;
                labColorSrc[posL] = CLAMP(valueL,
                                          KoColorSpaceMathsTraits<quint16>::min,
                                          KoColorSpaceMathsTraits<quint16>::max);

                qint32 valueAlpha = (labColorSrc[posAplha] * weights[0] + labColorDst[posAplha] * weights[1]) * factorInv;
                labColorSrc[posAplha] = CLAMP(valueAlpha,
                                              KoColorSpaceMathsTraits<quint16>::min,
                                              KoColorSpaceMathsTraits<quint16>::max);

                cs->fromLabA16((quint8*)labColorSrc, dstIt->rawData(), 1);
            } else {
                memcpy(dstIt->rawData(), dstIt->oldRawData(), pixelSize);
            }
        } while (dstIt->nextPixel());
        dstIt->nextRow();
    }
}
void KisOilPaintFilter::OilPaint(const KisPaintDeviceSP src, KisPaintDeviceSP dst, const QPoint& srcTopLeft, const QPoint& dstTopLeft, int w, int h,
                                 int BrushSize, int Smoothness, KoUpdater* progressUpdater) const
{
    if (progressUpdater) {
        progressUpdater->setRange(0, w * h);
    }

    QRect bounds(srcTopLeft.x(), srcTopLeft.y(), w, h);

    KisHLineConstIteratorSP it = src->createHLineConstIteratorNG(srcTopLeft.x(), srcTopLeft.y(), w);
    KisHLineIteratorSP dstIt = dst->createHLineIteratorNG(dstTopLeft.x(), dstTopLeft.y(), w);

    int progress = 0;
    for (qint32 yOffset = 0; yOffset < h; yOffset++) {
        do {  //&& !cancelRequested()) {
                MostFrequentColor(src, dstIt->rawData(), bounds, it->x(), it->y(), BrushSize, Smoothness);
        }  while (it->nextPixel() && dstIt->nextPixel());
        it->nextRow();
        dstIt->nextRow();

        if (progressUpdater) progressUpdater->setValue(progress += w);
    }
}
示例#7
0
KisHLineIteratorSP createIterator(KisPaintDeviceSP dev,
                                  const QRect &rc) {
    return dev->createHLineIteratorNG(rc.x(), rc.y(), rc.width());
}
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);
}
void KisCustomBrushWidget::createBrush()
{
    if (!m_image)
        return;

    if (m_brush){
        // don't delete shared pointer, please
        bool removedCorrectly = KisBrushServer::instance()->brushServer()->removeResourceFromServer(  m_brush.data() );
        if (!removedCorrectly){
            kWarning() << "Brush was not removed correctly for the resource server";
        }
    }

    if (brushStyle->currentIndex() == 0) {
        KisSelectionSP selection = m_image->globalSelection();
        // create copy of the data
        m_image->lock();
        KisPaintDeviceSP dev = new KisPaintDevice(*m_image->mergedImage());
        m_image->unlock();

        if (!selection){
            m_brush = new KisGbrBrush(dev, 0, 0, m_image->width(), m_image->height());
        }
        else {
            // apply selection mask
            QRect r = selection->selectedExactRect();
            dev->crop(r);

            KisHLineIteratorSP pixelIt = dev->createHLineIteratorNG(r.x(), r.top(), r.width());
            KisHLineConstIteratorSP maskIt = selection->projection()->createHLineIteratorNG(r.x(), r.top(), r.width());

            for (qint32 y = r.top(); y <= r.bottom(); ++y) {

                do {
                    dev->colorSpace()->applyAlphaU8Mask(pixelIt->rawData(), maskIt->oldRawData(), 1);
                } while (pixelIt->nextPixel() && maskIt->nextPixel());

                pixelIt->nextRow();
                maskIt->nextRow();
            }

            QRect rc = dev->exactBounds();
            m_brush = new KisGbrBrush(dev, rc.x(), rc.y(), rc.width(), rc.height());
        }

    } else {
        // For each layer in the current image, create a new image, and add it to the list
        QVector< QVector<KisPaintDevice*> > devices;
        devices.push_back(QVector<KisPaintDevice*>());
        int w = m_image->width();
        int h = m_image->height();

        m_image->lock();

        // We only loop over the rootLayer. Since we actually should have a layer selection
        // list, no need to elaborate on that here and now
        KoProperties properties;
        properties.setProperty("visible", true);
        QList<KisNodeSP> layers = m_image->root()->childNodes(QStringList("KisLayer"), properties);
        KisNodeSP node;
        foreach(KisNodeSP node, layers) {
            devices[0].push_back(node->projection().data());
        }

        QVector<KisParasite::SelectionMode> modes;

        switch (comboBox2->currentIndex()) {
        case 0: modes.push_back(KisParasite::Constant); break;
        case 1: modes.push_back(KisParasite::Random); break;
        case 2: modes.push_back(KisParasite::Incremental); break;
        case 3: modes.push_back(KisParasite::Pressure); break;
        case 4: modes.push_back(KisParasite::Angular); break;
        default: modes.push_back(KisParasite::Incremental);
        }

        m_brush = new KisImagePipeBrush(m_image->objectName(), w, h, devices, modes);
        m_image->unlock();
    }
KisSpacingInformation KisDuplicateOp::paintAt(const KisPaintInformation& info)
{
    if (!painter()->device()) return 1.0;

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

    if (!brush->canPaintFor(info))
        return 1.0;

    if (!m_duplicateStartIsSet) {
        m_duplicateStartIsSet = true;
        m_duplicateStart = info.pos();
    }

    KisPaintDeviceSP realSourceDevice = settings->node()->paintDevice();

    qreal scale = m_sizeOption.apply(info);
    if (checkSizeTooSmall(scale)) return KisSpacingInformation();

    QPointF hotSpot = brush->hotSpot(scale, scale, 0, info);
    QPointF pt = info.pos() - hotSpot;

    setCurrentScale(scale);

    // 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, y;
    qreal xFraction, yFraction; // will not be used
    splitCoordinate(pt.x(), &x, &xFraction);
    splitCoordinate(pt.y(), &y, &yFraction);

    QPoint srcPoint;

    if(m_moveSourcePoint)
    {
        srcPoint = QPoint(x - static_cast<qint32>(settings->offset().x()),
                          y - static_cast<qint32>(settings->offset().y()));
    } else {
        srcPoint = QPoint(static_cast<qint32>(settings->position().x() - hotSpot.x()),
                          static_cast<qint32>(settings->position().y() - hotSpot.y()));
    }

    qint32 sw = brush->maskWidth(scale, 0.0, xFraction, yFraction, info);
    qint32 sh = brush->maskHeight(scale, 0.0, xFraction, yFraction, info);

    if (srcPoint.x() < 0)
        srcPoint.setX(0);

    if (srcPoint.y() < 0)
        srcPoint.setY(0);

    // Perspective correction ?
    KisImageWSP image = settings->m_image;
    if (m_perspectiveCorrection && image && image->perspectiveGrid()->countSubGrids() == 1) {
        Matrix3qreal startM = Matrix3qreal::Identity();
        Matrix3qreal endM = Matrix3qreal::Identity();

        // First look for the grid corresponding to the start point
        KisSubPerspectiveGrid* subGridStart = *image->perspectiveGrid()->begin();
        QRect r = QRect(0, 0, image->width(), image->height());

#if 1
        if (subGridStart) {
            startM = KisPerspectiveMath::computeMatrixTransfoFromPerspective(r, *subGridStart->topLeft(), *subGridStart->topRight(), *subGridStart->bottomLeft(), *subGridStart->bottomRight());
        }
#endif
#if 1
        // Second look for the grid corresponding to the end point
        KisSubPerspectiveGrid* subGridEnd = *image->perspectiveGrid()->begin();
        if (subGridEnd) {
            endM = KisPerspectiveMath::computeMatrixTransfoToPerspective(*subGridEnd->topLeft(), *subGridEnd->topRight(), *subGridEnd->bottomLeft(), *subGridEnd->bottomRight(), r);
        }
#endif

        // Compute the translation in the perspective transformation space:
        QPointF positionStartPaintingT = KisPerspectiveMath::matProd(endM, QPointF(m_duplicateStart));
        QPointF duplicateStartPositionT = KisPerspectiveMath::matProd(endM, QPointF(m_duplicateStart) - QPointF(settings->offset()));
        QPointF translat = duplicateStartPositionT - positionStartPaintingT;

        KisRectIteratorSP dstIt = m_srcdev->createRectIteratorNG(0, 0, sw, sh);
        KisRandomSubAccessorSP srcAcc = realSourceDevice->createRandomSubAccessor();
        //Action
        do {
            QPointF p =  KisPerspectiveMath::matProd(startM, KisPerspectiveMath::matProd(endM, QPointF(dstIt->x() + x, dstIt->y() + y)) + translat);
            srcAcc->moveTo(p);
            srcAcc->sampledOldRawData(dstIt->rawData());
        } while (dstIt->nextPixel());


    } else {
        KisPainter copyPainter(m_srcdev);
        copyPainter.setCompositeOp(COMPOSITE_COPY);
        copyPainter.bitBltOldData(0, 0, realSourceDevice, srcPoint.x(), srcPoint.y(), sw, sh);
        copyPainter.end();
    }

    // heal ?

    if (m_healing) {
        quint16 srcData[4];
        quint16 tmpData[4];
        qreal* matrix = new qreal[ 3 * sw * sh ];
        // First divide
        const KoColorSpace* srcCs = realSourceDevice->colorSpace();
        const KoColorSpace* tmpCs = m_srcdev->colorSpace();
        KisHLineConstIteratorSP srcIt = realSourceDevice->createHLineConstIteratorNG(x, y, sw);
        KisHLineIteratorSP tmpIt = m_srcdev->createHLineIteratorNG(0, 0, sw);
        qreal* matrixIt = &matrix[0];
        for (int j = 0; j < sh; j++) {
            for (int i = 0; i < sw; i++) {
                srcCs->toLabA16(srcIt->oldRawData(), (quint8*)srcData, 1);
                tmpCs->toLabA16(tmpIt->rawData(), (quint8*)tmpData, 1);
                // Division
                for (int k = 0; k < 3; k++) {
                    matrixIt[k] = srcData[k] / (qreal)qMax((int)tmpData [k], 1);
                }
                srcIt->nextPixel();
                tmpIt->nextPixel();
                matrixIt += 3;
            }
            srcIt->nextRow();
            tmpIt->nextRow();
        }
        // Minimize energy
        {
            int iter = 0;
            qreal err;
            qreal* solution = new qreal [ 3 * sw * sh ];
            do {
                err = minimizeEnergy(&matrix[0], &solution[0], sw, sh);

                // swap pointers
                qreal *tmp = matrix;
                matrix = solution;
                solution = tmp;

                iter++;
            } while (err > 0.00001 && iter < 100);
            delete [] solution;
        }

        // Finaly multiply
        KisHLineIteratorSP srcIt2 = realSourceDevice->createHLineIteratorNG(x, y, sw);
        KisHLineIteratorSP tmpIt2 = m_srcdev->createHLineIteratorNG(0, 0, sw);
        matrixIt = &matrix[0];
        for (int j = 0; j < sh; j++) {
            for (int i = 0; i < sw; i++) {
                srcCs->toLabA16(srcIt2->rawData(), (quint8*)srcData, 1);
                tmpCs->toLabA16(tmpIt2->rawData(), (quint8*)tmpData, 1);
                // Multiplication
                for (int k = 0; k < 3; k++) {
                    tmpData[k] = (int)CLAMP(matrixIt[k] * qMax((int) tmpData[k], 1), 0, 65535);
                }
                tmpCs->fromLabA16((quint8*)tmpData, tmpIt2->rawData(), 1);
                srcIt2->nextPixel();
                tmpIt2->nextPixel();
                matrixIt += 3;
            }
            srcIt2->nextRow();
            tmpIt2->nextRow();
        }
        delete [] matrix;
    }

    static const KoColorSpace *cs = KoColorSpaceRegistry::instance()->alpha8();
    static KoColor color(Qt::black, cs);

    KisFixedPaintDeviceSP dab =
        m_dabCache->fetchDab(cs, color, scale, scale,
                             0.0, info);

    QRect dstRect = QRect(x, y, dab->bounds().width(), dab->bounds().height());
    if (dstRect.isEmpty()) return 1.0;

    painter()->bitBltWithFixedSelection(dstRect.x(), dstRect.y(),
                                        m_srcdev, dab,
                                        dstRect.width(),
                                        dstRect.height());

    painter()->renderMirrorMaskSafe(dstRect, m_srcdev, 0, 0, dab,
                                    !m_dabCache->needSeparateOriginal());

    return effectiveSpacing(dstRect.width(), dstRect.height());
}
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);
    }
}
示例#12
0
void KisFilterFastColorTransfer::processImpl(KisPaintDeviceSP device,
                                             const QRect& applyRect,
                                             const KisFilterConfiguration* config,
                                             KoUpdater* progressUpdater) const
{
    Q_ASSERT(device != 0);

    dbgPlugins << "Start transferring color";

    // Convert ref and src to LAB
    const KoColorSpace* labCS = KoColorSpaceRegistry::instance()->lab16();
    if (!labCS) {
        dbgPlugins << "The LAB colorspace is not available.";
        return;
    }
    
    dbgPlugins << "convert a copy of src to lab";
    const KoColorSpace* oldCS = device->colorSpace();
    KisPaintDeviceSP srcLAB = new KisPaintDevice(*device.data());
    dbgPlugins << "srcLab : " << srcLAB->extent();
    KUndo2Command* cmd = srcLAB->convertTo(labCS, KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags());
    delete cmd;

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

    // Compute the means and sigmas of src
    dbgPlugins << "Compute the means and sigmas of src";
    double meanL_src = 0., meanA_src = 0., meanB_src = 0.;
    double sigmaL_src = 0., sigmaA_src = 0., sigmaB_src = 0.;

    KisSequentialConstIterator srcIt(srcLAB, applyRect);

    do {
        const quint16* data = reinterpret_cast<const quint16*>(srcIt.oldRawData());
        quint32 L = data[0];
        quint32 A = data[1];
        quint32 B = data[2];
        meanL_src += L;
        meanA_src += A;
        meanB_src += B;
        sigmaL_src += L * L;
        sigmaA_src += A * A;
        sigmaB_src += B * B;
        if (progressUpdater) progressUpdater->setValue(++count);
    } while (srcIt.nextPixel() && !(progressUpdater && progressUpdater->interrupted()));
    
    double totalSize = 1. / (applyRect.width() * applyRect.height());
    meanL_src *= totalSize;
    meanA_src *= totalSize;
    meanB_src *= totalSize;
    sigmaL_src *= totalSize;
    sigmaA_src *= totalSize;
    sigmaB_src *= totalSize;
    
    dbgPlugins << totalSize << "" << meanL_src << "" << meanA_src << "" << meanB_src << "" << sigmaL_src << "" << sigmaA_src << "" << sigmaB_src;
    
    double meanL_ref = config->getDouble("meanL");
    double meanA_ref = config->getDouble("meanA");
    double meanB_ref = config->getDouble("meanB");
    double sigmaL_ref = config->getDouble("sigmaL");
    double sigmaA_ref = config->getDouble("sigmaA");
    double sigmaB_ref = config->getDouble("sigmaB");
    
    
    // Transfer colors
    dbgPlugins << "Transfer colors";
    {
        double coefL = sqrt((sigmaL_ref - meanL_ref * meanL_ref) / (sigmaL_src - meanL_src * meanL_src));
        double coefA = sqrt((sigmaA_ref - meanA_ref * meanA_ref) / (sigmaA_src - meanA_src * meanA_src));
        double coefB = sqrt((sigmaB_ref - meanB_ref * meanB_ref) / (sigmaB_src - meanB_src * meanB_src));
        KisHLineConstIteratorSP srcLABIt = srcLAB->createHLineConstIteratorNG(applyRect.x(), applyRect.y(), applyRect.width());
        KisHLineIteratorSP dstIt = device->createHLineIteratorNG(applyRect.x(), applyRect.y(), applyRect.width());
        quint16 labPixel[4];
        for (int y = 0; y < applyRect.height() && !(progressUpdater && progressUpdater->interrupted()); ++y) {
            do {
                const quint16* data = reinterpret_cast<const quint16*>(srcLABIt->oldRawData());
                labPixel[0] = (quint16)CLAMP(((double)data[0] - meanL_src) * coefL + meanL_ref, 0., 65535.);
                labPixel[1] = (quint16)CLAMP(((double)data[1] - meanA_src) * coefA + meanA_ref, 0., 65535.);
                labPixel[2] = (quint16)CLAMP(((double)data[2] - meanB_src) * coefB + meanB_ref, 0., 65535.);
                labPixel[3] = data[3];
                oldCS->fromLabA16(reinterpret_cast<const quint8*>(labPixel), dstIt->rawData(), 1);
                if (progressUpdater) progressUpdater->setValue(++count);
                srcLABIt->nextPixel();
            } while(dstIt->nextPixel());
            dstIt->nextRow();
            srcLABIt->nextRow();
        }

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