Branch data Line data Source code
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 : :
32 : 0 : QgsRasterPipe::QgsRasterPipe( const QgsRasterPipe &pipe )
33 : : {
34 : 0 : for ( int i = 0; i < pipe.size(); i++ )
35 : : {
36 : 0 : QgsRasterInterface *interface = pipe.at( i );
37 : 0 : QgsRasterInterface *clone = interface->clone();
38 : :
39 : 0 : Role role = interfaceRole( clone );
40 : 0 : QgsDebugMsgLevel( QStringLiteral( "cloned interface with role %1" ).arg( role ), 4 );
41 : 0 : if ( i > 0 )
42 : : {
43 : 0 : clone->setInput( mInterfaces.at( i - 1 ) );
44 : 0 : }
45 : 0 : mInterfaces.append( clone );
46 : 0 : if ( role != UnknownRole )
47 : : {
48 : 0 : mRoleMap.insert( role, i );
49 : 0 : }
50 : 0 : }
51 : 0 : setResamplingStage( pipe.resamplingStage() );
52 : 0 : }
53 : :
54 : 0 : QgsRasterPipe::~QgsRasterPipe()
55 : : {
56 : 0 : const auto constMInterfaces = mInterfaces;
57 : 0 : for ( QgsRasterInterface *interface : constMInterfaces )
58 : : {
59 : 0 : delete interface;
60 : : }
61 : 0 : }
62 : :
63 : 0 : bool QgsRasterPipe::connect( QVector<QgsRasterInterface *> interfaces )
64 : : {
65 : 0 : QgsDebugMsgLevel( QStringLiteral( "Entered" ), 4 );
66 : 0 : for ( int i = 1; i < interfaces.size(); i++ )
67 : : {
68 : 0 : 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 : 0 : return false;
76 : : }
77 : 0 : }
78 : 0 : return true;
79 : 0 : }
80 : :
81 : 0 : bool QgsRasterPipe::insert( int idx, QgsRasterInterface *interface )
82 : : {
83 : 0 : QgsDebugMsgLevel( QStringLiteral( "insert %1 at %2" ).arg( typeid( *interface ).name() ).arg( idx ), 4 );
84 : 0 : if ( idx > mInterfaces.size() )
85 : : {
86 : 0 : idx = mInterfaces.size();
87 : 0 : }
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 : 0 : QVector<QgsRasterInterface *> interfaces = mInterfaces;
91 : :
92 : 0 : interfaces.insert( idx, interface );
93 : 0 : bool success = false;
94 : 0 : if ( connect( interfaces ) )
95 : : {
96 : 0 : success = true;
97 : 0 : mInterfaces.insert( idx, interface );
98 : 0 : setRole( interface, idx );
99 : 0 : QgsDebugMsgLevel( QStringLiteral( "inserted OK" ), 4 );
100 : 0 : }
101 : :
102 : : // Connect or reconnect (after the test) interfaces
103 : 0 : connect( mInterfaces );
104 : 0 : return success;
105 : 0 : }
106 : :
107 : 0 : bool QgsRasterPipe::replace( int idx, QgsRasterInterface *interface )
108 : : {
109 : 0 : if ( !interface ) return false;
110 : :
111 : 0 : QgsDebugMsgLevel( QStringLiteral( "replace by %1 at %2" ).arg( typeid( *interface ).name() ).arg( idx ), 4 );
112 : 0 : if ( !checkBounds( idx ) ) return false;
113 : :
114 : : // make a copy of pipe to test connection, we test the connections
115 : : // of the whole pipe, because the types and band numbers may change
116 : 0 : QVector<QgsRasterInterface *> interfaces = mInterfaces;
117 : :
118 : 0 : interfaces[idx] = interface;
119 : 0 : bool success = false;
120 : 0 : if ( connect( interfaces ) )
121 : : {
122 : 0 : success = true;
123 : 0 : delete mInterfaces.at( idx );
124 : 0 : mInterfaces[idx] = interface;
125 : 0 : setRole( interface, idx );
126 : 0 : QgsDebugMsgLevel( QStringLiteral( "replaced OK" ), 4 );
127 : 0 : }
128 : :
129 : : // Connect or reconnect (after the test) interfaces
130 : 0 : connect( mInterfaces );
131 : 0 : return success;
132 : 0 : }
133 : :
134 : 0 : QgsRasterPipe::Role QgsRasterPipe::interfaceRole( QgsRasterInterface *interface ) const
135 : : {
136 : 0 : Role role = UnknownRole;
137 : 0 : if ( dynamic_cast<QgsRasterDataProvider *>( interface ) ) role = ProviderRole;
138 : 0 : else if ( dynamic_cast<QgsRasterRenderer *>( interface ) ) role = RendererRole;
139 : 0 : else if ( dynamic_cast<QgsRasterResampleFilter *>( interface ) ) role = ResamplerRole;
140 : 0 : else if ( dynamic_cast<QgsBrightnessContrastFilter *>( interface ) ) role = BrightnessRole;
141 : 0 : else if ( dynamic_cast<QgsHueSaturationFilter *>( interface ) ) role = HueSaturationRole;
142 : 0 : else if ( dynamic_cast<QgsRasterProjector *>( interface ) ) role = ProjectorRole;
143 : 0 : else if ( dynamic_cast<QgsRasterNuller *>( interface ) ) role = NullerRole;
144 : :
145 : 0 : QgsDebugMsgLevel( QStringLiteral( "%1 role = %2" ).arg( typeid( *interface ).name() ).arg( role ), 4 );
146 : 0 : return role;
147 : : }
148 : :
149 : 0 : void QgsRasterPipe::setRole( QgsRasterInterface *interface, int idx )
150 : : {
151 : 0 : Role role = interfaceRole( interface );
152 : 0 : if ( role == UnknownRole ) return;
153 : 0 : mRoleMap.insert( role, idx );
154 : 0 : }
155 : :
156 : 0 : void QgsRasterPipe::unsetRole( QgsRasterInterface *interface )
157 : : {
158 : 0 : Role role = interfaceRole( interface );
159 : 0 : if ( role == UnknownRole ) return;
160 : 0 : mRoleMap.remove( role );
161 : 0 : }
162 : :
163 : 0 : bool QgsRasterPipe::set( QgsRasterInterface *interface )
164 : : {
165 : 0 : if ( !interface ) return false;
166 : :
167 : 0 : QgsDebugMsgLevel( typeid( *interface ).name(), 4 );
168 : 0 : Role role = interfaceRole( interface );
169 : :
170 : : // We don't know where to place unknown interface
171 : 0 : if ( role == UnknownRole ) return false;
172 : :
173 : : //if ( mInterfacesMap.value ( role ) )
174 : 0 : if ( mRoleMap.contains( role ) )
175 : : {
176 : : // An old interface of the same role exists -> replace
177 : : // replace may still fail and return false
178 : 0 : return replace( mRoleMap.value( role ), interface );
179 : : }
180 : :
181 : 0 : int idx = 0;
182 : :
183 : : // Not found, find the best default position for this kind of interface
184 : : // QgsRasterDataProvider - ProviderRole
185 : : // QgsRasterRenderer - RendererRole
186 : : // QgsRasterResampler - ResamplerRole
187 : : // QgsRasterProjector - ProjectorRole
188 : :
189 : 0 : int providerIdx = mRoleMap.value( ProviderRole, -1 );
190 : 0 : int rendererIdx = mRoleMap.value( RendererRole, -1 );
191 : 0 : int resamplerIdx = mRoleMap.value( ResamplerRole, -1 );
192 : 0 : int brightnessIdx = mRoleMap.value( BrightnessRole, -1 );
193 : 0 : int hueSaturationIdx = mRoleMap.value( HueSaturationRole, -1 );
194 : :
195 : 0 : if ( role == ProviderRole )
196 : : {
197 : 0 : idx = 0;
198 : 0 : }
199 : 0 : else if ( role == RendererRole )
200 : : {
201 : 0 : idx = providerIdx + 1;
202 : 0 : }
203 : 0 : else if ( role == BrightnessRole )
204 : : {
205 : 0 : idx = std::max( providerIdx, rendererIdx ) + 1;
206 : 0 : }
207 : 0 : else if ( role == HueSaturationRole )
208 : : {
209 : 0 : idx = std::max( std::max( providerIdx, rendererIdx ), brightnessIdx ) + 1;
210 : 0 : }
211 : 0 : else if ( role == ResamplerRole )
212 : : {
213 : 0 : idx = std::max( std::max( std::max( providerIdx, rendererIdx ), brightnessIdx ), hueSaturationIdx ) + 1;
214 : 0 : }
215 : 0 : else if ( role == ProjectorRole )
216 : : {
217 : 0 : idx = std::max( std::max( std::max( std::max( providerIdx, rendererIdx ), brightnessIdx ), hueSaturationIdx ), resamplerIdx ) + 1;
218 : 0 : }
219 : :
220 : 0 : return insert( idx, interface ); // insert may still fail and return false
221 : 0 : }
222 : :
223 : 0 : QgsRasterInterface *QgsRasterPipe::interface( Role role ) const
224 : : {
225 : 0 : QgsDebugMsgLevel( QStringLiteral( "role = %1" ).arg( role ), 4 );
226 : 0 : if ( mRoleMap.contains( role ) )
227 : : {
228 : 0 : return mInterfaces.value( mRoleMap.value( role ) );
229 : : }
230 : 0 : return nullptr;
231 : 0 : }
232 : :
233 : 0 : QgsRasterDataProvider *QgsRasterPipe::provider() const
234 : : {
235 : 0 : return dynamic_cast<QgsRasterDataProvider *>( interface( ProviderRole ) );
236 : : }
237 : :
238 : 0 : QgsRasterRenderer *QgsRasterPipe::renderer() const
239 : : {
240 : 0 : return dynamic_cast<QgsRasterRenderer *>( interface( RendererRole ) );
241 : : }
242 : :
243 : 0 : QgsRasterResampleFilter *QgsRasterPipe::resampleFilter() const
244 : : {
245 : 0 : return dynamic_cast<QgsRasterResampleFilter *>( interface( ResamplerRole ) );
246 : : }
247 : :
248 : 0 : QgsBrightnessContrastFilter *QgsRasterPipe::brightnessFilter() const
249 : : {
250 : 0 : return dynamic_cast<QgsBrightnessContrastFilter *>( interface( BrightnessRole ) );
251 : : }
252 : :
253 : 0 : QgsHueSaturationFilter *QgsRasterPipe::hueSaturationFilter() const
254 : : {
255 : 0 : return dynamic_cast<QgsHueSaturationFilter *>( interface( HueSaturationRole ) );
256 : : }
257 : :
258 : 0 : QgsRasterProjector *QgsRasterPipe::projector() const
259 : : {
260 : 0 : return dynamic_cast<QgsRasterProjector *>( interface( ProjectorRole ) );
261 : : }
262 : :
263 : 0 : QgsRasterNuller *QgsRasterPipe::nuller() const
264 : : {
265 : 0 : return dynamic_cast<QgsRasterNuller *>( interface( NullerRole ) );
266 : : }
267 : :
268 : 0 : bool QgsRasterPipe::remove( int idx )
269 : : {
270 : 0 : QgsDebugMsgLevel( QStringLiteral( "remove at %1" ).arg( idx ), 4 );
271 : :
272 : 0 : if ( !checkBounds( idx ) ) return false;
273 : :
274 : : // make a copy of pipe to test connection, we test the connections
275 : : // of the whole pipe, because the types and band numbers may change
276 : 0 : QVector<QgsRasterInterface *> interfaces = mInterfaces;
277 : :
278 : 0 : interfaces.remove( idx );
279 : 0 : bool success = false;
280 : 0 : if ( connect( interfaces ) )
281 : : {
282 : 0 : success = true;
283 : 0 : unsetRole( mInterfaces.at( idx ) );
284 : 0 : delete mInterfaces.at( idx );
285 : 0 : mInterfaces.remove( idx );
286 : 0 : QgsDebugMsgLevel( QStringLiteral( "removed OK" ), 4 );
287 : 0 : }
288 : :
289 : : // Connect or reconnect (after the test) interfaces
290 : 0 : connect( mInterfaces );
291 : 0 : return success;
292 : 0 : }
293 : :
294 : 0 : bool QgsRasterPipe::remove( QgsRasterInterface *interface )
295 : : {
296 : 0 : if ( !interface ) return false;
297 : :
298 : 0 : return remove( mInterfaces.indexOf( interface ) );
299 : 0 : }
300 : :
301 : 0 : bool QgsRasterPipe::canSetOn( int idx, bool on )
302 : : {
303 : 0 : QgsDebugMsgLevel( QStringLiteral( "idx = %1 on = %2" ).arg( idx ).arg( on ), 4 );
304 : 0 : if ( !checkBounds( idx ) ) return false;
305 : :
306 : : // Because setting interface on/off may change its output we must check if
307 : : // connection is OK after such switch
308 : 0 : bool onOrig = mInterfaces.at( idx )->on();
309 : :
310 : 0 : if ( onOrig == on ) return true;
311 : :
312 : 0 : mInterfaces.at( idx )->setOn( on );
313 : :
314 : 0 : bool success = connect( mInterfaces );
315 : :
316 : 0 : mInterfaces.at( idx )->setOn( onOrig );
317 : 0 : connect( mInterfaces );
318 : 0 : return success;
319 : 0 : }
320 : :
321 : 0 : bool QgsRasterPipe::setOn( int idx, bool on )
322 : : {
323 : 0 : QgsDebugMsgLevel( QStringLiteral( "idx = %1 on = %2" ).arg( idx ).arg( on ), 4 );
324 : 0 : if ( !checkBounds( idx ) ) return false;
325 : :
326 : 0 : bool onOrig = mInterfaces.at( idx )->on();
327 : :
328 : 0 : if ( onOrig == on ) return true;
329 : :
330 : 0 : mInterfaces.at( idx )->setOn( on );
331 : :
332 : 0 : if ( connect( mInterfaces ) ) return true;
333 : :
334 : 0 : mInterfaces.at( idx )->setOn( onOrig );
335 : 0 : connect( mInterfaces );
336 : :
337 : 0 : return false;
338 : 0 : }
339 : :
340 : 0 : bool QgsRasterPipe::checkBounds( int idx ) const
341 : : {
342 : 0 : return !( idx < 0 || idx >= mInterfaces.size() );
343 : : }
344 : :
345 : 0 : void QgsRasterPipe::setResamplingStage( ResamplingStage stage )
346 : : {
347 : 0 : mResamplingStage = stage;
348 : 0 : setOn( ResamplerRole, stage == ResamplingStage::ResampleFilter );
349 : 0 : QgsRasterDataProvider *l_provider = provider();
350 : 0 : if ( l_provider )
351 : : {
352 : 0 : l_provider->enableProviderResampling( stage == ResamplingStage::Provider );
353 : 0 : }
354 : 0 : }
|