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"
26 #include "qgsrasterresamplefilter.h"
27 #include "qgsbrightnesscontrastfilter.h"
28 #include "qgshuesaturationfilter.h"
29 #include "qgsrasterprojector.h"
30 #include "qgsrasternuller.h"
31
QgsRasterPipe(const QgsRasterPipe & pipe)32 QgsRasterPipe::QgsRasterPipe( const QgsRasterPipe &pipe )
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 setResamplingStage( pipe.resamplingStage() );
52 }
53
~QgsRasterPipe()54 QgsRasterPipe::~QgsRasterPipe()
55 {
56 const auto constMInterfaces = mInterfaces;
57 for ( QgsRasterInterface *interface : constMInterfaces )
58 {
59 delete interface;
60 }
61 }
62
connect(QVector<QgsRasterInterface * > interfaces)63 bool QgsRasterPipe::connect( QVector<QgsRasterInterface *> interfaces )
64 {
65 QgsDebugMsgLevel( QStringLiteral( "Entered" ), 4 );
66 for ( int i = 1; i < interfaces.size(); i++ )
67 {
68 if ( ! interfaces[i]->setInput( interfaces[i - 1] ) )
69 {
70 #ifdef QGISDEBUG
71 const QgsRasterInterface &a = *interfaces[i];
72 const QgsRasterInterface &b = *interfaces[i - 1];
73 QgsDebugMsg( QStringLiteral( "cannot connect %1 to %2" ).arg( typeid( a ).name(), typeid( b ).name() ) );
74 #endif
75 return false;
76 }
77 }
78 return true;
79 }
80
insert(int idx,QgsRasterInterface * interface)81 bool QgsRasterPipe::insert( int idx, QgsRasterInterface *interface )
82 {
83 QgsDebugMsgLevel( QStringLiteral( "insert %1 at %2" ).arg( typeid( *interface ).name() ).arg( idx ), 4 );
84 if ( idx > mInterfaces.size() )
85 {
86 idx = mInterfaces.size();
87 }
88 // make a copy of pipe to test connection, we test the connections
89 // of the whole pipe, because the types and band numbers may change
90 QVector<QgsRasterInterface *> interfaces = mInterfaces;
91
92 interfaces.insert( idx, interface );
93 bool success = false;
94 if ( connect( interfaces ) )
95 {
96 success = true;
97 mInterfaces.insert( idx, interface );
98 setRole( interface, idx );
99 QgsDebugMsgLevel( QStringLiteral( "Pipe %1 inserted OK" ).arg( idx ), 4 );
100 }
101 else
102 {
103 QgsDebugMsgLevel( QStringLiteral( "Error inserting pipe %1" ).arg( idx ), 4 );
104 }
105
106 // Connect or reconnect (after the test) interfaces
107 connect( mInterfaces );
108 return success;
109 }
110
replace(int idx,QgsRasterInterface * interface)111 bool QgsRasterPipe::replace( int idx, QgsRasterInterface *interface )
112 {
113 if ( !interface ) return false;
114
115 QgsDebugMsgLevel( QStringLiteral( "replace by %1 at %2" ).arg( typeid( *interface ).name() ).arg( idx ), 4 );
116 if ( !checkBounds( idx ) ) return false;
117
118 // make a copy of pipe to test connection, we test the connections
119 // of the whole pipe, because the types and band numbers may change
120 QVector<QgsRasterInterface *> interfaces = mInterfaces;
121
122 interfaces[idx] = interface;
123 bool success = false;
124 if ( connect( interfaces ) )
125 {
126 success = true;
127 delete mInterfaces.at( idx );
128 mInterfaces[idx] = interface;
129 setRole( interface, idx );
130 QgsDebugMsgLevel( QStringLiteral( "replaced OK" ), 4 );
131 }
132
133 // Connect or reconnect (after the test) interfaces
134 connect( mInterfaces );
135 return success;
136 }
137
interfaceRole(QgsRasterInterface * interface) const138 QgsRasterPipe::Role QgsRasterPipe::interfaceRole( QgsRasterInterface *interface ) const
139 {
140 Role role = UnknownRole;
141 if ( dynamic_cast<QgsRasterDataProvider *>( interface ) ) role = ProviderRole;
142 else if ( dynamic_cast<QgsRasterRenderer *>( interface ) ) role = RendererRole;
143 else if ( dynamic_cast<QgsRasterResampleFilter *>( interface ) ) role = ResamplerRole;
144 else if ( dynamic_cast<QgsBrightnessContrastFilter *>( interface ) ) role = BrightnessRole;
145 else if ( dynamic_cast<QgsHueSaturationFilter *>( interface ) ) role = HueSaturationRole;
146 else if ( dynamic_cast<QgsRasterProjector *>( interface ) ) role = ProjectorRole;
147 else if ( dynamic_cast<QgsRasterNuller *>( interface ) ) role = NullerRole;
148
149 QgsDebugMsgLevel( QStringLiteral( "%1 role = %2" ).arg( typeid( *interface ).name() ).arg( role ), 4 );
150 return role;
151 }
152
setRole(QgsRasterInterface * interface,int idx)153 void QgsRasterPipe::setRole( QgsRasterInterface *interface, int idx )
154 {
155 Role role = interfaceRole( interface );
156 if ( role == UnknownRole ) return;
157 mRoleMap.insert( role, idx );
158 }
159
unsetRole(QgsRasterInterface * interface)160 void QgsRasterPipe::unsetRole( QgsRasterInterface *interface )
161 {
162 Role role = interfaceRole( interface );
163 if ( role == UnknownRole ) return;
164 const int roleIdx{ mRoleMap[role] };
165 mRoleMap.remove( role );
166
167 // Decrease all indexes greater than the removed one
168 const auto roleMapValues {mRoleMap.values()};
169 if ( roleIdx < *std::max_element( roleMapValues.begin(), roleMapValues.end() ) )
170 {
171 for ( auto it = mRoleMap.cbegin(); it != mRoleMap.cend(); ++it )
172 {
173 if ( it.value() > roleIdx )
174 {
175 mRoleMap[it.key()] = it.value() - 1;
176 }
177 }
178 }
179 }
180
set(QgsRasterInterface * interface)181 bool QgsRasterPipe::set( QgsRasterInterface *interface )
182 {
183 if ( !interface ) return false;
184
185 QgsDebugMsgLevel( typeid( *interface ).name(), 4 );
186 Role role = interfaceRole( interface );
187
188 // We don't know where to place unknown interface
189 if ( role == UnknownRole ) return false;
190
191 //if ( mInterfacesMap.value ( role ) )
192 if ( mRoleMap.contains( role ) )
193 {
194 // An old interface of the same role exists -> replace
195 // replace may still fail and return false
196 return replace( mRoleMap.value( role ), interface );
197 }
198
199 int idx = 0;
200
201 // Not found, find the best default position for this kind of interface
202 // QgsRasterDataProvider - ProviderRole
203 // QgsRasterRenderer - RendererRole
204 // QgsRasterResampler - ResamplerRole
205 // QgsRasterProjector - ProjectorRole
206
207 int providerIdx = mRoleMap.value( ProviderRole, -1 );
208 int rendererIdx = mRoleMap.value( RendererRole, -1 );
209 int resamplerIdx = mRoleMap.value( ResamplerRole, -1 );
210 int brightnessIdx = mRoleMap.value( BrightnessRole, -1 );
211 int hueSaturationIdx = mRoleMap.value( HueSaturationRole, -1 );
212
213 if ( role == ProviderRole )
214 {
215 idx = 0;
216 }
217 else if ( role == RendererRole )
218 {
219 idx = providerIdx + 1;
220 }
221 else if ( role == BrightnessRole )
222 {
223 idx = std::max( providerIdx, rendererIdx ) + 1;
224 }
225 else if ( role == HueSaturationRole )
226 {
227 idx = std::max( std::max( providerIdx, rendererIdx ), brightnessIdx ) + 1;
228 }
229 else if ( role == ResamplerRole )
230 {
231 idx = std::max( std::max( std::max( providerIdx, rendererIdx ), brightnessIdx ), hueSaturationIdx ) + 1;
232 }
233 else if ( role == ProjectorRole )
234 {
235 idx = std::max( std::max( std::max( std::max( providerIdx, rendererIdx ), brightnessIdx ), hueSaturationIdx ), resamplerIdx ) + 1;
236 }
237
238 return insert( idx, interface ); // insert may still fail and return false
239 }
240
interface(Role role) const241 QgsRasterInterface *QgsRasterPipe::interface( Role role ) const
242 {
243 QgsDebugMsgLevel( QStringLiteral( "role = %1" ).arg( role ), 4 );
244 if ( mRoleMap.contains( role ) )
245 {
246 return mInterfaces.value( mRoleMap.value( role ) );
247 }
248 return nullptr;
249 }
250
provider() const251 QgsRasterDataProvider *QgsRasterPipe::provider() const
252 {
253 return dynamic_cast<QgsRasterDataProvider *>( interface( ProviderRole ) );
254 }
255
renderer() const256 QgsRasterRenderer *QgsRasterPipe::renderer() const
257 {
258 return dynamic_cast<QgsRasterRenderer *>( interface( RendererRole ) );
259 }
260
resampleFilter() const261 QgsRasterResampleFilter *QgsRasterPipe::resampleFilter() const
262 {
263 return dynamic_cast<QgsRasterResampleFilter *>( interface( ResamplerRole ) );
264 }
265
brightnessFilter() const266 QgsBrightnessContrastFilter *QgsRasterPipe::brightnessFilter() const
267 {
268 return dynamic_cast<QgsBrightnessContrastFilter *>( interface( BrightnessRole ) );
269 }
270
hueSaturationFilter() const271 QgsHueSaturationFilter *QgsRasterPipe::hueSaturationFilter() const
272 {
273 return dynamic_cast<QgsHueSaturationFilter *>( interface( HueSaturationRole ) );
274 }
275
projector() const276 QgsRasterProjector *QgsRasterPipe::projector() const
277 {
278 return dynamic_cast<QgsRasterProjector *>( interface( ProjectorRole ) );
279 }
280
nuller() const281 QgsRasterNuller *QgsRasterPipe::nuller() const
282 {
283 return dynamic_cast<QgsRasterNuller *>( interface( NullerRole ) );
284 }
285
remove(int idx)286 bool QgsRasterPipe::remove( int idx )
287 {
288 QgsDebugMsgLevel( QStringLiteral( "remove at %1" ).arg( idx ), 4 );
289
290 if ( !checkBounds( idx ) ) return false;
291
292 // make a copy of pipe to test connection, we test the connections
293 // of the whole pipe, because the types and band numbers may change
294 QVector<QgsRasterInterface *> interfaces = mInterfaces;
295
296 interfaces.remove( idx );
297 bool success = false;
298 if ( connect( interfaces ) )
299 {
300 success = true;
301 unsetRole( mInterfaces.at( idx ) );
302 delete mInterfaces.at( idx );
303 mInterfaces.remove( idx );
304 QgsDebugMsgLevel( QStringLiteral( "Pipe %1 removed OK" ).arg( idx ), 4 );
305 }
306 else
307 {
308 QgsDebugMsgLevel( QStringLiteral( "Error removing pipe %1" ).arg( idx ), 4 );
309 }
310
311 // Connect or reconnect (after the test) interfaces
312 connect( mInterfaces );
313
314 return success;
315 }
316
remove(QgsRasterInterface * interface)317 bool QgsRasterPipe::remove( QgsRasterInterface *interface )
318 {
319 if ( !interface ) return false;
320
321 return remove( mInterfaces.indexOf( interface ) );
322 }
323
canSetOn(int idx,bool on)324 bool QgsRasterPipe::canSetOn( int idx, bool on )
325 {
326 QgsDebugMsgLevel( QStringLiteral( "idx = %1 on = %2" ).arg( idx ).arg( on ), 4 );
327 if ( !checkBounds( idx ) ) return false;
328
329 // Because setting interface on/off may change its output we must check if
330 // connection is OK after such switch
331 bool onOrig = mInterfaces.at( idx )->on();
332
333 if ( onOrig == on ) return true;
334
335 mInterfaces.at( idx )->setOn( on );
336
337 bool success = connect( mInterfaces );
338
339 mInterfaces.at( idx )->setOn( onOrig );
340 connect( mInterfaces );
341 return success;
342 }
343
setOn(int idx,bool on)344 bool QgsRasterPipe::setOn( int idx, bool on )
345 {
346 QgsDebugMsgLevel( QStringLiteral( "idx = %1 on = %2" ).arg( idx ).arg( on ), 4 );
347 if ( !checkBounds( idx ) ) return false;
348
349 bool onOrig = mInterfaces.at( idx )->on();
350
351 if ( onOrig == on ) return true;
352
353 mInterfaces.at( idx )->setOn( on );
354
355 if ( connect( mInterfaces ) ) return true;
356
357 mInterfaces.at( idx )->setOn( onOrig );
358 connect( mInterfaces );
359
360 return false;
361 }
362
checkBounds(int idx) const363 bool QgsRasterPipe::checkBounds( int idx ) const
364 {
365 return !( idx < 0 || idx >= mInterfaces.size() );
366 }
367
setResamplingStage(ResamplingStage stage)368 void QgsRasterPipe::setResamplingStage( ResamplingStage stage )
369 {
370 mResamplingStage = stage;
371 setOn( ResamplerRole, stage == ResamplingStage::ResampleFilter );
372 QgsRasterDataProvider *l_provider = provider();
373 if ( l_provider )
374 {
375 l_provider->enableProviderResampling( stage == ResamplingStage::Provider );
376 }
377 }
378