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