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

#include <kis_warptransform_worker.h>

+ Inheritance diagram for KisWarpTransformWorker:

Classes

struct  FunctionTransformOp
 

Public Types

typedef enum KisWarpTransformWorker::WarpCalculation_ WarpCalculation
 
enum  WarpCalculation_ { GRID = 0 , DRAW }
 
typedef enum KisWarpTransformWorker::WarpType_ WarpType
 
enum  WarpType_ { AFFINE_TRANSFORM = 0 , SIMILITUDE_TRANSFORM , RIGID_TRANSFORM , N_MODES }
 

Public Member Functions

QRect approxChangeRect (const QRect &rc)
 
QRect approxNeedRect (const QRect &rc, const QRect &fullBounds)
 
 KisWarpTransformWorker (WarpType warpType, QVector< QPointF > origPoint, QVector< QPointF > transfPoint, qreal alpha, KoUpdater *progress)
 
void run (KisPaintDeviceSP srcDev, KisPaintDeviceSP dstDev)
 
 ~KisWarpTransformWorker () override
 

Static Public Member Functions

static QPointF affineTransformMath (QPointF v, QVector< QPointF > p, QVector< QPointF > q, qreal alpha)
 
static QPointF rigidTransformMath (QPointF v, QVector< QPointF > p, QVector< QPointF > q, qreal alpha)
 
static QPointF similitudeTransformMath (QPointF v, QVector< QPointF > p, QVector< QPointF > q, qreal alpha)
 
static QImage transformQImage (WarpType warpType, const QVector< QPointF > &origPoint, const QVector< QPointF > &transfPoint, qreal alpha, const QImage &srcImage, const QPointF &srcQImageOffset, QPointF *newOffset)
 

Private Types

typedef QPointF(* WarpMathFunction) (QPointF, QVector< QPointF >, QVector< QPointF >, qreal)
 

Private Attributes

qreal m_alpha {1.0}
 
QVector< QPointF > m_origPoint
 
KoUpdaterm_progress {0}
 
QVector< QPointF > m_transfPoint
 
WarpCalculation m_warpCalc {GRID}
 
WarpMathFunction m_warpMathFunction
 

Detailed Description

Class to apply a transformation (affine, similitude, MLS) to a paintDevice or a QImage according an original set of points p, a new set of points q, and the constant alpha. The algorithms are based a paper entitled "Image Deformation Using Moving Least Squares", by Scott Schaefer (Texas A&M University), Travis McPhail (Rice University) and Joe Warren (Rice University)

Definition at line 32 of file kis_warptransform_worker.h.

Member Typedef Documentation

◆ WarpCalculation

◆ WarpMathFunction

typedef QPointF(* KisWarpTransformWorker::WarpMathFunction) (QPointF, QVector< QPointF >, QVector< QPointF >, qreal)
private

Definition at line 63 of file kis_warptransform_worker.h.

◆ WarpType

Member Enumeration Documentation

◆ WarpCalculation_

Enumerator
GRID 
DRAW 

Definition at line 38 of file kis_warptransform_worker.h.

◆ WarpType_

Enumerator
AFFINE_TRANSFORM 
SIMILITUDE_TRANSFORM 
RIGID_TRANSFORM 
N_MODES 

Definition at line 37 of file kis_warptransform_worker.h.

Constructor & Destructor Documentation

◆ KisWarpTransformWorker()

KisWarpTransformWorker::KisWarpTransformWorker ( WarpType warpType,
QVector< QPointF > origPoint,
QVector< QPointF > transfPoint,
qreal alpha,
KoUpdater * progress )

Definition at line 172 of file kis_warptransform_worker.cc.

