Krita Source Code Documentation
Loading...
Searching...
No Matches
KisLiquifyTransformWorker Class Reference

#include <kis_liquify_transform_worker.h>

+ Inheritance diagram for KisLiquifyTransformWorker:

Public Member Functions

QRect approxChangeRect (const QRect &rc)
 
QRect approxNeedRect (const QRect &rc, const QRect &fullBounds)
 
QSize gridSize () const
 
bool isIdentity () const
 
 KisLiquifyTransformWorker (const KisLiquifyTransformWorker &rhs)
 
 KisLiquifyTransformWorker (const QRect &srcBounds, KoUpdater *progress, int pixelPrecision=8)
 
bool operator== (const KisLiquifyTransformWorker &other) const
 
const QVector< QPointF > & originalPoints () const
 
int pointToIndex (const QPoint &cellPt)
 
void preparePoints ()
 
 Private (const QRect &_srcBounds, KoUpdater *_progress, int _pixelPrecision)
 
template<class ProcessOp >
void processTransformedPixels (ProcessOp op, const QPointF &base, qreal sigma, bool useWashMode, qreal flow)
 
template<class ProcessOp >
void processTransformedPixelsBuildUp (ProcessOp op, const QPointF &base, qreal sigma)
 
template<class ProcessOp >
void processTransformedPixelsWash (ProcessOp op, const QPointF &base, qreal sigma, qreal flow)
 
void rotatePoints (const QPointF &base, qreal angle, qreal sigma, bool useWashMode, qreal flow)
 
void run (KisPaintDeviceSP srcDevice, KisPaintDeviceSP dstDevice)
 
QImage runOnQImage (const QImage &srcImage, const QPointF &srcImageOffset, const QTransform &imageToThumbTransform, QPointF *newOffset)
 
void scalePoints (const QPointF &base, qreal scale, qreal sigma, bool useWashMode, qreal flow)
 
void toXML (QDomElement *e) const
 
QVector< QPointF > & transformedPoints ()
 
void transformSrcAndDst (const QTransform &t)
 
void translate (const QPointF &offset)
 
void translateDstSpace (const QPointF &offset)
 
void translatePoints (const QPointF &base, const QPointF &offset, qreal sigma, bool useWashMode, qreal flow)
 
void undoPoints (const QPointF &base, qreal amount, qreal sigma)
 
 ~KisLiquifyTransformWorker ()
 
- Public Member Functions inherited from Private
 Private (KisCanvas2 *c)
 

Static Public Member Functions

static KisLiquifyTransformWorkerfromXML (const QDomElement &e)
 

Public Attributes

QSize gridSize
 
QVector< QPointF > originalPoints
 
int pixelPrecision
 
KoUpdaterprogress
 
QRect srcBounds
 
QVector< QPointF > transformedPoints
 
- Public Attributes inherited from Private
KisCanvas2canvas
 
int displayedFrame
 
int intendedFrame
 

Private Attributes

const QScopedPointer< Privatem_d
 

Detailed Description

Definition at line 15 of file kis_liquify_transform_worker.cpp.

Constructor & Destructor Documentation

◆ KisLiquifyTransformWorker() [1/2]

KisLiquifyTransformWorker::KisLiquifyTransformWorker ( const QRect & srcBounds,
KoUpdater * progress,
int pixelPrecision = 8 )

Definition at line 58 of file kis_liquify_transform_worker.cpp.

62{
64
65 // TODO: implement 'progress' stuff
66 m_d->preparePoints();
67}
#define KIS_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:75
const QScopedPointer< Private > m_d

References KIS_ASSERT_RECOVER_RETURN, m_d, and srcBounds.

◆ KisLiquifyTransformWorker() [2/2]

KisLiquifyTransformWorker::KisLiquifyTransformWorker ( const KisLiquifyTransformWorker & rhs)

Definition at line 69 of file kis_liquify_transform_worker.cpp.

70 : m_d(new Private(*rhs.m_d.data()))
71{
72}

◆ ~KisLiquifyTransformWorker()

KisLiquifyTransformWorker::~KisLiquifyTransformWorker ( )

Definition at line 74 of file kis_liquify_transform_worker.cpp.

75{
76}

Member Function Documentation

◆ approxChangeRect()

QRect KisLiquifyTransformWorker::approxChangeRect ( const QRect & rc)

Here we just return the full area occupied by the transformed grid. We sample grid points for not doing too much work.

Definition at line 408 of file kis_liquify_transform_worker.cpp.

