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