QGIS API Documentation 4.1.0-Master (60fea48833c)
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
99
100#define ERR( message ) QGS_ERROR_MESSAGE( message, "Raster layer" )
101
102const double QgsRasterLayer::SAMPLE_SIZE = 250000;
103
107
111
113 : QgsMapLayer( Qgis::LayerType::Raster )
114 , QSTRING_NOT_SET( u"Not Set"_s )
115 , TRSTRING_NOT_SET( tr( "Not Set" ) )
116 , mTemporalProperties( new QgsRasterLayerTemporalProperties( this ) )
117 , mElevationProperties( new QgsRasterLayerElevationProperties( this ) )
118 , mPipe( std::make_unique< QgsRasterPipe >() )
119{
120 init();
121 setValid( false );
122}
123
124QgsRasterLayer::QgsRasterLayer( const QString &uri, const QString &baseName, const QString &providerKey, const LayerOptions &options )
125 : QgsMapLayer( Qgis::LayerType::Raster, baseName, uri )
126 // Constant that signals property not used.
127 , QSTRING_NOT_SET( u"Not Set"_s )
128 , TRSTRING_NOT_SET( tr( "Not Set" ) )
129 , mTemporalProperties( new QgsRasterLayerTemporalProperties( this ) )
130 , mElevationProperties( new QgsRasterLayerElevationProperties( this ) )
131 , mPipe( std::make_unique< QgsRasterPipe >() )
132{
134
135 QgsDebugMsgLevel( u"Entered"_s, 4 );
136 setProviderType( providerKey );
137
138 const QgsDataProvider::ProviderOptions providerOptions { options.transformContext };
139 Qgis::DataProviderReadFlags providerFlags;
140 if ( options.loadDefaultStyle )
141 {
143 }
144
145 setDataSource( uri, baseName, providerKey, providerOptions, providerFlags );
146
147 if ( isValid() )
148 {
149 mTemporalProperties->setDefaultsFromDataProviderTemporalCapabilities( mDataProvider->temporalCapabilities() );
150 }
151
152} // QgsRasterLayer ctor
153
155{
156 emit willBeDeleted();
157
158 mLabeling.reset();
159
160 setValid( false );
161 // Note: provider and other interfaces are owned and deleted by pipe
162}
163
165{
167
169 if ( mDataProvider )
170 {
171 options.transformContext = mDataProvider->transformContext();
172 }
173 auto layer = std::make_unique< QgsRasterLayer >( source(), name(), mProviderKey, options );
174 QgsMapLayer::clone( layer.get() );
175 layer->mElevationProperties = mElevationProperties->clone();
176 layer->mElevationProperties->setParent( layer.get() );
177 layer->setMapTipTemplate( mapTipTemplate() );
178 layer->setMapTipsEnabled( mapTipsEnabled() );
179
180 // do not clone data provider which is the first element in pipe
181 for ( int i = 1; i < mPipe->size(); i++ )
182 {
183 if ( mPipe->at( i ) )
184 layer->pipe()->set( mPipe->at( i )->clone() );
185 }
186 layer->pipe()->setDataDefinedProperties( mPipe->dataDefinedProperties() );
187 layer->setResamplingStage( mPipe->resamplingStage() );
188 if ( mDataProvider && layer->dataProvider() )
189 {
190 layer->dataProvider()->setZoomedInResamplingMethod( mDataProvider->zoomedInResamplingMethod() );
191 layer->dataProvider()->setZoomedOutResamplingMethod( mDataProvider->zoomedOutResamplingMethod() );
192 }
193
194 layer->setLabelsEnabled( mLabelsEnabled );
195 if ( mLabeling )
196 layer->setLabeling( mLabeling->clone() );
197
198 return layer.release();
199}
200
202{
204
205 if ( !mElevationProperties->isEnabled() )
206 return nullptr;
207
208 return new QgsRasterLayerProfileGenerator( this, request );
209}
210
212//
213// Static Methods and members
214//
216
217bool QgsRasterLayer::isValidRasterFileName( const QString &fileNameQString, QString &retErrMsg )
218{
219 const bool myIsValid = QgsGdalProvider::isValidRasterFileName( fileNameQString, retErrMsg );
220 return myIsValid;
221}
222
223bool QgsRasterLayer::isValidRasterFileName( QString const &fileNameQString )
224{
225 QString retErrMsg;
226 return isValidRasterFileName( fileNameQString, retErrMsg );
227}
228
229QDateTime QgsRasterLayer::lastModified( QString const &name )
230{
231 QgsDebugMsgLevel( "name=" + name, 4 );
232 QDateTime t;
233
234 const QFileInfo fi( name );
235
236 // Is it file?
237 if ( !fi.exists() )
238 return t;
239
240 t = fi.lastModified();
241
242 QgsDebugMsgLevel( "last modified = " + t.toString(), 4 );
243
244 return t;
245}
246
253
254// typedef for the QgsDataProvider class factory
256
258//
259// Non Static Public methods
260//
262
264{
266
267 if ( !mDataProvider )
268 return 0;
269 return mDataProvider->bandCount();
270}
271
272QString QgsRasterLayer::bandName( int bandNo ) const
273{
275
276 if ( !mDataProvider )
277 return QString();
278 return mDataProvider->generateBandName( bandNo );
279}
280
282{
284
285 if ( !mDataProvider )
286 return nullptr;
287 return mDataProvider->attributeTable( bandNoInt );
288}
289
291{
293
294 if ( !mDataProvider )
295 return 0;
296
297 int ratCount { 0 };
298 for ( int bandNo = 1; bandNo <= bandCount(); ++bandNo )
299 {
300 if ( attributeTable( bandNo ) )
301 {
302 ratCount++;
303 }
304 }
305 return ratCount;
306}
307
314
315void QgsRasterLayer::setRendererForDrawingStyle( Qgis::RasterDrawingStyle drawingStyle )
316{
318
319 setRenderer( QgsApplication::rasterRendererRegistry()->defaultRendererForDrawingStyle( drawingStyle, mDataProvider ) );
320}
321
328
330{
332
333 return mDataProvider;
334}
335
337{
339
340 if ( mDataProvider )
341 {
342 mDataProvider->reloadData();
343 }
344}
345
352
353
354void QgsRasterLayer::draw( QPainter *theQPainter, QgsRasterViewPort *rasterViewPort, const QgsMapToPixel *qgsMapToPixel )
355{
357
358 QgsDebugMsgLevel( u" 3 arguments"_s, 4 );
359 QElapsedTimer time;
360 time.start();
361 //
362 //
363 // The goal here is to make as many decisions as possible early on (outside of the rendering loop)
364 // so that we can maximise performance of the rendering process. So now we check which drawing
365 // procedure to use :
366 //
367
368 QgsRasterProjector *projector = mPipe->projector();
369 bool restoreOldResamplingStage = false;
370 const Qgis::RasterResamplingStage oldResamplingState = resamplingStage();
371 // TODO add a method to interface to get provider and get provider
372 // params in QgsRasterProjector
373
374 if ( projector )
375 {
376 // Force provider resampling if reprojection is needed
377 if ( mDataProvider
378 && ( mDataProvider->providerCapabilities() & Qgis::RasterProviderCapability::ProviderHintCanPerformProviderResampling )
379 && rasterViewPort->mSrcCRS != rasterViewPort->mDestCRS
380 && oldResamplingState != Qgis::RasterResamplingStage::Provider )
381 {
382 restoreOldResamplingStage = true;
384 }
385 projector->setCrs( rasterViewPort->mSrcCRS, rasterViewPort->mDestCRS, rasterViewPort->mTransformContext );
386 }
387
388 // Drawer to pipe?
389 QgsRasterIterator iterator( mPipe->last() );
390 QgsRasterDrawer drawer( &iterator );
391 drawer.draw( theQPainter, rasterViewPort, qgsMapToPixel );
392
393 if ( restoreOldResamplingStage )
394 {
395 setResamplingStage( oldResamplingState );
396 }
397
398 QgsDebugMsgLevel( u"total raster draw time (ms): %1"_s.arg( time.elapsed(), 5 ), 4 );
399}
400
402{
404
405 QgsRasterRenderer *renderer = mPipe->renderer();
406 return renderer ? renderer->legendSymbologyItems() : QList< QPair< QString, QColor > >();
407 ;
408}
409
411{
413
414 if ( !mDataProvider )
415 return QString();
416
417 const QgsLayerMetadataFormatter htmlFormatter( metadata() );
418 QString myMetadata = u"<html><head></head>\n<body>\n"_s;
419
420 myMetadata += generalHtmlMetadata();
421
422 // Begin Provider section
423 myMetadata += u"<h1>"_s + tr( "Information from provider" ) + u"</h1>\n<hr>\n"_s + u"<table class=\"list-view\">\n"_s;
424
425 myMetadata += u"\n"_s
426 %
427 // Extent
428 u"<tr><td class=\"highlight\">"_s
429 % tr( "Extent" )
430 % u"</td><td>"_s
431 % extent().toString()
432 % u"</td></tr>\n"_s
433 %
434
435 // Raster Width
436 u"<tr><td class=\"highlight\">"_s % tr( "Width" ) % u"</td><td>"_s;
437 if ( dataProvider()->capabilities() & Qgis::RasterInterfaceCapability::Size )
438 myMetadata += QString::number( width() );
439 else
440 myMetadata += tr( "n/a" );
441 myMetadata += u"</td></tr>\n"_s %
442
443 // Raster height
444 u"<tr><td class=\"highlight\">"_s
445 + tr( "Height" )
446 + u"</td><td>"_s;
447 if ( dataProvider()->capabilities() & Qgis::RasterInterfaceCapability::Size )
448 myMetadata += QString::number( height() );
449 else
450 myMetadata += tr( "n/a" );
451 myMetadata += u"</td></tr>\n"_s
452 %
453
454 // Data type
455 u"<tr><td class=\"highlight\">"_s % tr( "Data type" ) % u"</td><td>"_s;
456 // Just use the first band
457 switch ( mDataProvider->sourceDataType( 1 ) )
458 {
460 myMetadata += tr( "Byte - Eight bit unsigned integer" );
461 break;
463 myMetadata += tr( "Int8 - Eight bit signed integer" );
464 break;
466 myMetadata += tr( "UInt16 - Sixteen bit unsigned integer " );
467 break;
469 myMetadata += tr( "Int16 - Sixteen bit signed integer " );
470 break;
472 myMetadata += tr( "UInt32 - Thirty two bit unsigned integer " );
473 break;
475 myMetadata += tr( "Int32 - Thirty two bit signed integer " );
476 break;
478 myMetadata += tr( "Float32 - Thirty two bit floating point " );
479 break;
481 myMetadata += tr( "Float64 - Sixty four bit floating point " );
482 break;
484 myMetadata += tr( "CInt16 - Complex Int16 " );
485 break;
487 myMetadata += tr( "CInt32 - Complex Int32 " );
488 break;
490 myMetadata += tr( "CFloat32 - Complex Float32 " );
491 break;
493 myMetadata += tr( "CFloat64 - Complex Float64 " );
494 break;
495 default:
496 myMetadata += tr( "Could not determine raster data type." );
497 }
498 myMetadata += u"</td></tr>\n"_s
499 %
500
501 // Insert provider-specific (e.g. WMS-specific) metadata
502 mDataProvider->htmlMetadata()
503 %
504
505 // End Provider section
506 u"</table>\n<br><br>"_s;
507
508 // CRS
509 myMetadata += crsHtmlMetadata();
510
511 // Identification section
512 myMetadata += u"<h1>"_s
513 % tr( "Identification" )
514 % u"</h1>\n<hr>\n"_s
515 % htmlFormatter.identificationSectionHtml()
516 % u"<br><br>\n"_s
517 %
518
519 // extent section
520 u"<h1>"_s
521 % tr( "Extent" )
522 % u"</h1>\n<hr>\n"_s
523 % htmlFormatter.extentSectionHtml()
524 % u"<br><br>\n"_s
525 %
526
527 // Start the Access section
528 u"<h1>"_s
529 % tr( "Access" )
530 % u"</h1>\n<hr>\n"_s
531 % htmlFormatter.accessSectionHtml()
532 % u"<br><br>\n"_s
533 %
534
535 // Bands section
536 u"</table>\n<br><br><h1>"_s
537 % tr( "Bands" )
538 % u"</h1>\n<hr>\n<table class=\"list-view\">\n"_s
539 %
540
541 // Band count
542 u"<tr><td class=\"highlight\">"_s % tr( "Band count" ) % u"</td><td>"_s % QString::number( bandCount() ) % u"</td></tr>\n"_s;
543
544 // Band table
545 myMetadata += u"</table>\n<br><table width=\"100%\" class=\"tabular-view\">\n"_s
546 % u"<tr><th>"_s
547 % tr( "Number" )
548 % u"</th><th>"_s
549 % tr( "Band" )
550 % u"</th><th>"_s
551 % tr( "NoData" )
552 % u"</th><th>"_s
553 % tr( "Min" )
554 % u"</th><th>"_s
555 % tr( "Max" )
556 % u"</th></tr>\n"_s;
557
558 QgsRasterDataProvider *provider = const_cast< QgsRasterDataProvider * >( mDataProvider );
559 for ( int i = 1; i <= bandCount(); i++ )
560 {
561 QString rowClass;
562 if ( i % 2 )
563 rowClass = u"class=\"odd-row\""_s;
564
565 myMetadata += u"<tr "_s % rowClass % u"><td>"_s % QString::number( i ) % u"</td><td>"_s % bandName( i ) % u"</td><td>"_s;
566
567 if ( dataProvider()->sourceHasNoDataValue( i ) )
568 myMetadata += QString::number( dataProvider()->sourceNoDataValue( i ) );
569 else
570 myMetadata += tr( "n/a" );
571 myMetadata += "</td>"_L1;
572
573 if ( provider->hasStatistics( i, Qgis::RasterBandStatistic::Min | Qgis::RasterBandStatistic::Max, provider->extent(), static_cast<int>( SAMPLE_SIZE ) ) )
574 {
575 const QgsRasterBandStats myRasterBandStats = provider->bandStatistics( i, Qgis::RasterBandStatistic::Min | Qgis::RasterBandStatistic::Max, provider->extent(), static_cast<int>( SAMPLE_SIZE ) );
576 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;
577 }
578 else
579 {
580 myMetadata += u"<td>"_s % tr( "n/a" ) % u"</td><td>"_s % tr( "n/a" ) % u"</td>"_s;
581 }
582
583 myMetadata += "</tr>\n"_L1;
584 }
585
586 //close previous bands table
587 myMetadata += u"</table>\n<br><br>"_s
588 %
589
590 // Start the contacts section
591 u"<h1>"_s
592 % tr( "Contacts" )
593 % u"</h1>\n<hr>\n"_s
594 % htmlFormatter.contactsSectionHtml()
595 % u"<br><br>\n"_s
596 %
597
598 // Start the links section
599 u"<h1>"_s
600 % tr( "References" )
601 % u"</h1>\n<hr>\n"_s
602 % htmlFormatter.linksSectionHtml()
603 % u"<br><br>\n"_s
604 %
605
606 // Start the history section
607 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;
608 return myMetadata;
609}
610
612{
614
616 if ( mDataProvider && ( mDataProvider->flags() & Qgis::DataProviderFlag::IsBasemapSource ) )
617 {
619 }
620 return res;
621}
622
623QPixmap QgsRasterLayer::paletteAsPixmap( int bandNumber )
624{
626
627 //TODO: This function should take dimensions
628 QgsDebugMsgLevel( u"entered."_s, 4 );
629
630 // Only do this for the GDAL provider?
631 // Maybe WMS can do this differently using QImage::numColors and QImage::color()
632 if ( mDataProvider && mDataProvider->colorInterpretation( bandNumber ) == Qgis::RasterColorInterpretation::PaletteIndex )
633 {
634 QgsDebugMsgLevel( u"....found paletted image"_s, 4 );
635 QgsColorRampShader myShader;
636 const QList<QgsColorRampShader::ColorRampItem> myColorRampItemList = mDataProvider->colorTable( bandNumber );
637 if ( !myColorRampItemList.isEmpty() )
638 {
639 QgsDebugMsgLevel( u"....got color ramp item list"_s, 4 );
640 myShader.setColorRampItemList( myColorRampItemList );
642 // Draw image
643 const int mySize = 100;
644 QPixmap myPalettePixmap( mySize, mySize );
645 QPainter myQPainter( &myPalettePixmap );
646
647 QImage myQImage = QImage( mySize, mySize, QImage::Format_RGB32 );
648 myQImage.fill( 0 );
649 myPalettePixmap.fill();
650
651 const double myStep = ( static_cast< double >( myColorRampItemList.size() ) - 1 ) / static_cast< double >( mySize * mySize );
652 double myValue = 0.0;
653 for ( int myRow = 0; myRow < mySize; myRow++ )
654 {
655 QRgb *myLineBuffer = reinterpret_cast< QRgb * >( myQImage.scanLine( myRow ) );
656 for ( int myCol = 0; myCol < mySize; myCol++ )
657 {
658 myValue = myStep * static_cast< double >( myCol + myRow * mySize );
659 int c1, c2, c3, c4;
660 myShader.shade( myValue, &c1, &c2, &c3, &c4 );
661 myLineBuffer[myCol] = qRgba( c1, c2, c3, c4 );
662 }
663 }
664
665 myQPainter.drawImage( 0, 0, myQImage );
666 return myPalettePixmap;
667 }
668 const QPixmap myNullPixmap;
669 return myNullPixmap;
670 }
671 else
672 {
673 //invalid layer was requested
674 const QPixmap myNullPixmap;
675 return myNullPixmap;
676 }
677}
678
680{
682
683 // We return one raster pixel per map unit pixel
684 // One raster pixel can have several raster units...
685
686 // We can only use one of the mGeoTransform[], so go with the
687 // horisontal one.
688
689 if ( mDataProvider && mDataProvider->capabilities() & Qgis::RasterInterfaceCapability::Size && !qgsDoubleNear( mDataProvider->xSize(), 0.0 ) )
690 {
691 return mDataProvider->extent().width() / mDataProvider->xSize();
692 }
693 return 1;
694}
695
697{
699
700 if ( mDataProvider && mDataProvider->capabilities() & Qgis::RasterInterfaceCapability::Size && !qgsDoubleNear( mDataProvider->ySize(), 0.0 ) )
701 {
702 return mDataProvider->extent().height() / mDataProvider->ySize();
703 }
704 return 1;
705}
706
708{
710
711 if ( !mPipe->renderer() || mPipe->renderer()->opacity() == opacity )
712 return;
713
714 mPipe->renderer()->setOpacity( opacity );
715 emit opacityChanged( opacity );
717}
718
720{
722
723 return mPipe->renderer() ? mPipe->renderer()->opacity() : 1.0;
724}
725
726void QgsRasterLayer::init()
727{
729
731
732 whileBlocking( this )->setLegend( QgsMapLayerLegend::defaultRasterLegend( this ) );
733
734 setRendererForDrawingStyle( Qgis::RasterDrawingStyle::Undefined );
735
736 //Initialize the last view port structure, should really be a class
737 mLastViewPort.mWidth = 0;
738 mLastViewPort.mHeight = 0;
739}
740
742{
744
745 QgsDebugMsgLevel( u"Entered"_s, 4 );
746 setValid( false ); // assume the layer is invalid until we determine otherwise
747
748 // deletes pipe elements (including data provider)
749 mPipe = std::make_unique< QgsRasterPipe >();
750 mDataProvider = nullptr;
751
752 // XXX should I check for and possibly delete any pre-existing providers?
753 // XXX How often will that scenario occur?
754
755 mProviderKey = provider;
756 // set the layer name (uppercase first character)
757 if ( !mLayerName.isEmpty() ) // XXX shouldn't this happen in parent?
758 {
760 }
761
762 //mBandCount = 0;
763
764 if ( mPreloadedProvider )
765 {
766 mDataProvider = qobject_cast< QgsRasterDataProvider * >( mPreloadedProvider.release() );
767 }
768 else
769 {
770 std::unique_ptr< QgsScopedRuntimeProfile > profile;
771 if ( QgsApplication::profiler()->groupIsActive( u"projectload"_s ) )
772 profile = std::make_unique< QgsScopedRuntimeProfile >( tr( "Create %1 provider" ).arg( provider ), u"projectload"_s );
773
774 mDataProvider = qobject_cast< QgsRasterDataProvider * >( QgsProviderRegistry::instance()->createProvider( mProviderKey, mDataSource, options, flags ) );
775 }
776
777 if ( !mDataProvider )
778 {
779 //QgsMessageLog::logMessage( tr( "Cannot instantiate the data provider" ), tr( "Raster" ) );
780 appendError( ERR( tr( "Cannot instantiate the '%1' data provider" ).arg( mProviderKey ) ) );
781 return;
782 }
783 QgsDebugMsgLevel( u"Data provider created"_s, 4 );
784 mDataProvider->setParent( this );
785
786 // Set data provider into pipe even if not valid so that it is deleted with pipe (with layer)
787 if ( !mPipe->set( mDataProvider ) )
788 {
789 // data provider has been deleted by the pipe
790 mDataProvider = nullptr;
791 appendError( ERR( tr( "Could not insert provider into layer pipe (provider: %1, URI: %2)" ).arg( mProviderKey, mDataSource ) ) );
792 return;
793 }
794
795 if ( !mDataProvider->isValid() )
796 {
797 setError( mDataProvider->error() );
798 appendError( ERR( tr( "Provider is not valid (provider: %1, URI: %2)" ).arg( mProviderKey, mDataSource ) ) );
799 return;
800 }
801
802 if ( mDataProvider->providerCapabilities() & Qgis::RasterProviderCapability::ReadLayerMetadata )
803 {
804 setMetadata( mDataProvider->layerMetadata() );
805 QgsDebugMsgLevel( u"Set Data provider QgsLayerMetadata identifier[%1]"_s.arg( metadata().identifier() ), 4 );
806 }
807
808 if ( provider == "gdal"_L1 )
809 {
810 // make sure that the /vsigzip or /vsizip is added to uri, if applicable
811 mDataSource = mDataProvider->dataSourceUri();
812 }
813
815 {
816 // get the extent
817 const QgsRectangle mbr = mDataProvider->extent();
818
819 // store the extent
820 setExtent( mbr );
821 }
822
823 // upper case the first letter of the layer name
824 QgsDebugMsgLevel( "mLayerName: " + name(), 4 );
825
826 // set up the raster drawing style
827 // Do not set any 'sensible' style here, the style is set later
828
829 // Setup source CRS
830 setCrs( QgsCoordinateReferenceSystem( mDataProvider->crs() ) );
831
832 QgsDebugMsgLevel( "using wkt:\n" + crs().toWkt( Qgis::CrsWktVariant::Preferred ), 4 );
833
834 //defaults - Needs to be set after the Contrast list has been build
835 //Try to read the default contrast enhancement from the config file
836
837 //decide what type of layer this is...
838 //TODO Change this to look at the color interp and palette interp to decide which type of layer it is
839 QgsDebugMsgLevel( "bandCount = " + QString::number( mDataProvider->bandCount() ), 4 );
840 QgsDebugMsgLevel( "dataType = " + qgsEnumValueToKey< Qgis::DataType >( mDataProvider->dataType( 1 ) ), 4 );
841 const int bandCount = mDataProvider->bandCount();
842 if ( bandCount > 2 )
843 {
845 }
846 else if ( bandCount == 2 )
847 {
848 // handle singleband gray and paletted with alpha
849 auto colorInterpretationIsGrayOrUndefined = []( Qgis::RasterColorInterpretation interpretation ) {
851 };
852
853 auto colorInterpretationIsPaletted = []( Qgis::RasterColorInterpretation interpretation ) {
855 };
856
857 if ( ( colorInterpretationIsGrayOrUndefined( mDataProvider->colorInterpretation( 1 ) ) && mDataProvider->colorInterpretation( 2 ) == Qgis::RasterColorInterpretation::AlphaBand )
858 || ( mDataProvider->colorInterpretation( 1 ) == Qgis::RasterColorInterpretation::AlphaBand && colorInterpretationIsGrayOrUndefined( mDataProvider->colorInterpretation( 2 ) ) ) )
859 {
861 }
862 else if ( ( colorInterpretationIsPaletted( mDataProvider->colorInterpretation( 1 ) ) && mDataProvider->colorInterpretation( 2 ) == Qgis::RasterColorInterpretation::AlphaBand )
863 || ( mDataProvider->colorInterpretation( 1 ) == Qgis::RasterColorInterpretation::AlphaBand && colorInterpretationIsPaletted( mDataProvider->colorInterpretation( 2 ) ) ) )
864 {
865 mRasterType = Qgis::RasterLayerType::Palette;
866 }
867 else
868 {
870 }
871 }
872 else if ( mDataProvider->dataType( 1 ) == Qgis::DataType::ARGB32 || mDataProvider->dataType( 1 ) == Qgis::DataType::ARGB32_Premultiplied )
873 {
875 }
876 else if ( mDataProvider->colorInterpretation( 1 ) == Qgis::RasterColorInterpretation::PaletteIndex || mDataProvider->colorInterpretation( 1 ) == Qgis::RasterColorInterpretation::ContinuousPalette )
877 {
878 mRasterType = Qgis::RasterLayerType::Palette;
879 }
880 else
881 {
883 }
884
885 QgsDebugMsgLevel( "mRasterType = " + qgsEnumValueToKey( mRasterType ), 4 );
886
887 // Raster Attribute Table logic to load from provider or same basename + vat.dbf file.
888 QString errorMessage;
889 bool hasRat { mDataProvider->readNativeAttributeTable( &errorMessage ) };
890 if ( !hasRat )
891 {
892 errorMessage.clear();
893 QgsDebugMsgLevel( "Native Raster Raster Attribute Table read failed " + errorMessage, 2 );
894 if ( QFile::exists( mDataProvider->dataSourceUri() + ".vat.dbf" ) )
895 {
896 auto rat = std::make_unique<QgsRasterAttributeTable>();
897 hasRat = rat->readFromFile( mDataProvider->dataSourceUri() + ".vat.dbf", &errorMessage );
898 if ( hasRat )
899 {
900 if ( rat->isValid( &errorMessage ) )
901 {
902 mDataProvider->setAttributeTable( 1, rat.release() );
903 QgsDebugMsgLevel( "DBF Raster Attribute Table successfully read from " + mDataProvider->dataSourceUri() + ".vat.dbf", 2 );
904 }
905 else
906 {
907 QgsDebugMsgLevel( "DBF Raster Attribute Table is not valid, skipping: " + errorMessage, 2 );
908 }
909 }
910 else
911 {
912 QgsDebugMsgLevel( "DBF Raster Attribute Table read failed " + errorMessage, 2 );
913 }
914 }
915 }
916 else
917 {
918 QgsDebugMsgLevel( "Native Raster Attribute Table read success", 2 );
919 }
920
921 switch ( mRasterType )
922 {
924 {
925 QgsDebugMsgLevel( "Setting drawing style to SingleBandColorDataStyle " + qgsEnumValueToKey( Qgis::RasterDrawingStyle::SingleBandColorData ), 4 );
926 setRendererForDrawingStyle( Qgis::RasterDrawingStyle::SingleBandColorData );
927 break;
928 }
930 {
931 if ( mDataProvider->colorInterpretation( 1 ) == Qgis::RasterColorInterpretation::PaletteIndex )
932 {
933 setRendererForDrawingStyle( Qgis::RasterDrawingStyle::PalettedColor ); //sensible default
934 }
935 else if ( mDataProvider->colorInterpretation( 1 ) == Qgis::RasterColorInterpretation::ContinuousPalette )
936 {
937 setRendererForDrawingStyle( Qgis::RasterDrawingStyle::SingleBandPseudoColor );
938 // Load color table
939 const QList<QgsColorRampShader::ColorRampItem> colorTable = mDataProvider->colorTable( 1 );
941 if ( r )
942 {
943 // TODO: this should go somewhere else
944 QgsRasterShader *shader = new QgsRasterShader();
945 QgsColorRampShader *colorRampShader = new QgsColorRampShader();
947 colorRampShader->setColorRampItemList( colorTable );
948 shader->setRasterShaderFunction( colorRampShader );
949 r->setShader( shader );
950 }
951 }
952 else
953 {
954 setRendererForDrawingStyle( Qgis::RasterDrawingStyle::SingleBandGray ); //sensible default
955 }
956 break;
957 }
959 {
960 setRendererForDrawingStyle( Qgis::RasterDrawingStyle::MultiBandColor ); //sensible default
961 break;
962 }
964 {
965 setRendererForDrawingStyle( Qgis::RasterDrawingStyle::SingleBandGray ); //sensible default
966 break;
967 }
968 }
969
970 // Auto set alpha band
971 for ( int bandNo = 1; bandNo <= mDataProvider->bandCount(); bandNo++ )
972 {
973 if ( mDataProvider->colorInterpretation( bandNo ) == Qgis::RasterColorInterpretation::AlphaBand )
974 {
975 if ( auto *lRenderer = mPipe->renderer() )
976 {
977 lRenderer->setAlphaBand( bandNo );
978 }
979 break;
980 }
981 }
982
983 // brightness filter
985 mPipe->set( brightnessFilter );
986
987 // hue/saturation filter
989 mPipe->set( hueSaturationFilter );
990
991 // resampler (must be after renderer)
993 if ( mPipe->set( resampleFilter ) && mDataProvider->providerCapabilities() & Qgis::RasterProviderCapability::ProviderHintBenefitsFromResampling )
994 {
995 const QgsSettings settings;
996 QString resampling = settings.value( u"/Raster/defaultZoomedInResampling"_s, u"nearest neighbour"_s ).toString();
997 if ( resampling == "bilinear"_L1 )
998 {
999 resampleFilter->setZoomedInResampler( new QgsBilinearRasterResampler() );
1000 mDataProvider->setZoomedInResamplingMethod( Qgis::RasterResamplingMethod::Bilinear );
1001 }
1002 else if ( resampling == "cubic"_L1 )
1003 {
1004 resampleFilter->setZoomedInResampler( new QgsCubicRasterResampler() );
1005 mDataProvider->setZoomedInResamplingMethod( Qgis::RasterResamplingMethod::Cubic );
1006 }
1007 resampling = settings.value( u"/Raster/defaultZoomedOutResampling"_s, u"nearest neighbour"_s ).toString();
1008 if ( resampling == "bilinear"_L1 )
1009 {
1010 resampleFilter->setZoomedOutResampler( new QgsBilinearRasterResampler() );
1011 mDataProvider->setZoomedOutResamplingMethod( Qgis::RasterResamplingMethod::Bilinear );
1012 }
1013
1014 const double maxOversampling = QgsRasterLayer::settingsRasterDefaultOversampling->value();
1015 resampleFilter->setMaxOversampling( maxOversampling );
1016 mDataProvider->setMaxOversampling( maxOversampling );
1017
1019 {
1021 }
1022 else
1023 {
1025 }
1026 }
1027
1028 // projector (may be anywhere in pipe)
1029 QgsRasterProjector *projector = new QgsRasterProjector;
1030 mPipe->set( projector );
1031
1032 // Set default identify format - use the richest format available
1033 const Qgis::RasterInterfaceCapabilities capabilities = mDataProvider->capabilities();
1036 {
1037 // HTML is usually richest
1038 identifyFormat = Qgis::RasterIdentifyFormat::Html;
1039 }
1040 else if ( capabilities & Qgis::RasterInterfaceCapability::IdentifyFeature )
1041 {
1042 identifyFormat = Qgis::RasterIdentifyFormat::Feature;
1043 }
1044 else if ( capabilities & Qgis::RasterInterfaceCapability::IdentifyText )
1045 {
1046 identifyFormat = Qgis::RasterIdentifyFormat::Text;
1047 }
1048 else if ( capabilities & Qgis::RasterInterfaceCapability::IdentifyValue )
1049 {
1050 identifyFormat = Qgis::RasterIdentifyFormat::Value;
1051 }
1052 setCustomProperty( u"identify/format"_s, QgsRasterDataProvider::identifyFormatName( identifyFormat ) );
1053
1054 if ( QgsRasterDataProviderElevationProperties *properties = mDataProvider->elevationProperties() )
1055 {
1056 if ( properties->containsElevationData() )
1057 {
1058 mElevationProperties->setEnabled( true );
1059 }
1060 }
1061
1062 // Store timestamp
1063 // TODO move to provider
1064 mLastModified = lastModified( mDataSource );
1065
1066 // Do a passthrough for the status bar text
1068
1069 //mark the layer as valid
1070 setValid( true );
1071
1072 if ( mDataProvider->supportsSubsetString() )
1073 connect( this, &QgsRasterLayer::subsetStringChanged, this, &QgsMapLayer::configChanged, Qt::UniqueConnection );
1074 else
1076
1077
1078 QgsDebugMsgLevel( u"exiting."_s, 4 );
1079}
1080
1081void QgsRasterLayer::setDataSourcePrivate( const QString &dataSource, const QString &baseName, const QString &provider, const QgsDataProvider::ProviderOptions &options, Qgis::DataProviderReadFlags flags )
1082{
1084
1085 const bool hadRenderer( renderer() );
1086
1087 QDomImplementation domImplementation;
1088 QDomDocumentType documentType;
1089 QString errorMsg;
1090
1091 bool loadDefaultStyleFlag = false;
1093 {
1094 loadDefaultStyleFlag = true;
1095 }
1096
1097 // Store the original style
1098 if ( hadRenderer && !loadDefaultStyleFlag )
1099 {
1100 documentType = domImplementation.createDocumentType( u"qgis"_s, u"http://mrcc.com/qgis.dtd"_s, u"SYSTEM"_s );
1101
1102 QDomDocument doc = QDomDocument( documentType );
1103 QDomElement styleElem = doc.createElement( u"qgis"_s );
1104 styleElem.setAttribute( u"version"_s, Qgis::version() );
1105 const QgsReadWriteContext writeContext;
1106 if ( !writeSymbology( styleElem, doc, errorMsg, writeContext ) )
1107 {
1108 QgsDebugError( u"Could not store symbology for layer %1: %2"_s.arg( name(), errorMsg ) );
1109 }
1110 else
1111 {
1112 doc.appendChild( styleElem );
1113
1114 mOriginalStyleDocument = doc;
1115 mOriginalStyleElement = styleElem;
1116 }
1117 }
1118
1119 if ( mDataProvider )
1120 closeDataProvider();
1121
1122 init();
1123
1124 for ( int i = mPipe->size() - 1; i >= 0; --i )
1125 {
1126 mPipe->remove( i );
1127 }
1128
1129 mDataSource = dataSource;
1130 mLayerName = baseName;
1131
1132 setDataProvider( provider, options, flags );
1133
1134 if ( mDataProvider )
1135 mDataProvider->setDataSourceUri( mDataSource );
1136
1137 if ( isValid() )
1138 {
1139 // load default style
1140 bool defaultLoadedFlag = false;
1141 bool restoredStyle = false;
1142 if ( loadDefaultStyleFlag )
1143 {
1144 loadDefaultStyle( defaultLoadedFlag );
1145 }
1146 else if ( !mOriginalStyleElement.isNull() ) // Restore the style
1147 {
1148 QgsReadWriteContext readContext;
1149 if ( !readSymbology( mOriginalStyleElement, errorMsg, readContext ) )
1150 {
1151 QgsDebugError( u"Could not restore symbology for layer %1: %2"_s.arg( name() ).arg( errorMsg ) );
1152 }
1153 else
1154 {
1155 restoredStyle = true;
1156 emit repaintRequested();
1158 emit rendererChanged();
1159 }
1160 }
1161
1162 if ( !defaultLoadedFlag && !restoredStyle )
1163 {
1165 }
1166 }
1167}
1168
1169void QgsRasterLayer::writeRasterAttributeTableExternalPaths( QDomNode &layerNode, QDomDocument &doc, const QgsReadWriteContext &context ) const
1170{
1172
1173 if ( attributeTableCount() > 0 )
1174 {
1175 QDomElement elem = doc.createElement( u"FileBasedAttributeTables"_s );
1176 for ( int bandNo = 1; bandNo <= bandCount(); bandNo++ )
1177 {
1178 if ( QgsRasterAttributeTable *rat = attributeTable( bandNo ); rat && !rat->filePath().isEmpty() )
1179 {
1180 QDomElement ratElem = doc.createElement( u"AttributeTable"_s );
1181 ratElem.setAttribute( u"band"_s, bandNo );
1182 ratElem.setAttribute( u"path"_s, context.pathResolver().writePath( rat->filePath() ) );
1183 elem.appendChild( ratElem );
1184 }
1185 }
1186 layerNode.appendChild( elem );
1187 }
1188}
1189
1190void QgsRasterLayer::readRasterAttributeTableExternalPaths( const QDomNode &layerNode, QgsReadWriteContext &context ) const
1191{
1192 const QDomElement ratsElement = layerNode.firstChildElement( u"FileBasedAttributeTables"_s );
1193 if ( !ratsElement.isNull() && ratsElement.childNodes().count() > 0 )
1194 {
1195 const QDomNodeList ratElements { ratsElement.childNodes() };
1196 for ( int idx = 0; idx < ratElements.count(); idx++ )
1197 {
1198 const QDomNode ratElement { ratElements.at( idx ) };
1199 if ( ratElement.attributes().contains( u"band"_s ) && ratElement.attributes().contains( u"path"_s ) )
1200 {
1201 bool ok;
1202 const int band { ratElement.attributes().namedItem( u"band"_s ).nodeValue().toInt( &ok ) };
1203
1204 // Check band is ok
1205 if ( !ok || band <= 0 || band > bandCount() )
1206 {
1207 QgsMessageLog::logMessage( tr( "Error reading raster attribute table: invalid band %1." ).arg( band ), tr( "Raster" ) );
1208 continue;
1209 }
1210
1211 const QString path { context.pathResolver().readPath( ratElement.attributes().namedItem( u"path"_s ).nodeValue() ) };
1212 if ( !QFile::exists( path ) )
1213 {
1214 QgsMessageLog::logMessage( tr( "Error loading raster attribute table, file not found: %1." ).arg( path ), tr( "Raster" ) );
1215 continue;
1216 }
1217
1218 auto rat = std::make_unique<QgsRasterAttributeTable>();
1219 QString errorMessage;
1220 if ( !rat->readFromFile( path, &errorMessage ) )
1221 {
1222 QgsMessageLog::logMessage( tr( "Error loading raster attribute table from path %1: %2" ).arg( path, errorMessage ), tr( "Raster" ) );
1223 continue;
1224 }
1225
1226 // All good, set the RAT
1227 mDataProvider->setAttributeTable( band, rat.release() );
1228 }
1229 }
1230 }
1231}
1232
1233void QgsRasterLayer::closeDataProvider()
1234{
1236
1237 setValid( false );
1238 mPipe->remove( mDataProvider );
1239 mDataProvider = nullptr;
1240}
1241
1242void QgsRasterLayer::computeMinMax( int band, const QgsRasterMinMaxOrigin &mmo, Qgis::RasterRangeLimit limits, const QgsRectangle &extent, int sampleSize, double &min, double &max )
1243{
1245
1246 QgsRasterLayerUtils::computeMinMax( mDataProvider, band, mmo, limits, extent, sampleSize, min, max );
1247}
1248
1250{
1252
1253 return mDataProvider ? mDataProvider->ignoreExtents() : false;
1254}
1255
1262
1269
1271 QgsContrastEnhancement::ContrastEnhancementAlgorithm algorithm, Qgis::RasterRangeLimit limits, const QgsRectangle &extent, int sampleSize, bool generateLookupTableFlag
1272)
1273{
1275
1276 setContrastEnhancement( algorithm, limits, extent, sampleSize, generateLookupTableFlag, mPipe->renderer() );
1277}
1278
1280 QgsContrastEnhancement::ContrastEnhancementAlgorithm algorithm, Qgis::RasterRangeLimit limits, const QgsRectangle &extent, int sampleSize, bool generateLookupTableFlag, QgsRasterRenderer *rasterRenderer
1281)
1282{
1284
1285 QgsDebugMsgLevel( u"theAlgorithm = %1 limits = %2 extent.isEmpty() = %3"_s.arg( algorithm ).arg( qgsEnumValueToKey( limits ) ).arg( extent.isEmpty() ), 4 );
1286 if ( !rasterRenderer || !mDataProvider )
1287 {
1288 return;
1289 }
1290
1291 QList<int> myBands;
1292 QList<QgsContrastEnhancement *> myEnhancements;
1293 QgsRasterMinMaxOrigin myMinMaxOrigin;
1294 QgsRasterRenderer *myRasterRenderer = nullptr;
1295 QgsSingleBandGrayRenderer *myGrayRenderer = nullptr;
1296 QgsSingleBandPseudoColorRenderer *myPseudoColorRenderer = nullptr;
1297 QgsMultiBandColorRenderer *myMultiBandRenderer = nullptr;
1298 const QString rendererType = rasterRenderer->type();
1299 if ( rendererType == "singlebandgray"_L1 )
1300 {
1301 myGrayRenderer = dynamic_cast<QgsSingleBandGrayRenderer *>( rasterRenderer );
1302 if ( !myGrayRenderer )
1303 {
1304 return;
1305 }
1306 myBands << myGrayRenderer->inputBand();
1307 myRasterRenderer = myGrayRenderer;
1308 myMinMaxOrigin = myGrayRenderer->minMaxOrigin();
1309 }
1310 else if ( rendererType == "multibandcolor"_L1 )
1311 {
1312 myMultiBandRenderer = dynamic_cast<QgsMultiBandColorRenderer *>( rasterRenderer );
1313 if ( !myMultiBandRenderer )
1314 {
1315 return;
1316 }
1317 myBands << myMultiBandRenderer->redBand() << myMultiBandRenderer->greenBand() << myMultiBandRenderer->blueBand();
1318 myRasterRenderer = myMultiBandRenderer;
1319 myMinMaxOrigin = myMultiBandRenderer->minMaxOrigin();
1320 }
1321 else if ( rendererType == "singlebandpseudocolor"_L1 )
1322 {
1323 myPseudoColorRenderer = dynamic_cast<QgsSingleBandPseudoColorRenderer *>( rasterRenderer );
1324 if ( !myPseudoColorRenderer )
1325 {
1326 return;
1327 }
1328 myBands << myPseudoColorRenderer->inputBand();
1329 myRasterRenderer = myPseudoColorRenderer;
1330 myMinMaxOrigin = myPseudoColorRenderer->minMaxOrigin();
1331 }
1332 else
1333 {
1334 return;
1335 }
1336
1337 for ( const int myBand : std::as_const( myBands ) )
1338 {
1339 if ( myBand != -1 )
1340 {
1341 const Qgis::DataType myType = static_cast< Qgis::DataType >( mDataProvider->dataType( myBand ) );
1342 auto myEnhancement = std::make_unique<QgsContrastEnhancement>( static_cast< Qgis::DataType >( myType ) );
1343 myEnhancement->setContrastEnhancementAlgorithm( algorithm, generateLookupTableFlag );
1344
1345 double min;
1346 double max;
1347 computeMinMax( myBand, myMinMaxOrigin, limits, extent, sampleSize, min, max );
1348
1349 if ( rendererType == "singlebandpseudocolor"_L1 )
1350 {
1351 // This is not necessary, but clang-tidy thinks it is.
1352 if ( !myPseudoColorRenderer )
1353 {
1354 return;
1355 }
1356 // Do not overwrite min/max with NaN if they were already set,
1357 // for example when the style was already loaded from a raster attribute table
1358 // in that case we need to respect the style from the attribute table and do
1359 // not perform any reclassification.
1360 bool minMaxChanged { false };
1361 if ( !std::isnan( min ) )
1362 {
1363 myPseudoColorRenderer->setClassificationMin( min );
1364 minMaxChanged = true;
1365 }
1366
1367 if ( !std::isnan( max ) )
1368 {
1369 myPseudoColorRenderer->setClassificationMax( max );
1370 minMaxChanged = true;
1371 }
1372
1373 if ( minMaxChanged && myPseudoColorRenderer->shader() )
1374 {
1375 QgsColorRampShader *colorRampShader = dynamic_cast<QgsColorRampShader *>( myPseudoColorRenderer->shader()->rasterShaderFunction() );
1376 if ( colorRampShader )
1377 {
1378 colorRampShader->classifyColorRamp( myPseudoColorRenderer->inputBand(), extent, myPseudoColorRenderer->input() );
1379 }
1380 }
1381 }
1382 else
1383 {
1384 myEnhancement->setMinimumValue( min );
1385 myEnhancement->setMaximumValue( max );
1386 myEnhancements.append( myEnhancement.release() );
1387 }
1388 }
1389 else
1390 {
1391 myEnhancements.append( nullptr );
1392 }
1393 }
1394
1395 // Again, second check is redundant but clang-tidy doesn't agree
1396 if ( rendererType == "singlebandgray"_L1 && myGrayRenderer )
1397 {
1398 if ( myEnhancements.first() )
1399 myGrayRenderer->setContrastEnhancement( myEnhancements.takeFirst() );
1400 }
1401 else if ( rendererType == "multibandcolor"_L1 && myMultiBandRenderer )
1402 {
1403 if ( myEnhancements.first() )
1404 myMultiBandRenderer->setRedContrastEnhancement( myEnhancements.takeFirst() );
1405 if ( myEnhancements.first() )
1406 myMultiBandRenderer->setGreenContrastEnhancement( myEnhancements.takeFirst() );
1407 if ( myEnhancements.first() )
1408 myMultiBandRenderer->setBlueContrastEnhancement( myEnhancements.takeFirst() );
1409 }
1410
1411 //delete all remaining unused enhancements
1412 qDeleteAll( myEnhancements );
1413
1414 myMinMaxOrigin.setLimits( limits );
1415 if ( extent != QgsRectangle() && myMinMaxOrigin.extent() == Qgis::RasterRangeExtent::WholeRaster )
1416 {
1418 }
1419 if ( myRasterRenderer )
1420 {
1421 myRasterRenderer->setMinMaxOrigin( myMinMaxOrigin );
1422 }
1423
1424 if ( rasterRenderer == renderer() )
1425 {
1426 emit repaintRequested();
1428 emit rendererChanged();
1429 }
1430}
1431
1433{
1435
1436 QgsSingleBandGrayRenderer *singleBandRenderer = nullptr;
1437 QgsMultiBandColorRenderer *multiBandRenderer = nullptr;
1438 const QgsContrastEnhancement *ce = nullptr;
1439 if ( ( singleBandRenderer = dynamic_cast<QgsSingleBandGrayRenderer *>( renderer() ) ) )
1440 {
1441 ce = singleBandRenderer->contrastEnhancement();
1442 }
1443 else if ( ( multiBandRenderer = dynamic_cast<QgsMultiBandColorRenderer *>( renderer() ) ) )
1444 {
1445 ce = multiBandRenderer->redContrastEnhancement();
1446 }
1447
1448 if ( ce )
1449 {
1452 renderer()->minMaxOrigin().limits() == Qgis::RasterRangeLimit::NotSet ? Qgis::RasterRangeLimit::MinimumMaximum : renderer()->minMaxOrigin().limits(),
1453 extent,
1454 static_cast<int>( SAMPLE_SIZE ),
1455 true,
1456 renderer()
1457 );
1458 }
1459 else
1460 {
1462 Qgis::RasterRangeLimit myLimits;
1463 if ( defaultContrastEnhancementSettings( myAlgorithm, myLimits ) )
1464 {
1466 }
1467 }
1468}
1469
1471{
1473
1474 if ( !isValid() || !mDataProvider )
1475 {
1476 QgsDebugMsgLevel( u"invoked with invalid layer or null mDataProvider"_s, 3 );
1477 return customProperty( u"storedSubsetString"_s ).toString();
1478 }
1479 if ( !mDataProvider->supportsSubsetString() )
1480 {
1481 return QString();
1482 }
1483 return mDataProvider->subsetString();
1484}
1485
1486bool QgsRasterLayer::setSubsetString( const QString &subset )
1487{
1489
1490 if ( !isValid() || !mDataProvider )
1491 {
1492 QgsDebugMsgLevel( u"invoked with invalid layer or null mDataProvider or while editing"_s, 3 );
1493 setCustomProperty( u"storedSubsetString"_s, subset );
1494 return false;
1495 }
1496
1497 if ( !mDataProvider->supportsSubsetString() )
1498 {
1499 return false;
1500 }
1501
1502 if ( subset == mDataProvider->subsetString() )
1503 return true;
1504
1505 const bool res = mDataProvider->setSubsetString( subset );
1506
1507 // get the updated data source string from the provider
1508 mDataSource = mDataProvider->dataSourceUri();
1509
1510 if ( res )
1511 {
1512 setExtent( mDataProvider->extent() );
1513 QList<double> minValues;
1514 QList<double> maxValues;
1515 const QgsRasterMinMaxOrigin &minMaxOrigin = renderer()->minMaxOrigin();
1516 for ( const int bandIdx : renderer()->usesBands() )
1517 {
1518 double min;
1519 double max;
1520
1521 computeMinMax( bandIdx, minMaxOrigin, minMaxOrigin.limits(), extent(), static_cast<int>( QgsRasterLayer::SAMPLE_SIZE ), min, max );
1522 minValues.append( min );
1523 maxValues.append( max );
1524 }
1525 renderer()->refresh( extent(), minValues, maxValues, true );
1526 emit subsetStringChanged();
1527 }
1528
1529 return res;
1530}
1531
1533{
1535
1536 const QgsSettings mySettings;
1537
1538 QString key;
1539 QString defaultAlg;
1540 QString defaultLimits;
1541
1542 // TODO: we should not test renderer class here, move it somehow to renderers
1543 if ( dynamic_cast<QgsSingleBandGrayRenderer *>( renderer() ) )
1544 {
1545 key = u"singleBand"_s;
1548 }
1549 else if ( dynamic_cast<QgsMultiBandColorRenderer *>( renderer() ) )
1550 {
1551 if ( QgsRasterBlock::typeSize( dataProvider()->sourceDataType( 1 ) ) == 1 )
1552 {
1553 key = u"multiBandSingleByte"_s;
1556 }
1557 else
1558 {
1559 key = u"multiBandMultiByte"_s;
1562 }
1563 }
1564
1565 if ( key.isEmpty() )
1566 {
1567 QgsDebugMsgLevel( u"No default contrast enhancement for this drawing style"_s, 2 );
1569 myLimits = QgsRasterMinMaxOrigin::limitsFromString( QString() );
1570 return false;
1571 }
1572 QgsDebugMsgLevel( "key = " + key, 4 );
1573
1574 const QString myAlgorithmString = mySettings.value( "/Raster/defaultContrastEnhancementAlgorithm/" + key, defaultAlg ).toString();
1575 QgsDebugMsgLevel( "myAlgorithmString = " + myAlgorithmString, 4 );
1576
1577 myAlgorithm = QgsContrastEnhancement::contrastEnhancementAlgorithmFromString( myAlgorithmString );
1578
1579 const QString myLimitsString = mySettings.value( "/Raster/defaultContrastEnhancementLimits/" + key, defaultLimits ).toString();
1580 QgsDebugMsgLevel( "myLimitsString = " + myLimitsString, 4 );
1581 myLimits = QgsRasterMinMaxOrigin::limitsFromString( myLimitsString );
1582
1583 return true;
1584}
1585
1587{
1589
1590 QgsDebugMsgLevel( u"Entered"_s, 4 );
1591
1593 Qgis::RasterRangeLimit myLimits;
1594 defaultContrastEnhancementSettings( myAlgorithm, myLimits );
1595
1596 setContrastEnhancement( myAlgorithm, myLimits );
1597}
1598
1599void QgsRasterLayer::setLayerOrder( QStringList const &layers )
1600{
1602
1603 QgsDebugMsgLevel( u"entered."_s, 4 );
1604
1605 if ( mDataProvider )
1606 {
1607 QgsDebugMsgLevel( u"About to mDataProvider->setLayerOrder(layers)."_s, 4 );
1608 mDataProvider->setLayerOrder( layers );
1609 }
1610}
1611
1612void QgsRasterLayer::setSubLayerVisibility( const QString &name, bool vis )
1613{
1615
1616 if ( mDataProvider )
1617 {
1618 QgsDebugMsgLevel( u"About to mDataProvider->setSubLayerVisibility(name, vis)."_s, 4 );
1619 mDataProvider->setSubLayerVisibility( name, vis );
1620 }
1621}
1622
1624{
1626
1627 if ( !mDataProvider )
1628 return QDateTime();
1629 return mDataProvider->timestamp();
1630}
1631
1633{
1635
1636 if ( auto *lRenderer = mPipe->renderer() )
1637 {
1638 if ( !lRenderer->accept( visitor ) )
1639 return false;
1640 }
1641 return true;
1642}
1643
1645{
1647
1648 return mLabelsEnabled && static_cast< bool >( mLabeling );
1649}
1650
1652{
1654
1655 mLabelsEnabled = enabled;
1656}
1657
1659{
1661
1662 return mLabeling.get();
1663}
1664
1671
1673{
1675
1676 if ( mLabeling.get() == labeling )
1677 return;
1678
1679 mLabeling.reset( labeling );
1681}
1682
1683bool QgsRasterLayer::writeSld( QDomNode &node, QDomDocument &doc, QString &, const QVariantMap &props ) const
1684{
1686 QgsSldExportContext context;
1687 context.setExtraProperties( props );
1688 writeSld( node, doc, context );
1689 return true;
1690}
1691
1692bool QgsRasterLayer::writeSld( QDomNode &node, QDomDocument &doc, QgsSldExportContext &context ) const
1693{
1695
1696 QVariantMap localProps = context.extraProperties();
1698 {
1699 // TODO: QgsSymbolLayerUtils::mergeScaleDependencies generate SE only and not SLD1.0
1701 }
1702 context.setExtraProperties( localProps );
1703
1704 if ( isSpatial() ) // TODO: does it make sense this control?
1705 {
1706 // store constraints
1707 QDomElement constraintElem = doc.createElement( u"sld:LayerFeatureConstraints"_s );
1708 node.appendChild( constraintElem );
1709
1710 const QDomElement featureTypeConstraintElem = doc.createElement( u"sld:FeatureTypeConstraint"_s );
1711 constraintElem.appendChild( featureTypeConstraintElem );
1712
1713 QDomElement userStyleElem = doc.createElement( u"sld:UserStyle"_s );
1714 node.appendChild( userStyleElem );
1715
1716 if ( !name().isEmpty() )
1717 {
1718 QDomElement nameElem = doc.createElement( u"sld:Name"_s );
1719 nameElem.appendChild( doc.createTextNode( name() ) );
1720 userStyleElem.appendChild( nameElem );
1721 }
1722
1723 const QString abstract = !metadata().abstract().isEmpty() ? metadata().abstract() : serverProperties()->abstract();
1724 if ( !abstract.isEmpty() )
1725 {
1726 QDomElement abstractElem = doc.createElement( u"sld:Abstract"_s );
1727 abstractElem.appendChild( doc.createTextNode( abstract ) );
1728 userStyleElem.appendChild( abstractElem );
1729 }
1730
1731 const QString title = !metadata().title().isEmpty() ? metadata().title() : serverProperties()->title();
1732 if ( !title.isEmpty() )
1733 {
1734 QDomElement titleElem = doc.createElement( u"sld:Title"_s );
1735 titleElem.appendChild( doc.createTextNode( title ) );
1736 userStyleElem.appendChild( titleElem );
1737 }
1738
1739 QDomElement featureTypeStyleElem = doc.createElement( u"sld:FeatureTypeStyle"_s );
1740 userStyleElem.appendChild( featureTypeStyleElem );
1741
1742#if 0
1743 // TODO: Is there a way to fill it's value with the named style?
1744 // by default <sld:Name> under <sld:FeatureTypeStyle> can have 0 occurrences
1745 // the same happen for tags:
1746 // sld:Title
1747 // sld:Abstract
1748 // sld:FeatureTypeName
1749 // sld:SemanticTypeIdentifier
1750 QDomElement typeStyleNameElem = doc.createElement( u"sld:Name"_s );
1751 featureTypeStyleElem.appendChild( typeStyleNameElem );
1752#endif
1753
1754 QDomElement typeStyleRuleElem = doc.createElement( u"sld:Rule"_s );
1755 featureTypeStyleElem.appendChild( typeStyleRuleElem );
1756
1757 // add ScaleDenominator tags
1759 {
1760 // note that denominator is the inverted value of scale
1761 if ( maximumScale() != 0.0 )
1762 {
1763 QDomElement minScaleElem = doc.createElement( u"sld:MinScaleDenominator"_s );
1764 minScaleElem.appendChild( doc.createTextNode( QString::number( maximumScale() ) ) );
1765 typeStyleRuleElem.appendChild( minScaleElem );
1766 }
1767
1768 QDomElement maxScaleElem = doc.createElement( u"sld:MaxScaleDenominator"_s );
1769 maxScaleElem.appendChild( doc.createTextNode( QString::number( minimumScale() ) ) );
1770 typeStyleRuleElem.appendChild( maxScaleElem );
1771 }
1772
1773 // export renderer dependent tags
1774 mPipe->renderer()->toSld( doc, typeStyleRuleElem, context );
1775
1776 // inject raster layer parameters in RasterSymbolizer tag because
1777 // they belongs to rasterlayer and not to the renderer => avoid to
1778 // pass many parameters value via localProps
1779 const QDomNodeList elements = typeStyleRuleElem.elementsByTagName( u"sld:RasterSymbolizer"_s );
1780 if ( elements.size() != 0 )
1781 {
1782 // there SHOULD be only one
1783 QDomElement rasterSymbolizerElem = elements.at( 0 ).toElement();
1784
1785 // lamda helper used below to reduce code redundancy
1786 auto vendorOptionWriter = [&]( QString name, QString value ) {
1787 QDomElement vendorOptionElem = doc.createElement( u"sld:VendorOption"_s );
1788 vendorOptionElem.setAttribute( u"name"_s, name );
1789 vendorOptionElem.appendChild( doc.createTextNode( value ) );
1790 rasterSymbolizerElem.appendChild( vendorOptionElem );
1791 };
1792
1793 if ( hueSaturationFilter()->invertColors() )
1794 {
1795 vendorOptionWriter( u"invertColors"_s, QString::number( 1 ) );
1796 }
1797
1798 // add greyScale rendering mode if set
1800 {
1801 QString property;
1802 switch ( hueSaturationFilter()->grayscaleMode() )
1803 {
1805 property = u"lightness"_s;
1806 break;
1808 property = u"luminosity"_s;
1809 break;
1811 property = u"average"_s;
1812 break;
1814 // added just to avoid travis fail
1815 break;
1816 }
1817 if ( !property.isEmpty() )
1818 vendorOptionWriter( u"grayScale"_s, property );
1819 }
1820
1821 // add Hue, Saturation and Lighting values in props is Hue filter is set
1822 if ( hueSaturationFilter() && hueSaturationFilter()->colorizeOn() )
1823 {
1824 vendorOptionWriter( u"colorizeOn"_s, QString::number( hueSaturationFilter()->colorizeOn() ) );
1825 vendorOptionWriter( u"colorizeRed"_s, QString::number( hueSaturationFilter()->colorizeColor().red() ) );
1826 vendorOptionWriter( u"colorizeGreen"_s, QString::number( hueSaturationFilter()->colorizeColor().green() ) );
1827 vendorOptionWriter( u"colorizeBlue"_s, QString::number( hueSaturationFilter()->colorizeColor().blue() ) );
1828 if ( hueSaturationFilter()->colorizeStrength() != 100.0 )
1829 vendorOptionWriter( u"colorizeStrength"_s, QString::number( hueSaturationFilter()->colorizeStrength() / 100.0 ) );
1830 vendorOptionWriter( u"saturation"_s, QString::number( hueSaturationFilter()->colorizeColor().saturationF() ) );
1831 }
1832 else
1833 {
1834 // saturation != 0 (default value)
1835 if ( hueSaturationFilter()->saturation() != 0 )
1836 {
1837 // normlize value [-100:100] -> [0:1]
1838 const int s = hueSaturationFilter()->saturation();
1839 const double sF = ( s - ( -100.0 ) ) / ( 100.0 - ( -100.0 ) );
1840 vendorOptionWriter( u"saturation"_s, QString::number( sF ) );
1841 }
1842 }
1843
1844 // brightness != 0 (default value)
1845 if ( brightnessFilter()->brightness() != 0 )
1846 {
1847 // normalize value [-255:255] -> [0:1]
1848 const int b = brightnessFilter()->brightness();
1849 const double bF = ( b - ( -255.0 ) ) / ( 255.0 - ( -255.0 ) );
1850 vendorOptionWriter( u"brightness"_s, QString::number( bF ) );
1851 }
1852
1853 // contrast != 0 (default value)
1854 if ( brightnessFilter()->contrast() != 0 )
1855 {
1856 // normlize value [-100:100] -> [0:1]
1857 const int c = brightnessFilter()->contrast();
1858 const double cF = ( c - ( -100.0 ) ) / ( 100.0 - ( -100.0 ) );
1859 vendorOptionWriter( u"contrast"_s, QString::number( cF ) );
1860 }
1861
1862#if 0
1863 // TODO: check if the below mapping formula make sense to map QGIS contrast with SLD gamma value
1864 // add SLD1.0 ContrastEnhancement GammaValue = QGIS Contrast
1865 // SLD1.0 does only define 1 as neutral/center double value but does not define range.
1866 // because https://en.wikipedia.org/wiki/Gamma_correction assumed gamma is >0.
1867 // whilst QGIS has a -100/100 values centered in 0 => QGIS contrast value will be scaled in the
1868 // following way:
1869 // [-100,0] => [0,1] and [0,100] => [1,100]
1870 // an alternative could be scale [-100,100] => (0,2]
1871 //
1872 if ( newProps.contains( u"contrast"_s ) )
1873 {
1874 double gamma;
1875 double contrast = newProps[ u"contrast"_s ].toDouble();
1876 double percentage = ( contrast - ( -100.0 ) ) / ( 100.0 - ( -100.0 ) );
1877 if ( percentage <= 0.5 )
1878 {
1879 // stretch % to [0-1]
1880 gamma = percentage / 0.5;
1881 }
1882 else
1883 {
1884 gamma = contrast;
1885 }
1886
1887 QDomElement globalContrastEnhancementElem = doc.createElement( u"sld:ContrastEnhancement"_s );
1888 rasterSymolizerElem.appendChild( globalContrastEnhancementElem );
1889
1890 QDomElement gammaValueElem = doc.createElement( u"sld:GammaValue"_s );
1891 gammaValueElem.appendChild( doc.createTextNode( QString::number( gamma ) ) );
1892 globalContrastEnhancementElem.appendChild( gammaValueElem );
1893 }
1894#endif
1895 }
1896 }
1897 return true;
1898}
1899
1901{
1903
1904 QgsDebugMsgLevel( u"Entered"_s, 4 );
1905 if ( !renderer )
1906 {
1907 return;
1908 }
1909
1910 mPipe->set( renderer );
1911 emit rendererChanged();
1913}
1914
1916{
1918
1919 return mPipe->renderer();
1920}
1921
1923{
1925
1926 return mPipe->resampleFilter();
1927}
1928
1930{
1932
1933 return mPipe->brightnessFilter();
1934}
1935
1937{
1939
1940 return mPipe->hueSaturationFilter();
1941}
1942
1943void QgsRasterLayer::showStatusMessage( QString const &message )
1944{
1946
1947 // QgsDebugMsgLevel(QString("entered with '%1'.").arg(theMessage), 2);
1948
1949 // Pass-through
1950 // TODO: See if we can connect signal-to-signal. This is a kludge according to the Qt doc.
1951 emit statusChanged( message );
1952}
1953
1955{
1957
1958 if ( mDataProvider )
1959 mDataProvider->setTransformContext( transformContext );
1961}
1962
1963QStringList QgsRasterLayer::subLayers() const
1964{
1966
1967 if ( !mDataProvider )
1968 return QStringList();
1969 return mDataProvider->subLayers();
1970}
1971
1972// this function should be used when rendering with the MTR engine introduced in 2.3, as QPixmap is not thread safe (see bug #9626)
1973// note: previewAsImage and previewAsPixmap should use a common low-level fct QgsRasterLayer::previewOnPaintDevice( QSize size, QColor bgColor, QPaintDevice &device )
1974QImage QgsRasterLayer::previewAsImage( QSize size, const QColor &bgColor, QImage::Format format )
1975{
1977
1978 QImage image( size, format );
1979
1980 if ( !isValid() )
1981 return QImage();
1982
1983 if ( image.format() == QImage::Format_Indexed8 )
1984 {
1985 image.setColor( 0, bgColor.rgba() );
1986 image.fill( 0 ); //defaults to white, set to transparent for rendering on a map
1987 }
1988 else
1989 {
1990 image.fill( bgColor );
1991 }
1992
1993 QgsRasterViewPort *rasterViewPort = new QgsRasterViewPort();
1994
1995 double mapUnitsPerPixel;
1996 double x = 0.0;
1997 double y = 0.0;
1998 const QgsRectangle extent = mDataProvider->extent();
1999 if ( extent.width() / extent.height() >= static_cast< double >( image.width() ) / image.height() )
2000 {
2001 mapUnitsPerPixel = extent.width() / image.width();
2002 y = ( image.height() - extent.height() / mapUnitsPerPixel ) / 2;
2003 }
2004 else
2005 {
2006 mapUnitsPerPixel = extent.height() / image.height();
2007 x = ( image.width() - extent.width() / mapUnitsPerPixel ) / 2;
2008 }
2009
2010 const double pixelWidth = extent.width() / mapUnitsPerPixel;
2011 const double pixelHeight = extent.height() / mapUnitsPerPixel;
2012
2013 rasterViewPort->mTopLeftPoint = QgsPointXY( x, y );
2014 rasterViewPort->mBottomRightPoint = QgsPointXY( pixelWidth, pixelHeight );
2015 rasterViewPort->mWidth = image.width();
2016 rasterViewPort->mHeight = image.height();
2017
2018 rasterViewPort->mDrawnExtent = extent;
2019 rasterViewPort->mSrcCRS = QgsCoordinateReferenceSystem(); // will be invalid
2020 rasterViewPort->mDestCRS = QgsCoordinateReferenceSystem(); // will be invalid
2021
2022 QgsMapToPixel *mapToPixel = new QgsMapToPixel( mapUnitsPerPixel );
2023
2024 QPainter *painter = new QPainter( &image );
2025 draw( painter, rasterViewPort, mapToPixel );
2026 delete rasterViewPort;
2027 delete mapToPixel;
2028
2029 painter->end();
2030 delete painter;
2031
2032 return image;
2033}
2034
2035bool QgsRasterLayer::readSymbology( const QDomNode &layer_node, QString &errorMessage, QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories )
2036{
2038
2039 Q_UNUSED( errorMessage )
2040 // TODO: implement categories for raster layer
2041
2042 QDomElement rasterRendererElem;
2043
2044 const QDomElement layerElement = layer_node.toElement();
2045 readCommonStyle( layerElement, context, categories );
2046
2047 // pipe considers Symbology and Rendering components, why it's always handled as one
2048 if ( categories.testFlag( Symbology ) || categories.testFlag( Rendering ) )
2049 {
2050 // pipe element was introduced in the end of 1.9 development when there were
2051 // already many project files in use so we support 1.9 backward compatibility
2052 // even it was never officially released -> use pipe element if present, otherwise
2053 // use layer node
2054 QDomNode pipeNode = layer_node.firstChildElement( u"pipe"_s );
2055 if ( pipeNode.isNull() ) // old project
2056 {
2057 pipeNode = layer_node;
2058 }
2059
2060 //rasterlayerproperties element there -> old format (1.8 and early 1.9)
2061 if ( !layer_node.firstChildElement( u"rasterproperties"_s ).isNull() )
2062 {
2063 //copy node because layer_node is const
2064 QDomNode layerNodeCopy = layer_node.cloneNode();
2065 QDomDocument doc = layerNodeCopy.ownerDocument();
2066 QDomElement rasterPropertiesElem = layerNodeCopy.firstChildElement( u"rasterproperties"_s );
2067 QgsProjectFileTransform::convertRasterProperties( doc, layerNodeCopy, rasterPropertiesElem, this );
2068 rasterRendererElem = layerNodeCopy.firstChildElement( u"rasterrenderer"_s );
2069 QgsDebugMsgLevel( doc.toString(), 4 );
2070 }
2071 else
2072 {
2073 rasterRendererElem = pipeNode.firstChildElement( u"rasterrenderer"_s );
2074 }
2075
2076 if ( !rasterRendererElem.isNull() )
2077 {
2078 const QString rendererType = rasterRendererElem.attribute( u"type"_s );
2079 QgsRasterRendererRegistryEntry rendererEntry;
2080 if ( mDataProvider && QgsApplication::rasterRendererRegistry()->rendererData( rendererType, rendererEntry ) )
2081 {
2082 QgsRasterRenderer *renderer = rendererEntry.rendererCreateFunction( rasterRendererElem, mDataProvider );
2083 mPipe->set( renderer );
2084 }
2085 }
2086
2087 //brightness
2089 if ( mPipe->set( brightnessFilter ) )
2090 {
2091 const QDomElement brightnessElem = pipeNode.firstChildElement( u"brightnesscontrast"_s );
2092 if ( !brightnessElem.isNull() )
2093 {
2094 brightnessFilter->readXml( brightnessElem );
2095 }
2096 }
2097
2098 //hue/saturation
2100 if ( mPipe->set( hueSaturationFilter ) )
2101 {
2102 const QDomElement hueSaturationElem = pipeNode.firstChildElement( u"huesaturation"_s );
2103 if ( !hueSaturationElem.isNull() )
2104 {
2105 hueSaturationFilter->readXml( hueSaturationElem );
2106 }
2107 }
2108
2109 //resampler
2111 if ( mPipe->set( resampleFilter ) )
2112 {
2113 const QDomElement resampleElem = pipeNode.firstChildElement( u"rasterresampler"_s );
2114 if ( !resampleElem.isNull() )
2115 {
2116 resampleFilter->readXml( resampleElem );
2117 }
2118 }
2119
2120 //provider
2121 if ( mDataProvider )
2122 {
2123 const QDomElement providerElem = pipeNode.firstChildElement( u"provider"_s );
2124 if ( !providerElem.isNull() )
2125 {
2126 mDataProvider->readXml( providerElem );
2127 }
2128 }
2129
2130 // Resampling stage
2131 const QDomNode resamplingStageElement = pipeNode.namedItem( u"resamplingStage"_s );
2132 if ( !resamplingStageElement.isNull() )
2133 {
2134 const QDomElement e = resamplingStageElement.toElement();
2135 if ( e.text() == "provider"_L1 )
2137 else if ( e.text() == "resamplingFilter"_L1 )
2139 }
2140
2141 // get and set the blend mode if it exists
2142 const QDomNode blendModeNode = layer_node.namedItem( u"blendMode"_s );
2143 if ( !blendModeNode.isNull() )
2144 {
2145 const QDomElement e = blendModeNode.toElement();
2146 setBlendMode( QgsPainting::getCompositionMode( static_cast< Qgis::BlendMode >( e.text().toInt() ) ) );
2147 }
2148
2149 const QDomElement elemDataDefinedProperties = layer_node.firstChildElement( u"pipe-data-defined-properties"_s );
2150 if ( !elemDataDefinedProperties.isNull() )
2151 mPipe->dataDefinedProperties().readXml( elemDataDefinedProperties, QgsRasterPipe::propertyDefinitions() );
2152 }
2153
2154 // read labeling definition
2155 if ( categories.testFlag( Labeling ) )
2156 {
2157 QgsReadWriteContextCategoryPopper p = context.enterCategory( tr( "Labeling" ) );
2158
2159 QDomElement labelingElement = layer_node.firstChildElement( u"labeling"_s );
2160 if ( !labelingElement.isNull() )
2161 {
2163 mLabelsEnabled = layer_node.toElement().attribute( u"labelsEnabled"_s, u"0"_s ).toInt();
2165 }
2166 }
2167
2168 if ( categories.testFlag( MapTips ) )
2169 {
2170 QDomElement mapTipElem = layer_node.namedItem( u"mapTip"_s ).toElement();
2171 setMapTipTemplate( mapTipElem.text() );
2172 setMapTipsEnabled( mapTipElem.attribute( u"enabled"_s, u"1"_s ).toInt() == 1 );
2173 }
2174
2175 // read attribute table attribute table paths
2176 if ( categories.testFlag( AttributeTable ) )
2177 {
2178 readRasterAttributeTableExternalPaths( layer_node, context );
2179 }
2180
2181 if ( categories.testFlag( Legend ) )
2182 {
2183 QgsReadWriteContextCategoryPopper p = context.enterCategory( tr( "Legend" ) );
2184
2185 const QDomElement legendElem = layer_node.firstChildElement( u"legend"_s );
2186 QgsMapLayerLegend *rasterLegend = legend();
2187 if ( rasterLegend && !legendElem.isNull() )
2188 {
2189 rasterLegend->readXml( legendElem, context );
2190 }
2191 else if ( rasterLegend )
2192 {
2193 // Temporary fix for #63346 because legend was not saved if empty
2195 }
2196 }
2197
2198 emit rendererChanged();
2200
2201 return true;
2202}
2203
2204bool QgsRasterLayer::readStyle( const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories )
2205{
2207
2208 return readSymbology( node, errorMessage, context, categories );
2209}
2210
2211bool QgsRasterLayer::readXml( const QDomNode &layer_node, QgsReadWriteContext &context )
2212{
2214
2215 QgsDebugMsgLevel( u"Entered"_s, 4 );
2216 // Make sure to read the file first so stats etc are initialized properly!
2217
2218 //process provider key
2219 const QDomNode pkeyNode = layer_node.namedItem( u"provider"_s );
2220
2221 if ( pkeyNode.isNull() )
2222 {
2223 mProviderKey = u"gdal"_s;
2224 }
2225 else
2226 {
2227 const QDomElement pkeyElt = pkeyNode.toElement();
2228 mProviderKey = pkeyElt.text();
2229 if ( mProviderKey.isEmpty() )
2230 {
2231 mProviderKey = u"gdal"_s;
2232 }
2233 }
2234
2235 // Open the raster source based on provider and datasource
2236
2237 // Go down the raster-data-provider paradigm
2238
2239 // Collect provider-specific information
2240
2241 const QDomNode rpNode = layer_node.namedItem( u"rasterproperties"_s );
2242
2243 if ( mProviderKey == "wms"_L1 )
2244 {
2245 // >>> BACKWARD COMPATIBILITY < 1.9
2246 // The old WMS URI format does not contain all the information, we add them here.
2247 if ( !mDataSource.contains( "crs="_L1 ) && !mDataSource.contains( "format="_L1 ) )
2248 {
2249 QgsDebugMsgLevel( u"Old WMS URI format detected -> adding params"_s, 4 );
2250 QgsDataSourceUri uri;
2252 QDomElement layerElement = rpNode.firstChildElement( u"wmsSublayer"_s );
2253 while ( !layerElement.isNull() )
2254 {
2255 // TODO: sublayer visibility - post-0.8 release timeframe
2256
2257 // collect name for the sublayer
2258 uri.setParam( u"layers"_s, layerElement.namedItem( u"name"_s ).toElement().text() );
2259
2260 // collect style for the sublayer
2261 uri.setParam( u"styles"_s, layerElement.namedItem( u"style"_s ).toElement().text() );
2262
2263 layerElement = layerElement.nextSiblingElement( u"wmsSublayer"_s );
2264 }
2265
2266 // Collect format
2267 uri.setParam( u"format"_s, rpNode.namedItem( u"wmsFormat"_s ).toElement().text() );
2268
2269 // WMS CRS URL param should not be mixed with that assigned to the layer.
2270 // In the old WMS URI version there was no CRS and layer crs().authid() was used.
2271 uri.setParam( u"crs"_s, crs().authid() );
2272 mDataSource = uri.encodedUri();
2273 }
2274 // <<< BACKWARD COMPATIBILITY < 1.9
2275 }
2276
2278 {
2279 const QgsDataProvider::ProviderOptions providerOptions { context.transformContext() };
2281
2283 {
2284 const QDomNode extentNode = layer_node.namedItem( u"extent"_s );
2285 if ( !extentNode.isNull() )
2286 {
2287 // get the extent
2288 const QgsRectangle mbr = QgsXmlUtils::readRectangle( extentNode.toElement() );
2289
2290 // store the extent
2291 setExtent( mbr );
2292 }
2293 }
2294 setDataProvider( mProviderKey, providerOptions, flags );
2295 }
2296
2297 mOriginalStyleElement = layer_node.namedItem( u"originalStyle"_s ).firstChildElement();
2298 if ( mOriginalStyleElement.isNull() )
2299 mOriginalStyleElement = layer_node.toElement();
2300 mOriginalStyleDocument = layer_node.ownerDocument();
2301
2302 if ( !mDataProvider )
2303 {
2305 {
2306 QgsDebugError( u"Raster data provider could not be created for %1"_s.arg( mDataSource ) );
2307 return false;
2308 }
2309 }
2310
2311 QString error;
2312 const bool res = readSymbology( layer_node, error, context );
2313
2314 // old wms settings we need to correct
2315 if ( res && mProviderKey == "wms"_L1 && !renderer() )
2316 {
2317 setRendererForDrawingStyle( Qgis::RasterDrawingStyle::SingleBandColorData );
2318 }
2319
2320 // Check timestamp
2321 // This was probably introduced to reload completely raster if data changed and
2322 // reset completely symbology to reflect new data type etc. It creates however
2323 // problems, because user defined symbology is complete lost if data file time
2324 // changed (the content may be the same). See also 6900.
2325#if 0
2326 QDomNode stampNode = layer_node.namedItem( "timestamp" );
2327 if ( !stampNode.isNull() )
2328 {
2329 QDateTime stamp = QDateTime::fromString( stampNode.toElement().text(), Qt::ISODate );
2330 // TODO: very bad, we have to load twice!!! Make QgsDataProvider::timestamp() static?
2331 if ( stamp < mDataProvider->dataTimestamp() )
2332 {
2333 QgsDebugMsgLevel( u"data changed, reload provider"_s, 3 );
2334 closeDataProvider();
2335 init();
2337 if ( !isValid() ) return false;
2338 }
2339 }
2340#endif
2341
2342 // Load user no data value
2343 const QDomElement noDataElement = layer_node.firstChildElement( u"noData"_s );
2344
2345 const QDomNodeList noDataBandList = noDataElement.elementsByTagName( u"noDataList"_s );
2346
2347 for ( int i = 0; mDataProvider && i < noDataBandList.size(); ++i )
2348 {
2349 const QDomElement bandElement = noDataBandList.at( i ).toElement();
2350 bool ok;
2351 const int bandNo = bandElement.attribute( u"bandNo"_s ).toInt( &ok );
2352 QgsDebugMsgLevel( u"bandNo = %1"_s.arg( bandNo ), 4 );
2353 if ( ok && ( bandNo > 0 ) && ( bandNo <= mDataProvider->bandCount() ) )
2354 {
2355 mDataProvider->setUseSourceNoDataValue( bandNo, bandElement.attribute( u"useSrcNoData"_s ).toInt() );
2356 QgsRasterRangeList myNoDataRangeList;
2357
2358 const QDomNodeList rangeList = bandElement.elementsByTagName( u"noDataRange"_s );
2359
2360 myNoDataRangeList.reserve( rangeList.size() );
2361 for ( int j = 0; j < rangeList.size(); ++j )
2362 {
2363 const QDomElement rangeElement = rangeList.at( j ).toElement();
2364 const QgsRasterRange myNoDataRange( rangeElement.attribute( u"min"_s ).toDouble(), rangeElement.attribute( u"max"_s ).toDouble() );
2365 QgsDebugMsgLevel( u"min = %1 %2"_s.arg( rangeElement.attribute( "min" ) ).arg( myNoDataRange.min() ), 4 );
2366 myNoDataRangeList << myNoDataRange;
2367 }
2368 mDataProvider->setUserNoDataValue( bandNo, myNoDataRangeList );
2369 }
2370 }
2371
2372 readRasterAttributeTableExternalPaths( layer_node, context );
2373
2374 readStyleManager( layer_node );
2375
2376 return res;
2377}
2378
2379bool QgsRasterLayer::writeSymbology( QDomNode &layer_node, QDomDocument &document, QString &errorMessage, const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
2380{
2382
2383 Q_UNUSED( errorMessage )
2384 // TODO: implement categories for raster layer
2385
2386 QDomElement layerElement = layer_node.toElement();
2387
2388 writeCommonStyle( layerElement, document, context, categories );
2389
2390 if ( categories.testFlag( Labeling ) )
2391 {
2392 if ( mLabeling )
2393 {
2394 QDomElement labelingElement = mLabeling->save( document, context );
2395 layerElement.appendChild( labelingElement );
2396 }
2397 if ( mLabelsEnabled )
2398 layerElement.setAttribute( u"labelsEnabled"_s, u"1"_s );
2399 }
2400
2401 // save map tip
2402 if ( categories.testFlag( MapTips ) )
2403 {
2404 QDomElement mapTipElem = document.createElement( u"mapTip"_s );
2405 mapTipElem.setAttribute( u"enabled"_s, mapTipsEnabled() );
2406 QDomText mapTipText = document.createTextNode( mapTipTemplate() );
2407 mapTipElem.appendChild( mapTipText );
2408 layer_node.toElement().appendChild( mapTipElem );
2409 }
2410
2411 // save attribute table attribute table paths
2412 if ( categories.testFlag( AttributeTable ) )
2413 {
2414 writeRasterAttributeTableExternalPaths( layer_node, document, context );
2415 }
2416
2417 // pipe considers Symbology and Rendering components, why it's always handled as one
2418 if ( categories.testFlag( Symbology ) || categories.testFlag( Rendering ) )
2419 {
2420 // Store pipe members into pipe element, in future, it will be
2421 // possible to add custom filters into the pipe
2422 QDomElement pipeElement = document.createElement( u"pipe"_s );
2423
2424 for ( int i = 0; i < mPipe->size(); i++ )
2425 {
2426 QgsRasterInterface *interface = mPipe->at( i );
2427 if ( !interface )
2428 continue;
2429 interface->writeXml( document, pipeElement );
2430 }
2431
2432 QDomElement elemDataDefinedProperties = document.createElement( u"pipe-data-defined-properties"_s );
2433 mPipe->dataDefinedProperties().writeXml( elemDataDefinedProperties, QgsRasterPipe::propertyDefinitions() );
2434 layer_node.appendChild( elemDataDefinedProperties );
2435
2436 QDomElement resamplingStageElement = document.createElement( u"resamplingStage"_s );
2437 const QDomText resamplingStageText = document.createTextNode( resamplingStage() == Qgis::RasterResamplingStage::Provider ? u"provider"_s : u"resamplingFilter"_s );
2438 resamplingStageElement.appendChild( resamplingStageText );
2439 pipeElement.appendChild( resamplingStageElement );
2440
2441 layer_node.appendChild( pipeElement );
2442
2443 if ( !isValid() && !mOriginalStyleElement.isNull() )
2444 {
2445 QDomElement originalStyleElement = document.createElement( u"originalStyle"_s );
2446 originalStyleElement.appendChild( mOriginalStyleElement );
2447 layer_node.appendChild( originalStyleElement );
2448 }
2449
2450 // add blend mode node
2451 QDomElement blendModeElement = document.createElement( u"blendMode"_s );
2452 const QDomText blendModeText = document.createTextNode( QString::number( static_cast< int >( QgsPainting::getBlendModeEnum( blendMode() ) ) ) );
2453 blendModeElement.appendChild( blendModeText );
2454 layer_node.appendChild( blendModeElement );
2455 }
2456
2457 if ( categories.testFlag( Legend ) && legend() )
2458 {
2459 QDomElement legendElement = legend()->writeXml( document, context );
2460 if ( !legendElement.isNull() )
2461 layer_node.appendChild( legendElement );
2462 }
2463
2464 return true;
2465}
2466
2467bool QgsRasterLayer::writeStyle( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
2468{
2470
2471 return writeSymbology( node, doc, errorMessage, context, categories );
2472}
2473
2474bool QgsRasterLayer::writeXml( QDomNode &layer_node, QDomDocument &document, const QgsReadWriteContext &context ) const
2475{
2477
2478 if ( !mDataProvider )
2479 return false;
2480
2481 // first get the layer element so that we can append the type attribute
2482
2483 QDomElement mapLayerNode = layer_node.toElement();
2484
2485 if ( mapLayerNode.isNull() || "maplayer" != mapLayerNode.nodeName() )
2486 {
2487 QgsMessageLog::logMessage( tr( "<maplayer> not found." ), tr( "Raster" ) );
2488 return false;
2489 }
2490
2491 mapLayerNode.setAttribute( u"type"_s, QgsMapLayerFactory::typeToString( Qgis::LayerType::Raster ) );
2492
2493 // add provider node
2494
2495 QDomElement provider = document.createElement( u"provider"_s );
2496 const QDomText providerText = document.createTextNode( mProviderKey );
2497 provider.appendChild( providerText );
2498 layer_node.appendChild( provider );
2499
2500 // User no data
2501 QDomElement noData = document.createElement( u"noData"_s );
2502
2503 for ( int bandNo = 1; bandNo <= mDataProvider->bandCount(); bandNo++ )
2504 {
2505 QDomElement noDataRangeList = document.createElement( u"noDataList"_s );
2506 noDataRangeList.setAttribute( u"bandNo"_s, bandNo );
2507 noDataRangeList.setAttribute( u"useSrcNoData"_s, mDataProvider->useSourceNoDataValue( bandNo ) );
2508
2509 const auto constUserNoDataValues = mDataProvider->userNoDataValues( bandNo );
2510 for ( const QgsRasterRange &range : constUserNoDataValues )
2511 {
2512 QDomElement noDataRange = document.createElement( u"noDataRange"_s );
2513
2514 noDataRange.setAttribute( u"min"_s, QgsRasterBlock::printValue( range.min() ) );
2515 noDataRange.setAttribute( u"max"_s, QgsRasterBlock::printValue( range.max() ) );
2516 noDataRangeList.appendChild( noDataRange );
2517 }
2518
2519 noData.appendChild( noDataRangeList );
2520 }
2521 if ( noData.hasChildNodes() )
2522 {
2523 layer_node.appendChild( noData );
2524 }
2525
2526 // Store file-based raster attribute table paths (if any)
2527 writeRasterAttributeTableExternalPaths( layer_node, document, context );
2528
2529 writeStyleManager( layer_node, document );
2530
2531 //write out the symbology
2532 QString errorMsg;
2533 return writeSymbology( layer_node, document, errorMsg, context );
2534}
2535
2536
2543
2544QString QgsRasterLayer::decodedSource( const QString &source, const QString &provider, const QgsReadWriteContext &context ) const
2545{
2547
2548 return QgsProviderRegistry::instance()->relativeToAbsoluteUri( provider, source, context );
2549}
2550
2552{
2554
2555 if ( !mDataProvider )
2556 return 0;
2557 return mDataProvider->xSize();
2558}
2559
2561{
2563
2564 if ( !mDataProvider )
2565 return 0;
2566 return mDataProvider->ySize();
2567}
2568
2570{
2572
2573 mPipe->setResamplingStage( stage );
2574}
2575
2577{
2579
2580 return mPipe->resamplingStage();
2581}
2582
2583bool QgsRasterLayer::update()
2584{
2586
2587 QgsDebugMsgLevel( u"entered."_s, 4 );
2588 // Check if data changed
2589 if ( mDataProvider && mDataProvider->dataTimestamp() > mDataProvider->timestamp() )
2590 {
2591 QgsDebugMsgLevel( u"reload data"_s, 4 );
2592 closeDataProvider();
2593 init();
2594 const QgsDataProvider::ProviderOptions providerOptions;
2597 {
2599 }
2600 setDataProvider( mProviderKey, providerOptions, flags );
2601 emit dataChanged();
2602 }
2603 return isValid();
2604}
2605
2606#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:2363
RasterResamplingStage
Stage at which raster resampling occurs.
Definition qgis.h:1548
@ Provider
Resampling occurs in Provider.
Definition qgis.h:1550
@ ResampleFilter
Resampling occurs in ResamplingFilter.
Definition qgis.h:1549
@ ProviderHintBenefitsFromResampling
Provider benefits from resampling and should apply user default resampling settings.
Definition qgis.h:5047
@ ProviderHintCanPerformProviderResampling
Provider can perform resampling (to be opposed to post rendering resampling).
Definition qgis.h:5048
@ ReadLayerMetadata
Provider can read layer metadata from data store. Since QGIS 3.0. See QgsDataProvider::layerMetadata(...
Definition qgis.h:5045
@ Palette
Palette.
Definition qgis.h:4922
@ MultiBand
Multi band.
Definition qgis.h:4923
@ SingleBandColorData
Single band containing color data.
Definition qgis.h:4924
@ GrayOrUndefined
Gray or undefined.
Definition qgis.h:4921
RasterRangeLimit
Describes the limits used to compute raster ranges (min/max values).
Definition qgis.h:1623
@ CumulativeCut
Range is [ min + cumulativeCutLower() * (max - min), min + cumulativeCutUpper() * (max - min) ].
Definition qgis.h:1627
@ MinimumMaximum
Real min-max values.
Definition qgis.h:1625
@ NotSet
User defined.
Definition qgis.h:1624
@ Linear
Interpolates the color between two class breaks linearly.
Definition qgis.h:1504
@ Discrete
Assigns the color of the higher class for every pixel between two class breaks.
Definition qgis.h:1505
@ IsBasemapSource
Associated source should be considered a 'basemap' layer. See Qgis::MapLayerProperty::IsBasemapLayer.
Definition qgis.h:2391
@ Bilinear
Bilinear (2x2 kernel) resampling.
Definition qgis.h:1564
@ Cubic
Cubic Convolution Approximation (4x4 kernel) resampling.
Definition qgis.h:1565
RasterDrawingStyle
Raster drawing styles.
Definition qgis.h:4936
@ SingleBandGray
A single band image drawn as a range of gray colors.
Definition qgis.h:4938
@ SingleBandColorData
ARGB values rendered directly.
Definition qgis.h:4947
@ 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:4946
@ PalettedColor
A "Palette" image drawn using color table.
Definition qgis.h:4940
@ SingleBandPseudoColor
A single band image drawn using a pseudocolor algorithm.
Definition qgis.h:4939
@ Undefined
Undefined.
Definition qgis.h:4937
QFlags< RasterInterfaceCapability > RasterInterfaceCapabilities
Raster interface capabilities.
Definition qgis.h:5030
BlendMode
Blending modes defining the available composition modes that can be used when painting.
Definition qgis.h:5087
@ Size
Original data source size (and thus resolution) is known, it is not always available,...
Definition qgis.h:5012
@ IdentifyValue
Numerical values.
Definition qgis.h:5017
@ IdentifyFeature
WMS GML -> feature.
Definition qgis.h:5020
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:4699
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:1640
@ FixedCanvas
Current extent of the canvas (at the time of computation) is used to compute statistics.
Definition qgis.h:1641
QFlags< MapLayerProperty > MapLayerProperties
Map layer properties.
Definition qgis.h:2367
@ 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:4869
@ AlphaBand
Alpha (0=transparent, 255=opaque).
Definition qgis.h:4876
@ PaletteIndex
Paletted (see associated color table).
Definition qgis.h:4872
@ ContinuousPalette
Continuous palette, QGIS addition, GRASS.
Definition qgis.h:4887
RasterIdentifyFormat
Raster identify formats.
Definition qgis.h:4989
@ Feature
WMS GML/JSON -> feature.
Definition qgis.h:4994
@ Value
Numerical pixel value.
Definition qgis.h:4991
@ Undefined
Undefined.
Definition qgis.h:4990
@ Preferred
Preferred format, matching the most recent WKT ISO standard. Currently an alias to WKT2_2019,...
Definition qgis.h:2527
QString abstract() const
Returns a free-form description of the resource.
QString title() const
Returns the human readable name of the resource, typically displayed in search results.
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 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.
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.
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.
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.
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.
static QgsSettingsTreeNode * sTreeRaster
Stores settings for use within QGIS.
Definition qgssettings.h:68
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
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:7157
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
Definition qgis.h:6975
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition qgis.h:6880
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:63
#define QgsDebugError(str)
Definition qgslogger.h:59
#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.