QGIS API Documentation  3.20.0-Odense (decaadbb31)
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 
23 QgsPaintEffect *QgsBlurEffect::create( const QVariantMap &map )
24 {
25  QgsBlurEffect *newEffect = new QgsBlurEffect();
26  newEffect->readProperties( map );
27  return newEffect;
28 }
29 
31 {
32  if ( !source() || !enabled() || !context.painter() )
33  return;
34 
35  switch ( mBlurMethod )
36  {
37  case StackBlur:
38  drawStackBlur( context );
39  break;
40  case GaussianBlur:
41  drawGaussianBlur( context );
42  break;
43  }
44 }
45 
46 void QgsBlurEffect::drawStackBlur( QgsRenderContext &context )
47 {
48  int blurLevel = std::round( context.convertToPainterUnits( mBlurLevel, mBlurUnit, mBlurMapUnitScale ) );
49  QImage im = sourceAsImage( context )->copy();
51  drawBlurredImage( context, im );
52 }
53 
54 void QgsBlurEffect::drawGaussianBlur( QgsRenderContext &context )
55 {
56  int blurLevel = std::round( context.convertToPainterUnits( mBlurLevel, mBlurUnit, mBlurMapUnitScale ) );
57  QImage *im = QgsImageOperation::gaussianBlur( *sourceAsImage( context ), blurLevel );
58  drawBlurredImage( context, *im );
59  delete im;
60 }
61 
62 void QgsBlurEffect::drawBlurredImage( QgsRenderContext &context, QImage &image )
63 {
64  //opacity
65  QgsImageOperation::multiplyOpacity( image, mOpacity );
66 
67  QPainter *painter = context.painter();
68  QgsScopedQPainterState painterState( painter );
69  painter->setCompositionMode( mBlendMode );
70  painter->drawImage( imageOffset( context ), image );
71 }
72 
73 QVariantMap QgsBlurEffect::properties() const
74 {
75  QVariantMap props;
76  props.insert( QStringLiteral( "enabled" ), mEnabled ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
77  props.insert( QStringLiteral( "draw_mode" ), QString::number( static_cast< int >( mDrawMode ) ) );
78  props.insert( QStringLiteral( "blend_mode" ), QString::number( static_cast< int >( mBlendMode ) ) );
79  props.insert( QStringLiteral( "opacity" ), QString::number( mOpacity ) );
80  props.insert( QStringLiteral( "blur_level" ), QString::number( mBlurLevel ) );
81  props.insert( QStringLiteral( "blur_unit" ), QgsUnitTypes::encodeUnit( mBlurUnit ) );
82  props.insert( QStringLiteral( "blur_unit_scale" ), QgsSymbolLayerUtils::encodeMapUnitScale( mBlurMapUnitScale ) );
83  props.insert( QStringLiteral( "blur_method" ), QString::number( static_cast< int >( mBlurMethod ) ) );
84  return props;
85 }
86 
87 void QgsBlurEffect::readProperties( const QVariantMap &props )
88 {
89  bool ok;
90  QPainter::CompositionMode mode = static_cast< QPainter::CompositionMode >( props.value( QStringLiteral( "blend_mode" ) ).toInt( &ok ) );
91  if ( ok )
92  {
93  mBlendMode = mode;
94  }
95  if ( props.contains( QStringLiteral( "transparency" ) ) )
96  {
97  double transparency = props.value( QStringLiteral( "transparency" ) ).toDouble( &ok );
98  if ( ok )
99  {
100  mOpacity = 1.0 - transparency;
101  }
102  }
103  else
104  {
105  double opacity = props.value( QStringLiteral( "opacity" ) ).toDouble( &ok );
106  if ( ok )
107  {
108  mOpacity = opacity;
109  }
110  }
111 
112  mEnabled = props.value( QStringLiteral( "enabled" ), QStringLiteral( "1" ) ).toInt();
113  mDrawMode = static_cast< QgsPaintEffect::DrawMode >( props.value( QStringLiteral( "draw_mode" ), QStringLiteral( "2" ) ).toInt() );
114  double level = props.value( QStringLiteral( "blur_level" ) ).toDouble( &ok );
115  if ( ok )
116  {
117  mBlurLevel = level;
118  if ( !props.contains( QStringLiteral( "blur_unit" ) ) )
119  {
120  // deal with pre blur unit era by assuming 96 dpi and converting pixel values as millimeters
121  mBlurLevel *= 0.2645;
122  }
123  }
124  mBlurUnit = QgsUnitTypes::decodeRenderUnit( props.value( QStringLiteral( "blur_unit" ) ).toString() );
125  mBlurMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( props.value( QStringLiteral( "blur_unit_scale" ) ).toString() );
126  QgsBlurEffect::BlurMethod method = static_cast< QgsBlurEffect::BlurMethod >( props.value( QStringLiteral( "blur_method" ) ).toInt( &ok ) );
127  if ( ok )
128  {
129  mBlurMethod = method;
130  }
131 }
132 
134 {
135  QgsBlurEffect *newEffect = new QgsBlurEffect( *this );
136  return newEffect;
137 }
138 
139 QRectF QgsBlurEffect::boundingRect( const QRectF &rect, const QgsRenderContext &context ) const
140 {
141  int blurLevel = std::round( context.convertToPainterUnits( mBlurLevel, mBlurUnit, mBlurMapUnitScale ) );
142  //plus possible extension due to blur, with a couple of extra pixels thrown in for safety
143  double spread = blurLevel * 2.0 + 10;
144  return rect.adjusted( -spread, -spread, spread, spread );
145 }
A paint effect which blurs a source picture, using a number of different blur methods.
Definition: qgsblureffect.h:38
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
Constructor for QgsBlurEffect.
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)
Definition: qgsblureffect.h:44
@ GaussianBlur
Gaussian blur, a slower but high quality blur. Blur level values are the distance in pixels for the b...
Definition: qgsblureffect.h:46
@ StackBlur
Stack blur, a fast but low quality blur. Valid blur level values are between 0 - 16.
Definition: qgsblureffect.h:45
double opacity() const
Returns the opacity for the effect.
double blurLevel() const
Returns the blur level (radius)
Definition: qgsblureffect.h:86
static void multiplyOpacity(QImage &image, double factor)
Multiplies opacity of image pixel values by a factor.
static void stackBlur(QImage &image, int radius, bool alphaOnly=false)
Performs a stack blur on an image.
static QImage * gaussianBlur(QImage &image, int radius)
Performs a gaussian blur on an image.
Base class for visual effects which can be applied to QPicture drawings.
DrawMode mDrawMode
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.
QImage * sourceAsImage(QgsRenderContext &context)
Returns the source QPicture rendered to a new QImage.
Contains information about the context of a rendering operation.
QPainter * painter()
Returns the destination QPainter for the render operation.
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale()) const
Converts a size from the specified units to painter units (pixels).
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 QString encodeUnit(QgsUnitTypes::DistanceUnit unit)
Encodes a distance unit to a string.
static Q_INVOKABLE QgsUnitTypes::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.