QGIS API Documentation 3.29.0-Master (8c80f25a4f)
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 "qgsprovidermetadata.h"
22#include "qgsrasterprojector.h"
23#include "qgslogger.h"
24#include "qgsmessagelog.h"
25#include "qgsapplication.h"
26#include "qgspoint.h"
27#include "qgsvectorfilewriter.h"
28#include "qgsvectorlayer.h"
29
30#include <QTime>
31#include <QMap>
32#include <QByteArray>
33#include <QVariant>
34
35#include <QUrl>
36#include <QUrlQuery>
37#include <QSet>
38
39#define ERR(message) QgsError(message, "Raster provider")
40
42{
43 if ( mUseSrcNoDataValue.size() < bandNo )
44 {
45 for ( int i = mUseSrcNoDataValue.size(); i < bandNo; i++ )
46 {
47 mUseSrcNoDataValue.append( false );
48 }
49 }
50 mUseSrcNoDataValue[bandNo - 1] = use;
51}
52
53QgsRasterBlock *QgsRasterDataProvider::block( int bandNo, QgsRectangle const &boundingBox, int width, int height, QgsRasterBlockFeedback *feedback )
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 QgsDebugMsg( 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 QgsDebugMsg( 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;
89 if ( capabilities() & Size )
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 QgsDebugMsg( 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 QgsDebugMsg( 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 QgsDebugMsg( 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 char *tmpBits = tmpBlock->bits( tmpIndex );
202 char *bits = block->bits( index );
203 if ( !tmpBits )
204 {
205 QgsDebugMsg( 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 QgsDebugMsg( 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 QgsDebugMsg( 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(), QgsDataProvider::ReadFlags() )
238 , QgsRasterInterface( nullptr )
239 , mTemporalCapabilities( std::make_unique< QgsRasterDataProviderTemporalCapabilities >() )
240{
241
242}
243
245 QgsDataProvider::ReadFlags flags )
246 : QgsDataProvider( uri, options, flags )
247 , QgsRasterInterface( nullptr )
248 , mTemporalCapabilities( std::make_unique< QgsRasterDataProviderTemporalCapabilities >() )
249{
250}
251
252QgsRasterDataProvider::ProviderCapabilities QgsRasterDataProvider::providerCapabilities() const
253{
255}
256
258{
259 Q_UNUSED( bandNo )
261}
262
263//
264//Random Static convenience function
265//
267
268// TODO
269// (WMS) IdentifyFormatFeature is not consistent with QgsRaster::IdentifyFormatValue.
270// IdentifyFormatHtml: better error reporting
271QgsRasterIdentifyResult QgsRasterDataProvider::identify( const QgsPointXY &point, QgsRaster::IdentifyFormat format, const QgsRectangle &boundingBox, int width, int height, int /*dpi*/ )
272{
273 QgsDebugMsgLevel( QStringLiteral( "Entered" ), 4 );
274 QMap<int, QVariant> results;
275
277 {
278 QgsDebugMsg( QStringLiteral( "Format not supported" ) );
279 return QgsRasterIdentifyResult( ERR( tr( "Format not supported" ) ) );
280 }
281
282 if ( !extent().contains( point ) )
283 {
284 // Outside the raster
285 for ( int bandNo = 1; bandNo <= bandCount(); bandNo++ )
286 {
287 results.insert( bandNo, QVariant() );
288 }
290 }
291
292 QgsRectangle finalExtent = boundingBox;
293 if ( finalExtent.isEmpty() )
294 finalExtent = extent();
295
296 if ( width == 0 )
297 {
298 width = capabilities() & Size ? xSize() : 1000;
299 }
300 if ( height == 0 )
301 {
302 height = capabilities() & Size ? ySize() : 1000;
303 }
304
305 // Calculate the row / column where the point falls
306 const double xres = ( finalExtent.width() ) / width;
307 const double yres = ( finalExtent.height() ) / height;
308
309 const int col = static_cast< int >( std::floor( ( point.x() - finalExtent.xMinimum() ) / xres ) );
310 const int row = static_cast< int >( std::floor( ( finalExtent.yMaximum() - point.y() ) / yres ) );
311
312 const double xMin = finalExtent.xMinimum() + col * xres;
313 const double xMax = xMin + xres;
314 const double yMax = finalExtent.yMaximum() - row * yres;
315 const double yMin = yMax - yres;
316 const QgsRectangle pixelExtent( xMin, yMin, xMax, yMax );
317
318 for ( int bandNumber = 1; bandNumber <= bandCount(); bandNumber++ )
319 {
320 std::unique_ptr< QgsRasterBlock > bandBlock( block( bandNumber, pixelExtent, 1, 1 ) );
321
322 if ( bandBlock )
323 {
324 const double value = bandBlock->value( 0 );
325 results.insert( bandNumber, value );
326 }
327 else
328 {
329 results.insert( bandNumber, QVariant() );
330 }
331 }
333}
334
335double QgsRasterDataProvider::sample( const QgsPointXY &point, int band,
336 bool *ok, const QgsRectangle &boundingBox, int width, int height, int dpi )
337{
338 if ( ok )
339 *ok = false;
340
341 const auto res = identify( point, QgsRaster::IdentifyFormatValue, boundingBox, width, height, dpi );
342 const QVariant value = res.results().value( band );
343
344 if ( !value.isValid() )
345 return std::numeric_limits<double>::quiet_NaN();
346
347 if ( ok )
348 *ok = true;
349
350 return value.toDouble( ok );
351}
352
354{
355 return QStringLiteral( "text/plain" );
356}
357
358bool QgsRasterDataProvider::writeBlock( QgsRasterBlock *block, int band, int xOffset, int yOffset )
359{
360 if ( !block )
361 return false;
362 if ( !isEditable() )
363 {
364 QgsDebugMsg( QStringLiteral( "writeBlock() called on read-only provider." ) );
365 return false;
366 }
367 return write( block->bits(), band, block->width(), block->height(), xOffset, yOffset );
368}
369
370// typedef QList<QPair<QString, QString> > *pyramidResamplingMethods_t();
371QList<QPair<QString, QString> > QgsRasterDataProvider::pyramidResamplingMethods( const QString &providerKey )
372{
373 QList<QPair<QString, QString> > methods = QgsProviderRegistry::instance()->pyramidResamplingMethods( providerKey );
374 if ( methods.isEmpty() )
375 {
376 QgsDebugMsg( QStringLiteral( "provider pyramidResamplingMethods returned no methods" ) );
377 }
378 return methods;
379}
380
382{
383 const QList<QgsRasterPyramid> pyramidList = buildPyramidList();
384 return std::any_of( pyramidList.constBegin(), pyramidList.constEnd(), []( QgsRasterPyramid pyramid ) { return pyramid.getExists(); } );
385}
386
388{
389 if ( bandNo >= mUserNoDataValue.size() )
390 {
391 for ( int i = mUserNoDataValue.size(); i < bandNo; i++ )
392 {
394 }
395 }
396 QgsDebugMsgLevel( QStringLiteral( "set %1 band %1 no data ranges" ).arg( noData.size() ), 4 );
397
398 if ( mUserNoDataValue[bandNo - 1] != noData )
399 {
400 // Clear statistics
401 mStatistics.erase( std::remove_if( mStatistics.begin(), mStatistics.end(), [bandNo]( const QgsRasterBandStats & stats )
402 {
403 return stats.bandNumber == bandNo;
404 } ), mStatistics.end() );
405 mHistograms.erase( std::remove_if( mHistograms.begin(), mHistograms.end(), [bandNo]( const QgsRasterHistogram & histogram )
406 {
407 return histogram.bandNumber == bandNo;
408 } ), mHistograms.end() );
409 mUserNoDataValue[bandNo - 1] = noData;
410 }
411}
412
414{
415 return mTemporalCapabilities.get();
416}
417
419{
420 return mTemporalCapabilities.get();
421}
422
424 const QString &uri,
425 const QString &format, int nBands,
426 Qgis::DataType type,
427 int width, int height, double *geoTransform,
429 const QStringList &createOptions )
430{
432 providerKey,
433 uri, format,
434 nBands, type, width,
435 height, geoTransform, crs, createOptions );
436 if ( !ret )
437 {
438 QgsDebugMsg( "Cannot resolve 'createRasterDataProviderFunction' function in " + providerKey + " provider" );
439 }
440
441 // TODO: it would be good to return invalid QgsRasterDataProvider
442 // with QgsError set, but QgsRasterDataProvider has pure virtual methods
443
444 return ret;
445}
446
448{
449 switch ( format )
450 {
452 return QStringLiteral( "Value" );
454 return QStringLiteral( "Text" );
456 return QStringLiteral( "Html" );
458 return QStringLiteral( "Feature" );
459 default:
460 return QStringLiteral( "Undefined" );
461 }
462}
463
465{
466 switch ( format )
467 {
469 return tr( "Value" );
471 return tr( "Text" );
473 return tr( "Html" );
475 return tr( "Feature" );
476 default:
477 return QStringLiteral( "Undefined" );
478 }
479}
480
482{
483 if ( formatName == QLatin1String( "Value" ) ) return QgsRaster::IdentifyFormatValue;
484 if ( formatName == QLatin1String( "Text" ) ) return QgsRaster::IdentifyFormatText;
485 if ( formatName == QLatin1String( "Html" ) ) return QgsRaster::IdentifyFormatHtml;
486 if ( formatName == QLatin1String( "Feature" ) ) return QgsRaster::IdentifyFormatFeature;
488}
489
491{
492 switch ( format )
493 {
495 return IdentifyValue;
497 return IdentifyText;
499 return IdentifyHtml;
501 return IdentifyFeature;
502 default:
503 return NoCapabilities;
504 }
505}
506
508{
509 return QList< double >();
510}
511
513{
514 return false;
515}
516
518{
519 Q_UNUSED( point )
520 Q_UNUSED( type )
521 return QgsPoint();
522}
523
524bool QgsRasterDataProvider::userNoDataValuesContains( int bandNo, double value ) const
525{
526 const QgsRasterRangeList rangeList = mUserNoDataValue.value( bandNo - 1 );
527 return QgsRasterRange::contains( value, rangeList );
528}
529
531{
532 mDpi = other.mDpi;
537 mExtent = other.mExtent;
542
543 // copy temporal properties
544 if ( mTemporalCapabilities && other.mTemporalCapabilities )
545 {
546 *mTemporalCapabilities = *other.mTemporalCapabilities;
547 }
548}
549
550static QgsRasterDataProvider::ResamplingMethod resamplingMethodFromString( const QString &str )
551{
552 if ( str == QLatin1String( "bilinear" ) )
553 {
555 }
556 else if ( str == QLatin1String( "cubic" ) )
557 {
559 }
560 else if ( str == QLatin1String( "cubicSpline" ) )
561 {
563 }
564 else if ( str == QLatin1String( "lanczos" ) )
565 {
567 }
568 else if ( str == QLatin1String( "average" ) )
569 {
571 }
572 else if ( str == QLatin1String( "mode" ) )
573 {
575 }
576 else if ( str == QLatin1String( "gauss" ) )
577 {
579 }
581}
582
583void QgsRasterDataProvider::readXml( const QDomElement &filterElem )
584{
585 if ( filterElem.isNull() )
586 {
587 return;
588 }
589
590 const QDomElement resamplingElement = filterElem.firstChildElement( QStringLiteral( "resampling" ) );
591 if ( !resamplingElement.isNull() )
592 {
593 setMaxOversampling( resamplingElement.attribute( QStringLiteral( "maxOversampling" ), QStringLiteral( "2.0" ) ).toDouble() );
594 setZoomedInResamplingMethod( resamplingMethodFromString( resamplingElement.attribute( QStringLiteral( "zoomedInResamplingMethod" ) ) ) );
595 setZoomedOutResamplingMethod( resamplingMethodFromString( resamplingElement.attribute( QStringLiteral( "zoomedOutResamplingMethod" ) ) ) );
596 enableProviderResampling( resamplingElement.attribute( QStringLiteral( "enabled" ) ) == QLatin1String( "true" ) );
597 }
598}
599
600static QString resamplingMethodToString( QgsRasterDataProvider::ResamplingMethod method )
601{
602 switch ( method )
603 {
605 return QStringLiteral( "nearestNeighbour" );
607 return QStringLiteral( "bilinear" );
609 return QStringLiteral( "cubic" );
611 return QStringLiteral( "cubicSpline" );
613 return QStringLiteral( "lanczos" );
615 return QStringLiteral( "average" );
617 return QStringLiteral( "mode" );
619 return QStringLiteral( "gauss" );
620 }
621 // should not happen
622 return QStringLiteral( "nearestNeighbour" );
623}
624
625void QgsRasterDataProvider::writeXml( QDomDocument &doc, QDomElement &parentElem ) const
626{
627 QDomElement providerElement = doc.createElement( QStringLiteral( "provider" ) );
628 parentElem.appendChild( providerElement );
629
630 QDomElement resamplingElement = doc.createElement( QStringLiteral( "resampling" ) );
631 providerElement.appendChild( resamplingElement );
632
633 resamplingElement.setAttribute( QStringLiteral( "enabled" ),
634 mProviderResamplingEnabled ? QStringLiteral( "true" ) : QStringLiteral( "false" ) );
635
636 resamplingElement.setAttribute( QStringLiteral( "zoomedInResamplingMethod" ),
637 resamplingMethodToString( mZoomedInResamplingMethod ) );
638
639 resamplingElement.setAttribute( QStringLiteral( "zoomedOutResamplingMethod" ),
640 resamplingMethodToString( mZoomedOutResamplingMethod ) );
641
642 resamplingElement.setAttribute( QStringLiteral( "maxOversampling" ),
643 QString::number( mMaxOversampling ) );
644}
645
647{
648 try
649 {
650 return mAttributeTables.at( bandNumber ).get();
651 }
652 catch ( std::out_of_range const & )
653 {
654 return nullptr;
655 }
656}
657
659{
660 if ( attributeTable )
661 {
662 mAttributeTables[ bandNumber ] = std::unique_ptr<QgsRasterAttributeTable>( attributeTable );
663 }
664 else
665 {
666 removeAttributeTable( bandNumber );
667 }
668}
669
671{
672 if ( mAttributeTables.find( bandNumber ) != std::end( mAttributeTables ) )
673 {
674 mAttributeTables.erase( bandNumber );
675 }
676}
677
678bool QgsRasterDataProvider::writeFileBasedAttributeTable( int bandNumber, const QString &path, QString *errorMessage ) const
679{
680
681 QgsRasterAttributeTable *rat { attributeTable( bandNumber ) };
682 if ( ! rat )
683 {
684 if ( errorMessage )
685 {
686 *errorMessage = QObject::tr( "Raster has no Raster Attribute Table for band %1" ).arg( bandNumber );
687 }
688 return false;
689 }
690
691 return rat->writeToFile( path, errorMessage );
692}
693
695{
696 if ( errorMessage )
697 {
698 *errorMessage = QObject::tr( "Raster data provider has no native Raster Attribute Table support." );
699 }
700 return false;
701}
702
703bool QgsRasterDataProvider::readFileBasedAttributeTable( int bandNumber, const QString &path, QString *errorMessage )
704{
705 std::unique_ptr<QgsRasterAttributeTable> rat = std::make_unique<QgsRasterAttributeTable>();
706 if ( rat->readFromFile( path, errorMessage ) )
707 {
708 setAttributeTable( bandNumber, rat.release() );
709 return true;
710 }
711 else
712 {
713 return false;
714 }
715}
716
717bool QgsRasterDataProvider::writeNativeAttributeTable( QString *errorMessage ) //#spellok
718{
719 Q_UNUSED( errorMessage );
720 return false;
721}
722
724{
725 return colorName( colorInterpretation( bandNo ) );
726}
727
729{
730 QUrl url = QUrl::fromPercentEncoding( uri.toUtf8() );
731 const QUrlQuery query( url.query() );
732 VirtualRasterParameters components;
733
734 if ( ! query.hasQueryItem( QStringLiteral( "crs" ) ) )
735 {
736 QgsDebugMsg( "crs is missing" );
737 if ( ok ) *ok = false;
738 return components;
739 }
740 if ( ! components.crs.createFromString( query.queryItemValue( QStringLiteral( "crs" ) ) ) )
741 {
742 QgsDebugMsg( "failed to create crs" );
743 if ( ok ) *ok = false;
744 return components;
745 }
746
747
748 if ( ! query.hasQueryItem( QStringLiteral( "extent" ) ) )
749 {
750 QgsDebugMsg( "extent is missing" );
751 if ( ok ) *ok = false;
752 return components;
753 }
754 QStringList pointValuesList = query.queryItemValue( QStringLiteral( "extent" ) ).split( ',' );
755 if ( pointValuesList.size() != 4 )
756 {
757 QgsDebugMsg( "the extent is not correct" );
758 if ( ok ) *ok = false;
759 return components;
760 }
761 components.extent = QgsRectangle( pointValuesList.at( 0 ).toDouble(), pointValuesList.at( 1 ).toDouble(),
762 pointValuesList.at( 2 ).toDouble(), pointValuesList.at( 3 ).toDouble() );
763
764 if ( ! query.hasQueryItem( QStringLiteral( "width" ) ) )
765 {
766 QgsDebugMsg( "width is missing" );
767 if ( ok ) *ok = false;
768 return components;
769 }
770 bool flagW;
771 components.width = query.queryItemValue( QStringLiteral( "width" ) ).toInt( & flagW );
772 if ( !flagW || components.width < 0 )
773 {
774 QgsDebugMsg( "invalid or negative width input" );
775 if ( ok ) *ok = false;
776 return components;
777 }
778
779 if ( ! query.hasQueryItem( QStringLiteral( "height" ) ) )
780 {
781 QgsDebugMsg( "height is missing" );
782 if ( ok ) *ok = false;
783 return components;
784 }
785 bool flagH;
786 components.height = query.queryItemValue( QStringLiteral( "height" ) ).toInt( & flagH );
787 if ( !flagH || components.height < 0 )
788 {
789 QgsDebugMsg( "invalid or negative width input" );
790 if ( ok ) *ok = false;
791 return components;
792 }
793
794 if ( ! query.hasQueryItem( QStringLiteral( "formula" ) ) )
795 {
796 QgsDebugMsg( "formula is missing" );
797 if ( ok ) *ok = false;
798 return components;
799 }
800 components.formula = query.queryItemValue( QStringLiteral( "formula" ) );
801
802 for ( const auto &item : query.queryItems() )
803 {
804 if ( !( item.first.mid( item.first.indexOf( ':' ), -1 ) == QLatin1String( ":uri" ) ) )
805 {
806 continue;
807 }
808
810 rLayer.name = item.first.mid( 0, item.first.indexOf( ':' ) );
811 rLayer.uri = query.queryItemValue( item.first );
812 rLayer.provider = query.queryItemValue( item.first.mid( 0, item.first.indexOf( ':' ) ) + QStringLiteral( ":provider" ) );
813
814 if ( rLayer.uri.isNull() || rLayer.provider.isNull() )
815 {
816 QgsDebugMsg( "One or more raster information are missing" );
817 if ( ok ) *ok = false;
818 return components;
819 }
820
821 components.rInputLayers.append( rLayer ) ;
822
823 }
824
825 if ( ok ) *ok = true;
826 return components;
827}
828
830{
831 QUrl uri;
832 QUrlQuery query;
833
834 if ( parts.crs.isValid() )
835 {
836 query.addQueryItem( QStringLiteral( "crs" ), parts.crs.authid() );
837 }
838
839 if ( ! parts.extent.isNull() )
840 {
841 QString rect = QString( "%1,%2,%3,%4" ).arg( qgsDoubleToString( parts.extent.xMinimum() ), qgsDoubleToString( parts.extent.yMinimum() ),
843
844 query.addQueryItem( QStringLiteral( "extent" ), rect );
845 }
846
847 query.addQueryItem( QStringLiteral( "width" ), QString::number( parts.width ) );
848
849 query.addQueryItem( QStringLiteral( "height" ), QString::number( parts.height ) );
850
851 query.addQueryItem( QStringLiteral( "formula" ), parts.formula );
852
853 if ( ! parts.rInputLayers.isEmpty() )
854 {
855 for ( const auto &it : parts.rInputLayers )
856 {
857 query.addQueryItem( it.name + QStringLiteral( ":uri" ), it.uri );
858 query.addQueryItem( it.name + QStringLiteral( ":provider" ), it.provider );
859 }
860 }
861 uri.setQuery( query );
862 return QString( QUrl::toPercentEncoding( uri.toEncoded() ) );
863}
DataType
Raster data types.
Definition: qgis.h:129
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:59
double y
Definition: qgspointxy.h:63
Q_GADGET double x
Definition: qgspointxy.h:62
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 setNoDataValue(double noDataValue) SIP_HOLDGIL
Sets cell value that will be considered as "no data".
void setValid(bool valid) SIP_HOLDGIL
Mark block as valid or invalid.
int width() const SIP_HOLDGIL
Returns the width (number of columns) 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.
void applyNoDataValues(const QgsRasterRangeList &rangeList)
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.
int height() const SIP_HOLDGIL
Returns the height (number of rows) of the raster block.
bool setIsNoData(int row, int column) SIP_HOLDGIL
Set no data on pixel.
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.
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 QgsRaster::IdentifyFormat identifyFormatFromName(const QString &formatName)
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 NULL) 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.
QString colorName(int colorInterpretation) const
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 QgsRasterIdentifyResult identify(const QgsPointXY &point, QgsRaster::IdentifyFormat format, const QgsRectangle &boundingBox=QgsRectangle(), int width=0, int height=0, int dpi=96)
Identify raster value(s) found on the point position.
virtual QgsRasterDataProvider::ProviderCapabilities providerCapabilities() const
Returns flags containing the supported capabilities of the data provider.
virtual bool isEditable() const
Checks whether the provider is in editing mode, i.e.
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.
static Capability identifyFormatToCapability(QgsRaster::IdentifyFormat format)
bool hasPyramids()
Returns true if raster has at least one existing pyramid.
virtual double bandScale(int bandNo) const
Read band scale for raster value.
static QString identifyFormatName(QgsRaster::IdentifyFormat format)
@ NoProviderCapabilities
Provider has no capabilities.
int dpi() const
Returns the dpi of the output device.
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.
static QString identifyFormatLabel(QgsRaster::IdentifyFormat format)
QgsRasterBlock * block(int bandNo, const QgsRectangle &boundingBox, int width, int height, QgsRasterBlockFeedback *feedback=nullptr) override
Read block of data using given extent and size.
virtual int colorInterpretation(int bandNo) const
Returns data type for the band specified by number.
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.
QgsRasterDataProvider()
Provider capabilities.
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...
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 bool write(void *data, int band, int width, int height, int xOffset, int yOffset)
Writes into the provider datasource.
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.
QList< QgsRasterBandStats > mStatistics
List of cached statistics, all bands mixed.
Capability
If you add to this, please also add to capabilitiesString()
@ IdentifyValue
Numerical values.
@ IdentifyFeature
WMS GML -> feature.
@ Size
Original data source size (and thus resolution) is known, it is not always available,...
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 capabilities() const
Returns a bitmask containing the supported capabilities.
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.
IdentifyFormat
Definition: qgsraster.h:58
@ IdentifyFormatFeature
Definition: qgsraster.h:63
@ IdentifyFormatValue
Definition: qgsraster.h:60
@ IdentifyFormatText
Definition: qgsraster.h:61
@ IdentifyFormatUndefined
Definition: qgsraster.h:59
@ IdentifyFormatHtml
Definition: qgsraster.h:62
@ UndefinedColorInterpretation
Definition: qgsraster.h:37
A rectangle specified with double values.
Definition: qgsrectangle.h:42
QString toString(int precision=16) const
Returns a string representation of form xmin,ymin : xmax,ymax Coordinates will be truncated to the sp...
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:193
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:183
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:188
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:198
void setYMinimum(double y) SIP_HOLDGIL
Set the minimum y value.
Definition: qgsrectangle.h:161
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
Definition: qgsrectangle.h:479
void setXMaximum(double x) SIP_HOLDGIL
Set the maximum x value.
Definition: qgsrectangle.h:156
void setXMinimum(double x) SIP_HOLDGIL
Set the minimum x value.
Definition: qgsrectangle.h:151
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
Definition: qgsrectangle.h:230
void setYMaximum(double y) SIP_HOLDGIL
Set the maximum y value.
Definition: qgsrectangle.h:166
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
Definition: qgsrectangle.h:223
bool isEmpty() const
Returns true if the rectangle is empty.
Definition: qgsrectangle.h:469
#define str(x)
Definition: qgis.cpp:37
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition: qgis.h:2854
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:3470
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:2915
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
#define ERR(message)
QList< QgsRasterRange > QgsRasterRangeList
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