Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_motion_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_motion_blur.h"
12
13#include <KoCompositeOp.h>
14
17
18#include "ui_wdg_motion_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
40
42{
43 return new KisWdgMotionBlur(parent);
44}
45
47{
48 KisFilterConfigurationSP config = factoryConfiguration(resourcesInterface);
49 config->setProperty("blurAngle", 0);
50 config->setProperty("blurLength", 5);
51
52 return config;
53}
54
55namespace {
56struct MotionBlurProperties
57{
58 MotionBlurProperties(KisFilterConfigurationSP config, const KisLodTransformScalar &t)
59 {
60 const int blurAngle = config->getInt("blurAngle", 0);
61 const int blurLength = config->getInt("blurLength", 5);
62
63 // convert angle to radians
64 const qreal angleRadians = kisDegreesToRadians(qreal(blurAngle));
65
66 // construct image
67 const qreal halfWidth = 0.5 * t.scale(blurLength) * cos(angleRadians);
68 const qreal halfHeight = 0.5 * t.scale(blurLength) * sin(angleRadians);
69
70 kernelHalfSize.rwidth() = ceil(fabs(halfWidth));
71 kernelHalfSize.rheight() = ceil(fabs(halfHeight));
72 kernelSize = kernelHalfSize * 2 + QSize(1, 1);
73 this->blurLength = blurLength;
74
75
76 QPointF p1(0.5 * kernelSize.width(), 0.5 * kernelSize.height());
77 QPointF p2(halfWidth, halfHeight);
78 motionLine = QLineF(p1 - p2, p1 + p2);
79 }
80
81 int blurLength;
82 QSize kernelSize;
83 QSize kernelHalfSize;
84 QLineF motionLine;
85};
86}
87
89 const QRect& rect,
90 const KisFilterConfigurationSP config,
91 KoUpdater* progressUpdater
92 ) const
93{
94 QPoint srcTopLeft = rect.topLeft();
95
96 Q_ASSERT(device);
98
99 KisLodTransformScalar t(device);
100 MotionBlurProperties props(config, t);
101
102 if (props.blurLength == 0) {
103 return;
104 }
105
106 QBitArray channelFlags;
107
108 if (config) {
109 channelFlags = config->channelFlags();
110 }
111
112 if (channelFlags.isEmpty() || !config) {
113 channelFlags = QBitArray(device->colorSpace()->channelCount(), true);
114 }
115
116 QImage kernelRepresentation(props.kernelSize, QImage::Format_RGB32);
117 kernelRepresentation.fill(0);
118
119 QPainter imagePainter(&kernelRepresentation);
120 imagePainter.setRenderHint(QPainter::Antialiasing);
121 imagePainter.setPen(QPen(QColor::fromRgb(255, 255, 255), 1.0));
122 imagePainter.drawLine(props.motionLine);
123
124 // construct kernel from image
125 Eigen::Matrix<qreal, Eigen::Dynamic, Eigen::Dynamic> motionBlurKernel(props.kernelSize.height(), props.kernelSize.width());
126 for (int j = 0; j < props.kernelSize.height(); ++j) {
127 for (int i = 0; i < props.kernelSize.width(); ++i) {
128 motionBlurKernel(j, i) = qRed(kernelRepresentation.pixel(i, j));
129 }
130 }
131
132 // apply convolution
133 KisConvolutionPainter painter(device);
134 painter.setChannelFlags(channelFlags);
135 painter.setProgress(progressUpdater);
136
137 KisConvolutionKernelSP kernel = KisConvolutionKernel::fromMatrix(motionBlurKernel, 0, motionBlurKernel.sum());
138 painter.applyMatrix(kernel, device, srcTopLeft, srcTopLeft, rect.size(), BORDER_REPEAT);
139}
140
141QRect KisMotionBlurFilter::neededRect(const QRect & rect, const KisFilterConfigurationSP _config, int lod) const
142{
144 MotionBlurProperties props(_config, t);
145 return rect.adjusted(-props.kernelHalfSize.width(), -props.kernelHalfSize.height(), props.kernelHalfSize.width(), props.kernelHalfSize.height());
146}
147
148QRect KisMotionBlurFilter::changedRect(const QRect & rect, const KisFilterConfigurationSP _config, int lod) const
149{
150 return neededRect(rect, _config, lod);
151}
QPointF p2
QPointF p1
@ FULLY_INDEPENDENT
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)
void setSupportsLevelOfDetail(bool value)
qreal scale(qreal value) const
KisFilterConfigurationSP defaultConfiguration(KisResourcesInterfaceSP resourcesInterface) 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
KisConfigWidget * createConfigurationWidget(QWidget *parent, const KisPaintDeviceSP dev, bool useForMasks) const override
QRect neededRect(const QRect &rect, const KisFilterConfigurationSP _config, int lod) const override
const KoColorSpace * colorSpace() const
void setProgress(KoUpdater *progressUpdater)
void setChannelFlags(QBitArray channelFlags)
virtual quint32 channelCount() const =0
#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"))
T kisDegreesToRadians(T degrees)
Definition kis_global.h:176
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)