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