QGIS API Documentation 4.3.0-Master (dc0ce6e99ce)
Loading...
Searching...
No Matches
qgsrasterlayer.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsrasterlayer.cpp - description
3 -------------------
4begin : Sat Jun 22 2002
5copyright : (C) 2003 by Tim Sutton, Steve Halasz and Gary E.Sherman
6email : tim at linfiniti.com
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#include "qgsrasterlayer.h"
18
19#include <cmath>
20#include <cstdio>
21#include <limits>
22#include <typeinfo>
23
24#include "qgsapplication.h"
27#include "qgscolorrampshader.h"
30#include "qgsdatasourceuri.h"
31#include "qgsgdalprovider.h"
34#include "qgslogger.h"
35#include "qgsmaplayerfactory.h"
36#include "qgsmaplayerlegend.h"
37#include "qgsmaptopixel.h"
38#include "qgsmessagelog.h"
40#include "qgspainting.h"
41#include "qgspathresolver.h"
43#include "qgsproviderregistry.h"
45#include "qgsrasterdrawer.h"
46#include "qgsrasteriterator.h"
47#include "qgsrasterlabeling.h"
52#include "qgsrasterlayerutils.h"
53#include "qgsrasterpipe.h"
54#include "qgsrasterprojector.h"
55#include "qgsrasterrange.h"
58#include "qgsrastershader.h"
59#include "qgsreadwritecontext.h"
60#include "qgsrectangle.h"
61#include "qgsrendercontext.h"
62#include "qgsruntimeprofiler.h"
63#include "qgssettings.h"
65#include "qgssettingstree.h"
68#include "qgssldexportcontext.h"
69#include "qgssymbollayerutils.h"
70#include "qgsthreadingutils.h"
71#include "qgsxmlutils.h"
72
73#include <QApplication>
74#include <QCursor>
75#include <QDir>
76#include <QDomElement>
77#include <QDomNode>
78#include <QFile>
79#include <QFileInfo>
80#include <QFont>
81#include <QFontMetrics>
82#include <QFrame>
83#include <QImage>
84#include <QLabel>
85#include <QList>
86#include <QPainter>
87#include <QPixmap>
88#include <QRegularExpression>
89#include <QSlider>
90#include <QString>
91#include <QUrl>
92
93#include "moc_qgsrasterlayer.cpp"
94
95using namespace Qt::StringLiterals;
96
100 = new QgsSettingsEntryString( u"default-zoomed-in-resampling"_s, QgsSettingsTree::sTreeRaster, u"nearest neighbour"_s, u"Default zoomed-in resampling method for raster layers"_s );
102 = new QgsSettingsEntryString( u"default-zoomed-out-resampling"_s, QgsSettingsTree::sTreeRaster, u"nearest neighbour"_s, u"Default zoomed-out resampling method for raster layers"_s );
104 = new QgsSettingsEntryString( u"default-contrast-enhancement-algorithm/%1"_s, QgsSettingsTree::sTreeRaster, QString(), u"Default contrast enhancement algorithm per renderer type (singleBand, multiBandSingleByte, multiBandMultiByte)"_s );
106 = new QgsSettingsEntryString( u"default-contrast-enhancement-limits/%1"_s, QgsSettingsTree::sTreeRaster, QString(), u"Default contrast enhancement limits per renderer type (singleBand, multiBandSingleByte, multiBandMultiByte)"_s );
107
108#define ERR( message ) QGS_ERROR_MESSAGE( message, "Raster layer" )
109
110const double QgsRasterLayer::SAMPLE_SIZE = 250000;
111
115
119
121 : QgsMapLayer( Qgis::LayerType::Raster )
122 , QSTRING_NOT_SET( u"Not Set"_s )
123 , TRSTRING_NOT_SET( tr( "Not Set" ) )
124 , mTemporalProperties( new QgsRasterLayerTemporalProperties( this ) )
125 , mElevationProperties( new QgsRasterLayerElevationProperties( this ) )
126 , mPipe( std::make_unique< QgsRasterPipe >() )
127{
128 init();
129 setValid( false );
130}
131
132QgsRasterLayer::QgsRasterLayer( const QString &uri, const QString &baseName, const QString &providerKey, const LayerOptions &options )
133 : QgsMapLayer( Qgis::LayerType::Raster, baseName, uri )
134 // Constant that signals property not used.
135 , QSTRING_NOT_SET( u"Not Set"_s )
136 , TRSTRING_NOT_SET( tr( "Not Set" ) )
137 , mTemporalProperties( new QgsRasterLayerTemporalProperties( this ) )
138 , mElevationProperties( new QgsRasterLayerElevationProperties( this ) )
139 , mPipe( std::make_unique< QgsRasterPipe >() )
140{
142
143 QgsDebugMsgLevel( u"Entered"_s, 4 );
144 setProviderType( providerKey );
145
146 const QgsDataProvider::ProviderOptions providerOptions { options.transformContext };
147 Qgis::DataProviderReadFlags providerFlags;
148 if ( options.loadDefaultStyle )
149 {
151 }
152
153 setDataSource( uri, baseName, providerKey, providerOptions, providerFlags );
154
155 if ( isValid() )
156 {
157 mTemporalProperties->setDefaultsFromDataProviderTemporalCapabilities( mDataProvider->temporalCapabilities() );
158 }
159
160} // QgsRasterLayer ctor
161
163{
164 emit willBeDeleted();
165
166 mLabeling.reset();
167
168 setValid( false );
169 // Note: provider and other interfaces are owned and deleted by pipe
170}
171
173{
175
177 if ( mDataProvider )
178 {
179 options.transformContext = mDataProvider->transformContext();
180 }
181 auto layer = std::make_unique< QgsRasterLayer >( source(), name(), mProviderKey, options );
182 QgsMapLayer::clone( layer.get() );
183 layer->mElevationProperties = mElevationProperties->clone();
184 layer->mElevationProperties->setParent( layer.get() );
185 layer->setMapTipTemplate( mapTipTemplate() );
186 layer->setMapTipsEnabled( mapTipsEnabled() );
187
188 // do not clone data provider which is the first element in pipe
189 for ( int i = 1; i < mPipe->size(); i++ )
190 {
191 if ( mPipe->at( i ) )
192 layer->pipe()->set( mPipe->at( i )->clone() );
193 }
194 layer->pipe()->setDataDefinedProperties( mPipe->dataDefinedProperties() );
195 layer->setResamplingStage( mPipe->resamplingStage() );
196 if ( mDataProvider && layer->dataProvider() )
197 {
198 layer->dataProvider()->setZoomedInResamplingMethod( mDataProvider->zoomedInResamplingMethod() );
199 layer->dataProvider()->setZoomedOutResamplingMethod( mDataProvider->zoomedOutResamplingMethod() );
200 }
201
202 layer->setLabelsEnabled( mLabelsEnabled );
203 if ( mLabeling )
204 layer->setLabeling( mLabeling->clone() );
205
206 return layer.release();
207}
208
210{
212
213 if ( !mElevationProperties->isEnabled() )
214 return nullptr;
215
216 return new QgsRasterLayerProfileGenerator( this, request );
217}
218
220//
221// Static Methods and members
222//
224
225bool QgsRasterLayer::isValidRasterFileName( const QString &fileNameQString, QString &retErrMsg )
226{
227 const bool myIsValid = QgsGdalProvider::isValidRasterFileName( fileNameQString, retErrMsg );
228 return myIsValid;
229}
230
231bool QgsRasterLayer::isValidRasterFileName( QString const &fileNameQString )
232{
233 QString retErrMsg;
234 return isValidRasterFileName( fileNameQString, retErrMsg );
235}
236
237QDateTime QgsRasterLayer::lastModified( QString const &name )
238{
239 QgsDebugMsgLevel( "name=" + name, 4 );
240 QDateTime t;
241
242 const QFileInfo fi( name );
243
244 // Is it file?
245 if ( !fi.exists() )
246 return t;
247
248 t = fi.lastModified();
249
250 QgsDebugMsgLevel( "last modified = " + t.toString(), 4 );
251
252 return t;
253}
254
261
262// typedef for the QgsDataProvider class factory
264
266//
267// Non Static Public methods
268//
270
272{
274
275 if ( !mDataProvider )
276 return 0;
277 return mDataProvider->bandCount();
278}
279
280QString QgsRasterLayer::bandName( int bandNo ) const
281{
283
284 if ( !mDataProvider )
285 return QString();
286 return mDataProvider->generateBandName( bandNo );
287}
288
290{
292
293 if ( !mDataProvider )
294 return nullptr;
295 return mDataProvider->attributeTable( bandNoInt );
296}
297
299{
301
302 if ( !mDataProvider )
303 return 0;
304
305 int ratCount { 0 };
306 for ( int bandNo = 1; bandNo <= bandCount(); ++bandNo )
307 {
308 if ( attributeTable( bandNo ) )
309 {
310 ratCount++;
311 }
312 }
313 return ratCount;
314}
315
322
323void QgsRasterLayer::setRendererForDrawingStyle( Qgis::RasterDrawingStyle drawingStyle )
324{
326
327 setRenderer( QgsApplication::rasterRendererRegistry()->defaultRendererForDrawingStyle( drawingStyle, mDataProvider ) );
328}
329
336
338{
340
341 return mDataProvider;
342}
343
345{
347
348 if ( mDataProvider )
349 {
350 mDataProvider->reloadData();
351
352 if ( mDataProvider->isValid() )
353 {
354 const QgsRectangle extent = mDataProvider->extent();
355 if ( !extent.isNull() )
356 {
357 setExtent( extent );
358 }
359 }
360 }
361}
362
369
370
371void QgsRasterLayer::draw( QPainter *theQPainter, QgsRasterViewPort *rasterViewPort, const QgsMapToPixel *qgsMapToPixel )
372{
374
375 QgsDebugMsgLevel( u" 3 arguments"_s, 4 );
376 QElapsedTimer time;
377 time.start();
378 //
379 //
380 // The goal here is to make as many decisions as possible early on (outside of the rendering loop)
381 // so that we can maximise performance of the rendering process. So now we check which drawing
382 // procedure to use :
383 //
384
385 QgsRasterProjector *projector = mPipe->projector();
386 bool restoreOldResamplingStage = false;
387 const Qgis::RasterResamplingStage oldResamplingState = resamplingStage();
388 // TODO add a method to interface to get provider and get provider
389 // params in QgsRasterProjector
390
391 if ( projector )
392 {
393 // Force provider resampling if reprojection is needed
394 if ( mDataProvider
395 && ( mDataProvider->providerCapabilities() & Qgis::RasterProviderCapability::ProviderHintCanPerformProviderResampling )
396 && rasterViewPort->mSrcCRS != rasterViewPort->mDestCRS
397 && oldResamplingState != Qgis::RasterResamplingStage::Provider )
398 {
399 restoreOldResamplingStage = true;
401 }
402 projector->setCrs( rasterViewPort->mSrcCRS, rasterViewPort->mDestCRS, rasterViewPort->mTransformContext );
403 }
404
405 // Drawer to pipe?
406 QgsRasterIterator iterator( mPipe->last() );
407 QgsRasterDrawer drawer( &iterator );
408 drawer.draw( theQPainter, rasterViewPort, qgsMapToPixel );
409
410 if ( restoreOldResamplingStage )
411 {
412 setResamplingStage( oldResamplingState );
413 }
414
415 QgsDebugMsgLevel( u"total raster draw time (ms): %1"_s.arg( time.elapsed(), 5 ), 4 );
416}
417
419{
421
422 QgsRasterRenderer *renderer = mPipe->renderer();
423 return renderer ? renderer->legendSymbologyItems() : QList< QPair< QString, QColor > >();
424 ;
425}
426
428{
430
431 if ( !mDataProvider )
432 return QString();
433
434 const QgsLayerMetadataFormatter htmlFormatter( metadata() );
435 QString myMetadata = u"<html><head></head>\n<body>\n"_s;
436
437 myMetadata += generalHtmlMetadata();
438
439 // Begin Provider section
440 myMetadata += u"<h1>"_s + tr( "Information from provider" ) + u"</h1>\n<hr>\n"_s + u"<table class=\"list-view\">\n"_s;
441
442 myMetadata += u"\n"_s
443 %
444 // Extent
445 u"<tr><td class=\"highlight\">"_s
446 % tr( "Extent" )
447 % u"</td><td>"_s
448 % extent().toString()
449 % u"</td></tr>\n"_s
450 %
451
452 // Raster Width
453 u"<tr><td class=\"highlight\">"_s % tr( "Width" ) % u"</td><td>"_s;
454 if ( dataProvider()->capabilities() & Qgis::RasterInterfaceCapability::Size )
455 myMetadata += QString::number( width() );
456 else
457 myMetadata += tr( "n/a" );
458 myMetadata += u"</td></tr>\n"_s %
459
460 // Raster height
461 u"<tr><td class=\"highlight\">"_s
462 + tr( "Height" )
463 + u"</td><td>"_s;
464 if ( dataProvider()->capabilities() & Qgis::RasterInterfaceCapability::Size )
465 myMetadata += QString::number( height() );
466 else
467 myMetadata += tr( "n/a" );
468 myMetadata += u"</td></tr>\n"_s
469 %
470
471 // Data type
472 u"<tr><td class=\"highlight\">"_s % tr( "Data type" ) % u"</td><td>"_s;
473 // Just use the first band
474 switch ( mDataProvider->sourceDataType( 1 ) )
475 {
477 myMetadata += tr( "Byte - Eight bit unsigned integer" );
478 break;
480 myMetadata += tr( "Int8 - Eight bit signed integer" );
481 break;
483 myMetadata += tr( "UInt16 - Sixteen bit unsigned integer " );
484 break;
486 myMetadata += tr( "Int16 - Sixteen bit signed integer " );
487 break;
489 myMetadata += tr( "UInt32 - Thirty two bit unsigned integer " );
490 break;
492 myMetadata += tr( "Int32 - Thirty two bit signed integer " );
493 break;
495 myMetadata += tr( "Float32 - Thirty two bit floating point " );
496 break;
498 myMetadata += tr( "Float64 - Sixty four bit floating point " );
499 break;
501 myMetadata += tr( "CInt16 - Complex Int16 " );
502 break;
504 myMetadata += tr( "CInt32 - Complex Int32 " );
505 break;
507 myMetadata += tr( "CFloat32 - Complex Float32 " );
508 break;
510 myMetadata += tr( "CFloat64 - Complex Float64 " );
511 break;
512 default:
513 myMetadata += tr( "Could not determine raster data type." );
514 }
515 myMetadata += u"</td></tr>\n"_s
516 %
517
518 // Insert provider-specific (e.g. WMS-specific) metadata
519 mDataProvider->htmlMetadata()
520 %
521
522 // End Provider section
523 u"</table>\n<br><br>"_s;
524
525 // CRS
526 myMetadata += crsHtmlMetadata();
527
528 // Identification section
529 myMetadata += u"<h1>"_s
530 % tr( "Identification" )
531 % u"</h1>\n<hr>\n"_s
532 % htmlFormatter.identificationSectionHtml()
533 % u"<br><br>\n"_s
534 %
535
536 // extent section
537 u"<h1>"_s
538 % tr( "Extent" )
539 % u"</h1>\n<hr>\n"_s
540 % htmlFormatter.extentSectionHtml()
541 % u"<br><br>\n"_s
542 %
543
544 // Start the Access section
545 u"<h1>"_s
546 % tr( "Access" )
547 % u"</h1>\n<hr>\n"_s
548 % htmlFormatter.accessSectionHtml()
549 % u"<br><br>\n"_s
550 %
551
552 // Bands section
553 u"</table>\n<br><br><h1>"_s
554 % tr( "Bands" )
555 % u"</h1>\n<hr>\n<table class=\"list-view\">\n"_s
556 %
557
558 // Band count
559 u"<tr><td class=\"highlight\">"_s % tr( "Band count" ) % u"</td><td>"_s % QString::number( bandCount() ) % u"</td></tr>\n"_s;
560
561 // Band table
562 myMetadata += u"</table>\n<br><table width=\"100%\" class=\"tabular-view\">\n"_s
563 % u"<tr><th>"_s
564 % tr( "Number" )
565 % u"</th><th>"_s
566 % tr( "Band" )
567 % u"</th><th>"_s
568 % tr( "NoData" )
569 % u"</th><th>"_s
570 % tr( "Min" )
571 % u"</th><th>"_s
572 % tr( "Max" )
573 % u"</th></tr>\n"_s;
574
575 QgsRasterDataProvider *provider = const_cast< QgsRasterDataProvider * >( mDataProvider );
576 for ( int i = 1; i <= bandCount(); i++ )
577 {
578 QString rowClass;
579 if ( i % 2 )
580 rowClass = u"class=\"odd-row\""_s;
581
582 myMetadata += u"<tr "_s % rowClass % u"><td>"_s % QString::number( i ) % u"</td><td>"_s % bandName( i ) % u"</td><td>"_s;
583
584 if ( dataProvider()->sourceHasNoDataValue( i ) )
585 myMetadata += QString::number( dataProvider()->sourceNoDataValue( i ) );
586 else
587 myMetadata += tr( "n/a" );
588 myMetadata += "</td>"_L1;
589
590 if ( provider->hasStatistics( i, Qgis::RasterBandStatistic::Min | Qgis::RasterBandStatistic::Max, provider->extent(), static_cast<int>( SAMPLE_SIZE ) ) )
591 {
592 const QgsRasterBandStats myRasterBandStats = provider->bandStatistics( i, Qgis::RasterBandStatistic::Min | Qgis::RasterBandStatistic::Max, provider->extent(), static_cast<int>( SAMPLE_SIZE ) );
593 myMetadata += u"<td>"_s % QString::number( myRasterBandStats.minimumValue, 'f', 10 ) % u"</td>"_s % u"<td>"_s % QString::number( myRasterBandStats.maximumValue, 'f', 10 ) % u"</td>"_s;
594 }
595 else
596 {
597 myMetadata += u"<td>"_s % tr( "n/a" ) % u"</td><td>"_s % tr( "n/a" ) % u"</td>"_s;
598 }
599
600 myMetadata += "</tr>\n"_L1;
601 }
602
603 //close previous bands table
604 myMetadata += u"</table>\n<br><br>"_s
605 %
606
607 // Start the contacts section
608 u"<h1>"_s
609 % tr( "Contacts" )
610 % u"</h1>\n<hr>\n"_s
611 % htmlFormatter.contactsSectionHtml()
612 % u"<br><br>\n"_s
613 %
614
615 // Start the links section
616 u"<h1>"_s
617 % tr( "References" )
618 % u"</h1>\n<hr>\n"_s
619 % htmlFormatter.linksSectionHtml()
620 % u"<br><br>\n"_s
621 %
622
623 // Start the history section
624 u"<h1>"_s % tr( "History" ) % u"</h1>\n<hr>\n"_s % htmlFormatter.historySectionHtml() % u"<br><br>\n"_s % customPropertyHtmlMetadata() % u"\n</body>\n</html>\n"_s;
625 return myMetadata;
626}
627
629{
631
633 if ( mDataProvider && ( mDataProvider->flags() & Qgis::DataProviderFlag::IsBasemapSource ) )
634 {
636 }
637 return res;
638}
639
640QPixmap QgsRasterLayer::paletteAsPixmap( int bandNumber )
641{
643
644 //TODO: This function should take dimensions
645 QgsDebugMsgLevel( u"entered."_s, 4 );
646
647 // Only do this for the GDAL provider?
648 // Maybe WMS can do this differently using QImage::numColors and QImage::color()
649 if ( mDataProvider && mDataProvider->colorInterpretation( bandNumber ) == Qgis::RasterColorInterpretation::PaletteIndex )
650 {
651 QgsDebugMsgLevel( u"....found paletted image"_s, 4 );
652 QgsColorRampShader myShader;
653 const QList<QgsColorRampShader::ColorRampItem> myColorRampItemList = mDataProvider->colorTable( bandNumber );
654 if ( !myColorRampItemList.isEmpty() )
655 {
656 QgsDebugMsgLevel( u"....got color ramp item list"_s, 4 );
657 myShader.setColorRampItemList( myColorRampItemList );
659 // Draw image
660 const int mySize = 100;
661 QPixmap myPalettePixmap( mySize, mySize );
662 QPainter myQPainter( &myPalettePixmap );
663
664 QImage myQImage = QImage( mySize, mySize, QImage::Format_RGB32 );
665 myQImage.fill( 0 );
666 myPalettePixmap.fill();
667
668 const double myStep = ( static_cast< double >( myColorRampItemList.size() ) - 1 ) / static_cast< double >( mySize * mySize );
669 double myValue = 0.0;
670 for ( int myRow = 0; myRow < mySize; myRow++ )
671 {
672 QRgb *myLineBuffer = reinterpret_cast< QRgb * >( myQImage.scanLine( myRow ) );
673 for ( int myCol = 0; myCol < mySize; myCol++ )
674 {
675 myValue = myStep * static_cast< double >( myCol + myRow * mySize );
676 int c1, c2, c3, c4;
677 myShader.shade( myValue, &c1, &c2, &c3, &c4 );
678 myLineBuffer[myCol] = qRgba( c1, c2, c3, c4 );
679 }
680 }
681
682 myQPainter.drawImage( 0, 0, myQImage );
683 return myPalettePixmap;
684 }
685 const QPixmap myNullPixmap;
686 return myNullPixmap;
687 }
688 else
689 {
690 //invalid layer was requested
691 const QPixmap myNullPixmap;
692 return myNullPixmap;
693 }
694}
695
697{
699
700 // We return one raster pixel per map unit pixel
701 // One raster pixel can have several raster units...
702
703 // We can only use one of the mGeoTransform[], so go with the
704 // horisontal one.
705
706 if ( mDataProvider && mDataProvider->capabilities() & Qgis::RasterInterfaceCapability::Size && !qgsDoubleNear( mDataProvider->xSize(), 0.0 ) )
707 {
708 return mDataProvider->extent().width() / mDataProvider->xSize();
709 }
710 return 1;
711}
712
714{
716
717 if ( mDataProvider && mDataProvider->capabilities() & Qgis::RasterInterfaceCapability::Size && !qgsDoubleNear( mDataProvider->ySize(), 0.0 ) )
718 {
719 return mDataProvider->extent().height() / mDataProvider->ySize();
720 }
721 return 1;
722}
723
725{
727
728 if ( !mPipe->renderer() || mPipe->renderer()->opacity() == opacity )
729 return;
730
731 mPipe->renderer()->setOpacity( opacity );
732 emit opacityChanged( opacity );
734}
735
737{
739
740 return mPipe->renderer() ? mPipe->renderer()->opacity() : 1.0;
741}
742
743void QgsRasterLayer::init()
744{
746
748
749 whileBlocking( this )->setLegend( QgsMapLayerLegend::defaultRasterLegend( this ) );
750
751 setRendererForDrawingStyle( Qgis::RasterDrawingStyle::Undefined );
752
753 //Initialize the last view port structure, should really be a class
754 mLastViewPort.mWidth = 0;
755 mLastViewPort.mHeight = 0;
756}
757
759{
761
762 QgsDebugMsgLevel( u"Entered"_s, 4 );
763 setValid( false ); // assume the layer is invalid until we determine otherwise
764
765 // deletes pipe elements (including data provider)
766 mPipe = std::make_unique< QgsRasterPipe >();
767 mDataProvider = nullptr;
768
769 // XXX should I check for and possibly delete any pre-existing providers?
770 // XXX How often will that scenario occur?
771
772 mProviderKey = provider;
773 // set the layer name (uppercase first character)
774 if ( !mLayerName.isEmpty() ) // XXX shouldn't this happen in parent?
775 {
777 }
778
779 //mBandCount = 0;
780
781 if ( mPreloadedProvider )
782 {
783 mDataProvider = qobject_cast< QgsRasterDataProvider * >( mPreloadedProvider.release() );
784 }
785 else
786 {
787 std::unique_ptr< QgsScopedRuntimeProfile > profile;
788 if ( QgsApplication::profiler()->groupIsActive( u"projectload"_s ) )
789 profile = std::make_unique< QgsScopedRuntimeProfile >( tr( "Create %1 provider" ).arg( provider ), u"projectload"_s );
790
791 mDataProvider = qobject_cast< QgsRasterDataProvider * >( QgsProviderRegistry::instance()->createProvider( mProviderKey, mDataSource, options, flags ) );
792 }
793
794 if ( !mDataProvider )
795 {
796 //QgsMessageLog::logMessage( tr( "Cannot instantiate the data provider" ), tr( "Raster" ) );
797 appendError( ERR( tr( "Cannot instantiate the '%1' data provider" ).arg( mProviderKey ) ) );
798 return;
799 }
800 QgsDebugMsgLevel( u"Data provider created"_s, 4 );
801 mDataProvider->setParent( this );
802
803 // Set data provider into pipe even if not valid so that it is deleted with pipe (with layer)
804 if ( !mPipe->set( mDataProvider ) )
805 {
806 // data provider has been deleted by the pipe
807 mDataProvider = nullptr;
808 appendError( ERR( tr( "Could not insert provider into layer pipe (provider: %1, URI: %2)" ).arg( mProviderKey, mDataSource ) ) );
809 return;
810 }
811
812 if ( !mDataProvider->isValid() )
813 {
814 setError( mDataProvider->error() );
815 appendError( ERR( tr( "Provider is not valid (provider: %1, URI: %2)" ).arg( mProviderKey, mDataSource ) ) );
816 return;
817 }
818
819 if ( mDataProvider->providerCapabilities() & Qgis::RasterProviderCapability::ReadLayerMetadata )
820 {
821 setMetadata( mDataProvider->layerMetadata() );
822 QgsDebugMsgLevel( u"Set Data provider QgsLayerMetadata identifier[%1]"_s.arg( metadata().identifier() ), 4 );
823 }
824
825 if ( provider == "gdal"_L1 || provider == "wms"_L1 )
826 {
827 // if provider has updated its URI, make sure we store the updated one.
828 // TODO: this probably should be enabled for all provider, but we'll play it safe for now...
829 mDataSource = mDataProvider->dataSourceUri();
830 }
831
833 {
834 // get the extent
835 const QgsRectangle mbr = mDataProvider->extent();
836
837 // store the extent
838 setExtent( mbr );
839 }
840
841 // upper case the first letter of the layer name
842 QgsDebugMsgLevel( "mLayerName: " + name(), 4 );
843
844 // set up the raster drawing style
845 // Do not set any 'sensible' style here, the style is set later
846
847 // Setup source CRS
848 setCrs( QgsCoordinateReferenceSystem( mDataProvider->crs() ) );
849
850 QgsDebugMsgLevel( "using wkt:\n" + crs().toWkt( Qgis::CrsWktVariant::Preferred ), 4 );
851
852 //defaults - Needs to be set after the Contrast list has been build
853 //Try to read the default contrast enhancement from the config file
854
855 //decide what type of layer this is...
856 //TODO Change this to look at the color interp and palette interp to decide which type of layer it is
857 QgsDebugMsgLevel( "bandCount = " + QString::number( mDataProvider->bandCount() ), 4 );
858 QgsDebugMsgLevel( "dataType = " + qgsEnumValueToKey< Qgis::DataType >( mDataProvider->dataType( 1 ) ), 4 );
859 const int bandCount = mDataProvider->bandCount();
860 if ( bandCount > 2 )
861 {
863 }
864 else if ( bandCount == 2 )
865 {
866 // handle singleband gray and paletted with alpha
867 auto colorInterpretationIsGrayOrUndefined = []( Qgis::RasterColorInterpretation interpretation ) {
869 };
870
871 auto colorInterpretationIsPaletted = []( Qgis::RasterColorInterpretation interpretation ) {
873 };
874
875 if ( ( colorInterpretationIsGrayOrUndefined( mDataProvider->colorInterpretation( 1 ) ) && mDataProvider->colorInterpretation( 2 ) == Qgis::RasterColorInterpretation::AlphaBand )
876 || ( mDataProvider->colorInterpretation( 1 ) == Qgis::RasterColorInterpretation::AlphaBand && colorInterpretationIsGrayOrUndefined( mDataProvider->colorInterpretation( 2 ) ) ) )
877 {
879 }
880 else if ( ( colorInterpretationIsPaletted( mDataProvider->colorInterpretation( 1 ) ) && mDataProvider->colorInterpretation( 2 ) == Qgis::RasterColorInterpretation::AlphaBand )
881 || ( mDataProvider->colorInterpretation( 1 ) == Qgis::RasterColorInterpretation::AlphaBand && colorInterpretationIsPaletted( mDataProvider->colorInterpretation( 2 ) ) ) )
882 {
883 mRasterType = Qgis::RasterLayerType::Palette;
884 }
885 else
886 {
888 }
889 }
890 else if ( mDataProvider->dataType( 1 ) == Qgis::DataType::ARGB32 || mDataProvider->dataType( 1 ) == Qgis::DataType::ARGB32_Premultiplied )
891 {
893 }
894 else if ( mDataProvider->colorInterpretation( 1 ) == Qgis::RasterColorInterpretation::PaletteIndex || mDataProvider->colorInterpretation( 1 ) == Qgis::RasterColorInterpretation::ContinuousPalette )
895 {
896 mRasterType = Qgis::RasterLayerType::Palette;
897 }
898 else
899 {
901 }
902
903 QgsDebugMsgLevel( "mRasterType = " + qgsEnumValueToKey( mRasterType ), 4 );
904
905 // Raster Attribute Table logic to load from provider or same basename + vat.dbf file.
906 QString errorMessage;
907 bool hasRat { mDataProvider->readNativeAttributeTable( &errorMessage ) };
908 if ( !hasRat )
909 {
910 errorMessage.clear();
911 QgsDebugMsgLevel( "Native Raster Raster Attribute Table read failed " + errorMessage, 2 );
912 if ( QFile::exists( mDataProvider->dataSourceUri() + ".vat.dbf" ) )
913 {
914 auto rat = std::make_unique<QgsRasterAttributeTable>();
915 hasRat = rat->readFromFile( mDataProvider->dataSourceUri() + ".vat.dbf", &errorMessage );
916 if ( hasRat )
917 {
918 if ( rat->isValid( &errorMessage ) )
919 {
920 mDataProvider->setAttributeTable( 1, rat.release() );
921 QgsDebugMsgLevel( "DBF Raster Attribute Table successfully read from " + mDataProvider->dataSourceUri() + ".vat.dbf", 2 );
922 }
923 else
924 {
925 QgsDebugMsgLevel( "DBF Raster Attribute Table is not valid, skipping: " + errorMessage, 2 );
926 }
927 }
928 else
929 {
930 QgsDebugMsgLevel( "DBF Raster Attribute Table read failed " + errorMessage, 2 );
931 }
932 }
933 }
934 else
935 {
936 QgsDebugMsgLevel( "Native Raster Attribute Table read success", 2 );
937 }
938
939 switch ( mRasterType )
940 {
942 {
943 QgsDebugMsgLevel( "Setting drawing style to SingleBandColorDataStyle " + qgsEnumValueToKey( Qgis::RasterDrawingStyle::SingleBandColorData ), 4 );
944 setRendererForDrawingStyle( Qgis::RasterDrawingStyle::SingleBandColorData );
945 break;
946 }
948 {
949 if ( mDataProvider->colorInterpretation( 1 ) == Qgis::RasterColorInterpretation::PaletteIndex )
950 {
951 setRendererForDrawingStyle( Qgis::RasterDrawingStyle::PalettedColor ); //sensible default
952 }
953 else if ( mDataProvider->colorInterpretation( 1 ) == Qgis::RasterColorInterpretation::ContinuousPalette )
954 {
955 setRendererForDrawingStyle( Qgis::RasterDrawingStyle::SingleBandPseudoColor );
956 // Load color table
957 const QList<QgsColorRampShader::ColorRampItem> colorTable = mDataProvider->colorTable( 1 );
959 if ( r )
960 {
961 // TODO: this should go somewhere else
962 QgsRasterShader *shader = new QgsRasterShader();
963 QgsColorRampShader *colorRampShader = new QgsColorRampShader();
965 colorRampShader->setColorRampItemList( colorTable );
966 shader->setRasterShaderFunction( colorRampShader );
967 r->setShader( shader );
968 }
969 }
970 else
971 {
972 setRendererForDrawingStyle( Qgis::RasterDrawingStyle::SingleBandGray ); //sensible default
973 }
974 break;
975 }
977 {
978 setRendererForDrawingStyle( Qgis::RasterDrawingStyle::MultiBandColor ); //sensible default
979 break;
980 }
982 {
983 setRendererForDrawingStyle( Qgis::RasterDrawingStyle::SingleBandGray ); //sensible default
984 break;
985 }
986 }
987
988 // Auto set alpha band
989 for ( int bandNo = 1; bandNo <= mDataProvider->bandCount(); bandNo++ )
990 {
991 if ( mDataProvider->colorInterpretation( bandNo ) == Qgis::RasterColorInterpretation::AlphaBand )
992 {
993 if ( auto *lRenderer = mPipe->renderer() )
994 {
995 lRenderer->setAlphaBand( bandNo );
996 }
997 break;
998 }
999 }
1000
1001 // brightness filter
1003 mPipe->set( brightnessFilter );
1004
1005 // hue/saturation filter
1007 mPipe->set( hueSaturationFilter );
1008
1009 // resampler (must be after renderer)
1011 if ( mPipe->set( resampleFilter ) && mDataProvider->providerCapabilities() & Qgis::RasterProviderCapability::ProviderHintBenefitsFromResampling )
1012 {
1013 QString resampling = QgsRasterLayer::settingsRasterDefaultZoomedInResampling->value();
1014 if ( resampling == "bilinear"_L1 )
1015 {
1016 resampleFilter->setZoomedInResampler( new QgsBilinearRasterResampler() );
1017 mDataProvider->setZoomedInResamplingMethod( Qgis::RasterResamplingMethod::Bilinear );
1018 }
1019 else if ( resampling == "cubic"_L1 )
1020 {
1021 resampleFilter->setZoomedInResampler( new QgsCubicRasterResampler() );
1022 mDataProvider->setZoomedInResamplingMethod( Qgis::RasterResamplingMethod::Cubic );
1023 }
1025 if ( resampling == "bilinear"_L1 )
1026 {
1027 resampleFilter->setZoomedOutResampler( new QgsBilinearRasterResampler() );
1028 mDataProvider->setZoomedOutResamplingMethod( Qgis::RasterResamplingMethod::Bilinear );
1029 }
1030
1031 const double maxOversampling = QgsRasterLayer::settingsRasterDefaultOversampling->value();
1032 resampleFilter->setMaxOversampling( maxOversampling );
1033 mDataProvider->setMaxOversampling( maxOversampling );
1034
1036 {
1038 }
1039 else
1040 {
1042 }
1043 }
1044
1045 // projector (may be anywhere in pipe)
1046 QgsRasterProjector *projector = new QgsRasterProjector;
1047 mPipe->set( projector );
1048
1049 // Set default identify format - use the richest format available
1050 const Qgis::RasterInterfaceCapabilities capabilities = mDataProvider->capabilities();
1053 {
1054 // HTML is usually richest
1055 identifyFormat = Qgis::RasterIdentifyFormat::Html;
1056 }
1057 else if ( capabilities & Qgis::RasterInterfaceCapability::IdentifyFeature )
1058 {
1059 identifyFormat = Qgis::RasterIdentifyFormat::Feature;
1060 }
1061 else if ( capabilities & Qgis::RasterInterfaceCapability::IdentifyText )
1062 {
1063 identifyFormat = Qgis::RasterIdentifyFormat::Text;
1064 }
1065 else if ( capabilities & Qgis::RasterInterfaceCapability::IdentifyValue )
1066 {
1067 identifyFormat = Qgis::RasterIdentifyFormat::Value;
1068 }
1069 setCustomProperty( u"identify/format"_s, QgsRasterDataProvider::identifyFormatName( identifyFormat ) );
1070
1071 if ( QgsRasterDataProviderElevationProperties *properties = mDataProvider->elevationProperties() )
1072 {
1073 if ( properties->containsElevationData() )
1074 {
1075 mElevationProperties->setEnabled( true );
1076 }
1077 }
1078
1079 // Store timestamp
1080 // TODO move to provider
1081 mLastModified = lastModified( mDataSource );
1082
1083 // Do a passthrough for the status bar text
1085
1086 //mark the layer as valid
1087 setValid( true );
1088
1089 if ( mDataProvider->supportsSubsetString() )
1090 connect( this, &QgsRasterLayer::subsetStringChanged, this, &QgsMapLayer::configChanged, Qt::UniqueConnection );
1091 else
1093
1094
1095 QgsDebugMsgLevel( u"exiting."_s, 4 );
1096}
1097
1098void QgsRasterLayer::setDataSourcePrivate( const QString &dataSource, const QString &baseName, const QString &provider, const QgsDataProvider::ProviderOptions &options, Qgis::DataProviderReadFlags flags )
1099{
1101
1102 const bool hadRenderer( renderer() );
1103
1104 QDomImplementation domImplementation;
1105 QDomDocumentType documentType;
1106 QString errorMsg;
1107
1108 bool loadDefaultStyleFlag = false;
1110 {
1111 loadDefaultStyleFlag = true;
1112 }
1113
1114 // Store the original style
1115 if ( hadRenderer && !loadDefaultStyleFlag )
1116 {
1117 documentType = domImplementation.createDocumentType( u"qgis"_s, u"http://mrcc.com/qgis.dtd"_s, u"SYSTEM"_s );
1118
1119 QDomDocument doc = QDomDocument( documentType );
1120 QDomElement styleElem = doc.createElement( u"qgis"_s );
1121 styleElem.setAttribute( u"version"_s, Qgis::version() );
1122 const QgsReadWriteContext writeContext;
1123 if ( !writeSymbology( styleElem, doc, errorMsg, writeContext ) )
1124 {
1125 QgsDebugError( u"Could not store symbology for layer %1: %2"_s.arg( name(), errorMsg ) );
1126 }
1127 else
1128 {
1129 doc.appendChild( styleElem );
1130
1131 mOriginalStyleDocument = doc;
1132 mOriginalStyleElement = styleElem;
1133 }
1134 }
1135
1136 if ( mDataProvider )
1137 closeDataProvider();
1138
1139 init();
1140
1141 for ( int i = mPipe->size() - 1; i >= 0; --i )
1142 {
1143 mPipe->remove( i );
1144 }
1145
1146 mDataSource = dataSource;
1147 mLayerName = baseName;
1148
1149 setDataProvider( provider, options, flags );
1150
1151 if ( mDataProvider )
1152 mDataProvider->setDataSourceUri( mDataSource );
1153
1154 if ( isValid() )
1155 {
1156 // load default style
1157 bool defaultLoadedFlag = false;
1158 bool restoredStyle = false;
1159 if ( loadDefaultStyleFlag )
1160 {
1161 loadDefaultStyle( defaultLoadedFlag );
1162 }
1163 else if ( !mOriginalStyleElement.isNull() ) // Restore the style
1164 {
1165 QgsReadWriteContext readContext;
1166 if ( !readSymbology( mOriginalStyleElement, errorMsg, readContext ) )
1167 {
1168 QgsDebugError( u"Could not restore symbology for layer %1: %2"_s.arg( name() ).arg( errorMsg ) );
1169 }
1170 else
1171 {
1172 restoredStyle = true;
1173 emit repaintRequested();
1175 emit rendererChanged();
1176 }
1177 }
1178
1179 if ( !defaultLoadedFlag && !restoredStyle )
1180 {
1182 }
1183 }
1184}
1185
1186void QgsRasterLayer::writeRasterAttributeTableExternalPaths( QDomNode &layerNode, QDomDocument &doc, const QgsReadWriteContext &context ) const
1187{
1189
1190 if ( attributeTableCount() > 0 )
1191 {
1192 QDomElement elem = doc.createElement( u"FileBasedAttributeTables"_s );
1193 for ( int bandNo = 1; bandNo <= bandCount(); bandNo++ )
1194 {
1195 if ( QgsRasterAttributeTable *rat = attributeTable( bandNo ); rat && !rat->filePath().isEmpty() )
1196 {
1197 QDomElement ratElem = doc.createElement( u"AttributeTable"_s );
1198 ratElem.setAttribute( u"band"_s, bandNo );
1199 ratElem.setAttribute( u"path"_s, context.pathResolver().writePath( rat->filePath() ) );
1200 elem.appendChild( ratElem );
1201 }
1202 }
1203 layerNode.appendChild( elem );
1204 }
1205}
1206
1207void QgsRasterLayer::readRasterAttributeTableExternalPaths( const QDomNode &layerNode, QgsReadWriteContext &context ) const
1208{
1209 const QDomElement ratsElement = layerNode.firstChildElement( u"FileBasedAttributeTables"_s );
1210 if ( !ratsElement.isNull() && ratsElement.childNodes().count() > 0 )
1211 {
1212 const QDomNodeList ratElements { ratsElement.childNodes() };
1213 for ( int idx = 0; idx < ratElements.count(); idx++ )
1214 {
1215 const QDomNode ratElement { ratElements.at( idx ) };
1216 if ( ratElement.attributes().contains( u"band"_s ) && ratElement.attributes().contains( u"path"_s ) )
1217 {
1218 bool ok;
1219 const int band { ratElement.attributes().namedItem( u"band"_s ).nodeValue().toInt( &ok ) };
1220
1221 // Check band is ok
1222 if ( !ok || band <= 0 || band > bandCount() )
1223 {
1224 QgsMessageLog::logMessage( tr( "Error reading raster attribute table: invalid band %1." ).arg( band ), tr( "Raster" ) );
1225 continue;
1226 }
1227
1228 const QString path { context.pathResolver().readPath( ratElement.attributes().namedItem( u"path"_s ).nodeValue() ) };
1229 if ( !QFile::exists( path ) )
1230 {
1231 QgsMessageLog::logMessage( tr( "Error loading raster attribute table, file not found: %1." ).arg( path ), tr( "Raster" ) );
1232 continue;
1233 }
1234
1235 auto rat = std::make_unique<QgsRasterAttributeTable>();
1236 QString errorMessage;
1237 if ( !rat->readFromFile( path, &errorMessage ) )
1238 {
1239 QgsMessageLog::logMessage( tr( "Error loading raster attribute table from path %1: %2" ).arg( path, errorMessage ), tr( "Raster" ) );
1240 continue;
1241 }
1242
1243 // All good, set the RAT
1244 mDataProvider->setAttributeTable( band, rat.release() );
1245 }
1246 }
1247 }
1248}
1249
1250void QgsRasterLayer::closeDataProvider()
1251{
1253
1254 setValid( false );
1255 mPipe->remove( mDataProvider );
1256 mDataProvider = nullptr;
1257}
1258
1259void QgsRasterLayer::computeMinMax( int band, const QgsRasterMinMaxOrigin &mmo, Qgis::RasterRangeLimit limits, const QgsRectangle &extent, int sampleSize, double &min, double &max )
1260{
1262
1263 QgsRasterLayerUtils::computeMinMax( mDataProvider, band, mmo, limits, extent, sampleSize, min, max );
1264}
1265
1267{
1269
1270 return mDataProvider ? mDataProvider->ignoreExtents() : false;
1271}
1272
1279
1286
1288 QgsContrastEnhancement::ContrastEnhancementAlgorithm algorithm, Qgis::RasterRangeLimit limits, const QgsRectangle &extent, int sampleSize, bool generateLookupTableFlag
1289)
1290{
1292
1293 setContrastEnhancement( algorithm, limits, extent, sampleSize, generateLookupTableFlag, mPipe->renderer() );
1294}
1295
1297 QgsContrastEnhancement::ContrastEnhancementAlgorithm algorithm, Qgis::RasterRangeLimit limits, const QgsRectangle &extent, int sampleSize, bool generateLookupTableFlag, QgsRasterRenderer *rasterRenderer
1298)
1299{
1301
1302 QgsDebugMsgLevel( u"theAlgorithm = %1 limits = %2 extent.isEmpty() = %3"_s.arg( algorithm ).arg( qgsEnumValueToKey( limits ) ).arg( extent.isEmpty() ), 4 );
1303 if ( !rasterRenderer || !mDataProvider )
1304 {
1305 return;
1306 }
1307
1308 QList<int> myBands;
1309 QList<QgsContrastEnhancement *> myEnhancements;
1310 QgsRasterMinMaxOrigin myMinMaxOrigin;
1311 QgsRasterRenderer *myRasterRenderer = nullptr;
1312 QgsSingleBandGrayRenderer *myGrayRenderer = nullptr;
1313 QgsSingleBandPseudoColorRenderer *myPseudoColorRenderer = nullptr;
1314 QgsMultiBandColorRenderer *myMultiBandRenderer = nullptr;
1315 const QString rendererType = rasterRenderer->type();
1316 if ( rendererType == "singlebandgray"_L1 )
1317 {
1318 myGrayRenderer = dynamic_cast<QgsSingleBandGrayRenderer *>( rasterRenderer );
1319 if ( !myGrayRenderer )
1320 {
1321 return;
1322 }
1323 myBands << myGrayRenderer->inputBand();
1324 myRasterRenderer = myGrayRenderer;
1325 myMinMaxOrigin = myGrayRenderer->minMaxOrigin();
1326 }
1327 else if ( rendererType == "multibandcolor"_L1 )
1328 {
1329 myMultiBandRenderer = dynamic_cast<QgsMultiBandColorRenderer *>( rasterRenderer );
1330 if ( !myMultiBandRenderer )
1331 {
1332 return;
1333 }
1334 myBands << myMultiBandRenderer->redBand() << myMultiBandRenderer->greenBand() << myMultiBandRenderer->blueBand();
1335 myRasterRenderer = myMultiBandRenderer;
1336 myMinMaxOrigin = myMultiBandRenderer->minMaxOrigin();
1337 }
1338 else if ( rendererType == "singlebandpseudocolor"_L1 )
1339 {
1340 myPseudoColorRenderer = dynamic_cast<QgsSingleBandPseudoColorRenderer *>( rasterRenderer );
1341 if ( !myPseudoColorRenderer )
1342 {
1343 return;
1344 }
1345 myBands << myPseudoColorRenderer->inputBand();
1346 myRasterRenderer = myPseudoColorRenderer;
1347 myMinMaxOrigin = myPseudoColorRenderer->minMaxOrigin();
1348 }
1349 else
1350 {
1351 return;
1352 }
1353
1354 for ( const int myBand : std::as_const( myBands ) )
1355 {
1356 if ( myBand != -1 )
1357 {
1358 const Qgis::DataType myType = static_cast< Qgis::DataType >( mDataProvider->dataType( myBand ) );
1359 auto myEnhancement = std::make_unique<QgsContrastEnhancement>( static_cast< Qgis::DataType >( myType ) );
1360 myEnhancement->setContrastEnhancementAlgorithm( algorithm, generateLookupTableFlag );
1361
1362 double min;
1363 double max;
1364 computeMinMax( myBand, myMinMaxOrigin, limits, extent, sampleSize, min, max );
1365
1366 if ( rendererType == "singlebandpseudocolor"_L1 )
1367 {
1368 // This is not necessary, but clang-tidy thinks it is.
1369 if ( !myPseudoColorRenderer )
1370 {
1371 return;
1372 }
1373 // Do not overwrite min/max with NaN if they were already set,
1374 // for example when the style was already loaded from a raster attribute table
1375 // in that case we need to respect the style from the attribute table and do
1376 // not perform any reclassification.
1377 bool minMaxChanged { false };
1378 if ( !std::isnan( min ) )
1379 {
1380 myPseudoColorRenderer->setClassificationMin( min );
1381 minMaxChanged = true;
1382 }
1383
1384 if ( !std::isnan( max ) )
1385 {
1386 myPseudoColorRenderer->setClassificationMax( max );
1387 minMaxChanged = true;
1388 }
1389
1390 if ( minMaxChanged && myPseudoColorRenderer->shader() )
1391 {
1392 QgsColorRampShader *colorRampShader = dynamic_cast<QgsColorRampShader *>( myPseudoColorRenderer->shader()->rasterShaderFunction() );
1393 if ( colorRampShader )
1394 {
1395 colorRampShader->classifyColorRamp( myPseudoColorRenderer->inputBand(), extent, myPseudoColorRenderer->input() );
1396 }
1397 }
1398 }
1399 else
1400 {
1401 myEnhancement->setMinimumValue( min );
1402 myEnhancement->setMaximumValue( max );
1403 myEnhancements.append( myEnhancement.release() );
1404 }
1405 }
1406 else
1407 {
1408 myEnhancements.append( nullptr );
1409 }
1410 }
1411
1412 // Again, second check is redundant but clang-tidy doesn't agree
1413 if ( rendererType == "singlebandgray"_L1 && myGrayRenderer )
1414 {
1415 if ( myEnhancements.first() )
1416 myGrayRenderer->setContrastEnhancement( myEnhancements.takeFirst() );
1417 }
1418 else if ( rendererType == "multibandcolor"_L1 && myMultiBandRenderer )
1419 {
1420 if ( myEnhancements.first() )
1421 myMultiBandRenderer->setRedContrastEnhancement( myEnhancements.takeFirst() );
1422 if ( myEnhancements.first() )
1423 myMultiBandRenderer->setGreenContrastEnhancement( myEnhancements.takeFirst() );
1424 if ( myEnhancements.first() )
1425 myMultiBandRenderer->setBlueContrastEnhancement( myEnhancements.takeFirst() );
1426 }
1427
1428 //delete all remaining unused enhancements
1429 qDeleteAll( myEnhancements );
1430
1431 myMinMaxOrigin.setLimits( limits );
1432 if ( extent != QgsRectangle() && myMinMaxOrigin.extent() == Qgis::RasterRangeExtent::WholeRaster )
1433 {
1435 }
1436 if ( myRasterRenderer )
1437 {
1438 myRasterRenderer->setMinMaxOrigin( myMinMaxOrigin );
1439 }
1440
1441 if ( rasterRenderer == renderer() )
1442 {
1443 emit repaintRequested();
1445 emit rendererChanged();
1446 }
1447}
1448
1450{
1452
1453 QgsSingleBandGrayRenderer *singleBandRenderer = nullptr;
1454 QgsMultiBandColorRenderer *multiBandRenderer = nullptr;
1455 const QgsContrastEnhancement *ce = nullptr;
1456 if ( ( singleBandRenderer = dynamic_cast<QgsSingleBandGrayRenderer *>( renderer() ) ) )
1457 {
1458 ce = singleBandRenderer->contrastEnhancement();
1459 }
1460 else if ( ( multiBandRenderer = dynamic_cast<QgsMultiBandColorRenderer *>( renderer() ) ) )
1461 {
1462 ce = multiBandRenderer->redContrastEnhancement();
1463 }
1464
1465 if ( ce )
1466 {
1469 renderer()->minMaxOrigin().limits() == Qgis::RasterRangeLimit::NotSet ? Qgis::RasterRangeLimit::MinimumMaximum : renderer()->minMaxOrigin().limits(),
1470 extent,
1471 static_cast<int>( SAMPLE_SIZE ),
1472 true,
1473 renderer()
1474 );
1475 }
1476 else
1477 {
1479 Qgis::RasterRangeLimit myLimits;
1480 if ( defaultContrastEnhancementSettings( myAlgorithm, myLimits ) )
1481 {
1483 }
1484 }
1485}
1486
1488{
1490
1491 if ( !isValid() || !mDataProvider )
1492 {
1493 QgsDebugMsgLevel( u"invoked with invalid layer or null mDataProvider"_s, 3 );
1494 return customProperty( u"storedSubsetString"_s ).toString();
1495 }
1496 if ( !mDataProvider->supportsSubsetString() )
1497 {
1498 return QString();
1499 }
1500 return mDataProvider->subsetString();
1501}
1502
1503bool QgsRasterLayer::setSubsetString( const QString &subset )
1504{
1506
1507 if ( !isValid() || !mDataProvider )
1508 {
1509 QgsDebugMsgLevel( u"invoked with invalid layer or null mDataProvider or while editing"_s, 3 );
1510 setCustomProperty( u"storedSubsetString"_s, subset );
1511 return false;
1512 }
1513
1514 if ( !mDataProvider->supportsSubsetString() )
1515 {
1516 return false;
1517 }
1518
1519 if ( subset == mDataProvider->subsetString() )
1520 return true;
1521
1522 const bool res = mDataProvider->setSubsetString( subset );
1523
1524 // get the updated data source string from the provider
1525 mDataSource = mDataProvider->dataSourceUri();
1526
1527 if ( res )
1528 {
1529 setExtent( mDataProvider->extent() );
1530 QList<double> minValues;
1531 QList<double> maxValues;
1532 const QgsRasterMinMaxOrigin &minMaxOrigin = renderer()->minMaxOrigin();
1533 for ( const int bandIdx : renderer()->usesBands() )
1534 {
1535 double min;
1536 double max;
1537
1538 computeMinMax( bandIdx, minMaxOrigin, minMaxOrigin.limits(), extent(), static_cast<int>( QgsRasterLayer::SAMPLE_SIZE ), min, max );
1539 minValues.append( min );
1540 maxValues.append( max );
1541 }
1542 renderer()->refresh( extent(), minValues, maxValues, true );
1543 emit subsetStringChanged();
1544 }
1545
1546 return res;
1547}
1548
1550{
1552
1553 QString key;
1554 QString defaultAlg;
1555 QString defaultLimits;
1556
1557 // TODO: we should not test renderer class here, move it somehow to renderers
1558 if ( dynamic_cast<QgsSingleBandGrayRenderer *>( renderer() ) )
1559 {
1560 key = u"singleBand"_s;
1563 }
1564 else if ( dynamic_cast<QgsMultiBandColorRenderer *>( renderer() ) )
1565 {
1566 if ( QgsRasterBlock::typeSize( dataProvider()->sourceDataType( 1 ) ) == 1 )
1567 {
1568 key = u"multiBandSingleByte"_s;
1571 }
1572 else
1573 {
1574 key = u"multiBandMultiByte"_s;
1577 }
1578 }
1579
1580 if ( key.isEmpty() )
1581 {
1582 QgsDebugMsgLevel( u"No default contrast enhancement for this drawing style"_s, 2 );
1584 myLimits = QgsRasterMinMaxOrigin::limitsFromString( QString() );
1585 return false;
1586 }
1587 QgsDebugMsgLevel( "key = " + key, 4 );
1588
1589 const QString myAlgorithmString = settingsRasterDefaultContrastEnhancementAlgorithm->valueWithDefaultOverride( defaultAlg, { key } );
1590 QgsDebugMsgLevel( "myAlgorithmString = " + myAlgorithmString, 4 );
1591
1592 myAlgorithm = QgsContrastEnhancement::contrastEnhancementAlgorithmFromString( myAlgorithmString );
1593
1594 const QString myLimitsString = settingsRasterDefaultContrastEnhancementLimits->valueWithDefaultOverride( defaultLimits, { key } );
1595 QgsDebugMsgLevel( "myLimitsString = " + myLimitsString, 4 );
1596 myLimits = QgsRasterMinMaxOrigin::limitsFromString( myLimitsString );
1597
1598 return true;
1599}
1600
1602{
1604
1605 QgsDebugMsgLevel( u"Entered"_s, 4 );
1606
1608 Qgis::RasterRangeLimit myLimits;
1609 defaultContrastEnhancementSettings( myAlgorithm, myLimits );
1610
1611 setContrastEnhancement( myAlgorithm, myLimits );
1612}
1613
1614void QgsRasterLayer::setLayerOrder( QStringList const &layers )
1615{
1617
1618 QgsDebugMsgLevel( u"entered."_s, 4 );
1619
1620 if ( mDataProvider )
1621 {
1622 QgsDebugMsgLevel( u"About to mDataProvider->setLayerOrder(layers)."_s, 4 );
1623 mDataProvider->setLayerOrder( layers );
1624 }
1625}
1626
1627void QgsRasterLayer::setSubLayerVisibility( const QString &name, bool vis )
1628{
1630
1631 if ( mDataProvider )
1632 {
1633 QgsDebugMsgLevel( u"About to mDataProvider->setSubLayerVisibility(name, vis)."_s, 4 );
1634 mDataProvider->setSubLayerVisibility( name, vis );
1635 }
1636}
1637
1639{
1641
1642 if ( !mDataProvider )
1643 return QDateTime();
1644 return mDataProvider->timestamp();
1645}
1646
1648{
1650
1651 if ( auto *lRenderer = mPipe->renderer() )
1652 {
1653 if ( !lRenderer->accept( visitor ) )
1654 return false;
1655 }
1656 return true;
1657}
1658
1660{
1662
1663 return mLabelsEnabled && static_cast< bool >( mLabeling );
1664}
1665
1667{
1669
1670 mLabelsEnabled = enabled;
1671}
1672
1674{
1676
1677 return mLabeling.get();
1678}
1679
1686
1688{
1690
1691 if ( mLabeling.get() == labeling )
1692 return;
1693
1694 mLabeling.reset( labeling );
1696}
1697
1698bool QgsRasterLayer::writeSld( QDomNode &node, QDomDocument &doc, QString &, const QVariantMap &props ) const
1699{
1701 QgsSldExportContext context;
1702 context.setExtraProperties( props );
1703 writeSld( node, doc, context );
1704 return true;
1705}
1706
1707bool QgsRasterLayer::writeSld( QDomNode &node, QDomDocument &doc, QgsSldExportContext &context ) const
1708{
1710
1711 QVariantMap localProps = context.extraProperties();
1713 {
1714 // TODO: QgsSymbolLayerUtils::mergeScaleDependencies generate SE only and not SLD1.0
1716 }
1717 context.setExtraProperties( localProps );
1718
1719 if ( isSpatial() ) // TODO: does it make sense this control?
1720 {
1721 // store constraints
1722 QDomElement constraintElem = doc.createElement( u"sld:LayerFeatureConstraints"_s );
1723 node.appendChild( constraintElem );
1724
1725 const QDomElement featureTypeConstraintElem = doc.createElement( u"sld:FeatureTypeConstraint"_s );
1726 constraintElem.appendChild( featureTypeConstraintElem );
1727
1728 QDomElement userStyleElem = doc.createElement( u"sld:UserStyle"_s );
1729 node.appendChild( userStyleElem );
1730
1731 if ( !name().isEmpty() )
1732 {
1733 QDomElement nameElem = doc.createElement( u"sld:Name"_s );
1734 nameElem.appendChild( doc.createTextNode( name() ) );
1735 userStyleElem.appendChild( nameElem );
1736 }
1737
1738 const QString abstract = !metadata().abstract().isEmpty() ? metadata().abstract() : serverProperties()->abstract();
1739 if ( !abstract.isEmpty() )
1740 {
1741 QDomElement abstractElem = doc.createElement( u"sld:Abstract"_s );
1742 abstractElem.appendChild( doc.createTextNode( abstract ) );
1743 userStyleElem.appendChild( abstractElem );
1744 }
1745
1746 const QString title = !metadata().title().isEmpty() ? metadata().title() : serverProperties()->title();
1747 if ( !title.isEmpty() )
1748 {
1749 QDomElement titleElem = doc.createElement( u"sld:Title"_s );
1750 titleElem.appendChild( doc.createTextNode( title ) );
1751 userStyleElem.appendChild( titleElem );
1752 }
1753
1754 QDomElement featureTypeStyleElem = doc.createElement( u"sld:FeatureTypeStyle"_s );
1755 userStyleElem.appendChild( featureTypeStyleElem );
1756
1757#if 0
1758 // TODO: Is there a way to fill it's value with the named style?
1759 // by default <sld:Name> under <sld:FeatureTypeStyle> can have 0 occurrences
1760 // the same happen for tags:
1761 // sld:Title
1762 // sld:Abstract
1763 // sld:FeatureTypeName
1764 // sld:SemanticTypeIdentifier
1765 QDomElement typeStyleNameElem = doc.createElement( u"sld:Name"_s );
1766 featureTypeStyleElem.appendChild( typeStyleNameElem );
1767#endif
1768
1769 QDomElement typeStyleRuleElem = doc.createElement( u"sld:Rule"_s );
1770 featureTypeStyleElem.appendChild( typeStyleRuleElem );
1771
1772 // add ScaleDenominator tags
1774 {
1775 // note that denominator is the inverted value of scale
1776 if ( maximumScale() != 0.0 )
1777 {
1778 QDomElement minScaleElem = doc.createElement( u"sld:MinScaleDenominator"_s );
1779 minScaleElem.appendChild( doc.createTextNode( QString::number( maximumScale() ) ) );
1780 typeStyleRuleElem.appendChild( minScaleElem );
1781 }
1782
1783 QDomElement maxScaleElem = doc.createElement( u"sld:MaxScaleDenominator"_s );
1784 maxScaleElem.appendChild( doc.createTextNode( QString::number( minimumScale() ) ) );
1785 typeStyleRuleElem.appendChild( maxScaleElem );
1786 }
1787
1788 // export renderer dependent tags
1789 mPipe->renderer()->toSld( doc, typeStyleRuleElem, context );
1790
1791 // inject raster layer parameters in RasterSymbolizer tag because
1792 // they belongs to rasterlayer and not to the renderer => avoid to
1793 // pass many parameters value via localProps
1794 const QDomNodeList elements = typeStyleRuleElem.elementsByTagName( u"sld:RasterSymbolizer"_s );
1795 if ( elements.size() != 0 )
1796 {
1797 // there SHOULD be only one
1798 QDomElement rasterSymbolizerElem = elements.at( 0 ).toElement();
1799
1800 // lamda helper used below to reduce code redundancy
1801 auto vendorOptionWriter = [&]( QString name, QString value ) {
1802 QDomElement vendorOptionElem = doc.createElement( u"sld:VendorOption"_s );
1803 vendorOptionElem.setAttribute( u"name"_s, name );
1804 vendorOptionElem.appendChild( doc.createTextNode( value ) );
1805 rasterSymbolizerElem.appendChild( vendorOptionElem );
1806 };
1807
1808 if ( hueSaturationFilter()->invertColors() )
1809 {
1810 vendorOptionWriter( u"invertColors"_s, QString::number( 1 ) );
1811 }
1812
1813 // add greyScale rendering mode if set
1815 {
1816 QString property;
1817 switch ( hueSaturationFilter()->grayscaleMode() )
1818 {
1820 property = u"lightness"_s;
1821 break;
1823 property = u"luminosity"_s;
1824 break;
1826 property = u"average"_s;
1827 break;
1829 // added just to avoid travis fail
1830 break;
1831 }
1832 if ( !property.isEmpty() )
1833 vendorOptionWriter( u"grayScale"_s, property );
1834 }
1835
1836 // add Hue, Saturation and Lighting values in props is Hue filter is set
1837 if ( hueSaturationFilter() && hueSaturationFilter()->colorizeOn() )
1838 {
1839 vendorOptionWriter( u"colorizeOn"_s, QString::number( hueSaturationFilter()->colorizeOn() ) );
1840 vendorOptionWriter( u"colorizeRed"_s, QString::number( hueSaturationFilter()->colorizeColor().red() ) );
1841 vendorOptionWriter( u"colorizeGreen"_s, QString::number( hueSaturationFilter()->colorizeColor().green() ) );
1842 vendorOptionWriter( u"colorizeBlue"_s, QString::number( hueSaturationFilter()->colorizeColor().blue() ) );
1843 if ( hueSaturationFilter()->colorizeStrength() != 100.0 )
1844 vendorOptionWriter( u"colorizeStrength"_s, QString::number( hueSaturationFilter()->colorizeStrength() / 100.0 ) );
1845 vendorOptionWriter( u"saturation"_s, QString::number( hueSaturationFilter()->colorizeColor().saturationF() ) );
1846 }
1847 else
1848 {
1849 // saturation != 0 (default value)
1850 if ( hueSaturationFilter()->saturation() != 0 )
1851 {
1852 // normlize value [-100:100] -> [0:1]
1853 const int s = hueSaturationFilter()->saturation();
1854 const double sF = ( s - ( -100.0 ) ) / ( 100.0 - ( -100.0 ) );
1855 vendorOptionWriter( u"saturation"_s, QString::number( sF ) );
1856 }
1857 }
1858
1859 // brightness != 0 (default value)
1860 if ( brightnessFilter()->brightness() != 0 )
1861 {
1862 // normalize value [-255:255] -> [0:1]
1863 const int b = brightnessFilter()->brightness();
1864 const double bF = ( b - ( -255.0 ) ) / ( 255.0 - ( -255.0 ) );
1865 vendorOptionWriter( u"brightness"_s, QString::number( bF ) );
1866 }
1867
1868 // contrast != 0 (default value)
1869 if ( brightnessFilter()->contrast() != 0 )
1870 {
1871 // normlize value [-100:100] -> [0:1]
1872 const int c = brightnessFilter()->contrast();
1873 const double cF = ( c - ( -100.0 ) ) / ( 100.0 - ( -100.0 ) );
1874 vendorOptionWriter( u"contrast"_s, QString::number( cF ) );
1875 }
1876
1877#if 0
1878 // TODO: check if the below mapping formula make sense to map QGIS contrast with SLD gamma value
1879 // add SLD1.0 ContrastEnhancement GammaValue = QGIS Contrast
1880 // SLD1.0 does only define 1 as neutral/center double value but does not define range.
1881 // because https://en.wikipedia.org/wiki/Gamma_correction assumed gamma is >0.
1882 // whilst QGIS has a -100/100 values centered in 0 => QGIS contrast value will be scaled in the
1883 // following way:
1884 // [-100,0] => [0,1] and [0,100] => [1,100]
1885 // an alternative could be scale [-100,100] => (0,2]
1886 //
1887 if ( newProps.contains( u"contrast"_s ) )
1888 {
1889 double gamma;
1890 double contrast = newProps[ u"contrast"_s ].toDouble();
1891 double percentage = ( contrast - ( -100.0 ) ) / ( 100.0 - ( -100.0 ) );
1892 if ( percentage <= 0.5 )
1893 {
1894 // stretch % to [0-1]
1895 gamma = percentage / 0.5;
1896 }
1897 else
1898 {
1899 gamma = contrast;
1900 }
1901
1902 QDomElement globalContrastEnhancementElem = doc.createElement( u"sld:ContrastEnhancement"_s );
1903 rasterSymolizerElem.appendChild( globalContrastEnhancementElem );
1904
1905 QDomElement gammaValueElem = doc.createElement( u"sld:GammaValue"_s );
1906 gammaValueElem.appendChild( doc.createTextNode( QString::number( gamma ) ) );
1907 globalContrastEnhancementElem.appendChild( gammaValueElem );
1908 }
1909#endif
1910 }
1911 }
1912 return true;
1913}
1914
1916{
1918
1919 QgsDebugMsgLevel( u"Entered"_s, 4 );
1920 if ( !renderer )
1921 {
1922 return;
1923 }
1924
1925 mPipe->set( renderer );
1926 emit rendererChanged();
1928}
1929
1931{
1933
1934 return mPipe->renderer();
1935}
1936
1938{
1940
1941 return mPipe->resampleFilter();
1942}
1943
1945{
1947
1948 return mPipe->brightnessFilter();
1949}
1950
1952{
1954
1955 return mPipe->hueSaturationFilter();
1956}
1957
1958void QgsRasterLayer::showStatusMessage( QString const &message )
1959{
1961
1962 // QgsDebugMsgLevel(QString("entered with '%1'.").arg(theMessage), 2);
1963
1964 // Pass-through
1965 // TODO: See if we can connect signal-to-signal. This is a kludge according to the Qt doc.
1966 emit statusChanged( message );
1967}
1968
1970{
1972
1973 if ( mDataProvider )
1974 mDataProvider->setTransformContext( transformContext );
1976}
1977
1978QStringList QgsRasterLayer::subLayers() const
1979{
1981
1982 if ( !mDataProvider )
1983 return QStringList();
1984 return mDataProvider->subLayers();
1985}
1986
1987// this function should be used when rendering with the MTR engine introduced in 2.3, as QPixmap is not thread safe (see bug #9626)
1988// note: previewAsImage and previewAsPixmap should use a common low-level fct QgsRasterLayer::previewOnPaintDevice( QSize size, QColor bgColor, QPaintDevice &device )
1989QImage QgsRasterLayer::previewAsImage( QSize size, const QColor &bgColor, QImage::Format format )
1990{
1992
1993 QImage image( size, format );
1994
1995 if ( !isValid() )
1996 return QImage();
1997
1998 if ( image.format() == QImage::Format_Indexed8 )
1999 {
2000 image.setColor( 0, bgColor.rgba() );
2001 image.fill( 0 ); //defaults to white, set to transparent for rendering on a map
2002 }
2003 else
2004 {
2005 image.fill( bgColor );
2006 }
2007
2008 QgsRasterViewPort *rasterViewPort = new QgsRasterViewPort();
2009
2010 double mapUnitsPerPixel;
2011 double x = 0.0;
2012 double y = 0.0;
2013 const QgsRectangle extent = mDataProvider->extent();
2014 if ( extent.width() / extent.height() >= static_cast< double >( image.width() ) / image.height() )
2015 {
2016 mapUnitsPerPixel = extent.width() / image.width();
2017 y = ( image.height() - extent.height() / mapUnitsPerPixel ) / 2;
2018 }
2019 else
2020 {
2021 mapUnitsPerPixel = extent.height() / image.height();
2022 x = ( image.width() - extent.width() / mapUnitsPerPixel ) / 2;
2023 }
2024
2025 const double pixelWidth = extent.width() / mapUnitsPerPixel;
2026 const double pixelHeight = extent.height() / mapUnitsPerPixel;
2027
2028 rasterViewPort->mTopLeftPoint = QgsPointXY( x, y );
2029 rasterViewPort->mBottomRightPoint = QgsPointXY( pixelWidth, pixelHeight );
2030 rasterViewPort->mWidth = image.width();
2031 rasterViewPort->mHeight = image.height();
2032
2033 rasterViewPort->mDrawnExtent = extent;
2034 rasterViewPort->mSrcCRS = QgsCoordinateReferenceSystem(); // will be invalid
2035 rasterViewPort->mDestCRS = QgsCoordinateReferenceSystem(); // will be invalid
2036
2037 QgsMapToPixel *mapToPixel = new QgsMapToPixel( mapUnitsPerPixel );
2038
2039 QPainter *painter = new QPainter( &image );
2040 draw( painter, rasterViewPort, mapToPixel );
2041 delete rasterViewPort;
2042 delete mapToPixel;
2043
2044 painter->end();
2045 delete painter;
2046
2047 return image;
2048}
2049
2050bool QgsRasterLayer::readSymbology( const QDomNode &layer_node, QString &errorMessage, QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories )
2051{
2053
2054 Q_UNUSED( errorMessage )
2055 // TODO: implement categories for raster layer
2056
2057 QDomElement rasterRendererElem;
2058
2059 const QDomElement layerElement = layer_node.toElement();
2060 readCommonStyle( layerElement, context, categories );
2061
2062 // pipe considers Symbology and Rendering components, why it's always handled as one
2063 if ( categories.testFlag( Symbology ) || categories.testFlag( Rendering ) )
2064 {
2065 // pipe element was introduced in the end of 1.9 development when there were
2066 // already many project files in use so we support 1.9 backward compatibility
2067 // even it was never officially released -> use pipe element if present, otherwise
2068 // use layer node
2069 QDomNode pipeNode = layer_node.firstChildElement( u"pipe"_s );
2070 if ( pipeNode.isNull() ) // old project
2071 {
2072 pipeNode = layer_node;
2073 }
2074
2075 //rasterlayerproperties element there -> old format (1.8 and early 1.9)
2076 if ( !layer_node.firstChildElement( u"rasterproperties"_s ).isNull() )
2077 {
2078 //copy node because layer_node is const
2079 QDomNode layerNodeCopy = layer_node.cloneNode();
2080 QDomDocument doc = layerNodeCopy.ownerDocument();
2081 QDomElement rasterPropertiesElem = layerNodeCopy.firstChildElement( u"rasterproperties"_s );
2082 QgsProjectFileTransform::convertRasterProperties( doc, layerNodeCopy, rasterPropertiesElem, this );
2083 rasterRendererElem = layerNodeCopy.firstChildElement( u"rasterrenderer"_s );
2084 QgsDebugMsgLevel( doc.toString(), 4 );
2085 }
2086 else
2087 {
2088 rasterRendererElem = pipeNode.firstChildElement( u"rasterrenderer"_s );
2089 }
2090
2091 if ( !rasterRendererElem.isNull() )
2092 {
2093 const QString rendererType = rasterRendererElem.attribute( u"type"_s );
2094 QgsRasterRendererRegistryEntry rendererEntry;
2095 if ( mDataProvider && QgsApplication::rasterRendererRegistry()->rendererData( rendererType, rendererEntry ) )
2096 {
2097 QgsRasterRenderer *renderer = rendererEntry.rendererCreateFunction( rasterRendererElem, mDataProvider );
2098 mPipe->set( renderer );
2099 }
2100 }
2101
2102 //brightness
2104 if ( mPipe->set( brightnessFilter ) )
2105 {
2106 const QDomElement brightnessElem = pipeNode.firstChildElement( u"brightnesscontrast"_s );
2107 if ( !brightnessElem.isNull() )
2108 {
2109 brightnessFilter->readXml( brightnessElem );
2110 }
2111 }
2112
2113 //hue/saturation
2115 if ( mPipe->set( hueSaturationFilter ) )
2116 {
2117 const QDomElement hueSaturationElem = pipeNode.firstChildElement( u"huesaturation"_s );
2118 if ( !hueSaturationElem.isNull() )
2119 {
2120 hueSaturationFilter->readXml( hueSaturationElem );
2121 }
2122 }
2123
2124 //resampler
2126 if ( mPipe->set( resampleFilter ) )
2127 {
2128 const QDomElement resampleElem = pipeNode.firstChildElement( u"rasterresampler"_s );
2129 if ( !resampleElem.isNull() )
2130 {
2131 resampleFilter->readXml( resampleElem );
2132 }
2133 }
2134
2135 //provider
2136 if ( mDataProvider )
2137 {
2138 const QDomElement providerElem = pipeNode.firstChildElement( u"provider"_s );
2139 if ( !providerElem.isNull() )
2140 {
2141 mDataProvider->readXml( providerElem );
2142 }
2143 }
2144
2145 // Resampling stage
2146 const QDomNode resamplingStageElement = pipeNode.namedItem( u"resamplingStage"_s );
2147 if ( !resamplingStageElement.isNull() )
2148 {
2149 const QDomElement e = resamplingStageElement.toElement();
2150 if ( e.text() == "provider"_L1 )
2152 else if ( e.text() == "resamplingFilter"_L1 )
2154 }
2155
2156 // get and set the blend mode if it exists
2157 const QDomNode blendModeNode = layer_node.namedItem( u"blendMode"_s );
2158 if ( !blendModeNode.isNull() )
2159 {
2160 const QDomElement e = blendModeNode.toElement();
2161 setBlendMode( QgsPainting::getCompositionMode( static_cast< Qgis::BlendMode >( e.text().toInt() ) ) );
2162 }
2163
2164 const QDomElement elemDataDefinedProperties = layer_node.firstChildElement( u"pipe-data-defined-properties"_s );
2165 if ( !elemDataDefinedProperties.isNull() )
2166 mPipe->dataDefinedProperties().readXml( elemDataDefinedProperties, QgsRasterPipe::propertyDefinitions() );
2167 }
2168
2169 // read labeling definition
2170 if ( categories.testFlag( Labeling ) )
2171 {
2172 QgsReadWriteContextCategoryPopper p = context.enterCategory( tr( "Labeling" ) );
2173
2174 QDomElement labelingElement = layer_node.firstChildElement( u"labeling"_s );
2175 if ( !labelingElement.isNull() )
2176 {
2178 mLabelsEnabled = layer_node.toElement().attribute( u"labelsEnabled"_s, u"0"_s ).toInt();
2180 }
2181 }
2182
2183 if ( categories.testFlag( MapTips ) )
2184 {
2185 QDomElement mapTipElem = layer_node.namedItem( u"mapTip"_s ).toElement();
2186 setMapTipTemplate( mapTipElem.text() );
2187 setMapTipsEnabled( mapTipElem.attribute( u"enabled"_s, u"1"_s ).toInt() == 1 );
2188 }
2189
2190 // read attribute table attribute table paths
2191 if ( categories.testFlag( AttributeTable ) )
2192 {
2193 readRasterAttributeTableExternalPaths( layer_node, context );
2194 }
2195
2196 if ( categories.testFlag( Legend ) )
2197 {
2198 QgsReadWriteContextCategoryPopper p = context.enterCategory( tr( "Legend" ) );
2199
2200 const QDomElement legendElem = layer_node.firstChildElement( u"legend"_s );
2201 QgsMapLayerLegend *rasterLegend = legend();
2202 if ( rasterLegend && !legendElem.isNull() )
2203 {
2204 rasterLegend->readXml( legendElem, context );
2205 }
2206 else if ( rasterLegend )
2207 {
2208 // Temporary fix for #63346 because legend was not saved if empty
2210 }
2211 }
2212
2213 emit rendererChanged();
2215
2216 return true;
2217}
2218
2219bool QgsRasterLayer::readStyle( const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories )
2220{
2222
2223 return readSymbology( node, errorMessage, context, categories );
2224}
2225
2226bool QgsRasterLayer::readXml( const QDomNode &layer_node, QgsReadWriteContext &context )
2227{
2229
2230 QgsDebugMsgLevel( u"Entered"_s, 4 );
2231 // Make sure to read the file first so stats etc are initialized properly!
2232
2233 //process provider key
2234 const QDomNode pkeyNode = layer_node.namedItem( u"provider"_s );
2235
2236 if ( pkeyNode.isNull() )
2237 {
2238 mProviderKey = u"gdal"_s;
2239 }
2240 else
2241 {
2242 const QDomElement pkeyElt = pkeyNode.toElement();
2243 mProviderKey = pkeyElt.text();
2244 if ( mProviderKey.isEmpty() )
2245 {
2246 mProviderKey = u"gdal"_s;
2247 }
2248 }
2249
2250 // Open the raster source based on provider and datasource
2251
2252 // Go down the raster-data-provider paradigm
2253
2254 // Collect provider-specific information
2255
2256 const QDomNode rpNode = layer_node.namedItem( u"rasterproperties"_s );
2257
2258 if ( mProviderKey == "wms"_L1 )
2259 {
2260 // >>> BACKWARD COMPATIBILITY < 1.9
2261 // The old WMS URI format does not contain all the information, we add them here.
2262 if ( !mDataSource.contains( "crs="_L1 ) && !mDataSource.contains( "format="_L1 ) )
2263 {
2264 QgsDebugMsgLevel( u"Old WMS URI format detected -> adding params"_s, 4 );
2265 QgsDataSourceUri uri;
2267 QDomElement layerElement = rpNode.firstChildElement( u"wmsSublayer"_s );
2268 while ( !layerElement.isNull() )
2269 {
2270 // TODO: sublayer visibility - post-0.8 release timeframe
2271
2272 // collect name for the sublayer
2273 uri.setParam( u"layers"_s, layerElement.namedItem( u"name"_s ).toElement().text() );
2274
2275 // collect style for the sublayer
2276 uri.setParam( u"styles"_s, layerElement.namedItem( u"style"_s ).toElement().text() );
2277
2278 layerElement = layerElement.nextSiblingElement( u"wmsSublayer"_s );
2279 }
2280
2281 // Collect format
2282 uri.setParam( u"format"_s, rpNode.namedItem( u"wmsFormat"_s ).toElement().text() );
2283
2284 // WMS CRS URL param should not be mixed with that assigned to the layer.
2285 // In the old WMS URI version there was no CRS and layer crs().authid() was used.
2286 uri.setParam( u"crs"_s, crs().authid() );
2287 mDataSource = uri.encodedUri();
2288 }
2289 // <<< BACKWARD COMPATIBILITY < 1.9
2290 }
2291
2293 {
2294 const QgsDataProvider::ProviderOptions providerOptions { context.transformContext() };
2296
2298 {
2299 const QDomNode extentNode = layer_node.namedItem( u"extent"_s );
2300 if ( !extentNode.isNull() )
2301 {
2302 // get the extent
2303 const QgsRectangle mbr = QgsXmlUtils::readRectangle( extentNode.toElement() );
2304
2305 // store the extent
2306 setExtent( mbr );
2307 }
2308 }
2309 setDataProvider( mProviderKey, providerOptions, flags );
2310 }
2311
2312 mOriginalStyleElement = layer_node.namedItem( u"originalStyle"_s ).firstChildElement();
2313 if ( mOriginalStyleElement.isNull() )
2314 mOriginalStyleElement = layer_node.toElement();
2315 mOriginalStyleDocument = layer_node.ownerDocument();
2316
2317 if ( !mDataProvider )
2318 {
2320 {
2321 QgsDebugError( u"Raster data provider could not be created for %1"_s.arg( mDataSource ) );
2322 return false;
2323 }
2324 }
2325
2326 QString error;
2327 const bool res = readSymbology( layer_node, error, context );
2328
2329 // old wms settings we need to correct
2330 if ( res && mProviderKey == "wms"_L1 && !renderer() )
2331 {
2332 setRendererForDrawingStyle( Qgis::RasterDrawingStyle::SingleBandColorData );
2333 }
2334
2335 // Check timestamp
2336 // This was probably introduced to reload completely raster if data changed and
2337 // reset completely symbology to reflect new data type etc. It creates however
2338 // problems, because user defined symbology is complete lost if data file time
2339 // changed (the content may be the same). See also 6900.
2340#if 0
2341 QDomNode stampNode = layer_node.namedItem( "timestamp" );
2342 if ( !stampNode.isNull() )
2343 {
2344 QDateTime stamp = QDateTime::fromString( stampNode.toElement().text(), Qt::ISODate );
2345 // TODO: very bad, we have to load twice!!! Make QgsDataProvider::timestamp() static?
2346 if ( stamp < mDataProvider->dataTimestamp() )
2347 {
2348 QgsDebugMsgLevel( u"data changed, reload provider"_s, 3 );
2349 closeDataProvider();
2350 init();
2352 if ( !isValid() ) return false;
2353 }
2354 }
2355#endif
2356
2357 // Load user no data value
2358 const QDomElement noDataElement = layer_node.firstChildElement( u"noData"_s );
2359
2360 const QDomNodeList noDataBandList = noDataElement.elementsByTagName( u"noDataList"_s );
2361
2362 for ( int i = 0; mDataProvider && i < noDataBandList.size(); ++i )
2363 {
2364 const QDomElement bandElement = noDataBandList.at( i ).toElement();
2365 bool ok;
2366 const int bandNo = bandElement.attribute( u"bandNo"_s ).toInt( &ok );
2367 QgsDebugMsgLevel( u"bandNo = %1"_s.arg( bandNo ), 4 );
2368 if ( ok && ( bandNo > 0 ) && ( bandNo <= mDataProvider->bandCount() ) )
2369 {
2370 mDataProvider->setUseSourceNoDataValue( bandNo, bandElement.attribute( u"useSrcNoData"_s ).toInt() );
2371 QgsRasterRangeList myNoDataRangeList;
2372
2373 const QDomNodeList rangeList = bandElement.elementsByTagName( u"noDataRange"_s );
2374
2375 myNoDataRangeList.reserve( rangeList.size() );
2376 for ( int j = 0; j < rangeList.size(); ++j )
2377 {
2378 const QDomElement rangeElement = rangeList.at( j ).toElement();
2379 const QgsRasterRange myNoDataRange( rangeElement.attribute( u"min"_s ).toDouble(), rangeElement.attribute( u"max"_s ).toDouble() );
2380 QgsDebugMsgLevel( u"min = %1 %2"_s.arg( rangeElement.attribute( "min" ) ).arg( myNoDataRange.min() ), 4 );
2381 myNoDataRangeList << myNoDataRange;
2382 }
2383 mDataProvider->setUserNoDataValue( bandNo, myNoDataRangeList );
2384 }
2385 }
2386
2387 readRasterAttributeTableExternalPaths( layer_node, context );
2388
2389 readStyleManager( layer_node );
2390
2391 return res;
2392}
2393
2394bool QgsRasterLayer::writeSymbology( QDomNode &layer_node, QDomDocument &document, QString &errorMessage, const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
2395{
2397
2398 Q_UNUSED( errorMessage )
2399 // TODO: implement categories for raster layer
2400
2401 QDomElement layerElement = layer_node.toElement();
2402
2403 writeCommonStyle( layerElement, document, context, categories );
2404
2405 if ( categories.testFlag( Labeling ) )
2406 {
2407 if ( mLabeling )
2408 {
2409 QDomElement labelingElement = mLabeling->save( document, context );
2410 layerElement.appendChild( labelingElement );
2411 }
2412 if ( mLabelsEnabled )
2413 layerElement.setAttribute( u"labelsEnabled"_s, u"1"_s );
2414 }
2415
2416 // save map tip
2417 if ( categories.testFlag( MapTips ) )
2418 {
2419 QDomElement mapTipElem = document.createElement( u"mapTip"_s );
2420 mapTipElem.setAttribute( u"enabled"_s, mapTipsEnabled() );
2421 QDomText mapTipText = document.createTextNode( mapTipTemplate() );
2422 mapTipElem.appendChild( mapTipText );
2423 layer_node.toElement().appendChild( mapTipElem );
2424 }
2425
2426 // save attribute table attribute table paths
2427 if ( categories.testFlag( AttributeTable ) )
2428 {
2429 writeRasterAttributeTableExternalPaths( layer_node, document, context );
2430 }
2431
2432 // pipe considers Symbology and Rendering components, why it's always handled as one
2433 if ( categories.testFlag( Symbology ) || categories.testFlag( Rendering ) )
2434 {
2435 // Store pipe members into pipe element, in future, it will be
2436 // possible to add custom filters into the pipe
2437 QDomElement pipeElement = document.createElement( u"pipe"_s );
2438
2439 for ( int i = 0; i < mPipe->size(); i++ )
2440 {
2441 QgsRasterInterface *interface = mPipe->at( i );
2442 if ( !interface )
2443 continue;
2444 interface->writeXml( document, pipeElement );
2445 }
2446
2447 QDomElement elemDataDefinedProperties = document.createElement( u"pipe-data-defined-properties"_s );
2448 mPipe->dataDefinedProperties().writeXml( elemDataDefinedProperties, QgsRasterPipe::propertyDefinitions() );
2449 layer_node.appendChild( elemDataDefinedProperties );
2450
2451 QDomElement resamplingStageElement = document.createElement( u"resamplingStage"_s );
2452 const QDomText resamplingStageText = document.createTextNode( resamplingStage() == Qgis::RasterResamplingStage::Provider ? u"provider"_s : u"resamplingFilter"_s );
2453 resamplingStageElement.appendChild( resamplingStageText );
2454 pipeElement.appendChild( resamplingStageElement );
2455
2456 layer_node.appendChild( pipeElement );
2457
2458 if ( !isValid() && !mOriginalStyleElement.isNull() )
2459 {
2460 QDomElement originalStyleElement = document.createElement( u"originalStyle"_s );
2461 originalStyleElement.appendChild( mOriginalStyleElement );
2462 layer_node.appendChild( originalStyleElement );
2463 }
2464
2465 // add blend mode node
2466 QDomElement blendModeElement = document.createElement( u"blendMode"_s );
2467 const QDomText blendModeText = document.createTextNode( QString::number( static_cast< int >( QgsPainting::getBlendModeEnum( blendMode() ) ) ) );
2468 blendModeElement.appendChild( blendModeText );
2469 layer_node.appendChild( blendModeElement );
2470 }
2471
2472 if ( categories.testFlag( Legend ) && legend() )
2473 {
2474 QDomElement legendElement = legend()->writeXml( document, context );
2475 if ( !legendElement.isNull() )
2476 layer_node.appendChild( legendElement );
2477 }
2478
2479 return true;
2480}
2481
2482bool QgsRasterLayer::writeStyle( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
2483{
2485
2486 return writeSymbology( node, doc, errorMessage, context, categories );
2487}
2488
2489bool QgsRasterLayer::writeXml( QDomNode &layer_node, QDomDocument &document, const QgsReadWriteContext &context ) const
2490{
2492
2493 if ( !mDataProvider )
2494 return false;
2495
2496 // first get the layer element so that we can append the type attribute
2497
2498 QDomElement mapLayerNode = layer_node.toElement();
2499
2500 if ( mapLayerNode.isNull() || "maplayer" != mapLayerNode.nodeName() )
2501 {
2502 QgsMessageLog::logMessage( tr( "<maplayer> not found." ), tr( "Raster" ) );
2503 return false;
2504 }
2505
2506 mapLayerNode.setAttribute( u"type"_s, QgsMapLayerFactory::typeToString( Qgis::LayerType::Raster ) );
2507
2508 // add provider node
2509
2510 QDomElement provider = document.createElement( u"provider"_s );
2511 const QDomText providerText = document.createTextNode( mProviderKey );
2512 provider.appendChild( providerText );
2513 layer_node.appendChild( provider );
2514
2515 // User no data
2516 QDomElement noData = document.createElement( u"noData"_s );
2517
2518 for ( int bandNo = 1; bandNo <= mDataProvider->bandCount(); bandNo++ )
2519 {
2520 QDomElement noDataRangeList = document.createElement( u"noDataList"_s );
2521 noDataRangeList.setAttribute( u"bandNo"_s, bandNo );
2522 noDataRangeList.setAttribute( u"useSrcNoData"_s, mDataProvider->useSourceNoDataValue( bandNo ) );
2523
2524 const auto constUserNoDataValues = mDataProvider->userNoDataValues( bandNo );
2525 for ( const QgsRasterRange &range : constUserNoDataValues )
2526 {
2527 QDomElement noDataRange = document.createElement( u"noDataRange"_s );
2528
2529 noDataRange.setAttribute( u"min"_s, QgsRasterBlock::printValue( range.min() ) );
2530 noDataRange.setAttribute( u"max"_s, QgsRasterBlock::printValue( range.max() ) );
2531 noDataRangeList.appendChild( noDataRange );
2532 }
2533
2534 noData.appendChild( noDataRangeList );
2535 }
2536 if ( noData.hasChildNodes() )
2537 {
2538 layer_node.appendChild( noData );
2539 }
2540
2541 // Store file-based raster attribute table paths (if any)
2542 writeRasterAttributeTableExternalPaths( layer_node, document, context );
2543
2544 writeStyleManager( layer_node, document );
2545
2546 //write out the symbology
2547 QString errorMsg;
2548 return writeSymbology( layer_node, document, errorMsg, context );
2549}
2550
2551
2558
2559QString QgsRasterLayer::decodedSource( const QString &source, const QString &provider, const QgsReadWriteContext &context ) const
2560{
2562
2563 return QgsProviderRegistry::instance()->relativeToAbsoluteUri( provider, source, context );
2564}
2565
2567{
2569
2570 if ( !mDataProvider )
2571 return 0;
2572 return mDataProvider->xSize();
2573}
2574
2576{
2578
2579 if ( !mDataProvider )
2580 return 0;
2581 return mDataProvider->ySize();
2582}
2583
2585{
2587
2588 mPipe->setResamplingStage( stage );
2589}
2590
2592{
2594
2595 return mPipe->resamplingStage();
2596}
2597
2598bool QgsRasterLayer::update()
2599{
2601
2602 QgsDebugMsgLevel( u"entered."_s, 4 );
2603 // Check if data changed
2604 if ( mDataProvider && mDataProvider->dataTimestamp() > mDataProvider->timestamp() )
2605 {
2606 QgsDebugMsgLevel( u"reload data"_s, 4 );
2607 closeDataProvider();
2608 init();
2609 const QgsDataProvider::ProviderOptions providerOptions;
2612 {
2614 }
2615 setDataProvider( mProviderKey, providerOptions, flags );
2616 emit dataChanged();
2617 }
2618 return isValid();
2619}
2620
2621#undef ERR
Provides global constants and enumerations for use throughout the application.
Definition qgis.h:62
static QString version()
Version string.
Definition qgis.cpp:682
@ IsBasemapLayer
Layer is considered a 'basemap' layer, and certain properties of the layer should be ignored when cal...
Definition qgis.h:2447
RasterResamplingStage
Stage at which raster resampling occurs.
Definition qgis.h:1619
@ Provider
Resampling occurs in Provider.
Definition qgis.h:1621
@ ResampleFilter
Resampling occurs in ResamplingFilter.
Definition qgis.h:1620
@ ProviderHintBenefitsFromResampling
Provider benefits from resampling and should apply user default resampling settings.
Definition qgis.h:5389
@ ProviderHintCanPerformProviderResampling
Provider can perform resampling (to be opposed to post rendering resampling).
Definition qgis.h:5390
@ ReadLayerMetadata
Provider can read layer metadata from data store. Since QGIS 3.0. See QgsDataProvider::layerMetadata(...
Definition qgis.h:5387
@ Palette
Palette.
Definition qgis.h:5264
@ MultiBand
Multi band.
Definition qgis.h:5265
@ SingleBandColorData
Single band containing color data.
Definition qgis.h:5266
@ GrayOrUndefined
Gray or undefined.
Definition qgis.h:5263
RasterRangeLimit
Describes the limits used to compute raster ranges (min/max values).
Definition qgis.h:1694
@ CumulativeCut
Range is [ min + cumulativeCutLower() * (max - min), min + cumulativeCutUpper() * (max - min) ].
Definition qgis.h:1698
@ MinimumMaximum
Real min-max values.
Definition qgis.h:1696
@ NotSet
User defined.
Definition qgis.h:1695
@ Linear
Interpolates the color between two class breaks linearly.
Definition qgis.h:1575
@ Discrete
Assigns the color of the higher class for every pixel between two class breaks.
Definition qgis.h:1576
@ IsBasemapSource
Associated source should be considered a 'basemap' layer. See Qgis::MapLayerProperty::IsBasemapLayer.
Definition qgis.h:2475
@ Bilinear
Bilinear (2x2 kernel) resampling.
Definition qgis.h:1635
@ Cubic
Cubic Convolution Approximation (4x4 kernel) resampling.
Definition qgis.h:1636
RasterDrawingStyle
Raster drawing styles.
Definition qgis.h:5278
@ SingleBandGray
A single band image drawn as a range of gray colors.
Definition qgis.h:5280
@ SingleBandColorData
ARGB values rendered directly.
Definition qgis.h:5289
@ MultiBandColor
A layer containing 2 or more bands, mapped to RGB color space. In the case of a multiband with only t...
Definition qgis.h:5288
@ PalettedColor
A "Palette" image drawn using color table.
Definition qgis.h:5282
@ SingleBandPseudoColor
A single band image drawn using a pseudocolor algorithm.
Definition qgis.h:5281
@ Undefined
Undefined.
Definition qgis.h:5279
QFlags< RasterInterfaceCapability > RasterInterfaceCapabilities
Raster interface capabilities.
Definition qgis.h:5372
BlendMode
Blending modes defining the available composition modes that can be used when painting.
Definition qgis.h:5429
@ Size
Original data source size (and thus resolution) is known, it is not always available,...
Definition qgis.h:5354
@ IdentifyValue
Numerical values.
Definition qgis.h:5359
@ IdentifyFeature
WMS GML -> feature.
Definition qgis.h:5362
QFlags< DataProviderReadFlag > DataProviderReadFlags
Flags which control data provider construction.
Definition qgis.h:512
@ ExcludeByDefault
If set, the layer should not be included in legends by default, and must be manually added by a user.
Definition qgis.h:5012
DataType
Raster data types.
Definition qgis.h:393
@ CInt32
Complex Int32.
Definition qgis.h:404
@ Float32
Thirty two bit floating point (float).
Definition qgis.h:401
@ CFloat64
Complex Float64.
Definition qgis.h:406
@ Int16
Sixteen bit signed integer (qint16).
Definition qgis.h:398
@ ARGB32_Premultiplied
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32_Premultiplied.
Definition qgis.h:408
@ Int8
Eight bit signed integer (qint8) (added in QGIS 3.30).
Definition qgis.h:396
@ UInt16
Sixteen bit unsigned integer (quint16).
Definition qgis.h:397
@ Byte
Eight bit unsigned integer (quint8).
Definition qgis.h:395
@ ARGB32
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32.
Definition qgis.h:407
@ Int32
Thirty two bit signed integer (qint32).
Definition qgis.h:400
@ Float64
Sixty four bit floating point (double).
Definition qgis.h:402
@ CFloat32
Complex Float32.
Definition qgis.h:405
@ CInt16
Complex Int16.
Definition qgis.h:403
@ UInt32
Thirty two bit unsigned integer (quint32).
Definition qgis.h:399
@ Raster
Raster layer.
Definition qgis.h:208
@ WholeRaster
Whole raster is used to compute statistics.
Definition qgis.h:1711
@ FixedCanvas
Current extent of the canvas (at the time of computation) is used to compute statistics.
Definition qgis.h:1712
QFlags< MapLayerProperty > MapLayerProperties
Map layer properties.
Definition qgis.h:2451
@ LoadDefaultStyle
Reset the layer's style to the default for the datasource.
Definition qgis.h:495
@ SkipGetExtent
Skip the extent from provider.
Definition qgis.h:496
@ TrustDataSource
Trust datasource config (primary key unicity, geometry type and srid, etc). Improves provider load ti...
Definition qgis.h:492
RasterColorInterpretation
Raster color interpretation.
Definition qgis.h:5211
@ AlphaBand
Alpha (0=transparent, 255=opaque).
Definition qgis.h:5218
@ PaletteIndex
Paletted (see associated color table).
Definition qgis.h:5214
@ ContinuousPalette
Continuous palette, QGIS addition, GRASS.
Definition qgis.h:5229
RasterIdentifyFormat
Raster identify formats.
Definition qgis.h:5331
@ Feature
WMS GML/JSON -> feature.
Definition qgis.h:5336
@ Value
Numerical pixel value.
Definition qgis.h:5333
@ Undefined
Undefined.
Definition qgis.h:5332
@ Preferred
Preferred format, matching the most recent WKT ISO standard. Currently an alias to WKT2_2019,...
Definition qgis.h:2611
Abstract base class for objects which generate elevation profiles.
Abstract base class for labeling settings for raster layers.
static QgsAbstractRasterLayerLabeling * createFromElement(const QDomElement &element, const QgsReadWriteContext &context)
Tries to create an instance of an implementation based on the XML data.
static QgsRasterRendererRegistry * rasterRendererRegistry()
Returns the application's raster renderer registry, used for managing raster layer renderers.
static QgsRuntimeProfiler * profiler()
Returns the application runtime profiler.
Brightness/contrast and gamma correction filter pipe for rasters.
int contrast() const
Returns current contrast level.
int brightness() const
Returns current brightness level.
A ramp shader will color a raster pixel based on a list of values ranges in a ramp.
bool shade(double value, int *returnRedValue, int *returnGreenValue, int *returnBlueValue, int *returnAlphaValue) const override
Generates an new RGBA value based on one input value.
void classifyColorRamp(int classes=0, int band=-1, const QgsRectangle &extent=QgsRectangle(), QgsRasterInterface *input=nullptr)
Classify color ramp shader.
void setColorRampType(Qgis::ShaderInterpolationMethod colorRampType)
Sets the color ramp interpolation method.
void setColorRampItemList(const QList< QgsColorRampShader::ColorRampItem > &list)
Sets a custom color map.
Handles contrast enhancement and clipping.
ContrastEnhancementAlgorithm
This enumerator describes the types of contrast enhancement algorithms that can be used.
@ StretchToMinimumMaximum
Linear histogram.
@ NoEnhancement
Default color scaling algorithm, no scaling is applied.
static QString contrastEnhancementAlgorithmString(ContrastEnhancementAlgorithm algorithm)
Returns a string to serialize ContrastEnhancementAlgorithm.
static ContrastEnhancementAlgorithm contrastEnhancementAlgorithmFromString(const QString &contrastEnhancementString)
Deserialize ContrastEnhancementAlgorithm.
ContrastEnhancementAlgorithm contrastEnhancementAlgorithm() const
Represents a coordinate reference system (CRS).
Contains information about the context in which a coordinate transform is executed.
Cubic Raster Resampler.
Abstract base class for spatial data provider implementations.
Stores the component parts of a data source URI (e.g.
QByteArray encodedUri() const
Returns the complete encoded URI as a byte array.
void setEncodedUri(const QByteArray &uri)
Sets the complete encoded uri.
void setParam(const QString &key, const QString &value)
Sets a generic parameter value on the URI.
Color and saturation filter pipe for rasters.
Formats layer metadata into HTML.
QString linksSectionHtml() const
Formats the "Links" section according to a metadata object.
QString extentSectionHtml(const bool showSpatialExtent=true) const
Formats the "Extents" section according to a metadata object (extent and temporal).
QString contactsSectionHtml() const
Formats the "Contacts" section according to a metadata object.
QString identificationSectionHtml() const
Formats the "Identification" section according to a metadata object.
QString historySectionHtml() const
Formats the "History" section according to a metadata object.
QString accessSectionHtml() const
Formats the "Access" section according to a metadata object.
Base class for storage of map layer elevation properties.
static QString typeToString(Qgis::LayerType type)
Converts a map layer type to a string value.
An abstract interface for implementations of legends for one map layer.
virtual void readXml(const QDomElement &elem, const QgsReadWriteContext &context)
Reads configuration from a DOM element previously written by writeXml().
virtual QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const
Writes configuration to a DOM element, to be used later with readXml().
static QgsMapLayerLegend * defaultRasterLegend(QgsRasterLayer *rl)
Create new legend implementation for raster layer.
void setFlag(Qgis::MapLayerLegendFlag flag, bool on=true)
Enables or disables a particular flag (other flags are not affected).
Base class for utility classes that encapsulate information necessary for rendering of map layers.
QString title() const
Returns the title of the layer used by QGIS Server in GetCapabilities request.
QString abstract() const
Returns the abstract of the layerused by QGIS Server in GetCapabilities request.
Base class for storage of map layer temporal properties.
QString name
Definition qgsmaplayer.h:87
void readStyleManager(const QDomNode &layerNode)
Read style manager's configuration (if any). To be called by subclasses.
void setError(const QgsError &error)
Sets error message.
void writeStyleManager(QDomNode &layerNode, QDomDocument &doc) const
Write style manager's configuration (if exists). To be called by subclasses.
QgsMapLayerLegend * legend() const
Can be nullptr.
virtual Q_INVOKABLE QgsRectangle extent() const
Returns the extent of the layer.
QString source() const
Returns the source for the layer.
Q_INVOKABLE QVariant customProperty(const QString &value, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer.
void setBlendMode(QPainter::CompositionMode blendMode)
Set the blending mode used for rendering a layer.
void configChanged()
Emitted whenever the configuration is changed.
static Qgis::DataProviderReadFlags providerReadFlags(const QDomNode &layerNode, QgsMapLayer::ReadFlags layerReadFlags)
Returns provider read flag deduced from layer read flags layerReadFlags and a dom node layerNode that...
QgsCoordinateReferenceSystem crs
Definition qgsmaplayer.h:90
QgsMapLayerServerProperties * serverProperties()
Returns QGIS Server Properties for the map layer.
virtual QString loadDefaultStyle(bool &resultFlag)
Retrieve the default style for this layer if one exists (either as a .qml file on disk or as a record...
void setDataSource(const QString &dataSource, const QString &baseName=QString(), const QString &provider=QString(), bool loadDefaultStyleFlag=false)
Updates the data source of the layer.
QString mLayerName
Name of the layer - used for display.
void triggerRepaint(bool deferredUpdate=false)
Will advise the map canvas (and any other interested party) that this layer requires to be repainted.
QString crsHtmlMetadata() const
Returns a HTML fragment containing the layer's CRS metadata, for use in the htmlMetadata() method.
QgsLayerMetadata metadata
Definition qgsmaplayer.h:89
Q_DECL_DEPRECATED QString abstract() const
Returns the abstract of the layer used by QGIS Server in GetCapabilities request.
QgsMapLayer(Qgis::LayerType type=Qgis::LayerType::Vector, const QString &name=QString(), const QString &source=QString())
Constructor for QgsMapLayer.
QPainter::CompositionMode blendMode() const
Returns the current blending mode for a layer.
void statusChanged(const QString &status)
Emit a signal with status (e.g. to be caught by QgisApp and display a msg on status bar).
virtual void setMetadata(const QgsLayerMetadata &metadata)
Sets the layer's metadata store.
QFlags< StyleCategory > StyleCategories
Q_INVOKABLE void setCustomProperty(const QString &key, const QVariant &value)
Set a custom property for layer.
QString mProviderKey
Data provider key (name of the data provider).
QgsCoordinateTransformContext transformContext() const
Returns the layer data provider coordinate transform context or a default transform context if the la...
std::unique_ptr< QgsDataProvider > mPreloadedProvider
Optionally used when loading a project, it is released when the layer is effectively created.
void rendererChanged()
Signal emitted when renderer is changed.
Q_DECL_DEPRECATED QString title() const
Returns the title of the layer used by QGIS Server in GetCapabilities request.
virtual QgsError error() const
Gets current status error.
QgsMapLayer::LayerFlags flags
Definition qgsmaplayer.h:99
bool hasScaleBasedVisibility() const
Returns whether scale based visibility is enabled for the layer.
void opacityChanged(double opacity)
Emitted when the layer's opacity is changed, where opacity is a value between 0 (transparent) and 1 (...
void emitStyleChanged()
Triggers an emission of the styleChanged() signal.
void dataChanged()
Data of layer changed.
void willBeDeleted()
Emitted in the destructor when the layer is about to be deleted, but it is still in a perfectly valid...
virtual QgsMapLayer * clone() const =0
Returns a new instance equivalent to this one except for the id which is still unique.
void setName(const QString &name)
Set the display name of the layer.
virtual void setExtent(const QgsRectangle &rect)
Sets the extent.
void appendError(const QgsErrorMessage &error)
Add error message.
QString mDataSource
Data source description string, varies by layer type.
void setMapTipsEnabled(bool enabled)
Enable or disable map tips for this layer.
@ FlagReadExtentFromXml
Read extent from xml and skip get extent from provider.
@ FlagTrustLayerMetadata
Trust layer metadata. Improves layer load time by skipping expensive checks like primary key unicity,...
@ FlagDontResolveLayers
Don't resolve layer paths or create data providers for layers.
void setValid(bool valid)
Sets whether layer is valid or not.
void readCommonStyle(const QDomElement &layerElement, const QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories)
Read style data common to all layer types.
QgsMapLayer::ReadFlags mReadFlags
Read flags. It's up to the subclass to respect these when restoring state from XML.
double minimumScale() const
Returns the minimum map scale (i.e.
void repaintRequested(bool deferredUpdate=false)
By emitting this signal the layer tells that either appearance or content have been changed and any v...
void setMapTipTemplate(const QString &mapTipTemplate)
The mapTip is a pretty, html representation for feature information.
bool mapTipsEnabled
Definition qgsmaplayer.h:97
@ AttributeTable
Attribute table settings: choice and order of columns, conditional styling.
@ Symbology
Symbology.
@ MapTips
Map tips.
@ Rendering
Rendering: scale visibility, simplify method, opacity.
@ Legend
Legend settings.
@ Labeling
Labeling.
void setProviderType(const QString &providerType)
Sets the providerType (provider key).
QString customPropertyHtmlMetadata() const
Returns an HTML fragment containing custom property information, for use in the htmlMetadata() method...
QString generalHtmlMetadata() const
Returns an HTML fragment containing general metadata information, for use in the htmlMetadata() metho...
void writeCommonStyle(QDomElement &layerElement, QDomDocument &document, const QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories) const
Write style data common to all layer types.
double maximumScale() const
Returns the maximum map scale (i.e.
void invalidateWgs84Extent()
Invalidates the WGS84 extent.
QString mapTipTemplate
Definition qgsmaplayer.h:96
bool mShouldValidateCrs
true if the layer's CRS should be validated and invalid CRSes are not permitted.
void setCrs(const QgsCoordinateReferenceSystem &srs, bool emitSignal=true)
Sets layer's spatial reference system.
Perform transforms between map coordinates and device coordinates.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE(), Qgis::StringFormat format=Qgis::StringFormat::PlainText)
Adds a message to the log instance (and creates it if necessary).
Renderer for multiband images with the color components.
int blueBand() const
Returns the band number for the blue channel.
void setGreenContrastEnhancement(QgsContrastEnhancement *ce)
Sets the contrast enhancement to use for the green channel.
void setBlueContrastEnhancement(QgsContrastEnhancement *ce)
Sets the contrast enhancement to use for the blue channel.
void setRedContrastEnhancement(QgsContrastEnhancement *ce)
Sets the contrast enhancement to use for the red channel.
const QgsContrastEnhancement * redContrastEnhancement() const
Returns the contrast enhancement to use for the red channel.
int redBand() const
Returns the band number for the red channel.
int greenBand() const
Returns the band number for the green channel.
static Qgis::BlendMode getBlendModeEnum(QPainter::CompositionMode blendMode)
Returns a Qgis::BlendMode corresponding to a QPainter::CompositionMode.
static QPainter::CompositionMode getCompositionMode(Qgis::BlendMode blendMode)
Returns a QPainter::CompositionMode corresponding to a Qgis::BlendMode.
QString writePath(const QString &filename) const
Prepare a filename to save it to the project file.
QString readPath(const QString &filename) const
Turn filename read from the project file to an absolute path.
Represents a 2D point.
Definition qgspointxy.h:62
Encapsulates properties and constraints relating to fetching elevation profiles from different source...
static void convertRasterProperties(QDomDocument &doc, QDomNode &parentNode, QDomElement &rasterPropertiesElem, QgsRasterLayer *rlayer)
QString absoluteToRelativeUri(const QString &providerKey, const QString &uri, const QgsReadWriteContext &context) const
Converts absolute path(s) to relative path(s) in the given provider-specific URI.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
QString relativeToAbsoluteUri(const QString &providerKey, const QString &uri, const QgsReadWriteContext &context) const
Converts relative path(s) to absolute path(s) in the given provider-specific URI.
Represents a Raster Attribute Table (RAT).
QString filePath() const
Returns the (possibly empty) path of the file-based RAT, the path is set when a RAT is read or writte...
The RasterBandStats struct is a container for statistics about a single raster band.
double minimumValue
The minimum cell value in the raster band.
double maximumValue
The maximum cell value in the raster band.
static int typeSize(Qgis::DataType dataType)
Returns the size in bytes for the specified dataType.
static QString printValue(double value, bool localized=false)
Print double value with all necessary significant digits.
Handles elevation related properties for a raster data provider.
Base class for raster data providers.
QDateTime timestamp() const override
Time stamp of data source in the moment when data/metadata were loaded by provider.
QgsRectangle extent() const override=0
Returns the extent of the layer.
QDateTime dataTimestamp() const override
Current time stamp of data source.
void statusChanged(const QString &) const
Emit a message to be displayed on status bar, usually used by network providers (WMS,...
static QString identifyFormatName(Qgis::RasterIdentifyFormat format)
Converts a raster identify format to a string name.
The drawing pipe for raster layers.
void draw(QPainter *p, QgsRasterViewPort *viewPort, const QgsMapToPixel *qgsMapToPixel, QgsRasterBlockFeedback *feedback=nullptr)
Draws raster data.
Base class for processing filters like renderers, reprojector, resampler etc.
Q_DECL_DEPRECATED QgsRasterBandStats bandStatistics(int bandNo, int stats, const QgsRectangle &extent=QgsRectangle(), int sampleSize=0, QgsRasterBlockFeedback *feedback=nullptr)
Returns the band statistics.
Q_DECL_DEPRECATED bool hasStatistics(int bandNo, int stats, const QgsRectangle &extent=QgsRectangle(), int sampleSize=0)
Returns true if histogram is available (cached, already calculated).
virtual void writeXml(QDomDocument &doc, QDomElement &parentElem) const
Write base class members to xml.
virtual QgsRasterInterface * input() const
Current input.
Iterator for sequentially processing raster cells.
Raster layer specific subclass of QgsMapLayerElevationProperties.
Implementation of QgsAbstractProfileGenerator for raster layers.
Implementation of threaded rendering for raster layers.
Implementation of map layer temporal properties for raster layers.
static void computeMinMax(QgsRasterDataProvider *provider, int band, const QgsRasterMinMaxOrigin &mmo, Qgis::RasterRangeLimit limits, const QgsRectangle &extent, int sampleSize, double &min, double &max)
Compute the min max values for provider along band according to MinMaxOrigin parameters mmo and exten...
QString htmlMetadata() const override
Obtain a formatted HTML string containing assorted metadata for this layer.
bool canCreateRasterAttributeTable()
Returns true if the raster renderer is suitable for creation of a raster attribute table.
void subsetStringChanged()
Emitted when the layer's subset string has changed.
static const QgsSettingsEntryString * settingsRasterDefaultContrastEnhancementLimits
Qgis::MapLayerProperties properties() const override
Returns the map layer properties of this layer.
QString encodedSource(const QString &source, const QgsReadWriteContext &context) const override
Called by writeLayerXML(), used by derived classes to encode provider's specific data source to proje...
const QgsAbstractRasterLayerLabeling * labeling() const
Access to const labeling configuration.
Q_DECL_DEPRECATED QgsLegendColorList legendSymbologyItems() const
Returns a list with classification items (Text and color).
QgsMapLayerRenderer * createMapRenderer(QgsRenderContext &rendererContext) override
Returns new instance of QgsMapLayerRenderer that will be used for rendering of given context.
void showStatusMessage(const QString &message)
QgsRasterAttributeTable * attributeTable(int bandNumber) const
Returns the (possibly NULL) raster attribute table for the given band bandNumber.
virtual bool setSubsetString(const QString &subset)
Sets the string (typically sql) used to define a subset of the layer.
QgsRasterResampleFilter * resampleFilter() const
Returns the raster's resample filter.
bool writeSymbology(QDomNode &, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories) const override
Write the style for the layer into the document provided.
QgsRasterLayer * clone() const override
Returns a new instance equivalent to this one.
void setResamplingStage(Qgis::RasterResamplingStage stage)
Select which stage of the pipe should apply resampling.
Qgis::RasterResamplingStage resamplingStage() const
Returns which stage of the pipe should apply resampling.
static const QgsSettingsEntryBool * settingsRasterDefaultEarlyResampling
int attributeTableCount() const
Returns the number of attribute tables for the raster by counting the number of bands that have an as...
void refreshContrastEnhancement(const QgsRectangle &extent)
Refresh contrast enhancement with new extent.
int height() const
Returns the height of the (unclipped) raster.
static const Qgis::RasterRangeLimit SINGLE_BAND_MIN_MAX_LIMITS
Default enhancement limits for single band raster.
Q_DECL_DEPRECATED void setDataProvider(const QString &provider)
Set the data provider.
static const QgsContrastEnhancement::ContrastEnhancementAlgorithm MULTIPLE_BAND_SINGLE_BYTE_ENHANCEMENT_ALGORITHM
Default enhancement algorithm for multiple band raster of type Byte.
int bandCount() const
Returns the number of bands in this layer.
QgsMapLayerTemporalProperties * temporalProperties() override
Returns the layer's temporal properties.
static const QgsSettingsEntryString * settingsRasterDefaultContrastEnhancementAlgorithm
bool ignoreExtents() const
If the ignoreExtent flag is set, the layer will also render outside the bounding box reported by the ...
QString decodedSource(const QString &source, const QString &provider, const QgsReadWriteContext &context) const override
Called by readLayerXML(), used by derived classes to decode provider's specific data source from proj...
double opacity() const final
Returns the opacity for the layer, where opacity is a value between 0 (totally transparent) and 1....
void computeMinMax(int band, const QgsRasterMinMaxOrigin &mmo, Qgis::RasterRangeLimit limits, const QgsRectangle &extent, int sampleSize, double &min, double &max)
Compute the min max values along band according to MinMaxOrigin parameters mmo and extent.
bool labelsEnabled() const
Returns whether the layer contains labels which are enabled and should be drawn.
void setSubLayerVisibility(const QString &name, bool vis) override
Set the visibility of the given sublayer name.
static const QgsSettingsEntryDouble * settingsRasterDefaultOversampling
void setLabeling(QgsAbstractRasterLayerLabeling *labeling)
Sets labeling configuration.
virtual QString subsetString() const
Returns the string (typically sql) used to define a subset of the layer.
QgsAbstractProfileGenerator * createProfileGenerator(const QgsProfileRequest &request) override
Given a profile request, returns a new profile generator ready for generating elevation profiles.
QgsBrightnessContrastFilter * brightnessFilter() const
Returns the raster's brightness/contrast filter.
bool writeXml(QDomNode &layer_node, QDomDocument &doc, const QgsReadWriteContext &context) const override
Called by writeLayerXML(), used by children to write state specific to them to project files.
bool writeStyle(QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories) const override
Write just the symbology information for the layer into the document.
double rasterUnitsPerPixelX() const
Returns the number of raster units per each raster pixel in X axis.
void reload() override
Synchronises with changes in the datasource.
bool accept(QgsStyleEntityVisitorInterface *visitor) const override
Accepts the specified symbology visitor, causing it to visit all symbols associated with the layer.
QImage previewAsImage(QSize size, const QColor &bgColor=Qt::white, QImage::Format format=QImage::Format_ARGB32_Premultiplied)
Draws a preview of the rasterlayer into a QImage.
QStringList subLayers() const override
Returns the sublayers of this layer.
static const Qgis::RasterRangeLimit MULTIPLE_BAND_MULTI_BYTE_MIN_MAX_LIMITS
Default enhancement limits for multiple band raster of type different from Byte.
void setContrastEnhancement(QgsContrastEnhancement::ContrastEnhancementAlgorithm algorithm, Qgis::RasterRangeLimit limits=Qgis::RasterRangeLimit::MinimumMaximum, const QgsRectangle &extent=QgsRectangle(), int sampleSize=QgsRasterLayer::SAMPLE_SIZE, bool generateLookupTableFlag=true)
Set contrast enhancement algorithm.
static const QgsSettingsEntryString * settingsRasterDefaultZoomedInResampling
void setDefaultContrastEnhancement()
Sets the default contrast enhancement.
QgsRasterRenderer * renderer() const
Returns the raster's renderer.
static const double SAMPLE_SIZE
Default sample size (number of pixels) for estimated statistics/histogram calculation.
static const QgsContrastEnhancement::ContrastEnhancementAlgorithm MULTIPLE_BAND_MULTI_BYTE_ENHANCEMENT_ALGORITHM
Default enhancement algorithm for multiple band raster of type different from Byte.
static const Qgis::RasterRangeLimit MULTIPLE_BAND_SINGLE_BYTE_MIN_MAX_LIMITS
Default enhancement limits for multiple band raster of type Byte.
bool readXml(const QDomNode &layer_node, QgsReadWriteContext &context) override
Called by readLayerXML(), used by children to read state specific to them from project files.
void setLabelsEnabled(bool enabled)
Sets whether labels should be enabled for the layer.
QString bandName(int bandNoInt) const
Returns the name of a band given its number.
QgsRasterDataProvider * dataProvider() override
Returns the source data provider.
static bool isValidRasterFileName(const QString &fileNameQString, QString &retError)
This helper checks to see whether the file name appears to be a valid raster file name.
bool isSpatial() const override
Returns true if the layer is considered a spatial layer, ie it has some form of geometry associated w...
void setOpacity(double opacity) final
Sets the opacity for the layer, where opacity is a value between 0 (totally transparent) and 1....
double rasterUnitsPerPixelY() const
Returns the number of raster units per each raster pixel in Y axis.
int width() const
Returns the width of the (unclipped) raster.
QgsMapLayerElevationProperties * elevationProperties() override
Returns the layer's elevation properties.
bool readSymbology(const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories) override
Read the symbology for the current layer from the DOM node supplied.
static const QgsSettingsEntryString * settingsRasterDefaultZoomedOutResampling
void draw(QPainter *theQPainter, QgsRasterViewPort *myRasterViewPort, const QgsMapToPixel *qgsMapToPixel=nullptr)
This is an overloaded version of the draw() function that is called by both draw() and thumbnailAsPix...
Q_DECL_DEPRECATED bool writeSld(QDomNode &node, QDomDocument &doc, QString &errorMessage, const QVariantMap &props=QVariantMap()) const
Writes the symbology of the layer into the document provided in SLD 1.0.0 format.
static QDateTime lastModified(const QString &name)
Returns time stamp for given file name.
static const QgsContrastEnhancement::ContrastEnhancementAlgorithm SINGLE_BAND_ENHANCEMENT_ALGORITHM
Default enhancement algorithm for single band raster.
~QgsRasterLayer() override
QDateTime timestamp() const override
Time stamp of data source in the moment when data/metadata were loaded by provider.
void setTransformContext(const QgsCoordinateTransformContext &transformContext) override
Sets the coordinate transform context to transformContext.
void setRenderer(QgsRasterRenderer *renderer)
Sets the raster's renderer.
QgsRasterLayer()
Constructor. Provider is not set.
void setLayerOrder(const QStringList &layers) override
Reorders the previously selected sublayers of this layer from bottom to top.
bool defaultContrastEnhancementSettings(QgsContrastEnhancement::ContrastEnhancementAlgorithm &myAlgorithm, Qgis::RasterRangeLimit &myLimits) const
Returns default contrast enhancement settings for that type of raster.
QgsHueSaturationFilter * hueSaturationFilter() const
Returns the raster's hue/saturation filter.
bool readStyle(const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories) override
Read the style for the current layer from the DOM node supplied.
QPixmap paletteAsPixmap(int bandNumber=1)
Returns a 100x100 pixmap of the color palette.
Describes the origin of minimum and maximum values in a raster.
static QString limitsString(Qgis::RasterRangeLimit limits)
Returns a string to serialize Limits.
void setLimits(Qgis::RasterRangeLimit limits)
Sets the limits.
void setExtent(Qgis::RasterRangeExtent extent)
Sets the extent.
Qgis::RasterRangeExtent extent() const
Returns the raster extent.
static Qgis::RasterRangeLimit limitsFromString(const QString &limits)
Deserialize Limits.
Qgis::RasterRangeLimit limits() const
Returns the raster limits.
Contains a pipeline of raster interfaces for sequential raster processing.
static QgsPropertiesDefinition propertyDefinitions()
Returns the definitions for data defined properties available for use in raster pipes.
Implements approximate projection support for optimised raster transformation.
Q_DECL_DEPRECATED void setCrs(const QgsCoordinateReferenceSystem &srcCRS, const QgsCoordinateReferenceSystem &destCRS, int srcDatumTransform=-1, int destDatumTransform=-1)
Sets the source and destination CRS.
Represents a range of raster values between min and max, optionally including the min and max value.
double min() const
Returns the minimum value for the range.
Raster renderer pipe that applies colors to a raster.
virtual QString type() const
Returns a unique string representation of the renderer type.
virtual bool canCreateRasterAttributeTable() const
Returns true if the renderer is suitable for attribute table creation.
void setMinMaxOrigin(const QgsRasterMinMaxOrigin &origin)
Sets origin of min/max values.
const QgsRasterMinMaxOrigin & minMaxOrigin() const
Returns const reference to origin of min/max values.
virtual bool refresh(const QgsRectangle &extent, const QList< double > &min, const QList< double > &max, bool forceRefresh=false)
Refreshes the renderer according to the min and max values associated with the extent.
Resample filter pipe for rasters.
Interface for all raster shaders.
void setRasterShaderFunction(QgsRasterShaderFunction *function)
A public method that allows the user to set their own shader function.
Allows entering a context category and takes care of leaving this category on deletion of the class.
A container for the context for various read/write operations on objects.
QgsReadWriteContextCategoryPopper enterCategory(const QString &category, const QString &details=QString()) const
Push a category to the stack.
QgsCoordinateTransformContext transformContext() const
Returns data provider coordinate transform context.
const QgsPathResolver & pathResolver() const
Returns path resolver for conversion between relative and absolute paths.
A rectangle specified with double values.
Q_INVOKABLE QString toString(int precision=16) const
Returns a string representation of form xmin,ymin : xmax,ymax Coordinates will be rounded to the spec...
Contains information about the context of a rendering operation.
A boolean settings entry.
A double settings entry.
A string settings entry.
static QgsSettingsTreeNode * sTreeRaster
Raster renderer pipe for single band gray.
void setContrastEnhancement(QgsContrastEnhancement *ce)
Takes ownership.
int inputBand() const override
Returns the input band for the renderer, or -1 if no input band is available.
Raster renderer pipe for single band pseudocolor.
void setShader(QgsRasterShader *shader)
Takes ownership of the shader.
QgsRasterShader * shader()
Returns the raster shader.
int inputBand() const override
Returns the input band for the renderer, or -1 if no input band is available.
Holds SLD export options and other information related to SLD export of a QGIS layer style.
void setExtraProperties(const QVariantMap &properties)
Sets the open ended set of properties that can drive/inform the SLD encoding.
QVariantMap extraProperties() const
Returns the open ended set of properties that can drive/inform the SLD encoding.
An interface for classes which can visit style entity (e.g.
static void mergeScaleDependencies(double mScaleMinDenom, double mScaleMaxDenom, QVariantMap &props)
Merges the local scale limits, if any, with the ones already in the map, if any.
static QgsRectangle readRectangle(const QDomElement &element)
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into allowing algorithms to be written in pure substantial changes are required in order to port existing x Processing algorithms for QGIS x The most significant changes are outlined not GeoAlgorithm For algorithms which operate on features one by consider subclassing the QgsProcessingFeatureBasedAlgorithm class This class allows much of the boilerplate code for looping over features from a vector layer to be bypassed and instead requires implementation of a processFeature method Ensure that your algorithm(or algorithm 's parent class) implements the new pure virtual createInstance(self) call
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
Definition qgis.h:7793
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
Definition qgis.h:7557
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition qgis.h:7451
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:80
#define QgsDebugError(str)
Definition qgslogger.h:71
#define ERR(message)
QgsDataProvider * classFactoryFunction_t(const QString *, const QgsDataProvider::ProviderOptions &options)
QList< QPair< QString, QColor > > QgsLegendColorList
QList< QgsRasterRange > QgsRasterRangeList
#define QGIS_PROTECT_QOBJECT_THREAD_ACCESS
Setting options for creating vector data providers.
Setting options for loading raster layers.
bool skipCrsValidation
Controls whether the layer is allowed to have an invalid/unknown CRS.
bool loadDefaultStyle
Sets to true if the default layer style should be loaded.
QgsCoordinateTransformContext transformContext
Coordinate transform context.
Registry for raster renderer entries.
QgsRasterRendererCreateFunc rendererCreateFunction
This class provides details of the viewable area that a raster will be rendered into.
qgssize mHeight
Height, number of rows to be rendered.
QgsCoordinateReferenceSystem mDestCRS
Target (map) coordinate system.
QgsPointXY mBottomRightPoint
Coordinate (in output device coordinate system) of bottom right corner of the part of the raster that...
QgsPointXY mTopLeftPoint
Coordinate (in output device coordinate system) of top left corner of the part of the raster that is ...
QgsCoordinateReferenceSystem mSrcCRS
Source (layer) coordinate system.
QgsRectangle mDrawnExtent
Intersection of current map extent and layer extent, in map (destination) CRS.
QgsCoordinateTransformContext mTransformContext
Coordinate transform context.
qgssize mWidth
Width, number of columns to be rendered.