409{
410 const qreal margin = 0.05;
411
416 const int maxSamplePoints = 200;
417 const int minStep = 3;
418 const int step = qMax(minStep, m_d->transformedPoints.size() / maxSamplePoints);
419 Q_UNUSED(step);
420
421 QVector<QPoint> samplePoints;
422 for (auto it = m_d->transformedPoints.constBegin(); it != m_d->transformedPoints.constEnd(); ++it) {
423 samplePoints << it->toPoint();
424 }
425
426 QRect resultRect = KisAlgebra2D::approximateRectFromPoints(samplePoints);
427 return KisAlgebra2D::blowRect(resultRect | rc, margin);
428}
Rect blowRect(const Rect &rect, qreal coeff)
QRect approximateRectFromPoints(const QVector< QPoint > &points)

References KisAlgebra2D::approximateRectFromPoints(), KisAlgebra2D::blowRect(), and m_d.

◆ approxNeedRect()

QRect KisLiquifyTransformWorker::approxNeedRect ( const QRect & rc,
const QRect & fullBounds )

Definition at line 430 of file kis_liquify_transform_worker.cpp.

431{
432 Q_UNUSED(rc);
433 return fullBounds;
434}

◆ fromXML()

KisLiquifyTransformWorker * KisLiquifyTransformWorker::fromXML ( const QDomElement & e)
static

Definition at line 530 of file kis_liquify_transform_worker.cpp.

531{
532 QDomElement liquifyEl;
533
534 QRect srcBounds;
537 int pixelPrecision;
538 QSize gridSize;
539
540 bool result = false;
541
542
543 result =
544 KisDomUtils::findOnlyElement(e, "liquify_points", &liquifyEl) &&
545
546 KisDomUtils::loadValue(liquifyEl, "srcBounds", &srcBounds) &&
547 KisDomUtils::loadValue(liquifyEl, "originalPoints", &originalPoints) &&
548 KisDomUtils::loadValue(liquifyEl, "transformedPoints", &transformedPoints) &&
549 KisDomUtils::loadValue(liquifyEl, "pixelPrecision", &pixelPrecision) &&
550 KisDomUtils::loadValue(liquifyEl, "gridSize", &gridSize);
551
552 if (!result) {
553 warnKrita << "WARNING: Failed to load liquify worker from XML";
554 return new KisLiquifyTransformWorker(QRect(0,0,1024, 1024), 0, 8);
555 }
556
559
560 const int numPoints = originalPoints.size();
561
562 if (numPoints != transformedPoints.size() ||
563 numPoints != worker->m_d->originalPoints.size() ||
564 gridSize != worker->m_d->gridSize) {
565 warnKrita << "WARNING: Inconsistent number of points!";
566 warnKrita << ppVar(originalPoints.size());
569 warnKrita << ppVar(worker->m_d->originalPoints.size());
570 warnKrita << ppVar(worker->m_d->transformedPoints.size());
571 warnKrita << ppVar(worker->m_d->gridSize);
572
573 return worker;
574 }
575
576 for (int i = 0; i < numPoints; i++) {
577 worker->m_d->originalPoints[i] = originalPoints[i];
578 worker->m_d->transformedPoints[i] = transformedPoints[i];
579 }
580
581
582 return worker;
583}
#define warnKrita
Definition kis_debug.h:87
#define ppVar(var)
Definition kis_debug.h:155
bool findOnlyElement(const QDomElement &parent, const QString &tag, QDomElement *el, QStringList *errorMessages)
bool loadValue(const QDomElement &e, float *v)
KisLiquifyTransformWorker(const QRect &srcBounds, KoUpdater *progress, int pixelPrecision=8)

References KisDomUtils::findOnlyElement(), gridSize, KisLiquifyTransformWorker(), KisDomUtils::loadValue(), m_d, originalPoints, pixelPrecision, ppVar, srcBounds, transformedPoints, and warnKrita.

◆ gridSize()

QSize KisLiquifyTransformWorker::gridSize ( ) const

◆ isIdentity()

bool KisLiquifyTransformWorker::isIdentity ( ) const

Definition at line 98 of file kis_liquify_transform_worker.cpp.

99{
100 const qreal eps = 1e-6;
101 return KisAlgebra2D::fuzzyPointCompare(m_d->originalPoints, m_d->transformedPoints, eps);
102}
const qreal eps
bool fuzzyPointCompare(const QPointF &p1, const QPointF &p2)

References eps, KisAlgebra2D::fuzzyPointCompare(), and m_d.

◆ operator==()

