QGIS API Documentation 3.99.0-Master (d270888f95f)
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 ( int 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 ) ) tmpXRes = xRes;
100 if ( qgsDoubleNear( tmpYRes, yRes ) ) tmpYRes = yRes;
101 }
102 else
103 {
104 tmpXRes = xRes;
105 tmpYRes = yRes;
106 }
107
108 if ( tmpExtent != boundingBox ||
109 tmpXRes > xRes || tmpYRes > yRes )
110 {
111 // Read smaller extent or lower resolution
112
113 if ( !extent().contains( boundingBox ) )
114 {
115 const QRect subRect = QgsRasterBlock::subRect( boundingBox, width, height, extent() );
116 block->setIsNoDataExcept( subRect );
117 }
118
119 // Calculate row/col limits (before tmpExtent is aligned)
120 const int fromRow = std::round( ( boundingBox.yMaximum() - tmpExtent.yMaximum() ) / yRes );
121 const int toRow = std::round( ( boundingBox.yMaximum() - tmpExtent.yMinimum() ) / yRes ) - 1;
122 const int fromCol = std::round( ( tmpExtent.xMinimum() - boundingBox.xMinimum() ) / xRes );
123 const int toCol = std::round( ( tmpExtent.xMaximum() - boundingBox.xMinimum() ) / xRes ) - 1;
124
125 QgsDebugMsgLevel( u"fromRow = %1 toRow = %2 fromCol = %3 toCol = %4"_s.arg( fromRow ).arg( toRow ).arg( fromCol ).arg( toCol ), 4 );
126
127 if ( fromRow < 0 || fromRow >= height || toRow < 0 || toRow >= height ||
128 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
247}
248
251 : QgsDataProvider( uri, options, flags )
252 , QgsRasterInterface( nullptr )
253 , mTemporalCapabilities( std::make_unique< QgsRasterDataProviderTemporalCapabilities >() )
254 , mElevationProperties( std::make_unique< QgsRasterDataProviderElevationProperties >() )
255{
256}
257
264
272
273// TODO
274// (WMS) IdentifyFormatFeature is not consistent with QgsRaster::IdentifyFormatValue.
275// IdentifyFormatHtml: better error reporting
276QgsRasterIdentifyResult QgsRasterDataProvider::identify( const QgsPointXY &point, Qgis::RasterIdentifyFormat format, const QgsRectangle &boundingBox, int width, int height, int /*dpi*/ )
277{
279
280 QgsDebugMsgLevel( u"Entered"_s, 4 );
281 QMap<int, QVariant> results;
282
284 {
285 QgsDebugError( u"Format not supported"_s );
286 return QgsRasterIdentifyResult( ERR( tr( "Format not supported" ) ) );
287 }
288
289 if ( !extent().contains( point ) )
290 {
291 // Outside the raster
292 for ( int bandNo = 1; bandNo <= bandCount(); bandNo++ )
293 {
294 results.insert( bandNo, QVariant() );
295 }
297 }
298
299 QgsRectangle finalExtent = boundingBox;
300 if ( finalExtent.isEmpty() )
301 finalExtent = extent();
302
303 if ( width == 0 )
304 {
306 }
307 if ( height == 0 )
308 {
309 height = ( capabilities() & Qgis::RasterInterfaceCapability::Size ) ? ySize() : 1000;
310 }
311
312 // Calculate the row / column where the point falls
313 const double xres = ( finalExtent.width() ) / width;
314 const double yres = ( finalExtent.height() ) / height;
315
316 const int col = static_cast< int >( std::floor( ( point.x() - finalExtent.xMinimum() ) / xres ) );
317 const int row = static_cast< int >( std::floor( ( finalExtent.yMaximum() - point.y() ) / yres ) );
318
319 const double xMin = finalExtent.xMinimum() + col * xres;
320 const double xMax = xMin + xres;
321 const double yMax = finalExtent.yMaximum() - row * yres;
322 const double yMin = yMax - yres;
323 const QgsRectangle pixelExtent( xMin, yMin, xMax, yMax );
324
325 for ( int bandNumber = 1; bandNumber <= bandCount(); bandNumber++ )
326 {
327 std::unique_ptr< QgsRasterBlock > bandBlock( block( bandNumber, pixelExtent, 1, 1 ) );
328
329 if ( bandBlock )
330 {
331 const double value = bandBlock->value( 0 );
332 if ( ( sourceHasNoDataValue( bandNumber ) && useSourceNoDataValue( bandNumber ) &&
333 ( std::isnan( value ) || qgsDoubleNear( value, sourceNoDataValue( bandNumber ) ) ) ) ||
334 ( QgsRasterRange::contains( value, userNoDataValues( bandNumber ) ) ) )
335 {
336 results.insert( bandNumber, QVariant() ); // null QVariant represents no data
337 }
338 else
339 {
340 results.insert( bandNumber, value );
341 }
342 }
343 else
344 {
345 results.insert( bandNumber, QVariant() );
346 }
347 }
349}
350
351double QgsRasterDataProvider::sample( const QgsPointXY &point, int band,
352 bool *ok, const QgsRectangle &boundingBox, int width, int height, int dpi )
353{
355
356 if ( ok )
357 *ok = false;
358
359 const auto res = identify( point, Qgis::RasterIdentifyFormat::Value, boundingBox, width, height, dpi );
360 const QVariant value = res.results().value( band );
361
362 if ( !value.isValid() )
363 return std::numeric_limits<double>::quiet_NaN();
364
365 if ( ok )
366 *ok = true;
367
368 return value.toDouble( ok );
369}
370
372{
374
375 return u"text/plain"_s;
376}
377
378bool QgsRasterDataProvider::writeBlock( QgsRasterBlock *block, int band, int xOffset, int yOffset )
379{
381
382 if ( !block )
383 return false;
384 if ( !isEditable() )
385 {
386 setError( QgsError( u"writeBlock() called on read-only provider."_s, u"writeBlock"_s ) );
387 QgsDebugError( u"writeBlock() called on read-only provider."_s );
388 return false;
389 }
390 return write( block->bits(), band, block->width(), block->height(), xOffset, yOffset );
391}
392
393// typedef QList<QPair<QString, QString> > *pyramidResamplingMethods_t();
394QList<QPair<QString, QString> > QgsRasterDataProvider::pyramidResamplingMethods( const QString &providerKey )
395{
396 QList<QPair<QString, QString> > methods = QgsProviderRegistry::instance()->pyramidResamplingMethods( providerKey );
397 if ( methods.isEmpty() )
398 {
399 QgsDebugMsgLevel( u"provider pyramidResamplingMethods returned no methods"_s, 2 );
400 }
401 return methods;
402}
403
405{
407
408 const QList<QgsRasterPyramid> pyramidList = buildPyramidList();
409 return std::any_of( pyramidList.constBegin(), pyramidList.constEnd(), []( QgsRasterPyramid pyramid ) { return pyramid.getExists(); } );
410}
411
413{
415
416 if ( bandNo >= mUserNoDataValue.size() )
417 {
418 for ( int i = mUserNoDataValue.size(); i < bandNo; i++ )
419 {
421 }
422 }
423 QgsDebugMsgLevel( u"set %1 band %1 no data ranges"_s.arg( noData.size() ), 4 );
424
425 if ( mUserNoDataValue[bandNo - 1] != noData )
426 {
427 // Clear statistics
428 mStatistics.erase( std::remove_if( mStatistics.begin(), mStatistics.end(), [bandNo]( const QgsRasterBandStats & stats )
429 {
430 return stats.bandNumber == bandNo;
431 } ), mStatistics.end() );
432 mHistograms.erase( std::remove_if( mHistograms.begin(), mHistograms.end(), [bandNo]( const QgsRasterHistogram & histogram )
433 {
434 return histogram.bandNumber == bandNo;
435 } ), mHistograms.end() );
436 mUserNoDataValue[bandNo - 1] = noData;
437 }
438}
439
446
453
460
467
469 const QString &uri,
470 const QString &format, int nBands,
471 Qgis::DataType type,
472 int width, int height, double *geoTransform,
474 const QStringList &creationOptions )
475{
477 providerKey,
478 uri, format,
479 nBands, type, width,
480 height, geoTransform, crs, creationOptions );
481 if ( !ret )
482 {
483 QgsDebugError( "Cannot resolve 'createRasterDataProviderFunction' function in " + providerKey + " provider" );
484 }
485
486 // TODO: it would be good to return invalid QgsRasterDataProvider
487 // with QgsError set, but QgsRasterDataProvider has pure virtual methods
488
489 return ret;
490}
491
493{
494 switch ( format )
495 {
497 return u"Value"_s;
499 return u"Text"_s;
501 return u"Html"_s;
503 return u"Feature"_s;
505 break;
506 }
507 return u"Undefined"_s;
508}
509
511{
512 switch ( format )
513 {
515 return tr( "Value" );
517 return tr( "Text" );
519 return tr( "HTML" );
521 return tr( "Feature" );
523 break;
524 }
525 return u"Undefined"_s;
526}
527
529{
530 if ( formatName == "Value"_L1 )
532 if ( formatName == "Text"_L1 )
534 if ( formatName == "Html"_L1 )
536 if ( formatName == "Feature"_L1 )
539}
540
558
560{
562
563 return QList< double >();
564}
565
567{
569
570 return false;
571}
572
574{
576
577 Q_UNUSED( point )
578 Q_UNUSED( type )
579 return QgsPoint();
580}
581
582bool QgsRasterDataProvider::userNoDataValuesContains( int bandNo, double value ) const
583{
585
586 const QgsRasterRangeList rangeList = mUserNoDataValue.value( bandNo - 1 );
587 return QgsRasterRange::contains( value, rangeList );
588}
589
591{
593
594 mDpi = other.mDpi;
599 mExtent = other.mExtent;
604
605 if ( mTemporalCapabilities && other.mTemporalCapabilities )
606 {
607 *mTemporalCapabilities = *other.mTemporalCapabilities;
608 }
609 if ( mElevationProperties && other.mElevationProperties )
610 {
611 *mElevationProperties = *other.mElevationProperties;
612 }
613}
614
615static Qgis::RasterResamplingMethod resamplingMethodFromString( const QString &str )
616{
617 if ( str == "bilinear"_L1 )
618 {
620 }
621 else if ( str == "cubic"_L1 )
622 {
624 }
625 else if ( str == "cubicSpline"_L1 )
626 {
628 }
629 else if ( str == "lanczos"_L1 )
630 {
632 }
633 else if ( str == "average"_L1 )
634 {
636 }
637 else if ( str == "mode"_L1 )
638 {
640 }
641 else if ( str == "gauss"_L1 )
642 {
644 }
646}
647
648void QgsRasterDataProvider::readXml( const QDomElement &filterElem )
649{
651
652 if ( filterElem.isNull() )
653 {
654 return;
655 }
656
657 const QDomElement resamplingElement = filterElem.firstChildElement( u"resampling"_s );
658 if ( !resamplingElement.isNull() )
659 {
660 setMaxOversampling( resamplingElement.attribute( u"maxOversampling"_s, u"2.0"_s ).toDouble() );
661 setZoomedInResamplingMethod( resamplingMethodFromString( resamplingElement.attribute( u"zoomedInResamplingMethod"_s ) ) );
662 setZoomedOutResamplingMethod( resamplingMethodFromString( resamplingElement.attribute( u"zoomedOutResamplingMethod"_s ) ) );
663 enableProviderResampling( resamplingElement.attribute( u"enabled"_s ) == "true"_L1 );
664 }
665}
666
667static QString resamplingMethodToString( Qgis::RasterResamplingMethod method )
668{
669 switch ( method )
670 {
672 return u"nearestNeighbour"_s;
674 return u"bilinear"_s;
676 return u"cubic"_s;
678 return u"cubicSpline"_s;
680 return u"lanczos"_s;
682 return u"average"_s;
684 return u"mode"_s;
686 return u"gauss"_s;
687 }
688 // should not happen
689 return u"nearestNeighbour"_s;
690}
691
692void QgsRasterDataProvider::writeXml( QDomDocument &doc, QDomElement &parentElem ) const
693{
695
696 QDomElement providerElement = doc.createElement( u"provider"_s );
697 parentElem.appendChild( providerElement );
698
699 QDomElement resamplingElement = doc.createElement( u"resampling"_s );
700 providerElement.appendChild( resamplingElement );
701
702 resamplingElement.setAttribute( u"enabled"_s,
703 mProviderResamplingEnabled ? u"true"_s : u"false"_s );
704
705 resamplingElement.setAttribute( u"zoomedInResamplingMethod"_s,
706 resamplingMethodToString( mZoomedInResamplingMethod ) );
707
708 resamplingElement.setAttribute( u"zoomedOutResamplingMethod"_s,
709 resamplingMethodToString( mZoomedOutResamplingMethod ) );
710
711 resamplingElement.setAttribute( u"maxOversampling"_s,
712 QString::number( mMaxOversampling ) );
713}
714
716{
718
719 try
720 {
721 return mAttributeTables.at( bandNumber ).get();
722 }
723 catch ( std::out_of_range const & )
724 {
725 return nullptr;
726 }
727}
728
730{
732
733 if ( attributeTable )
734 {
735 mAttributeTables[ bandNumber ] = std::unique_ptr<QgsRasterAttributeTable>( attributeTable );
736 }
737 else
738 {
739 removeAttributeTable( bandNumber );
740 }
741}
742
744{
746
747 if ( mAttributeTables.find( bandNumber ) != std::end( mAttributeTables ) )
748 {
749 mAttributeTables.erase( bandNumber );
750 }
751}
752
753bool QgsRasterDataProvider::writeFileBasedAttributeTable( int bandNumber, const QString &path, QString *errorMessage ) const
754{
756
757 QgsRasterAttributeTable *rat { attributeTable( bandNumber ) };
758 if ( ! rat )
759 {
760 if ( errorMessage )
761 {
762 *errorMessage = QObject::tr( "Raster has no Raster Attribute Table for band %1" ).arg( bandNumber );
763 }
764 return false;
765 }
766
767 return rat->writeToFile( path, errorMessage );
768}
769
771{
773
774 if ( errorMessage )
775 {
776 *errorMessage = QObject::tr( "Raster data provider has no native Raster Attribute Table support." );
777 }
778 return false;
779}
780
782{
783 Q_UNUSED( bandNumber )
784 return QString();
785}
786
787bool QgsRasterDataProvider::readFileBasedAttributeTable( int bandNumber, const QString &path, QString *errorMessage )
788{
790
791 auto rat = std::make_unique<QgsRasterAttributeTable>();
792 if ( rat->readFromFile( path, errorMessage ) )
793 {
794 setAttributeTable( bandNumber, rat.release() );
795 return true;
796 }
797 else
798 {
799 return false;
800 }
801}
802
803bool QgsRasterDataProvider::writeNativeAttributeTable( QString *errorMessage ) //#spellok
804{
806
807 Q_UNUSED( errorMessage );
808 return false;
809}
810
812{
814
815 return colorName( colorInterpretation( bandNo ) );
816}
817
819{
820 // Modified copy from GDAL
821 switch ( colorInterpretation )
822 {
824 return tr( "Undefined" );
825
827 return tr( "Gray" );
828
830 return tr( "Palette" );
831
833 return tr( "Red" );
834
836 return tr( "Green" );
837
839 return tr( "Blue" );
840
842 return tr( "Alpha" );
843
845 return tr( "Hue" );
846
848 return tr( "Saturation" );
849
851 return tr( "Lightness" );
852
854 return tr( "Cyan" );
855
857 return tr( "Magenta" );
858
860 return tr( "Yellow" );
861
863 return tr( "Black" );
864
866 return tr( "YCbCr_Y" );
867
869 return tr( "YCbCr_Cb" );
870
872 return tr( "YCbCr_Cr" );
873
875 return tr( "Continuous Palette" );
876
878 return tr( "Panchromatic" );
879
881 return tr( "Coastal" );
882
884 return tr( "Red Edge" );
885
887 return tr( "Near-InfraRed (NIR)" );
888
890 return tr( "Short-Wavelength InfraRed (SWIR)" );
891
893 return tr( "Mid-Wavelength InfraRed (MWIR)" );
894
896 return tr( "Long-Wavelength InfraRed (LWIR)" );
897
899 return tr( "Thermal InfraRed (TIR)" );
900
902 return tr( "Other InfraRed" );
903
905 return tr( "Synthetic Aperture Radar (SAR) Ka band" );
906
908 return tr( "Synthetic Aperture Radar (SAR) K band" );
909
911 return tr( "Synthetic Aperture Radar (SAR) Ku band" );
912
914 return tr( "Synthetic Aperture Radar (SAR) X band" );
915
917 return tr( "Synthetic Aperture Radar (SAR) C band" );
918
920 return tr( "Synthetic Aperture Radar (SAR) S band" );
921
923 return tr( "Synthetic Aperture Radar (SAR) L band" );
924
926 return tr( "Synthetic Aperture Radar (SAR) P band" );
927 }
928 return QString();
929}
930
932{
933 QUrl url = QUrl::fromPercentEncoding( uri.toUtf8() );
934 const QUrlQuery query( url.query() );
935 VirtualRasterParameters components;
936
937 if ( ! query.hasQueryItem( u"crs"_s ) )
938 {
939 QgsDebugError( "crs is missing" );
940 if ( ok ) *ok = false;
941 return components;
942 }
943 if ( ! components.crs.createFromString( query.queryItemValue( u"crs"_s ) ) )
944 {
945 QgsDebugError( "failed to create crs" );
946 if ( ok ) *ok = false;
947 return components;
948 }
949
950
951 if ( ! query.hasQueryItem( u"extent"_s ) )
952 {
953 QgsDebugError( "extent is missing" );
954 if ( ok ) *ok = false;
955 return components;
956 }
957 QStringList pointValuesList = query.queryItemValue( u"extent"_s ).split( ',' );
958 if ( pointValuesList.size() != 4 )
959 {
960 QgsDebugError( "the extent is not correct" );
961 if ( ok ) *ok = false;
962 return components;
963 }
964 components.extent = QgsRectangle( pointValuesList.at( 0 ).toDouble(), pointValuesList.at( 1 ).toDouble(),
965 pointValuesList.at( 2 ).toDouble(), pointValuesList.at( 3 ).toDouble() );
966
967 if ( ! query.hasQueryItem( u"width"_s ) )
968 {
969 QgsDebugError( "width is missing" );
970 if ( ok ) *ok = false;
971 return components;
972 }
973 bool flagW;
974 components.width = query.queryItemValue( u"width"_s ).toInt( & flagW );
975 if ( !flagW || components.width < 0 )
976 {
977 QgsDebugError( "invalid or negative width input" );
978 if ( ok ) *ok = false;
979 return components;
980 }
981
982 if ( ! query.hasQueryItem( u"height"_s ) )
983 {
984 QgsDebugError( "height is missing" );
985 if ( ok ) *ok = false;
986 return components;
987 }
988 bool flagH;
989 components.height = query.queryItemValue( u"height"_s ).toInt( & flagH );
990 if ( !flagH || components.height < 0 )
991 {
992 QgsDebugError( "invalid or negative width input" );
993 if ( ok ) *ok = false;
994 return components;
995 }
996
997 if ( ! query.hasQueryItem( u"formula"_s ) )
998 {
999 QgsDebugError( "formula is missing" );
1000 if ( ok ) *ok = false;
1001 return components;
1002 }
1003 components.formula = query.queryItemValue( u"formula"_s );
1004
1005 for ( const auto &item : query.queryItems() )
1006 {
1007 if ( !( item.first.mid( item.first.indexOf( ':' ), -1 ) == ":uri"_L1 ) )
1008 {
1009 continue;
1010 }
1011
1013 rLayer.name = item.first.mid( 0, item.first.indexOf( ':' ) );
1014 rLayer.uri = query.queryItemValue( item.first );
1015 rLayer.provider = query.queryItemValue( item.first.mid( 0, item.first.indexOf( ':' ) ) + u":provider"_s );
1016
1017 if ( rLayer.uri.isNull() || rLayer.provider.isNull() )
1018 {
1019 QgsDebugError( "One or more raster information are missing" );
1020 if ( ok ) *ok = false;
1021 return components;
1022 }
1023
1024 components.rInputLayers.append( rLayer ) ;
1025
1026 }
1027
1028 if ( ok ) *ok = true;
1029 return components;
1030}
1031
1033{
1034 QUrl uri;
1035 QUrlQuery query;
1036
1037 if ( parts.crs.isValid() )
1038 {
1039 query.addQueryItem( u"crs"_s, parts.crs.authid() );
1040 }
1041
1042 if ( ! parts.extent.isNull() )
1043 {
1044 QString rect = QString( "%1,%2,%3,%4" ).arg( qgsDoubleToString( parts.extent.xMinimum() ), qgsDoubleToString( parts.extent.yMinimum() ),
1046
1047 query.addQueryItem( u"extent"_s, rect );
1048 }
1049
1050 query.addQueryItem( u"width"_s, QString::number( parts.width ) );
1051
1052 query.addQueryItem( u"height"_s, QString::number( parts.height ) );
1053
1054 query.addQueryItem( u"formula"_s, parts.formula );
1055
1056 if ( ! parts.rInputLayers.isEmpty() )
1057 {
1058 for ( const auto &it : parts.rInputLayers )
1059 {
1060 query.addQueryItem( it.name + u":uri"_s, it.uri );
1061 query.addQueryItem( it.name + u":provider"_s, it.provider );
1062 }
1063 }
1064 uri.setQuery( query );
1065 return QString( QUrl::toPercentEncoding( uri.toEncoded() ) );
1066}
1067
1069{
1070 return false;
1071}
1072
1074{
1075 return false;
1076}
1077
1078
1079#undef ERR
Provides global constants and enumerations for use throughout the application.
Definition qgis.h:59
QFlags< RasterProviderCapability > RasterProviderCapabilities
Raster data provider capabilities.
Definition qgis.h:4978
@ NoProviderCapabilities
Provider has no capabilities.
Definition qgis.h:4959
RasterResamplingMethod
Resampling method for raster provider-level resampling.
Definition qgis.h:1542
@ Lanczos
Lanczos windowed sinc interpolation (6x6 kernel).
Definition qgis.h:1547
@ Nearest
Nearest-neighbour resampling.
Definition qgis.h:1543
@ Mode
Mode (selects the value which appears most often of all the sampled points).
Definition qgis.h:1549
@ Bilinear
Bilinear (2x2 kernel) resampling.
Definition qgis.h:1544
@ Average
Average resampling.
Definition qgis.h:1548
@ CubicSpline
Cubic B-Spline Approximation (4x4 kernel).
Definition qgis.h:1546
@ Cubic
Cubic Convolution Approximation (4x4 kernel) resampling.
Definition qgis.h:1545
@ Gauss
Gauss blurring.
Definition qgis.h:1550
RasterInterfaceCapability
Raster interface capabilities.
Definition qgis.h:4925
@ NoCapabilities
No capabilities.
Definition qgis.h:4926
@ Size
Original data source size (and thus resolution) is known, it is not always available,...
Definition qgis.h:4927
@ IdentifyValue
Numerical values.
Definition qgis.h:4932
@ IdentifyFeature
WMS GML -> feature.
Definition qgis.h:4935
QFlags< DataProviderReadFlag > DataProviderReadFlags
Flags which control data provider construction.
Definition qgis.h:505
DataType
Raster data types.
Definition qgis.h:379
RasterColorInterpretation
Raster color interpretation.
Definition qgis.h:4784
@ NIRBand
Near-InfraRed (NIR) band [0.75 - 1.40 um].
Definition qgis.h:4810
@ GreenBand
Green band of RGBA image, or green spectral band [0.51 - 0.60 um].
Definition qgis.h:4789
@ SAR_K_Band
Synthetic Aperture Radar (SAR) K band [1.1 - 1.7 cm / 18 - 27 GHz].
Definition qgis.h:4817
@ SAR_L_Band
Synthetic Aperture Radar (SAR) L band [15 - 30 cm / 1 - 2 GHz].
Definition qgis.h:4822
@ SaturationBand
Saturation band of HLS image.
Definition qgis.h:4793
@ MagentaBand
Magenta band of CMYK image.
Definition qgis.h:4796
@ BlackBand
Black band of CMLY image.
Definition qgis.h:4798
@ AlphaBand
Alpha (0=transparent, 255=opaque).
Definition qgis.h:4791
@ SWIRBand
Short-Wavelength InfraRed (SWIR) band [1.40 - 3.00 um].
Definition qgis.h:4811
@ SAR_X_Band
Synthetic Aperture Radar (SAR) X band [2.4 - 3.8 cm / 8 - 12 GHz].
Definition qgis.h:4819
@ BlueBand
Blue band of RGBA image, or blue spectral band [0.45 - 0.53 um].
Definition qgis.h:4790
@ LWIRBand
Long-Wavelength InfraRed (LWIR) band [8.00 - 15 um].
Definition qgis.h:4813
@ RedEdgeBand
Red-edge band [0.69 - 0.79 um].
Definition qgis.h:4809
@ SAR_Ku_Band
Synthetic Aperture Radar (SAR) Ku band [1.7 - 2.4 cm / 12 - 18 GHz].
Definition qgis.h:4818
@ YellowBand
Yellow band of CMYK image, or yellow spectral band [0.58 - 0.62 um].
Definition qgis.h:4797
@ CyanBand
Cyan band of CMYK image.
Definition qgis.h:4795
@ SAR_C_Band
Synthetic Aperture Radar (SAR) C band [3.8 - 7.5 cm / 4 - 8 GHz].
Definition qgis.h:4820
@ LightnessBand
Lightness band of HLS image.
Definition qgis.h:4794
@ CoastalBand
Coastal band [0.40 - 0.45 um].
Definition qgis.h:4808
@ HueBand
Hue band of HLS image.
Definition qgis.h:4792
@ MWIRBand
Mid-Wavelength InfraRed (MWIR) band [3.00 - 8.00 um].
Definition qgis.h:4812
@ PaletteIndex
Paletted (see associated color table).
Definition qgis.h:4787
@ TIRBand
Thermal InfraRed (TIR) band (MWIR or LWIR) [3 - 15 um].
Definition qgis.h:4814
@ SAR_Ka_Band
Synthetic Aperture Radar (SAR) Ka band [0.8 - 1.1 cm / 27 - 40 GHz].
Definition qgis.h:4816
@ SAR_S_Band
Synthetic Aperture Radar (SAR) S band [7.5 - 15 cm / 2 - 4 GHz].
Definition qgis.h:4821
@ SAR_P_Band
Synthetic Aperture Radar (SAR) P band [30 - 100 cm / 0.3 - 1 GHz].
Definition qgis.h:4823
@ RedBand
Red band of RGBA image, or red spectral band [0.62 - 0.69 um].
Definition qgis.h:4788
@ PanBand
Panchromatic band [0.40 - 1.00 um].
Definition qgis.h:4807
@ ContinuousPalette
Continuous palette, QGIS addition, GRASS.
Definition qgis.h:4802
@ OtherIRBand
Other infrared band [0.75 - 1000 um].
Definition qgis.h:4815
RasterIdentifyFormat
Raster identify formats.
Definition qgis.h:4904
@ Feature
WMS GML/JSON -> feature.
Definition qgis.h:4909
@ Value
Numerical pixel value.
Definition qgis.h:4906
@ Undefined
Undefined.
Definition qgis.h:4905
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 truncated to the sp...
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:6817
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:7423
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
Definition qgis.h:6900
#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