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

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

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

    delete colors[0];
    delete colors[1];
}
void 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);
}