QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
qgsrasterdataprovider.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsrasterdataprovider.cpp - DataProvider Interface for raster layers
3 --------------------------------------
4 Date : Mar 11, 2005
5 Copyright : (C) 2005 by Brendan Morley
6 email : morb at ozemail dot com dot au
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 "qgsproviderregistry.h"
21#include "qgsprovidermetadata.h"
22#include "qgsrasterprojector.h"
23#include "qgslogger.h"
24#include "qgsmessagelog.h"
25#include "qgsapplication.h"
26#include "qgspoint.h"
27
28#include <QTime>
29#include <QMap>
30#include <QByteArray>
31#include <QVariant>
32
33#include <QUrl>
34#include <QUrlQuery>
35#include <QSet>
36
37#define ERR(message) QgsError(message, "Raster provider")
38
40{
41 if ( mUseSrcNoDataValue.size() < bandNo )
42 {
43 for ( int i = mUseSrcNoDataValue.size(); i < bandNo; i++ )
44 {
45 mUseSrcNoDataValue.append( false );
46 }
47 }
48 mUseSrcNoDataValue[bandNo - 1] = use;
49}
50
51QgsRasterBlock *QgsRasterDataProvider::block( int bandNo, QgsRectangle const &boundingBox, int width, int height, QgsRasterBlockFeedback *feedback )
52{
53 QgsDebugMsgLevel( QStringLiteral( "bandNo = %1 width = %2 height = %3" ).arg( bandNo ).arg( width ).arg( height ), 4 );
54 QgsDebugMsgLevel( QStringLiteral( "boundingBox = %1" ).arg( boundingBox.toString() ), 4 );
55
56 std::unique_ptr< QgsRasterBlock > block = std::make_unique< QgsRasterBlock >( dataType( bandNo ), width, height );
57 if ( sourceHasNoDataValue( bandNo ) && useSourceNoDataValue( bandNo ) )
58 {
60 }
61
62 if ( block->isEmpty() )
63 {
64 QgsDebugMsg( QStringLiteral( "Couldn't create raster block" ) );
65 block->setError( { tr( "Couldn't create raster block." ), QStringLiteral( "Raster" ) } );
66 block->setValid( false );
67 return block.release();
68 }
69
70 // Read necessary extent only
71 QgsRectangle tmpExtent = boundingBox;
72
73 if ( tmpExtent.isEmpty() )
74 {
75 QgsDebugMsg( QStringLiteral( "Extent outside provider extent" ) );
76 block->setError( { tr( "Extent outside provider extent." ), QStringLiteral( "Raster" ) } );
77 block->setValid( false );
79 return block.release();
80 }
81
82 const double xRes = boundingBox.width() / width;
83 const double yRes = boundingBox.height() / height;
84 double tmpXRes, tmpYRes;
85 double providerXRes = 0;
86 double providerYRes = 0;
87 if ( capabilities() & Size )
88 {
89 providerXRes = extent().width() / xSize();
90 providerYRes = extent().height() / ySize();
91 tmpXRes = std::max( providerXRes, xRes );
92 tmpYRes = std::max( providerYRes, yRes );
93 if ( qgsDoubleNear( tmpXRes, xRes ) ) tmpXRes = xRes;
94 if ( qgsDoubleNear( tmpYRes, yRes ) ) tmpYRes = yRes;
95 }
96 else
97 {
98 tmpXRes = xRes;
99 tmpYRes = yRes;
100 }
101
102 if ( tmpExtent != boundingBox ||
103 tmpXRes > xRes || tmpYRes > yRes )
104 {
105 // Read smaller extent or lower resolution
106
107 if ( !extent().contains( boundingBox ) )
108 {
109 const QRect subRect = QgsRasterBlock::subRect( boundingBox, width, height, extent() );
110 block->setIsNoDataExcept( subRect );
111 }
112
113 // Calculate row/col limits (before tmpExtent is aligned)
114 const int fromRow = std::round( ( boundingBox.yMaximum() - tmpExtent.yMaximum() ) / yRes );
115 const int toRow = std::round( ( boundingBox.yMaximum() - tmpExtent.yMinimum() ) / yRes ) - 1;
116 const int fromCol = std::round( ( tmpExtent.xMinimum() - boundingBox.xMinimum() ) / xRes );
117 const int toCol = std::round( ( tmpExtent.xMaximum() - boundingBox.xMinimum() ) / xRes ) - 1;
118
119 QgsDebugMsgLevel( QStringLiteral( "fromRow = %1 toRow = %2 fromCol = %3 toCol = %4" ).arg( fromRow ).arg( toRow ).arg( fromCol ).arg( toCol ), 4 );
120
121 if ( fromRow < 0 || fromRow >= height || toRow < 0 || toRow >= height ||
122 fromCol < 0 || fromCol >= width || toCol < 0 || toCol >= width )
123 {
124 // Should not happen
125 QgsDebugMsg( QStringLiteral( "Row or column limits out of range" ) );
126 block->setError( { tr( "Row or column limits out of range" ), QStringLiteral( "Raster" ) } );
127 block->setValid( false );
128 return block.release();
129 }
130
131 // If lower source resolution is used, the extent must be aligned to original
132 // resolution to avoid possible shift due to resampling
133 if ( tmpXRes > xRes )
134 {
135 int col = std::floor( ( tmpExtent.xMinimum() - extent().xMinimum() ) / providerXRes );
136 tmpExtent.setXMinimum( extent().xMinimum() + col * providerXRes );
137 col = std::ceil( ( tmpExtent.xMaximum() - extent().xMinimum() ) / providerXRes );
138 tmpExtent.setXMaximum( extent().xMinimum() + col * providerXRes );
139 }
140 if ( tmpYRes > yRes )
141 {
142 int row = std::floor( ( extent().yMaximum() - tmpExtent.yMaximum() ) / providerYRes );
143 tmpExtent.setYMaximum( extent().yMaximum() - row * providerYRes );
144 row = std::ceil( ( extent().yMaximum() - tmpExtent.yMinimum() ) / providerYRes );
145 tmpExtent.setYMinimum( extent().yMaximum() - row * providerYRes );
146 }
147 const int tmpWidth = std::round( tmpExtent.width() / tmpXRes );
148 const int tmpHeight = std::round( tmpExtent.height() / tmpYRes );
149 tmpXRes = tmpExtent.width() / tmpWidth;
150 tmpYRes = tmpExtent.height() / tmpHeight;
151
152 QgsDebugMsgLevel( QStringLiteral( "Reading smaller block tmpWidth = %1 height = %2" ).arg( tmpWidth ).arg( tmpHeight ), 4 );
153 QgsDebugMsgLevel( QStringLiteral( "tmpExtent = %1" ).arg( tmpExtent.toString() ), 4 );
154
155 std::unique_ptr< QgsRasterBlock > tmpBlock = std::make_unique< QgsRasterBlock >( dataType( bandNo ), tmpWidth, tmpHeight );
156 if ( sourceHasNoDataValue( bandNo ) && useSourceNoDataValue( bandNo ) )
157 {
158 tmpBlock->setNoDataValue( sourceNoDataValue( bandNo ) );
159 }
160
161 if ( !readBlock( bandNo, tmpExtent, tmpWidth, tmpHeight, tmpBlock->bits(), feedback ) )
162 {
163 QgsDebugMsg( QStringLiteral( "Error occurred while reading block" ) );
164 block->setError( { tr( "Error occurred while reading block." ), QStringLiteral( "Raster" ) } );
165 block->setValid( false );
167 return block.release();
168 }
169
170 const int pixelSize = dataTypeSize( bandNo );
171
172 const double xMin = boundingBox.xMinimum();
173 const double yMax = boundingBox.yMaximum();
174 const double tmpXMin = tmpExtent.xMinimum();
175 const double tmpYMax = tmpExtent.yMaximum();
176
177 for ( int row = fromRow; row <= toRow; row++ )
178 {
179 const double y = yMax - ( row + 0.5 ) * yRes;
180 const int tmpRow = std::floor( ( tmpYMax - y ) / tmpYRes );
181
182 for ( int col = fromCol; col <= toCol; col++ )
183 {
184 const double x = xMin + ( col + 0.5 ) * xRes;
185 const int tmpCol = std::floor( ( x - tmpXMin ) / tmpXRes );
186
187 if ( tmpRow < 0 || tmpRow >= tmpHeight || tmpCol < 0 || tmpCol >= tmpWidth )
188 {
189 QgsDebugMsg( QStringLiteral( "Source row or column limits out of range" ) );
190 block->setIsNoData(); // so that the problem becomes obvious and fixed
191 block->setError( { tr( "Source row or column limits out of range." ), QStringLiteral( "Raster" ) } );
192 block->setValid( false );
193 return block.release();
194 }
195
196 const qgssize tmpIndex = static_cast< qgssize >( tmpRow ) * static_cast< qgssize >( tmpWidth ) + tmpCol;
197 const qgssize index = row * static_cast< qgssize >( width ) + col;
198
199 char *tmpBits = tmpBlock->bits( tmpIndex );
200 char *bits = block->bits( index );
201 if ( !tmpBits )
202 {
203 QgsDebugMsg( QStringLiteral( "Cannot get input block data tmpRow = %1 tmpCol = %2 tmpIndex = %3." ).arg( tmpRow ).arg( tmpCol ).arg( tmpIndex ) );
204 continue;
205 }
206 if ( !bits )
207 {
208 QgsDebugMsg( QStringLiteral( "Cannot set output block data." ) );
209 continue;
210 }
211 memcpy( bits, tmpBits, pixelSize );
212 }
213 }
214 }
215 else
216 {
217 if ( !readBlock( bandNo, boundingBox, width, height, block->bits(), feedback ) )
218 {
219 QgsDebugMsg( QStringLiteral( "Error occurred while reading block" ) );
221 block->setError( { tr( "Error occurred while reading block." ), QStringLiteral( "Raster" ) } );
222 block->setValid( false );
223 return block.release();
224 }
225 }
226
227 // apply scale and offset
228 block->applyScaleOffset( bandScale( bandNo ), bandOffset( bandNo ) );
229 // apply user no data values
231 return block.release();
232}
233
235 : QgsDataProvider( QString(), QgsDataProvider::ProviderOptions(), QgsDataProvider::ReadFlags() )
236 , QgsRasterInterface( nullptr )
237 , mTemporalCapabilities( std::make_unique< QgsRasterDataProviderTemporalCapabilities >() )
238{
239
240}
241
243 QgsDataProvider::ReadFlags flags )
244 : QgsDataProvider( uri, options, flags )
245 , QgsRasterInterface( nullptr )
246 , mTemporalCapabilities( std::make_unique< QgsRasterDataProviderTemporalCapabilities >() )
247{
248}
249
250QgsRasterDataProvider::ProviderCapabilities QgsRasterDataProvider::providerCapabilities() const
251{
253}
254
256{
257 Q_UNUSED( bandNo )
259}
260
261//
262//Random Static convenience function
263//
265
266// TODO
267// (WMS) IdentifyFormatFeature is not consistent with QgsRaster::IdentifyFormatValue.
268// IdentifyFormatHtml: better error reporting
269QgsRasterIdentifyResult QgsRasterDataProvider::identify( const QgsPointXY &point, QgsRaster::IdentifyFormat format, const QgsRectangle &boundingBox, int width, int height, int /*dpi*/ )
270{
271 QgsDebugMsgLevel( QStringLiteral( "Entered" ), 4 );
272 QMap<int, QVariant> results;
273
275 {
276 QgsDebugMsg( QStringLiteral( "Format not supported" ) );
277 return QgsRasterIdentifyResult( ERR( tr( "Format not supported" ) ) );
278 }
279
280 if ( !extent().contains( point ) )
281 {
282 // Outside the raster
283 for ( int bandNo = 1; bandNo <= bandCount(); bandNo++ )
284 {
285 results.insert( bandNo, QVariant() );
286 }
288 }
289
290 QgsRectangle finalExtent = boundingBox;
291 if ( finalExtent.isEmpty() )
292 finalExtent = extent();
293
294 if ( width == 0 )
295 {
296 width = capabilities() & Size ? xSize() : 1000;
297 }
298 if ( height == 0 )
299 {
300 height = capabilities() & Size ? ySize() : 1000;
301 }
302
303 // Calculate the row / column where the point falls
304 const double xres = ( finalExtent.width() ) / width;
305 const double yres = ( finalExtent.height() ) / height;
306
307 const int col = static_cast< int >( std::floor( ( point.x() - finalExtent.xMinimum() ) / xres ) );
308 const int row = static_cast< int >( std::floor( ( finalExtent.yMaximum() - point.y() ) / yres ) );
309
310 const double xMin = finalExtent.xMinimum() + col * xres;
311 const double xMax = xMin + xres;
312 const double yMax = finalExtent.yMaximum() - row * yres;
313 const double yMin = yMax - yres;
314 const QgsRectangle pixelExtent( xMin, yMin, xMax, yMax );
315
316 for ( int i = 1; i <= bandCount(); i++ )
317 {
318 std::unique_ptr< QgsRasterBlock > bandBlock( block( i, pixelExtent, 1, 1 ) );
319
320 if ( bandBlock )
321 {
322 const double value = bandBlock->value( 0 );
323
324 results.insert( i, value );
325 }
326 else
327 {
328 results.insert( i, QVariant() );
329 }
330 }
332}
333
334double QgsRasterDataProvider::sample( const QgsPointXY &point, int band,
335 bool *ok, const QgsRectangle &boundingBox, int width, int height, int dpi )
336{
337 if ( ok )
338 *ok = false;
339
340 const auto res = identify( point, QgsRaster::IdentifyFormatValue, boundingBox, width, height, dpi );
341 const QVariant value = res.results().value( band );
342
343 if ( !value.isValid() )
344 return std::numeric_limits<double>::quiet_NaN();
345
346 if ( ok )
347 *ok = true;
348
349 return value.toDouble( ok );
350}
351
353{
354 return QStringLiteral( "text/plain" );
355}
356
357bool QgsRasterDataProvider::writeBlock( QgsRasterBlock *block, int band, int xOffset, int yOffset )
358{
359 if ( !block )
360 return false;
361 if ( !isEditable() )
362 {
363 QgsDebugMsg( QStringLiteral( "writeBlock() called on read-only provider." ) );
364 return false;
365 }
366 return write( block->bits(), band, block->width(), block->height(), xOffset, yOffset );
367}
368
369// typedef QList<QPair<QString, QString> > *pyramidResamplingMethods_t();
370QList<QPair<QString, QString> > QgsRasterDataProvider::pyramidResamplingMethods( const QString &providerKey )
371{
372 QList<QPair<QString, QString> > methods = QgsProviderRegistry::instance()->pyramidResamplingMethods( providerKey );
373 if ( methods.isEmpty() )
374 {
375 QgsDebugMsg( QStringLiteral( "provider pyramidResamplingMethods returned no methods" ) );
376 }
377 return methods;
378}
379
381{
382 const QList<QgsRasterPyramid> pyramidList = buildPyramidList();
383 return std::any_of( pyramidList.constBegin(), pyramidList.constEnd(), []( QgsRasterPyramid pyramid ) { return pyramid.getExists(); } );
384}
385
387{
388 if ( bandNo >= mUserNoDataValue.size() )
389 {
390 for ( int i = mUserNoDataValue.size(); i < bandNo; i++ )
391 {
393 }
394 }
395 QgsDebugMsgLevel( QStringLiteral( "set %1 band %1 no data ranges" ).arg( noData.size() ), 4 );
396
397 if ( mUserNoDataValue[bandNo - 1] != noData )
398 {
399 // Clear statistics
400 mStatistics.erase( std::remove_if( mStatistics.begin(), mStatistics.end(), [bandNo]( const QgsRasterBandStats & stats )
401 {
402 return stats.bandNumber == bandNo;
403 } ), mStatistics.end() );
404 mHistograms.erase( std::remove_if( mHistograms.begin(), mHistograms.end(), [bandNo]( const QgsRasterHistogram & histogram )
405 {
406 return histogram.bandNumber == bandNo;
407 } ), mHistograms.end() );
408 mUserNoDataValue[bandNo - 1] = noData;
409 }
410}
411
413{
414 return mTemporalCapabilities.get();
415}
416
418{
419 return mTemporalCapabilities.get();
420}
421
423 const QString &uri,
424 const QString &format, int nBands,
425 Qgis::DataType type,
426 int width, int height, double *geoTransform,
428 const QStringList &createOptions )
429{
431 providerKey,
432 uri, format,
433 nBands, type, width,
434 height, geoTransform, crs, createOptions );
435 if ( !ret )
436 {
437 QgsDebugMsg( "Cannot resolve 'createRasterDataProviderFunction' function in " + providerKey + " provider" );
438 }
439
440 // TODO: it would be good to return invalid QgsRasterDataProvider
441 // with QgsError set, but QgsRasterDataProvider has pure virtual methods
442
443 return ret;
444}
445
447{
448 switch ( format )
449 {
451 return QStringLiteral( "Value" );
453 return QStringLiteral( "Text" );
455 return QStringLiteral( "Html" );
457 return QStringLiteral( "Feature" );
458 default:
459 return QStringLiteral( "Undefined" );
460 }
461}
462
464{
465 switch ( format )
466 {
468 return tr( "Value" );
470 return tr( "Text" );
472 return tr( "Html" );
474 return tr( "Feature" );
475 default:
476 return QStringLiteral( "Undefined" );
477 }
478}
479
481{
482 if ( formatName == QLatin1String( "Value" ) ) return QgsRaster::IdentifyFormatValue;
483 if ( formatName == QLatin1String( "Text" ) ) return QgsRaster::IdentifyFormatText;
484 if ( formatName == QLatin1String( "Html" ) ) return QgsRaster::IdentifyFormatHtml;
485 if ( formatName == QLatin1String( "Feature" ) ) return QgsRaster::IdentifyFormatFeature;
487}
488
490{
491 switch ( format )
492 {
494 return IdentifyValue;
496 return IdentifyText;
498 return IdentifyHtml;
500 return IdentifyFeature;
501 default:
502 return NoCapabilities;
503 }
504}
505
507{
508 return QList< double >();
509}
510
512{
513 return false;
514}
515
517{
518 Q_UNUSED( point )
519 Q_UNUSED( type )
520 return QgsPoint();
521}
522
523bool QgsRasterDataProvider::userNoDataValuesContains( int bandNo, double value ) const
524{
525 const QgsRasterRangeList rangeList = mUserNoDataValue.value( bandNo - 1 );
526 return QgsRasterRange::contains( value, rangeList );
527}
528
530{
531 mDpi = other.mDpi;
536 mExtent = other.mExtent;
541
542 // copy temporal properties
543 if ( mTemporalCapabilities && other.mTemporalCapabilities )
544 {
545 *mTemporalCapabilities = *other.mTemporalCapabilities;
546 }
547}
548
549static QgsRasterDataProvider::ResamplingMethod resamplingMethodFromString( const QString &str )
550{
551 if ( str == QLatin1String( "bilinear" ) )
552 {
554 }
555 else if ( str == QLatin1String( "cubic" ) )
556 {
558 }
559 else if ( str == QLatin1String( "cubicSpline" ) )
560 {
562 }
563 else if ( str == QLatin1String( "lanczos" ) )
564 {
566 }
567 else if ( str == QLatin1String( "average" ) )
568 {
570 }
571 else if ( str == QLatin1String( "mode" ) )
572 {
574 }
575 else if ( str == QLatin1String( "gauss" ) )
576 {
578 }
580}
581
582void QgsRasterDataProvider::readXml( const QDomElement &filterElem )
583{
584 if ( filterElem.isNull() )
585 {
586 return;
587 }
588
589 const QDomElement resamplingElement = filterElem.firstChildElement( QStringLiteral( "resampling" ) );
590 if ( !resamplingElement.isNull() )
591 {
592 setMaxOversampling( resamplingElement.attribute( QStringLiteral( "maxOversampling" ), QStringLiteral( "2.0" ) ).toDouble() );
593 setZoomedInResamplingMethod( resamplingMethodFromString( resamplingElement.attribute( QStringLiteral( "zoomedInResamplingMethod" ) ) ) );
594 setZoomedOutResamplingMethod( resamplingMethodFromString( resamplingElement.attribute( QStringLiteral( "zoomedOutResamplingMethod" ) ) ) );
595 enableProviderResampling( resamplingElement.attribute( QStringLiteral( "enabled" ) ) == QLatin1String( "true" ) );
596 }
597}
598
599static QString resamplingMethodToString( QgsRasterDataProvider::ResamplingMethod method )
600{
601 switch ( method )
602 {
604 return QStringLiteral( "nearestNeighbour" );
606 return QStringLiteral( "bilinear" );
608 return QStringLiteral( "cubic" );
610 return QStringLiteral( "cubicSpline" );
612 return QStringLiteral( "lanczos" );
614 return QStringLiteral( "average" );
616 return QStringLiteral( "mode" );
618 return QStringLiteral( "gauss" );
619 }
620 // should not happen
621 return QStringLiteral( "nearestNeighbour" );
622}
623
624void QgsRasterDataProvider::writeXml( QDomDocument &doc, QDomElement &parentElem ) const
625{
626 QDomElement providerElement = doc.createElement( QStringLiteral( "provider" ) );
627 parentElem.appendChild( providerElement );
628
629 QDomElement resamplingElement = doc.createElement( QStringLiteral( "resampling" ) );
630 providerElement.appendChild( resamplingElement );
631
632 resamplingElement.setAttribute( QStringLiteral( "enabled" ),
633 mProviderResamplingEnabled ? QStringLiteral( "true" ) : QStringLiteral( "false" ) );
634
635 resamplingElement.setAttribute( QStringLiteral( "zoomedInResamplingMethod" ),
636 resamplingMethodToString( mZoomedInResamplingMethod ) );
637
638 resamplingElement.setAttribute( QStringLiteral( "zoomedOutResamplingMethod" ),
639 resamplingMethodToString( mZoomedOutResamplingMethod ) );
640
641 resamplingElement.setAttribute( QStringLiteral( "maxOversampling" ),
642 QString::number( mMaxOversampling ) );
643}
644
646{
647 return colorName( colorInterpretation( bandNo ) );
648}
649
651{
652 QUrl url = QUrl::fromPercentEncoding( uri.toUtf8() );
653 const QUrlQuery query( url.query() );
654 VirtualRasterParameters components;
655
656 if ( ! query.hasQueryItem( QStringLiteral( "crs" ) ) )
657 {
658 QgsDebugMsg( "crs is missing" );
659 if ( ok ) *ok = false;
660 return components;
661 }
662 if ( ! components.crs.createFromString( query.queryItemValue( QStringLiteral( "crs" ) ) ) )
663 {
664 QgsDebugMsg( "failed to create crs" );
665 if ( ok ) *ok = false;
666 return components;
667 }
668
669
670 if ( ! query.hasQueryItem( QStringLiteral( "extent" ) ) )
671 {
672 QgsDebugMsg( "extent is missing" );
673 if ( ok ) *ok = false;
674 return components;
675 }
676 QStringList pointValuesList = query.queryItemValue( QStringLiteral( "extent" ) ).split( ',' );
677 if ( pointValuesList.size() != 4 )
678 {
679 QgsDebugMsg( "the extent is not correct" );
680 if ( ok ) *ok = false;
681 return components;
682 }
683 components.extent = QgsRectangle( pointValuesList.at( 0 ).toDouble(), pointValuesList.at( 1 ).toDouble(),
684 pointValuesList.at( 2 ).toDouble(), pointValuesList.at( 3 ).toDouble() );
685
686 if ( ! query.hasQueryItem( QStringLiteral( "width" ) ) )
687 {
688 QgsDebugMsg( "width is missing" );
689 if ( ok ) *ok = false;
690 return components;
691 }
692 bool flagW;
693 components.width = query.queryItemValue( QStringLiteral( "width" ) ).toInt( & flagW );
694 if ( !flagW || components.width < 0 )
695 {
696 QgsDebugMsg( "invalid or negative width input" );
697 if ( ok ) *ok = false;
698 return components;
699 }
700
701 if ( ! query.hasQueryItem( QStringLiteral( "height" ) ) )
702 {
703 QgsDebugMsg( "height is missing" );
704 if ( ok ) *ok = false;
705 return components;
706 }
707 bool flagH;
708 components.height = query.queryItemValue( QStringLiteral( "height" ) ).toInt( & flagH );
709 if ( !flagH || components.height < 0 )
710 {
711 QgsDebugMsg( "invalid or negative width input" );
712 if ( ok ) *ok = false;
713 return components;
714 }
715
716 if ( ! query.hasQueryItem( QStringLiteral( "formula" ) ) )
717 {
718 QgsDebugMsg( "formula is missing" );
719 if ( ok ) *ok = false;
720 return components;
721 }
722 components.formula = query.queryItemValue( QStringLiteral( "formula" ) );
723
724 for ( const auto &item : query.queryItems() )
725 {
726 if ( !( item.first.mid( item.first.indexOf( ':' ), -1 ) == QLatin1String( ":uri" ) ) )
727 {
728 continue;
729 }
730
732 rLayer.name = item.first.mid( 0, item.first.indexOf( ':' ) );
733 rLayer.uri = query.queryItemValue( item.first );
734 rLayer.provider = query.queryItemValue( item.first.mid( 0, item.first.indexOf( ':' ) ) + QStringLiteral( ":provider" ) );
735
736 if ( rLayer.uri.isNull() || rLayer.provider.isNull() )
737 {
738 QgsDebugMsg( "One or more raster information are missing" );
739 if ( ok ) *ok = false;
740 return components;
741 }
742
743 components.rInputLayers.append( rLayer ) ;
744
745 }
746
747 if ( ok ) *ok = true;
748 return components;
749}
750
752{
753 QUrl uri;
754 QUrlQuery query;
755
756 if ( parts.crs.isValid() )
757 {
758 query.addQueryItem( QStringLiteral( "crs" ), parts.crs.authid() );
759 }
760
761 if ( ! parts.extent.isNull() )
762 {
763 QString rect = QString( "%1,%2,%3,%4" ).arg( qgsDoubleToString( parts.extent.xMinimum() ), qgsDoubleToString( parts.extent.yMinimum() ),
765
766 query.addQueryItem( QStringLiteral( "extent" ), rect );
767 }
768
769 query.addQueryItem( QStringLiteral( "width" ), QString::number( parts.width ) );
770
771 query.addQueryItem( QStringLiteral( "height" ), QString::number( parts.height ) );
772
773 query.addQueryItem( QStringLiteral( "formula" ), parts.formula );
774
775 if ( ! parts.rInputLayers.isEmpty() )
776 {
777 for ( const auto &it : parts.rInputLayers )
778 {
779 query.addQueryItem( it.name + QStringLiteral( ":uri" ), it.uri );
780 query.addQueryItem( it.name + QStringLiteral( ":provider" ), it.provider );
781 }
782 }
783 uri.setQuery( query );
784 return QString( QUrl::toPercentEncoding( uri.toEncoded() ) );
785}
DataType
Raster data types.
Definition: qgis.h:129
This class represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
bool createFromString(const QString &definition)
Set up this CRS from a string definition.
Abstract base class for spatial data provider implementations.
virtual QgsCoordinateReferenceSystem crs() const =0
Returns the coordinate system for the data source.
QgsDataSourceUri uri() const
Gets the data source specification.
A class to represent a 2D point.
Definition: qgspointxy.h:59
double y
Definition: qgspointxy.h:63
Q_GADGET double x
Definition: qgspointxy.h:62
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:49
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
QgsRasterDataProvider * createRasterDataProvider(const QString &providerKey, const QString &uri, const QString &format, int nBands, Qgis::DataType type, int width, int height, double *geoTransform, const QgsCoordinateReferenceSystem &crs, const QStringList &createOptions=QStringList())
Creates new instance of raster data provider.
QList< QPair< QString, QString > > pyramidResamplingMethods(const QString &providerKey)
Returns list of raster pyramid resampling methods.
The RasterBandStats struct is a container for statistics about a single raster band.
Feedback object tailored for raster block reading.
Raster data container.
bool isEmpty() const
Returns true if block is empty, i.e.
void setNoDataValue(double noDataValue) SIP_HOLDGIL
Sets cell value that will be considered as "no data".
void setValid(bool valid) SIP_HOLDGIL
Mark block as valid or invalid.
int width() const SIP_HOLDGIL
Returns the width (number of columns) of the raster block.
char * bits(int row, int column)
Returns a pointer to block data.
bool setIsNoDataExcept(QRect exceptRect)
Set the whole block to no data except specified rectangle.
void applyNoDataValues(const QgsRasterRangeList &rangeList)
void applyScaleOffset(double scale, double offset)
Apply band scale and offset to raster block values.
static QRect subRect(const QgsRectangle &extent, int width, int height, const QgsRectangle &subExtent)
For extent and width, height find rectangle covered by subextent.
void setError(const QgsError &error)
Sets the last error.
int height() const SIP_HOLDGIL
Returns the height (number of rows) of the raster block.
bool setIsNoData(int row, int column) SIP_HOLDGIL
Set no data on pixel.
Implementation of data provider temporal properties for QgsRasterDataProviders.
Base class for raster data providers.
double mMaxOversampling
Maximum boundary for oversampling (to avoid too much data traffic). Default: 2.0.
QList< bool > mUseSrcNoDataValue
Use source nodata value.
TransformType
Types of transformation in transformCoordinates() function.
static QgsRaster::IdentifyFormat identifyFormatFromName(const QString &formatName)
virtual bool sourceHasNoDataValue(int bandNo) const
Returns true if source band has no data value.
static QString encodeVirtualRasterProviderUri(const VirtualRasterParameters &parts)
Encodes the URI starting from the struct .
virtual double bandOffset(int bandNo) const
Read band offset for raster value.
virtual QString lastErrorFormat()
Returns the format of the error text for the last error in this provider.
bool mProviderResamplingEnabled
Whether provider resampling is enabled.
virtual bool useSourceNoDataValue(int bandNo) const
Returns the source nodata value usage.
static QgsRasterDataProvider::VirtualRasterParameters decodeVirtualRasterProviderUri(const QString &uri, bool *ok=nullptr)
Decodes the URI returning a struct with all the parameters for QgsVirtualRasterProvider class.
virtual void setUseSourceNoDataValue(int bandNo, bool use)
Sets the source nodata value usage.
virtual double sourceNoDataValue(int bandNo) const
Value representing no data value.
QString colorName(int colorInterpretation) const
void readXml(const QDomElement &filterElem) override
Sets base class members from xml. Usually called from create() methods of subclasses.
QList< QgsRasterRangeList > mUserNoDataValue
List of lists of user defined additional no data values for each band, indexed from 0.
virtual QgsRasterIdentifyResult identify(const QgsPointXY &point, QgsRaster::IdentifyFormat format, const QgsRectangle &boundingBox=QgsRectangle(), int width=0, int height=0, int dpi=96)
Identify raster value(s) found on the point position.
virtual QgsRasterDataProvider::ProviderCapabilities providerCapabilities() const
Returns flags containing the supported capabilities of the data provider.
virtual bool isEditable() const
Checks whether the provider is in editing mode, i.e.
void copyBaseSettings(const QgsRasterDataProvider &other)
Copy member variables from other raster data provider. Useful for implementation of clone() method in...
bool userNoDataValuesContains(int bandNo, double value) const
Returns true if user no data contains value.
bool writeBlock(QgsRasterBlock *block, int band, int xOffset=0, int yOffset=0)
Writes pixel data from a raster block into the provider data source.
virtual bool enableProviderResampling(bool enable)
Enable or disable provider-level resampling.
QgsRectangle extent() const override=0
Returns the extent of the layer.
virtual bool ignoreExtents() const
Returns true if the extents reported by the data provider are not reliable and it's possible that the...
virtual bool setMaxOversampling(double factor)
Sets maximum oversampling factor for zoomed-out operations.
Qgis::DataType dataType(int bandNo) const override=0
Returns data type for the band specified by number.
ResamplingMethod mZoomedOutResamplingMethod
Resampling method for zoomed out pixel extraction.
static Capability identifyFormatToCapability(QgsRaster::IdentifyFormat format)
bool hasPyramids()
Returns true if raster has at least one existing pyramid.
virtual double bandScale(int bandNo) const
Read band scale for raster value.
static QString identifyFormatName(QgsRaster::IdentifyFormat format)
@ NoProviderCapabilities
Provider has no capabilities.
int dpi() const
Returns the dpi of the output device.
virtual double sample(const QgsPointXY &point, int band, bool *ok=nullptr, const QgsRectangle &boundingBox=QgsRectangle(), int width=0, int height=0, int dpi=96)
Samples a raster value from the specified band found at the point position.
static QString identifyFormatLabel(QgsRaster::IdentifyFormat format)
QgsRasterBlock * block(int bandNo, const QgsRectangle &boundingBox, int width, int height, QgsRasterBlockFeedback *feedback=nullptr) override
Read block of data using given extent and size.
virtual int colorInterpretation(int bandNo) const
Returns data type for the band specified by number.
QList< double > mSrcNoDataValue
Source no data value is available and is set to be used or internal no data is available.
virtual bool readBlock(int bandNo, int xBlock, int yBlock, void *data)
Reads a block of raster data into data.
ResamplingMethod mZoomedInResamplingMethod
Resampling method for zoomed in pixel extraction.
QgsRasterDataProvider()
Provider capabilities.
QList< bool > mSrcHasNoDataValue
Source no data value exists.
static QgsRasterDataProvider * create(const QString &providerKey, const QString &uri, const QString &format, int nBands, Qgis::DataType type, int width, int height, double *geoTransform, const QgsCoordinateReferenceSystem &crs, const QStringList &createOptions=QStringList())
Creates a new dataset with mDataSourceURI.
virtual QgsRasterRangeList userNoDataValues(int bandNo) const
Returns a list of user no data value ranges.
virtual bool setZoomedInResamplingMethod(ResamplingMethod method)
Set resampling method to apply for zoomed-in operations.
static QList< QPair< QString, QString > > pyramidResamplingMethods(const QString &providerKey)
Returns a list of pyramid resampling method name and label pairs for given provider.
void writeXml(QDomDocument &doc, QDomElement &parentElem) const override
Write base class members to xml.
virtual QList< double > nativeResolutions() const
Returns a list of native resolutions if available, i.e.
virtual QgsPoint transformCoordinates(const QgsPoint &point, TransformType type)
Transforms coordinates between source image coordinate space [0..width]x[0..height] and layer coordin...
QgsRasterDataProviderTemporalCapabilities * temporalCapabilities() override
Returns the provider's temporal capabilities.
QString colorInterpretationName(int bandNo) const override
Returns the name of the color interpretation for the specified bandNumber.
ResamplingMethod
Resampling method for provider-level resampling.
@ Lanczos
Lanczos windowed sinc interpolation (6x6 kernel)
@ Nearest
Nearest-neighbour resampling.
@ Mode
Mode (selects the value which appears most often of all the sampled points)
@ Bilinear
Bilinear (2x2 kernel) resampling.
@ CubicSpline
Cubic B-Spline Approximation (4x4 kernel)
@ Cubic
Cubic Convolution Approximation (4x4 kernel) resampling.
virtual bool write(void *data, int band, int width, int height, int xOffset, int yOffset)
Writes into the provider datasource.
virtual void setUserNoDataValue(int bandNo, const QgsRasterRangeList &noData)
virtual bool setZoomedOutResamplingMethod(ResamplingMethod method)
Set resampling method to apply for zoomed-out operations.
virtual QList< QgsRasterPyramid > buildPyramidList(const QList< int > &overviewList=QList< int >())
Returns the raster layers pyramid list.
The QgsRasterHistogram is a container for histogram of a single raster band.
Raster identify results container.
Base class for processing filters like renderers, reprojector, resampler etc.
QList< QgsRasterBandStats > mStatistics
List of cached statistics, all bands mixed.
Capability
If you add to this, please also add to capabilitiesString()
@ IdentifyValue
Numerical values.
@ IdentifyFeature
WMS GML -> feature.
@ Size
Original data source size (and thus resolution) is known, it is not always available,...
virtual int xSize() const
Gets raster size.
virtual int bandCount() const =0
Gets number of bands.
int dataTypeSize(int bandNo) const
Returns the size (in bytes) for the data type for the specified band.
virtual int capabilities() const
Returns a bitmask containing the supported capabilities.
virtual int ySize() const
QList< QgsRasterHistogram > mHistograms
List of cached histograms, all bands mixed.
virtual QgsRasterHistogram histogram(int bandNo, int binCount=0, double minimum=std::numeric_limits< double >::quiet_NaN(), double maximum=std::numeric_limits< double >::quiet_NaN(), const QgsRectangle &extent=QgsRectangle(), int sampleSize=0, bool includeOutOfRange=false, QgsRasterBlockFeedback *feedback=nullptr)
Returns a band histogram.
This struct is used to store pyramid info for the raster layer.
bool contains(double value) const
Returns true if this range contains the specified value.
IdentifyFormat
Definition: qgsraster.h:58
@ IdentifyFormatFeature
Definition: qgsraster.h:63
@ IdentifyFormatValue
Definition: qgsraster.h:60
@ IdentifyFormatText
Definition: qgsraster.h:61
@ IdentifyFormatUndefined
Definition: qgsraster.h:59
@ IdentifyFormatHtml
Definition: qgsraster.h:62
@ UndefinedColorInterpretation
Definition: qgsraster.h:37
A rectangle specified with double values.
Definition: qgsrectangle.h:42
QString toString(int precision=16) const
Returns a string representation of form xmin,ymin : xmax,ymax Coordinates will be truncated to the sp...
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:193
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:183
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:188
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:198
void setYMinimum(double y) SIP_HOLDGIL
Set the minimum y value.
Definition: qgsrectangle.h:161
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
Definition: qgsrectangle.h:479
void setXMaximum(double x) SIP_HOLDGIL
Set the maximum x value.
Definition: qgsrectangle.h:156
void setXMinimum(double x) SIP_HOLDGIL
Set the minimum x value.
Definition: qgsrectangle.h:151
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
Definition: qgsrectangle.h:230
void setYMaximum(double y) SIP_HOLDGIL
Set the maximum y value.
Definition: qgsrectangle.h:166
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
Definition: qgsrectangle.h:223
bool isEmpty() const
Returns true if the rectangle is empty.
Definition: qgsrectangle.h:469
#define str(x)
Definition: qgis.cpp:37
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition: qgis.h:2466
unsigned long long qgssize
Qgssize is used instead of size_t, because size_t is stdlib type, unknown by SIP, and it would be har...
Definition: qgis.h:3032
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:2527
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
#define ERR(message)
QList< QgsRasterRange > QgsRasterRangeList
const QgsCoordinateReferenceSystem & crs
Setting options for creating vector data providers.
Struct that stores information of the raster used in QgsVirtualRasterProvider for the calculations,...
Struct that stores the information about the parameters that should be given to the QgsVirtualRasterP...
QList< QgsRasterDataProvider::VirtualRasterInputLayers > rInputLayers