QGIS API Documentation 3.41.0-Master (45a0abf3bec)
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
18#include "qgsproviderregistry.h"
20#include "moc_qgsrasterdataprovider.cpp"
22#include "qgslogger.h"
23#include "qgspoint.h"
24#include "qgsthreadingutils.h"
25
26#include <QTime>
27#include <QMap>
28#include <QByteArray>
29#include <QVariant>
30
31#include <QUrl>
32#include <QUrlQuery>
33#include <QSet>
34
35#define ERR(message) QgsError(message, "Raster provider")
36
38{
40
41 if ( mUseSrcNoDataValue.size() < bandNo )
42 {
43 for ( int i = mUseSrcNoDataValue.size(); i < bandNo; i++ )
44 {
45 mUseSrcNoDataValue.append( false );
46 }
47 }
48 mUseSrcNoDataValue[bandNo - 1] = use;
49}
50
51QgsRasterBlock *QgsRasterDataProvider::block( int bandNo, QgsRectangle const &boundingBox, int width, int height, QgsRasterBlockFeedback *feedback )
52{
54
55 QgsDebugMsgLevel( QStringLiteral( "bandNo = %1 width = %2 height = %3" ).arg( bandNo ).arg( width ).arg( height ), 4 );
56 QgsDebugMsgLevel( QStringLiteral( "boundingBox = %1" ).arg( boundingBox.toString() ), 4 );
57
58 std::unique_ptr< QgsRasterBlock > block = std::make_unique< QgsRasterBlock >( dataType( bandNo ), width, height );
59 if ( sourceHasNoDataValue( bandNo ) && useSourceNoDataValue( bandNo ) )
60 {
62 }
63
64 if ( block->isEmpty() )
65 {
66 QgsDebugError( QStringLiteral( "Couldn't create raster block" ) );
67 block->setError( { tr( "Couldn't create raster block." ), QStringLiteral( "Raster" ) } );
68 block->setValid( false );
69 return block.release();
70 }
71
72 // Read necessary extent only
73 QgsRectangle tmpExtent = boundingBox;
74
75 if ( tmpExtent.isEmpty() )
76 {
77 QgsDebugError( QStringLiteral( "Extent outside provider extent" ) );
78 block->setError( { tr( "Extent outside provider extent." ), QStringLiteral( "Raster" ) } );
79 block->setValid( false );
81 return block.release();
82 }
83
84 const double xRes = boundingBox.width() / width;
85 const double yRes = boundingBox.height() / height;
86 double tmpXRes, tmpYRes;
87 double providerXRes = 0;
88 double providerYRes = 0;
90 {
91 providerXRes = extent().width() / xSize();
92 providerYRes = extent().height() / ySize();
93 tmpXRes = std::max( providerXRes, xRes );
94 tmpYRes = std::max( providerYRes, yRes );
95 if ( qgsDoubleNear( tmpXRes, xRes ) ) tmpXRes = xRes;
96 if ( qgsDoubleNear( tmpYRes, yRes ) ) tmpYRes = yRes;
97 }
98 else
99 {
100 tmpXRes = xRes;
101 tmpYRes = yRes;
102 }
103
104 if ( tmpExtent != boundingBox ||
105 tmpXRes > xRes || tmpYRes > yRes )
106 {
107 // Read smaller extent or lower resolution
108
109 if ( !extent().contains( boundingBox ) )
110 {
111 const QRect subRect = QgsRasterBlock::subRect( boundingBox, width, height, extent() );
112 block->setIsNoDataExcept( subRect );
113 }
114
115 // Calculate row/col limits (before tmpExtent is aligned)
116 const int fromRow = std::round( ( boundingBox.yMaximum() - tmpExtent.yMaximum() ) / yRes );
117 const int toRow = std::round( ( boundingBox.yMaximum() - tmpExtent.yMinimum() ) / yRes ) - 1;
118 const int fromCol = std::round( ( tmpExtent.xMinimum() - boundingBox.xMinimum() ) / xRes );
119 const int toCol = std::round( ( tmpExtent.xMaximum() - boundingBox.xMinimum() ) / xRes ) - 1;
120
121 QgsDebugMsgLevel( QStringLiteral( "fromRow = %1 toRow = %2 fromCol = %3 toCol = %4" ).arg( fromRow ).arg( toRow ).arg( fromCol ).arg( toCol ), 4 );
122
123 if ( fromRow < 0 || fromRow >= height || toRow < 0 || toRow >= height ||
124 fromCol < 0 || fromCol >= width || toCol < 0 || toCol >= width )
125 {
126 // Should not happen
127 QgsDebugError( QStringLiteral( "Row or column limits out of range" ) );
128 block->setError( { tr( "Row or column limits out of range" ), QStringLiteral( "Raster" ) } );
129 block->setValid( false );
130 return block.release();
131 }
132
133 // If lower source resolution is used, the extent must be aligned to original
134 // resolution to avoid possible shift due to resampling
135 if ( tmpXRes > xRes )
136 {
137 int col = std::floor( ( tmpExtent.xMinimum() - extent().xMinimum() ) / providerXRes );
138 tmpExtent.setXMinimum( extent().xMinimum() + col * providerXRes );
139 col = std::ceil( ( tmpExtent.xMaximum() - extent().xMinimum() ) / providerXRes );
140 tmpExtent.setXMaximum( extent().xMinimum() + col * providerXRes );
141 }
142 if ( tmpYRes > yRes )
143 {
144 int row = std::floor( ( extent().yMaximum() - tmpExtent.yMaximum() ) / providerYRes );
145 tmpExtent.setYMaximum( extent().yMaximum() - row * providerYRes );
146 row = std::ceil( ( extent().yMaximum() - tmpExtent.yMinimum() ) / providerYRes );
147 tmpExtent.setYMinimum( extent().yMaximum() - row * providerYRes );
148 }
149 const int tmpWidth = std::round( tmpExtent.width() / tmpXRes );
150 const int tmpHeight = std::round( tmpExtent.height() / tmpYRes );
151 tmpXRes = tmpExtent.width() / tmpWidth;
152 tmpYRes = tmpExtent.height() / tmpHeight;
153
154 QgsDebugMsgLevel( QStringLiteral( "Reading smaller block tmpWidth = %1 height = %2" ).arg( tmpWidth ).arg( tmpHeight ), 4 );
155 QgsDebugMsgLevel( QStringLiteral( "tmpExtent = %1" ).arg( tmpExtent.toString() ), 4 );
156
157 std::unique_ptr< QgsRasterBlock > tmpBlock = std::make_unique< QgsRasterBlock >( dataType( bandNo ), tmpWidth, tmpHeight );
158 if ( sourceHasNoDataValue( bandNo ) && useSourceNoDataValue( bandNo ) )
159 {
160 tmpBlock->setNoDataValue( sourceNoDataValue( bandNo ) );
161 }
162
163 if ( !readBlock( bandNo, tmpExtent, tmpWidth, tmpHeight, tmpBlock->bits(), feedback ) )
164 {
165 QgsDebugError( QStringLiteral( "Error occurred while reading block" ) );
166 block->setError( { tr( "Error occurred while reading block." ), QStringLiteral( "Raster" ) } );
167 block->setValid( false );
169 return block.release();
170 }
171
172 const int pixelSize = dataTypeSize( bandNo );
173
174 const double xMin = boundingBox.xMinimum();
175 const double yMax = boundingBox.yMaximum();
176 const double tmpXMin = tmpExtent.xMinimum();
177 const double tmpYMax = tmpExtent.yMaximum();
178
179 for ( int row = fromRow; row <= toRow; row++ )
180 {
181 const double y = yMax - ( row + 0.5 ) * yRes;
182 const int tmpRow = std::floor( ( tmpYMax - y ) / tmpYRes );
183
184 for ( int col = fromCol; col <= toCol; col++ )
185 {
186 const double x = xMin + ( col + 0.5 ) * xRes;
187 const int tmpCol = std::floor( ( x - tmpXMin ) / tmpXRes );
188
189 if ( tmpRow < 0 || tmpRow >= tmpHeight || tmpCol < 0 || tmpCol >= tmpWidth )
190 {
191 QgsDebugError( QStringLiteral( "Source row or column limits out of range" ) );
192 block->setIsNoData(); // so that the problem becomes obvious and fixed
193 block->setError( { tr( "Source row or column limits out of range." ), QStringLiteral( "Raster" ) } );
194 block->setValid( false );
195 return block.release();
196 }
197
198 const qgssize tmpIndex = static_cast< qgssize >( tmpRow ) * static_cast< qgssize >( tmpWidth ) + tmpCol;
199 const qgssize index = row * static_cast< qgssize >( width ) + col;
200
201 const char *tmpBits = tmpBlock->constBits( tmpIndex );
202 char *bits = block->bits( index );
203 if ( !tmpBits )
204 {
205 QgsDebugError( QStringLiteral( "Cannot get input block data tmpRow = %1 tmpCol = %2 tmpIndex = %3." ).arg( tmpRow ).arg( tmpCol ).arg( tmpIndex ) );
206 continue;
207 }
208 if ( !bits )
209 {
210 QgsDebugError( QStringLiteral( "Cannot set output block data." ) );
211 continue;
212 }
213 memcpy( bits, tmpBits, pixelSize );
214 }
215 }
216 }
217 else
218 {
219 if ( !readBlock( bandNo, boundingBox, width, height, block->bits(), feedback ) )
220 {
221 QgsDebugError( QStringLiteral( "Error occurred while reading block" ) );
223 block->setError( { tr( "Error occurred while reading block." ), QStringLiteral( "Raster" ) } );
224 block->setValid( false );
225 return block.release();
226 }
227 }
228
229 // apply scale and offset
230 block->applyScaleOffset( bandScale( bandNo ), bandOffset( bandNo ) );
231 // apply user no data values
233 return block.release();
234}
235
237 : QgsDataProvider( QString(), QgsDataProvider::ProviderOptions(), Qgis::DataProviderReadFlags() )
238 , QgsRasterInterface( nullptr )
239 , mTemporalCapabilities( std::make_unique< QgsRasterDataProviderTemporalCapabilities >() )
240 , mElevationProperties( std::make_unique< QgsRasterDataProviderElevationProperties >() )
241{
242
243}
244
247 : QgsDataProvider( uri, options, flags )
248 , QgsRasterInterface( nullptr )
249 , mTemporalCapabilities( std::make_unique< QgsRasterDataProviderTemporalCapabilities >() )
250 , mElevationProperties( std::make_unique< QgsRasterDataProviderElevationProperties >() )
251{
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( QStringLiteral( "Entered" ), 4 );
277 QMap<int, QVariant> results;
278
280 {
281 QgsDebugError( QStringLiteral( "Format not supported" ) );
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 results.insert( bandNumber, value );
329 }
330 else
331 {
332 results.insert( bandNumber, QVariant() );
333 }
334 }
336}
337
338double QgsRasterDataProvider::sample( const QgsPointXY &point, int band,
339 bool *ok, const QgsRectangle &boundingBox, int width, int height, int dpi )
340{
342
343 if ( ok )
344 *ok = false;
345
346 const auto res = identify( point, Qgis::RasterIdentifyFormat::Value, boundingBox, width, height, dpi );
347 const QVariant value = res.results().value( band );
348
349 if ( !value.isValid() )
350 return std::numeric_limits<double>::quiet_NaN();
351
352 if ( ok )
353 *ok = true;
354
355 return value.toDouble( ok );
356}
357
359{
361
362 return QStringLiteral( "text/plain" );
363}
364
365bool QgsRasterDataProvider::writeBlock( QgsRasterBlock *block, int band, int xOffset, int yOffset )
366{
368
369 if ( !block )
370 return false;
371 if ( !isEditable() )
372 {
373 QgsDebugError( QStringLiteral( "writeBlock() called on read-only provider." ) );
374 return false;
375 }
376 return write( block->bits(), band, block->width(), block->height(), xOffset, yOffset );
377}
378
379// typedef QList<QPair<QString, QString> > *pyramidResamplingMethods_t();
380QList<QPair<QString, QString> > QgsRasterDataProvider::pyramidResamplingMethods( const QString &providerKey )
381{
382 QList<QPair<QString, QString> > methods = QgsProviderRegistry::instance()->pyramidResamplingMethods( providerKey );
383 if ( methods.isEmpty() )
384 {
385 QgsDebugMsgLevel( QStringLiteral( "provider pyramidResamplingMethods returned no methods" ), 2 );
386 }
387 return methods;
388}
389
391{
393
394 const QList<QgsRasterPyramid> pyramidList = buildPyramidList();
395 return std::any_of( pyramidList.constBegin(), pyramidList.constEnd(), []( QgsRasterPyramid pyramid ) { return pyramid.getExists(); } );
396}
397
399{
401
402 if ( bandNo >= mUserNoDataValue.size() )
403 {
404 for ( int i = mUserNoDataValue.size(); i < bandNo; i++ )
405 {
407 }
408 }
409 QgsDebugMsgLevel( QStringLiteral( "set %1 band %1 no data ranges" ).arg( noData.size() ), 4 );
410
411 if ( mUserNoDataValue[bandNo - 1] != noData )
412 {
413 // Clear statistics
414 mStatistics.erase( std::remove_if( mStatistics.begin(), mStatistics.end(), [bandNo]( const QgsRasterBandStats & stats )
415 {
416 return stats.bandNumber == bandNo;
417 } ), mStatistics.end() );
418 mHistograms.erase( std::remove_if( mHistograms.begin(), mHistograms.end(), [bandNo]( const QgsRasterHistogram & histogram )
419 {
420 return histogram.bandNumber == bandNo;
421 } ), mHistograms.end() );
422 mUserNoDataValue[bandNo - 1] = noData;
423 }
424}
425
432
439
446
453
455 const QString &uri,
456 const QString &format, int nBands,
457 Qgis::DataType type,
458 int width, int height, double *geoTransform,
460 const QStringList &createOptions )
461{
463 providerKey,
464 uri, format,
465 nBands, type, width,
466 height, geoTransform, crs, createOptions );
467 if ( !ret )
468 {
469 QgsDebugError( "Cannot resolve 'createRasterDataProviderFunction' function in " + providerKey + " provider" );
470 }
471
472 // TODO: it would be good to return invalid QgsRasterDataProvider
473 // with QgsError set, but QgsRasterDataProvider has pure virtual methods
474
475 return ret;
476}
477
479{
480 switch ( format )
481 {
483 return QStringLiteral( "Value" );
485 return QStringLiteral( "Text" );
487 return QStringLiteral( "Html" );
489 return QStringLiteral( "Feature" );
491 break;
492 }
493 return QStringLiteral( "Undefined" );
494}
495
497{
498 switch ( format )
499 {
501 return tr( "Value" );
503 return tr( "Text" );
505 return tr( "HTML" );
507 return tr( "Feature" );
509 break;
510 }
511 return QStringLiteral( "Undefined" );
512}
513
515{
516 if ( formatName == QLatin1String( "Value" ) )
518 if ( formatName == QLatin1String( "Text" ) )
520 if ( formatName == QLatin1String( "Html" ) )
522 if ( formatName == QLatin1String( "Feature" ) )
525}
526
544
546{
548
549 return QList< double >();
550}
551
553{
555
556 return false;
557}
558
560{
562
563 Q_UNUSED( point )
564 Q_UNUSED( type )
565 return QgsPoint();
566}
567
568bool QgsRasterDataProvider::userNoDataValuesContains( int bandNo, double value ) const
569{
571
572 const QgsRasterRangeList rangeList = mUserNoDataValue.value( bandNo - 1 );
573 return QgsRasterRange::contains( value, rangeList );
574}
575
577{
579
580 mDpi = other.mDpi;
585 mExtent = other.mExtent;
590
591 if ( mTemporalCapabilities && other.mTemporalCapabilities )
592 {
593 *mTemporalCapabilities = *other.mTemporalCapabilities;
594 }
595 if ( mElevationProperties && other.mElevationProperties )
596 {
597 *mElevationProperties = *other.mElevationProperties;
598 }
599}
600
601static QgsRasterDataProvider::ResamplingMethod resamplingMethodFromString( const QString &str )
602{
603 if ( str == QLatin1String( "bilinear" ) )
604 {
606 }
607 else if ( str == QLatin1String( "cubic" ) )
608 {
610 }
611 else if ( str == QLatin1String( "cubicSpline" ) )
612 {
614 }
615 else if ( str == QLatin1String( "lanczos" ) )
616 {
618 }
619 else if ( str == QLatin1String( "average" ) )
620 {
622 }
623 else if ( str == QLatin1String( "mode" ) )
624 {
626 }
627 else if ( str == QLatin1String( "gauss" ) )
628 {
630 }
632}
633
634void QgsRasterDataProvider::readXml( const QDomElement &filterElem )
635{
637
638 if ( filterElem.isNull() )
639 {
640 return;
641 }
642
643 const QDomElement resamplingElement = filterElem.firstChildElement( QStringLiteral( "resampling" ) );
644 if ( !resamplingElement.isNull() )
645 {
646 setMaxOversampling( resamplingElement.attribute( QStringLiteral( "maxOversampling" ), QStringLiteral( "2.0" ) ).toDouble() );
647 setZoomedInResamplingMethod( resamplingMethodFromString( resamplingElement.attribute( QStringLiteral( "zoomedInResamplingMethod" ) ) ) );
648 setZoomedOutResamplingMethod( resamplingMethodFromString( resamplingElement.attribute( QStringLiteral( "zoomedOutResamplingMethod" ) ) ) );
649 enableProviderResampling( resamplingElement.attribute( QStringLiteral( "enabled" ) ) == QLatin1String( "true" ) );
650 }
651}
652
653static QString resamplingMethodToString( QgsRasterDataProvider::ResamplingMethod method )
654{
655 switch ( method )
656 {
658 return QStringLiteral( "nearestNeighbour" );
660 return QStringLiteral( "bilinear" );
662 return QStringLiteral( "cubic" );
664 return QStringLiteral( "cubicSpline" );
666 return QStringLiteral( "lanczos" );
668 return QStringLiteral( "average" );
670 return QStringLiteral( "mode" );
672 return QStringLiteral( "gauss" );
673 }
674 // should not happen
675 return QStringLiteral( "nearestNeighbour" );
676}
677
678void QgsRasterDataProvider::writeXml( QDomDocument &doc, QDomElement &parentElem ) const
679{
681
682 QDomElement providerElement = doc.createElement( QStringLiteral( "provider" ) );
683 parentElem.appendChild( providerElement );
684
685 QDomElement resamplingElement = doc.createElement( QStringLiteral( "resampling" ) );
686 providerElement.appendChild( resamplingElement );
687
688 resamplingElement.setAttribute( QStringLiteral( "enabled" ),
689 mProviderResamplingEnabled ? QStringLiteral( "true" ) : QStringLiteral( "false" ) );
690
691 resamplingElement.setAttribute( QStringLiteral( "zoomedInResamplingMethod" ),
692 resamplingMethodToString( mZoomedInResamplingMethod ) );
693
694 resamplingElement.setAttribute( QStringLiteral( "zoomedOutResamplingMethod" ),
695 resamplingMethodToString( mZoomedOutResamplingMethod ) );
696
697 resamplingElement.setAttribute( QStringLiteral( "maxOversampling" ),
698 QString::number( mMaxOversampling ) );
699}
700
702{
704
705 try
706 {
707 return mAttributeTables.at( bandNumber ).get();
708 }
709 catch ( std::out_of_range const & )
710 {
711 return nullptr;
712 }
713}
714
716{
718
719 if ( attributeTable )
720 {
721 mAttributeTables[ bandNumber ] = std::unique_ptr<QgsRasterAttributeTable>( attributeTable );
722 }
723 else
724 {
725 removeAttributeTable( bandNumber );
726 }
727}
728
730{
732
733 if ( mAttributeTables.find( bandNumber ) != std::end( mAttributeTables ) )
734 {
735 mAttributeTables.erase( bandNumber );
736 }
737}
738
739bool QgsRasterDataProvider::writeFileBasedAttributeTable( int bandNumber, const QString &path, QString *errorMessage ) const
740{
742
743 QgsRasterAttributeTable *rat { attributeTable( bandNumber ) };
744 if ( ! rat )
745 {
746 if ( errorMessage )
747 {
748 *errorMessage = QObject::tr( "Raster has no Raster Attribute Table for band %1" ).arg( bandNumber );
749 }
750 return false;
751 }
752
753 return rat->writeToFile( path, errorMessage );
754}
755
757{
759
760 if ( errorMessage )
761 {
762 *errorMessage = QObject::tr( "Raster data provider has no native Raster Attribute Table support." );
763 }
764 return false;
765}
766
768{
769 Q_UNUSED( bandNumber )
770 return QString();
771}
772
773bool QgsRasterDataProvider::readFileBasedAttributeTable( int bandNumber, const QString &path, QString *errorMessage )
774{
776
777 std::unique_ptr<QgsRasterAttributeTable> rat = std::make_unique<QgsRasterAttributeTable>();
778 if ( rat->readFromFile( path, errorMessage ) )
779 {
780 setAttributeTable( bandNumber, rat.release() );
781 return true;
782 }
783 else
784 {
785 return false;
786 }
787}
788
789bool QgsRasterDataProvider::writeNativeAttributeTable( QString *errorMessage ) //#spellok
790{
792
793 Q_UNUSED( errorMessage );
794 return false;
795}
796
798{
800
801 return colorName( colorInterpretation( bandNo ) );
802}
803
805{
806 // Modified copy from GDAL
807 switch ( colorInterpretation )
808 {
810 return tr( "Undefined" );
811
813 return tr( "Gray" );
814
816 return tr( "Palette" );
817
819 return tr( "Red" );
820
822 return tr( "Green" );
823
825 return tr( "Blue" );
826
828 return tr( "Alpha" );
829
831 return tr( "Hue" );
832
834 return tr( "Saturation" );
835
837 return tr( "Lightness" );
838
840 return tr( "Cyan" );
841
843 return tr( "Magenta" );
844
846 return tr( "Yellow" );
847
849 return tr( "Black" );
850
852 return tr( "YCbCr_Y" );
853
855 return tr( "YCbCr_Cb" );
856
858 return tr( "YCbCr_Cr" );
859
861 return tr( "Continuous Palette" );
862
864 return tr( "Panchromatic" );
865
867 return tr( "Coastal" );
868
870 return tr( "Red Edge" );
871
873 return tr( "Near-InfraRed (NIR)" );
874
876 return tr( "Short-Wavelength InfraRed (SWIR)" );
877
879 return tr( "Mid-Wavelength InfraRed (MWIR)" );
880
882 return tr( "Long-Wavelength InfraRed (LWIR)" );
883
885 return tr( "Thermal InfraRed (TIR)" );
886
888 return tr( "Other InfraRed" );
889
891 return tr( "Synthetic Aperture Radar (SAR) Ka band" );
892
894 return tr( "Synthetic Aperture Radar (SAR) K band" );
895
897 return tr( "Synthetic Aperture Radar (SAR) Ku band" );
898
900 return tr( "Synthetic Aperture Radar (SAR) X band" );
901
903 return tr( "Synthetic Aperture Radar (SAR) C band" );
904
906 return tr( "Synthetic Aperture Radar (SAR) S band" );
907
909 return tr( "Synthetic Aperture Radar (SAR) L band" );
910
912 return tr( "Synthetic Aperture Radar (SAR) P band" );
913 }
914 return QString();
915}
916
918{
919 QUrl url = QUrl::fromPercentEncoding( uri.toUtf8() );
920 const QUrlQuery query( url.query() );
921 VirtualRasterParameters components;
922
923 if ( ! query.hasQueryItem( QStringLiteral( "crs" ) ) )
924 {
925 QgsDebugError( "crs is missing" );
926 if ( ok ) *ok = false;
927 return components;
928 }
929 if ( ! components.crs.createFromString( query.queryItemValue( QStringLiteral( "crs" ) ) ) )
930 {
931 QgsDebugError( "failed to create crs" );
932 if ( ok ) *ok = false;
933 return components;
934 }
935
936
937 if ( ! query.hasQueryItem( QStringLiteral( "extent" ) ) )
938 {
939 QgsDebugError( "extent is missing" );
940 if ( ok ) *ok = false;
941 return components;
942 }
943 QStringList pointValuesList = query.queryItemValue( QStringLiteral( "extent" ) ).split( ',' );
944 if ( pointValuesList.size() != 4 )
945 {
946 QgsDebugError( "the extent is not correct" );
947 if ( ok ) *ok = false;
948 return components;
949 }
950 components.extent = QgsRectangle( pointValuesList.at( 0 ).toDouble(), pointValuesList.at( 1 ).toDouble(),
951 pointValuesList.at( 2 ).toDouble(), pointValuesList.at( 3 ).toDouble() );
952
953 if ( ! query.hasQueryItem( QStringLiteral( "width" ) ) )
954 {
955 QgsDebugError( "width is missing" );
956 if ( ok ) *ok = false;
957 return components;
958 }
959 bool flagW;
960 components.width = query.queryItemValue( QStringLiteral( "width" ) ).toInt( & flagW );
961 if ( !flagW || components.width < 0 )
962 {
963 QgsDebugError( "invalid or negative width input" );
964 if ( ok ) *ok = false;
965 return components;
966 }
967
968 if ( ! query.hasQueryItem( QStringLiteral( "height" ) ) )
969 {
970 QgsDebugError( "height is missing" );
971 if ( ok ) *ok = false;
972 return components;
973 }
974 bool flagH;
975 components.height = query.queryItemValue( QStringLiteral( "height" ) ).toInt( & flagH );
976 if ( !flagH || components.height < 0 )
977 {
978 QgsDebugError( "invalid or negative width input" );
979 if ( ok ) *ok = false;
980 return components;
981 }
982
983 if ( ! query.hasQueryItem( QStringLiteral( "formula" ) ) )
984 {
985 QgsDebugError( "formula is missing" );
986 if ( ok ) *ok = false;
987 return components;
988 }
989 components.formula = query.queryItemValue( QStringLiteral( "formula" ) );
990
991 for ( const auto &item : query.queryItems() )
992 {
993 if ( !( item.first.mid( item.first.indexOf( ':' ), -1 ) == QLatin1String( ":uri" ) ) )
994 {
995 continue;
996 }
997
999 rLayer.name = item.first.mid( 0, item.first.indexOf( ':' ) );
1000 rLayer.uri = query.queryItemValue( item.first );
1001 rLayer.provider = query.queryItemValue( item.first.mid( 0, item.first.indexOf( ':' ) ) + QStringLiteral( ":provider" ) );
1002
1003 if ( rLayer.uri.isNull() || rLayer.provider.isNull() )
1004 {
1005 QgsDebugError( "One or more raster information are missing" );
1006 if ( ok ) *ok = false;
1007 return components;
1008 }
1009
1010 components.rInputLayers.append( rLayer ) ;
1011
1012 }
1013
1014 if ( ok ) *ok = true;
1015 return components;
1016}
1017
1019{
1020 QUrl uri;
1021 QUrlQuery query;
1022
1023 if ( parts.crs.isValid() )
1024 {
1025 query.addQueryItem( QStringLiteral( "crs" ), parts.crs.authid() );
1026 }
1027
1028 if ( ! parts.extent.isNull() )
1029 {
1030 QString rect = QString( "%1,%2,%3,%4" ).arg( qgsDoubleToString( parts.extent.xMinimum() ), qgsDoubleToString( parts.extent.yMinimum() ),
1032
1033 query.addQueryItem( QStringLiteral( "extent" ), rect );
1034 }
1035
1036 query.addQueryItem( QStringLiteral( "width" ), QString::number( parts.width ) );
1037
1038 query.addQueryItem( QStringLiteral( "height" ), QString::number( parts.height ) );
1039
1040 query.addQueryItem( QStringLiteral( "formula" ), parts.formula );
1041
1042 if ( ! parts.rInputLayers.isEmpty() )
1043 {
1044 for ( const auto &it : parts.rInputLayers )
1045 {
1046 query.addQueryItem( it.name + QStringLiteral( ":uri" ), it.uri );
1047 query.addQueryItem( it.name + QStringLiteral( ":provider" ), it.provider );
1048 }
1049 }
1050 uri.setQuery( query );
1051 return QString( QUrl::toPercentEncoding( uri.toEncoded() ) );
1052}
The Qgis class provides global constants for use throughout the application.
Definition qgis.h:54
QFlags< RasterProviderCapability > RasterProviderCapabilities
Raster data provider capabilities.
Definition qgis.h:4570
@ NoProviderCapabilities
Provider has no capabilities.
RasterInterfaceCapability
Raster interface capabilities.
Definition qgis.h:4517
@ NoCapabilities
No capabilities.
@ Size
Original data source size (and thus resolution) is known, it is not always available,...
@ IdentifyValue
Numerical values.
@ IdentifyFeature
WMS GML -> feature.
QFlags< DataProviderReadFlag > DataProviderReadFlags
Flags which control data provider construction.
Definition qgis.h:450
DataType
Raster data types.
Definition qgis.h:351
RasterColorInterpretation
Raster color interpretation.
Definition qgis.h:4376
@ NIRBand
Near-InfraRed (NIR) band [0.75 - 1.40 um].
@ GreenBand
Green band of RGBA image, or green spectral band [0.51 - 0.60 um].
@ SAR_K_Band
Synthetic Aperture Radar (SAR) K band [1.1 - 1.7 cm / 18 - 27 GHz].
@ SAR_L_Band
Synthetic Aperture Radar (SAR) L band [15 - 30 cm / 1 - 2 GHz].
@ SaturationBand
Saturation band of HLS image.
@ MagentaBand
Magenta band of CMYK image.
@ BlackBand
Black band of CMLY image.
@ AlphaBand
Alpha (0=transparent, 255=opaque)
@ SWIRBand
Short-Wavelength InfraRed (SWIR) band [1.40 - 3.00 um].
@ SAR_X_Band
Synthetic Aperture Radar (SAR) X band [2.4 - 3.8 cm / 8 - 12 GHz].
@ BlueBand
Blue band of RGBA image, or blue spectral band [0.45 - 0.53 um].
@ LWIRBand
Long-Wavelength InfraRed (LWIR) band [8.00 - 15 um].
@ RedEdgeBand
Red-edge band [0.69 - 0.79 um].
@ SAR_Ku_Band
Synthetic Aperture Radar (SAR) Ku band [1.7 - 2.4 cm / 12 - 18 GHz].
@ YellowBand
Yellow band of CMYK image, or yellow spectral band [0.58 - 0.62 um].
@ CyanBand
Cyan band of CMYK image.
@ SAR_C_Band
Synthetic Aperture Radar (SAR) C band [3.8 - 7.5 cm / 4 - 8 GHz].
@ LightnessBand
Lightness band of HLS image.
@ CoastalBand
Coastal band [0.40 - 0.45 um].
@ HueBand
Hue band of HLS image.
@ MWIRBand
Mid-Wavelength InfraRed (MWIR) band [3.00 - 8.00 um].
@ PaletteIndex
Paletted (see associated color table)
@ TIRBand
Thermal InfraRed (TIR) band (MWIR or LWIR) [3 - 15 um].
@ SAR_Ka_Band
Synthetic Aperture Radar (SAR) Ka band [0.8 - 1.1 cm / 27 - 40 GHz].
@ SAR_S_Band
Synthetic Aperture Radar (SAR) S band [7.5 - 15 cm / 2 - 4 GHz].
@ SAR_P_Band
Synthetic Aperture Radar (SAR) P band [30 - 100 cm / 0.3 - 1 GHz].
@ RedBand
Red band of RGBA image, or red spectral band [0.62 - 0.69 um].
@ PanBand
Panchromatic band [0.40 - 1.00 um].
@ ContinuousPalette
Continuous palette, QGIS addition, GRASS.
@ OtherIRBand
Other infrared band [0.75 - 1000 um].
RasterIdentifyFormat
Raster identify formats.
Definition qgis.h:4496
@ Feature
WMS GML/JSON -> feature.
@ Value
Numerical pixel value.
This class represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
bool createFromString(const QString &definition)
Set up this CRS from a string definition.
Abstract base class for spatial data provider implementations.
virtual QgsCoordinateReferenceSystem crs() const =0
Returns the coordinate system for the data source.
QgsDataSourceUri uri() const
Gets the data source specification.
A class to represent a 2D point.
Definition qgspointxy.h:60
double y
Definition qgspointxy.h:64
double x
Definition qgspointxy.h:63
Point geometry type, with support for z-dimension and m-values.
Definition qgspoint.h:49
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
QgsRasterDataProvider * createRasterDataProvider(const QString &providerKey, const QString &uri, const QString &format, int nBands, Qgis::DataType type, int width, int height, double *geoTransform, const QgsCoordinateReferenceSystem &crs, const QStringList &createOptions=QStringList())
Creates new instance of raster data provider.
QList< QPair< QString, QString > > pyramidResamplingMethods(const QString &providerKey)
Returns list of raster pyramid resampling methods.
The QgsRasterAttributeTable class 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.
bool isEmpty() const
Returns true if block is empty, i.e.
void setValid(bool valid)
Mark block as valid or invalid.
int height() const
Returns the height (number of rows) of the raster block.
char * bits(int row, int column)
Returns a pointer to block data.
bool setIsNoDataExcept(QRect exceptRect)
Set the whole block to no data except specified rectangle.
const char * constBits(qgssize index) const
Returns a const pointer to block data.
void applyNoDataValues(const QgsRasterRangeList &rangeList)
void setNoDataValue(double noDataValue)
Sets cell value that will be considered as "no data".
int width() const
Returns the width (number of columns) of the raster block.
void applyScaleOffset(double scale, double offset)
Apply band scale and offset to raster block values.
static QRect subRect(const QgsRectangle &extent, int width, int height, const QgsRectangle &subExtent)
For extent and width, height find rectangle covered by subextent.
void setError(const QgsError &error)
Sets the last error.
bool setIsNoData(int row, int column)
Set no data on pixel.
Handles elevation related properties for a raster data provider.
Implementation of data provider temporal properties for QgsRasterDataProviders.
Base class for raster data providers.
double mMaxOversampling
Maximum boundary for oversampling (to avoid too much data traffic). Default: 2.0.
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.
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.
bool writeBlock(QgsRasterBlock *block, int band, int xOffset=0, int yOffset=0)
Writes pixel data from a raster block into the provider data source.
virtual bool enableProviderResampling(bool enable)
Enable or disable provider-level resampling.
QgsRectangle extent() const override=0
Returns the extent of the layer.
virtual bool ignoreExtents() const
Returns true if the extents reported by the data provider are not reliable and it's possible that the...
virtual bool setMaxOversampling(double factor)
Sets maximum oversampling factor for zoomed-out operations.
Qgis::DataType dataType(int bandNo) const override=0
Returns data type for the band specified by number.
ResamplingMethod mZoomedOutResamplingMethod
Resampling method for zoomed out pixel extraction.
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.
ResamplingMethod mZoomedInResamplingMethod
Resampling method for zoomed in pixel extraction.
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.
static QgsRasterDataProvider * create(const QString &providerKey, const QString &uri, const QString &format, int nBands, Qgis::DataType type, int width, int height, double *geoTransform, const QgsCoordinateReferenceSystem &crs, const QStringList &createOptions=QStringList())
Creates a new dataset with mDataSourceURI.
virtual QgsRasterRangeList userNoDataValues(int bandNo) const
Returns a list of user no data value ranges.
virtual bool setZoomedInResamplingMethod(ResamplingMethod method)
Set resampling method to apply for zoomed-in operations.
static QList< QPair< QString, QString > > pyramidResamplingMethods(const QString &providerKey)
Returns a list of pyramid resampling method name and label pairs for given provider.
void writeXml(QDomDocument &doc, QDomElement &parentElem) const override
Write base class members to xml.
virtual QList< double > nativeResolutions() const
Returns a list of native resolutions if available, i.e.
virtual QgsPoint transformCoordinates(const QgsPoint &point, TransformType type)
Transforms coordinates between source image coordinate space [0..width]x[0..height] and layer coordin...
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.
ResamplingMethod
Resampling method for provider-level resampling.
@ Lanczos
Lanczos windowed sinc interpolation (6x6 kernel)
@ Nearest
Nearest-neighbour resampling.
@ Mode
Mode (selects the value which appears most often of all the sampled points)
@ Bilinear
Bilinear (2x2 kernel) resampling.
@ CubicSpline
Cubic B-Spline Approximation (4x4 kernel)
@ Cubic
Cubic Convolution Approximation (4x4 kernel) resampling.
virtual 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 bool setZoomedOutResamplingMethod(ResamplingMethod method)
Set resampling method to apply for zoomed-out operations.
virtual QList< QgsRasterPyramid > buildPyramidList(const QList< int > &overviewList=QList< int >())
Returns the raster layers pyramid list.
The QgsRasterHistogram is a container for histogram of a single raster band.
Raster identify results container.
Base class for processing filters like renderers, reprojector, resampler etc.
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.
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.
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() const
Returns the x minimum value (left side of rectangle).
void setYMinimum(double y)
Set the minimum y value.
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
void setXMinimum(double x)
Set the minimum x value.
double width() const
Returns the width of the rectangle.
double xMaximum() const
Returns the x maximum value (right side of rectangle).
bool isNull() const
Test if the rectangle is null (holding no spatial information).
double yMaximum() const
Returns the y maximum value (top side of rectangle).
void setYMaximum(double y)
Set the maximum y value.
void setXMaximum(double x)
Set the maximum x value.
bool isEmpty() const
Returns true if the rectangle has no area.
double height() const
Returns the height of the rectangle.
#define str(x)
Definition qgis.cpp:39
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition qgis.h:5875
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:6506
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition qgis.h:5958
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:39
#define QgsDebugError(str)
Definition qgslogger.h:38
#define ERR(message)
QList< QgsRasterRange > QgsRasterRangeList
#define QGIS_PROTECT_QOBJECT_THREAD_ACCESS
const QgsCoordinateReferenceSystem & crs
Setting options for creating vector data providers.
Struct that stores information of the raster used in QgsVirtualRasterProvider for the calculations,...
Struct that stores the information about the parameters that should be given to the QgsVirtualRasterP...
QList< QgsRasterDataProvider::VirtualRasterInputLayers > rInputLayers