void KisUnsharpFilter::processRaw(KisPaintDeviceSP device, const QRect &rect, quint8 threshold, qreal weights[2], qreal factor, const QBitArray &channelFlags) const { const KoColorSpace *cs = device->colorSpace(); const int pixelSize = cs->pixelSize(); KoConvolutionOp * convolutionOp = cs->convolutionOp(); KisHLineIteratorSP dstIt = device->createHLineIteratorNG(rect.x(), rect.y(), rect.width()); quint8 *colors[2]; colors[0] = new quint8[pixelSize]; colors[1] = new quint8[pixelSize]; for (int j = 0; j < rect.height(); j++) { do { quint8 diff = cs->difference(dstIt->oldRawData(), dstIt->rawDataConst()); if (diff > threshold) { memcpy(colors[0], dstIt->oldRawData(), pixelSize); memcpy(colors[1], dstIt->rawDataConst(), pixelSize); convolutionOp->convolveColors(colors, weights, dstIt->rawData(), factor, 0, 2, channelFlags); } else { memcpy(dstIt->rawData(), dstIt->oldRawData(), pixelSize); } } while (dstIt->nextPixel()); dstIt->nextRow(); } delete colors[0]; delete colors[1]; }
void KisSimpleNoiseReducer::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfiguration* config, KoUpdater* progressUpdater ) const { QPoint srcTopLeft = applyRect.topLeft(); Q_ASSERT(device); int threshold, windowsize; if (config == 0) { config = defaultConfiguration(device); } if (progressUpdater) { progressUpdater->setRange(0, applyRect.width() * applyRect.height()); } int count = 0; threshold = config->getInt("threshold", 15); windowsize = config->getInt("windowsize", 1); const KoColorSpace* cs = device->colorSpace(); // Compute the blur mask KisCircleMaskGenerator* kas = new KisCircleMaskGenerator(2*windowsize + 1, 1, windowsize, windowsize, 2); KisConvolutionKernelSP kernel = KisConvolutionKernel::fromMaskGenerator(kas); delete kas; KisPaintDeviceSP interm = new KisPaintDevice(*device); // TODO no need for a full copy and then a transaction KisConvolutionPainter painter(interm); painter.beginTransaction("bouuh"); painter.applyMatrix(kernel, interm, srcTopLeft, srcTopLeft, applyRect.size(), BORDER_REPEAT); painter.deleteTransaction(); if (progressUpdater && progressUpdater->interrupted()) { return; } KisHLineIteratorSP dstIt = device->createHLineIteratorNG(srcTopLeft.x(), srcTopLeft.y(), applyRect.width()); KisHLineConstIteratorSP intermIt = interm->createHLineConstIteratorNG(srcTopLeft.x(), srcTopLeft.y(), applyRect.width()); for (int j = 0; j < applyRect.height() && !(progressUpdater && progressUpdater->interrupted()); j++) { do { quint8 diff = cs->difference(dstIt->oldRawData(), intermIt->oldRawData()); if (diff > threshold) { memcpy(dstIt->rawData(), intermIt->oldRawData(), cs->pixelSize()); } if (progressUpdater) progressUpdater->setValue(++count); intermIt->nextPixel(); } while (dstIt->nextPixel() && !(progressUpdater && progressUpdater->interrupted())); dstIt->nextRow(); intermIt->nextRow(); } }
void KisUnsharpFilter::processLightnessOnly(KisPaintDeviceSP device, const QRect &rect, quint8 threshold, qreal weights[2], qreal factor, const QBitArray & /*channelFlags*/) const { const KoColorSpace *cs = device->colorSpace(); const int pixelSize = cs->pixelSize(); KisHLineIteratorSP dstIt = device->createHLineIteratorNG(rect.x(), rect.y(), rect.width()); quint16 labColorSrc[4]; quint16 labColorDst[4]; const int posL = 0; const int posAplha = 3; const qreal factorInv = 1.0 / factor; for (int j = 0; j < rect.height(); j++) { do { quint8 diff = cs->differenceA(dstIt->oldRawData(), dstIt->rawDataConst()); if (diff > threshold) { cs->toLabA16(dstIt->oldRawData(), (quint8*)labColorSrc, 1); cs->toLabA16(dstIt->rawDataConst(), (quint8*)labColorDst, 1); qint32 valueL = (labColorSrc[posL] * weights[0] + labColorDst[posL] * weights[1]) * factorInv; labColorSrc[posL] = CLAMP(valueL, KoColorSpaceMathsTraits<quint16>::min, KoColorSpaceMathsTraits<quint16>::max); qint32 valueAlpha = (labColorSrc[posAplha] * weights[0] + labColorDst[posAplha] * weights[1]) * factorInv; labColorSrc[posAplha] = CLAMP(valueAlpha, KoColorSpaceMathsTraits<quint16>::min, KoColorSpaceMathsTraits<quint16>::max); cs->fromLabA16((quint8*)labColorSrc, dstIt->rawData(), 1); } else { memcpy(dstIt->rawData(), dstIt->oldRawData(), pixelSize); } } while (dstIt->nextPixel()); dstIt->nextRow(); } }
void KisUnsharpFilter::process(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfiguration* config, KoUpdater* progressUpdater ) const { QPointer<KoUpdater> filterUpdater = 0; QPointer<KoUpdater> convolutionUpdater = 0; KoProgressUpdater* updater = 0; if (progressUpdater) { updater = new KoProgressUpdater(progressUpdater); updater->start(); // Two sub-sub tasks that each go from 0 to 100. convolutionUpdater = updater->startSubtask(); filterUpdater = updater->startSubtask(); } if (!config) config = new KisFilterConfiguration(id().id(), 1); QVariant value; uint halfSize = (config->getProperty("halfSize", value)) ? value.toUInt() : 5; uint brushsize = 2 * halfSize + 1; double amount = (config->getProperty("amount", value)) ? value.toDouble() : 0.5; uint threshold = (config->getProperty("threshold", value)) ? value.toUInt() : 10; KisCircleMaskGenerator* kas = new KisCircleMaskGenerator(brushsize, 1, halfSize, halfSize, 2); KisConvolutionKernelSP kernel = KisConvolutionKernel::fromMaskGenerator(kas); KisPaintDeviceSP interm = new KisPaintDevice(*device); const KoColorSpace * cs = interm->colorSpace(); KoConvolutionOp * convolutionOp = cs->convolutionOp(); KisConvolutionPainter painter(interm); // TODO no need for a full copy and then a transaction if (progressUpdater) { painter.setProgress(convolutionUpdater); } QBitArray channelFlags = config->channelFlags(); if (channelFlags.isEmpty()) { channelFlags = cs->channelFlags(); } painter.setChannelFlags(channelFlags); painter.beginTransaction("convolution step"); painter.applyMatrix(kernel, interm, applyRect.topLeft(), applyRect.topLeft(), applyRect.size(), BORDER_REPEAT); painter.deleteTransaction(); if (progressUpdater && progressUpdater->interrupted()) { return; } KisHLineIteratorSP dstIt = device->createHLineIteratorNG(applyRect.x(), applyRect.y(), applyRect.width()); KisHLineConstIteratorSP intermIt = interm->createHLineConstIteratorNG(applyRect.x(), applyRect.y(), applyRect.width()); int cdepth = cs -> pixelSize(); quint8 *colors[2]; colors[0] = new quint8[cdepth]; colors[1] = new quint8[cdepth]; int pixelsProcessed = 0; qreal weights[2]; qreal factor = 128; // XXX: Added static cast to avoid warning weights[0] = static_cast<qreal>(factor * (1. + amount)); weights[1] = static_cast<qreal>(-factor * amount); int steps = 100 / applyRect.width() * applyRect.height(); for (int j = 0; j < applyRect.height(); j++) { do { quint8 diff = cs->difference(dstIt->oldRawData(), intermIt->oldRawData()); if (diff > threshold) { memcpy(colors[0], dstIt->oldRawData(), cdepth); memcpy(colors[1], intermIt->oldRawData(), cdepth); convolutionOp->convolveColors(colors, weights, dstIt->rawData(), factor, 0, 2.0, channelFlags); } else { memcpy(dstIt->rawData(), dstIt->oldRawData(), cdepth); } ++pixelsProcessed; if (progressUpdater) filterUpdater->setProgress(steps * pixelsProcessed); intermIt->nextPixel(); } while (dstIt->nextPixel()); if (progressUpdater && progressUpdater->interrupted()) { return; } dstIt->nextRow(); intermIt->nextRow(); } delete colors[0]; delete colors[1]; delete updater; if (progressUpdater) progressUpdater->setProgress(100); }