KisPaintDeviceSP initAsymTestDevice(QRect &imageRect, int &pixelSize, QByteArray &initialData)
{
    KisPaintDeviceSP dev = new KisPaintDevice(KoColorSpaceRegistry::instance()->rgb8());
    pixelSize = dev->pixelSize();

    imageRect = QRect(0,0,5,5);
    initialData.resize(25 * pixelSize);

    quint8 *ptr = (quint8*) initialData.data();
    for(int i = 0; i < 25; i++) {
        KoColor pixel(QColor(i,i,i,255), dev->colorSpace());
        memcpy(ptr, pixel.data(), pixelSize);

        ptr += pixelSize;
    }

    dev->writeBytes((const quint8*)initialData.constData(), imageRect);

    return dev;
}
Beispiel #2
0
void checkReadWriteRoundTrip(KisPaintDeviceSP dev,
                             const QRect &rc)
{
    KisPaintDeviceSP deviceCopy = new KisPaintDevice(*dev.data());

    QRect readRect(10, 10, 20, 20);
    int bufSize = rc.width() * rc.height() * dev->pixelSize();

    QScopedPointer<quint8> buf1(new quint8[bufSize]);

    deviceCopy->readBytes(buf1.data(), rc);

    deviceCopy->clear();
    QVERIFY(deviceCopy->extent().isEmpty());


    QScopedPointer<quint8> buf2(new quint8[bufSize]);
    deviceCopy->writeBytes(buf1.data(), rc);
    deviceCopy->readBytes(buf2.data(), rc);

    QVERIFY(!memcmp(buf1.data(), buf2.data(), bufSize));
}
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;
}