bool KisLiquifyTransformWorker::operator== ( const KisLiquifyTransformWorker & other) const

Definition at line 78 of file kis_liquify_transform_worker.cpp.

79{
80 bool result =
81 m_d->srcBounds == other.m_d->srcBounds &&
82 m_d->pixelPrecision == other.m_d->pixelPrecision &&
83 m_d->gridSize == other.m_d->gridSize &&
84 m_d->originalPoints.size() == other.m_d->originalPoints.size() &&
85 m_d->transformedPoints.size() == other.m_d->transformedPoints.size();
86
87 if (!result) return false;
88
89 const qreal eps = 1e-6;
90
91 result =
92 KisAlgebra2D::fuzzyPointCompare(m_d->originalPoints, other.m_d->originalPoints, eps) &&
93 KisAlgebra2D::fuzzyPointCompare(m_d->transformedPoints, other.m_d->transformedPoints, eps);
94
95 return result;
96}

References eps, KisAlgebra2D::fuzzyPointCompare(), and m_d.

◆ originalPoints()

const QVector< QPointF > & KisLiquifyTransformWorker::originalPoints ( ) const

◆ pointToIndex()

int KisLiquifyTransformWorker::pointToIndex ( const QPoint & cellPt)

Definition at line 104 of file kis_liquify_transform_worker.cpp.

105{
106 return GridIterationTools::pointToIndex(cellPt, m_d->gridSize);
107}
int pointToIndex(const QPoint &cellPt, const QSize &gridSize)

References m_d, and GridIterationTools::pointToIndex().

◆ preparePoints()

void KisLiquifyTransformWorker::preparePoints ( )

◆ Private()

KisLiquifyTransformWorker::Private ( const QRect & _srcBounds,
KoUpdater * _progress,
int _pixelPrecision )
inline

Definition at line 17 of file kis_liquify_transform_worker.cpp.

20 : srcBounds(_srcBounds),
21 progress(_progress),
22 pixelPrecision(_pixelPrecision)
23 {
24 }

◆ processTransformedPixels()

template<class ProcessOp >
void KisLiquifyTransformWorker::processTransformedPixels ( ProcessOp op,
const QPointF & base,
qreal sigma,
bool useWashMode,
qreal flow )

◆ processTransformedPixelsBuildUp()

template<class ProcessOp >
void KisLiquifyTransformWorker::processTransformedPixelsBuildUp ( ProcessOp op,
const QPointF & base,
qreal sigma )

◆ processTransformedPixelsWash()

template<class ProcessOp >
void KisLiquifyTransformWorker::processTransformedPixelsWash ( ProcessOp op,
const QPointF & base,
qreal sigma,
qreal flow )

◆ rotatePoints()

void KisLiquifyTransformWorker::rotatePoints ( const QPointF & base,
qreal angle,
qreal sigma,
bool useWashMode,
qreal flow )

Definition at line 382 of file kis_liquify_transform_worker.cpp.

387{
388 RotateOp op(angle);
389 m_d->processTransformedPixels(op, base, sigma, useWashMode, flow);
390}

References m_d.

◆ run()

void KisLiquifyTransformWorker::run ( KisPaintDeviceSP srcDevice,
KisPaintDeviceSP dstDevice )

Definition at line 392 of file kis_liquify_transform_worker.cpp.

393{
394 KIS_SAFE_ASSERT_RECOVER_RETURN(*srcDevice->colorSpace() == *dstDevice->colorSpace());
395
396 dstDevice->clear();
397
398 using namespace GridIterationTools;
399
400 PaintDevicePolygonOp polygonOp(srcDevice, dstDevice);
401 RegularGridIndexesOp indexesOp(m_d->gridSize);
402 iterateThroughGrid<AlwaysCompletePolygonPolicy>(polygonOp, indexesOp,
403 m_d->gridSize,
404 m_d->originalPoints,
405 m_d->transformedPoints);
406}
virtual void clear()
const KoColorSpace * colorSpace() const
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128

References KisPaintDevice::clear(), KisPaintDevice::colorSpace(), KIS_SAFE_ASSERT_RECOVER_RETURN, and m_d.

◆ runOnQImage()

QImage KisLiquifyTransformWorker::runOnQImage ( const QImage & srcImage,
const QPointF & srcImageOffset,
const QTransform & imageToThumbTransform,
QPointF * newOffset )

Definition at line 463 of file kis_liquify_transform_worker.cpp.

