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; }
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; }