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