467{
468 KIS_ASSERT_RECOVER(m_d->originalPoints.size() == m_d->transformedPoints.size()) {
469 return QImage();
470 }
471
472 KIS_ASSERT_RECOVER(!srcImage.isNull()) {
473 return QImage();
474 }
475
476 KIS_ASSERT_RECOVER(srcImage.format() == QImage::Format_ARGB32) {
477 return QImage();
478 }
479
480 QVector<QPointF> originalPointsLocal(m_d->originalPoints);
481 QVector<QPointF> transformedPointsLocal(m_d->transformedPoints);
482
483 PointMapFunction mapFunc = bindPointMapTransform(imageToThumbTransform);
484
485 std::transform(originalPointsLocal.begin(), originalPointsLocal.end(),
486 originalPointsLocal.begin(), mapFunc);
487
488 std::transform(transformedPointsLocal.begin(), transformedPointsLocal.end(),
489 transformedPointsLocal.begin(), mapFunc);
490
491 QRectF dstBounds;
492 Q_FOREACH (const QPointF &pt, transformedPointsLocal) {
493 KisAlgebra2D::accumulateBounds(pt, &dstBounds);
494 }
495
496 const QRectF srcBounds(srcImageOffset, srcImage.size());
497 dstBounds |= srcBounds;
498
499 QPointF dstQImageOffset = dstBounds.topLeft();
500 *newOffset = dstQImageOffset;
501
502 QRect dstBoundsI = dstBounds.toAlignedRect();
503
504 QImage dstImage(dstBoundsI.size(), srcImage.format());
505 dstImage.fill(0);
506
507 GridIterationTools::QImagePolygonOp polygonOp(srcImage, dstImage, srcImageOffset, dstQImageOffset);
511 m_d->gridSize,
512 originalPointsLocal,
513 transformedPointsLocal);
514 return dstImage;
515}
#define KIS_ASSERT_RECOVER(cond)
Definition kis_assert.h:55
std::function< QPointF(const QPointF &)> PointMapFunction
PointMapFunction bindPointMapTransform(const QTransform &transform)
void iterateThroughGrid(PolygonOp &polygonOp, IndexesOp &indexesOp, const QSize &gridSize, const QVector< QPointF > &originalPoints, const QVector< QPointF > &transformedPoints)
void accumulateBounds(const Point &pt, Rect *bounds)

References KisAlgebra2D::accumulateBounds(), bindPointMapTransform(), GridIterationTools::iterateThroughGrid(), KIS_ASSERT_RECOVER, m_d, and srcBounds.

◆ scalePoints()

void KisLiquifyTransformWorker::scalePoints ( const QPointF & base,
qreal scale,
qreal sigma,
bool useWashMode,
qreal flow )

Definition at line 372 of file kis_liquify_transform_worker.cpp.

377{
378 ScaleOp op(scale);
379 m_d->processTransformedPixels(op, base, sigma, useWashMode, flow);
380}

References m_d.

◆ toXML()

void KisLiquifyTransformWorker::toXML ( QDomElement * e) const

Definition at line 517 of file kis_liquify_transform_worker.cpp.

518{
519 QDomDocument doc = e->ownerDocument();
520 QDomElement liqEl = doc.createElement("liquify_points");
521 e->appendChild(liqEl);
522
523 KisDomUtils::saveValue(&liqEl, "srcBounds", m_d->srcBounds);
524 KisDomUtils::saveValue(&liqEl, "originalPoints", m_d->originalPoints);
525 KisDomUtils::saveValue(&liqEl, "transformedPoints", m_d->transformedPoints);
526 KisDomUtils::saveValue(&liqEl, "pixelPrecision", m_d->pixelPrecision);
527 KisDomUtils::saveValue(&liqEl, "gridSize", m_d->gridSize);
528}
void saveValue(QDomElement *parent, const QString &tag, const QSize &size)

References m_d, and KisDomUtils::saveValue().

◆ transformedPoints()

QVector< QPointF > & KisLiquifyTransformWorker::transformedPoints ( )

◆ transformSrcAndDst()

void KisLiquifyTransformWorker::transformSrcAndDst ( const QTransform & t)

Definition at line 436 of file kis_liquify_transform_worker.cpp.

437{
438 KIS_SAFE_ASSERT_RECOVER_RETURN(t.type() <= QTransform::TxScale);
439
440 m_d->srcBounds = t.mapRect(m_d->srcBounds);
441
442 for (auto it = m_d->originalPoints.begin(); it != m_d->originalPoints.end(); ++it) {
443 *it = t.map(*it);
444 }
445 for (auto it = m_d->transformedPoints.begin(); it != m_d->transformedPoints.end(); ++it) {
446 *it = t.map(*it);
447 }
448}

