QGIS API Documentation  3.13.0-Master (b73bd58cfb)
qgsrasterpipe.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsrasterpipe.cpp - Internal raster processing modules interface
3  --------------------------------------
4  Date : Jun 21, 2012
5  Copyright : (C) 2012 by Radim Blazek
6  email : radim dot blazek 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 <typeinfo>
19 
20 #include <QByteArray>
21 
22 #include "qgslogger.h"
23 #include "qgsrasterpipe.h"
24 #include "qgsrasterdataprovider.h"
25 #include "qgsrasterrenderer.h"
28 #include "qgshuesaturationfilter.h"
29 #include "qgsrasterprojector.h"
30 #include "qgsrasternuller.h"
31 
33 {
34  for ( int i = 0; i < pipe.size(); i++ )
35  {
36  QgsRasterInterface *interface = pipe.at( i );
37  QgsRasterInterface *clone = interface->clone();
38 
39  Role role = interfaceRole( clone );
40  QgsDebugMsgLevel( QStringLiteral( "cloned interface with role %1" ).arg( role ), 4 );
41  if ( i > 0 )
42  {
43  clone->setInput( mInterfaces.at( i - 1 ) );
44  }
45  mInterfaces.append( clone );
46  if ( role != UnknownRole )
47  {
48  mRoleMap.insert( role, i );
49  }
50  }
51 }
52 
54 {
55  const auto constMInterfaces = mInterfaces;
56  for ( QgsRasterInterface *interface : constMInterfaces )
57  {
58  delete interface;
59  }
60 }
61 
62 bool QgsRasterPipe::connect( QVector<QgsRasterInterface *> interfaces )
63 {
64  QgsDebugMsgLevel( QStringLiteral( "Entered" ), 4 );
65  for ( int i = 1; i < interfaces.size(); i++ )
66  {
67  if ( ! interfaces[i]->setInput( interfaces[i - 1] ) )
68  {
69 #ifdef QGISDEBUG
70  const QgsRasterInterface &a = *interfaces[i];
71  const QgsRasterInterface &b = *interfaces[i - 1];
72  QgsDebugMsg( QStringLiteral( "cannot connect %1 to %2" ).arg( typeid( a ).name(), typeid( b ).name() ) );
73 #endif
74  return false;
75  }
76  }
77  return true;
78 }
79 
80 bool QgsRasterPipe::insert( int idx, QgsRasterInterface *interface )
81 {
82  QgsDebugMsgLevel( QStringLiteral( "insert %1 at %2" ).arg( typeid( *interface ).name() ).arg( idx ), 4 );
83  if ( idx > mInterfaces.size() )
84  {
85  idx = mInterfaces.size();
86  }
87  // make a copy of pipe to test connection, we test the connections
88  // of the whole pipe, because the types and band numbers may change
89  QVector<QgsRasterInterface *> interfaces = mInterfaces;
90 
91  interfaces.insert( idx, interface );
92  bool success = false;
93  if ( connect( interfaces ) )
94  {
95  success = true;
96  mInterfaces.insert( idx, interface );
97  setRole( interface, idx );
98  QgsDebugMsgLevel( QStringLiteral( "inserted OK" ), 4 );
99  }
100 
101  // Connect or reconnect (after the test) interfaces
102  connect( mInterfaces );
103  return success;
104 }
105 
106 bool QgsRasterPipe::replace( int idx, QgsRasterInterface *interface )
107 {
108  if ( !interface ) return false;
109 
110  QgsDebugMsgLevel( QStringLiteral( "replace by %1 at %2" ).arg( typeid( *interface ).name() ).arg( idx ), 4 );
111  if ( !checkBounds( idx ) ) return false;
112 
113  // make a copy of pipe to test connection, we test the connections
114  // of the whole pipe, because the types and band numbers may change
115  QVector<QgsRasterInterface *> interfaces = mInterfaces;
116 
117  interfaces[idx] = interface;
118  bool success = false;
119  if ( connect( interfaces ) )
120  {
121  success = true;
122  delete mInterfaces.at( idx );
123  mInterfaces[idx] = interface;
124  setRole( interface, idx );
125  QgsDebugMsgLevel( QStringLiteral( "replaced OK" ), 4 );
126  }
127 
128  // Connect or reconnect (after the test) interfaces
129  connect( mInterfaces );
130  return success;
131 }
132 
133 QgsRasterPipe::Role QgsRasterPipe::interfaceRole( QgsRasterInterface *interface ) const
134 {
135  Role role = UnknownRole;
136  if ( dynamic_cast<QgsRasterDataProvider *>( interface ) ) role = ProviderRole;
137  else if ( dynamic_cast<QgsRasterRenderer *>( interface ) ) role = RendererRole;
138  else if ( dynamic_cast<QgsRasterResampleFilter *>( interface ) ) role = ResamplerRole;
139  else if ( dynamic_cast<QgsBrightnessContrastFilter *>( interface ) ) role = BrightnessRole;
140  else if ( dynamic_cast<QgsHueSaturationFilter *>( interface ) ) role = HueSaturationRole;
141  else if ( dynamic_cast<QgsRasterProjector *>( interface ) ) role = ProjectorRole;
142  else if ( dynamic_cast<QgsRasterNuller *>( interface ) ) role = NullerRole;
143 
144  QgsDebugMsgLevel( QStringLiteral( "%1 role = %2" ).arg( typeid( *interface ).name() ).arg( role ), 4 );
145  return role;
146 }
147 
148 void QgsRasterPipe::setRole( QgsRasterInterface *interface, int idx )
149 {
150  Role role = interfaceRole( interface );
151  if ( role == UnknownRole ) return;
152  mRoleMap.insert( role, idx );
153 }
154 
155 void QgsRasterPipe::unsetRole( QgsRasterInterface *interface )
156 {
157  Role role = interfaceRole( interface );
158  if ( role == UnknownRole ) return;
159  mRoleMap.remove( role );
160 }
161 
163 {
164  if ( !interface ) return false;
165 
166  QgsDebugMsgLevel( QStringLiteral( "%1" ).arg( typeid( *interface ).name() ), 4 );
167  Role role = interfaceRole( interface );
168 
169  // We don't know where to place unknown interface
170  if ( role == UnknownRole ) return false;
171 
172  //if ( mInterfacesMap.value ( role ) )
173  if ( mRoleMap.contains( role ) )
174  {
175  // An old interface of the same role exists -> replace
176  // replace may still fail and return false
177  return replace( mRoleMap.value( role ), interface );
178  }
179 
180  int idx = 0;
181 
182  // Not found, find the best default position for this kind of interface
183  // QgsRasterDataProvider - ProviderRole
184  // QgsRasterRenderer - RendererRole
185  // QgsRasterResampler - ResamplerRole
186  // QgsRasterProjector - ProjectorRole
187 
188  int providerIdx = mRoleMap.value( ProviderRole, -1 );
189  int rendererIdx = mRoleMap.value( RendererRole, -1 );
190  int resamplerIdx = mRoleMap.value( ResamplerRole, -1 );
191  int brightnessIdx = mRoleMap.value( BrightnessRole, -1 );
192  int hueSaturationIdx = mRoleMap.value( HueSaturationRole, -1 );
193 
194  if ( role == ProviderRole )
195  {
196  idx = 0;
197  }
198  else if ( role == RendererRole )
199  {
200  idx = providerIdx + 1;
201  }
202  else if ( role == BrightnessRole )
203  {
204  idx = std::max( providerIdx, rendererIdx ) + 1;
205  }
206  else if ( role == HueSaturationRole )
207  {
208  idx = std::max( std::max( providerIdx, rendererIdx ), brightnessIdx ) + 1;
209  }
210  else if ( role == ResamplerRole )
211  {
212  idx = std::max( std::max( std::max( providerIdx, rendererIdx ), brightnessIdx ), hueSaturationIdx ) + 1;
213  }
214  else if ( role == ProjectorRole )
215  {
216  idx = std::max( std::max( std::max( std::max( providerIdx, rendererIdx ), brightnessIdx ), hueSaturationIdx ), resamplerIdx ) + 1;
217  }
218 
219  return insert( idx, interface ); // insert may still fail and return false
220 }
221 
222 QgsRasterInterface *QgsRasterPipe::interface( Role role ) const
223 {
224  QgsDebugMsgLevel( QStringLiteral( "role = %1" ).arg( role ), 4 );
225  if ( mRoleMap.contains( role ) )
226  {
227  return mInterfaces.value( mRoleMap.value( role ) );
228  }
229  return nullptr;
230 }
231 
233 {
234  return dynamic_cast<QgsRasterDataProvider *>( interface( ProviderRole ) );
235 }
236 
238 {
239  return dynamic_cast<QgsRasterRenderer *>( interface( RendererRole ) );
240 }
241 
243 {
244  return dynamic_cast<QgsRasterResampleFilter *>( interface( ResamplerRole ) );
245 }
246 
248 {
249  return dynamic_cast<QgsBrightnessContrastFilter *>( interface( BrightnessRole ) );
250 }
251 
253 {
254  return dynamic_cast<QgsHueSaturationFilter *>( interface( HueSaturationRole ) );
255 }
256 
258 {
259  return dynamic_cast<QgsRasterProjector *>( interface( ProjectorRole ) );
260 }
261 
263 {
264  return dynamic_cast<QgsRasterNuller *>( interface( NullerRole ) );
265 }
266 
267 bool QgsRasterPipe::remove( int idx )
268 {
269  QgsDebugMsgLevel( QStringLiteral( "remove at %1" ).arg( idx ), 4 );
270 
271  if ( !checkBounds( idx ) ) return false;
272 
273  // make a copy of pipe to test connection, we test the connections
274  // of the whole pipe, because the types and band numbers may change
275  QVector<QgsRasterInterface *> interfaces = mInterfaces;
276 
277  interfaces.remove( idx );
278  bool success = false;
279  if ( connect( interfaces ) )
280  {
281  success = true;
282  unsetRole( mInterfaces.at( idx ) );
283  delete mInterfaces.at( idx );
284  mInterfaces.remove( idx );
285  QgsDebugMsgLevel( QStringLiteral( "removed OK" ), 4 );
286  }
287 
288  // Connect or reconnect (after the test) interfaces
289  connect( mInterfaces );
290  return success;
291 }
292 
294 {
295  if ( !interface ) return false;
296 
297  return remove( mInterfaces.indexOf( interface ) );
298 }
299 
300 bool QgsRasterPipe::canSetOn( int idx, bool on )
301 {
302  QgsDebugMsgLevel( QStringLiteral( "idx = %1 on = %2" ).arg( idx ).arg( on ), 4 );
303  if ( !checkBounds( idx ) ) return false;
304 
305  // Because setting interface on/off may change its output we must check if
306  // connection is OK after such switch
307  bool onOrig = mInterfaces.at( idx )->on();
308 
309  if ( onOrig == on ) return true;
310 
311  mInterfaces.at( idx )->setOn( on );
312 
313  bool success = connect( mInterfaces );
314 
315  mInterfaces.at( idx )->setOn( onOrig );
316  connect( mInterfaces );
317  return success;
318 }
319 
320 bool QgsRasterPipe::setOn( int idx, bool on )
321 {
322  QgsDebugMsgLevel( QStringLiteral( "idx = %1 on = %2" ).arg( idx ).arg( on ), 4 );
323  if ( !checkBounds( idx ) ) return false;
324 
325  bool onOrig = mInterfaces.at( idx )->on();
326 
327  if ( onOrig == on ) return true;
328 
329  mInterfaces.at( idx )->setOn( on );
330 
331  if ( connect( mInterfaces ) ) return true;
332 
333  mInterfaces.at( idx )->setOn( onOrig );
334  connect( mInterfaces );
335 
336  return false;
337 }
338 
339 bool QgsRasterPipe::checkBounds( int idx ) const
340 {
341  return !( idx < 0 || idx >= mInterfaces.size() );
342 }
Base class for processing modules.
Definition: qgsrasterpipe.h:46
QgsRasterRenderer * renderer() const
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
QgsRasterResampleFilter * resampleFilter() const
QgsRasterProjector * projector() const
Raster pipe that deals with null values.
bool insert(int idx, QgsRasterInterface *interface)
Try to insert interface at specified index and connect if connection would fail, the interface is not...
Resample filter pipe for rasters.
bool replace(int idx, QgsRasterInterface *interface)
Try to replace interface at specified index and connect if connection would fail, the interface is no...
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
Base class for processing filters like renderers, reprojector, resampler etc.
int size() const
QgsRasterProjector implements approximate projection support for it calculates grid of points in sour...
bool canSetOn(int idx, bool on)
Test if interface at index may be switched on/off.
bool set(QgsRasterInterface *interface)
Insert a new known interface in default place or replace interface of the same role if it already exi...
bool remove(int idx)
Remove and delete interface at given index if possible.
bool setOn(int idx, bool on)
Set interface at index on/off Returns true on success.
virtual QgsRasterInterface * clone() const =0
Clone itself, create deep copy.
Brightness/contrast filter pipe for rasters.
Color and saturation filter pipe for rasters.
QgsRasterDataProvider * provider() const
QgsRasterNuller * nuller() const
QgsBrightnessContrastFilter * brightnessFilter() const
QgsHueSaturationFilter * hueSaturationFilter() const
Raster renderer pipe that applies colors to a raster.
Base class for raster data providers.
QgsRasterPipe()=default
Constructor for QgsRasterPipe.