void KisFilterSelectionsBenchmark::testBitBltSelections(int num)
{
    KisPaintDeviceSP projection =
        new KisPaintDevice(m_device->colorSpace());

    double avTime;
    KisTimeCounter timer;

    QRect filterRect = m_selection->selectedExactRect();

    timer.restart();
    for (int i = 0; i < num; i++) {
        KisPaintDeviceSP cacheDevice = new KisPaintDevice(projection->colorSpace());

        KisTransaction transac(cacheDevice, 0);
        m_filter->process(m_device, cacheDevice, 0, filterRect, m_configuration, 0);

        KisPainter gc(projection);
        gc.beginTransaction();
        gc.setCompositeOp(projection->colorSpace()->compositeOp(COMPOSITE_ALPHA_DARKEN));
        gc.setSelection(m_selection);
        gc.bitBlt(filterRect.topLeft(), cacheDevice, filterRect);
        gc.deleteTransaction();
    }
    avTime = double(timer.elapsed()) / num;

    projection->convertToQImage(0).save("TFS__BITBLT_WITH_SELECTIONS.png");

    if (num > WARMUP_CYCLES || SHOW_WARMUPS)
        dbgKrita << "bitBlt with sel:\t\t\t" << avTime;
}
void KisPasteNewActionFactory::run(KisViewManager *viewManager)
{
    Q_UNUSED(viewManager);

    KisPaintDeviceSP clip = KisClipboard::instance()->clip(QRect(), true);
    if (!clip) return;

    QRect rect = clip->exactBounds();
    if (rect.isEmpty()) return;

    KisDocument *doc = KisPart::instance()->createDocument();

    KisImageSP image = new KisImage(doc->createUndoStore(),
                                    rect.width(),
                                    rect.height(),
                                    clip->colorSpace(),
                                    i18n("Pasted"));
    KisPaintLayerSP layer =
        new KisPaintLayer(image.data(), clip->objectName(),
                          OPACITY_OPAQUE_U8, clip->colorSpace());

    KisPainter::copyAreaOptimized(QPoint(), clip, layer->paintDevice(), rect);

    image->addNode(layer.data(), image->rootLayer());
    doc->setCurrentImage(image);
    KisPart::instance()->addDocument(doc);

    KisMainWindow *win = viewManager->mainWindow();
    win->addViewAndNotifyLoadingCompleted(doc);
}
Пример #3
0
void KisPaintDeviceTest::testCreation()
{
    const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8();
    KisPaintDeviceSP dev = new KisPaintDevice(cs);
    QVERIFY(dev->objectName().isEmpty());

    dev = new KisPaintDevice(cs);
    QVERIFY(*dev->colorSpace() == *cs);
    QVERIFY(dev->x() == 0);
    QVERIFY(dev->y() == 0);
    QVERIFY(dev->pixelSize() == cs->pixelSize());
    QVERIFY(dev->channelCount() == cs->channelCount());
    QVERIFY(dev->dataManager() != 0);

    KisImageSP image = new KisImage(0, 1000, 1000, cs, "merge test");
    KisPaintLayerSP layer = new KisPaintLayer(image, "bla", 125);

    dev = new KisPaintDevice(layer.data(), cs);
    QVERIFY(*dev->colorSpace() == *cs);
    QVERIFY(dev->x() == 0);
    QVERIFY(dev->y() == 0);
    QVERIFY(dev->pixelSize() == cs->pixelSize());
    QVERIFY(dev->channelCount() == cs->channelCount());
    QVERIFY(dev->dataManager() != 0);

    // Let the layer go out of scope and see what happens
    {
        KisPaintLayerSP l2 = new KisPaintLayer(image, "blabla", 250);
        dev = new KisPaintDevice(l2.data(), cs);
    }

}
Пример #4
0
void KisPaintDeviceTest::testMakeClone()
{
    QImage image(QString(FILES_DATA_DIR) + QDir::separator() + "hakonepa.png");

    const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8();
    KisPaintDeviceSP srcDev = new KisPaintDevice(cs);
    srcDev->convertFromQImage(image, 0);
    srcDev->move(10,10);

    const KoColorSpace * weirdCS = KoColorSpaceRegistry::instance()->lab16();
    KisPaintDeviceSP dstDev = new KisPaintDevice(weirdCS);
    dstDev->move(1000,1000);

    QVERIFY(!dstDev->fastBitBltPossible(srcDev));

    QRect cloneRect(100,100,200,200);
    QPoint errpoint;

    dstDev->makeCloneFrom(srcDev, cloneRect);

    QVERIFY(*dstDev->colorSpace() == *srcDev->colorSpace());
    QCOMPARE(dstDev->pixelSize(), srcDev->pixelSize());
    QCOMPARE(dstDev->x(), srcDev->x());
    QCOMPARE(dstDev->y(), srcDev->y());
    QCOMPARE(dstDev->exactBounds(), cloneRect);

    QImage srcImage = srcDev->convertToQImage(0, cloneRect.x(), cloneRect.y(),
                                              cloneRect.width(), cloneRect.height());
    QImage dstImage = dstDev->convertToQImage(0, cloneRect.x(), cloneRect.y(),
                                              cloneRect.width(), cloneRect.height());
    if (!TestUtil::compareQImages(errpoint, dstImage, srcImage)) {
        QFAIL(QString("Failed to create identical image, first different pixel: %1,%2 \n").arg(errpoint.x()).arg(errpoint.y()).toLatin1());
    }
}
void KisThreadedApplicatorTest::testApplication()
{
    const KoColorSpace * colorSpace = KoColorSpaceRegistry::instance()->rgb8();
    TestJobFactory factory;
    TestUtil::TestProgressBar bar;
    KoProgressUpdater updater(&bar);
    KisPaintDeviceSP test = new KisPaintDevice(colorSpace);

    quint8 *bytes = test->colorSpace()->allocPixelBuffer(1);
    memset(bytes, 128, test->colorSpace()->pixelSize());
    test->fill(0, 0, 1000, 1000, bytes);

    KisTransaction transaction("", test);

    KisThreadedApplicator applicator(test, QRect(0, 0, 1000, 1000), &factory, &updater);
    applicator.execute();

    KisRectConstIteratorPixel it = test->createRectConstIterator(0, 0, 1000, 1000);
    while (!it.isDone()) {
        QCOMPARE((int)it.rawData()[0], (int)255);
        QCOMPARE((int)it.rawData()[1], (int)255);
        QCOMPARE((int)it.rawData()[2], (int)255);
        QCOMPARE((int)it.rawData()[3], (int)255);
        ++it;
    }
}
Пример #6
0
void MoveSelectionStrokeStrategy::initStrokeCallback()
{
    KisStrokeStrategyUndoCommandBased::initStrokeCallback();

    KisPaintDeviceSP paintDevice = m_paintLayer->paintDevice();

    KisPaintDeviceSP movedDevice = new KisPaintDevice(m_paintLayer.data(), paintDevice->colorSpace());


    QRect copyRect = m_selection->selectedRect();
    KisPainter gc(movedDevice);
    gc.setSelection(m_selection);
    gc.bitBlt(copyRect.topLeft(), paintDevice, copyRect);
    gc.end();

    KisTransaction cutTransaction(name(), paintDevice);
    paintDevice->clearSelection(m_selection);
    runAndSaveCommand(KUndo2CommandSP(cutTransaction.endAndTake()),
                      KisStrokeJobData::SEQUENTIAL,
                      KisStrokeJobData::NORMAL);

    KisIndirectPaintingSupport *indirect =
        static_cast<KisIndirectPaintingSupport*>(m_paintLayer.data());
    indirect->setTemporaryTarget(movedDevice);
    indirect->setTemporaryCompositeOp(paintDevice->colorSpace()->compositeOp(COMPOSITE_OVER));
    indirect->setTemporaryOpacity(OPACITY_OPAQUE_U8);

    m_selection->setVisible(false);
}
void KisPasteNewActionFactory::run(KisView2 *view)
{
    Q_UNUSED(view);

    KisPaintDeviceSP clip = KisClipboard::instance()->clip(QRect(), true);
    if (!clip) return;

    QRect rect = clip->exactBounds();
    if (rect.isEmpty()) return;

    KisDoc2 *doc = new KisDoc2();
    if (!doc) return;

    KisImageSP image = new KisImage(doc->createUndoStore(),
                                    rect.width(),
                                    rect.height(),
                                    clip->colorSpace(),
                                    i18n("Pasted"));
    KisPaintLayerSP layer =
        new KisPaintLayer(image.data(), clip->objectName(),
                          OPACITY_OPAQUE_U8, clip->colorSpace());

    KisPainter p(layer->paintDevice());
    p.setCompositeOp(COMPOSITE_COPY);
    p.bitBlt(0, 0, clip, rect.x(), rect.y(), rect.width(), rect.height());
    p.end();

    image->addNode(layer.data(), image->rootLayer());
    doc->setCurrentImage(image);

    KoMainWindow *win = doc->documentPart()->createMainWindow();
    win->show();
    win->setRootDocument(doc);
}
Пример #8
0
KisPaintDeviceSP KisMultipleProjection::getProjection(const QString &id, const QString &compositeOpId, KisPaintDeviceSP prototype)
{
    QReadLocker readLocker(&m_d->lock);

    PlanesMap::const_iterator constIt = m_d->planes.constFind(id);

    if (constIt == m_d->planes.constEnd() ||
        constIt->compositeOpId != compositeOpId ||
        !(*constIt->device->colorSpace() == *prototype->colorSpace())) {

        readLocker.unlock();

        {
            QWriteLocker writeLocker(&m_d->lock);

            PlanesMap::iterator writeIt = m_d->planes.find(id);
            if (writeIt == m_d->planes.end()) {
                ProjectionStruct plane;
                plane.device = new KisPaintDevice(*prototype);
                plane.compositeOpId = compositeOpId;
                writeIt = m_d->planes.insert(id, plane);
            } else if (writeIt->compositeOpId != compositeOpId ||
                       !(*writeIt->device->colorSpace() == *prototype->colorSpace())) {

                writeIt->device->makeCloneFromRough(prototype, prototype->extent());
                writeIt->compositeOpId = compositeOpId;
            }

            return writeIt->device;
        }
    }

    return constIt->device;
}
Пример #9
0
bool KisKraLoadVisitor::loadPaintDeviceFrame(KisPaintDeviceSP device, const QString &location, DevicePolicy policy)
{
    if (m_store->open(location)) {
        if (!policy.read(device, m_store->device())) {
            m_errorMessages << i18n("Could not read pixel data: %1.", location);
            device->disconnect();
            m_store->close();
            return false;
        }
        m_store->close();
    } else {
        m_errorMessages << i18n("Could not load pixel data: %1.", location);
        return false;
    }
    if (m_store->open(location + ".defaultpixel")) {
        int pixelSize = device->colorSpace()->pixelSize();
        if (m_store->size() == pixelSize) {
            KoColor color(Qt::transparent, device->colorSpace());
            m_store->read((char*)color.data(), pixelSize);
            policy.setDefaultPixel(device, color);
        }
        m_store->close();
    }

    return true;
}
    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());
    }
