QGIS API Documentation 3.40.0-Bratislava (b56115d8743)
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"
21#include "qgslogger.h"
22#include "qgspoint.h"
23#include "qgsthreadingutils.h"
24
25#include <QTime>
26#include <QMap>
27#include <QByteArray>
28#include <QVariant>
29
30#include <QUrl>
31#include <QUrlQuery>
32#include <QSet>
33
34#define ERR(message) QgsError(message, "Raster provider")
35
37{
39
40 if ( mUseSrcNoDataValue.size() < bandNo )
41 {
42 for ( int i = mUseSrcNoDataValue.size(); i < bandNo; i++ )
43 {
44 mUseSrcNoDataValue.append( false );
45 }
46 }
47 mUseSrcNoDataValue[bandNo - 1] = use;
48}
49
50QgsRasterBlock *QgsRasterDataProvider::block( int bandNo, QgsRectangle const &boundingBox, int width, int height, QgsRasterBlockFeedback *feedback )
51{
53
54 QgsDebugMsgLevel( QStringLiteral( "bandNo = %1 width = %2 height = %3" ).arg( bandNo ).arg( width ).arg( height ), 4 );
55 QgsDebugMsgLevel( QStringLiteral( "boundingBox = %1" ).arg( boundingBox.toString() ), 4 );
56
57 std::unique_ptr< QgsRasterBlock > block = std::make_unique< QgsRasterBlock >( dataType( bandNo ), width, height );
58 if ( sourceHasNoDataValue( bandNo ) && useSourceNoDataValue( bandNo ) )
59 {
61 }
62
63 if ( block->isEmpty() )
64 {
65 QgsDebugError( QStringLiteral( "Couldn't create raster block" ) );
66 block->setError( { tr( "Couldn't create raster block." ), QStringLiteral( "Raster" ) } );
67 block->setValid( false );
68 return block.release();
69 }
70
71 // Read necessary extent only
72 QgsRectangle tmpExtent = boundingBox;
73
74 if ( tmpExtent.isEmpty() )
75 {
76 QgsDebugError( QStringLiteral( "Extent outside provider extent" ) );
77 block->setError( { tr( "Extent outside provider extent." ), QStringLiteral( "Raster" ) } );
78 block->setValid( false );
80 return block.release();
81 }
82
83 const double xRes = boundingBox.width() / width;
84 const double yRes = boundingBox.height() / height;
85 double tmpXRes, tmpYRes;
86 double providerXRes = 0;
87 double providerYRes = 0;
89 {
90 providerXRes = extent().width() / xSize();
91 providerYRes = extent().height() / ySize();
92 tmpXRes = std::max( providerXRes, xRes );
93 tmpYRes = std::max( providerYRes, yRes );
94 if ( qgsDoubleNear( tmpXRes, xRes ) ) tmpXRes = xRes;
95 if ( qgsDoubleNear( tmpYRes, yRes ) ) tmpYRes = yRes;
96 }
97 else
98 {
99 tmpXRes = xRes;
100 tmpYRes = yRes;
101 }
102
103 if ( tmpExtent != boundingBox ||
104 tmpXRes > xRes || tmpYRes > yRes )
105 {
106 // Read smaller extent or lower resolution
107
108 if ( !extent().contains( boundingBox ) )
109 {
110 const QRect subRect = QgsRasterBlock::subRect( boundingBox, width, height, extent() );
111 block->setIsNoDataExcept( subRect );
112 }
113
114 // Calculate row/col limits (before tmpExtent is aligned)
115 const int fromRow = std::round( ( boundingBox.yMaximum() - tmpExtent.yMaximum() ) / yRes );
116 const int toRow = std::round( ( boundingBox.yMaximum() - tmpExtent.yMinimum() ) / yRes ) - 1;
117 const int fromCol = std::round( ( tmpExtent.xMinimum() - boundingBox.xMinimum() ) / xRes );
118 const int toCol = std::round( ( tmpExtent.xMaximum() - boundingBox.xMinimum() ) / xRes ) - 1;
119
120 QgsDebugMsgLevel( QStringLiteral( "fromRow = %1 toRow = %2 fromCol = %3 toCol = %4" ).arg( fromRow ).arg( toRow ).arg( fromCol ).arg( toCol ), 4 );
121
122 if ( fromRow < 0 || fromRow >= height || toRow < 0 || toRow >= height ||
123 fromCol < 0 || fromCol >= width || toCol < 0 || toCol >= width )
124 {
125 // Should not happen
126 QgsDebugError( QStringLiteral( "Row or column limits out of range" ) );
127 block->setError( { tr( "Row or column limits out of range" ), QStringLiteral( "Raster" ) } );
128 block->setValid( false );
129 return block.release();
130 }
131
132 // If lower source resolution is used, the extent must be aligned to original
133 // resolution to avoid possible shift due to resampling
134 if ( tmpXRes > xRes )
135 {
136 int col = std::floor( ( tmpExtent.xMinimum() - extent().xMinimum() ) / providerXRes );
137 tmpExtent.setXMinimum( extent().xMinimum() + col * providerXRes );
138 col = std::ceil( ( tmpExtent.xMaximum() - extent().xMinimum() ) / providerXRes );
139 tmpExtent.setXMaximum( extent().xMinimum() + col * providerXRes );
140 }
141 if ( tmpYRes > yRes )
142 {
143 int row = std::floor( ( extent().yMaximum() - tmpExtent.yMaximum() ) / providerYRes );
144 tmpExtent.setYMaximum( extent().yMaximum() - row * providerYRes );
145 row = std::ceil( ( extent().yMaximum() - tmpExtent.yMinimum() ) / providerYRes );
146 tmpExtent.setYMinimum( extent().yMaximum() - row * providerYRes );
147 }
148 const int tmpWidth = std::round( tmpExtent.width() / tmpXRes );
149 const int tmpHeight = std::round( tmpExtent.height() / tmpYRes );
150 tmpXRes = tmpExtent.width() / tmpWidth;
151 tmpYRes = tmpExtent.height() / tmpHeight;
152
153 QgsDebugMsgLevel( QStringLiteral( "Reading smaller block tmpWidth = %1 height = %2" ).arg( tmpWidth ).arg( tmpHeight ), 4 );
154 QgsDebugMsgLevel( QStringLiteral( "tmpExtent = %1" ).arg( tmpExtent.toString() ), 4 );
155
156 std::unique_ptr< QgsRasterBlock > tmpBlock = std::make_unique< QgsRasterBlock >( dataType( bandNo ), tmpWidth, tmpHeight );
157 if ( sourceHasNoDataValue( bandNo ) && useSourceNoDataValue( bandNo ) )
158 {
159 tmpBlock->setNoDataValue( sourceNoDataValue( bandNo ) );
160 }
161
162 if ( !readBlock( bandNo, tmpExtent, tmpWidth, tmpHeight, tmpBlock->bits(), feedback ) )
163 {
164 QgsDebugError( QStringLiteral( "Error occurred while reading block" ) );
165 block->setError( { tr( "Error occurred while reading block." ), QStringLiteral( "Raster" ) } );
166 block->setValid( false );
168 return block.release();
169 }
170
171 const int pixelSize = dataTypeSize( bandNo );
172
173 const double xMin = boundingBox.xMinimum();
174 const double yMax = boundingBox.yMaximum();
175 const double tmpXMin = tmpExtent.xMinimum();
176 const double tmpYMax = tmpExtent.yMaximum();
177
178 for ( int row = fromRow; row <= toRow; row++ )
179 {
180 const double y = yMax - ( row + 0.5 ) * yRes;
181 const int tmpRow = std::floor( ( tmpYMax - y ) / tmpYRes );
182
183 for ( int col = fromCol; col <= toCol; col++ )
184 {
185 const double x = xMin + ( col + 0.5 ) * xRes;
186 const int tmpCol = std::floor( ( x - tmpXMin ) / tmpXRes );
187
188 if ( tmpRow < 0 || tmpRow >= tmpHeight || tmpCol < 0 || tmpCol >= tmpWidth )
189 {
190 QgsDebugError( QStringLiteral( "Source row or column limits out of range" ) );
191 block->setIsNoData(); // so that the problem becomes obvious and fixed
192 block->setError( { tr( "Source row or column limits out of range." ), QStringLiteral( "Raster" ) } );
193 block->setValid( false );
194 return block.release();
195 }
196
197 const qgssize tmpIndex = static_cast< qgssize >( tmpRow ) * static_cast< qgssize >( tmpWidth ) + tmpCol;
198 const qgssize index = row * static_cast< qgssize >( width ) + col;
199
200 const char *tmpBits = tmpBlock->constBits( tmpIndex );
201 char *bits = block->bits( index );
202 if ( !tmpBits )
203 {
204 QgsDebugError( QStringLiteral( "Cannot get input block data tmpRow = %1 tmpCol = %2 tmpIndex = %3." ).arg( tmpRow ).arg( tmpCol ).arg( tmpIndex ) );
205 continue;
206 }
207 if ( !bits )
208 {
209 QgsDebugError( QStringLiteral( "Cannot set output block data." ) );
210 continue;
211 }
212 memcpy( bits, tmpBits, pixelSize );
213 }
214 }
215 }
216 else
217 {
218 if ( !readBlock( bandNo, boundingBox, width, height, block->bits(), feedback ) )
219 {
220 QgsDebugError( QStringLiteral( "Error occurred while reading block" ) );
222 block->setError( { tr( "Error occurred while reading block." ), QStringLiteral( "Raster" ) } );
223 block->setValid( false );
224 return block.release();
225 }
226 }
227
228 // apply scale and offset
229 block->applyScaleOffset( bandScale( bandNo ), bandOffset( bandNo ) );
230 // apply user no data values
232 return block.release();
233}
234
236 : QgsDataProvider( QString(), QgsDataProvider::ProviderOptions(), Qgis::DataProviderReadFlags() )
237 , QgsRasterInterface( nullptr )
238 , mTemporalCapabilities( std::make_unique< QgsRasterDataProviderTemporalCapabilities >() )
239 , mElevationProperties( std::make_unique< QgsRasterDataProviderElevationProperties >() )
240{
241
242}
243
246 : QgsDataProvider( uri, options, flags )
247 , QgsRasterInterface( nullptr )
248 , mTemporalCapabilities( std::make_unique< QgsRasterDataProviderTemporalCapabilities >() )
249 , mElevationProperties( std::make_unique< QgsRasterDataProviderElevationProperties >() )
250{
251}
252
259
267
268// TODO
269// (WMS) IdentifyFormatFeature is not consistent with QgsRaster::IdentifyFormatValue.
270// IdentifyFormatHtml: better error reporting
271QgsRasterIdentifyResult QgsRasterDataProvider::identify( const QgsPointXY &point, Qgis::RasterIdentifyFormat format, const QgsRectangle &boundingBox, int width, int height, int /*dpi*/ )
272{
274
275 QgsDebugMsgLevel( QStringLiteral( "Entered" ), 4 );
276 QMap<int, QVariant> results;
277
279 {
280 QgsDebugError( QStringLiteral( "Format not supported" ) );
281 return QgsRasterIdentifyResult( ERR( tr( "Format not supported" ) ) );
282 }
283
284 if ( !extent().contains( point ) )
285 {
286 // Outside the raster
287 for ( int bandNo = 1; bandNo <= bandCount(); bandNo++ )
288 {
289 results.insert( bandNo, QVariant() );
290 }
292 }
293
294 QgsRectangle finalExtent = boundingBox;
295 if ( finalExtent.isEmpty() )
296 finalExtent = extent();
297
298 if ( width == 0 )
299 {
301 }
302 if ( height == 0 )
303 {
304 height = ( capabilities() & Qgis::RasterInterfaceCapability::Size ) ? ySize() : 1000;
305 }
306
307 // Calculate the row / column where the point falls
308 const double xres = ( finalExtent.width() ) / width;
309 const double yres = ( finalExtent.height() ) / height;
310
311 const int col = static_cast< int >( std::floor( ( point.x() - finalExtent.xMinimum() ) / xres ) );
312 const int row = static_cast< int >( std::floor( ( finalExtent.yMaximum() - point.y() ) / yres ) );
313
314 const double xMin = finalExtent.xMinimum() + col * xres;
315 const double xMax = xMin + xres;
316 const double yMax = finalExtent.yMaximum() - row * yres;
317 const double yMin = yMax - yres;
318 const QgsRectangle pixelExtent( xMin, yMin, xMax, yMax );
319
320 for ( int bandNumber = 1; bandNumber <= bandCount(); bandNumber++ )
321 {
322 std::unique_ptr< QgsRasterBlock > bandBlock( block( bandNumber, pixelExtent, 1, 1 ) );
323
324 if ( bandBlock )
325 {
326 const double value = bandBlock->value( 0 );
327 results.insert( bandNumber, value );
328 }
329 else
330 {
331 results.insert( bandNumber, QVariant() );
332 }
333 }
335}
336
337double QgsRasterDataProvider::sample( const QgsPointXY &point, int band,
338 bool *ok, const QgsRectangle &boundingBox, int width, int height, int dpi )
339{
341
342 if ( ok )
343 *ok = false;
344
345 const auto res = identify( point, Qgis::RasterIdentifyFormat::Value, boundingBox, width, height, dpi );
346 const QVariant value = res.results().value( band );
347
348 if ( !value.isValid() )
349 return std::numeric_limits<double>::quiet_NaN();
350
351 if ( ok )
352 *ok = true;
353
354 return value.toDouble( ok );
355}
356
358{
360
361 return QStringLiteral( "text/plain" );
362}
363
364bool QgsRasterDataProvider::writeBlock( QgsRasterBlock *block, int band, int xOffset, int yOffset )
365{
367
368 if ( !block )
369 return false;
370 if ( !isEditable() )
371 {
372 QgsDebugError( QStringLiteral( "writeBlock() called on read-only provider." ) );
373 return false;
374 }
375 return write( block->bits(), band, block->width(), block->height(), xOffset, yOffset );
376}
377
378// typedef QList<QPair<QString, QString> > *pyramidResamplingMethods_t();
379QList<QPair<QString, QString> > QgsRasterDataProvider::pyramidResamplingMethods( const QString &providerKey )
380{
381 QList<QPair<QString, QString> > methods = QgsProviderRegistry::instance()->pyramidResamplingMethods( providerKey );
382 if ( methods.isEmpty() )
383 {
384 QgsDebugMsgLevel( QStringLiteral( "provider pyramidResamplingMethods returned no methods" ), 2 );
385 }
386 return methods;
387}
388
390{
392
393 const QList<QgsRasterPyramid> pyramidList = buildPyramidList();
394 return std::any_of( pyramidList.constBegin(), pyramidList.constEnd(), []( QgsRasterPyramid pyramid ) { return pyramid.getExists(); } );
395}
396
398{
400
401 if ( bandNo >= mUserNoDataValue.size() )
402 {
403 for ( int i = mUserNoDataValue.size(); i < bandNo; i++ )
404 {
406 }
407 }
408 QgsDebugMsgLevel( QStringLiteral( "set %1 band %1 no data ranges" ).arg( noData.size() ), 4 );
409
410 if ( mUserNoDataValue[bandNo - 1] != noData )
411 {
412 // Clear statistics
413 mStatistics.erase( std::remove_if( mStatistics.begin(), mStatistics.end(), [bandNo]( const QgsRasterBandStats & stats )
414 {
415 return stats.bandNumber == bandNo;
416 } ), mStatistics.end() );
417 mHistograms.erase( std::remove_if( mHistograms.begin(), mHistograms.end(), [bandNo]( const QgsRasterHistogram & histogram )
418 {
419 return histogram.bandNumber == bandNo;
420 } ), mHistograms.end() );
421 mUserNoDataValue[bandNo - 1] = noData;
422 }
423}
424
431
438
445
452
454 const QString &uri,
455 const QString &format, int nBands,
456 Qgis::DataType type,
457 int width, int height, double *geoTransform,
459 const QStringList &createOptions )
460{
462 providerKey,
463 uri, format,
464 nBands, type, width,
465 height, geoTransform, crs, createOptions );
466 if ( !ret )
467 {
468 QgsDebugError( "Cannot resolve 'createRasterDataProviderFunction' function in " + providerKey + " provider" );
469 }
470
471 // TODO: it would be good to return invalid QgsRasterDataProvider
472 // with QgsError set, but QgsRasterDataProvider has pure virtual methods
473
474 return ret;
475}
476
478{
479 switch ( format )
480 {
482 return QStringLiteral( "Value" );
484 return QStringLiteral( "Text" );
486 return QStringLiteral( "Html" );
488 return QStringLiteral( "Feature" );
490 break;
491 }
492 return QStringLiteral( "Undefined" );
493}
494
496{
497 switch ( format )
498 {
500 return tr( "Value" );
502 return tr( "Text" );
504 return tr( "HTML" );
506 return tr( "Feature" );
508 break;
509 }
510 return QStringLiteral( "Undefined" );
511}
512
514{
515 if ( formatName == QLatin1String( "Value" ) )
517 if ( formatName == QLatin1String( "Text" ) )
519 if ( formatName == QLatin1String( "Html" ) )
521 if ( formatName == QLatin1String( "Feature" ) )
524}
525
543
545{
547
548 return QList< double >();
549}
550
552{
554
555 return false;
556}
557
559{
561
562 Q_UNUSED( point )
563 Q_UNUSED( type )
564 return QgsPoint();
565}
566
567bool QgsRasterDataProvider::userNoDataValuesContains( int bandNo, double value ) const
568{
570
571 const QgsRasterRangeList rangeList = mUserNoDataValue.value( bandNo - 1 );
572 return QgsRasterRange::contains( value, rangeList );
573}
574
576{
578
579 mDpi = other.mDpi;
584 mExtent = other.mExtent;
589
590 if ( mTemporalCapabilities && other.mTemporalCapabilities )
591 {
592 *mTemporalCapabilities = *other.mTemporalCapabilities;
593 }
594 if ( mElevationProperties && other.mElevationProperties )
595 {
596 *mElevationProperties = *other.mElevationProperties;
597 }
598}
599
600static QgsRasterDataProvider::ResamplingMethod resamplingMethodFromString( const QString &str )
601{
602 if ( str == QLatin1String( "bilinear" ) )
603 {
605 }
606 else if ( str == QLatin1String( "cubic" ) )
607 {
609 }
610 else if ( str == QLatin1String( "cubicSpline" ) )
611 {
613 }
614 else if ( str == QLatin1String( "lanczos" ) )
615 {
617 }
618 else if ( str == QLatin1String( "average" ) )
619 {
621 }
622 else if ( str == QLatin1String( "mode" ) )
623 {
625 }
626 else if ( str == QLatin1String( "gauss" ) )
627 {
629 }
631}
632
633void QgsRasterDataProvider::readXml( const QDomElement &filterElem )
634{
636
637 if ( filterElem.isNull() )
638 {
639 return;
640 }
641
642 const QDomElement resamplingElement = filterElem.firstChildElement( QStringLiteral( "resampling" ) );
643 if ( !resamplingElement.isNull() )
644 {
645 setMaxOversampling( resamplingElement.attribute( QStringLiteral( "maxOversampling" ), QStringLiteral( "2.0" ) ).toDouble() );
646 setZoomedInResamplingMethod( resamplingMethodFromString( resamplingElement.attribute( QStringLiteral( "zoomedInResamplingMethod" ) ) ) );
647 setZoomedOutResamplingMethod( resamplingMethodFromString( resamplingElement.attribute( QStringLiteral( "zoomedOutResamplingMethod" ) ) ) );
648 enableProviderResampling( resamplingElement.attribute( QStringLiteral( "enabled" ) ) == QLatin1String( "true" ) );
649 }
650}
651
652static QString resamplingMethodToString( QgsRasterDataProvider::ResamplingMethod method )
653{
654 switch ( method )
655 {
657 return QStringLiteral( "nearestNeighbour" );
659 return QStringLiteral( "bilinear" );
661 return QStringLiteral( "cubic" );
663 return QStringLiteral( "cubicSpline" );
665 return QStringLiteral( "lanczos" );
667 return QStringLiteral( "average" );
669 return QStringLiteral( "mode" );
671 return QStringLiteral( "gauss" );
672 }
673 // should not happen
674 return QStringLiteral( "nearestNeighbour" );
675}
676
677void QgsRasterDataProvider::writeXml( QDomDocument &doc, QDomElement &parentElem ) const
678{
680
681 QDomElement providerElement = doc.createElement( QStringLiteral( "provider" ) );
682 parentElem.appendChild( providerElement );
683
684 QDomElement resamplingElement = doc.createElement( QStringLiteral( "resampling" ) );
685 providerElement.appendChild( resamplingElement );
686
687 resamplingElement.setAttribute( QStringLiteral( "enabled" ),
688 mProviderResamplingEnabled ? QStringLiteral( "true" ) : QStringLiteral( "false" ) );
689
690 resamplingElement.setAttribute( QStringLiteral( "zoomedInResamplingMethod" ),
691 resamplingMethodToString( mZoomedInResamplingMethod ) );
692
693 resamplingElement.setAttribute( QStringLiteral( "zoomedOutResamplingMethod" ),
694 resamplingMethodToString( mZoomedOutResamplingMethod ) );
695
696 resamplingElement.setAttribute( QStringLiteral( "maxOversampling" ),
697 QString::number( mMaxOversampling ) );
698}
699
701{
703
704 try
705 {
706 return mAttributeTables.at( bandNumber ).get();
707 }
708 catch ( std::out_of_range const & )
709 {
710 return nullptr;
711 }
712}
713
715{
717
718 if ( attributeTable )
719 {
720 mAttributeTables[ bandNumber ] = std::unique_ptr<QgsRasterAttributeTable>( attributeTable );
721 }
722 else
723 {
724 removeAttributeTable( bandNumber );
725 }
726}
727
729{
731
732 if ( mAttributeTables.find( bandNumber ) != std::end( mAttributeTables ) )
733 {
734 mAttributeTables.erase( bandNumber );
735 }
736}
737
738bool QgsRasterDataProvider::writeFileBasedAttributeTable( int bandNumber, const QString &path, QString *errorMessage ) const
739{
741
742 QgsRasterAttributeTable *rat { attributeTable( bandNumber ) };
743 if ( ! rat )
744 {
745 if ( errorMessage )
746 {
747 *errorMessage = QObject::tr( "Raster has no Raster Attribute Table for band %1" ).arg( bandNumber );
748 }
749 return false;
750 }
751
752 return rat->writeToFile( path, errorMessage );
753}
754
756{
758
759 if ( errorMessage )
760 {
761 *errorMessage = QObject::tr( "Raster data provider has no native Raster Attribute Table support." );
762 }
763 return false;
764}
765
767{
768 Q_UNUSED( bandNumber )
769 return QString();
770}
771
772bool QgsRasterDataProvider::readFileBasedAttributeTable( int bandNumber, const QString &path, QString *errorMessage )
773{
775
776 std::unique_ptr<QgsRasterAttributeTable> rat = std::make_unique<QgsRasterAttributeTable>();
777 if ( rat->readFromFile( path, errorMessage ) )
778 {
779 setAttributeTable( bandNumber, rat.release() );
780 return true;
781 }
782 else
783 {
784 return false;
785 }
786}
787
788bool QgsRasterDataProvider::writeNativeAttributeTable( QString *errorMessage ) //#spellok
789{
791
792 Q_UNUSED( errorMessage );
793 return false;
794}
795
797{
799
800 return colorName( colorInterpretation( bandNo ) );
801}
802
804{
805 // Modified copy from GDAL
806 switch ( colorInterpretation )
807 {
809 return tr( "Undefined" );
810
812 return tr( "Gray" );
813
815 return tr( "Palette" );
816
818 return tr( "Red" );
819
821 return tr( "Green" );
822
824 return tr( "Blue" );
825
827 return tr( "Alpha" );
828
830 return tr( "Hue" );
831
833 return tr( "Saturation" );
834
836 return tr( "Lightness" );
837
839 return tr( "Cyan" );
840
842 return tr( "Magenta" );
843
845 return tr( "Yellow" );
846
848 return tr( "Black" );
849
851 return tr( "YCbCr_Y" );
852
854 return tr( "YCbCr_Cb" );
855
857 return tr( "YCbCr_Cr" );
858
860 return tr( "Continuous Palette" );
861
863 return tr( "Panchromatic" );
864
866 return tr( "Coastal" );
867
869 return tr( "Red Edge" );
870
872 return tr( "Near-InfraRed (NIR)" );
873
875 return tr( "Short-Wavelength InfraRed (SWIR)" );
876
878 return tr( "Mid-Wavelength InfraRed (MWIR)" );
879
881 return tr( "Long-Wavelength InfraRed (LWIR)" );
882
884 return tr( "Thermal InfraRed (TIR)" );
885
887 return tr( "Other InfraRed" );
888
890 return tr( "Synthetic Aperture Radar (SAR) Ka band" );
891
893 return tr( "Synthetic Aperture Radar (SAR) K band" );
894
896 return tr( "Synthetic Aperture Radar (SAR) Ku band" );
897
899 return tr( "Synthetic Aperture Radar (SAR) X band" );
900
902 return tr( "Synthetic Aperture Radar (SAR) C band" );
903
905 return tr( "Synthetic Aperture Radar (SAR) S band" );
906
908 return tr( "Synthetic Aperture Radar (SAR) L band" );
909
911 return tr( "Synthetic Aperture Radar (SAR) P band" );
912 }
913 return QString();
914}
915
917{
918 QUrl url = QUrl::fromPercentEncoding( uri.toUtf8() );
919 const QUrlQuery query( url.query() );
920 VirtualRasterParameters components;
921
922 if ( ! query.hasQueryItem( QStringLiteral( "crs" ) ) )
923 {
924 QgsDebugError( "crs is missing" );
925 if ( ok ) *ok = false;
926 return components;
927 }
928 if ( ! components.crs.createFromString( query.queryItemValue( QStringLiteral( "crs" ) ) ) )
929 {
930 QgsDebugError( "failed to create crs" );
931 if ( ok ) *ok = false;
932 return components;
933 }
934
935
936 if ( ! query.hasQueryItem( QStringLiteral( "extent" ) ) )
937 {
938 QgsDebugError( "extent is missing" );
939 if ( ok ) *ok = false;
940 return components;
941 }
942 QStringList pointValuesList = query.queryItemValue( QStringLiteral( "extent" ) ).split( ',' );
943 if ( pointValuesList.size() != 4 )
944 {
945 QgsDebugError( "the extent is not correct" );
946 if ( ok ) *ok = false;
947 return components;
948 }
949 components.extent = QgsRectangle( pointValuesList.at( 0 ).toDouble(), pointValuesList.at( 1 ).toDouble(),
950 pointValuesList.at( 2 ).toDouble(), pointValuesList.at( 3 ).toDouble() );
951
952 if ( ! query.hasQueryItem( QStringLiteral( "width" ) ) )
953 {
954 QgsDebugError( "width is missing" );
955 if ( ok ) *ok = false;
956 return components;
957 }
958 bool flagW;
959 components.width = query.queryItemValue( QStringLiteral( "width" ) ).toInt( & flagW );
960 if ( !flagW || components.width < 0 )
961 {
962 QgsDebugError( "invalid or negative width input" );
963 if ( ok ) *ok = false;
964 return components;
965 }
966
967 if ( ! query.hasQueryItem( QStringLiteral( "height" ) ) )
968 {
969 QgsDebugError( "height is missing" );
970 if ( ok ) *ok = false;
971 return components;
972 }
973 bool flagH;
974 components.height = query.queryItemValue( QStringLiteral( "height" ) ).toInt( & flagH );
975 if ( !flagH || components.height < 0 )
976 {
977 QgsDebugError( "invalid or negative width input" );
978 if ( ok ) *ok = false;
979 return components;
980 }
981
982 if ( ! query.hasQueryItem( QStringLiteral( "formula" ) ) )
983 {
984 QgsDebugError( "formula is missing" );
985 if ( ok ) *ok = false;
986 return components;
987 }
988 components.formula = query.queryItemValue( QStringLiteral( "formula" ) );
989
990 for ( const auto &item : query.queryItems() )
991 {
992 if ( !( item.first.mid( item.first.indexOf( ':' ), -1 ) == QLatin1String( ":uri" ) ) )
993 {
994 continue;
995 }
996
998 rLayer.name = item.first.mid( 0, item.first.indexOf( ':' ) );
999 rLayer.uri = query.queryItemValue( item.first );
1000 rLayer.provider = query.queryItemValue( item.first.mid( 0, item.first.indexOf( ':' ) ) + QStringLiteral( ":provider" ) );
1001
1002 if ( rLayer.uri.isNull() || rLayer.provider.isNull() )
1003 {
1004 QgsDebugError( "One or more raster information are missing" );
1005 if ( ok ) *ok = false;
1006 return components;
1007 }
1008
1009 components.rInputLayers.append( rLayer ) ;
1010
1011 }
1012
1013 if ( ok ) *ok = true;
1014 return components;
1015}
1016
1018{
1019 QUrl uri;
1020 QUrlQuery query;
1021
1022 if ( parts.crs.isValid() )
1023 {
1024 query.addQueryItem( QStringLiteral( "crs" ), parts.crs.authid() );
1025 }
1026
1027 if ( ! parts.extent.isNull() )
1028 {
1029 QString rect = QString( "%1,%2,%3,%4" ).arg( qgsDoubleToString( parts.extent.xMinimum() ), qgsDoubleToString( parts.extent.yMinimum() ),
1031
1032 query.addQueryItem( QStringLiteral( "extent" ), rect );
1033 }
1034
1035 query.addQueryItem( QStringLiteral( "width" ), QString::number( parts.width ) );
1036
1037 query.addQueryItem( QStringLiteral( "height" ), QString::number( parts.height ) );
1038
1039 query.addQueryItem( QStringLiteral( "formula" ), parts.formula );
1040
1041 if ( ! parts.rInputLayers.isEmpty() )
1042 {
1043 for ( const auto &it : parts.rInputLayers )
1044 {
1045 query.addQueryItem( it.name + QStringLiteral( ":uri" ), it.uri );
1046 query.addQueryItem( it.name + QStringLiteral( ":provider" ), it.provider );
1047 }
1048 }
1049 uri.setQuery( query );
1050 return QString( QUrl::toPercentEncoding( uri.toEncoded() ) );
1051}
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:4562
@ NoProviderCapabilities
Provider has no capabilities.
RasterInterfaceCapability
Raster interface capabilities.
Definition qgis.h:4509
@ 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:4368
@ 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:4488
@ 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:38
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition qgis.h:5834
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:6465
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition qgis.h:5917
#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