QGIS API Documentation 3.99.0-Master (26c88405ac0)
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 <QTime>
30#include <QUrl>
31#include <QUrlQuery>
32#include <QVariant>
33
34#include "moc_qgsrasterdataprovider.cpp"
35
36#define ERR(message) QgsError(message, "Raster provider")
37
39{
41
42 if ( mUseSrcNoDataValue.size() < bandNo )
43 {
44 for ( int i = mUseSrcNoDataValue.size(); i < bandNo; i++ )
45 {
46 mUseSrcNoDataValue.append( false );
47 }
48 }
49 mUseSrcNoDataValue[bandNo - 1] = use;
50}
51
52QgsRasterBlock *QgsRasterDataProvider::block( int bandNo, QgsRectangle const &boundingBox, int width, int height, QgsRasterBlockFeedback *feedback )
53{
55
56 QgsDebugMsgLevel( QStringLiteral( "bandNo = %1 width = %2 height = %3" ).arg( bandNo ).arg( width ).arg( height ), 4 );
57 QgsDebugMsgLevel( QStringLiteral( "boundingBox = %1" ).arg( boundingBox.toString() ), 4 );
58
59 auto block = std::make_unique< QgsRasterBlock >( dataType( bandNo ), width, height );
60 if ( sourceHasNoDataValue( bandNo ) && useSourceNoDataValue( bandNo ) )
61 {
62 block->setNoDataValue( sourceNoDataValue( bandNo ) );
63 }
64
65 if ( block->isEmpty() )
66 {
67 QgsDebugError( QStringLiteral( "Couldn't create raster block" ) );
68 block->setError( { tr( "Couldn't create raster block." ), QStringLiteral( "Raster" ) } );
69 block->setValid( false );
70 return block.release();
71 }
72
73 // Read necessary extent only
74 QgsRectangle tmpExtent = boundingBox;
75
76 if ( tmpExtent.isEmpty() )
77 {
78 QgsDebugError( QStringLiteral( "Extent outside provider extent" ) );
79 block->setError( { tr( "Extent outside provider extent." ), QStringLiteral( "Raster" ) } );
80 block->setValid( false );
81 block->setIsNoData();
82 return block.release();
83 }
84
85 const double xRes = boundingBox.width() / width;
86 const double yRes = boundingBox.height() / height;
87 double tmpXRes, tmpYRes;
88 double providerXRes = 0;
89 double providerYRes = 0;
91 {
92 providerXRes = extent().width() / xSize();
93 providerYRes = extent().height() / ySize();
94 tmpXRes = std::max( providerXRes, xRes );
95 tmpYRes = std::max( providerYRes, yRes );
96 if ( qgsDoubleNear( tmpXRes, xRes ) ) tmpXRes = xRes;
97 if ( qgsDoubleNear( tmpYRes, yRes ) ) tmpYRes = yRes;
98 }
99 else
100 {
101 tmpXRes = xRes;
102 tmpYRes = yRes;
103 }
104
105 if ( tmpExtent != boundingBox ||
106 tmpXRes > xRes || tmpYRes > yRes )
107 {
108 // Read smaller extent or lower resolution
109
110 if ( !extent().contains( boundingBox ) )
111 {
112 const QRect subRect = QgsRasterBlock::subRect( boundingBox, width, height, extent() );
113 block->setIsNoDataExcept( subRect );
114 }
115
116 // Calculate row/col limits (before tmpExtent is aligned)
117 const int fromRow = std::round( ( boundingBox.yMaximum() - tmpExtent.yMaximum() ) / yRes );
118 const int toRow = std::round( ( boundingBox.yMaximum() - tmpExtent.yMinimum() ) / yRes ) - 1;
119 const int fromCol = std::round( ( tmpExtent.xMinimum() - boundingBox.xMinimum() ) / xRes );
120 const int toCol = std::round( ( tmpExtent.xMaximum() - boundingBox.xMinimum() ) / xRes ) - 1;
121
122 QgsDebugMsgLevel( QStringLiteral( "fromRow = %1 toRow = %2 fromCol = %3 toCol = %4" ).arg( fromRow ).arg( toRow ).arg( fromCol ).arg( toCol ), 4 );
123
124 if ( fromRow < 0 || fromRow >= height || toRow < 0 || toRow >= height ||
125 fromCol < 0 || fromCol >= width || toCol < 0 || toCol >= width )
126 {
127 // Should not happen
128 QgsDebugError( QStringLiteral( "Row or column limits out of range" ) );
129 block->setError( { tr( "Row or column limits out of range" ), QStringLiteral( "Raster" ) } );
130 block->setValid( false );
131 return block.release();
132 }
133
134 // If lower source resolution is used, the extent must be aligned to original
135 // resolution to avoid possible shift due to resampling
136 if ( tmpXRes > xRes )
137 {
138 int col = std::floor( ( tmpExtent.xMinimum() - extent().xMinimum() ) / providerXRes );
139 tmpExtent.setXMinimum( extent().xMinimum() + col * providerXRes );
140 col = std::ceil( ( tmpExtent.xMaximum() - extent().xMinimum() ) / providerXRes );
141 tmpExtent.setXMaximum( extent().xMinimum() + col * providerXRes );
142 }
143 if ( tmpYRes > yRes )
144 {
145 int row = std::floor( ( extent().yMaximum() - tmpExtent.yMaximum() ) / providerYRes );
146 tmpExtent.setYMaximum( extent().yMaximum() - row * providerYRes );
147 row = std::ceil( ( extent().yMaximum() - tmpExtent.yMinimum() ) / providerYRes );
148 tmpExtent.setYMinimum( extent().yMaximum() - row * providerYRes );
149 }
150 const int tmpWidth = std::round( tmpExtent.width() / tmpXRes );
151 const int tmpHeight = std::round( tmpExtent.height() / tmpYRes );
152 tmpXRes = tmpExtent.width() / tmpWidth;
153 tmpYRes = tmpExtent.height() / tmpHeight;
154
155 QgsDebugMsgLevel( QStringLiteral( "Reading smaller block tmpWidth = %1 height = %2" ).arg( tmpWidth ).arg( tmpHeight ), 4 );
156 QgsDebugMsgLevel( QStringLiteral( "tmpExtent = %1" ).arg( tmpExtent.toString() ), 4 );
157
158 auto tmpBlock = std::make_unique< QgsRasterBlock >( dataType( bandNo ), tmpWidth, tmpHeight );
159 if ( sourceHasNoDataValue( bandNo ) && useSourceNoDataValue( bandNo ) )
160 {
161 tmpBlock->setNoDataValue( sourceNoDataValue( bandNo ) );
162 }
163
164 if ( !readBlock( bandNo, tmpExtent, tmpWidth, tmpHeight, tmpBlock->bits(), feedback ) )
165 {
166 QgsDebugError( QStringLiteral( "Error occurred while reading block" ) );
167 block->setError( { tr( "Error occurred while reading block." ), QStringLiteral( "Raster" ) } );
168 block->setValid( false );
169 block->setIsNoData();
170 return block.release();
171 }
172
173 const int pixelSize = dataTypeSize( bandNo );
174
175 const double xMin = boundingBox.xMinimum();
176 const double yMax = boundingBox.yMaximum();
177 const double tmpXMin = tmpExtent.xMinimum();
178 const double tmpYMax = tmpExtent.yMaximum();
179
180 for ( int row = fromRow; row <= toRow; row++ )
181 {
182 const double y = yMax - ( row + 0.5 ) * yRes;
183 const int tmpRow = std::floor( ( tmpYMax - y ) / tmpYRes );
184
185 for ( int col = fromCol; col <= toCol; col++ )
186 {
187 const double x = xMin + ( col + 0.5 ) * xRes;
188 const int tmpCol = std::floor( ( x - tmpXMin ) / tmpXRes );
189
190 if ( tmpRow < 0 || tmpRow >= tmpHeight || tmpCol < 0 || tmpCol >= tmpWidth )
191 {
192 QgsDebugError( QStringLiteral( "Source row or column limits out of range" ) );
193 block->setIsNoData(); // so that the problem becomes obvious and fixed
194 block->setError( { tr( "Source row or column limits out of range." ), QStringLiteral( "Raster" ) } );
195 block->setValid( false );
196 return block.release();
197 }
198
199 const qgssize tmpIndex = static_cast< qgssize >( tmpRow ) * static_cast< qgssize >( tmpWidth ) + tmpCol;
200 const qgssize index = row * static_cast< qgssize >( width ) + col;
201
202 const char *tmpBits = tmpBlock->constBits( tmpIndex );
203 char *bits = block->bits( index );
204 if ( !tmpBits )
205 {
206 QgsDebugError( QStringLiteral( "Cannot get input block data tmpRow = %1 tmpCol = %2 tmpIndex = %3." ).arg( tmpRow ).arg( tmpCol ).arg( tmpIndex ) );
207 continue;
208 }
209 if ( !bits )
210 {
211 QgsDebugError( QStringLiteral( "Cannot set output block data." ) );
212 continue;
213 }
214 memcpy( bits, tmpBits, pixelSize );
215 }
216 }
217 }
218 else
219 {
220 if ( !readBlock( bandNo, boundingBox, width, height, block->bits(), feedback ) )
221 {
222 QgsDebugError( QStringLiteral( "Error occurred while reading block" ) );
223 block->setIsNoData();
224 block->setError( { tr( "Error occurred while reading block." ), QStringLiteral( "Raster" ) } );
225 block->setValid( false );
226 return block.release();
227 }
228 }
229
230 // apply scale and offset
231 block->applyScaleOffset( bandScale( bandNo ), bandOffset( bandNo ) );
232 // apply user no data values
233 block->applyNoDataValues( userNoDataValues( bandNo ) );
234 return block.release();
235}
236
238 : QgsDataProvider( QString(), QgsDataProvider::ProviderOptions(), Qgis::DataProviderReadFlags() )
239 , QgsRasterInterface( nullptr )
240 , mTemporalCapabilities( std::make_unique< QgsRasterDataProviderTemporalCapabilities >() )
241 , mElevationProperties( std::make_unique< QgsRasterDataProviderElevationProperties >() )
242{
243
244}
245
248 : QgsDataProvider( uri, options, flags )
249 , QgsRasterInterface( nullptr )
250 , mTemporalCapabilities( std::make_unique< QgsRasterDataProviderTemporalCapabilities >() )
251 , mElevationProperties( std::make_unique< QgsRasterDataProviderElevationProperties >() )
252{
253}
254
261
269
270// TODO
271// (WMS) IdentifyFormatFeature is not consistent with QgsRaster::IdentifyFormatValue.
272// IdentifyFormatHtml: better error reporting
273QgsRasterIdentifyResult QgsRasterDataProvider::identify( const QgsPointXY &point, Qgis::RasterIdentifyFormat format, const QgsRectangle &boundingBox, int width, int height, int /*dpi*/ )
274{
276
277 QgsDebugMsgLevel( QStringLiteral( "Entered" ), 4 );
278 QMap<int, QVariant> results;
279
281 {
282 QgsDebugError( QStringLiteral( "Format not supported" ) );
283 return QgsRasterIdentifyResult( ERR( tr( "Format not supported" ) ) );
284 }
285
286 if ( !extent().contains( point ) )
287 {
288 // Outside the raster
289 for ( int bandNo = 1; bandNo <= bandCount(); bandNo++ )
290 {
291 results.insert( bandNo, QVariant() );
292 }
294 }
295
296 QgsRectangle finalExtent = boundingBox;
297 if ( finalExtent.isEmpty() )
298 finalExtent = extent();
299
300 if ( width == 0 )
301 {
303 }
304 if ( height == 0 )
305 {
306 height = ( capabilities() & Qgis::RasterInterfaceCapability::Size ) ? ySize() : 1000;
307 }
308
309 // Calculate the row / column where the point falls
310 const double xres = ( finalExtent.width() ) / width;
311 const double yres = ( finalExtent.height() ) / height;
312
313 const int col = static_cast< int >( std::floor( ( point.x() - finalExtent.xMinimum() ) / xres ) );
314 const int row = static_cast< int >( std::floor( ( finalExtent.yMaximum() - point.y() ) / yres ) );
315
316 const double xMin = finalExtent.xMinimum() + col * xres;
317 const double xMax = xMin + xres;
318 const double yMax = finalExtent.yMaximum() - row * yres;
319 const double yMin = yMax - yres;
320 const QgsRectangle pixelExtent( xMin, yMin, xMax, yMax );
321
322 for ( int bandNumber = 1; bandNumber <= bandCount(); bandNumber++ )
323 {
324 std::unique_ptr< QgsRasterBlock > bandBlock( block( bandNumber, pixelExtent, 1, 1 ) );
325
326 if ( bandBlock )
327 {
328 const double value = bandBlock->value( 0 );
329 if ( ( sourceHasNoDataValue( bandNumber ) && useSourceNoDataValue( bandNumber ) &&
330 ( std::isnan( value ) || qgsDoubleNear( value, sourceNoDataValue( bandNumber ) ) ) ) ||
331 ( QgsRasterRange::contains( value, userNoDataValues( bandNumber ) ) ) )
332 {
333 results.insert( bandNumber, QVariant() ); // null QVariant represents no data
334 }
335 else
336 {
337 results.insert( bandNumber, value );
338 }
339 }
340 else
341 {
342 results.insert( bandNumber, QVariant() );
343 }
344 }
346}
347
348double QgsRasterDataProvider::sample( const QgsPointXY &point, int band,
349 bool *ok, const QgsRectangle &boundingBox, int width, int height, int dpi )
350{
352
353 if ( ok )
354 *ok = false;
355
356 const auto res = identify( point, Qgis::RasterIdentifyFormat::Value, boundingBox, width, height, dpi );
357 const QVariant value = res.results().value( band );
358
359 if ( !value.isValid() )
360 return std::numeric_limits<double>::quiet_NaN();
361
362 if ( ok )
363 *ok = true;
364
365 return value.toDouble( ok );
366}
367
369{
371
372 return QStringLiteral( "text/plain" );
373}
374
375bool QgsRasterDataProvider::writeBlock( QgsRasterBlock *block, int band, int xOffset, int yOffset )
376{
378
379 if ( !block )
380 return false;
381 if ( !isEditable() )
382 {
383 setError( QgsError( QStringLiteral( "writeBlock() called on read-only provider." ), QStringLiteral( "writeBlock" ) ) );
384 QgsDebugError( QStringLiteral( "writeBlock() called on read-only provider." ) );
385 return false;
386 }
387 return write( block->bits(), band, block->width(), block->height(), xOffset, yOffset );
388}
389
390// typedef QList<QPair<QString, QString> > *pyramidResamplingMethods_t();
391QList<QPair<QString, QString> > QgsRasterDataProvider::pyramidResamplingMethods( const QString &providerKey )
392{
393 QList<QPair<QString, QString> > methods = QgsProviderRegistry::instance()->pyramidResamplingMethods( providerKey );
394 if ( methods.isEmpty() )
395 {
396 QgsDebugMsgLevel( QStringLiteral( "provider pyramidResamplingMethods returned no methods" ), 2 );
397 }
398 return methods;
399}
400
402{
404
405 const QList<QgsRasterPyramid> pyramidList = buildPyramidList();
406 return std::any_of( pyramidList.constBegin(), pyramidList.constEnd(), []( QgsRasterPyramid pyramid ) { return pyramid.getExists(); } );
407}
408
410{
412
413 if ( bandNo >= mUserNoDataValue.size() )
414 {
415 for ( int i = mUserNoDataValue.size(); i < bandNo; i++ )
416 {
418 }
419 }
420 QgsDebugMsgLevel( QStringLiteral( "set %1 band %1 no data ranges" ).arg( noData.size() ), 4 );
421
422 if ( mUserNoDataValue[bandNo - 1] != noData )
423 {
424 // Clear statistics
425 mStatistics.erase( std::remove_if( mStatistics.begin(), mStatistics.end(), [bandNo]( const QgsRasterBandStats & stats )
426 {
427 return stats.bandNumber == bandNo;
428 } ), mStatistics.end() );
429 mHistograms.erase( std::remove_if( mHistograms.begin(), mHistograms.end(), [bandNo]( const QgsRasterHistogram & histogram )
430 {
431 return histogram.bandNumber == bandNo;
432 } ), mHistograms.end() );
433 mUserNoDataValue[bandNo - 1] = noData;
434 }
435}
436
443
450
457
464
466 const QString &uri,
467 const QString &format, int nBands,
468 Qgis::DataType type,
469 int width, int height, double *geoTransform,
471 const QStringList &creationOptions )
472{
474 providerKey,
475 uri, format,
476 nBands, type, width,
477 height, geoTransform, crs, creationOptions );
478 if ( !ret )
479 {
480 QgsDebugError( "Cannot resolve 'createRasterDataProviderFunction' function in " + providerKey + " provider" );
481 }
482
483 // TODO: it would be good to return invalid QgsRasterDataProvider
484 // with QgsError set, but QgsRasterDataProvider has pure virtual methods
485
486 return ret;
487}
488
490{
491 switch ( format )
492 {
494 return QStringLiteral( "Value" );
496 return QStringLiteral( "Text" );
498 return QStringLiteral( "Html" );
500 return QStringLiteral( "Feature" );
502 break;
503 }
504 return QStringLiteral( "Undefined" );
505}
506
508{
509 switch ( format )
510 {
512 return tr( "Value" );
514 return tr( "Text" );
516 return tr( "HTML" );
518 return tr( "Feature" );
520 break;
521 }
522 return QStringLiteral( "Undefined" );
523}
524
526{
527 if ( formatName == QLatin1String( "Value" ) )
529 if ( formatName == QLatin1String( "Text" ) )
531 if ( formatName == QLatin1String( "Html" ) )
533 if ( formatName == QLatin1String( "Feature" ) )
536}
537
555
557{
559
560 return QList< double >();
561}
562
564{
566
567 return false;
568}
569
571{
573
574 Q_UNUSED( point )
575 Q_UNUSED( type )
576 return QgsPoint();
577}
578
579bool QgsRasterDataProvider::userNoDataValuesContains( int bandNo, double value ) const
580{
582
583 const QgsRasterRangeList rangeList = mUserNoDataValue.value( bandNo - 1 );
584 return QgsRasterRange::contains( value, rangeList );
585}
586
588{
590
591 mDpi = other.mDpi;
596 mExtent = other.mExtent;
601
602 if ( mTemporalCapabilities && other.mTemporalCapabilities )
603 {
604 *mTemporalCapabilities = *other.mTemporalCapabilities;
605 }
606 if ( mElevationProperties && other.mElevationProperties )
607 {
608 *mElevationProperties = *other.mElevationProperties;
609 }
610}
611
612static Qgis::RasterResamplingMethod resamplingMethodFromString( const QString &str )
613{
614 if ( str == QLatin1String( "bilinear" ) )
615 {
617 }
618 else if ( str == QLatin1String( "cubic" ) )
619 {
621 }
622 else if ( str == QLatin1String( "cubicSpline" ) )
623 {
625 }
626 else if ( str == QLatin1String( "lanczos" ) )
627 {
629 }
630 else if ( str == QLatin1String( "average" ) )
631 {
633 }
634 else if ( str == QLatin1String( "mode" ) )
635 {
637 }
638 else if ( str == QLatin1String( "gauss" ) )
639 {
641 }
643}
644
645void QgsRasterDataProvider::readXml( const QDomElement &filterElem )
646{
648
649 if ( filterElem.isNull() )
650 {
651 return;
652 }
653
654 const QDomElement resamplingElement = filterElem.firstChildElement( QStringLiteral( "resampling" ) );
655 if ( !resamplingElement.isNull() )
656 {
657 setMaxOversampling( resamplingElement.attribute( QStringLiteral( "maxOversampling" ), QStringLiteral( "2.0" ) ).toDouble() );
658 setZoomedInResamplingMethod( resamplingMethodFromString( resamplingElement.attribute( QStringLiteral( "zoomedInResamplingMethod" ) ) ) );
659 setZoomedOutResamplingMethod( resamplingMethodFromString( resamplingElement.attribute( QStringLiteral( "zoomedOutResamplingMethod" ) ) ) );
660 enableProviderResampling( resamplingElement.attribute( QStringLiteral( "enabled" ) ) == QLatin1String( "true" ) );
661 }
662}
663
664static QString resamplingMethodToString( Qgis::RasterResamplingMethod method )
665{
666 switch ( method )
667 {
669 return QStringLiteral( "nearestNeighbour" );
671 return QStringLiteral( "bilinear" );
673 return QStringLiteral( "cubic" );
675 return QStringLiteral( "cubicSpline" );
677 return QStringLiteral( "lanczos" );
679 return QStringLiteral( "average" );
681 return QStringLiteral( "mode" );
683 return QStringLiteral( "gauss" );
684 }
685 // should not happen
686 return QStringLiteral( "nearestNeighbour" );
687}
688
689void QgsRasterDataProvider::writeXml( QDomDocument &doc, QDomElement &parentElem ) const
690{
692
693 QDomElement providerElement = doc.createElement( QStringLiteral( "provider" ) );
694 parentElem.appendChild( providerElement );
695
696 QDomElement resamplingElement = doc.createElement( QStringLiteral( "resampling" ) );
697 providerElement.appendChild( resamplingElement );
698
699 resamplingElement.setAttribute( QStringLiteral( "enabled" ),
700 mProviderResamplingEnabled ? QStringLiteral( "true" ) : QStringLiteral( "false" ) );
701
702 resamplingElement.setAttribute( QStringLiteral( "zoomedInResamplingMethod" ),
703 resamplingMethodToString( mZoomedInResamplingMethod ) );
704
705 resamplingElement.setAttribute( QStringLiteral( "zoomedOutResamplingMethod" ),
706 resamplingMethodToString( mZoomedOutResamplingMethod ) );
707
708 resamplingElement.setAttribute( QStringLiteral( "maxOversampling" ),
709 QString::number( mMaxOversampling ) );
710}
711
713{
715
716 try
717 {
718 return mAttributeTables.at( bandNumber ).get();
719 }
720 catch ( std::out_of_range const & )
721 {
722 return nullptr;
723 }
724}
725
727{
729
730 if ( attributeTable )
731 {
732 mAttributeTables[ bandNumber ] = std::unique_ptr<QgsRasterAttributeTable>( attributeTable );
733 }
734 else
735 {
736 removeAttributeTable( bandNumber );
737 }
738}
739
741{
743
744 if ( mAttributeTables.find( bandNumber ) != std::end( mAttributeTables ) )
745 {
746 mAttributeTables.erase( bandNumber );
747 }
748}
749
750bool QgsRasterDataProvider::writeFileBasedAttributeTable( int bandNumber, const QString &path, QString *errorMessage ) const
751{
753
754 QgsRasterAttributeTable *rat { attributeTable( bandNumber ) };
755 if ( ! rat )
756 {
757 if ( errorMessage )
758 {
759 *errorMessage = QObject::tr( "Raster has no Raster Attribute Table for band %1" ).arg( bandNumber );
760 }
761 return false;
762 }
763
764 return rat->writeToFile( path, errorMessage );
765}
766
768{
770
771 if ( errorMessage )
772 {
773 *errorMessage = QObject::tr( "Raster data provider has no native Raster Attribute Table support." );
774 }
775 return false;
776}
777
779{
780 Q_UNUSED( bandNumber )
781 return QString();
782}
783
784bool QgsRasterDataProvider::readFileBasedAttributeTable( int bandNumber, const QString &path, QString *errorMessage )
785{
787
788 auto rat = std::make_unique<QgsRasterAttributeTable>();
789 if ( rat->readFromFile( path, errorMessage ) )
790 {
791 setAttributeTable( bandNumber, rat.release() );
792 return true;
793 }
794 else
795 {
796 return false;
797 }
798}
799
800bool QgsRasterDataProvider::writeNativeAttributeTable( QString *errorMessage ) //#spellok
801{
803
804 Q_UNUSED( errorMessage );
805 return false;
806}
807
809{
811
812 return colorName( colorInterpretation( bandNo ) );
813}
814
816{
817 // Modified copy from GDAL
818 switch ( colorInterpretation )
819 {
821 return tr( "Undefined" );
822
824 return tr( "Gray" );
825
827 return tr( "Palette" );
828
830 return tr( "Red" );
831
833 return tr( "Green" );
834
836 return tr( "Blue" );
837
839 return tr( "Alpha" );
840
842 return tr( "Hue" );
843
845 return tr( "Saturation" );
846
848 return tr( "Lightness" );
849
851 return tr( "Cyan" );
852
854 return tr( "Magenta" );
855
857 return tr( "Yellow" );
858
860 return tr( "Black" );
861
863 return tr( "YCbCr_Y" );
864
866 return tr( "YCbCr_Cb" );
867
869 return tr( "YCbCr_Cr" );
870
872 return tr( "Continuous Palette" );
873
875 return tr( "Panchromatic" );
876
878 return tr( "Coastal" );
879
881 return tr( "Red Edge" );
882
884 return tr( "Near-InfraRed (NIR)" );
885
887 return tr( "Short-Wavelength InfraRed (SWIR)" );
888
890 return tr( "Mid-Wavelength InfraRed (MWIR)" );
891
893 return tr( "Long-Wavelength InfraRed (LWIR)" );
894
896 return tr( "Thermal InfraRed (TIR)" );
897
899 return tr( "Other InfraRed" );
900
902 return tr( "Synthetic Aperture Radar (SAR) Ka band" );
903
905 return tr( "Synthetic Aperture Radar (SAR) K band" );
906
908 return tr( "Synthetic Aperture Radar (SAR) Ku band" );
909
911 return tr( "Synthetic Aperture Radar (SAR) X band" );
912
914 return tr( "Synthetic Aperture Radar (SAR) C band" );
915
917 return tr( "Synthetic Aperture Radar (SAR) S band" );
918
920 return tr( "Synthetic Aperture Radar (SAR) L band" );
921
923 return tr( "Synthetic Aperture Radar (SAR) P band" );
924 }
925 return QString();
926}
927
929{
930 QUrl url = QUrl::fromPercentEncoding( uri.toUtf8() );
931 const QUrlQuery query( url.query() );
932 VirtualRasterParameters components;
933
934 if ( ! query.hasQueryItem( QStringLiteral( "crs" ) ) )
935 {
936 QgsDebugError( "crs is missing" );
937 if ( ok ) *ok = false;
938 return components;
939 }
940 if ( ! components.crs.createFromString( query.queryItemValue( QStringLiteral( "crs" ) ) ) )
941 {
942 QgsDebugError( "failed to create crs" );
943 if ( ok ) *ok = false;
944 return components;
945 }
946
947
948 if ( ! query.hasQueryItem( QStringLiteral( "extent" ) ) )
949 {
950 QgsDebugError( "extent is missing" );
951 if ( ok ) *ok = false;
952 return components;
953 }
954 QStringList pointValuesList = query.queryItemValue( QStringLiteral( "extent" ) ).split( ',' );
955 if ( pointValuesList.size() != 4 )
956 {
957 QgsDebugError( "the extent is not correct" );
958 if ( ok ) *ok = false;
959 return components;
960 }
961 components.extent = QgsRectangle( pointValuesList.at( 0 ).toDouble(), pointValuesList.at( 1 ).toDouble(),
962 pointValuesList.at( 2 ).toDouble(), pointValuesList.at( 3 ).toDouble() );
963
964 if ( ! query.hasQueryItem( QStringLiteral( "width" ) ) )
965 {
966 QgsDebugError( "width is missing" );
967 if ( ok ) *ok = false;
968 return components;
969 }
970 bool flagW;
971 components.width = query.queryItemValue( QStringLiteral( "width" ) ).toInt( & flagW );
972 if ( !flagW || components.width < 0 )
973 {
974 QgsDebugError( "invalid or negative width input" );
975 if ( ok ) *ok = false;
976 return components;
977 }
978
979 if ( ! query.hasQueryItem( QStringLiteral( "height" ) ) )
980 {
981 QgsDebugError( "height is missing" );
982 if ( ok ) *ok = false;
983 return components;
984 }
985 bool flagH;
986 components.height = query.queryItemValue( QStringLiteral( "height" ) ).toInt( & flagH );
987 if ( !flagH || components.height < 0 )
988 {
989 QgsDebugError( "invalid or negative width input" );
990 if ( ok ) *ok = false;
991 return components;
992 }
993
994 if ( ! query.hasQueryItem( QStringLiteral( "formula" ) ) )
995 {
996 QgsDebugError( "formula is missing" );
997 if ( ok ) *ok = false;
998 return components;
999 }
1000 components.formula = query.queryItemValue( QStringLiteral( "formula" ) );
1001
1002 for ( const auto &item : query.queryItems() )
1003 {
1004 if ( !( item.first.mid( item.first.indexOf( ':' ), -1 ) == QLatin1String( ":uri" ) ) )
1005 {
1006 continue;
1007 }
1008
1010 rLayer.name = item.first.mid( 0, item.first.indexOf( ':' ) );
1011 rLayer.uri = query.queryItemValue( item.first );
1012 rLayer.provider = query.queryItemValue( item.first.mid( 0, item.first.indexOf( ':' ) ) + QStringLiteral( ":provider" ) );
1013
1014 if ( rLayer.uri.isNull() || rLayer.provider.isNull() )
1015 {
1016 QgsDebugError( "One or more raster information are missing" );
1017 if ( ok ) *ok = false;
1018 return components;
1019 }
1020
1021 components.rInputLayers.append( rLayer ) ;
1022
1023 }
1024
1025 if ( ok ) *ok = true;
1026 return components;
1027}
1028
1030{
1031 QUrl uri;
1032 QUrlQuery query;
1033
1034 if ( parts.crs.isValid() )
1035 {
1036 query.addQueryItem( QStringLiteral( "crs" ), parts.crs.authid() );
1037 }
1038
1039 if ( ! parts.extent.isNull() )
1040 {
1041 QString rect = QString( "%1,%2,%3,%4" ).arg( qgsDoubleToString( parts.extent.xMinimum() ), qgsDoubleToString( parts.extent.yMinimum() ),
1043
1044 query.addQueryItem( QStringLiteral( "extent" ), rect );
1045 }
1046
1047 query.addQueryItem( QStringLiteral( "width" ), QString::number( parts.width ) );
1048
1049 query.addQueryItem( QStringLiteral( "height" ), QString::number( parts.height ) );
1050
1051 query.addQueryItem( QStringLiteral( "formula" ), parts.formula );
1052
1053 if ( ! parts.rInputLayers.isEmpty() )
1054 {
1055 for ( const auto &it : parts.rInputLayers )
1056 {
1057 query.addQueryItem( it.name + QStringLiteral( ":uri" ), it.uri );
1058 query.addQueryItem( it.name + QStringLiteral( ":provider" ), it.provider );
1059 }
1060 }
1061 uri.setQuery( query );
1062 return QString( QUrl::toPercentEncoding( uri.toEncoded() ) );
1063}
1064
1065#undef ERR
Provides global constants and enumerations for use throughout the application.
Definition qgis.h:56
QFlags< RasterProviderCapability > RasterProviderCapabilities
Raster data provider capabilities.
Definition qgis.h:4906
@ NoProviderCapabilities
Provider has no capabilities.
Definition qgis.h:4887
RasterResamplingMethod
Resampling method for raster provider-level resampling.
Definition qgis.h:1484
@ Lanczos
Lanczos windowed sinc interpolation (6x6 kernel).
Definition qgis.h:1489
@ Nearest
Nearest-neighbour resampling.
Definition qgis.h:1485
@ Mode
Mode (selects the value which appears most often of all the sampled points).
Definition qgis.h:1491
@ Bilinear
Bilinear (2x2 kernel) resampling.
Definition qgis.h:1486
@ Average
Average resampling.
Definition qgis.h:1490
@ CubicSpline
Cubic B-Spline Approximation (4x4 kernel).
Definition qgis.h:1488
@ Cubic
Cubic Convolution Approximation (4x4 kernel) resampling.
Definition qgis.h:1487
@ Gauss
Gauss blurring.
Definition qgis.h:1492
RasterInterfaceCapability
Raster interface capabilities.
Definition qgis.h:4853
@ NoCapabilities
No capabilities.
Definition qgis.h:4854
@ Size
Original data source size (and thus resolution) is known, it is not always available,...
Definition qgis.h:4855
@ IdentifyValue
Numerical values.
Definition qgis.h:4860
@ IdentifyFeature
WMS GML -> feature.
Definition qgis.h:4863
QFlags< DataProviderReadFlag > DataProviderReadFlags
Flags which control data provider construction.
Definition qgis.h:486
DataType
Raster data types.
Definition qgis.h:372
RasterColorInterpretation
Raster color interpretation.
Definition qgis.h:4712
@ NIRBand
Near-InfraRed (NIR) band [0.75 - 1.40 um].
Definition qgis.h:4738
@ GreenBand
Green band of RGBA image, or green spectral band [0.51 - 0.60 um].
Definition qgis.h:4717
@ SAR_K_Band
Synthetic Aperture Radar (SAR) K band [1.1 - 1.7 cm / 18 - 27 GHz].
Definition qgis.h:4745
@ SAR_L_Band
Synthetic Aperture Radar (SAR) L band [15 - 30 cm / 1 - 2 GHz].
Definition qgis.h:4750
@ SaturationBand
Saturation band of HLS image.
Definition qgis.h:4721
@ MagentaBand
Magenta band of CMYK image.
Definition qgis.h:4724
@ BlackBand
Black band of CMLY image.
Definition qgis.h:4726
@ AlphaBand
Alpha (0=transparent, 255=opaque).
Definition qgis.h:4719
@ SWIRBand
Short-Wavelength InfraRed (SWIR) band [1.40 - 3.00 um].
Definition qgis.h:4739
@ SAR_X_Band
Synthetic Aperture Radar (SAR) X band [2.4 - 3.8 cm / 8 - 12 GHz].
Definition qgis.h:4747
@ BlueBand
Blue band of RGBA image, or blue spectral band [0.45 - 0.53 um].
Definition qgis.h:4718
@ LWIRBand
Long-Wavelength InfraRed (LWIR) band [8.00 - 15 um].
Definition qgis.h:4741
@ RedEdgeBand
Red-edge band [0.69 - 0.79 um].
Definition qgis.h:4737
@ SAR_Ku_Band
Synthetic Aperture Radar (SAR) Ku band [1.7 - 2.4 cm / 12 - 18 GHz].
Definition qgis.h:4746
@ YellowBand
Yellow band of CMYK image, or yellow spectral band [0.58 - 0.62 um].
Definition qgis.h:4725
@ CyanBand
Cyan band of CMYK image.
Definition qgis.h:4723
@ SAR_C_Band
Synthetic Aperture Radar (SAR) C band [3.8 - 7.5 cm / 4 - 8 GHz].
Definition qgis.h:4748
@ LightnessBand
Lightness band of HLS image.
Definition qgis.h:4722
@ CoastalBand
Coastal band [0.40 - 0.45 um].
Definition qgis.h:4736
@ HueBand
Hue band of HLS image.
Definition qgis.h:4720
@ MWIRBand
Mid-Wavelength InfraRed (MWIR) band [3.00 - 8.00 um].
Definition qgis.h:4740
@ PaletteIndex
Paletted (see associated color table).
Definition qgis.h:4715
@ TIRBand
Thermal InfraRed (TIR) band (MWIR or LWIR) [3 - 15 um].
Definition qgis.h:4742
@ SAR_Ka_Band
Synthetic Aperture Radar (SAR) Ka band [0.8 - 1.1 cm / 27 - 40 GHz].
Definition qgis.h:4744
@ SAR_S_Band
Synthetic Aperture Radar (SAR) S band [7.5 - 15 cm / 2 - 4 GHz].
Definition qgis.h:4749
@ SAR_P_Band
Synthetic Aperture Radar (SAR) P band [30 - 100 cm / 0.3 - 1 GHz].
Definition qgis.h:4751
@ RedBand
Red band of RGBA image, or red spectral band [0.62 - 0.69 um].
Definition qgis.h:4716
@ PanBand
Panchromatic band [0.40 - 1.00 um].
Definition qgis.h:4735
@ ContinuousPalette
Continuous palette, QGIS addition, GRASS.
Definition qgis.h:4730
@ OtherIRBand
Other infrared band [0.75 - 1000 um].
Definition qgis.h:4743
RasterIdentifyFormat
Raster identify formats.
Definition qgis.h:4832
@ Feature
WMS GML/JSON -> feature.
Definition qgis.h:4837
@ Value
Numerical pixel value.
Definition qgis.h:4834
@ Undefined
Undefined.
Definition qgis.h:4833
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:81
Represents 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.
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.
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:6524
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:7142
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
Definition qgis.h:6607
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:61
#define QgsDebugError(str)
Definition qgslogger.h:57
#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