void KisSmallTilesFilter::processImpl(KisPaintDeviceSP device, const QRect& /*applyRect*/, const KisFilterConfiguration* config, KoUpdater* progressUpdater ) const { Q_ASSERT(!device.isNull()); //read the filter configuration values from the KisFilterConfiguration object quint32 numberOfTiles = config->getInt("numberOfTiles", 2); QRect srcRect = device->exactBounds(); int w = static_cast<int>(srcRect.width() / numberOfTiles); int h = static_cast<int>(srcRect.height() / numberOfTiles); KisPaintDeviceSP tile = device->createThumbnailDevice(srcRect.width() / numberOfTiles, srcRect.height() / numberOfTiles); if (tile.isNull()) return; KisPainter gc(device); gc.setCompositeOp(COMPOSITE_COPY); if (progressUpdater) { progressUpdater->setRange(0, numberOfTiles); } for (uint y = 0; y < numberOfTiles; ++y) { for (uint x = 0; x < numberOfTiles; ++x) { gc.bitBlt(w * x, h * y, tile, 0, 0, w, h); } if (progressUpdater) progressUpdater->setValue(y); } gc.end(); }
void KisSmallTilesFilter::process(KisConstProcessingInformation srcInfo, KisProcessingInformation dstInfo, const QSize& size, const KisFilterConfiguration* config, KoUpdater* progressUpdater ) const { const KisPaintDeviceSP src = srcInfo.paintDevice(); KisPaintDeviceSP dst = dstInfo.paintDevice(); QPoint dstTopLeft = dstInfo.topLeft(); QPoint srcTopLeft = srcInfo.topLeft(); Q_ASSERT(!src.isNull()); Q_ASSERT(!dst.isNull()); //read the filter configuration values from the KisFilterConfiguration object quint32 numberOfTiles = config->getInt("numberOfTiles", 2); QRect srcRect = src->exactBounds(); int w = static_cast<int>(srcRect.width() / numberOfTiles); int h = static_cast<int>(srcRect.height() / numberOfTiles); KisPaintDeviceSP tile = KisPaintDeviceSP(0); if (srcInfo.selection()) { KisPaintDeviceSP tmp = new KisPaintDevice(src->colorSpace()); KisPainter gc(tmp); gc.setCompositeOp(COMPOSITE_COPY); gc.bitBlt(0, 0, src, srcTopLeft.x(), srcTopLeft.y(), size.width(), size.height()); tile = tmp->createThumbnailDevice(srcRect.width() / numberOfTiles, srcRect.height() / numberOfTiles); } else { tile = src->createThumbnailDevice(srcRect.width() / numberOfTiles, srcRect.height() / numberOfTiles); } if (tile.isNull()) return; KisPainter gc(dst); gc.setCompositeOp(COMPOSITE_COPY); if (progressUpdater) { progressUpdater->setRange(0, numberOfTiles); } if (srcInfo.selection()) { gc.setSelection(srcInfo.selection()); } for (uint y = 0; y < numberOfTiles; ++y) { for (uint x = 0; x < numberOfTiles; ++x) { gc.bitBlt(w * x, h * y, tile, 0, 0, w, h); } if (progressUpdater) progressUpdater->setValue(y); } gc.end(); }
void ShivaGenerator::generate(KisProcessingInformation dstInfo, const QSize& size, const KisFilterConfiguration* config, KoUpdater* progressUpdater) const { Q_UNUSED(progressUpdater); KisPaintDeviceSP dst = dstInfo.paintDevice(); QPoint dstTopLeft = dstInfo.topLeft(); UpdaterProgressReport* report = 0; if (progressUpdater) { progressUpdater->setRange(0, size.height()); report = new UpdaterProgressReport(progressUpdater); } Q_ASSERT(!dst.isNull()); // Q_ASSERT(config); // TODO implement the generating of pixel OpenShiva::Kernel kernel; kernel.setSource(*m_source); if (config) { QMap<QString, QVariant> map = config->getProperties(); for (QMap<QString, QVariant>::iterator it = map.begin(); it != map.end(); ++it) { const GTLCore::Metadata::Entry* entry = kernel.metadata()->parameter(it.key().toAscii().data()); if (entry && entry->asParameterEntry()) { #if OPENSHIVA_12 GTLCore::Value val = qvariantToValue(it.value(), entry->asParameterEntry()->valueType()); #else GTLCore::Value val = qvariantToValue(it.value(), entry->asParameterEntry()->type()); #endif if(val.isValid()) { kernel.setParameter(it.key().toAscii().data(), val); } } } } { QMutexLocker l(shivaMutex); kernel.compile(); } if (kernel.isCompiled()) { PaintDeviceImage pdi(dst); #if OPENSHIVA_12 std::list< GTLCore::AbstractImage* > inputs; GTLCore::Region region(dstTopLeft.x(), dstTopLeft.y() , size.width(), size.height()); kernel.evaluatePixeles(region, inputs, &pdi, report ); #else std::list< const GTLCore::AbstractImage* > inputs; GTLCore::RegionI region(dstTopLeft.x(), dstTopLeft.y() , size.width(), size.height()); kernel.evaluatePixels(region, inputs, &pdi, report ); #endif } #if OPENSHIVA_13_OR_MORE else { dbgPlugins << "Error: " << kernel.compilationMessages().toString().c_str(); } #endif }
void KoPatternGenerator::generate(KisProcessingInformation dstInfo, const QSize& size, const KisFilterConfiguration* config, KoUpdater* progressUpdater) const { KisPaintDeviceSP dst = dstInfo.paintDevice(); Q_ASSERT(!dst.isNull()); Q_ASSERT(config); if (!config) return; QString patternName = config->getString("pattern", "Grid01.pat"); KoResourceServer<KoPattern> *rserver = KoResourceServerProvider::instance()->patternServer(); KoPattern *pattern = rserver->resourceByName(patternName); // KoColor c = config->getColor("color"); KisFillPainter gc(dst); gc.setPattern(pattern); // gc.setPaintColor(c); gc.setProgress(progressUpdater); gc.setChannelFlags(config->channelFlags()); gc.setOpacity(OPACITY_OPAQUE_U8); gc.setSelection(dstInfo.selection()); gc.setWidth(size.width()); gc.setHeight(size.height()); gc.setFillStyle(KisFillPainter::FillStylePattern); gc.fillRect(QRect(dstInfo.topLeft(), size), pattern); gc.end(); }
void KisFilterRandomPick::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const { Q_UNUSED(config); Q_ASSERT(!device.isNull()); if (progressUpdater) { progressUpdater->setRange(0, applyRect.width() * applyRect.height()); } int count = 0; const KoColorSpace * cs = device->colorSpace(); QVariant value; int level = (config && config->getProperty("level", value)) ? value.toInt() : 50; int opacity = (config && config->getProperty("opacity", value)) ? value.toInt() : 100; double windowsize = (config && config->getProperty("windowsize", value)) ? value.toDouble() : 2.5; int seedThreshold = rand(); int seedH = rand(); int seedV = rand(); if (config) { seedThreshold = config->getInt("seedThreshold", seedThreshold); seedH = config->getInt("seedH", seedH); seedV = config->getInt("seedV", seedV); } KisRandomGenerator randT(seedThreshold); KisRandomGenerator randH(seedH); KisRandomGenerator randV(seedV); KisSequentialIterator dstIt(device, applyRect); KisRandomConstAccessorSP srcRA = device->createRandomConstAccessorNG(0, 0); double threshold = (100 - level) / 100.0; qint16 weights[2]; weights[0] = (255 * opacity) / 100; weights[1] = 255 - weights[0]; const quint8* pixels[2]; KoMixColorsOp * mixOp = cs->mixColorsOp(); do{ if (randT.doubleRandomAt(dstIt.x(), dstIt.y()) > threshold) { int x = static_cast<int>(dstIt.x() + windowsize * (randH.doubleRandomAt(dstIt.x(), dstIt.y()) - 0.5)); int y = static_cast<int>(dstIt.y() + windowsize * (randV.doubleRandomAt(dstIt.x(), dstIt.y()) -0.5)); srcRA->moveTo(x, y); pixels[0] = srcRA->oldRawData(); pixels[1] = dstIt.oldRawData(); mixOp->mixColors(pixels, weights, 2, dstIt.rawData()); } if (progressUpdater) progressUpdater->setValue(++count); } while(dstIt.nextPixel()); }
// gmic assumes float rgba in 0.0 - 255.0, thus default value void KisGmicSimpleConvertor::convertToGmicImage(KisPaintDeviceSP dev, gmic_image<float>& gmicImage, QRect rc) { Q_ASSERT(!dev.isNull()); Q_ASSERT(gmicImage._spectrum == 4); // rgba if (rc.isEmpty()) { rc = QRect(0,0,gmicImage._width, gmicImage._height); } const KoColorSpace *rgbaFloat32bitcolorSpace = KoColorSpaceRegistry::instance()->colorSpace(RGBAColorModelID.id(), Float32BitsColorDepthID.id(), KoColorSpaceRegistry::instance()->rgb8()->profile()); Q_CHECK_PTR(rgbaFloat32bitcolorSpace); int greenOffset = gmicImage._width * gmicImage._height; int blueOffset = greenOffset * 2; int alphaOffset = greenOffset * 3; KoColorConversionTransformation::Intent renderingIntent = KoColorConversionTransformation::internalRenderingIntent(); KoColorConversionTransformation::ConversionFlags conversionFlags = KoColorConversionTransformation::internalConversionFlags(); const KoColorSpace * colorSpace = dev->colorSpace(); KisRandomConstAccessorSP it = dev->createRandomConstAccessorNG(0,0); int optimalBufferSize = 64; // most common numContiguousColumns, tile size? quint8 * floatRGBApixel = new quint8[rgbaFloat32bitcolorSpace->pixelSize() * optimalBufferSize]; quint32 pixelSize = rgbaFloat32bitcolorSpace->pixelSize(); int pos = 0; for (int y = 0; y < rc.height(); y++) { int x = 0; while (x < rc.width()) { it->moveTo(x, y); qint32 numContiguousColumns = qMin(it->numContiguousColumns(x), optimalBufferSize); numContiguousColumns = qMin(numContiguousColumns, rc.width() - x); colorSpace->convertPixelsTo(it->rawDataConst(), floatRGBApixel, rgbaFloat32bitcolorSpace, numContiguousColumns, renderingIntent, conversionFlags); pos = y * gmicImage._width + x; for (qint32 bx = 0; bx < numContiguousColumns; bx++) { memcpy(gmicImage._data + pos ,floatRGBApixel + bx * pixelSize , 4); memcpy(gmicImage._data + pos + greenOffset ,floatRGBApixel + bx * pixelSize + 4, 4); memcpy(gmicImage._data + pos + blueOffset ,floatRGBApixel + bx * pixelSize + 8, 4); memcpy(gmicImage._data + pos + alphaOffset ,floatRGBApixel + bx * pixelSize + 12, 4); pos++; } x += numContiguousColumns; } } delete [] floatRGBApixel; }
void ShivaFilter::processImpl(KisPaintDeviceSP dev, const QRect& size, const KisFilterConfiguration* config, KoUpdater* progressUpdater ) const { Q_UNUSED(progressUpdater); QPoint dstTopLeft = size.topLeft(); UpdaterProgressReport* report = 0; if (progressUpdater) { progressUpdater->setRange(0, size.height()); report = new UpdaterProgressReport(progressUpdater); } Q_ASSERT(!dev.isNull()); // Q_ASSERT(config); // TODO support for selection OpenShiva::Kernel kernel; kernel.setSource(*m_source); if (config) { QMap<QString, QVariant> map = config->getProperties(); for (QMap<QString, QVariant>::iterator it = map.begin(); it != map.end(); ++it) { dbgPlugins << it.key() << " " << it.value(); const GTLCore::Metadata::Entry* entry = kernel.metadata()->parameter(it.key().toLatin1().constData()); if (entry && entry->asParameterEntry()) { GTLCore::Value val = qvariantToValue(it.value(), entry->asParameterEntry()->type()); if(val.isValid()) { kernel.setParameter(it.key().toLatin1().constData(), val); } } } } kernel.setParameter(OpenShiva::Kernel::IMAGE_WIDTH, float(dev->defaultBounds()->bounds().width())); kernel.setParameter(OpenShiva::Kernel::IMAGE_HEIGHT, float(dev->defaultBounds()->bounds().height())); KisGtlLocker gtlLocker; { dbgPlugins << "Compile: " << m_source->name().c_str(); QMutexLocker l(shivaMutex); kernel.compile(); } if (kernel.isCompiled()) { ConstPaintDeviceImage pdisrc(dev); PaintDeviceImage pdi(dev); std::list< const GTLCore::AbstractImage* > inputs; GTLCore::RegionI region(dstTopLeft.x(), dstTopLeft.y() , size.width(), size.height()); inputs.push_back(&pdisrc); dbgPlugins << "Run: " << m_source->name().c_str() << " " << dstTopLeft << " " << size; kernel.evaluatePixels(region, inputs, &pdi, report ); } }
void KisOilPaintFilter::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfiguration* config, KoUpdater* progressUpdater ) const { QPoint srcTopLeft = applyRect.topLeft(); Q_ASSERT(!device.isNull()); qint32 width = applyRect.width(); qint32 height = applyRect.height(); //read the filter configuration values from the KisFilterConfiguration object quint32 brushSize = config ? config->getInt("brushSize", 1) : 1; quint32 smooth = config ? config->getInt("smooth", 30) : 30; OilPaint(device, device, srcTopLeft, applyRect.topLeft(), width, height, brushSize, smooth, progressUpdater); }
void KisGmicSimpleConvertor::convertFromGmicImage(gmic_image<float>& gmicImage, KisPaintDeviceSP dst, float gmicMaxChannelValue) { Q_ASSERT(!dst.isNull()); const KoColorSpace *rgbaFloat32bitcolorSpace = KoColorSpaceRegistry::instance()->colorSpace(RGBAColorModelID.id(), Float32BitsColorDepthID.id(), KoColorSpaceRegistry::instance()->rgb8()->profile()); const KoColorSpace *dstColorSpace = dst->colorSpace(); if (dstColorSpace == 0) { dstColorSpace = rgbaFloat32bitcolorSpace; } KisPaintDeviceSP dev = dst; int greenOffset = gmicImage._width * gmicImage._height; int blueOffset = greenOffset * 2; int alphaOffset = greenOffset * 3; QRect rc(0,0,gmicImage._width, gmicImage._height); KisRandomAccessorSP it = dev->createRandomAccessorNG(0,0); int pos; float r,g,b,a; int optimalBufferSize = 64; // most common numContiguousColumns, tile size? quint8 * floatRGBApixel = new quint8[rgbaFloat32bitcolorSpace->pixelSize() * optimalBufferSize]; quint32 pixelSize = rgbaFloat32bitcolorSpace->pixelSize(); KoColorConversionTransformation::Intent renderingIntent = KoColorConversionTransformation::internalRenderingIntent(); KoColorConversionTransformation::ConversionFlags conversionFlags = KoColorConversionTransformation::internalConversionFlags(); // Krita needs rgba in 0.0...1.0 float multiplied = KoColorSpaceMathsTraits<float>::unitValue / gmicMaxChannelValue; switch (gmicImage._spectrum) { case 1: { // convert grayscale to rgba for (int y = 0; y < rc.height(); y++) { int x = 0; while (x < rc.width()) { it->moveTo(x, y); qint32 numContiguousColumns = qMin(it->numContiguousColumns(x), optimalBufferSize); numContiguousColumns = qMin(numContiguousColumns, rc.width() - x); pos = y * gmicImage._width + x; for (qint32 bx = 0; bx < numContiguousColumns; bx++) { r = g = b = gmicImage._data[pos] * multiplied; a = KoColorSpaceMathsTraits<float>::unitValue; memcpy(floatRGBApixel + bx * pixelSize, &r,4); memcpy(floatRGBApixel + bx * pixelSize + 4, &g,4); memcpy(floatRGBApixel + bx * pixelSize + 8, &b,4); memcpy(floatRGBApixel + bx * pixelSize + 12, &a,4); pos++; } rgbaFloat32bitcolorSpace->convertPixelsTo(floatRGBApixel, it->rawData(), dstColorSpace, numContiguousColumns,renderingIntent, conversionFlags); x += numContiguousColumns; } } break; } case 2: { // convert grayscale alpha to rgba for (int y = 0; y < rc.height(); y++) { int x = 0; while (x < rc.width()) { it->moveTo(x, y); qint32 numContiguousColumns = qMin(it->numContiguousColumns(x), optimalBufferSize); numContiguousColumns = qMin(numContiguousColumns, rc.width() - x); pos = y * gmicImage._width + x; for (qint32 bx = 0; bx < numContiguousColumns; bx++) { r = g = b = gmicImage._data[pos] * multiplied; a = gmicImage._data[pos + greenOffset] * multiplied; memcpy(floatRGBApixel + bx * pixelSize, &r,4); memcpy(floatRGBApixel + bx * pixelSize + 4, &g,4); memcpy(floatRGBApixel + bx * pixelSize + 8, &b,4); memcpy(floatRGBApixel + bx * pixelSize + 12, &a,4); pos++; } rgbaFloat32bitcolorSpace->convertPixelsTo(floatRGBApixel, it->rawData(), dstColorSpace, numContiguousColumns,renderingIntent, conversionFlags); x += numContiguousColumns; } } break; } case 3: { // convert rgb -> rgba for (int y = 0; y < rc.height(); y++) { int x = 0; while (x < rc.width()) { it->moveTo(x, y); qint32 numContiguousColumns = qMin(it->numContiguousColumns(x), optimalBufferSize); numContiguousColumns = qMin(numContiguousColumns, rc.width() - x); pos = y * gmicImage._width + x; for (qint32 bx = 0; bx < numContiguousColumns; bx++) { r = gmicImage._data[pos] * multiplied; g = gmicImage._data[pos + greenOffset] * multiplied; b = gmicImage._data[pos + blueOffset ] * multiplied; a = gmicMaxChannelValue * multiplied; memcpy(floatRGBApixel + bx * pixelSize, &r,4); memcpy(floatRGBApixel + bx * pixelSize + 4, &g,4); memcpy(floatRGBApixel + bx * pixelSize + 8, &b,4); memcpy(floatRGBApixel + bx * pixelSize + 12, &a,4); pos++; } rgbaFloat32bitcolorSpace->convertPixelsTo(floatRGBApixel, it->rawData(), dstColorSpace, numContiguousColumns,renderingIntent, conversionFlags); x += numContiguousColumns; } } break; } case 4: { for (int y = 0; y < rc.height(); y++) { int x = 0; while (x < rc.width()) { it->moveTo(x, y); qint32 numContiguousColumns = qMin(it->numContiguousColumns(x), optimalBufferSize); numContiguousColumns = qMin(numContiguousColumns, rc.width() - x); pos = y * gmicImage._width + x; for (qint32 bx = 0; bx < numContiguousColumns; bx++) { r = gmicImage._data[pos] * multiplied; g = gmicImage._data[pos + greenOffset] * multiplied; b = gmicImage._data[pos + blueOffset ] * multiplied; a = gmicImage._data[pos + alphaOffset] * multiplied; memcpy(floatRGBApixel + bx * pixelSize, &r,4); memcpy(floatRGBApixel + bx * pixelSize + 4, &g,4); memcpy(floatRGBApixel + bx * pixelSize + 8, &b,4); memcpy(floatRGBApixel + bx * pixelSize + 12, &a,4); pos++; } rgbaFloat32bitcolorSpace->convertPixelsTo(floatRGBApixel, it->rawData(), dstColorSpace, numContiguousColumns,renderingIntent, conversionFlags); x += numContiguousColumns; } } break; } default: { dbgPlugins << "Unsupported gmic output format : " << gmicImage._width << gmicImage._height << gmicImage._depth << gmicImage._spectrum; } } }
void KisFilterNoise::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfiguration* config, KoUpdater* progressUpdater ) const { Q_ASSERT(!device.isNull()); if (progressUpdater) { progressUpdater->setRange(0, applyRect.width() * applyRect.height()); } int count = 0; const KoColorSpace * cs = device->colorSpace(); QVariant value; int level = (config && config->getProperty("level", value)) ? value.toInt() : 50; int opacity = (config && config->getProperty("opacity", value)) ? value.toInt() : 100; KisSequentialIterator it(device, applyRect); quint8* interm = new quint8[cs->pixelSize()]; double threshold = (100.0 - level) * 0.01; qint16 weights[2]; weights[0] = (255 * opacity) / 100; weights[1] = 255 - weights[0]; const quint8* pixels[2]; pixels[0] = interm; KoMixColorsOp * mixOp = cs->mixColorsOp(); int seedThreshold = rand(); int seedRed = rand(); int seedGreen = rand(); int seedBlue = rand(); if (config) { seedThreshold = config->getInt("seedThreshold", seedThreshold); seedRed = config->getInt("seedRed", seedRed); seedGreen = config->getInt("seedGreen", seedGreen); seedBlue = config->getInt("seedBlue", seedBlue); } KisRandomGenerator randt(seedThreshold); KisRandomGenerator randr(seedRed); KisRandomGenerator randg(seedGreen); KisRandomGenerator randb(seedBlue); do { if (randt.doubleRandomAt(it.x(), it.y()) > threshold) { // XXX: Added static_cast to get rid of warnings QColor c = qRgb(static_cast<int>((double)randr.doubleRandomAt(it.x(), it.y()) * 255), static_cast<int>((double)randg.doubleRandomAt(it.x(), it.y()) * 255), static_cast<int>((double)randb.doubleRandomAt(it.x(), it.y()) * 255)); cs->fromQColor(c, interm, 0); pixels[1] = it.oldRawData(); mixOp->mixColors(pixels, weights, 2, it.rawData()); } if (progressUpdater) progressUpdater->setValue(++count); } while (it.nextPixel() && !(progressUpdater && progressUpdater->interrupted())); delete [] interm; }
void KisRainDropsFilter::process(KisConstProcessingInformation srcInfo, KisProcessingInformation dstInfo, const QSize& size, const KisFilterConfiguration* config, KoUpdater* progressUpdater ) const { const KisPaintDeviceSP src = srcInfo.paintDevice(); KisPaintDeviceSP dst = dstInfo.paintDevice(); QPoint dstTopLeft = dstInfo.topLeft(); QPoint srcTopLeft = srcInfo.topLeft(); Q_UNUSED(config); Q_ASSERT(!src.isNull()); Q_ASSERT(!dst.isNull()); //read the filter configuration values from the KisFilterConfiguration object quint32 DropSize = config->getInt("dropSize", 80); quint32 number = config->getInt("number", 80); quint32 fishEyes = config->getInt("fishEyes", 30); if (progressUpdater) { progressUpdater->setRange(0, size.width() * size.height()); } int count = 0; if (fishEyes <= 0) fishEyes = 1; if (fishEyes > 100) fishEyes = 100; int Width = size.width(); int Height = size.height(); bool** BoolMatrix = CreateBoolArray(Width, Height); int i, j, k, l, m, n; // loop variables int Bright; // Bright value for shadows and highlights int x, y; // center coordinates int Counter = 0; // Counter (duh !) int NewSize; // Size of current raindrop int halfSize; // Half of the current raindrop int Radius; // Maximum radius for raindrop int BlurRadius; // Blur Radius int BlurPixels; double r, a; // polar coordinates double OldRadius; // Radius before processing double NewfishEyes = (double)fishEyes * 0.01; // FishEye fishEyesicients double s; double R, G, B; bool FindAnother = false; // To search for good coordinates const KoColorSpace * cs = src->colorSpace(); // XXX: move the seed to the config, so the filter can be used as // and adjustment filter (boud). // And use a thread-safe random number generator QDateTime dt = QDateTime::currentDateTime(); QDateTime Y2000(QDate(2000, 1, 1), QTime(0, 0, 0)); srand((uint) dt.secsTo(Y2000)); // Init booleen Matrix. for (i = 0 ; (i < Width) && !(progressUpdater && progressUpdater->interrupted()) ; ++i) { for (j = 0 ; (j < Height) && !(progressUpdater && progressUpdater->interrupted()); ++j) { BoolMatrix[i][j] = false; } } KisRandomAccessorSP dstAccessor = dst->createRandomAccessorNG(dstTopLeft.x(), dstTopLeft.y()); KisRandomConstAccessorSP srcAccessor = src->createRandomConstAccessorNG(dstTopLeft.x(), dstTopLeft.y()); for (uint NumBlurs = 0; (NumBlurs <= number) && !(progressUpdater && progressUpdater->interrupted()); ++NumBlurs) { NewSize = (int)(rand() * ((double)(DropSize - 5) / RAND_MAX) + 5); halfSize = NewSize / 2; Radius = halfSize; s = Radius / log(NewfishEyes * Radius + 1); Counter = 0; do { FindAnother = false; y = (int)(rand() * ((double)(Width - 1) / RAND_MAX)); x = (int)(rand() * ((double)(Height - 1) / RAND_MAX)); if (BoolMatrix[y][x]) FindAnother = true; else for (i = x - halfSize ; (i <= x + halfSize) && !(progressUpdater && progressUpdater->interrupted()); i++) for (j = y - halfSize ; (j <= y + halfSize) && !(progressUpdater && progressUpdater->interrupted()); j++) if ((i >= 0) && (i < Height) && (j >= 0) && (j < Width)) if (BoolMatrix[j][i]) FindAnother = true; Counter++; } while ((FindAnother && (Counter < 10000) && !(progressUpdater && progressUpdater->interrupted()))); if (Counter >= 10000) { NumBlurs = number; break; } for (i = -1 * halfSize ; (i < NewSize - halfSize) && !(progressUpdater && progressUpdater->interrupted()); i++) { for (j = -1 * halfSize ; (j < NewSize - halfSize) && !(progressUpdater && progressUpdater->interrupted()); j++) { r = sqrt(i * i + j * j); a = atan2(static_cast<double>(i), static_cast<double>(j)); if (r <= Radius) { OldRadius = r; r = (exp(r / s) - 1) / NewfishEyes; k = x + (int)(r * sin(a)); l = y + (int)(r * cos(a)); m = x + i; n = y + j; if ((k >= 0) && (k < Height) && (l >= 0) && (l < Width)) { if ((m >= 0) && (m < Height) && (n >= 0) && (n < Width)) { Bright = 0; if (OldRadius >= 0.9 * Radius) { if ((a <= 0) && (a > -2.25)) Bright = -80; else if ((a <= -2.25) && (a > -2.5)) Bright = -40; else if ((a <= 0.25) && (a > 0)) Bright = -40; } else if (OldRadius >= 0.8 * Radius) { if ((a <= -0.75) && (a > -1.50)) Bright = -40; else if ((a <= 0.10) && (a > -0.75)) Bright = -30; else if ((a <= -1.50) && (a > -2.35)) Bright = -30; } else if (OldRadius >= 0.7 * Radius) { if ((a <= -0.10) && (a > -2.0)) Bright = -20; else if ((a <= 2.50) && (a > 1.90)) Bright = 60; } else if (OldRadius >= 0.6 * Radius) { if ((a <= -0.50) && (a > -1.75)) Bright = -20; else if ((a <= 0) && (a > -0.25)) Bright = 20; else if ((a <= -2.0) && (a > -2.25)) Bright = 20; } else if (OldRadius >= 0.5 * Radius) { if ((a <= -0.25) && (a > -0.50)) Bright = 30; else if ((a <= -1.75) && (a > -2.0)) Bright = 30; } else if (OldRadius >= 0.4 * Radius) { if ((a <= -0.5) && (a > -1.75)) Bright = 40; } else if (OldRadius >= 0.3 * Radius) { if ((a <= 0) && (a > -2.25)) Bright = 30; } else if (OldRadius >= 0.2 * Radius) { if ((a <= -0.5) && (a > -1.75)) Bright = 20; } BoolMatrix[n][m] = true; QColor originalColor; srcAccessor->moveTo(srcTopLeft.x() + l, srcTopLeft.y() + k); cs->toQColor(srcAccessor->oldRawData(), &originalColor); int newRed = CLAMP(originalColor.red() + Bright, 0, quint8_MAX); int newGreen = CLAMP(originalColor.green() + Bright, 0, quint8_MAX); int newBlue = CLAMP(originalColor.blue() + Bright, 0, quint8_MAX); QColor newColor; newColor.setRgb(newRed, newGreen, newBlue); dstAccessor->moveTo(dstTopLeft.x() + n, dstTopLeft.y() + m); cs->fromQColor(newColor, dstAccessor->rawData()); } } } } } BlurRadius = NewSize / 25 + 1; for (i = -1 * halfSize - BlurRadius ; (i < NewSize - halfSize + BlurRadius) && !(progressUpdater && progressUpdater->interrupted()) ; i++) { for (j = -1 * halfSize - BlurRadius; ((j < NewSize - halfSize + BlurRadius) && !(progressUpdater && progressUpdater->interrupted())); ++j) { r = sqrt(i * i + j * j); if (r <= Radius * 1.1) { R = G = B = 0; BlurPixels = 0; for (k = -1 * BlurRadius; k < BlurRadius + 1; k++) for (l = -1 * BlurRadius; l < BlurRadius + 1; l++) { m = x + i + k; n = y + j + l; if ((m >= 0) && (m < Height) && (n >= 0) && (n < Width)) { QColor color; dstAccessor->moveTo(dstTopLeft.x() + n, dstTopLeft.y() + m); cs->toQColor(dstAccessor->rawData(), &color); R += color.red(); G += color.green(); B += color.blue(); BlurPixels++; } } m = x + i; n = y + j; if ((m >= 0) && (m < Height) && (n >= 0) && (n < Width)) { QColor color; color.setRgb((int)(R / BlurPixels), (int)(G / BlurPixels), (int)(B / BlurPixels)); dstAccessor->moveTo(dstTopLeft.x() + n, dstTopLeft.y() + m); cs->fromQColor(color, dstAccessor->rawData()); } } } } if (progressUpdater) progressUpdater->setValue(++count); } FreeBoolArray(BoolMatrix, Width); }
void KisWaveletNoiseReduction::process(KisConstProcessingInformation srcInfo, KisProcessingInformation dstInfo, const QSize& areaSize, const KisFilterConfiguration* config, KoUpdater* progressUpdater ) const { const KisPaintDeviceSP src = srcInfo.paintDevice(); KisPaintDeviceSP dst = dstInfo.paintDevice(); QPoint dstTopLeft = dstInfo.topLeft(); QPoint srcTopLeft = srcInfo.topLeft(); Q_ASSERT(!src.isNull()); Q_ASSERT(!dst.isNull()); // TODO take selections into account float threshold; if (!config) { config = defaultConfiguration(src); } threshold = config->getDouble("threshold", BEST_WAVELET_THRESHOLD_VALUE); qint32 depth = src->colorSpace()->colorChannelCount(); int size; int maxrectsize = qMax(areaSize.width(), areaSize.height()); for (size = 2; size < maxrectsize; size *= 2) ; KisMathToolbox* mathToolbox = KisMathToolboxRegistry::instance()->get(src->colorSpace()->mathToolboxId().id()); QRect srcRect(srcTopLeft, areaSize); if (progressUpdater) { progressUpdater->setRange(0, mathToolbox->fastWaveletTotalSteps(srcRect) * 2 + size*size*depth); } int count = 0; // connect(mathToolbox, SIGNAL(nextStep()), this, SLOT(incProgress())); // dbgFilters << size <<"" << maxrectsize <<"" << srcTopLeft.x() <<"" << srcTopLeft.y(); // dbgFilters <<"Transforming..."; // setProgressStage( i18n("Fast wavelet transformation") ,progress()); KisMathToolbox::KisWavelet* buff = 0; KisMathToolbox::KisWavelet* wav = 0; try { buff = mathToolbox->initWavelet(src, srcRect); } catch (std::bad_alloc) { if (buff) delete buff; return; } try { wav = mathToolbox->fastWaveletTransformation(src, srcRect, buff); } catch (std::bad_alloc) { if (wav) delete wav; return; } // dbgFilters <<"Thresholding..."; float* fin = wav->coeffs + wav->depth * wav->size * wav->size; for (float* it = wav->coeffs + wav->depth; it < fin; it++) { if (*it > threshold) { *it -= threshold; } else if (*it < -threshold) { *it += threshold; } else { *it = 0.; } if (progressUpdater) progressUpdater->setValue(++count); } // dbgFilters <<"Untransforming..."; mathToolbox->fastWaveletUntransformation(dst, QRect(dstTopLeft, areaSize), wav, buff); delete wav; delete buff; // disconnect(mathToolbox, SIGNAL(nextStep()), this, SLOT(incProgress())); }
void KisRoundCornersFilter::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfiguration* config, KoUpdater* progressUpdater ) const { Q_UNUSED(config); Q_ASSERT(!device.isNull()); if (!device || !config) { warnKrita << "Invalid parameters for round corner filter"; dbgPlugins << device << " " << config; return; } //read the filter configuration values from the KisFilterConfiguration object qint32 radius = qMax(1, config->getInt("radius" , 30)); if (progressUpdater) { progressUpdater->setRange(0, applyRect.height()); } qint32 width = applyRect.width(); KisHLineIteratorSP dstIt = device->createHLineIteratorNG(applyRect.x(), applyRect.y(), width); const KoColorSpace* cs = device->colorSpace(); QRect bounds = device->defaultBounds()->bounds(); for (qint32 y = applyRect.y(); y < applyRect.y() + applyRect.height(); y++) { qint32 x = applyRect.x(); do { if (x <= radius && y <= radius) { double dx = radius - x; double dy = radius - y; double dradius = static_cast<double>(radius); if (dx >= sqrt(dradius*dradius - dy*dy)) { cs->setOpacity(dstIt->rawData(), OPACITY_TRANSPARENT_U8, 1); } } else if (x >= bounds.width() - radius && y <= radius) { double dx = x + radius - bounds.width(); double dy = radius - y; double dradius = static_cast<double>(radius); if (dx >= sqrt(dradius*dradius - dy*dy)) { cs->setOpacity(dstIt->rawData(), OPACITY_TRANSPARENT_U8, 1); } } else if (x <= radius && y >= bounds.height() - radius) { double dx = radius - x; double dy = y + radius - bounds.height(); double dradius = static_cast<double>(radius); if (dx >= sqrt(dradius*dradius - dy*dy)) { cs->setOpacity(dstIt->rawData(), OPACITY_TRANSPARENT_U8, 1); } } else if (x >= bounds.width() - radius && y >= bounds.height() - radius) { double dx = x + radius - bounds.width() ; double dy = y + radius - bounds.height(); double dradius = static_cast<double>(radius); if (dx >= sqrt(dradius*dradius - dy*dy)) { cs->setOpacity(dstIt->rawData(), OPACITY_TRANSPARENT_U8, 1); } } ++x; } while(dstIt->nextPixel()); dstIt->nextRow(); if (progressUpdater) progressUpdater->setValue(y); } }
void KisSobelFilter::process(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfiguration* configuration, KoUpdater* progressUpdater ) const { QPoint srcTopLeft = applyRect.topLeft(); Q_ASSERT(!device.isNull()); //read the filter configuration values from the KisFilterConfiguration object bool doHorizontal = configuration->getBool("doHorizontally", true); bool doVertical = configuration->getBool("doVertically", true); bool keepSign = configuration->getBool("keepSign", true); bool makeOpaque = configuration->getBool("makeOpaque", true); quint32 width = applyRect.width(); quint32 height = applyRect.height(); quint32 pixelSize = device->pixelSize(); int cost = applyRect.height(); /* allocate row buffers */ quint8* prevRow = new quint8[(width + 2) * pixelSize]; Q_CHECK_PTR(prevRow); quint8* curRow = new quint8[(width + 2) * pixelSize]; Q_CHECK_PTR(curRow); quint8* nextRow = new quint8[(width + 2) * pixelSize]; Q_CHECK_PTR(nextRow); quint8* dest = new quint8[ width * pixelSize]; Q_CHECK_PTR(dest); quint8* pr = prevRow + pixelSize; quint8* cr = curRow + pixelSize; quint8* nr = nextRow + pixelSize; prepareRow(device, pr, srcTopLeft.x(), srcTopLeft.y() - 1, width, height); prepareRow(device, cr, srcTopLeft.x(), srcTopLeft.y(), width, height); quint32 counter = 0; quint8* d; quint8* tmp; qint32 gradient, horGradient, verGradient; // loop through the rows, applying the sobel convolution KisHLineIteratorSP dstIt = device->createHLineIteratorNG(srcTopLeft.x(), srcTopLeft.y(), width); for (quint32 row = 0; row < height; row++) { // prepare the next row prepareRow(device, nr, srcTopLeft.x(), srcTopLeft.y() + row + 1, width, height); d = dest; for (quint32 col = 0; col < width * pixelSize; col++) { int positive = col + pixelSize; int negative = col - pixelSize; horGradient = (doHorizontal ? ((pr[negative] + 2 * pr[col] + pr[positive]) - (nr[negative] + 2 * nr[col] + nr[positive])) : 0); verGradient = (doVertical ? ((pr[negative] + 2 * cr[negative] + nr[negative]) - (pr[positive] + 2 * cr[positive] + nr[positive])) : 0); gradient = (qint32)((doVertical && doHorizontal) ? (ROUND(RMS(horGradient, verGradient)) / 5.66) // always >0 : (keepSign ? (127 + (ROUND((horGradient + verGradient) / 8.0))) : (ROUND(qAbs(horGradient + verGradient) / 4.0)))); *d++ = gradient; if (gradient > 10) counter ++; } // shuffle the row pointers tmp = pr; pr = cr; cr = nr; nr = tmp; //store the dest device->writeBytes(dest, srcTopLeft.x(), row, width, 1); if (makeOpaque) { do { device->colorSpace()->setOpacity(dstIt->rawData(), OPACITY_OPAQUE_U8, 1); } while(dstIt->nextPixel()); dstIt->nextRow(); } if (progressUpdater) progressUpdater->setProgress(row / cost); } delete[] prevRow; delete[] curRow; delete[] nextRow; delete[] dest; }