Exemple #1
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;
    }
}
Exemple #2
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


}
void KisFilterColorToAlpha::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 != 0);
    Q_ASSERT(dst != 0);

    if (config == 0) config = new KisFilterConfiguration("colortoalpha", 1);

    QVariant value;
    QColor cTA = (config->getProperty("targetcolor", value)) ? value.value<QColor>() : QColor(255, 255, 255);
    int threshold = (config->getProperty("threshold", value)) ? value.toInt() : 0;
    qreal thresholdF = threshold;

    KisRectIteratorPixel dstIt = dst->createRectIterator(dstTopLeft.x(), dstTopLeft.y(), size.width(), size.height(), dstInfo.selection());
    KisRectConstIteratorPixel srcIt = src->createRectConstIterator(srcTopLeft.x(), srcTopLeft.y(), size.width(), size.height(), srcInfo.selection());

    int totalCost = size.width() * size.height() / 100;
    if (totalCost == 0) totalCost = 1;
    int currentProgress = 0;

    const KoColorSpace * cs = src->colorSpace();
    qint32 pixelsize = cs->pixelSize();

    quint8* color = new quint8[pixelsize];
    cs->fromQColor(cTA, color);

    while (! srcIt.isDone()) {
        if (srcIt.isSelected()) {
            quint8 d = cs->difference(color, srcIt.oldRawData());
            qreal newOpacity; // = cs->opacityF(srcIt.rawData());
            if (d >= threshold) {
                newOpacity = 1.0;
            } else {
                newOpacity = d / thresholdF;
            }
            memcpy(dstIt.rawData(), srcIt.rawData(), pixelsize);
            if(newOpacity < cs->opacityF(srcIt.rawData()))
            {
              cs->setOpacity(dstIt.rawData(), newOpacity, 1);
            }
        }
        if (progressUpdater) progressUpdater->setProgress((++currentProgress) / totalCost);
        ++srcIt;
        ++dstIt;
    }
    delete[] color;
}
Exemple #4
0
lInterestPoints HarrisPointDetector::computeInterestPoints(KisPaintDeviceSP device, const QRect& rect)
// lHarrisPoints computeHarrisPoints(KisPaintDeviceSP device, QRect rect)
{
    dbgPlugins << "Compute Harris points on the rect :" << rect;
    Q_ASSERT(device->colorSpace()->id() == "GRAYA");
    lInterestPoints points;

    // Compute the derivatives
    KisEightFloatColorSpace* floatCs = new KisEightFloatColorSpace();
    KisPaintDeviceSP infoDevice = new KisPaintDevice(floatCs, "infoDevice");

    float g_var = DERIVATION_SIGMA * DERIVATION_SIGMA ;
    float sqrt2pi = sqrt(2 * M_PI);
    float beta0 = 1 / (sqrt2pi * DERIVATION_SIGMA);

    float beta1 = beta0 * exp(-1 / (2 * g_var));
    float beta2 = beta0 * exp(-4 / (2 * g_var));

    float alpha1 = beta1 / g_var;
    float alpha2 = 2 * beta2 / g_var;



    {
        KisHLineConstIteratorPixel hitDevice = device->createHLineConstIterator(rect.left(), rect.top() + 2, rect.width() - 4);
        KisHLineIteratorPixel hitinfoDevice = infoDevice-> createHLineIterator(rect.left() + 2, 2, rect.width());

        quint8 pixelvalue[5];

        dbgPlugins << " Compute the derivatives";
        dbgPlugins << "  horizontal derivatives";
        /* Horizontal computation of derivatives */
        for (int y = rect.top() + 2; y < rect.bottom() - 2; y++) {
            pixelvalue[LEFTLEFT] = *hitDevice.rawData();
            ++hitDevice;
            pixelvalue[LEFT] = *hitDevice.rawData();
            ++hitDevice;
            pixelvalue[CENTER] = *hitDevice.rawData();
            ++hitDevice;
            pixelvalue[RIGHT] = *hitDevice.rawData();
            ++hitDevice;
            while (!hitDevice.isDone()) {
                pixelvalue[RIGHTRIGHT] = *hitDevice.rawData();
                float* infoValues = reinterpret_cast<float*>(hitinfoDevice.rawData());
                infoValues[INFO_HDIFF] = alpha1 * (pixelvalue[LEFT] - pixelvalue[RIGHT]) + alpha2 * (pixelvalue[LEFTLEFT] - pixelvalue[RIGHTRIGHT]);
                infoValues[INFO_HADD] = beta0 * (pixelvalue[CENTER]) + beta1 * (pixelvalue[LEFT] + pixelvalue[RIGHT]) + beta2 * (pixelvalue[LEFTLEFT] + pixelvalue[RIGHTRIGHT]);
                infoValues[INFO_INTENSITY] = pixelvalue[CENTER];
//                     dbgPlugins << hitDevice.x() <<"" << hitDevice.y() <<"" << infoValues[INFO_HDIFF] <<"" << infoValues[INFO_HADD] <<"" << (int)pixelvalue[CENTER] <<"" << infoValues[INFO_INTENSITY];
                memmove(pixelvalue, pixelvalue + 1, 4*sizeof(quint8));
                ++hitDevice;
                ++hitinfoDevice;
            }
            hitDevice.nextRow();
            hitinfoDevice.nextRow();
        }
    }

    KisTransaction a("", infoDevice);
    {
        KisVLineConstIteratorPixel vitinfoDeviceRead = infoDevice-> createVLineConstIterator(rect.left() + 4, rect.top(), rect.height());
        KisVLineIteratorPixel vitinfoDevice = infoDevice-> createVLineIterator(rect.left() + 4, rect.top() + 2, rect.height() - 2);

        float hdiffValue[5];
        float haddValue[5];
        dbgPlugins << "  vertical derivatives";
        /* Vertical computation of derivatives */
        for (int x = rect.left() + 4; x < rect.right() - 4; x++) {
            const float* infoValue = reinterpret_cast<const float*>(vitinfoDeviceRead.oldRawData());
            hdiffValue[TOPTOP] = infoValue[INFO_HDIFF];
            haddValue[TOPTOP] = infoValue[INFO_HADD];
            ++vitinfoDeviceRead;
            infoValue = reinterpret_cast<const float*>(vitinfoDeviceRead.oldRawData());
            hdiffValue[TOP] = infoValue[INFO_HDIFF];
            haddValue[TOP] = infoValue[INFO_HADD];
            ++vitinfoDeviceRead;
            infoValue = reinterpret_cast<const float*>(vitinfoDeviceRead.oldRawData());
            hdiffValue[CENTER] = infoValue[INFO_HDIFF];
            haddValue[CENTER] = infoValue[INFO_HADD];
            ++vitinfoDeviceRead;
            infoValue = reinterpret_cast<const float*>(vitinfoDeviceRead.oldRawData());
            hdiffValue[RIGHT] = infoValue[INFO_HDIFF];
            haddValue[RIGHT] = infoValue[INFO_HADD];
            ++vitinfoDeviceRead;

            while (!vitinfoDevice.isDone()) {
                infoValue = reinterpret_cast<const float*>(vitinfoDeviceRead.oldRawData());
                hdiffValue[RIGHTRIGHT] = infoValue[INFO_HDIFF];
                haddValue[RIGHTRIGHT] = infoValue[INFO_HADD];

                float c_grdy = beta0 * hdiffValue[ CENTER ] + beta1 * (hdiffValue[ TOP ] + hdiffValue[ BOTTOM ]) + beta2 * (hdiffValue[ TOPTOP ] + hdiffValue[ BOTTOMBOTTOM ]);
                float c_grdx = alpha1 * (haddValue[ TOP ] - haddValue[ BOTTOM ]) + alpha2 * (haddValue[ TOPTOP ] - haddValue[ BOTTOMBOTTOM ]);

                float* infoValueDst = reinterpret_cast<float*>(vitinfoDevice.rawData());
                infoValueDst[ INFO_XX ] = c_grdx * c_grdx;
                infoValueDst[ INFO_YY ] = c_grdy * c_grdy;
                infoValueDst[ INFO_X ] = c_grdx;
                infoValueDst[ INFO_Y ] = c_grdy;
                infoValueDst[ INFO_XY ] = c_grdx * c_grdy;

                memmove(hdiffValue, hdiffValue + 1, 4 * sizeof(float));
                memmove(haddValue , haddValue + 1 , 4 * sizeof(float));
                ++vitinfoDeviceRead;
                ++vitinfoDevice;
            }
            vitinfoDeviceRead.nextCol();
            vitinfoDevice.nextCol();
        }
    }

    // Apply a blur

    // Apply a blur
    KisTransaction("", infoDevice);

#if 1
    {
        KisHLineConstIteratorPixel hitDevice = infoDevice->createHLineConstIterator(rect.left(), rect.top() + 2, rect.width() - 4);
        KisHLineIteratorPixel hitinfoDevice = infoDevice-> createHLineIterator(rect.left() + 2, rect.top() + 2, rect.width() - 4);

        float pixelvalue[6][6];

        dbgPlugins << " Compute the blur";
        dbgPlugins << "  horizontal blur";
        /* Horizontal computation of derivatives */
        for (int y = rect.top() + 2; y < rect.bottom() - 2; y++) {
            memcpy(pixelvalue[LEFTLEFT], hitDevice.rawData(), 6*sizeof(float));
            ++hitDevice;
            memcpy(pixelvalue[LEFT], hitDevice.rawData(), 6*sizeof(float));
            ++hitDevice;
            memcpy(pixelvalue[CENTER], hitDevice.rawData(), 6*sizeof(float));
            ++hitDevice;
            memcpy(pixelvalue[RIGHT], hitDevice.rawData(), 6*sizeof(float));
            ++hitDevice;
            while (!hitDevice.isDone()) {
                memcpy(pixelvalue[RIGHTRIGHT], hitDevice.rawData(), 6*sizeof(float));
                float* infoValues = reinterpret_cast<float*>(hitinfoDevice.rawData());
                for (int i = 0; i < 5; i++) {
                    infoValues[i] = beta0 *  pixelvalue[CENTER][i] + beta1 * (pixelvalue[LEFT][i] + pixelvalue[RIGHT][i]) + beta2 * (pixelvalue[LEFTLEFT][i] + pixelvalue[RIGHTRIGHT][i]);
//                   infoValues[i] =2 *  pixelvalue[CENTER][i] + ( pixelvalue[LEFT][i] + pixelvalue[RIGHT][i] );
                }
//                 memmove(pixelvalue, pixelvalue + 1, 4*sizeof(float[6]));
                for (int i = 0; i < 5; i++) {
                    memcpy(pixelvalue[i], pixelvalue[i+1], 6*sizeof(float));
                }
                ++hitDevice;
                ++hitinfoDevice;
            }
            hitDevice.nextRow();
            hitinfoDevice.nextRow();
        }
    }
    KisTransaction b("", infoDevice);
    {
        KisVLineConstIteratorPixel vitinfoDeviceRead = infoDevice-> createVLineConstIterator(rect.left() + 4, rect.top(), rect.height());
        KisVLineIteratorPixel vitinfoDevice = infoDevice-> createVLineIterator(rect.left() + 4, rect.top() + 2, rect.height() - 4);

        float infoValue[6][6];
        dbgPlugins << "  vertical blur";
        /* Vertical computation of derivatives */
        for (int x = rect.left() + 4; x < rect.right() - 4; x++) {
            memcpy(infoValue[TOPTOP], vitinfoDeviceRead.oldRawData(), 6*sizeof(float));
            ++vitinfoDeviceRead;
            memcpy(infoValue[TOP], vitinfoDeviceRead.oldRawData(), 6*sizeof(float));
            ++vitinfoDeviceRead;
            memcpy(infoValue[CENTER], vitinfoDeviceRead.oldRawData(), 6*sizeof(float));
            ++vitinfoDeviceRead;
            memcpy(infoValue[BOTTOM], vitinfoDeviceRead.oldRawData(), 6*sizeof(float));
            ++vitinfoDeviceRead;
            while (!vitinfoDevice.isDone()) {
                memcpy(infoValue[BOTTOMBOTTOM], vitinfoDeviceRead.oldRawData(), 6*sizeof(float));
                float* dst = reinterpret_cast<float*>(vitinfoDevice.rawData());
                for (int i = 0; i < 5; i++) {
                    dst[i] =  beta0 * infoValue[CENTER][i] + beta1 * (infoValue[BOTTOM][i] + infoValue[TOP][i]) + beta2 * (infoValue[TOPTOP][i] + infoValue[BOTTOMBOTTOM][i]);
//                   dst[i] =  (2*infoValue[CENTER][i] + ( infoValue[BOTTOM][i] + infoValue[TOP][i] )) / 16;
                }
//                 memmove(infoValue, infoValue + 1, 4*sizeof(float[6]));
                for (int i = 0; i < 5; i++) {
                    memcpy(infoValue[i], infoValue[i+1], 6*sizeof(float));
                }
                ++vitinfoDeviceRead;
                ++vitinfoDevice;
            }
            vitinfoDeviceRead.nextCol();
            vitinfoDevice.nextCol();
        }
    }
#endif

#if 0
    KisTransaction("", infoDevice);
    dbgPlugins << " Blur";
    {
        // Compute the blur mask
        KisAutobrushShape* kas = new KisAutobrushCircleShape(5, 5, 2, 2);

        QImage mask;
        kas->createBrush(&mask);
        KisKernelSP kernel = KisKernel::fromQImage(mask);
        // Apply the convolution to xxDevice
        KisConvolutionPainter infoDevicePainter(infoDevice);
        infoDevicePainter.beginTransaction("bouuh");
        infoDevicePainter.applyMatrix(kernel, 2, 2, rect.width() - 4, rect.height() - 4, BORDER_REPEAT);
        delete kas;
    }
#endif
    dbgPlugins << " compute curvatures";
    // Compute the curvatures
    {
        KisRectIteratorPixel vitinfoDeviceRect = infoDevice->createRectIterator(2, 0, rect.width() - 2, rect.height() - 2);
        for (;!vitinfoDeviceRect.isDone(); ++vitinfoDeviceRect) {
            float* infoValue = reinterpret_cast<float*>(vitinfoDeviceRect.rawData());

            float det = infoValue[INFO_XX] * infoValue[INFO_YY] - infoValue[INFO_XY] * infoValue[INFO_XY];
            float trace = infoValue[INFO_XX] + infoValue[INFO_YY];
            float temp = sqrt(trace * trace - 4 * det);

            infoValue[ INFO_HIGH ] = 0.5 * (trace + temp);
            infoValue[ INFO_LOW  ] = 0.5 * (trace - temp);
            if (infoValue[ INFO_HIGH ] < infoValue[ INFO_LOW  ]) {
                float a = infoValue[ INFO_HIGH ];
                infoValue[ INFO_HIGH ] = infoValue[ INFO_LOW ];
                infoValue[ INFO_LOW ] = a;
            }
//                 dbgPlugins << vitinfoDeviceRect.x() <<"" << vitinfoDeviceRect.y() <<"" << infoValue[INFO_XX] <<"" << infoValue[INFO_YY]  <<"" << infoValue[INFO_XY] <<"" << infoValue[INFO_HIGH] <<"" << infoValue[INFO_LOW] <<"" << trace <<"" << temp <<"" << det;
        }
    }
    HarrisPoints zones(5, 5, rect.width(), rect.height(), FEATURES_QUANTITY);
    // Detect Harris Points
    {
        int margin = 8;
        KisHLineIterator hitinfoDevice = infoDevice-> createHLineIterator(margin, margin, rect.width() - 2 * margin);
        for (int y = margin + rect.top(); y < rect.bottom() - margin; y++) {
            for (int x = margin + rect.left(); x < rect.right() - margin; x++, ++hitinfoDevice) {
                float* infoValue = reinterpret_cast<float*>(hitinfoDevice.rawData());
                float low = infoValue[ INFO_LOW ];
//                     dbgPlugins << low;
                if (low > THRESHOLD_LAMBDA) {
                    KisRectIteratorPixel vitinfoDeviceRect = infoDevice->createRectIterator(x - 1, y - 1, 3, 3);
                    bool greater = true;
                    for (;!vitinfoDeviceRect.isDone(); ++vitinfoDeviceRect) {
                        if (reinterpret_cast<float*>(vitinfoDeviceRect.rawData())[ INFO_LOW ] > low) {
                            greater = false;
                            break;
                        }
                    }
                    if (greater) {
//                             dbgPlugins <<"new point";
                        HarrisPoint* hp = new HarrisPoint(x, y, infoValue[INFO_INTENSITY], infoValue[INFO_HIGH], infoValue[INFO_LOW], device);
#if 0
                        points.push_back(hp);
#endif
#if 0
                        if (points.empty()) {
                            points.push_back(hp);
                        } else {
                            if (points.size() >= FEATURES_QUANTITY && hp->low() > static_cast<HarrisPoint*>(points.back())->low()) { // remove last element, the totalNumber stay equal to FEATURES_QUANTITY
                                points.pop_back();
                            }
                            if (points.size() != FEATURES_QUANTITY) {
                                lInterestPoints::iterator it;
                                if (hp->low() < static_cast<HarrisPoint*>(points.back())->low()) {
                                    points.push_back(hp);
                                } else {
                                    // insert the new corner at his right place
                                    bool inserted = false;
                                    for (it = points.begin(); it != points.end(); it++) {
                                        if (hp->low() >= static_cast<HarrisPoint*>(*it)->low()) {
                                            //                                             dbgPlugins <<"insert point";
                                            points.insert(it, hp);
                                            inserted = true;
                                            break;
                                        }
                                    }
                                    if (!inserted) delete hp;
                                }
                            } else { // hp wasn't added to the list, remove it
                                delete hp;
                            }
                        }
#endif
#if 1
                        zones.instertPoint(hp);
#endif
                    }
                }
            }
            hitinfoDevice.nextRow();
        }
    }
    points = zones.points();
    dbgPlugins << "Harris detector has found :" << points.size() << " harris points";

    delete floatCs;
    return points;
}
void KisCubismFilter::cubism(KisPaintDeviceSP src,
                             const QPoint& srcTopLeft,
                             KisPaintDeviceSP dst,
                             const QPoint& dstTopLeft,
                             const QSize& size,
                             quint32 tileSize,
                             quint32 tileSaturation) const
{
    Q_ASSERT(src);
    Q_ASSERT(dst);

    //fill the destination image with the background color (black for now)
    KisRectIteratorPixel dstIt = dst->createRectIterator(dstTopLeft.x(), dstTopLeft.y(), size.width(), size.height());
    qint32 depth = src->colorSpace()->colorChannelCount();
    while (! dstIt.isDone()) {
        for (qint32 i = 0; i < depth; i++) {
            dstIt.rawData()[i] = 0;
        }
        ++dstIt;
    }

    //compute number of rows and columns
    qint32 cols = (size.width() + tileSize - 1) / tileSize;
    qint32 rows = (size.height() + tileSize - 1) / tileSize;
    qint32 numTiles = (rows + 1) * (cols + 1);

//         setProgressTotalSteps(numTiles);
//         setProgressStage(i18n("Applying cubism filter..."),0);

    qint32* randomIndices = new qint32[numTiles];
    for (qint32 i = 0; i < numTiles; i++) {
        randomIndices[i] = i;
    }
    randomizeIndices(numTiles, randomIndices);

    qint32 count = 0;
    qint32 i, j, ix, iy;
    double x, y, width, height, theta;
    KisPolygon *poly = new KisPolygon();
    qint32 pixelSize = src->pixelSize();
    const quint8 *srcPixel /*= new quint8[ pixelSize ]*/;
    quint8 *dstPixel = 0;
    KisRandomAccessor srcAccessor = src->createRandomAccessor(0, 0);
    while (count < numTiles) {
        i = randomIndices[count] / (cols + 1);
        j = randomIndices[count] % (cols + 1);
        x = j * tileSize + (tileSize / 4.0) - randomDoubleNumber(0, tileSize / 2.0) + dstTopLeft.x();
        y = i * tileSize + (tileSize / 4.0) - randomDoubleNumber(0, tileSize / 2.0) + dstTopLeft.y();
        width = (tileSize + randomDoubleNumber(0, tileSize / 4.0) - tileSize / 8.0) * tileSaturation;
        height = (tileSize + randomDoubleNumber(0, tileSize / 4.0) - tileSize / 8.0) * tileSaturation;
        theta = randomDoubleNumber(0, 2 * M_PI);
        poly->clear();
        poly->addPoint(-width / 2.0, -height / 2.0);
        poly->addPoint(width / 2.0, -height / 2.0);
        poly->addPoint(width / 2.0, height / 2.0);
        poly->addPoint(-width / 2.0, height / 2.0);
        poly->rotate(theta);
        poly->translate(x, y);
        //  bounds check on x, y
        ix = (qint32) CLAMP(x, dstTopLeft.x(), dstTopLeft.x() + size.width() - 1);
        iy = (qint32) CLAMP(y, dstTopLeft.y(), dstTopLeft.y() + size.height() - 1);

        //read the pixel at ix, iy
        srcAccessor.moveTo(ix, iy);
        srcPixel = srcAccessor.rawData();
        if (srcPixel[pixelSize - 1]) {
            fillPolyColor(src, srcTopLeft, dst, dstTopLeft, size, poly, srcPixel, dstPixel);
        }
        count++;
//                 if ((count % 5) == 0) setProgress(count);
    }

}