173 : m_progress(progress)
174{
175 m_origPoint = origPoint;
176 m_transfPoint = transfPoint;
177 m_alpha = alpha;
178
179 switch(warpType) {
180 case AFFINE_TRANSFORM:
182 break;
185 break;
186 case RIGID_TRANSFORM:
188 break;
189 default:
191 break;
192 }
193}
static QPointF affineTransformMath(QPointF v, QVector< QPointF > p, QVector< QPointF > q, qreal alpha)
static QPointF rigidTransformMath(QPointF v, QVector< QPointF > p, QVector< QPointF > q, qreal alpha)
static QPointF similitudeTransformMath(QPointF v, QVector< QPointF > p, QVector< QPointF > q, qreal alpha)

References AFFINE_TRANSFORM, affineTransformMath(), m_alpha, m_origPoint, m_transfPoint, m_warpMathFunction, RIGID_TRANSFORM, rigidTransformMath(), SIMILITUDE_TRANSFORM, and similitudeTransformMath().

◆ ~KisWarpTransformWorker()

KisWarpTransformWorker::~KisWarpTransformWorker ( )
override

Definition at line 195 of file kis_warptransform_worker.cc.

196{
197}

Member Function Documentation

◆ affineTransformMath()

QPointF KisWarpTransformWorker::affineTransformMath ( QPointF v,
QVector< QPointF > p,
QVector< QPointF > q,
qreal alpha )
static

Definition at line 25 of file kis_warptransform_worker.cc.

26{
27 int nbPoints = p.size();
28 QVarLengthArray<qreal> w(nbPoints);
29 qreal sumWi = 0;
30 QPointF pStar(0, 0), qStar(0, 0);
31 QVarLengthArray<QPointF> pHat(nbPoints), qHat(nbPoints);
32
33 for (int i = 0; i < nbPoints; ++i) {
34 if (v == p[i])
35 return q[i];
36
37 QVector2D tmp(p[i] - v);
38 w[i] = 1. / pow(tmp.lengthSquared(), alpha);
39 pStar += w[i] * p[i];
40 qStar += w[i] * q[i];
41 sumWi += w[i];
42 }
43 pStar /= sumWi;
44 qStar /= sumWi;
45
46 qreal A_tmp[4] = {0, 0, 0, 0};
47 for (int i = 0; i < nbPoints; ++i) {
48 pHat[i] = p[i] - pStar;
49 qHat[i] = q[i] - qStar;
50
51 A_tmp[0] += w[i] * pow(pHat[i].x(), 2);
52 A_tmp[3] += w[i] * pow(pHat[i].y(), 2);
53 A_tmp[1] += w[i] * pHat[i].x() * pHat[i].y();
54 }
55 A_tmp[2] = A_tmp[1];
56 qreal det_A_tmp = A_tmp[0] * A_tmp[3] - A_tmp[1] * A_tmp[2];
57
58 qreal A_tmp_inv[4];
59
60 if (det_A_tmp == 0)
61 return v;
62
63 A_tmp_inv[0] = A_tmp[3] / det_A_tmp;
64 A_tmp_inv[1] = - A_tmp[1] / det_A_tmp;
65 A_tmp_inv[2] = A_tmp_inv[1];
66 A_tmp_inv[3] = A_tmp[0] / det_A_tmp;
67
68 QPointF t = v - pStar;
69 QPointF A_precalc(t.x() * A_tmp_inv[0] + t.y() * A_tmp_inv[1], t.x() * A_tmp_inv[2] + t.y() * A_tmp_inv[3]);
70 qreal A_j;
71
72 QPointF res = qStar;
73 for (int j = 0; j < nbPoints; ++j) {
74 A_j = A_precalc.x() * pHat[j].x() + A_precalc.y() * pHat[j].y();
75
76 res += w[j] * A_j * qHat[j];
77 }
78
79 return res;
80}
const Params2D p
qreal v

References p, and v.

◆ approxChangeRect()

QRect KisWarpTransformWorker::approxChangeRect ( const QRect & rc)

Definition at line 254 of file kis_warptransform_worker.cc.

255{
256 const qreal margin = 0.05;
257
258 FunctionTransformOp functionOp(m_warpMathFunction, m_origPoint, m_transfPoint, m_alpha);
259 QRect resultRect = KisAlgebra2D::approximateRectWithPointTransform(rc, functionOp);
260
261 return KisAlgebra2D::blowRect(resultRect, margin);
262}
Rect blowRect(const Rect &rect, qreal coeff)
QRect approximateRectWithPointTransform(const QRect &rect, std::function< QPointF(QPointF)> func)

References KisAlgebra2D::approximateRectWithPointTransform(), KisAlgebra2D::blowRect(), m_alpha, m_origPoint, m_transfPoint, and m_warpMathFunction.

◆ approxNeedRect()

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

Definition at line 264 of file kis_warptransform_worker.cc.

265{
266 Q_UNUSED(rc);
267 return fullBounds;
268}

◆ rigidTransformMath()

QPointF KisWarpTransformWorker::rigidTransformMath ( QPointF v,
QVector< QPointF > p,
QVector< QPointF > q,
qreal alpha )
static

Definition at line 129 of file kis_warptransform_worker.cc.

130{
131 int nbPoints = p.size();
132 QVarLengthArray<qreal> w(nbPoints);
133 qreal sumWi = 0;
134 QPointF pStar(0, 0), qStar(0, 0);
135 QVarLengthArray<QPointF> pHat(nbPoints), qHat(nbPoints);
136
137 for (int i = 0; i < nbPoints; ++i) {
138 if (v == p[i])
139 return q[i];
140
141 QVector2D tmp(p[i] - v);
142 w[i] = 1. / pow(tmp.lengthSquared(), alpha);
143 pStar += w[i] * p[i];
144 qStar += w[i] * q[i];
145 sumWi += w[i];
146 }
147 pStar /= sumWi;
148 qStar /= sumWi;
149
150 QVector2D res_tmp(0, 0);
151 qreal qx, qy, px, py;
152 for (int i = 0; i < nbPoints; ++i) {
153 pHat[i] = p[i] - pStar;
154 qHat[i] = q[i] - qStar;
155
156 qx = w[i] * qHat[i].x();
157 qy = w[i] * qHat[i].y();
158 px = pHat[i].x();
159 py = pHat[i].y();
160
161 res_tmp += QVector2D(qx * px + qy * py, qx * py - qy * px);
162 }
163
164 QPointF f_arrow(res_tmp.normalized().toPointF());
165 QVector2D v_m_pStar(v - pStar);
166 QPointF res(f_arrow.x() * v_m_pStar.x() + f_arrow.y() * v_m_pStar.y(), f_arrow.x() * v_m_pStar.y() - f_arrow.y() * v_m_pStar.x());
167 res += qStar;
168
169 return res;
170}

References p, and v.

◆ run()

void KisWarpTransformWorker::run ( KisPaintDeviceSP srcDev,
KisPaintDeviceSP dstDev )

Definition at line 222 of file kis_warptransform_worker.cc.

223{
224 KIS_SAFE_ASSERT_RECOVER_RETURN(*srcDev->colorSpace() == *dstDev->colorSpace());
225
226 if (!m_warpMathFunction ||
227 m_origPoint.isEmpty() ||
228 m_origPoint.size() != m_transfPoint.size()) {
229
230 return;
231 }
232
233 if (m_origPoint.size() == 1) {
234 dstDev->makeCloneFromRough(srcDev, srcDev->extent());
235 QPointF translate(QPointF(srcDev->x(), srcDev->y()) + m_transfPoint[0] - m_origPoint[0]);
236 dstDev->moveTo(translate.toPoint());
237 return;
238 }
239
240 const QRect srcBounds = srcDev->region().boundingRect();
241
242 dstDev->clear();
243
244 const int pixelPrecision = 8;
245
246 FunctionTransformOp functionOp(m_warpMathFunction, m_origPoint, m_transfPoint, m_alpha);
247 GridIterationTools::PaintDevicePolygonOp polygonOp(srcDev, dstDev);
248 GridIterationTools::processGrid(polygonOp, functionOp,
249 srcBounds, pixelPrecision);
250}
virtual void clear()
KisRegion region() const
void makeCloneFromRough(KisPaintDeviceSP src, const QRect &minimalRect)
QRect extent() const
const KoColorSpace * colorSpace() const
void moveTo(qint32 x, qint32 y)
QRect boundingRect() const
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128
void processGrid(ProcessCell &cellOp, const QRect &srcBounds, const int pixelPrecision)

References KisRegion::boundingRect(), KisPaintDevice::clear(), KisPaintDevice::colorSpace(), KisPaintDevice::extent(), KIS_SAFE_ASSERT_RECOVER_RETURN, m_alpha, m_origPoint, m_transfPoint, m_warpMathFunction, KisPaintDevice::makeCloneFromRough(), KisPaintDevice::moveTo(), GridIterationTools::processGrid(), KisPaintDevice::region(), KisPaintDevice::x(), and KisPaintDevice::y().

◆ similitudeTransformMath()

QPointF KisWarpTransformWorker::similitudeTransformMath ( QPointF v,
QVector< QPointF > p,
QVector< QPointF > q,
qreal alpha )
static

Definition at line 82 of file kis_warptransform_worker.cc.

83{
84 int nbPoints = p.size();
85 QVarLengthArray<qreal> w(nbPoints);
86 qreal sumWi = 0;
87 QPointF pStar(0, 0), qStar(0, 0);
88 QVarLengthArray<QPointF> pHat(nbPoints), qHat(nbPoints);
89
90 for (int i = 0; i < nbPoints; ++i) {
91 if (v == p[i])
92 return q[i];
93
94 QVector2D tmp(p[i] - v);
95 w[i] = 1. / pow(tmp.lengthSquared(), alpha);
96 pStar += w[i] * p[i];
97 qStar += w[i] * q[i];
98 sumWi += w[i];
99 }
100 pStar /= sumWi;
101 qStar /= sumWi;
102
103 qreal mu_s = 0;
104 QPointF res_tmp(0, 0);
105 qreal qx, qy, px, py;
106 for (int i = 0; i < nbPoints; ++i) {
107 pHat[i] = p[i] - pStar;
108 qHat[i] = q[i] - qStar;
109
110 QVector2D tmp(pHat[i]);
111 mu_s += w[i] * tmp.lengthSquared();
112
113 qx = w[i] * qHat[i].x();
114 qy = w[i] * qHat[i].y();
115 px = pHat[i].x();
116 py = pHat[i].y();
117
118 res_tmp += QPointF(qx * px + qy * py, qx * py - qy * px);
119 }
120
121 res_tmp /= mu_s;
122 QPointF v_m_pStar(v - pStar);
123 QPointF res(res_tmp.x() * v_m_pStar.x() + res_tmp.y() * v_m_pStar.y(), res_tmp.x() * v_m_pStar.y() - res_tmp.y() * v_m_pStar.x());
124 res += qStar;
125
126 return res;
127}

References p, and v.

◆ transformQImage()

QImage KisWarpTransformWorker::transformQImage ( WarpType warpType,
const QVector< QPointF > & origPoint,
const QVector< QPointF > & transfPoint,
qreal alpha,
const QImage & srcImage,
const QPointF & srcQImageOffset,
QPointF * newOffset )
static

Definition at line 270 of file kis_warptransform_worker.cc.

277{
278 KIS_ASSERT_RECOVER(srcImage.format() == QImage::Format_ARGB32) {
279 return QImage();
280 }
281
282 WarpMathFunction warpMathFunction = &rigidTransformMath;
283
284 switch (warpType) {
285 case AFFINE_TRANSFORM:
286 warpMathFunction = &affineTransformMath;
287 break;
289 warpMathFunction = &similitudeTransformMath;
290 break;
291 case RIGID_TRANSFORM:
292 warpMathFunction = &rigidTransformMath;
293 break;
294 default:
295 KIS_ASSERT_RECOVER(0 && "Unknown warp mode") { return QImage(); }
296 }
297
298 if (!warpMathFunction ||
299 origPoint.isEmpty() ||
300 origPoint.size() != transfPoint.size()) {
301
302 return srcImage;
303 }
304
305 if (origPoint.size() == 1) {
306 *newOffset = srcQImageOffset + (transfPoint[0] - origPoint[0]).toPoint();
307 return srcImage;
308 }
309
310 FunctionTransformOp functionOp(warpMathFunction, origPoint, transfPoint, alpha);
311
312 const QRectF srcBounds = QRectF(srcQImageOffset, srcImage.size());
313 QRectF dstBounds;
314
315 {
316 QPolygonF testPoints;
317 testPoints << srcBounds.topLeft();
318 testPoints << srcBounds.topRight();
319 testPoints << srcBounds.bottomRight();
320 testPoints << srcBounds.bottomLeft();
321 testPoints << srcBounds.topLeft();
322
323 QPolygonF::iterator it = testPoints.begin() + 1;
324
325 while (it != testPoints.end()) {
326 it = testPoints.insert(it, 0.5 * (*it + *(it - 1)));
327 it += 2;
328 }
329
330 it = testPoints.begin();
331
332 while (it != testPoints.end()) {
333 *it = functionOp(*it);
334 ++it;
335 }
336
337 dstBounds = testPoints.boundingRect();
338 }
339
340 QPointF dstQImageOffset = dstBounds.topLeft();
341 *newOffset = dstQImageOffset;
342
343 QRect dstBoundsI = dstBounds.toAlignedRect();
344 QImage dstImage(dstBoundsI.size(), srcImage.format());
345 dstImage.fill(0);
346
347 const int pixelPrecision = 32;
348 GridIterationTools::QImagePolygonOp polygonOp(srcImage, dstImage, srcQImageOffset, dstQImageOffset);
349 GridIterationTools::processGrid(polygonOp, functionOp, srcBounds.toAlignedRect(), pixelPrecision);
350
351 return dstImage;
352}
QPointF(* WarpMathFunction)(QPointF, QVector< QPointF >, QVector< QPointF >, qreal)
#define KIS_ASSERT_RECOVER(cond)
Definition kis_assert.h:55

References AFFINE_TRANSFORM, affineTransformMath(), KIS_ASSERT_RECOVER, GridIterationTools::processGrid(), RIGID_TRANSFORM, rigidTransformMath(), SIMILITUDE_TRANSFORM, and similitudeTransformMath().

Member Data Documentation

◆ m_alpha

qreal KisWarpTransformWorker::m_alpha {1.0}
private

Definition at line 70 of file kis_warptransform_worker.h.

70{1.0};

◆ m_origPoint

QVector<QPointF> KisWarpTransformWorker::m_origPoint
private

Definition at line 68 of file kis_warptransform_worker.h.

◆ m_progress

KoUpdater* KisWarpTransformWorker::m_progress {0}
private

Definition at line 71 of file kis_warptransform_worker.h.

71{0};

◆ m_transfPoint

QVector<QPointF> KisWarpTransformWorker::m_transfPoint
private

Definition at line 69 of file kis_warptransform_worker.h.

◆ m_warpCalc

WarpCalculation KisWarpTransformWorker::m_warpCalc {GRID}
private

Definition at line 67 of file kis_warptransform_worker.h.

67{GRID};

◆ m_warpMathFunction

WarpMathFunction KisWarpTransformWorker::m_warpMathFunction
private

Definition at line 66 of file kis_warptransform_worker.h.


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