2
* This file is part of Krita
4
* Copyright (c) 2010 Edward Apap <schumifer@hotmail.com>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22
#include "kis_lens_blur_filter.h"
23
#include "kis_wdg_lens_blur.h"
25
#include <kcombobox.h>
26
#include <knuminput.h>
28
#include <KoCompositeOp.h>
30
#include <kis_convolution_kernel.h>
31
#include <kis_convolution_painter.h>
32
#include <kis_iterators_pixel.h>
34
#include "ui_wdg_lens_blur.h"
36
#include <filter/kis_filter_configuration.h>
37
#include <kis_selection.h>
38
#include <kis_paint_device.h>
39
#include <kis_processing_information.h>
46
KisLensBlurFilter::KisLensBlurFilter() : KisFilter(id(), categoryBlur(), i18n("&Lens Blur..."))
48
setSupportsPainting(true);
49
setSupportsPreview(true);
50
setSupportsIncrementalPainting(true);
51
setSupportsAdjustmentLayers(true);
52
setColorSpaceIndependence(FULLY_INDEPENDENT);
55
KisConfigWidget * KisLensBlurFilter::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP, const KisImageWSP image) const
58
return new KisWdgLensBlur(parent);
61
KisFilterConfiguration* KisLensBlurFilter::factoryConfiguration(const KisPaintDeviceSP) const
63
KisFilterConfiguration* config = new KisFilterConfiguration(id().id(), 1);
64
config->setProperty("irisShape", "Pentagon (5)");
65
config->setProperty("irisRadius", 5);
66
config->setProperty("irisRotation", 0);
71
void KisLensBlurFilter::process(KisConstProcessingInformation srcInfo,
72
KisProcessingInformation dstInfo,
74
const KisFilterConfiguration* config,
75
KoUpdater* progressUpdater
78
const KisPaintDeviceSP src = srcInfo.paintDevice();
79
KisPaintDeviceSP dst = dstInfo.paintDevice();
80
QPoint dstTopLeft = dstInfo.topLeft();
81
QPoint srcTopLeft = srcInfo.topLeft();
86
if (!config) config = new KisFilterConfiguration(id().id(), 1);
89
config->getProperty("irisShape", value);
90
QString irisShape = value.toString();
91
config->getProperty("irisRadius", value);
92
uint irisRadius = value.toUInt();
93
config->getProperty("irisRotation", value);
94
uint irisRotation = value.toUInt();
99
QBitArray channelFlags;
101
channelFlags = config->channelFlags();
103
if (channelFlags.isEmpty() || !config) {
104
channelFlags = QBitArray(src->colorSpace()->channelCount(), true);
107
QPolygonF irisShapePoly;
112
if (irisShape == "Triangle") sides = 3;
113
else if (irisShape == "Quadrilateral (4)") sides = 4;
114
else if (irisShape == "Pentagon (5)") sides = 5;
115
else if (irisShape == "Hexagon (6)") sides = 6;
116
else if (irisShape == "Heptagon (7)") sides = 7;
117
else if (irisShape == "Octagon (8)") sides = 8;
120
for (int i = 0; i < sides; ++i) {
121
irisShapePoly << QPointF(0.5 * cos(angle), 0.5 * sin(angle));
122
angle += 2 * M_PI / sides;
125
QTransform transform;
126
transform.rotate(irisRotation);
127
transform.scale(irisRadius * 2, irisRadius * 2);
129
QPolygonF transformedIris;
130
for (int i = 0; i < irisShapePoly.count(); ++i) {
131
transformedIris << irisShapePoly[i] * transform;
134
// find extremes to determine kernel size required
135
qreal minX = 0, maxX = 0, minY = 0, maxY = 0;
136
for (int i = 0; i < transformedIris.count(); ++i) {
137
if (transformedIris[i].x() < minX) minX = transformedIris[i].x();
138
if (transformedIris[i].x() > maxX) maxX = transformedIris[i].x();
139
if (transformedIris[i].y() < minY) minY = transformedIris[i].y();
140
if (transformedIris[i].y() > maxY) maxY = transformedIris[i].y();
143
int kernelWidth = ceil(maxX) - ceil(minX);
144
int kernelHeight = ceil(maxY) - ceil(minY);
146
QImage kernelRepresentation(kernelWidth, kernelHeight, QImage::Format_RGB32);
147
kernelRepresentation.fill(0);
149
QPainter imagePainter(&kernelRepresentation);
150
imagePainter.setRenderHint(QPainter::Antialiasing);
151
imagePainter.setBrush(QColor::fromRgb(255, 255, 255));
153
QTransform offsetTransform;
154
offsetTransform.translate(-minX, -minY);
155
imagePainter.setTransform(offsetTransform);
156
imagePainter.drawPolygon(transformedIris, Qt::WindingFill);
158
// construct kernel from image
159
Matrix<qreal, Dynamic, Dynamic> irisKernel(kernelHeight, kernelWidth);
160
for (int j = 0; j < kernelHeight; ++j) {
161
for (int i = 0; i < kernelWidth; ++i) {
162
irisKernel(j, i) = qRed(kernelRepresentation.pixel(i, j));
167
KisConvolutionPainter painter(dst, dstInfo.selection());
168
painter.setChannelFlags(channelFlags);
169
painter.setProgress(progressUpdater);
171
KisConvolutionKernelSP kernel = KisConvolutionKernel::fromMatrix(irisKernel, 0, irisKernel.sum());
172
painter.applyMatrix(kernel, src, srcTopLeft, dstTopLeft, size, BORDER_REPEAT);