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