QGIS API Documentation 4.1.0-Master (3b8ef1f72a3)
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 if ( !feedback || !feedback->isCanceled() )
170 {
171 QgsDebugError( u"Error occurred while reading block"_s );
172 block->setError( { tr( "Error occurred while reading block." ), u"Raster"_s } );
173 }
174 block->setValid( false );
175 block->setIsNoData();
176 return block.release();
177 }
178
179 const int pixelSize = dataTypeSize( bandNo );
180
181 const double xMin = boundingBox.xMinimum();
182 const double yMax = boundingBox.yMaximum();
183 const double tmpXMin = tmpExtent.xMinimum();
184 const double tmpYMax = tmpExtent.yMaximum();
185
186 for ( int row = fromRow; row <= toRow; row++ )
187 {
188 const double y = yMax - ( row + 0.5 ) * yRes;
189 const int tmpRow = std::floor( ( tmpYMax - y ) / tmpYRes );
190
191 for ( int col = fromCol; col <= toCol; col++ )
192 {
193 const double x = xMin + ( col + 0.5 ) * xRes;
194 const int tmpCol = std::floor( ( x - tmpXMin ) / tmpXRes );
195
196 if ( tmpRow < 0 || tmpRow >= tmpHeight || tmpCol < 0 || tmpCol >= tmpWidth )
197 {
198 QgsDebugError( u"Source row or column limits out of range"_s );
199 block->setIsNoData(); // so that the problem becomes obvious and fixed
200 block->setError( { tr( "Source row or column limits out of range." ), u"Raster"_s } );
201 block->setValid( false );
202 return block.release();
203 }
204
205 const qgssize tmpIndex = static_cast< qgssize >( tmpRow ) * static_cast< qgssize >( tmpWidth ) + tmpCol;
206 const qgssize index = row * static_cast< qgssize >( width ) + col;
207
208 const char *tmpBits = tmpBlock->constBits( tmpIndex );
209 char *bits = block->bits( index );
210 if ( !tmpBits )
211 {
212 QgsDebugError( u"Cannot get input block data tmpRow = %1 tmpCol = %2 tmpIndex = %3."_s.arg( tmpRow ).arg( tmpCol ).arg( tmpIndex ) );
213 continue;
214 }
215 if ( !bits )
216 {
217 QgsDebugError( u"Cannot set output block data."_s );
218 continue;
219 }
220 memcpy( bits, tmpBits, pixelSize );
221 }
222 }
223 }
224 else
225 {
226 if ( !readBlock( bandNo, boundingBox, width, height, block->bits(), feedback ) )
227 {
228 if ( !feedback || !feedback->isCanceled() )
229 {
230 QgsDebugError( u"Error occurred while reading block"_s );
231 block->setError( { tr( "Error occurred while reading block." ), u"Raster"_s } );
232 }
233 block->setIsNoData();
234 block->setValid( false );
235 return block.release();
236 }
237 }
238
239 // apply scale and offset
240 block->applyScaleOffset( bandScale( bandNo ), bandOffset( bandNo ) );
241 // apply user no data values
242 block->applyNoDataValues( userNoDataValues( bandNo ) );
243 return block.release();
244}
245
247 : QgsDataProvider( QString(), QgsDataProvider::ProviderOptions(), Qgis::DataProviderReadFlags() )
248 , QgsRasterInterface( nullptr )
249 , mTemporalCapabilities( std::make_unique< QgsRasterDataProviderTemporalCapabilities >() )
250 , mElevationProperties( std::make_unique< QgsRasterDataProviderElevationProperties >() )
251{}
252
254 : QgsDataProvider( uri, options, flags )
255 , QgsRasterInterface( nullptr )
256 , mTemporalCapabilities( std::make_unique< QgsRasterDataProviderTemporalCapabilities >() )
257 , mElevationProperties( std::make_unique< QgsRasterDataProviderElevationProperties >() )
258{}
259
266
274
275// TODO
276// (WMS) IdentifyFormatFeature is not consistent with QgsRaster::IdentifyFormatValue.
277// IdentifyFormatHtml: better error reporting
278QgsRasterIdentifyResult QgsRasterDataProvider::identify( const QgsPointXY &point, Qgis::RasterIdentifyFormat format, const QgsRectangle &boundingBox, int width, int height, int /*dpi*/ )
279{
281
282 QgsDebugMsgLevel( u"Entered"_s, 4 );
283 QMap<int, QVariant> results;
284
286 {
287 QgsDebugError( u"Format not supported"_s );
288 return QgsRasterIdentifyResult( ERR( tr( "Format not supported" ) ) );
289 }
290
291 if ( !extent().contains( point ) )
292 {
293 // Outside the raster
294 for ( int bandNo = 1; bandNo <= bandCount(); bandNo++ )
295 {
296 results.insert( bandNo, QVariant() );
297 }
299 }
300
301 QgsRectangle finalExtent = boundingBox;
302 if ( finalExtent.isEmpty() )
303 finalExtent = extent();
304
305 if ( width == 0 )
306 {
308 }
309 if ( height == 0 )
310 {
311 height = ( capabilities() & Qgis::RasterInterfaceCapability::Size ) ? ySize() : 1000;
312 }
313
314 // Calculate the row / column where the point falls
315 const double xres = ( finalExtent.width() ) / width;
316 const double yres = ( finalExtent.height() ) / height;
317
318 const int col = static_cast< int >( std::floor( ( point.x() - finalExtent.xMinimum() ) / xres ) );
319 const int row = static_cast< int >( std::floor( ( finalExtent.yMaximum() - point.y() ) / yres ) );
320
321 const double xMin = finalExtent.xMinimum() + col * xres;
322 const double xMax = xMin + xres;
323 const double yMax = finalExtent.yMaximum() - row * yres;
324 const double yMin = yMax - yres;
325 const QgsRectangle pixelExtent( xMin, yMin, xMax, yMax );
326
327 for ( int bandNumber = 1; bandNumber <= bandCount(); bandNumber++ )
328 {
329 std::unique_ptr< QgsRasterBlock > bandBlock( block( bandNumber, pixelExtent, 1, 1 ) );
330
331 if ( bandBlock )
332 {
333 const double value = bandBlock->value( 0 );
334 if ( ( sourceHasNoDataValue( bandNumber ) && useSourceNoDataValue( bandNumber ) && ( std::isnan( value ) || qgsDoubleNear( value, sourceNoDataValue( bandNumber ) ) ) )
335 || ( QgsRasterRange::contains( value, userNoDataValues( bandNumber ) ) ) )
336 {
337 results.insert( bandNumber, QVariant() ); // null QVariant represents no data
338 }
339 else
340 {
341 results.insert( bandNumber, value );
342 }
343 }
344 else
345 {
346 results.insert( bandNumber, QVariant() );
347 }
348 }
350}
351
352double QgsRasterDataProvider::sample( const QgsPointXY &point, int band, 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 ) { return stats.bandNumber == bandNo; } ), mStatistics.end() );
429 mHistograms.erase( std::remove_if( mHistograms.begin(), mHistograms.end(), [bandNo]( const QgsRasterHistogram &histogram ) { return histogram.bandNumber == bandNo; } ), mHistograms.end() );
430 mUserNoDataValue[bandNo - 1] = noData;
431 }
432}
433
440
447
454
461
463 const QString &providerKey,
464 const QString &uri,
465 const QString &format,
466 int nBands,
467 Qgis::DataType type,
468 int width,
469 int height,
470 double *geoTransform,
472 const QStringList &creationOptions
473)
474{
475 QgsRasterDataProvider *ret = QgsProviderRegistry::instance()->createRasterDataProvider( providerKey, uri, format, nBands, type, width, height, geoTransform, crs, creationOptions );
476 if ( !ret )
477 {
478 QgsDebugError( "Cannot resolve 'createRasterDataProviderFunction' function in " + providerKey + " provider" );
479 }
480
481 // TODO: it would be good to return invalid QgsRasterDataProvider
482 // with QgsError set, but QgsRasterDataProvider has pure virtual methods
483
484 return ret;
485}
486
488{
489 switch ( format )
490 {
492 return u"Value"_s;
494 return u"Text"_s;
496 return u"Html"_s;
498 return u"Feature"_s;
500 break;
501 }
502 return u"Undefined"_s;
503}
504
506{
507 switch ( format )
508 {
510 return tr( "Value" );
512 return tr( "Text" );
514 return tr( "HTML" );
516 return tr( "Feature" );
518 break;
519 }
520 return u"Undefined"_s;
521}
522
524{
525 if ( formatName == "Value"_L1 )
527 if ( formatName == "Text"_L1 )
529 if ( formatName == "Html"_L1 )
531 if ( formatName == "Feature"_L1 )
534}
535
553
555{
557
558 return QList< double >();
559}
560
562{
564
565 return false;
566}
567
569{
571
572 Q_UNUSED( point )
573 Q_UNUSED( type )
574 return QgsPoint();
575}
576
577bool QgsRasterDataProvider::userNoDataValuesContains( int bandNo, double value ) const
578{
580
581 const QgsRasterRangeList rangeList = mUserNoDataValue.value( bandNo - 1 );
582 return QgsRasterRange::contains( value, rangeList );
583}
584
586{
588
589 mDpi = other.mDpi;
594 mExtent = other.mExtent;
599
600 if ( mTemporalCapabilities && other.mTemporalCapabilities )
601 {
602 *mTemporalCapabilities = *other.mTemporalCapabilities;
603 }
604 if ( mElevationProperties && other.mElevationProperties )
605 {
606 *mElevationProperties = *other.mElevationProperties;
607 }
608}
609
610static Qgis::RasterResamplingMethod resamplingMethodFromString( const QString &str )
611{
612 if ( str == "bilinear"_L1 )
613 {
615 }
616 else if ( str == "cubic"_L1 )
617 {
619 }
620 else if ( str == "cubicSpline"_L1 )
621 {
623 }
624 else if ( str == "lanczos"_L1 )
625 {
627 }
628 else if ( str == "average"_L1 )
629 {
631 }
632 else if ( str == "mode"_L1 )
633 {
635 }
636 else if ( str == "gauss"_L1 )
637 {
639 }
641}
642
643void QgsRasterDataProvider::readXml( const QDomElement &filterElem )
644{
646
647 if ( filterElem.isNull() )
648 {
649 return;
650 }
651
652 const QDomElement resamplingElement = filterElem.firstChildElement( u"resampling"_s );
653 if ( !resamplingElement.isNull() )
654 {
655 setMaxOversampling( resamplingElement.attribute( u"maxOversampling"_s, u"2.0"_s ).toDouble() );
656 setZoomedInResamplingMethod( resamplingMethodFromString( resamplingElement.attribute( u"zoomedInResamplingMethod"_s ) ) );
657 setZoomedOutResamplingMethod( resamplingMethodFromString( resamplingElement.attribute( u"zoomedOutResamplingMethod"_s ) ) );
658 enableProviderResampling( resamplingElement.attribute( u"enabled"_s ) == "true"_L1 );
659 }
660}
661
662static QString resamplingMethodToString( Qgis::RasterResamplingMethod method )
663{
664 switch ( method )
665 {
667 return u"nearestNeighbour"_s;
669 return u"bilinear"_s;
671 return u"cubic"_s;
673 return u"cubicSpline"_s;
675 return u"lanczos"_s;
677 return u"average"_s;
679 return u"mode"_s;
681 return u"gauss"_s;
682 }
683 // should not happen
684 return u"nearestNeighbour"_s;
685}
686
687void QgsRasterDataProvider::writeXml( QDomDocument &doc, QDomElement &parentElem ) const
688{
690
691 QDomElement providerElement = doc.createElement( u"provider"_s );
692 parentElem.appendChild( providerElement );
693
694 QDomElement resamplingElement = doc.createElement( u"resampling"_s );
695 providerElement.appendChild( resamplingElement );
696
697 resamplingElement.setAttribute( u"enabled"_s, mProviderResamplingEnabled ? u"true"_s : u"false"_s );
698
699 resamplingElement.setAttribute( u"zoomedInResamplingMethod"_s, resamplingMethodToString( mZoomedInResamplingMethod ) );
700
701 resamplingElement.setAttribute( u"zoomedOutResamplingMethod"_s, resamplingMethodToString( mZoomedOutResamplingMethod ) );
702
703 resamplingElement.setAttribute( u"maxOversampling"_s, QString::number( mMaxOversampling ) );
704}
705
707{
709
710 try
711 {
712 return mAttributeTables.at( bandNumber ).get();
713 }
714 catch ( std::out_of_range const & )
715 {
716 return nullptr;
717 }
718}
719
721{
723
724 if ( attributeTable )
725 {
726 mAttributeTables[bandNumber] = std::unique_ptr<QgsRasterAttributeTable>( attributeTable );
727 }
728 else
729 {
730 removeAttributeTable( bandNumber );
731 }
732}
733
735{
737
738 if ( mAttributeTables.find( bandNumber ) != std::end( mAttributeTables ) )
739 {
740 mAttributeTables.erase( bandNumber );
741 }
742}
743
744bool QgsRasterDataProvider::writeFileBasedAttributeTable( int bandNumber, const QString &path, QString *errorMessage ) const
745{
747
748 QgsRasterAttributeTable *rat { attributeTable( bandNumber ) };
749 if ( !rat )
750 {
751 if ( errorMessage )
752 {
753 *errorMessage = QObject::tr( "Raster has no Raster Attribute Table for band %1" ).arg( bandNumber );
754 }
755 return false;
756 }
757
758 return rat->writeToFile( path, errorMessage );
759}
760
762{
764
765 if ( errorMessage )
766 {
767 *errorMessage = QObject::tr( "Raster data provider has no native Raster Attribute Table support." );
768 }
769 return false;
770}
771
773{
774 Q_UNUSED( bandNumber )
775 return QString();
776}
777
778bool QgsRasterDataProvider::readFileBasedAttributeTable( int bandNumber, const QString &path, QString *errorMessage )
779{
781
782 auto rat = std::make_unique<QgsRasterAttributeTable>();
783 if ( rat->readFromFile( path, errorMessage ) )
784 {
785 setAttributeTable( bandNumber, rat.release() );
786 return true;
787 }
788 else
789 {
790 return false;
791 }
792}
793
794bool QgsRasterDataProvider::writeNativeAttributeTable( QString *errorMessage ) //#spellok
795{
797
798 Q_UNUSED( errorMessage );
799 return false;
800}
801
803{
805
806 return colorName( colorInterpretation( bandNo ) );
807}
808
810{
811 // Modified copy from GDAL
812 switch ( colorInterpretation )
813 {
815 return tr( "Undefined" );
816
818 return tr( "Gray" );
819
821 return tr( "Palette" );
822
824 return tr( "Red" );
825
827 return tr( "Green" );
828
830 return tr( "Blue" );
831
833 return tr( "Alpha" );
834
836 return tr( "Hue" );
837
839 return tr( "Saturation" );
840
842 return tr( "Lightness" );
843
845 return tr( "Cyan" );
846
848 return tr( "Magenta" );
849
851 return tr( "Yellow" );
852
854 return tr( "Black" );
855
857 return tr( "YCbCr_Y" );
858
860 return tr( "YCbCr_Cb" );
861
863 return tr( "YCbCr_Cr" );
864
866 return tr( "Continuous Palette" );
867
869 return tr( "Panchromatic" );
870
872 return tr( "Coastal" );
873
875 return tr( "Red Edge" );
876
878 return tr( "Near-InfraRed (NIR)" );
879
881 return tr( "Short-Wavelength InfraRed (SWIR)" );
882
884 return tr( "Mid-Wavelength InfraRed (MWIR)" );
885
887 return tr( "Long-Wavelength InfraRed (LWIR)" );
888
890 return tr( "Thermal InfraRed (TIR)" );
891
893 return tr( "Other InfraRed" );
894
896 return tr( "Synthetic Aperture Radar (SAR) Ka band" );
897
899 return tr( "Synthetic Aperture Radar (SAR) K band" );
900
902 return tr( "Synthetic Aperture Radar (SAR) Ku band" );
903
905 return tr( "Synthetic Aperture Radar (SAR) X band" );
906
908 return tr( "Synthetic Aperture Radar (SAR) C band" );
909
911 return tr( "Synthetic Aperture Radar (SAR) S band" );
912
914 return tr( "Synthetic Aperture Radar (SAR) L band" );
915
917 return tr( "Synthetic Aperture Radar (SAR) P band" );
918 }
919 return QString();
920}
921
923{
924 QUrl url = QUrl::fromPercentEncoding( uri.toUtf8() );
925 const QUrlQuery query( url.query() );
926 VirtualRasterParameters components;
927
928 if ( !query.hasQueryItem( u"crs"_s ) )
929 {
930 QgsDebugError( "crs is missing" );
931 if ( ok )
932 *ok = false;
933 return components;
934 }
935 if ( !components.crs.createFromString( query.queryItemValue( u"crs"_s ) ) )
936 {
937 QgsDebugError( "failed to create crs" );
938 if ( ok )
939 *ok = false;
940 return components;
941 }
942
943
944 if ( !query.hasQueryItem( u"extent"_s ) )
945 {
946 QgsDebugError( "extent is missing" );
947 if ( ok )
948 *ok = false;
949 return components;
950 }
951 QStringList pointValuesList = query.queryItemValue( u"extent"_s ).split( ',' );
952 if ( pointValuesList.size() != 4 )
953 {
954 QgsDebugError( "the extent is not correct" );
955 if ( ok )
956 *ok = false;
957 return components;
958 }
959 components.extent = QgsRectangle( pointValuesList.at( 0 ).toDouble(), pointValuesList.at( 1 ).toDouble(), pointValuesList.at( 2 ).toDouble(), pointValuesList.at( 3 ).toDouble() );
960
961 if ( !query.hasQueryItem( u"width"_s ) )
962 {
963 QgsDebugError( "width is missing" );
964 if ( ok )
965 *ok = false;
966 return components;
967 }
968 bool flagW;
969 components.width = query.queryItemValue( u"width"_s ).toInt( &flagW );
970 if ( !flagW || components.width < 0 )
971 {
972 QgsDebugError( "invalid or negative width input" );
973 if ( ok )
974 *ok = false;
975 return components;
976 }
977
978 if ( !query.hasQueryItem( u"height"_s ) )
979 {
980 QgsDebugError( "height is missing" );
981 if ( ok )
982 *ok = false;
983 return components;
984 }
985 bool flagH;
986 components.height = query.queryItemValue( u"height"_s ).toInt( &flagH );
987 if ( !flagH || components.height < 0 )
988 {
989 QgsDebugError( "invalid or negative width input" );
990 if ( ok )
991 *ok = false;
992 return components;
993 }
994
995 if ( !query.hasQueryItem( u"formula"_s ) )
996 {
997 QgsDebugError( "formula is missing" );
998 if ( ok )
999 *ok = false;
1000 return components;
1001 }
1002 components.formula = query.queryItemValue( u"formula"_s );
1003
1004 const QList<std::pair<QString, QString> > &queryItems { query.queryItems() };
1005 for ( const auto &item : std::as_const( 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 )
1021 *ok = false;
1022 return components;
1023 }
1024
1025 components.rInputLayers.append( rLayer );
1026 }
1027
1028 if ( ok )
1029 *ok = true;
1030 return components;
1031}
1032
1034{
1035 QUrl uri;
1036 QUrlQuery query;
1037
1038 if ( parts.crs.isValid() )
1039 {
1040 query.addQueryItem( u"crs"_s, parts.crs.authid() );
1041 }
1042
1043 if ( !parts.extent.isNull() )
1044 {
1045 QString rect
1046 = QString( "%1,%2,%3,%4" )
1048
1049 query.addQueryItem( u"extent"_s, rect );
1050 }
1051
1052 query.addQueryItem( u"width"_s, QString::number( parts.width ) );
1053
1054 query.addQueryItem( u"height"_s, QString::number( parts.height ) );
1055
1056 query.addQueryItem( u"formula"_s, parts.formula );
1057
1058 if ( !parts.rInputLayers.isEmpty() )
1059 {
1060 for ( const auto &it : parts.rInputLayers )
1061 {
1062 query.addQueryItem( it.name + u":uri"_s, it.uri );
1063 query.addQueryItem( it.name + u":provider"_s, it.provider );
1064 }
1065 }
1066 uri.setQuery( query );
1067 return QString( QUrl::toPercentEncoding( uri.toEncoded() ) );
1068}
1069
1071{
1072 return false;
1073}
1074
1076{
1077 return false;
1078}
1079
1080
1081#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:5162
@ NoProviderCapabilities
Provider has no capabilities.
Definition qgis.h:5143
RasterResamplingMethod
Resampling method for raster provider-level resampling.
Definition qgis.h:1602
@ Lanczos
Lanczos windowed sinc interpolation (6x6 kernel).
Definition qgis.h:1607
@ Nearest
Nearest-neighbour resampling.
Definition qgis.h:1603
@ Mode
Mode (selects the value which appears most often of all the sampled points).
Definition qgis.h:1609
@ Bilinear
Bilinear (2x2 kernel) resampling.
Definition qgis.h:1604
@ Average
Average resampling.
Definition qgis.h:1608
@ CubicSpline
Cubic B-Spline Approximation (4x4 kernel).
Definition qgis.h:1606
@ Cubic
Cubic Convolution Approximation (4x4 kernel) resampling.
Definition qgis.h:1605
@ Gauss
Gauss blurring.
Definition qgis.h:1610
RasterInterfaceCapability
Raster interface capabilities.
Definition qgis.h:5109
@ NoCapabilities
No capabilities.
Definition qgis.h:5110
@ Size
Original data source size (and thus resolution) is known, it is not always available,...
Definition qgis.h:5111
@ IdentifyValue
Numerical values.
Definition qgis.h:5116
@ IdentifyFeature
WMS GML -> feature.
Definition qgis.h:5119
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:4968
@ NIRBand
Near-InfraRed (NIR) band [0.75 - 1.40 um].
Definition qgis.h:4994
@ GreenBand
Green band of RGBA image, or green spectral band [0.51 - 0.60 um].
Definition qgis.h:4973
@ SAR_K_Band
Synthetic Aperture Radar (SAR) K band [1.1 - 1.7 cm / 18 - 27 GHz].
Definition qgis.h:5001
@ SAR_L_Band
Synthetic Aperture Radar (SAR) L band [15 - 30 cm / 1 - 2 GHz].
Definition qgis.h:5006
@ SaturationBand
Saturation band of HLS image.
Definition qgis.h:4977
@ MagentaBand
Magenta band of CMYK image.
Definition qgis.h:4980
@ BlackBand
Black band of CMLY image.
Definition qgis.h:4982
@ AlphaBand
Alpha (0=transparent, 255=opaque).
Definition qgis.h:4975
@ SWIRBand
Short-Wavelength InfraRed (SWIR) band [1.40 - 3.00 um].
Definition qgis.h:4995
@ SAR_X_Band
Synthetic Aperture Radar (SAR) X band [2.4 - 3.8 cm / 8 - 12 GHz].
Definition qgis.h:5003
@ BlueBand
Blue band of RGBA image, or blue spectral band [0.45 - 0.53 um].
Definition qgis.h:4974
@ LWIRBand
Long-Wavelength InfraRed (LWIR) band [8.00 - 15 um].
Definition qgis.h:4997
@ RedEdgeBand
Red-edge band [0.69 - 0.79 um].
Definition qgis.h:4993
@ SAR_Ku_Band
Synthetic Aperture Radar (SAR) Ku band [1.7 - 2.4 cm / 12 - 18 GHz].
Definition qgis.h:5002
@ YellowBand
Yellow band of CMYK image, or yellow spectral band [0.58 - 0.62 um].
Definition qgis.h:4981
@ CyanBand
Cyan band of CMYK image.
Definition qgis.h:4979
@ SAR_C_Band
Synthetic Aperture Radar (SAR) C band [3.8 - 7.5 cm / 4 - 8 GHz].
Definition qgis.h:5004
@ LightnessBand
Lightness band of HLS image.
Definition qgis.h:4978
@ CoastalBand
Coastal band [0.40 - 0.45 um].
Definition qgis.h:4992
@ HueBand
Hue band of HLS image.
Definition qgis.h:4976
@ MWIRBand
Mid-Wavelength InfraRed (MWIR) band [3.00 - 8.00 um].
Definition qgis.h:4996
@ PaletteIndex
Paletted (see associated color table).
Definition qgis.h:4971
@ TIRBand
Thermal InfraRed (TIR) band (MWIR or LWIR) [3 - 15 um].
Definition qgis.h:4998
@ SAR_Ka_Band
Synthetic Aperture Radar (SAR) Ka band [0.8 - 1.1 cm / 27 - 40 GHz].
Definition qgis.h:5000
@ SAR_S_Band
Synthetic Aperture Radar (SAR) S band [7.5 - 15 cm / 2 - 4 GHz].
Definition qgis.h:5005
@ SAR_P_Band
Synthetic Aperture Radar (SAR) P band [30 - 100 cm / 0.3 - 1 GHz].
Definition qgis.h:5007
@ RedBand
Red band of RGBA image, or red spectral band [0.62 - 0.69 um].
Definition qgis.h:4972
@ PanBand
Panchromatic band [0.40 - 1.00 um].
Definition qgis.h:4991
@ ContinuousPalette
Continuous palette, QGIS addition, GRASS.
Definition qgis.h:4986
@ OtherIRBand
Other infrared band [0.75 - 1000 um].
Definition qgis.h:4999
RasterIdentifyFormat
Raster identify formats.
Definition qgis.h:5088
@ Feature
WMS GML/JSON -> feature.
Definition qgis.h:5093
@ Value
Numerical pixel value.
Definition qgis.h:5090
@ Undefined
Undefined.
Definition qgis.h:5089
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
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition qgsfeedback.h:56
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:6995
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:7602
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
Definition qgis.h:7077
#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