QGIS API Documentation  3.14.0-Pi (9f7028fd23)
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 }
qgsrasterprojector.h
QgsRasterPipe::setOn
bool setOn(int idx, bool on)
Set interface at index on/off Returns true on success.
Definition: qgsrasterpipe.cpp:320
QgsRasterPipe::ProviderRole
@ ProviderRole
Definition: qgsrasterpipe.h:53
qgsrasterpipe.h
QgsRasterPipe::insert
bool insert(int idx, QgsRasterInterface *interface)
Try to insert interface at specified index and connect if connection would fail, the interface is not...
Definition: qgsrasterpipe.cpp:80
QgsRasterPipe::ResamplerRole
@ ResamplerRole
Definition: qgsrasterpipe.h:56
QgsDebugMsgLevel
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
QgsRasterPipe::NullerRole
@ NullerRole
Definition: qgsrasterpipe.h:58
QgsRasterPipe::~QgsRasterPipe
~QgsRasterPipe()
Definition: qgsrasterpipe.cpp:53
QgsRasterPipe::canSetOn
bool canSetOn(int idx, bool on)
Test if interface at index may be switched on/off.
Definition: qgsrasterpipe.cpp:300
QgsRasterPipe::set
bool set(QgsRasterInterface *interface)
Insert a new known interface in default place or replace interface of the same role if it already exi...
Definition: qgsrasterpipe.cpp:162
QgsRasterPipe
Definition: qgsrasterpipe.h:46
QgsRasterPipe::BrightnessRole
@ BrightnessRole
Definition: qgsrasterpipe.h:55
qgsrasterrenderer.h
QgsRasterNuller
Definition: qgsrasternuller.h:32
QgsDebugMsg
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
QgsRasterPipe::provider
QgsRasterDataProvider * provider() const
Definition: qgsrasterpipe.cpp:232
QgsRasterProjector
QgsRasterProjector implements approximate projection support for it calculates grid of points in sour...
Definition: qgsrasterprojector.h:47
QgsRasterPipe::Role
Role
Definition: qgsrasterpipe.h:50
QgsRasterPipe::remove
bool remove(int idx)
Remove and delete interface at given index if possible.
Definition: qgsrasterpipe.cpp:267
QgsRasterPipe::RendererRole
@ RendererRole
Definition: qgsrasterpipe.h:54
QgsRasterPipe::brightnessFilter
QgsBrightnessContrastFilter * brightnessFilter() const
Definition: qgsrasterpipe.cpp:247
QgsRasterPipe::ProjectorRole
@ ProjectorRole
Definition: qgsrasterpipe.h:57
QgsRasterPipe::renderer
QgsRasterRenderer * renderer() const
Definition: qgsrasterpipe.cpp:237
QgsRasterRenderer
Definition: qgsrasterrenderer.h:38
QgsRasterInterface::clone
virtual QgsRasterInterface * clone() const =0
Clone itself, create deep copy.
QgsRasterPipe::UnknownRole
@ UnknownRole
Definition: qgsrasterpipe.h:52
QgsHueSaturationFilter
Definition: qgshuesaturationfilter.h:31
QgsRasterPipe::HueSaturationRole
@ HueSaturationRole
Definition: qgsrasterpipe.h:59
QgsRasterPipe::hueSaturationFilter
QgsHueSaturationFilter * hueSaturationFilter() const
Definition: qgsrasterpipe.cpp:252
qgsrasterresamplefilter.h
qgsbrightnesscontrastfilter.h
qgshuesaturationfilter.h
QgsRasterPipe::replace
bool replace(int idx, QgsRasterInterface *interface)
Try to replace interface at specified index and connect if connection would fail, the interface is no...
Definition: qgsrasterpipe.cpp:106
QgsRasterInterface
Definition: qgsrasterinterface.h:116
QgsBrightnessContrastFilter
Definition: qgsbrightnesscontrastfilter.h:31
QgsRasterResampleFilter
Definition: qgsrasterresamplefilter.h:32
QgsRasterPipe::resampleFilter
QgsRasterResampleFilter * resampleFilter() const
Definition: qgsrasterpipe.cpp:242
QgsRasterPipe::projector
QgsRasterProjector * projector() const
Definition: qgsrasterpipe.cpp:257
QgsRasterPipe::QgsRasterPipe
QgsRasterPipe()=default
Constructor for QgsRasterPipe.
qgslogger.h
qgsrasternuller.h
QgsRasterDataProvider
Definition: qgsrasterdataprovider.h:88
QgsRasterPipe::size
int size() const
Definition: qgsrasterpipe.h:112
QgsRasterPipe::nuller
QgsRasterNuller * nuller() const
Definition: qgsrasterpipe.cpp:262
qgsrasterdataprovider.h