QGIS API Documentation 4.0.0-Norrköping (1ddcee3d0e4)
Loading...
Searching...
No Matches
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
19
20#include "qgslogger.h"
21#include "qgspoint.h"
22#include "qgsproviderregistry.h"
24#include "qgsthreadingutils.h"
25
26#include <QByteArray>
27#include <QMap>
28#include <QSet>
29#include <QString>
30#include <QTime>
31#include <QUrl>
32#include <QUrlQuery>
33#include <QVariant>
34
35#include "moc_qgsrasterdataprovider.cpp"
36
37using namespace Qt::StringLiterals;
38
39#define ERR( message ) QgsError( message, "Raster provider" )
40
42{
44
45 if ( mUseSrcNoDataValue.size() < bandNo )
46 {
47 for ( qsizetype i = mUseSrcNoDataValue.size(); i < bandNo; i++ )
48 {
49 mUseSrcNoDataValue.append( false );
50 }
51 }
52 mUseSrcNoDataValue[bandNo - 1] = use;
53}
54
55QgsRasterBlock *QgsRasterDataProvider::block( int bandNo, QgsRectangle const &boundingBox, int width, int height, QgsRasterBlockFeedback *feedback )
56{
58
59 QgsDebugMsgLevel( u"bandNo = %1 width = %2 height = %3"_s.arg( bandNo ).arg( width ).arg( height ), 4 );
60 QgsDebugMsgLevel( u"boundingBox = %1"_s.arg( boundingBox.toString() ), 4 );
61
62 auto block = std::make_unique< QgsRasterBlock >( dataType( bandNo ), width, height );
63 if ( sourceHasNoDataValue( bandNo ) && useSourceNoDataValue( bandNo ) )
64 {
65 block->setNoDataValue( sourceNoDataValue( bandNo ) );
66 }
67
68 if ( block->isEmpty() )
69 {
70 QgsDebugError( u"Couldn't create raster block"_s );
71 block->setError( { tr( "Couldn't create raster block." ), u"Raster"_s } );
72 block->setValid( false );
73 return block.release();
74 }
75
76 // Read necessary extent only
77 QgsRectangle tmpExtent = boundingBox;
78
79 if ( tmpExtent.isEmpty() )
80 {
81 QgsDebugError( u"Extent outside provider extent"_s );
82 block->setError( { tr( "Extent outside provider extent." ), u"Raster"_s } );
83 block->setValid( false );
84 block->setIsNoData();
85 return block.release();
86 }
87
88 const double xRes = boundingBox.width() / width;
89 const double yRes = boundingBox.height() / height;
90 double tmpXRes, tmpYRes;
91 double providerXRes = 0;
92 double providerYRes = 0;
94 {
95 providerXRes = extent().width() / xSize();
96 providerYRes = extent().height() / ySize();
97 tmpXRes = std::max( providerXRes, xRes );
98 tmpYRes = std::max( providerYRes, yRes );
99 if ( qgsDoubleNear( tmpXRes, xRes ) )
100 tmpXRes = xRes;
101 if ( qgsDoubleNear( tmpYRes, yRes ) )
102 tmpYRes = yRes;
103 }
104 else
105 {
106 tmpXRes = xRes;
107 tmpYRes = yRes;
108 }
109
110 if ( tmpExtent != boundingBox || tmpXRes > xRes || tmpYRes > yRes )
111 {
112 // Read smaller extent or lower resolution
113
114 if ( !extent().contains( boundingBox ) )
115 {
116 const QRect subRect = QgsRasterBlock::subRect( boundingBox, width, height, extent() );
117 block->setIsNoDataExcept( subRect );
118 }
119
120 // Calculate row/col limits (before tmpExtent is aligned)
121 const int fromRow = std::round( ( boundingBox.yMaximum() - tmpExtent.yMaximum() ) / yRes );
122 const int toRow = std::round( ( boundingBox.yMaximum() - tmpExtent.yMinimum() ) / yRes ) - 1;
123 const int fromCol = std::round( ( tmpExtent.xMinimum() - boundingBox.xMinimum() ) / xRes );
124 const int toCol = std::round( ( tmpExtent.xMaximum() - boundingBox.xMinimum() ) / xRes ) - 1;
125
126 QgsDebugMsgLevel( u"fromRow = %1 toRow = %2 fromCol = %3 toCol = %4"_s.arg( fromRow ).arg( toRow ).arg( fromCol ).arg( toCol ), 4 );
127
128 if ( fromRow < 0 || fromRow >= height || toRow < 0 || toRow >= height || fromCol < 0 || fromCol >= width || toCol < 0 || toCol >= width )
129 {
130 // Should not happen
131 QgsDebugError( u"Row or column limits out of range"_s );
132 block->setError( { tr( "Row or column limits out of range" ), u"Raster"_s } );
133 block->setValid( false );
134 return block.release();
135 }
136
137 // If lower source resolution is used, the extent must be aligned to original
138 // resolution to avoid possible shift due to resampling
139 if ( tmpXRes > xRes )
140 {
141 int col = std::floor( ( tmpExtent.xMinimum() - extent().xMinimum() ) / providerXRes );
142 tmpExtent.setXMinimum( extent().xMinimum() + col * providerXRes );
143 col = std::ceil( ( tmpExtent.xMaximum() - extent().xMinimum() ) / providerXRes );
144 tmpExtent.setXMaximum( extent().xMinimum() + col * providerXRes );
145 }
146 if ( tmpYRes > yRes )
147 {
148 int row = std::floor( ( extent().yMaximum() - tmpExtent.yMaximum() ) / providerYRes );
149 tmpExtent.setYMaximum( extent().yMaximum() - row * providerYRes );
150 row = std::ceil( ( extent().yMaximum() - tmpExtent.yMinimum() ) / providerYRes );
151 tmpExtent.setYMinimum( extent().yMaximum() - row * providerYRes );
152 }
153 const int tmpWidth = std::round( tmpExtent.width() / tmpXRes );
154 const int tmpHeight = std::round( tmpExtent.height() / tmpYRes );
155 tmpXRes = tmpExtent.width() / tmpWidth;
156 tmpYRes = tmpExtent.height() / tmpHeight;
157
158 QgsDebugMsgLevel( u"Reading smaller block tmpWidth = %1 height = %2"_s.arg( tmpWidth ).arg( tmpHeight ), 4 );
159 QgsDebugMsgLevel( u"tmpExtent = %1"_s.arg( tmpExtent.toString() ), 4 );
160
161 auto tmpBlock = std::make_unique< QgsRasterBlock >( dataType( bandNo ), tmpWidth, tmpHeight );
162 if ( sourceHasNoDataValue( bandNo ) && useSourceNoDataValue( bandNo ) )
163 {
164 tmpBlock->setNoDataValue( sourceNoDataValue( bandNo ) );
165 }
166
167 if ( !readBlock( bandNo, tmpExtent, tmpWidth, tmpHeight, tmpBlock->bits(), feedback ) )
168 {
169 QgsDebugError( u"Error occurred while reading block"_s );
170 block->setError( { tr( "Error occurred while reading block." ), u"Raster"_s } );
171 block->setValid( false );
172 block->setIsNoData();
173 return block.release();
174 }
175
176 const int pixelSize = dataTypeSize( bandNo );
177
178 const double xMin = boundingBox.xMinimum();
179 const double yMax = boundingBox.yMaximum();
180 const double tmpXMin = tmpExtent.xMinimum();
181 const double tmpYMax = tmpExtent.yMaximum();
182
183 for ( int row = fromRow; row <= toRow; row++ )
184 {
185 const double y = yMax - ( row + 0.5 ) * yRes;
186 const int tmpRow = std::floor( ( tmpYMax - y ) / tmpYRes );
187
188 for ( int col = fromCol; col <= toCol; col++ )
189 {
190 const double x = xMin + ( col + 0.5 ) * xRes;
191 const int tmpCol = std::floor( ( x - tmpXMin ) / tmpXRes );
192
193 if ( tmpRow < 0 || tmpRow >= tmpHeight || tmpCol < 0 || tmpCol >= tmpWidth )
194 {
195 QgsDebugError( u"Source row or column limits out of range"_s );
196 block->setIsNoData(); // so that the problem becomes obvious and fixed
197 block->setError( { tr( "Source row or column limits out of range." ), u"Raster"_s } );
198 block->setValid( false );
199 return block.release();
200 }
201
202 const qgssize tmpIndex = static_cast< qgssize >( tmpRow ) * static_cast< qgssize >( tmpWidth ) + tmpCol;
203 const qgssize index = row * static_cast< qgssize >( width ) + col;
204
205 const char *tmpBits = tmpBlock->constBits( tmpIndex );
206 char *bits = block->bits( index );
207 if ( !tmpBits )
208 {
209 QgsDebugError( u"Cannot get input block data tmpRow = %1 tmpCol = %2 tmpIndex = %3."_s.arg( tmpRow ).arg( tmpCol ).arg( tmpIndex ) );
210 continue;
211 }
212 if ( !bits )
213 {
214 QgsDebugError( u"Cannot set output block data."_s );
215 continue;
216 }
217 memcpy( bits, tmpBits, pixelSize );
218 }
219 }
220 }
221 else
222 {
223 if ( !readBlock( bandNo, boundingBox, width, height, block->bits(), feedback ) )
224 {
225 QgsDebugError( u"Error occurred while reading block"_s );
226 block->setIsNoData();
227 block->setError( { tr( "Error occurred while reading block." ), u"Raster"_s } );
228 block->setValid( false );
229 return block.release();
230 }
231 }
232
233 // apply scale and offset
234 block->applyScaleOffset( bandScale( bandNo ), bandOffset( bandNo ) );
235 // apply user no data values
236 block->applyNoDataValues( userNoDataValues( bandNo ) );
237 return block.release();
238}
239
241 : QgsDataProvider( QString(), QgsDataProvider::ProviderOptions(), Qgis::DataProviderReadFlags() )
242 , QgsRasterInterface( nullptr )
243 , mTemporalCapabilities( std::make_unique< QgsRasterDataProviderTemporalCapabilities >() )
244 , mElevationProperties( std::make_unique< QgsRasterDataProviderElevationProperties >() )
245{}
246
248 : QgsDataProvider( uri, options, flags )
249 , QgsRasterInterface( nullptr )
250 , mTemporalCapabilities( std::make_unique< QgsRasterDataProviderTemporalCapabilities >() )
251 , mElevationProperties( std::make_unique< QgsRasterDataProviderElevationProperties >() )
252{}
253
260
268
269// TODO
270// (WMS) IdentifyFormatFeature is not consistent with QgsRaster::IdentifyFormatValue.
271// IdentifyFormatHtml: better error reporting
272QgsRasterIdentifyResult QgsRasterDataProvider::identify( const QgsPointXY &point, Qgis::RasterIdentifyFormat format, const QgsRectangle &boundingBox, int width, int height, int /*dpi*/ )
273{
275
276 QgsDebugMsgLevel( u"Entered"_s, 4 );
277 QMap<int, QVariant> results;
278
280 {
281 QgsDebugError( u"Format not supported"_s );
282 return QgsRasterIdentifyResult( ERR( tr( "Format not supported" ) ) );
283 }
284
285 if ( !extent().contains( point ) )
286 {
287 // Outside the raster
288 for ( int bandNo = 1; bandNo <= bandCount(); bandNo++ )
289 {
290 results.insert( bandNo, QVariant() );
291 }
293 }
294
295 QgsRectangle finalExtent = boundingBox;
296 if ( finalExtent.isEmpty() )
297 finalExtent = extent();
298
299 if ( width == 0 )
300 {
302 }
303 if ( height == 0 )
304 {
305 height = ( capabilities() & Qgis::RasterInterfaceCapability::Size ) ? ySize() : 1000;
306 }
307
308 // Calculate the row / column where the point falls
309 const double xres = ( finalExtent.width() ) / width;
310 const double yres = ( finalExtent.height() ) / height;
311
312 const int col = static_cast< int >( std::floor( ( point.x() - finalExtent.xMinimum() ) / xres ) );
313 const int row = static_cast< int >( std::floor( ( finalExtent.yMaximum() - point.y() ) / yres ) );
314
315 const double xMin = finalExtent.xMinimum() + col * xres;
316 const double xMax = xMin + xres;
317 const double yMax = finalExtent.yMaximum() - row * yres;
318 const double yMin = yMax - yres;
319 const QgsRectangle pixelExtent( xMin, yMin, xMax, yMax );
320
321 for ( int bandNumber = 1; bandNumber <= bandCount(); bandNumber++ )
322 {
323 std::unique_ptr< QgsRasterBlock > bandBlock( block( bandNumber, pixelExtent, 1, 1 ) );
324
325 if ( bandBlock )
326 {
327 const double value = bandBlock->value( 0 );
328 if ( ( sourceHasNoDataValue( bandNumber ) && useSourceNoDataValue( bandNumber ) && ( std::isnan( value ) || qgsDoubleNear( value, sourceNoDataValue( bandNumber ) ) ) )
329 || ( QgsRasterRange::contains( value, userNoDataValues( bandNumber ) ) ) )
330 {
331 results.insert( bandNumber, QVariant() ); // null QVariant represents no data
332 }
333 else
334 {
335 results.insert( bandNumber, value );
336 }
337 }
338 else
339 {
340 results.insert( bandNumber, QVariant() );
341 }
342 }
344}
345
346double QgsRasterDataProvider::sample( const QgsPointXY &point, int band, bool *ok, const QgsRectangle &boundingBox, int width, int height, int dpi )
347{
349
350 if ( ok )
351 *ok = false;
352
353 const auto res = identify( point, Qgis::RasterIdentifyFormat::Value, boundingBox, width, height, dpi );
354 const QVariant value = res.results().value( band );
355
356 if ( !value.isValid() )
357 return std::numeric_limits<double>::quiet_NaN();
358
359 if ( ok )
360 *ok = true;
361
362 return value.toDouble( ok );
363}
364
366{
368
369 return u"text/plain"_s;
370}
371
372bool QgsRasterDataProvider::writeBlock( QgsRasterBlock *block, int band, int xOffset, int yOffset )
373{
375
376 if ( !block )
377 return false;
378 if ( !isEditable() )
379 {
380 setError( QgsError( u"writeBlock() called on read-only provider."_s, u"writeBlock"_s ) );
381 QgsDebugError( u"writeBlock() called on read-only provider."_s );
382 return false;
383 }
384 return write( block->bits(), band, block->width(), block->height(), xOffset, yOffset );
385}
386
387// typedef QList<QPair<QString, QString> > *pyramidResamplingMethods_t();
388QList<QPair<QString, QString> > QgsRasterDataProvider::pyramidResamplingMethods( const QString &providerKey )
389{
390 QList<QPair<QString, QString> > methods = QgsProviderRegistry::instance()->pyramidResamplingMethods( providerKey );
391 if ( methods.isEmpty() )
392 {
393 QgsDebugMsgLevel( u"provider pyramidResamplingMethods returned no methods"_s, 2 );
394 }
395 return methods;
396}
397
399{
401
402 const QList<QgsRasterPyramid> pyramidList = buildPyramidList();
403 return std::any_of( pyramidList.constBegin(), pyramidList.constEnd(), []( QgsRasterPyramid pyramid ) { return pyramid.getExists(); } );
404}
405
407{
409
410 if ( bandNo >= mUserNoDataValue.size() )
411 {
412 for ( int i = mUserNoDataValue.size(); i < bandNo; i++ )
413 {
415 }
416 }
417 QgsDebugMsgLevel( u"set %1 band %1 no data ranges"_s.arg( noData.size() ), 4 );
418
419 if ( mUserNoDataValue[bandNo - 1] != noData )
420 {
421 // Clear statistics
422 mStatistics.erase( std::remove_if( mStatistics.begin(), mStatistics.end(), [bandNo]( const QgsRasterBandStats &stats ) { return stats.bandNumber == bandNo; } ), mStatistics.end() );
423 mHistograms.erase( std::remove_if( mHistograms.begin(), mHistograms.end(), [bandNo]( const QgsRasterHistogram &histogram ) { return histogram.bandNumber == bandNo; } ), mHistograms.end() );
424 mUserNoDataValue[bandNo - 1] = noData;
425 }
426}
427
434
441
448
455
457 const QString &providerKey,
458 const QString &uri,
459 const QString &format,
460 int nBands,
461 Qgis::DataType type,
462 int width,
463 int height,
464 double *geoTransform,
466 const QStringList &creationOptions
467)
468{
469 QgsRasterDataProvider *ret = QgsProviderRegistry::instance()->createRasterDataProvider( providerKey, uri, format, nBands, type, width, height, geoTransform, crs, creationOptions );
470 if ( !ret )
471 {
472 QgsDebugError( "Cannot resolve 'createRasterDataProviderFunction' function in " + providerKey + " provider" );
473 }
474
475 // TODO: it would be good to return invalid QgsRasterDataProvider
476 // with QgsError set, but QgsRasterDataProvider has pure virtual methods
477
478 return ret;
479}
480
482{
483 switch ( format )
484 {
486 return u"Value"_s;
488 return u"Text"_s;
490 return u"Html"_s;
492 return u"Feature"_s;
494 break;
495 }
496 return u"Undefined"_s;
497}
498
500{
501 switch ( format )
502 {
504 return tr( "Value" );
506 return tr( "Text" );
508 return tr( "HTML" );
510 return tr( "Feature" );
512 break;
513 }
514 return u"Undefined"_s;
515}
516
518{
519 if ( formatName == "Value"_L1 )
521 if ( formatName == "Text"_L1 )
523 if ( formatName == "Html"_L1 )
525 if ( formatName == "Feature"_L1 )
528}
529
547
549{
551
552 return QList< double >();
553}
554
556{
558
559 return false;
560}
561
563{
565
566 Q_UNUSED( point )
567 Q_UNUSED( type )
568 return QgsPoint();
569}
570
571bool QgsRasterDataProvider::userNoDataValuesContains( int bandNo, double value ) const
572{
574
575 const QgsRasterRangeList rangeList = mUserNoDataValue.value( bandNo - 1 );
576 return QgsRasterRange::contains( value, rangeList );
577}
578
580{
582
583 mDpi = other.mDpi;
588 mExtent = other.mExtent;
593
594 if ( mTemporalCapabilities && other.mTemporalCapabilities )
595 {
596 *mTemporalCapabilities = *other.mTemporalCapabilities;
597 }
598 if ( mElevationProperties && other.mElevationProperties )
599 {
600 *mElevationProperties = *other.mElevationProperties;
601 }
602}
603
604static Qgis::RasterResamplingMethod resamplingMethodFromString( const QString &str )
605{
606 if ( str == "bilinear"_L1 )
607 {
609 }
610 else if ( str == "cubic"_L1 )
611 {
613 }
614 else if ( str == "cubicSpline"_L1 )
615 {
617 }
618 else if ( str == "lanczos"_L1 )
619 {
621 }
622 else if ( str == "average"_L1 )
623 {
625 }
626 else if ( str == "mode"_L1 )
627 {
629 }
630 else if ( str == "gauss"_L1 )
631 {
633 }
635}
636
637void QgsRasterDataProvider::readXml( const QDomElement &filterElem )
638{
640
641 if ( filterElem.isNull() )
642 {
643 return;
644 }
645
646 const QDomElement resamplingElement = filterElem.firstChildElement( u"resampling"_s );
647 if ( !resamplingElement.isNull() )
648 {
649 setMaxOversampling( resamplingElement.attribute( u"maxOversampling"_s, u"2.0"_s ).toDouble() );
650 setZoomedInResamplingMethod( resamplingMethodFromString( resamplingElement.attribute( u"zoomedInResamplingMethod"_s ) ) );
651 setZoomedOutResamplingMethod( resamplingMethodFromString( resamplingElement.attribute( u"zoomedOutResamplingMethod"_s ) ) );
652 enableProviderResampling( resamplingElement.attribute( u"enabled"_s ) == "true"_L1 );
653 }
654}
655
656static QString resamplingMethodToString( Qgis::RasterResamplingMethod method )
657{
658 switch ( method )
659 {
661 return u"nearestNeighbour"_s;
663 return u"bilinear"_s;
665 return u"cubic"_s;
667 return u"cubicSpline"_s;
669 return u"lanczos"_s;
671 return u"average"_s;
673 return u"mode"_s;
675 return u"gauss"_s;
676 }
677 // should not happen
678 return u"nearestNeighbour"_s;
679}
680
681void QgsRasterDataProvider::writeXml( QDomDocument &doc, QDomElement &parentElem ) const
682{
684
685 QDomElement providerElement = doc.createElement( u"provider"_s );
686 parentElem.appendChild( providerElement );
687
688 QDomElement resamplingElement = doc.createElement( u"resampling"_s );
689 providerElement.appendChild( resamplingElement );
690
691 resamplingElement.setAttribute( u"enabled"_s, mProviderResamplingEnabled ? u"true"_s : u"false"_s );
692
693 resamplingElement.setAttribute( u"zoomedInResamplingMethod"_s, resamplingMethodToString( mZoomedInResamplingMethod ) );
694
695 resamplingElement.setAttribute( u"zoomedOutResamplingMethod"_s, resamplingMethodToString( mZoomedOutResamplingMethod ) );
696
697 resamplingElement.setAttribute( u"maxOversampling"_s, QString::number( mMaxOversampling ) );
698}
699
701{
703
704 try
705 {
706 return mAttributeTables.at( bandNumber ).get();
707 }
708 catch ( std::out_of_range const & )
709 {
710 return nullptr;
711 }
712}
713
715{
717
718 if ( attributeTable )
719 {
720 mAttributeTables[bandNumber] = std::unique_ptr<QgsRasterAttributeTable>( attributeTable );
721 }
722 else
723 {
724 removeAttributeTable( bandNumber );
725 }
726}
727
729{
731
732 if ( mAttributeTables.find( bandNumber ) != std::end( mAttributeTables ) )
733 {
734 mAttributeTables.erase( bandNumber );
735 }
736}
737
738bool QgsRasterDataProvider::writeFileBasedAttributeTable( int bandNumber, const QString &path, QString *errorMessage ) const
739{
741
742 QgsRasterAttributeTable *rat { attributeTable( bandNumber ) };
743 if ( !rat )
744 {
745 if ( errorMessage )
746 {
747 *errorMessage = QObject::tr( "Raster has no Raster Attribute Table for band %1" ).arg( bandNumber );
748 }
749 return false;
750 }
751
752 return rat->writeToFile( path, errorMessage );
753}
754
756{
758
759 if ( errorMessage )
760 {
761 *errorMessage = QObject::tr( "Raster data provider has no native Raster Attribute Table support." );
762 }
763 return false;
764}
765
767{
768 Q_UNUSED( bandNumber )
769 return QString();
770}
771
772bool QgsRasterDataProvider::readFileBasedAttributeTable( int bandNumber, const QString &path, QString *errorMessage )
773{
775
776 auto rat = std::make_unique<QgsRasterAttributeTable>();
777 if ( rat->readFromFile( path, errorMessage ) )
778 {
779 setAttributeTable( bandNumber, rat.release() );
780 return true;
781 }
782 else
783 {
784 return false;
785 }
786}
787
788bool QgsRasterDataProvider::writeNativeAttributeTable( QString *errorMessage ) //#spellok
789{
791
792 Q_UNUSED( errorMessage );
793 return false;
794}
795
797{
799
800 return colorName( colorInterpretation( bandNo ) );
801}
802
804{
805 // Modified copy from GDAL
806 switch ( colorInterpretation )
807 {
809 return tr( "Undefined" );
810
812 return tr( "Gray" );
813
815 return tr( "Palette" );
816
818 return tr( "Red" );
819
821 return tr( "Green" );
822
824 return tr( "Blue" );
825
827 return tr( "Alpha" );
828
830 return tr( "Hue" );
831
833 return tr( "Saturation" );
834
836 return tr( "Lightness" );
837
839 return tr( "Cyan" );
840
842 return tr( "Magenta" );
843
845 return tr( "Yellow" );
846
848 return tr( "Black" );
849
851 return tr( "YCbCr_Y" );
852
854 return tr( "YCbCr_Cb" );
855
857 return tr( "YCbCr_Cr" );
858
860 return tr( "Continuous Palette" );
861
863 return tr( "Panchromatic" );
864
866 return tr( "Coastal" );
867
869 return tr( "Red Edge" );
870
872 return tr( "Near-InfraRed (NIR)" );
873
875 return tr( "Short-Wavelength InfraRed (SWIR)" );
876
878 return tr( "Mid-Wavelength InfraRed (MWIR)" );
879
881 return tr( "Long-Wavelength InfraRed (LWIR)" );
882
884 return tr( "Thermal InfraRed (TIR)" );
885
887 return tr( "Other InfraRed" );
888
890 return tr( "Synthetic Aperture Radar (SAR) Ka band" );
891
893 return tr( "Synthetic Aperture Radar (SAR) K band" );
894
896 return tr( "Synthetic Aperture Radar (SAR) Ku band" );
897
899 return tr( "Synthetic Aperture Radar (SAR) X band" );
900
902 return tr( "Synthetic Aperture Radar (SAR) C band" );
903
905 return tr( "Synthetic Aperture Radar (SAR) S band" );
906
908 return tr( "Synthetic Aperture Radar (SAR) L band" );
909
911 return tr( "Synthetic Aperture Radar (SAR) P band" );
912 }
913 return QString();
914}
915
917{
918 QUrl url = QUrl::fromPercentEncoding( uri.toUtf8() );
919 const QUrlQuery query( url.query() );
920 VirtualRasterParameters components;
921
922 if ( !query.hasQueryItem( u"crs"_s ) )
923 {
924 QgsDebugError( "crs is missing" );
925 if ( ok )
926 *ok = false;
927 return components;
928 }
929 if ( !components.crs.createFromString( query.queryItemValue( u"crs"_s ) ) )
930 {
931 QgsDebugError( "failed to create crs" );
932 if ( ok )
933 *ok = false;
934 return components;
935 }
936
937
938 if ( !query.hasQueryItem( u"extent"_s ) )
939 {
940 QgsDebugError( "extent is missing" );
941 if ( ok )
942 *ok = false;
943 return components;
944 }
945 QStringList pointValuesList = query.queryItemValue( u"extent"_s ).split( ',' );
946 if ( pointValuesList.size() != 4 )
947 {
948 QgsDebugError( "the extent is not correct" );
949 if ( ok )
950 *ok = false;
951 return components;
952 }
953 components.extent = QgsRectangle( pointValuesList.at( 0 ).toDouble(), pointValuesList.at( 1 ).toDouble(), pointValuesList.at( 2 ).toDouble(), pointValuesList.at( 3 ).toDouble() );
954
955 if ( !query.hasQueryItem( u"width"_s ) )
956 {
957 QgsDebugError( "width is missing" );
958 if ( ok )
959 *ok = false;
960 return components;
961 }
962 bool flagW;
963 components.width = query.queryItemValue( u"width"_s ).toInt( &flagW );
964 if ( !flagW || components.width < 0 )
965 {
966 QgsDebugError( "invalid or negative width input" );
967 if ( ok )
968 *ok = false;
969 return components;
970 }
971
972 if ( !query.hasQueryItem( u"height"_s ) )
973 {
974 QgsDebugError( "height is missing" );
975 if ( ok )
976 *ok = false;
977 return components;
978 }
979 bool flagH;
980 components.height = query.queryItemValue( u"height"_s ).toInt( &flagH );
981 if ( !flagH || components.height < 0 )
982 {
983 QgsDebugError( "invalid or negative width input" );
984 if ( ok )
985 *ok = false;
986 return components;
987 }
988
989 if ( !query.hasQueryItem( u"formula"_s ) )
990 {
991 QgsDebugError( "formula is missing" );
992 if ( ok )
993 *ok = false;
994 return components;
995 }
996 components.formula = query.queryItemValue( u"formula"_s );
997
998 const QList<std::pair<QString, QString> > &queryItems { query.queryItems() };
999 for ( const auto &item : std::as_const( queryItems ) )
1000 {
1001 if ( !( item.first.mid( item.first.indexOf( ':' ), -1 ) == ":uri"_L1 ) )
1002 {
1003 continue;
1004 }
1005
1007 rLayer.name = item.first.mid( 0, item.first.indexOf( ':' ) );
1008 rLayer.uri = query.queryItemValue( item.first );
1009 rLayer.provider = query.queryItemValue( item.first.mid( 0, item.first.indexOf( ':' ) ) + u":provider"_s );
1010
1011 if ( rLayer.uri.isNull() || rLayer.provider.isNull() )
1012 {
1013 QgsDebugError( "One or more raster information are missing" );
1014 if ( ok )
1015 *ok = false;
1016 return components;
1017 }
1018
1019 components.rInputLayers.append( rLayer );
1020 }
1021
1022 if ( ok )
1023 *ok = true;
1024 return components;
1025}
1026
1028{
1029 QUrl uri;
1030 QUrlQuery query;
1031
1032 if ( parts.crs.isValid() )
1033 {
1034 query.addQueryItem( u"crs"_s, parts.crs.authid() );
1035 }
1036
1037 if ( !parts.extent.isNull() )
1038 {
1039 QString rect
1040 = QString( "%1,%2,%3,%4" )
1042
1043 query.addQueryItem( u"extent"_s, rect );
1044 }
1045
1046 query.addQueryItem( u"width"_s, QString::number( parts.width ) );
1047
1048 query.addQueryItem( u"height"_s, QString::number( parts.height ) );
1049
1050 query.addQueryItem( u"formula"_s, parts.formula );
1051
1052 if ( !parts.rInputLayers.isEmpty() )
1053 {
1054 for ( const auto &it : parts.rInputLayers )
1055 {
1056 query.addQueryItem( it.name + u":uri"_s, it.uri );
1057 query.addQueryItem( it.name + u":provider"_s, it.provider );
1058 }
1059 }
1060 uri.setQuery( query );
1061 return QString( QUrl::toPercentEncoding( uri.toEncoded() ) );
1062}
1063
1065{
1066 return false;
1067}
1068
1070{
1071 return false;
1072}
1073
1074
1075#undef ERR
Provides global constants and enumerations for use throughout the application.
Definition qgis.h:62
QFlags< RasterProviderCapability > RasterProviderCapabilities
Raster data provider capabilities.
Definition qgis.h:5063
@ NoProviderCapabilities
Provider has no capabilities.
Definition qgis.h:5044
RasterResamplingMethod
Resampling method for raster provider-level resampling.
Definition qgis.h:1562
@ Lanczos
Lanczos windowed sinc interpolation (6x6 kernel).
Definition qgis.h:1567
@ Nearest
Nearest-neighbour resampling.
Definition qgis.h:1563
@ Mode
Mode (selects the value which appears most often of all the sampled points).
Definition qgis.h:1569
@ Bilinear
Bilinear (2x2 kernel) resampling.
Definition qgis.h:1564
@ Average
Average resampling.
Definition qgis.h:1568
@ CubicSpline
Cubic B-Spline Approximation (4x4 kernel).
Definition qgis.h:1566
@ Cubic
Cubic Convolution Approximation (4x4 kernel) resampling.
Definition qgis.h:1565
@ Gauss
Gauss blurring.
Definition qgis.h:1570
RasterInterfaceCapability
Raster interface capabilities.
Definition qgis.h:5010
@ NoCapabilities
No capabilities.
Definition qgis.h:5011
@ Size
Original data source size (and thus resolution) is known, it is not always available,...
Definition qgis.h:5012
@ IdentifyValue
Numerical values.
Definition qgis.h:5017
@ IdentifyFeature
WMS GML -> feature.
Definition qgis.h:5020
QFlags< DataProviderReadFlag > DataProviderReadFlags
Flags which control data provider construction.
Definition qgis.h:512
DataType
Raster data types.
Definition qgis.h:393
RasterColorInterpretation
Raster color interpretation.
Definition qgis.h:4869
@ NIRBand
Near-InfraRed (NIR) band [0.75 - 1.40 um].
Definition qgis.h:4895
@ GreenBand
Green band of RGBA image, or green spectral band [0.51 - 0.60 um].
Definition qgis.h:4874
@ SAR_K_Band
Synthetic Aperture Radar (SAR) K band [1.1 - 1.7 cm / 18 - 27 GHz].
Definition qgis.h:4902
@ SAR_L_Band
Synthetic Aperture Radar (SAR) L band [15 - 30 cm / 1 - 2 GHz].
Definition qgis.h:4907
@ SaturationBand
Saturation band of HLS image.
Definition qgis.h:4878
@ MagentaBand
Magenta band of CMYK image.
Definition qgis.h:4881
@ BlackBand
Black band of CMLY image.
Definition qgis.h:4883
@ AlphaBand
Alpha (0=transparent, 255=opaque).
Definition qgis.h:4876
@ SWIRBand
Short-Wavelength InfraRed (SWIR) band [1.40 - 3.00 um].
Definition qgis.h:4896
@ SAR_X_Band
Synthetic Aperture Radar (SAR) X band [2.4 - 3.8 cm / 8 - 12 GHz].
Definition qgis.h:4904
@ BlueBand
Blue band of RGBA image, or blue spectral band [0.45 - 0.53 um].
Definition qgis.h:4875
@ LWIRBand
Long-Wavelength InfraRed (LWIR) band [8.00 - 15 um].
Definition qgis.h:4898
@ RedEdgeBand
Red-edge band [0.69 - 0.79 um].
Definition qgis.h:4894
@ SAR_Ku_Band
Synthetic Aperture Radar (SAR) Ku band [1.7 - 2.4 cm / 12 - 18 GHz].
Definition qgis.h:4903
@ YellowBand
Yellow band of CMYK image, or yellow spectral band [0.58 - 0.62 um].
Definition qgis.h:4882
@ CyanBand
Cyan band of CMYK image.
Definition qgis.h:4880
@ SAR_C_Band
Synthetic Aperture Radar (SAR) C band [3.8 - 7.5 cm / 4 - 8 GHz].
Definition qgis.h:4905
@ LightnessBand
Lightness band of HLS image.
Definition qgis.h:4879
@ CoastalBand
Coastal band [0.40 - 0.45 um].
Definition qgis.h:4893
@ HueBand
Hue band of HLS image.
Definition qgis.h:4877
@ MWIRBand
Mid-Wavelength InfraRed (MWIR) band [3.00 - 8.00 um].
Definition qgis.h:4897
@ PaletteIndex
Paletted (see associated color table).
Definition qgis.h:4872
@ TIRBand
Thermal InfraRed (TIR) band (MWIR or LWIR) [3 - 15 um].
Definition qgis.h:4899
@ SAR_Ka_Band
Synthetic Aperture Radar (SAR) Ka band [0.8 - 1.1 cm / 27 - 40 GHz].
Definition qgis.h:4901
@ SAR_S_Band
Synthetic Aperture Radar (SAR) S band [7.5 - 15 cm / 2 - 4 GHz].
Definition qgis.h:4906
@ SAR_P_Band
Synthetic Aperture Radar (SAR) P band [30 - 100 cm / 0.3 - 1 GHz].
Definition qgis.h:4908
@ RedBand
Red band of RGBA image, or red spectral band [0.62 - 0.69 um].
Definition qgis.h:4873
@ PanBand
Panchromatic band [0.40 - 1.00 um].
Definition qgis.h:4892
@ ContinuousPalette
Continuous palette, QGIS addition, GRASS.
Definition qgis.h:4887
@ OtherIRBand
Other infrared band [0.75 - 1000 um].
Definition qgis.h:4900
RasterIdentifyFormat
Raster identify formats.
Definition qgis.h:4989
@ Feature
WMS GML/JSON -> feature.
Definition qgis.h:4994
@ Value
Numerical pixel value.
Definition qgis.h:4991
@ Undefined
Undefined.
Definition qgis.h:4990
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.
void setError(const QgsError &error)
Sets error message.
virtual Qgis::DataProviderFlags flags() const
Returns the generic data provider flags.
virtual QgsCoordinateReferenceSystem crs() const =0
Returns the coordinate system for the data source.
QgsDataProvider(const QString &uri=QString(), const QgsDataProvider::ProviderOptions &providerOptions=QgsDataProvider::ProviderOptions(), Qgis::DataProviderReadFlags flags=Qgis::DataProviderReadFlags())
Create a new dataprovider with the specified in the uri.
QgsDataSourceUri uri() const
Gets the data source specification.
A container for error messages.
Definition qgserror.h:83
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition qgsfeedback.h:44
Represents a 2D point.
Definition qgspointxy.h:62
double y
Definition qgspointxy.h:66
double x
Definition qgspointxy.h:65
Point geometry type, with support for z-dimension and m-values.
Definition qgspoint.h:53
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.
Represents a Raster Attribute Table (RAT).
bool writeToFile(const QString &path, QString *errorMessage=nullptr)
Writes the Raster Attribute Table to a DBF file specified by path, optionally reporting any error in ...
The RasterBandStats struct is a container for statistics about a single raster band.
Feedback object tailored for raster block reading.
Raster data container.
static QRect subRect(const QgsRectangle &extent, int width, int height, const QgsRectangle &subExtent)
For extent and width, height find rectangle covered by subextent.
Handles elevation related properties for a raster data provider.
Implementation of data provider temporal properties for QgsRasterDataProviders.
double mMaxOversampling
Maximum boundary for oversampling (to avoid too much data traffic). Default: 2.0.
virtual bool write(const void *data, int band, int width, int height, int xOffset, int yOffset)
Writes into the provider datasource.
QList< bool > mUseSrcNoDataValue
Use source nodata value.
TransformType
Types of transformation in transformCoordinates() function.
bool writeFileBasedAttributeTable(int bandNumber, const QString &path, QString *errorMessage=nullptr) const
Writes the filesystem-based attribute table for the specified bandNumber to path, optionally reportin...
static Qgis::RasterInterfaceCapability identifyFormatToCapability(Qgis::RasterIdentifyFormat format)
Converts a raster identify format to a capability.
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 writeNativeAttributeTable(QString *errorMessage=nullptr)
Writes the native attribute table, optionally reporting any error in errorMessage,...
virtual bool useSourceNoDataValue(int bandNo) const
Returns the source nodata value usage.
bool readFileBasedAttributeTable(int bandNumber, const QString &path, QString *errorMessage=nullptr)
Loads the filesystem-based attribute table for the specified bandNumber from path,...
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.
QgsRasterAttributeTable * attributeTable(int bandNumber) const
Returns the (possibly nullptr) attribute table for the specified bandNumber.
virtual bool setZoomedInResamplingMethod(Qgis::RasterResamplingMethod method)
Set resampling method to apply for zoomed-in operations.
void setAttributeTable(int bandNumber, QgsRasterAttributeTable *attributeTable)
Set the attribute table to attributeTable for the specified bandNumber, if the attributeTable is null...
virtual double sourceNoDataValue(int bandNo) const
Value representing no data value.
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 bool isEditable() const
Checks whether the provider is in editing mode, i.e.
QString colorName(Qgis::RasterColorInterpretation colorInterpretation) const
Returns a string color name representation of a color interpretation.
virtual bool readNativeAttributeTable(QString *errorMessage=nullptr)
Reads the native attribute table, optionally reporting any error in errorMessage, returns true on suc...
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.
virtual bool setZoomedOutResamplingMethod(Qgis::RasterResamplingMethod method)
Set resampling method to apply for zoomed-out operations.
Qgis::RasterResamplingMethod mZoomedInResamplingMethod
Resampling method for zoomed in pixel extraction.
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.
virtual bool closeWithProgress(QgsFeedback *feedback)
Close the provider with feedback.
virtual bool hasReportsDuringClose() const
Returns whether closeWithProgress() will actually report closing progress.
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.
QgsRasterDataProviderElevationProperties * elevationProperties() override
Returns the provider's elevation properties.
bool hasPyramids()
Returns true if raster has at least one existing pyramid.
virtual QgsRasterIdentifyResult identify(const QgsPointXY &point, Qgis::RasterIdentifyFormat format, const QgsRectangle &boundingBox=QgsRectangle(), int width=0, int height=0, int dpi=96)
Identify raster value(s) found on the point position.
virtual double bandScale(int bandNo) const
Read band scale for raster value.
int dpi() const
Returns the dpi of the output device.
virtual Qgis::RasterColorInterpretation colorInterpretation(int bandNo) const
Returns data type for the band specified by number.
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.
QgsRasterBlock * block(int bandNo, const QgsRectangle &boundingBox, int width, int height, QgsRasterBlockFeedback *feedback=nullptr) override
Read block of data using given extent and size.
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.
virtual Qgis::RasterProviderCapabilities providerCapabilities() const
Returns flags containing the supported capabilities of the data provider.
QList< bool > mSrcHasNoDataValue
Source no data value exists.
void removeAttributeTable(int bandNumber)
Remove the attribute table for the specified bandNumber.
Qgis::RasterResamplingMethod mZoomedOutResamplingMethod
Resampling method for zoomed out pixel extraction.
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.
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...
static QString identifyFormatName(Qgis::RasterIdentifyFormat format)
Converts a raster identify format to a string name.
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.
virtual QString bandDescription(int bandNumber)
Returns the description for band bandNumber, or an empty string if the band is not valid or has not d...
static Qgis::RasterIdentifyFormat identifyFormatFromName(const QString &formatName)
Converts a string formatName to a raster identify format.
static QString identifyFormatLabel(Qgis::RasterIdentifyFormat format)
Converts a raster identify format to a translated string label.
virtual void setUserNoDataValue(int bandNo, const QgsRasterRangeList &noData)
virtual QList< QgsRasterPyramid > buildPyramidList(const QList< int > &overviewList=QList< int >())
Returns the raster layers pyramid list.
A container for a histogram of a single raster band.
Raster identify results container.
virtual Qgis::RasterInterfaceCapabilities capabilities() const
Returns the capabilities supported by the interface.
QList< QgsRasterBandStats > mStatistics
List of cached statistics, all bands mixed.
virtual int xSize() const
Gets raster size.
QgsRasterInterface(QgsRasterInterface *input=nullptr)
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 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.
A rectangle specified with double values.
Q_INVOKABLE QString toString(int precision=16) const
Returns a string representation of form xmin,ymin : xmax,ymax Coordinates will be rounded to the spec...
double xMinimum
double yMinimum
double xMaximum
void setYMinimum(double y)
Set the minimum y value.
void setXMinimum(double x)
Set the minimum x value.
void setYMaximum(double y)
Set the maximum y value.
void setXMaximum(double x)
Set the maximum x value.
double yMaximum
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition qgis.h:6893
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:7485
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
Definition qgis.h:6975
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:63
#define QgsDebugError(str)
Definition qgslogger.h:59
#define ERR(message)
QList< QgsRasterRange > QgsRasterRangeList
#define QGIS_PROTECT_QOBJECT_THREAD_ACCESS
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