Пример #11
0
void KisConvolutionPainterTest::testAsymmConvolutionImp(QBitArray channelFlags)
{
    qreal offset = 0.0;
    qreal factor = 1.0;
    Eigen::Matrix<qreal, 3, 3> filter = initAsymmFilter(offset, factor);

    QRect imageRect;
    int pixelSize = -1;
    QByteArray initialData;
    KisPaintDeviceSP dev = initAsymTestDevice(imageRect, pixelSize, initialData);

    KisConvolutionKernelSP kernel =
        KisConvolutionKernel::fromMatrix(filter, offset, factor);
    KisConvolutionPainter gc(dev);
    gc.beginTransaction();
    gc.setChannelFlags(channelFlags);

    QRect filterRect = imageRect.adjusted(1,1,-1,-1);
    gc.applyMatrix(kernel, dev, filterRect.topLeft(), filterRect.topLeft(),
                   filterRect.size());
    gc.deleteTransaction();


    QByteArray resultData(initialData.size(), 0);
    dev->readBytes((quint8*)resultData.data(), imageRect);

    QRect filteredRect = imageRect.adjusted(1, 1, -1, -1);

    quint8 *srcPtr = (quint8*) initialData.data();
    quint8 *resPtr = (quint8*) resultData.data();

    for(int row = 0; row < imageRect.height(); row++) {
        for(int col = 0; col < imageRect.width(); col++) {

            bool isFiltered = filteredRect.contains(col, row);

            int pixelValue = 8 + row * imageRect.width() + col;
            KoColor filteredPixel(QColor(pixelValue, pixelValue, pixelValue, 255), dev->colorSpace());

            KoColor resultPixel(dev->colorSpace());
            for(int j = 0; j < pixelSize; j++) {
                resultPixel.data()[j] = isFiltered && channelFlags[j] ?
                    filteredPixel.data()[j] : srcPtr[j];
            }

            if(memcmp(resPtr, resultPixel.data(), pixelSize)) {
                printPixel("Actual:  ", pixelSize, resPtr);
                printPixel("Expected:", pixelSize, resultPixel.data());
                QFAIL("Failed to filter area");
            }

            srcPtr += pixelSize;
            resPtr += pixelSize;
        }
    }
}
Пример #12
0
void KisResourcesSnapshot::setCurrentNode(KisNodeSP node)
{
    m_d->currentNode = node;

    KisPaintDeviceSP device;
    if(m_d->currentNode && (device = m_d->currentNode->paintDevice())) {
        m_d->compositeOp = device->colorSpace()->compositeOp(m_d->compositeOpId);
        if(!m_d->compositeOp) {
            m_d->compositeOp = device->colorSpace()->compositeOp(COMPOSITE_OVER);
        }
    }
}
Пример #13
0
void KisUniformColorSource::colorize(KisPaintDeviceSP dev, const QRect& size)
{
    Q_UNUSED(size);
    if (!m_cachedColor || !(*dev->colorSpace() == *m_cachedColor->colorSpace())) {
        if (m_cachedColor) delete m_cachedColor;
        m_cachedColor = new KoColor(dev->colorSpace());
        m_cachedColor->fromKoColor(*m_color);
    }

    dev->dataManager()->setDefaultPixel(m_cachedColor->data());
    dev->clear();
}
Пример #14
0
KisPaintDeviceSP createDevice()
{
    const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8();
    KisPaintDeviceSP dev = new KisPaintDevice(cs);
    KisFillPainter gc(dev);
    KoColor c(Qt::red, dev->colorSpace());
    gc.fillRect(0, 0, 100, 100, c);
    c = KoColor(Qt::blue, dev->colorSpace());
    gc.fillRect(100, 0, 100, 100, c);
    gc.end();

    return dev;
}
Пример #15
0
KisPaintDeviceSP KisShearVisitor::yShear(KisPaintDeviceSP src, qreal shearY, KoUpdater *progress)
{
    int start = progress->progress();

    KisPaintDeviceSP dst = KisPaintDeviceSP(new KisPaintDevice(src->colorSpace()));
    KoMixColorsOp * mixOp = src->colorSpace()->mixColorsOp();

    dst->setX(src->x());
    dst->setY(src->y());

    QRect r = src->exactBounds();

    qreal displacement;
    qint32 displacementInt;
    qreal weight;

    for (qint32 x = r.left(); x <= r.right(); x++) {

        //calculate displacement
        displacement = x * shearY;

        displacementInt = (qint32)(floor(displacement));
        weight = displacement - displacementInt;

        qint16 pixelWeights[2];

        pixelWeights[0] = static_cast<quint8>(weight * 255 + 0.5);
        pixelWeights[1] = 255 - pixelWeights[0];

        KisVLineConstIteratorPixel srcIt = src->createVLineIterator(x, r.y(), r.height() + 1);
        KisVLineIteratorPixel leftSrcIt = src->createVLineIterator(x, r.y() - 1, r.height() + 1);
        KisVLineIteratorPixel dstIt = dst->createVLineIterator(x, r.y() + displacementInt, r.height() + 1);

        while (!srcIt.isDone()) {

            const quint8 *pixelPtrs[2];

            pixelPtrs[0] = leftSrcIt.rawData();
            pixelPtrs[1] = srcIt.rawData();

            mixOp->mixColors(pixelPtrs, pixelWeights, 2, dstIt.rawData());

            ++srcIt;
            ++leftSrcIt;
            ++dstIt;
        }
        progress->setProgress(start + x);
    }
    return dst;
}
Пример #16
0
KisPaintDeviceSP KisShearVisitor::xShear(KisPaintDeviceSP src, qreal shearX, KoUpdater *progress)
{
    KisPaintDeviceSP dst = KisPaintDeviceSP(new KisPaintDevice(src->colorSpace()));
    dst->setX(src->x());
    dst->setY(src->y());

    QRect r = src->exactBounds();

    qreal displacement;
    qint32 displacementInt;
    qreal weight;

    KoMixColorsOp * mixOp = src->colorSpace()->mixColorsOp();

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

        //calculate displacement
        displacement = -y * shearX;

        displacementInt = (qint32)(floor(displacement));
        weight = displacement - displacementInt;

        qint16 pixelWeights[2];

        pixelWeights[0] = static_cast<quint8>(weight * 255 + 0.5);
        pixelWeights[1] = 255 - pixelWeights[0];

        KisHLineConstIteratorPixel srcIt = src->createHLineIterator(r.x(), y, r.width() + 1);
        KisHLineConstIteratorPixel leftSrcIt = src->createHLineIterator(r.x() - 1, y, r.width() + 1);
        KisHLineIteratorPixel dstIt = dst->createHLineIterator(r.x() + displacementInt, y, r.width() + 1);

        while (!srcIt.isDone()) {

            const quint8 *pixelPtrs[2];

            pixelPtrs[0] = leftSrcIt.rawData();
            pixelPtrs[1] = srcIt.rawData();

            mixOp->mixColors(pixelPtrs, pixelWeights, 2, dstIt.rawData());

            ++srcIt;
            ++leftSrcIt;
            ++dstIt;
        }
        progress->setProgress(y);

    }
    return dst;
}
Пример #17
0
void KisBrushOp::paintAt(const KisPaintInformation& info)
{
    if (!painter()->device()) return;

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

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

    KisPaintDeviceSP device = painter()->device();

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

    quint8 origOpacity = settings->m_optionsWidget->m_opacityOption->apply(painter(), info.pressure());
    KoColor origColor = settings->m_optionsWidget->m_darkenOption->apply(painter(), info.pressure());

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

    KisFixedPaintDeviceSP dab = cachedDab(device->colorSpace());
    if (brush->brushType() == IMAGE || brush->brushType() == PIPE_IMAGE) {
        dab = brush->image(device->colorSpace(), scale, 0.0, adjustedInfo, xFraction, yFraction);
    } else {
        KoColor color = painter()->paintColor();
        color.convertTo(dab->colorSpace());
        brush->mask(dab, color, scale, scale, 0.0, info, xFraction, yFraction);
    }

    painter()->bltFixed(QPoint(x, y), dab, dab->bounds());
    painter()->setOpacity(origOpacity);
    painter()->setPaintColor(origColor);

}
Пример #18
0
    QVector<QPoint> splitIntoConnectedComponents(KisPaintDeviceSP dev,
                                                 const QRect &boundingRect)
{
    QVector<QPoint> points;
    const KoColorSpace *cs = dev->colorSpace();

    const QRect rect = dev->exactBounds() & boundingRect;
    if (rect.isEmpty()) return points;

    /**
     * Please note that since we modify the device inside
     * clearNonZeroComponent() call, we must use a *writable*
     * iterator, for not ending up with a lazy copied old version of a
     * device.
     */
    KisSequentialIterator dstIt(dev, rect);

    do {
        if (cs->opacityU8(dstIt.rawData()) > 0) {
            const QPoint pt(dstIt.x(), dstIt.y());
            points << pt;

            KisScanlineFill fill(dev, pt, rect);
            fill.clearNonZeroComponent();
        }
    } while (dstIt.nextPixel());

    return points;
}
Пример #19
0
void KisCubismFilter::process(KisConstProcessingInformation srcInfo,
                              KisProcessingInformation dstInfo,
                              const QSize& size,
                              const KisFilterConfiguration* configuration,
                              KoUpdater* progressUpdater
                             ) const
{
    Q_UNUSED(progressUpdater);

    const KisPaintDeviceSP src = srcInfo.paintDevice();
    KisPaintDeviceSP dst = dstInfo.paintDevice();
    QPoint dstTopLeft = dstInfo.topLeft();
    QPoint srcTopLeft = srcInfo.topLeft();
    Q_ASSERT(src);
    Q_ASSERT(dst);
    Q_ASSERT(configuration);

    //read the filter configuration values from the KisFilterConfiguration object
    quint32 tileSize = configuration->getInt("tileSize", 1);
    quint32 tileSaturation = configuration->getInt("tileSaturation");

    if (srcInfo.selection()) {

        KisPaintDeviceSP dev = new KisPaintDevice(src->colorSpace());

        cubism(src, srcTopLeft, dev, dstTopLeft, size, tileSize, tileSaturation);

        KisPainter gc(dst);
        gc.setSelection(srcInfo.selection());
        gc.bitBlt(dstTopLeft.x(), dstTopLeft.y(), dev, dstTopLeft.x(), dstTopLeft.y(), size.width(), size.height());
        gc.end();
    } else {
        cubism(src, srcTopLeft, dst, dstTopLeft, size, tileSize, tileSaturation);
    }
}
Пример #20
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];
}
Пример #21
0
void KisConvolutionPainterTest::testGaussianBase(KisPaintDeviceSP dev, bool useFftw, const QString &prefix)
{
   QBitArray channelFlags =
       KoColorSpaceRegistry::instance()->rgb8()->channelFlags(true, true);

   KisPainter gc(dev);


   qreal horizontalRadius = 5, verticalRadius = 5;

   for(int i = 0; i < 3 ; i++, horizontalRadius+=5, verticalRadius+=5)
   {
       QTime timer;
       timer.start();

       gc.beginTransaction();

       if (( horizontalRadius > 0 ) && ( verticalRadius > 0 )) {
           KisPaintDeviceSP interm = new KisPaintDevice(dev->colorSpace());

           KisConvolutionKernelSP kernelHoriz = KisGaussianKernel::createHorizontalKernel(horizontalRadius);
           KisConvolutionKernelSP kernelVertical = KisGaussianKernel::createVerticalKernel(verticalRadius);

           const QRect applyRect = dev->exactBounds();

           KisConvolutionPainter::TestingEnginePreference enginePreference =
               useFftw ?
               KisConvolutionPainter::FFTW :
               KisConvolutionPainter::SPATIAL;

           KisConvolutionPainter horizPainter(interm, enginePreference);
           horizPainter.setChannelFlags(channelFlags);
           horizPainter.applyMatrix(kernelHoriz, dev,
                                    applyRect.topLeft() - QPoint(0, verticalRadius),
                                    applyRect.topLeft() - QPoint(0, verticalRadius),
                                    applyRect.size() + QSize(0, 2 * verticalRadius),
                                    BORDER_REPEAT);

           KisConvolutionPainter verticalPainter(dev, enginePreference);
           verticalPainter.setChannelFlags(channelFlags);
           verticalPainter.applyMatrix(kernelVertical, interm,
                                       applyRect.topLeft(),
                                       applyRect.topLeft(),
                                       applyRect.size(), BORDER_REPEAT);

           QImage result = dev->convertToQImage(0, applyRect.x(), applyRect.y(), applyRect.width(), applyRect.height());

           QString engine = useFftw ? "fftw" : "spatial";
           QString testCaseName = QString("test_gaussian_%1_%2_%3.png").arg(horizontalRadius).arg(verticalRadius).arg(engine);

           TestUtil::checkQImage(result,
                                 "convolution_painter_test",
                                 QString("gaussian_") + prefix,
                                 testCaseName);

           gc.revertTransaction();
       }
       dbgKrita << "Elapsed time:" << timer.elapsed() << "ms";
    }
}
Пример #22
0
quint8 KisPressureRateOption::apply( quint8 opacity, qint32 sw,  qint32 sh, KisPaintDeviceSP srcdev, double pressure) const
{
    opacity = rate();

    if (isChecked()) {
        if (customCurve()) {
            opacity = qBound((qint32)OPACITY_TRANSPARENT, 
                             (qint32)(double(opacity) * scaleToCurve(pressure) / PRESSURE_DEFAULT),
                             (qint32)OPACITY_OPAQUE);

        } else {
            opacity = qBound((qint32)OPACITY_TRANSPARENT,
                             (qint32)(double(opacity) * pressure / PRESSURE_DEFAULT),
                             (qint32)OPACITY_OPAQUE);
        }
    }

#if 0
    // TODO It's also applied in the smudgeop, do other paintops that require a rate
    // needs to do this to their srcDev ?
    KisRectIterator it = srcdev->createRectIterator(0, 0, sw, sh);
    KoColorSpace* cs = srcdev->colorSpace();

    while (not it.isDone()) {
        cs->setAlpha(it.rawData(), (cs->alpha(it.rawData()) * opacity) / OPACITY_OPAQUE, 1);
        ++it;
    }
    return OPACITY_OPAQUE - opacity;
#else
    return opacity;
#endif


}
Пример #23
0
void KisFillPainterTest::benchmarkFillingScanlineColor()
{
    const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8();
    KisPaintDeviceSP dev = new KisPaintDevice(cs);

    QImage srcImage(TestUtil::fetchDataFileLazy("heavy_labyrinth.png"));
    QVERIFY(!srcImage.isNull());

    QRect imageRect = srcImage.rect();

    dev->convertFromQImage(srcImage, 0, 0, 0);


    QBENCHMARK_ONCE {
        KisScanlineFill gc(dev, QPoint(), imageRect);
        gc.setThreshold(THRESHOLD);
        gc.fillColor(KoColor(Qt::red, dev->colorSpace()));
    }

    QImage resultImage =
        dev->convertToQImage(0,
                             imageRect.x(), imageRect.y(),
                             imageRect.width(), imageRect.height());

    QVERIFY(TestUtil::checkQImage(resultImage,
                                  "fill_painter",
                                  "scanline_",
                                  "heavy_labyrinth_top_left"));
}
void KisConvolutionFilter::process(KisPaintDeviceSP device,
                                  const QRect& applyRect,
                                  const KisFilterConfiguration* config,
                                  KoUpdater* progressUpdater) const
{
    Q_UNUSED(config);

    QPoint srcTopLeft = applyRect.topLeft();
    Q_ASSERT(device != 0);

    KisConvolutionPainter painter(device);

    QBitArray channelFlags;
    if (config) {
        channelFlags = config->channelFlags();
    }
    if (channelFlags.isEmpty() || !config) {
        channelFlags = QBitArray(device->colorSpace()->channelCount(), true);
    }
 
    painter.setChannelFlags(channelFlags);
    painter.setProgress(progressUpdater);
    painter.applyMatrix(m_matrix, device, srcTopLeft, srcTopLeft, applyRect.size(), BORDER_REPEAT);

}
void KisFilterStrokeStrategy::initStrokeCallback()
{
    KisPainterBasedStrokeStrategy::initStrokeCallback();

    KisPaintDeviceSP dev = targetDevice();

    if (activeSelection() ||
        (dev->colorSpace() != dev->compositionSourceColorSpace() &&
         !(dev->colorSpace() == dev->compositionSourceColorSpace()))) {

        m_d->filterDevice = dev->createCompositionSourceDevice(dev);
        m_d->secondaryTransaction = new KisTransaction("", m_d->filterDevice);
    } else {
        m_d->filterDevice = dev;
    }
}
void KisConvolutionFilter::process(KisConstProcessingInformation srcInfo,
                                   KisProcessingInformation dstInfo,
                                   const QSize& size,
                                   const KisFilterConfiguration* config,
                                   KoUpdater* progressUpdater
                                  ) const
{
    Q_UNUSED(config);

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

    KisConvolutionPainter painter(dst, dstInfo.selection());

    QBitArray channelFlags;
    if (config) {
        channelFlags = config->channelFlags();
    }
    if (channelFlags.isEmpty() || !config) {
        channelFlags = QBitArray(src->colorSpace()->channelCount(), true);
    }
 
    // disable alpha channel
    channelFlags.clearBit(1);

    painter.setChannelFlags(channelFlags);
    painter.setProgress(progressUpdater);
    painter.applyMatrix(m_matrix, src, srcTopLeft, dstTopLeft, size, BORDER_REPEAT);

}
Пример #27
0
void KisFeatherSelectionFilter::process(KisPixelSelectionSP pixelSelection, const QRect& rect)
{
    // compute horizontal kernel
    const uint kernelSize = m_radius * 2 + 1;
    Matrix<qreal, Dynamic, Dynamic> gaussianMatrix(1, kernelSize);

    const qreal multiplicand = 1 / (2 * M_PI * m_radius * m_radius);
    const qreal exponentMultiplicand = 1 / (2 * m_radius * m_radius);

    for (uint x = 0; x < kernelSize; x++) {
        uint xDistance = qAbs((int)m_radius - (int)x);
        gaussianMatrix(0, x) = multiplicand * exp( -(qreal)((xDistance * xDistance) + (m_radius * m_radius)) * exponentMultiplicand );
    }

    KisConvolutionKernelSP kernelHoriz = KisConvolutionKernel::fromMatrix(gaussianMatrix, 0, gaussianMatrix.sum());
    KisConvolutionKernelSP kernelVertical = KisConvolutionKernel::fromMatrix(gaussianMatrix.transpose(), 0, gaussianMatrix.sum());

    KisPaintDeviceSP interm = new KisPaintDevice(pixelSelection->colorSpace());
    KisConvolutionPainter horizPainter(interm);
    horizPainter.setChannelFlags(interm->colorSpace()->channelFlags(false, true));
    horizPainter.applyMatrix(kernelHoriz, pixelSelection, rect.topLeft(), rect.topLeft(), rect.size(), BORDER_REPEAT);
    horizPainter.end();

    KisConvolutionPainter verticalPainter(pixelSelection);
    verticalPainter.setChannelFlags(pixelSelection->colorSpace()->channelFlags(false, true));
    verticalPainter.applyMatrix(kernelVertical, interm, rect.topLeft(), rect.topLeft(), rect.size(), BORDER_REPEAT);
    verticalPainter.end();
}
Пример #28
0
void KisBidirectionalMixingOption::apply(KisPaintDeviceSP dab, KisPaintDeviceSP device, KisPainter* painter, qint32 sx, qint32 sy, qint32 sw, qint32 sh, quint8 pressure, const QRect& dstRect)
{
    if (!isChecked()) return;

    KoColorSpace *cs = dab->colorSpace();
    KisPaintDeviceSP canvas = new KisPaintDevice(cs);
    KisPainter p(canvas);
    p.setCompositeOp(COMPOSITE_COPY);
    p.bitBlt(sx, sy, device, dstRect.x(), dstRect.y(), sw, sh);

    int count = cs->channelCount();
    KisRectIterator cit = canvas->createRectIterator(sx, sy, sw, sh);
    KisRectIterator dit = dab->createRectIterator(sx, sy, sw, sh);
    QVector<float> cc(count), dc(count);
    while (!cit.isDone()) {
        if (cs->alpha(dit.rawData()) > 10 && cs->alpha(cit.rawData()) > 10) {
            cs->normalisedChannelsValue(cit.rawData(), cc);
            cs->normalisedChannelsValue(dit.rawData(), dc);
            for (int i = 0; i < count; i++)
                dc[i] = (1.0 - 0.4 * pressure) * cc[i] + 0.4 * pressure * dc[i];
            cs->fromNormalisedChannelsValue(dit.rawData(), dc);
            if (dit.x() == (int)(sw / 2) && dit.y() == (int)(sh / 2))
                painter->setPaintColor(KoColor(dit.rawData(), cs));
        }
        ++cit;
        ++dit;
    }
}
Пример #29
0
void SprayBrush::paintDistanceMap(KisPaintDeviceSP dev, const KisPaintInformation &info, const KoColor &painterColor){
    KisRandomAccessor accessor = dev->createRandomAccessor(0, 0);
    KoColor color = painterColor;

    qreal posX = info.pos().x();
    qreal posY = info.pos().y();
    
    qreal opacity = 255;
    for (int y = -m_radius; y <= m_radius; y++){
        for (int x = -m_radius; x <= m_radius; x++){
            //opacity = sqrt(y*y + x*x) / m_radius;
            opacity = (y*y + x*x) / (m_radius * m_radius);
            opacity = 1.0 - opacity;
            opacity *= m_scale;

            if (opacity < 0) continue;
            if (opacity > 1.0) opacity = 1.0;

            if ( (y*y + x*x) <= (m_radius * m_radius) )
            {
                color.setOpacity( opacity * 255);
                accessor.moveTo(x + posX, y + posY);
                memcpy( accessor.rawData(), color.data(), dev->colorSpace()->pixelSize() );
            }

        }
    }
}
Пример #30
0
void ChalkBrush::paint(KisPaintDeviceSP dev, qreal x, qreal y, const KoColor &color)
{

    m_inkColor = color;
    m_counter++;
    qreal decr = (m_counter * m_counter * m_counter) / 1000000.0f;

    Bristle *bristle;

    qint32 pixelSize = dev->colorSpace()->pixelSize();
    KisRandomAccessor accessor = dev->createRandomAccessor((int)x, (int)y);

    qreal dirt, result;

    //count decrementing of saturation and alpha
    result = log( ( qreal )m_counter);
    result = -(result * 10) / 100.0;

    QHash<QString, QVariant> params;
    params["h"] = 0.0;
    params["s"] = result;
    params["v"] = 0.0;

    KoColorTransformation* transfo = dev->colorSpace()->createColorTransformation("hsv_adjustment", params);
    transfo->transform(m_inkColor.data(), m_inkColor.data(), 1);

    int opacity = static_cast<int>((1.0f + result) * 255.0);
    m_inkColor.setOpacity(opacity);

    for (int i = 0;i < m_bristles.size();i++) {
        bristle = &m_bristles[i];

        // let's call that noise from ground to chalk :)
        dirt = drand48();
        if (bristle->distanceCenter() > m_radius || dirt < 0.5) {
            continue;
        }

        int dx, dy;
        dx = (int)(x + bristle->x());
        dy = (int)(y + bristle->y());

        accessor.moveTo(dx, dy);
        memcpy(accessor.rawData(), m_inkColor.data(), pixelSize);
        bristle->setInkAmount(1.0f - decr);
    }
}