References KIS_SAFE_ASSERT_RECOVER_RETURN, and m_d.

◆ translate()

void KisLiquifyTransformWorker::translate ( const QPointF & offset)

Definition at line 164 of file kis_liquify_transform_worker.cpp.

165{
166 QVector<QPointF>::iterator it = m_d->transformedPoints.begin();
167 QVector<QPointF>::iterator end = m_d->transformedPoints.end();
168
169 QVector<QPointF>::iterator refIt = m_d->originalPoints.begin();
170 KIS_ASSERT_RECOVER_RETURN(m_d->originalPoints.size() ==
171 m_d->transformedPoints.size());
172
173 for (; it != end; ++it, ++refIt) {
174 *it += offset;
175 *refIt += offset;
176 }
177}

References KIS_ASSERT_RECOVER_RETURN, and m_d.

◆ translateDstSpace()

void KisLiquifyTransformWorker::translateDstSpace ( const QPointF & offset)

Definition at line 179 of file kis_liquify_transform_worker.cpp.

180{
181 QVector<QPointF>::iterator it = m_d->transformedPoints.begin();
182 QVector<QPointF>::iterator end = m_d->transformedPoints.end();
183
184 for (; it != end; ++it) {
185 *it += offset;
186 }
187}

References m_d.

◆ translatePoints()

void KisLiquifyTransformWorker::translatePoints ( const QPointF & base,
const QPointF & offset,
qreal sigma,
bool useWashMode,
qreal flow )

Definition at line 362 of file kis_liquify_transform_worker.cpp.

367{
368 TranslateOp op(offset);
369 m_d->processTransformedPixels(op, base, sigma, useWashMode, flow);
370}

References m_d.

◆ undoPoints()

void KisLiquifyTransformWorker::undoPoints ( const QPointF & base,
qreal amount,
qreal sigma )

Definition at line 189 of file kis_liquify_transform_worker.cpp.

192{
193 const qreal maxDistCoeff = 3.0;
194 const qreal maxDist = maxDistCoeff * sigma;
195 QRectF clipRect(base.x() - maxDist, base.y() - maxDist,
196 2 * maxDist, 2 * maxDist);
197
198 QVector<QPointF>::iterator it = m_d->transformedPoints.begin();
199 QVector<QPointF>::iterator end = m_d->transformedPoints.end();
200
201 QVector<QPointF>::iterator refIt = m_d->originalPoints.begin();
202 KIS_ASSERT_RECOVER_RETURN(m_d->originalPoints.size() ==
203 m_d->transformedPoints.size());
204
205 for (; it != end; ++it, ++refIt) {
206 if (!clipRect.contains(*it)) continue;
207
208 QPointF diff = *it - base;
209 qreal dist = KisAlgebra2D::norm(diff);
210 if (dist > maxDist) continue;
211
212 qreal lambda = exp(-0.5 * pow2(dist / sigma));
213 lambda *= amount;
214 *it = *refIt * lambda + *it * (1.0 - lambda);
215 }
216}
T pow2(const T &x)
Definition kis_global.h:166
qreal norm(const T &a)

References KIS_ASSERT_RECOVER_RETURN, m_d, KisAlgebra2D::norm(), and pow2().

Member Data Documentation

◆ gridSize

QSize KisLiquifyTransformWorker::gridSize

Definition at line 33 of file kis_liquify_transform_worker.cpp.

◆ m_d

const QScopedPointer<Private> KisLiquifyTransformWorker::m_d
private

Definition at line 85 of file kis_liquify_transform_worker.h.

◆ originalPoints

const QVector< QPointF > & KisLiquifyTransformWorker::originalPoints

Definition at line 28 of file kis_liquify_transform_worker.cpp.

◆ pixelPrecision

int KisLiquifyTransformWorker::pixelPrecision

Definition at line 32 of file kis_liquify_transform_worker.cpp.

◆ progress

KoUpdater* KisLiquifyTransformWorker::progress

Definition at line 31 of file kis_liquify_transform_worker.cpp.

◆ srcBounds

QRect KisLiquifyTransformWorker::srcBounds

Definition at line 26 of file kis_liquify_transform_worker.cpp.

◆ transformedPoints

QVector< QPointF > & KisLiquifyTransformWorker::transformedPoints

Definition at line 29 of file kis_liquify_transform_worker.cpp.


The documentation for this class was generated from the following files: