18 return 0.3 * radius + 0.3;
27Eigen::Matrix<qreal, Eigen::Dynamic, Eigen::Dynamic>
31 Eigen::Matrix<qreal, Eigen::Dynamic, Eigen::Dynamic> matrix(1, kernelSize);
34 const qreal multiplicand = 1 / (sqrt(2 *
M_PI * sigma * sigma));
35 const qreal exponentMultiplicand = 1 / (2 * sigma * sigma);
42 const int center = kernelSize / 2;
44 for (
int x = 0; x < kernelSize; x++) {
45 qreal xDistance = center - x;
46 matrix(0, x) = multiplicand * exp( -xDistance * xDistance * exponentMultiplicand );
52Eigen::Matrix<qreal, Eigen::Dynamic, Eigen::Dynamic>
56 Eigen::Matrix<qreal, Eigen::Dynamic, Eigen::Dynamic> matrix(kernelSize, 1);
59 const qreal multiplicand = 1 / (sqrt(2 *
M_PI * sigma * sigma));
60 const qreal exponentMultiplicand = 1 / (2 * sigma * sigma);
67 const int center = kernelSize / 2;
69 for (
int y = 0; y < kernelSize; y++) {
70 qreal yDistance = center - y;
71 matrix(y, 0) = multiplicand * exp( -yDistance * yDistance * exponentMultiplicand );
97 Eigen::Matrix<qreal, Eigen::Dynamic, Eigen::Dynamic> uni =
v * h;
104 qreal xRadius, qreal yRadius,
105 const QBitArray &channelFlags,
107 bool createTransaction,
110 QPoint srcTopLeft =
rect.topLeft();
120 QScopedPointer<KisTransaction> transaction;
125 painter.
applyMatrix(kernel2D, device, srcTopLeft, srcTopLeft,
rect.size(), borderOp);
127 }
else if (xRadius > 0.0 && yRadius > 0.0) {
134 qreal verticalCenter = qreal(kernelVertical->
height()) / 2.0;
140 srcTopLeft - QPoint(0, ceil(verticalCenter)),
141 srcTopLeft - QPoint(0, ceil(verticalCenter)),
142 rect.size() + QSize(0, 2 * ceil(verticalCenter)), borderOp);
148 verticalPainter.
applyMatrix(kernelVertical, interm, srcTopLeft, srcTopLeft,
rect.size(), borderOp);
150 }
else if (xRadius > 0.0) {
157 QScopedPointer<KisTransaction> transaction;
162 painter.
applyMatrix(kernelHoriz, device, srcTopLeft, srcTopLeft,
rect.size(), borderOp);
164 }
else if (yRadius > 0.0) {
171 QScopedPointer<KisTransaction> transaction;
176 painter.
applyMatrix(kernelVertical, device, srcTopLeft, srcTopLeft,
rect.size(), borderOp);
180Eigen::Matrix<qreal, Eigen::Dynamic, Eigen::Dynamic>
183 int kernelSize = 2 * (includeWrappedArea ? 2 : 1) * std::ceil(radius) + 1;
184 Eigen::Matrix<qreal, Eigen::Dynamic, Eigen::Dynamic> matrix(kernelSize, kernelSize);
186 const qreal sigma = radius;
187 const qreal multiplicand = -1.0 / (
M_PI *
pow2(
pow2(sigma)));
188 const qreal exponentMultiplicand = 1 / (2 *
pow2(sigma));
195 const int center = kernelSize / 2;
197 for (
int y = 0; y < kernelSize; y++) {
198 const qreal yDistance = center - y;
199 for (
int x = 0; x < kernelSize; x++) {
200 const qreal xDistance = center - x;
202 const qreal normalizedDistance = exponentMultiplicand *
distance;
204 matrix(x, y) = multiplicand *
205 (1.0 - normalizedDistance) *
206 exp(-normalizedDistance);
210 qreal lateral = matrix.sum() - matrix(center, center);
211 matrix(center, center) = -lateral;
216 for (
int y = 0; y < kernelSize; y++) {
217 for (
int x = 0; x < kernelSize; x++) {
218 const qreal
value = matrix(x, y);
224 qreal positiveSum = 0;
226 qreal quarterSum = 0;
229 const qreal offset = totalSum /
pow2(qreal(kernelSize));
231 for (
int y = 0; y < kernelSize; y++) {
232 for (
int x = 0; x < kernelSize; x++) {
233 qreal
value = matrix(x, y);
235 matrix(x, y) =
value;
238 positiveSum +=
value;
243 if (x > center && y > center) {
251 const qreal scale = coeff * 2.0 / positiveSum;
253 positiveSum *= scale;
259 Q_UNUSED(quarterSum);
266 qreal radius, qreal coeff,
267 const QBitArray &channelFlags,
270 QPoint srcTopLeft =
rect.topLeft();
276 Eigen::Matrix<qreal, Eigen::Dynamic, Eigen::Dynamic> matrix =
288 qreal radius, qreal coeff,
289 const QBitArray &channelFlags,
292 QPoint srcTopLeft =
rect.topLeft();
298 Eigen::Matrix<qreal, Eigen::Dynamic, Eigen::Dynamic> matrix =
310 const int kernelSize = 2 * std::ceil(radius) + 1;
311 Eigen::Matrix<qreal, Eigen::Dynamic, Eigen::Dynamic> matrix(kernelSize, kernelSize);
313 const qreal fadeStart = qMax(1.0, radius - 1.0);
320 const int center = kernelSize / 2;
322 for (
int y = 0; y < kernelSize; y++) {
323 const qreal yDistance = center - y;
324 for (
int x = 0; x < kernelSize; x++) {
325 const qreal xDistance = center - x;
337 matrix(x, y) =
value;
348 QPoint srcTopLeft =
rect.topLeft();
354 Eigen::Matrix<qreal, Eigen::Dynamic, Eigen::Dynamic> matrix =
createDilateMatrix(radius);
360 QScopedPointer<KisTransaction> transaction;
377 quint8 *dstPtr = dstIt.
rawData();
378 *dstPtr = 255 - *dstPtr;
382 applyDilate(device,
rect, radius, channelFlags, progressUpdater, createTransaction);
387 quint8 *dstPtr = dstIt.
rawData();
388 *dstPtr = 255 - *dstPtr;
float value(const T *src, size_t ch)
qreal distance(const QPointF &p1, const QPointF &p2)
The KisConvolutionPainter class applies a convolution kernel to a paint device.
void applyMatrix(const KisConvolutionKernelSP kernel, const KisPaintDeviceSP src, QPoint srcPos, QPoint dstPos, QSize areaSize, KisConvolutionBorderOp borderOp=BORDER_REPEAT)
static bool supportsFFTW()
bool needsTransaction(const KisConvolutionKernelSP kernel) const
static void applyGaussian(KisPaintDeviceSP device, const QRect &rect, qreal xRadius, qreal yRadius, const QBitArray &channelFlags, KoUpdater *updater, bool createTransaction=false, KisConvolutionBorderOp borderOp=BORDER_REPEAT)
static KisConvolutionKernelSP createVerticalKernel(qreal radius)
static qreal sigmaFromRadius(qreal radius)
static Eigen::Matrix< qreal, Eigen::Dynamic, Eigen::Dynamic > createHorizontalMatrix(qreal radius)
static Eigen::Matrix< qreal, Eigen::Dynamic, Eigen::Dynamic > createDilateMatrix(qreal radius)
static int kernelSizeFromRadius(qreal radius)
static KisConvolutionKernelSP createUniform2DKernel(qreal xRadius, qreal yRadius)
static void applyTightLoG(KisPaintDeviceSP device, const QRect &rect, qreal radius, qreal coeff, const QBitArray &channelFlags, KoUpdater *progressUpdater)
static void applyLoG(KisPaintDeviceSP device, const QRect &rect, qreal radius, qreal coeff, const QBitArray &channelFlags, KoUpdater *progressUpdater)
static void applyErodeU8(KisPaintDeviceSP device, const QRect &rect, qreal radius, const QBitArray &channelFlags, KoUpdater *progressUpdater, bool createTransaction=false)
static Eigen::Matrix< qreal, Eigen::Dynamic, Eigen::Dynamic > createLoGMatrix(qreal radius, qreal coeff, bool zeroCentered, bool includeWrappedArea)
static KisConvolutionKernelSP createHorizontalKernel(qreal radius)
static void applyDilate(KisPaintDeviceSP device, const QRect &rect, qreal radius, const QBitArray &channelFlags, KoUpdater *progressUpdater, bool createTransaction=false)
static Eigen::Matrix< qreal, Eigen::Dynamic, Eigen::Dynamic > createVerticalMatrix(qreal radius)
const KoColorSpace * colorSpace() const
void prepareClone(KisPaintDeviceSP src)
void setProgress(KoUpdater *progressUpdater)
void setChannelFlags(QBitArray channelFlags)
ALWAYS_INLINE quint8 * rawData()
virtual quint32 pixelSize() const =0
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
#define KIS_ASSERT_RECOVER_NOOP(cond)
static KisConvolutionKernelSP fromMatrix(Eigen::Matrix< qreal, Eigen::Dynamic, Eigen::Dynamic > matrix, qreal offset, qreal factor)