QGIS API Documentation 3.41.0-Master (88383c3d16f)
Loading...
Searching...
No Matches
qgsblureffect.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsblureffect.cpp
3 -----------------
4 begin : December 2014
5 copyright : (C) 2014 Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18#include "qgsblureffect.h"
19#include "qgsimageoperation.h"
20#include "qgsrendercontext.h"
21#include "qgssymbollayerutils.h"
22#include "qgsunittypes.h"
23
24QgsPaintEffect *QgsBlurEffect::create( const QVariantMap &map )
25{
26 QgsBlurEffect *newEffect = new QgsBlurEffect();
27 newEffect->readProperties( map );
28 return newEffect;
29}
30
32{
33 if ( !enabled() || !context.painter() || source().isNull() )
34 return;
35
36 switch ( mBlurMethod )
37 {
38 case StackBlur:
39 drawStackBlur( context );
40 break;
41 case GaussianBlur:
42 drawGaussianBlur( context );
43 break;
44 }
45}
46
47void QgsBlurEffect::drawStackBlur( QgsRenderContext &context )
48{
49 const int blurLevel = std::round( context.convertToPainterUnits( mBlurLevel, mBlurUnit, mBlurMapUnitScale, Qgis::RenderSubcomponentProperty::BlurSize ) );
50
51 QImage im = sourceAsImage( context ).copy();
52 QgsImageOperation::stackBlur( im, blurLevel, false, context.feedback() );
53 drawBlurredImage( context, im );
54}
55
56void QgsBlurEffect::drawGaussianBlur( QgsRenderContext &context )
57{
58 const int blurLevel = std::round( context.convertToPainterUnits( mBlurLevel, mBlurUnit, mBlurMapUnitScale, Qgis::RenderSubcomponentProperty::BlurSize ) );
59
60 QImage source = sourceAsImage( context ).copy();
61 QImage *im = QgsImageOperation::gaussianBlur( source, blurLevel, context.feedback() );
62 if ( !im->isNull() )
63 drawBlurredImage( context, *im );
64 delete im;
65}
66
67void QgsBlurEffect::drawBlurredImage( QgsRenderContext &context, QImage &image )
68{
69 //opacity
70 QgsImageOperation::multiplyOpacity( image, mOpacity, context.feedback() );
71
72 QPainter *painter = context.painter();
73 const QgsScopedQPainterState painterState( painter );
74 painter->setCompositionMode( mBlendMode );
75 painter->drawImage( imageOffset( context ), image );
76}
77
78QVariantMap QgsBlurEffect::properties() const
79{
80 QVariantMap props;
81 props.insert( QStringLiteral( "enabled" ), mEnabled ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
82 props.insert( QStringLiteral( "draw_mode" ), QString::number( static_cast< int >( mDrawMode ) ) );
83 props.insert( QStringLiteral( "blend_mode" ), QString::number( static_cast< int >( mBlendMode ) ) );
84 props.insert( QStringLiteral( "opacity" ), QString::number( mOpacity ) );
85 props.insert( QStringLiteral( "blur_level" ), QString::number( mBlurLevel ) );
86 props.insert( QStringLiteral( "blur_unit" ), QgsUnitTypes::encodeUnit( mBlurUnit ) );
87 props.insert( QStringLiteral( "blur_unit_scale" ), QgsSymbolLayerUtils::encodeMapUnitScale( mBlurMapUnitScale ) );
88 props.insert( QStringLiteral( "blur_method" ), QString::number( static_cast< int >( mBlurMethod ) ) );
89 return props;
90}
91
92void QgsBlurEffect::readProperties( const QVariantMap &props )
93{
94 bool ok;
95 const QPainter::CompositionMode mode = static_cast< QPainter::CompositionMode >( props.value( QStringLiteral( "blend_mode" ) ).toInt( &ok ) );
96 if ( ok )
97 {
98 mBlendMode = mode;
99 }
100 if ( props.contains( QStringLiteral( "transparency" ) ) )
101 {
102 const double transparency = props.value( QStringLiteral( "transparency" ) ).toDouble( &ok );
103 if ( ok )
104 {
105 mOpacity = 1.0 - transparency;
106 }
107 }
108 else
109 {
110 const double opacity = props.value( QStringLiteral( "opacity" ) ).toDouble( &ok );
111 if ( ok )
112 {
113 mOpacity = opacity;
114 }
115 }
116
117 mEnabled = props.value( QStringLiteral( "enabled" ), QStringLiteral( "1" ) ).toInt();
118 mDrawMode = static_cast< QgsPaintEffect::DrawMode >( props.value( QStringLiteral( "draw_mode" ), QStringLiteral( "2" ) ).toInt() );
119 const double level = props.value( QStringLiteral( "blur_level" ) ).toDouble( &ok );
120 if ( ok )
121 {
122 mBlurLevel = level;
123 if ( !props.contains( QStringLiteral( "blur_unit" ) ) )
124 {
125 // deal with pre blur unit era by assuming 96 dpi and converting pixel values as millimeters
126 mBlurLevel *= 0.2645;
127 }
128 }
129 mBlurUnit = QgsUnitTypes::decodeRenderUnit( props.value( QStringLiteral( "blur_unit" ) ).toString() );
130 mBlurMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( props.value( QStringLiteral( "blur_unit_scale" ) ).toString() );
131 const QgsBlurEffect::BlurMethod method = static_cast< QgsBlurEffect::BlurMethod >( props.value( QStringLiteral( "blur_method" ) ).toInt( &ok ) );
132 if ( ok )
133 {
134 mBlurMethod = method;
135 }
136}
137
139{
140 QgsBlurEffect *newEffect = new QgsBlurEffect( *this );
141 return newEffect;
142}
143
144QRectF QgsBlurEffect::boundingRect( const QRectF &rect, const QgsRenderContext &context ) const
145{
146 const int blurLevel = std::round( context.convertToPainterUnits( mBlurLevel, mBlurUnit, mBlurMapUnitScale, Qgis::RenderSubcomponentProperty::BlurSize ) );
147
148 //plus possible extension due to blur, with a couple of extra pixels thrown in for safety
149 const double spread = blurLevel * 2.0 + 10;
150 return rect.adjusted( -spread, -spread, spread, spread );
151}
A paint effect which blurs a source picture, using a number of different blur methods.
QgsBlurEffect * clone() const override
Duplicates an effect by creating a deep copy of the effect.
QVariantMap properties() const override
Returns the properties describing the paint effect encoded in a string format.
void draw(QgsRenderContext &context) override
Handles drawing of the effect's result on to the specified render context.
QRectF boundingRect(const QRectF &rect, const QgsRenderContext &context) const override
Returns the bounding rect required for drawing the effect.
static QgsPaintEffect * create(const QVariantMap &map)
Creates a new QgsBlurEffect effect from a properties string map.
QgsBlurEffect()=default
void readProperties(const QVariantMap &props) override
Reads a string map of an effect's properties and restores the effect to the state described by the pr...
BlurMethod
Available blur methods (algorithms)
@ GaussianBlur
Gaussian blur, a slower but high quality blur. Blur level values are the distance in pixels for the b...
@ StackBlur
Stack blur, a fast but low quality blur. Valid blur level values are between 0 - 16.
double opacity() const
Returns the opacity for the effect.
double blurLevel() const
Returns the blur level (radius)
static void multiplyOpacity(QImage &image, double factor, QgsFeedback *feedback=nullptr)
Multiplies opacity of image pixel values by a factor.
static QImage * gaussianBlur(QImage &image, int radius, QgsFeedback *feedback=nullptr)
Performs a gaussian blur on an image.
static void stackBlur(QImage &image, int radius, bool alphaOnly=false, QgsFeedback *feedback=nullptr)
Performs a stack blur on an image.
Base class for visual effects which can be applied to QPicture drawings.
QImage sourceAsImage(QgsRenderContext &context)
Returns the source QPicture rendered to a new QImage.
const QPicture & source() const
Returns the source QPicture.
QPointF imageOffset(const QgsRenderContext &context) const
Returns the offset which should be used when drawing the source image on to a destination render cont...
bool enabled() const
Returns whether the effect is enabled.
DrawMode
Drawing modes for effects.
Contains information about the context of a rendering operation.
double convertToPainterUnits(double size, Qgis::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
QPainter * painter()
Returns the destination QPainter for the render operation.
QgsFeedback * feedback() const
Returns the feedback object that can be queried regularly during rendering to check if rendering shou...
Scoped object for saving and restoring a QPainter object's state.
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
static Q_INVOKABLE Qgis::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.
static Q_INVOKABLE QString encodeUnit(Qgis::DistanceUnit unit)
Encodes a distance unit to a string.