void KisTotalRandomColorSource::colorize(KisPaintDeviceSP dev, const QRect& rect) { KoColor kc(dev->colorSpace()); QColor qc; int pixelSize = dev->colorSpace()->pixelSize(); KisHLineIteratorPixel it = dev->createHLineIterator(rect.x(), rect.y(), rect.width(), 0); for (int y = 0; y < rect.height(); y++) { while (!it.isDone()) { qc.setRgb((int)((255.0*rand()) / RAND_MAX), (int)((255.0*rand()) / RAND_MAX), (int)((255.0*rand()) / RAND_MAX)); kc.fromQColor(qc); memcpy(it.rawData(), kc.data(), pixelSize); ++it; } it.nextRow(); } }
QRect KisImagePyramid::downsampleByFactor2(const QRect& srcRect, KisPaintDevice* src, KisPaintDevice* dst) { qint32 srcX, srcY, srcWidth, srcHeight; srcRect.getRect(&srcX, &srcY, &srcWidth, &srcHeight); alignRectBy2(srcX, srcY, srcWidth, srcHeight); qint32 dstX = srcX / 2; qint32 dstY = srcY / 2; qint32 dstWidth = srcWidth / 2; qint32 dstHeight = srcHeight / 2; KisHLineConstIteratorPixel srcIt0 = src->createHLineConstIterator(srcX, srcY, srcWidth); KisHLineConstIteratorPixel srcIt1 = src->createHLineConstIterator(srcX, srcY + 1, srcWidth); KisHLineIteratorPixel dstIt = dst->createHLineIterator(dstX, dstY, dstWidth); for (int row = 0; row < dstHeight; ++row) { while (!dstIt.isDone()) { int srcItConseq = srcIt0.nConseqHPixels(); int dstItConseq = dstIt.nConseqHPixels(); int conseqPixels = qMin(srcItConseq, dstItConseq * 2); Q_ASSERT(!isOdd(conseqPixels)); downsamplePixels(srcIt0.rawData(), srcIt1.rawData(), dstIt.rawData(), conseqPixels); srcIt0 += conseqPixels; srcIt1 += conseqPixels; dstIt += conseqPixels / 2; } srcIt0.nextRow(); srcIt0.nextRow(); srcIt1.nextRow(); srcIt1.nextRow(); dstIt.nextRow(); } return QRect(dstX, dstY, dstWidth, dstHeight); }
void KisFilterOp::paintAt(const KisPaintInformation& info) { if (!painter()) { return; } KisFilterSP filter = settings->filter(); if (!filter) { return; } if (!source()) { return; } KisBrushSP brush = m_brush;; if (!brush) return; KisPaintInformation adjustedInfo = settings->m_optionsWidget->m_sizeOption->apply(info); if (! brush->canPaintFor(adjustedInfo)) return; double pScale = KisPaintOp::scaleForPressure(adjustedInfo.pressure()); // TODO: why is there scale and pScale that seems to contains the same things ? QPointF hotSpot = brush->hotSpot(pScale, pScale); QPointF pt = info.pos() - hotSpot; // Split the coordinates into integer plus fractional parts. The integer // is where the dab will be positioned and the fractional part determines // the sub-pixel positioning. qint32 x; double xFraction; qint32 y; double yFraction; splitCoordinate(pt.x(), &x, &xFraction); splitCoordinate(pt.y(), &y, &yFraction); double scale = KisPaintOp::scaleForPressure(adjustedInfo.pressure()); qint32 maskWidth = brush->maskWidth(scale, 0.0); qint32 maskHeight = brush->maskHeight(scale, 0.0); // Filter the paint device filter->process(KisConstProcessingInformation(source(), QPoint(x, y)), KisProcessingInformation(m_tmpDevice, QPoint(0, 0)), QSize(maskWidth, maskHeight), settings->filterConfig(), 0); // Apply the mask on the paint device (filter before mask because edge pixels may be important) KisFixedPaintDeviceSP fixedDab = new KisFixedPaintDevice(m_tmpDevice->colorSpace()); fixedDab->setRect(m_tmpDevice->extent()); fixedDab->initialize(); m_tmpDevice->readBytes(fixedDab->data(), fixedDab->bounds()); brush->mask(fixedDab, scale, scale, 0.0, info, xFraction, yFraction); m_tmpDevice->writeBytes(fixedDab->data(), fixedDab->bounds()); if (!settings->ignoreAlpha()) { KisHLineIteratorPixel itTmpDev = m_tmpDevice->createHLineIterator(0, 0, maskWidth); KisHLineIteratorPixel itSrc = source()->createHLineIterator(x, y, maskWidth); const KoColorSpace* cs = m_tmpDevice->colorSpace(); for (int y = 0; y < maskHeight; ++y) { while (!itTmpDev.isDone()) { quint8 alphaTmpDev = cs->alpha(itTmpDev.rawData()); quint8 alphaSrc = cs->alpha(itSrc.rawData()); cs->setAlpha(itTmpDev.rawData(), qMin(alphaTmpDev, alphaSrc), 1); ++itTmpDev; ++itSrc; } itTmpDev.nextRow(); itSrc.nextRow(); } } // Blit the paint device onto the layer QRect dabRect = QRect(0, 0, maskWidth, maskHeight); QRect dstRect = QRect(x, y, dabRect.width(), dabRect.height()); if (painter()->bounds().isValid()) { dstRect &= painter()->bounds(); } if (dstRect.isNull() || dstRect.isEmpty() || !dstRect.isValid()) return; qint32 sx = dstRect.x() - x; qint32 sy = dstRect.y() - y; qint32 sw = dstRect.width(); qint32 sh = dstRect.height(); painter()->bitBlt(dstRect.x(), dstRect.y(), m_tmpDevice, sx, sy, sw, sh); }
void KisDuplicateOp::paintAt(const KisPaintInformation& info) { if (!painter()) return; if (!m_duplicateStartIsSet) { m_duplicateStartIsSet = true; m_duplicateStart = info.pos(); } bool heal = settings->healing(); if (!source()) return; KisBrushSP brush = m_brush; if (!brush) return; if (! brush->canPaintFor(info)) return; double scale = KisPaintOp::scaleForPressure(info.pressure()); QPointF hotSpot = brush->hotSpot(scale, scale); QPointF pt = info.pos() - hotSpot; // Split the coordinates into integer plus fractional parts. The integer // is where the dab will be positioned and the fractional part determines // the sub-pixel positioning. qint32 x; double xFraction; qint32 y; double yFraction; splitCoordinate(pt.x(), &x, &xFraction); splitCoordinate(pt.y(), &y, &yFraction); xFraction = yFraction = 0.0; QPointF srcPointF = pt - settings->offset(); QPoint srcPoint = QPoint(x - static_cast<qint32>(settings->offset().x()), y - static_cast<qint32>(settings->offset().y())); qint32 sw = brush->maskWidth(scale, 0.0); qint32 sh = brush->maskHeight(scale, 0.0); if (srcPoint.x() < 0) srcPoint.setX(0); if (srcPoint.y() < 0) srcPoint.setY(0); if (!(m_srcdev && !(*m_srcdev->colorSpace() == *source()->colorSpace()))) { m_srcdev = new KisPaintDevice(source()->colorSpace()); } Q_CHECK_PTR(m_srcdev); // Perspective correction ? KisPainter copyPainter(m_srcdev); KisImageSP image = settings->m_image; if (settings->perspectiveCorrection() && image && image->perspectiveGrid()->countSubGrids() == 1) { Matrix3qreal startM = Matrix3qreal::Identity(); Matrix3qreal endM = Matrix3qreal::Identity(); // First look for the grid corresponding to the start point KisSubPerspectiveGrid* subGridStart = *image->perspectiveGrid()->begin(); QRect r = QRect(0, 0, image->width(), image->height()); #if 1 if (subGridStart) { startM = KisPerspectiveMath::computeMatrixTransfoFromPerspective(r, *subGridStart->topLeft(), *subGridStart->topRight(), *subGridStart->bottomLeft(), *subGridStart->bottomRight()); } #endif #if 1 // Second look for the grid corresponding to the end point KisSubPerspectiveGrid* subGridEnd = *image->perspectiveGrid()->begin(); if (subGridEnd) { endM = KisPerspectiveMath::computeMatrixTransfoToPerspective(*subGridEnd->topLeft(), *subGridEnd->topRight(), *subGridEnd->bottomLeft(), *subGridEnd->bottomRight(), r); } #endif // Compute the translation in the perspective transformation space: QPointF positionStartPaintingT = KisPerspectiveMath::matProd(endM, QPointF(m_duplicateStart)); QPointF duplicateStartPositionT = KisPerspectiveMath::matProd(endM, QPointF(m_duplicateStart) - QPointF(settings->offset())); QPointF translat = duplicateStartPositionT - positionStartPaintingT; KisRectIteratorPixel dstIt = m_srcdev->createRectIterator(0, 0, sw, sh); KisRandomSubAccessorPixel srcAcc = source()->createRandomSubAccessor(); //Action while (!dstIt.isDone()) { if (dstIt.isSelected()) { QPointF p = KisPerspectiveMath::matProd(startM, KisPerspectiveMath::matProd(endM, QPointF(dstIt.x() + x, dstIt.y() + y)) + translat); srcAcc.moveTo(p); srcAcc.sampledOldRawData(dstIt.rawData()); } ++dstIt; } } else { // Or, copy the source data on the temporary device: copyPainter.setCompositeOp(COMPOSITE_COPY); copyPainter.bitBlt(0, 0, source(), srcPoint.x(), srcPoint.y(), sw, sh); copyPainter.end(); } // heal ? if (heal) { quint16 dataDevice[4]; quint16 dataSrcDev[4]; double* matrix = new double[ 3 * sw * sh ]; // First divide const KoColorSpace* deviceCs = source()->colorSpace(); KisHLineConstIteratorPixel deviceIt = source()->createHLineConstIterator(x, y, sw); KisHLineIteratorPixel srcDevIt = m_srcdev->createHLineIterator(0, 0, sw); double* matrixIt = &matrix[0]; for (int j = 0; j < sh; j++) { for (int i = 0; !srcDevIt.isDone(); i++) { deviceCs->toLabA16(deviceIt.rawData(), (quint8*)dataDevice, 1); deviceCs->toLabA16(srcDevIt.rawData(), (quint8*)dataSrcDev, 1); // Division for (int k = 0; k < 3; k++) { matrixIt[k] = dataDevice[k] / (double)qMax((int)dataSrcDev [k], 1); } ++deviceIt; ++srcDevIt; matrixIt += 3; } deviceIt.nextRow(); srcDevIt.nextRow(); } // Minimize energy { int iter = 0; double err; double* solution = new double [ 3 * sw * sh ]; do { err = minimizeEnergy(&matrix[0], &solution[0], sw, sh); memcpy(&matrix[0], &solution[0], sw * sh * 3 * sizeof(double)); iter++; } while (err < 0.00001 && iter < 100); delete [] solution; } // Finaly multiply deviceIt = source()->createHLineIterator(x, y, sw); srcDevIt = m_srcdev->createHLineIterator(0, 0, sw); matrixIt = &matrix[0]; for (int j = 0; j < sh; j++) { for (int i = 0; !srcDevIt.isDone(); i++) { deviceCs->toLabA16(deviceIt.rawData(), (quint8*)dataDevice, 1); deviceCs->toLabA16(srcDevIt.rawData(), (quint8*)dataSrcDev, 1); // Multiplication for (int k = 0; k < 3; k++) { dataSrcDev[k] = (int)CLAMP(matrixIt[k] * qMax((int) dataSrcDev[k], 1), 0, 65535); } deviceCs->fromLabA16((quint8*)dataSrcDev, srcDevIt.rawData(), 1); ++deviceIt; ++srcDevIt; matrixIt += 3; } deviceIt.nextRow(); srcDevIt.nextRow(); } delete [] matrix; } KisFixedPaintDeviceSP fixedDab = new KisFixedPaintDevice(m_srcdev->colorSpace()); fixedDab->setRect(QRect(0, 0, sw, sh)); fixedDab->initialize(); m_srcdev->readBytes(fixedDab->data(), fixedDab->bounds()); brush->mask(fixedDab, scale, scale, 0.0, info, xFraction, yFraction); m_srcdev->writeBytes(fixedDab->data(), fixedDab->bounds()); QRect dabRect = QRect(0, 0, brush->maskWidth(scale, 0.0), brush->maskHeight(scale, 0.0)); QRect dstRect = QRect(x, y, dabRect.width(), dabRect.height()); if (painter()->bounds().isValid()) { dstRect &= painter()->bounds(); } if (dstRect.isNull() || dstRect.isEmpty() || !dstRect.isValid()) return; qint32 sx = dstRect.x() - x; qint32 sy = dstRect.y() - y; sw = dstRect.width(); sh = dstRect.height(); painter()->bitBlt(dstRect.x(), dstRect.y(), m_srcdev, sx, sy, sw, sh); }
qreal KisFilterOp::paintAt(const KisPaintInformation& info) { if (!painter()) { return 1.0; } if (!m_filter) { return 1.0; } if (!source()) { return 1.0; } KisBrushSP brush = m_brush;; if (!brush) return 1.0; if (! brush->canPaintFor(info)) return 1.0; qreal scale = KisPaintOp::scaleForPressure(m_sizeOption.apply(info)); if ((scale * brush->width()) <= 0.01 || (scale * brush->height()) <= 0.01) return spacing(scale); setCurrentScale(scale); QPointF hotSpot = brush->hotSpot(scale, scale); QPointF pt = info.pos() - hotSpot; // Split the coordinates into integer plus fractional parts. The integer // is where the dab will be positioned and the fractional part determines // the sub-pixel positioning. qint32 x; qreal xFraction; qint32 y; qreal yFraction; splitCoordinate(pt.x(), &x, &xFraction); splitCoordinate(pt.y(), &y, &yFraction); qint32 maskWidth = brush->maskWidth(scale, 0.0); qint32 maskHeight = brush->maskHeight(scale, 0.0); // Filter the paint device m_filter->process(KisConstProcessingInformation(source(), QPoint(x, y)), KisProcessingInformation(m_tmpDevice, QPoint(0, 0)), QSize(maskWidth, maskHeight), m_filterConfiguration, 0); // Apply the mask on the paint device (filter before mask because edge pixels may be important) KisFixedPaintDeviceSP fixedDab = new KisFixedPaintDevice(m_tmpDevice->colorSpace()); fixedDab->setRect(m_tmpDevice->extent()); fixedDab->initialize(); m_tmpDevice->readBytes(fixedDab->data(), fixedDab->bounds()); brush->mask(fixedDab, scale, scale, 0.0, info, xFraction, yFraction); m_tmpDevice->writeBytes(fixedDab->data(), fixedDab->bounds()); if (!m_ignoreAlpha) { KisHLineIteratorPixel itTmpDev = m_tmpDevice->createHLineIterator(0, 0, maskWidth); KisHLineIteratorPixel itSrc = source()->createHLineIterator(x, y, maskWidth); const KoColorSpace* cs = m_tmpDevice->colorSpace(); for (int y = 0; y < maskHeight; ++y) { while (!itTmpDev.isDone()) { quint8 alphaTmpDev = cs->opacityU8(itTmpDev.rawData()); quint8 alphaSrc = cs->opacityU8(itSrc.rawData()); cs->setOpacity(itTmpDev.rawData(), qMin(alphaTmpDev, alphaSrc), 1); ++itTmpDev; ++itSrc; } itTmpDev.nextRow(); itSrc.nextRow(); } } // Blit the paint device onto the layer QRect dabRect = QRect(0, 0, maskWidth, maskHeight); QRect dstRect = QRect(x, y, dabRect.width(), dabRect.height()); if (dstRect.isNull() || dstRect.isEmpty() || !dstRect.isValid()) return 1.0; qint32 sx = dstRect.x() - x; qint32 sy = dstRect.y() - y; qint32 sw = dstRect.width(); qint32 sh = dstRect.height(); painter()->bitBlt(dstRect.x(), dstRect.y(), m_tmpDevice, sx, sy, sw, sh); return spacing(scale); }