Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_lens_blur_filter.cpp
Go to the documentation of this file.
1/*
2 * This file is part of Krita
3 *
4 * SPDX-FileCopyrightText: 2010 Edward Apap <schumifer@hotmail.com>
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9
11#include "kis_wdg_lens_blur.h"
12
13#include <KoCompositeOp.h>
14
17
18#include "ui_wdg_lens_blur.h"
19
22#include <kis_selection.h>
23#include <kis_paint_device.h>
25#include "kis_lod_transform.h"
26
27
28#include <QPainter>
29
30#include <math.h>
31
32
41
43{
44 return new KisWdgLensBlur(parent);
45}
46
48{
49 QPolygonF iris = getIrisPolygon(config, lod);
50 QRect rect = iris.boundingRect().toAlignedRect();
51
52 int w = std::ceil(qreal(rect.width()) / 2.0);
53 int h = std::ceil(qreal(rect.height()) / 2.0);
54
55 return QSize(w, h);
56}
57
59{
60 KisFilterConfigurationSP config = factoryConfiguration(resourcesInterface);
61 config->setProperty("irisShape", "Pentagon (5)");
62 config->setProperty("irisRadius", 5);
63 config->setProperty("irisRotation", 0);
64
65 QSize halfSize = getKernelHalfSize(config, 0);
66 config->setProperty("halfWidth", halfSize.width());
67 config->setProperty("halfHeight", halfSize.height());
68
69 return config;
70}
71
73{
74 KIS_ASSERT_RECOVER(config) { return QPolygonF(); }
75
77
78 QVariant value;
79 config->getProperty("irisShape", value);
80 QString irisShape = value.toString();
81 config->getProperty("irisRadius", value);
82 uint irisRadius = t.scale(value.toUInt());
83 config->getProperty("irisRotation", value);
84 uint irisRotation = value.toUInt();
85
86 if (irisRadius < 1)
87 return QPolygon();
88
89 QPolygonF irisShapePoly;
90
91 int sides = 1;
92 qreal angle = 0;
93
94 if (irisShape == "Triangle") sides = 3;
95 else if (irisShape == "Quadrilateral (4)") sides = 4;
96 else if (irisShape == "Pentagon (5)") sides = 5;
97 else if (irisShape == "Hexagon (6)") sides = 6;
98 else if (irisShape == "Heptagon (7)") sides = 7;
99 else if (irisShape == "Octagon (8)") sides = 8;
100 else return QPolygonF();
101
102 for (int i = 0; i < sides; ++i) {
103 irisShapePoly << QPointF(0.5 * cos(angle), 0.5 * sin(angle));
104 angle += 2 * M_PI / sides;
105 }
106
107 QTransform transform;
108 transform.rotate(irisRotation);
109 transform.scale(irisRadius * 2, irisRadius * 2);
110
111 QPolygonF transformedIris = transform.map(irisShapePoly);
112
113 return transformedIris;
114}
115
117 const QRect& rect,
118 const KisFilterConfigurationSP config,
119 KoUpdater* progressUpdater
120 ) const
121{
122 QPoint srcTopLeft = rect.topLeft();
123
124 Q_ASSERT(device != 0);
126
127 QBitArray channelFlags = config->channelFlags();
128 if (channelFlags.isEmpty()) {
129 channelFlags = QBitArray(device->colorSpace()->channelCount(), true);
130 }
131
132 const int lod = device->defaultBounds()->currentLevelOfDetail();
133 QPolygonF transformedIris = getIrisPolygon(config, lod);
134 if (transformedIris.isEmpty()) return;
135
136 QRectF boundingRect = transformedIris.boundingRect();
137
138 int kernelWidth = boundingRect.toAlignedRect().width();
139 int kernelHeight = boundingRect.toAlignedRect().height();
140
141 QImage kernelRepresentation(kernelWidth, kernelHeight, QImage::Format_RGB32);
142 kernelRepresentation.fill(0);
143
144 QPainter imagePainter(&kernelRepresentation);
145 imagePainter.setRenderHint(QPainter::Antialiasing);
146 imagePainter.setBrush(QColor::fromRgb(255, 255, 255));
147
148 QTransform offsetTransform;
149 offsetTransform.translate(-boundingRect.x(), -boundingRect.y());
150 imagePainter.setTransform(offsetTransform);
151 imagePainter.drawPolygon(transformedIris, Qt::WindingFill);
152
153 // construct kernel from image
154 Eigen::Matrix<qreal, Eigen::Dynamic, Eigen::Dynamic> irisKernel(kernelHeight, kernelWidth);
155 for (int j = 0; j < kernelHeight; ++j) {
156 for (int i = 0; i < kernelWidth; ++i) {
157 irisKernel(j, i) = qRed(kernelRepresentation.pixel(i, j));
158 }
159 }
160
161 // apply convolution
162 KisConvolutionPainter painter(device);
163 painter.setChannelFlags(channelFlags);
164 painter.setProgress(progressUpdater);
165
166 KisConvolutionKernelSP kernel = KisConvolutionKernel::fromMatrix(irisKernel, 0, irisKernel.sum());
167 painter.applyMatrix(kernel, device, srcTopLeft, srcTopLeft, rect.size(), BORDER_REPEAT);
168}
169
170QRect KisLensBlurFilter::neededRect(const QRect & rect, const KisFilterConfigurationSP _config, int lod) const
171{
173
174 QVariant value;
175 const int halfWidth = t.scale(_config->getProperty("halfWidth", value) ? value.toUInt() : 5);
176 const int halfHeight = t.scale(_config->getProperty("halfHeight", value) ? value.toUInt() : 5);
177
178 return rect.adjusted(-halfWidth * 2, -halfHeight * 2, halfWidth * 2, halfHeight * 2);
179}
180
181QRect KisLensBlurFilter::changedRect(const QRect & rect, const KisFilterConfigurationSP _config, int lod) const
182{
184
185 QVariant value;
186 const int halfWidth = t.scale(_config->getProperty("halfWidth", value) ? value.toUInt() : 5);
187 const int halfHeight = t.scale(_config->getProperty("halfHeight", value) ? value.toUInt() : 5);
188
189 return rect.adjusted(-halfWidth, -halfHeight, halfWidth, halfHeight);
190}
float value(const T *src, size_t ch)
@ FULLY_INDEPENDENT
unsigned int uint
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)
virtual int currentLevelOfDetail() const =0
void setSupportsLevelOfDetail(bool value)
static QSize getKernelHalfSize(const KisFilterConfigurationSP config, int lod)
static QPolygonF getIrisPolygon(const KisFilterConfigurationSP config, int lod)
QRect neededRect(const QRect &rect, const KisFilterConfigurationSP _config, int lod) const override
QRect changedRect(const QRect &rect, const KisFilterConfigurationSP _config, int lod) const override
void processImpl(KisPaintDeviceSP src, const QRect &size, const KisFilterConfigurationSP config, KoUpdater *progressUpdater) const override
KisFilterConfigurationSP defaultConfiguration(KisResourcesInterfaceSP resourcesInterface) const override
KisConfigWidget * createConfigurationWidget(QWidget *parent, const KisPaintDeviceSP dev, bool useForMasks) const override
qreal scale(qreal value) const
const KoColorSpace * colorSpace() const
KisDefaultBoundsBaseSP defaultBounds() const
void setProgress(KoUpdater *progressUpdater)
void setChannelFlags(QBitArray channelFlags)
virtual quint32 channelCount() const =0
#define KIS_ASSERT_RECOVER(cond)
Definition kis_assert.h:55
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128
const KoID FiltersCategoryBlurId("blur_filters", ki18nc("The category of blur filters, like gaussian blur. Verb.", "Blur"))
#define M_PI
Definition kis_global.h:111
virtual KisFilterConfigurationSP factoryConfiguration(KisResourcesInterfaceSP resourcesInterface) const
void setSupportsAdjustmentLayers(bool v)
void setSupportsPainting(bool v)
void setColorSpaceIndependence(ColorSpaceIndependence v)
static KisConvolutionKernelSP fromMatrix(Eigen::Matrix< qreal, Eigen::Dynamic, Eigen::Dynamic > matrix, qreal offset, qreal factor)