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