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