QGIS API Documentation 3.41.0-Master (af5edcb665c)
Loading...
Searching...
No Matches
qgsrasterlayer.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsrasterlayer.cpp - description
3 -------------------
4begin : Sat Jun 22 2002
5copyright : (C) 2003 by Tim Sutton, Steve Halasz and Gary E.Sherman
6email : tim at linfiniti.com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17#include "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
66#include <cmath>
67#include <cstdio>
68#include <limits>
69#include <typeinfo>
70
71#include <QApplication>
72#include <QCursor>
73#include <QDir>
74#include <QDomElement>
75#include <QDomNode>
76#include <QFile>
77#include <QFileInfo>
78#include <QFont>
79#include <QFontMetrics>
80#include <QFrame>
81#include <QImage>
82#include <QLabel>
83#include <QList>
84#include <QPainter>
85#include <QPixmap>
86#include <QRegularExpression>
87#include <QSlider>
88#include <QUrl>
89
92
93#define ERR(message) QGS_ERROR_MESSAGE(message,"Raster layer")
94
95const double QgsRasterLayer::SAMPLE_SIZE = 250000;
96
103
110
112 : QgsMapLayer( Qgis::LayerType::Raster )
113 , QSTRING_NOT_SET( QStringLiteral( "Not Set" ) )
114 , TRSTRING_NOT_SET( tr( "Not Set" ) )
115 , mTemporalProperties( new QgsRasterLayerTemporalProperties( this ) )
116 , mElevationProperties( new QgsRasterLayerElevationProperties( this ) )
117 , mPipe( std::make_unique< QgsRasterPipe >() )
118{
119 init();
120 setValid( false );
121}
122
124 const QString &baseName,
125 const QString &providerKey,
126 const LayerOptions &options )
127 : QgsMapLayer( Qgis::LayerType::Raster, baseName, uri )
128 // Constant that signals property not used.
129 , QSTRING_NOT_SET( QStringLiteral( "Not Set" ) )
130 , TRSTRING_NOT_SET( tr( "Not Set" ) )
131 , mTemporalProperties( new QgsRasterLayerTemporalProperties( this ) )
132 , mElevationProperties( new QgsRasterLayerElevationProperties( this ) )
133 , mPipe( std::make_unique< QgsRasterPipe >() )
134{
136
137 QgsDebugMsgLevel( QStringLiteral( "Entered" ), 4 );
138 setProviderType( providerKey );
139
140 const QgsDataProvider::ProviderOptions providerOptions { options.transformContext };
141 Qgis::DataProviderReadFlags providerFlags;
142 if ( options.loadDefaultStyle )
143 {
145 }
146
147 setDataSource( uri, baseName, providerKey, providerOptions, providerFlags );
148
149 if ( isValid() )
150 {
151 mTemporalProperties->setDefaultsFromDataProviderTemporalCapabilities( mDataProvider->temporalCapabilities() );
152 }
153
154} // QgsRasterLayer ctor
155
157{
158 emit willBeDeleted();
159
160 mLabeling.reset();
161
162 setValid( false );
163 // Note: provider and other interfaces are owned and deleted by pipe
164}
165
167{
169
171 if ( mDataProvider )
172 {
173 options.transformContext = mDataProvider->transformContext();
174 }
175 std::unique_ptr< QgsRasterLayer > layer = std::make_unique< QgsRasterLayer >( source(), name(), mProviderKey, options );
176 QgsMapLayer::clone( layer.get() );
177 layer->mElevationProperties = mElevationProperties->clone();
178 layer->mElevationProperties->setParent( layer.get() );
179 layer->setMapTipTemplate( mapTipTemplate() );
180 layer->setMapTipsEnabled( mapTipsEnabled() );
181
182 // do not clone data provider which is the first element in pipe
183 for ( int i = 1; i < mPipe->size(); i++ )
184 {
185 if ( mPipe->at( i ) )
186 layer->pipe()->set( mPipe->at( i )->clone() );
187 }
188 layer->pipe()->setDataDefinedProperties( mPipe->dataDefinedProperties() );
189 layer->setResamplingStage( mPipe->resamplingStage() );
190 if ( mDataProvider && layer->dataProvider() )
191 {
192 layer->dataProvider()->setZoomedInResamplingMethod( mDataProvider->zoomedInResamplingMethod() );
193 layer->dataProvider()->setZoomedOutResamplingMethod( mDataProvider->zoomedOutResamplingMethod() );
194 }
195
196 layer->setLabelsEnabled( mLabelsEnabled );
197 if ( mLabeling )
198 layer->setLabeling( mLabeling->clone() );
199
200 return layer.release();
201}
202
204{
206
207 if ( !mElevationProperties->isEnabled() )
208 return nullptr;
209
210 return new QgsRasterLayerProfileGenerator( this, request );
211}
212
214//
215// Static Methods and members
216//
218
219bool QgsRasterLayer::isValidRasterFileName( const QString &fileNameQString, QString &retErrMsg )
220{
221 const bool myIsValid = QgsGdalProvider::isValidRasterFileName( fileNameQString, retErrMsg );
222 return myIsValid;
223}
224
225bool QgsRasterLayer::isValidRasterFileName( QString const &fileNameQString )
226{
227 QString retErrMsg;
228 return isValidRasterFileName( fileNameQString, retErrMsg );
229}
230
231QDateTime QgsRasterLayer::lastModified( QString const &name )
232{
233 QgsDebugMsgLevel( "name=" + name, 4 );
234 QDateTime t;
235
236 const QFileInfo fi( name );
237
238 // Is it file?
239 if ( !fi.exists() )
240 return t;
241
242 t = fi.lastModified();
243
244 QgsDebugMsgLevel( "last modified = " + t.toString(), 4 );
245
246 return t;
247}
248
255
256// typedef for the QgsDataProvider class factory
258
260//
261// Non Static Public methods
262//
264
266{
268
269 if ( !mDataProvider ) return 0;
270 return mDataProvider->bandCount();
271}
272
273QString QgsRasterLayer::bandName( int bandNo ) const
274{
276
277 if ( !mDataProvider ) return QString();
278 return mDataProvider->generateBandName( bandNo );
279}
280
282{
284
285 if ( !mDataProvider )
286 return nullptr;
287 return mDataProvider->attributeTable( bandNoInt );
288}
289
291{
293
294 if ( !mDataProvider )
295 return 0;
296
297 int ratCount { 0 };
298 for ( int bandNo = 1; bandNo <= bandCount(); ++bandNo )
299 {
300 if ( attributeTable( bandNo ) )
301 {
302 ratCount++;
303 }
304 }
305 return ratCount;
306}
307
314
315void QgsRasterLayer::setRendererForDrawingStyle( Qgis::RasterDrawingStyle drawingStyle )
316{
318
319 setRenderer( QgsApplication::rasterRendererRegistry()->defaultRendererForDrawingStyle( drawingStyle, mDataProvider ) );
320}
321
328
330{
332
333 return mDataProvider;
334}
335
337{
339
340 if ( mDataProvider )
341 {
342 mDataProvider->reloadData();
343 }
344}
345
352
353
354void QgsRasterLayer::draw( QPainter *theQPainter,
355 QgsRasterViewPort *rasterViewPort,
356 const QgsMapToPixel *qgsMapToPixel )
357{
359
360 QgsDebugMsgLevel( QStringLiteral( " 3 arguments" ), 4 );
361 QElapsedTimer time;
362 time.start();
363 //
364 //
365 // The goal here is to make as many decisions as possible early on (outside of the rendering loop)
366 // so that we can maximise performance of the rendering process. So now we check which drawing
367 // procedure to use :
368 //
369
370 QgsRasterProjector *projector = mPipe->projector();
371 bool restoreOldResamplingStage = false;
372 const Qgis::RasterResamplingStage oldResamplingState = resamplingStage();
373 // TODO add a method to interface to get provider and get provider
374 // params in QgsRasterProjector
375
376 if ( projector )
377 {
378 // Force provider resampling if reprojection is needed
379 if ( mDataProvider &&
381 rasterViewPort->mSrcCRS != rasterViewPort->mDestCRS &&
382 oldResamplingState != Qgis::RasterResamplingStage::Provider )
383 {
384 restoreOldResamplingStage = true;
386 }
387 projector->setCrs( rasterViewPort->mSrcCRS, rasterViewPort->mDestCRS, rasterViewPort->mTransformContext );
388 }
389
390 // Drawer to pipe?
391 QgsRasterIterator iterator( mPipe->last() );
392 QgsRasterDrawer drawer( &iterator );
393 drawer.draw( theQPainter, rasterViewPort, qgsMapToPixel );
394
395 if ( restoreOldResamplingStage )
396 {
397 setResamplingStage( oldResamplingState );
398 }
399
400 QgsDebugMsgLevel( QStringLiteral( "total raster draw time (ms): %1" ).arg( time.elapsed(), 5 ), 4 );
401}
402
404{
406
407 QgsRasterRenderer *renderer = mPipe->renderer();
408 return renderer ? renderer->legendSymbologyItems() : QList< QPair< QString, QColor > >();;
409}
410
412{
414
415 if ( !mDataProvider )
416 return QString();
417
418 const QgsLayerMetadataFormatter htmlFormatter( metadata() );
419 QString myMetadata = QStringLiteral( "<html><head></head>\n<body>\n" );
420
421 myMetadata += generalHtmlMetadata();
422
423 // Begin Provider section
424 myMetadata += QStringLiteral( "<h1>" ) + tr( "Information from provider" ) + QStringLiteral( "</h1>\n<hr>\n" ) + QStringLiteral( "<table class=\"list-view\">\n" );
425
426 myMetadata += QStringLiteral( "\n" ) %
427 // Extent
428 QStringLiteral( "<tr><td class=\"highlight\">" ) % tr( "Extent" ) % QStringLiteral( "</td><td>" ) % extent().toString() % QStringLiteral( "</td></tr>\n" ) %
429
430 // Raster Width
431 QStringLiteral( "<tr><td class=\"highlight\">" ) % tr( "Width" ) % QStringLiteral( "</td><td>" );
432 if ( dataProvider()->capabilities() & Qgis::RasterInterfaceCapability::Size )
433 myMetadata += QString::number( width() );
434 else
435 myMetadata += tr( "n/a" );
436 myMetadata += QStringLiteral( "</td></tr>\n" ) %
437
438 // Raster height
439 QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Height" ) + QStringLiteral( "</td><td>" );
440 if ( dataProvider()->capabilities() & Qgis::RasterInterfaceCapability::Size )
441 myMetadata += QString::number( height() );
442 else
443 myMetadata += tr( "n/a" );
444 myMetadata += QStringLiteral( "</td></tr>\n" ) %
445
446 // Data type
447 QStringLiteral( "<tr><td class=\"highlight\">" ) % tr( "Data type" ) % QStringLiteral( "</td><td>" );
448 // Just use the first band
449 switch ( mDataProvider->sourceDataType( 1 ) )
450 {
452 myMetadata += tr( "Byte - Eight bit unsigned integer" );
453 break;
455 myMetadata += tr( "Int8 - Eight bit signed integer" );
456 break;
458 myMetadata += tr( "UInt16 - Sixteen bit unsigned integer " );
459 break;
461 myMetadata += tr( "Int16 - Sixteen bit signed integer " );
462 break;
464 myMetadata += tr( "UInt32 - Thirty two bit unsigned integer " );
465 break;
467 myMetadata += tr( "Int32 - Thirty two bit signed integer " );
468 break;
470 myMetadata += tr( "Float32 - Thirty two bit floating point " );
471 break;
473 myMetadata += tr( "Float64 - Sixty four bit floating point " );
474 break;
476 myMetadata += tr( "CInt16 - Complex Int16 " );
477 break;
479 myMetadata += tr( "CInt32 - Complex Int32 " );
480 break;
482 myMetadata += tr( "CFloat32 - Complex Float32 " );
483 break;
485 myMetadata += tr( "CFloat64 - Complex Float64 " );
486 break;
487 default:
488 myMetadata += tr( "Could not determine raster data type." );
489 }
490 myMetadata += QStringLiteral( "</td></tr>\n" ) %
491
492 // Insert provider-specific (e.g. WMS-specific) metadata
493 mDataProvider->htmlMetadata() %
494
495 // End Provider section
496 QStringLiteral( "</table>\n<br><br>" );
497
498 // CRS
499 myMetadata += crsHtmlMetadata();
500
501 // Identification section
502 myMetadata += QStringLiteral( "<h1>" ) % tr( "Identification" ) % QStringLiteral( "</h1>\n<hr>\n" ) %
503 htmlFormatter.identificationSectionHtml() %
504 QStringLiteral( "<br><br>\n" ) %
505
506 // extent section
507 QStringLiteral( "<h1>" ) % tr( "Extent" ) % QStringLiteral( "</h1>\n<hr>\n" ) %
508 htmlFormatter.extentSectionHtml( ) %
509 QStringLiteral( "<br><br>\n" ) %
510
511 // Start the Access section
512 QStringLiteral( "<h1>" ) % tr( "Access" ) % QStringLiteral( "</h1>\n<hr>\n" ) %
513 htmlFormatter.accessSectionHtml( ) %
514 QStringLiteral( "<br><br>\n" ) %
515
516 // Bands section
517 QStringLiteral( "</table>\n<br><br><h1>" ) % tr( "Bands" ) % QStringLiteral( "</h1>\n<hr>\n<table class=\"list-view\">\n" ) %
518
519 // Band count
520 QStringLiteral( "<tr><td class=\"highlight\">" ) % tr( "Band count" ) % QStringLiteral( "</td><td>" ) % QString::number( bandCount() ) % QStringLiteral( "</td></tr>\n" );
521
522 // Band table
523 myMetadata += QStringLiteral( "</table>\n<br><table width=\"100%\" class=\"tabular-view\">\n" ) %
524 QStringLiteral( "<tr><th>" ) % tr( "Number" ) % QStringLiteral( "</th><th>" ) % tr( "Band" ) % QStringLiteral( "</th><th>" ) % tr( "NoData" ) % QStringLiteral( "</th><th>" ) %
525 tr( "Min" ) % QStringLiteral( "</th><th>" ) % tr( "Max" ) % QStringLiteral( "</th></tr>\n" );
526
527 QgsRasterDataProvider *provider = const_cast< QgsRasterDataProvider * >( mDataProvider );
528 for ( int i = 1; i <= bandCount(); i++ )
529 {
530 QString rowClass;
531 if ( i % 2 )
532 rowClass = QStringLiteral( "class=\"odd-row\"" );
533
534 myMetadata += QStringLiteral( "<tr " ) % rowClass % QStringLiteral( "><td>" ) % QString::number( i ) % QStringLiteral( "</td><td>" ) % bandName( i ) % QStringLiteral( "</td><td>" );
535
536 if ( dataProvider()->sourceHasNoDataValue( i ) )
537 myMetadata += QString::number( dataProvider()->sourceNoDataValue( i ) );
538 else
539 myMetadata += tr( "n/a" );
540 myMetadata += QLatin1String( "</td>" );
541
542 if ( provider->hasStatistics( i, Qgis::RasterBandStatistic::Min | Qgis::RasterBandStatistic::Max, provider->extent(), static_cast<int>( SAMPLE_SIZE ) ) )
543 {
544 const QgsRasterBandStats myRasterBandStats = provider->bandStatistics( i, Qgis::RasterBandStatistic::Min | Qgis::RasterBandStatistic::Max, provider->extent(), static_cast<int>( SAMPLE_SIZE ) );
545 myMetadata += QStringLiteral( "<td>" ) % QString::number( myRasterBandStats.minimumValue, 'f', 10 ) % QStringLiteral( "</td>" ) %
546 QStringLiteral( "<td>" ) % QString::number( myRasterBandStats.maximumValue, 'f', 10 ) % QStringLiteral( "</td>" );
547 }
548 else
549 {
550 myMetadata += QStringLiteral( "<td>" ) % tr( "n/a" ) % QStringLiteral( "</td><td>" ) % tr( "n/a" ) % QStringLiteral( "</td>" );
551 }
552
553 myMetadata += QLatin1String( "</tr>\n" );
554 }
555
556 //close previous bands table
557 myMetadata += QStringLiteral( "</table>\n<br><br>" ) %
558
559 // Start the contacts section
560 QStringLiteral( "<h1>" ) % tr( "Contacts" ) % QStringLiteral( "</h1>\n<hr>\n" ) %
561 htmlFormatter.contactsSectionHtml( ) %
562 QStringLiteral( "<br><br>\n" ) %
563
564 // Start the links section
565 QStringLiteral( "<h1>" ) % tr( "References" ) % QStringLiteral( "</h1>\n<hr>\n" ) %
566 htmlFormatter.linksSectionHtml( ) %
567 QStringLiteral( "<br><br>\n" ) %
568
569 // Start the history section
570 QStringLiteral( "<h1>" ) % tr( "History" ) % QStringLiteral( "</h1>\n<hr>\n" ) %
571 htmlFormatter.historySectionHtml( ) %
572 QStringLiteral( "<br><br>\n" ) %
574 QStringLiteral( "\n</body>\n</html>\n" );
575 return myMetadata;
576}
577
579{
581
583 if ( mDataProvider && ( mDataProvider->flags() & Qgis::DataProviderFlag::IsBasemapSource ) )
584 {
586 }
587 return res;
588}
589
590QPixmap QgsRasterLayer::paletteAsPixmap( int bandNumber )
591{
593
594 //TODO: This function should take dimensions
595 QgsDebugMsgLevel( QStringLiteral( "entered." ), 4 );
596
597 // Only do this for the GDAL provider?
598 // Maybe WMS can do this differently using QImage::numColors and QImage::color()
599 if ( mDataProvider &&
601 {
602 QgsDebugMsgLevel( QStringLiteral( "....found paletted image" ), 4 );
603 QgsColorRampShader myShader;
604 const QList<QgsColorRampShader::ColorRampItem> myColorRampItemList = mDataProvider->colorTable( bandNumber );
605 if ( !myColorRampItemList.isEmpty() )
606 {
607 QgsDebugMsgLevel( QStringLiteral( "....got color ramp item list" ), 4 );
608 myShader.setColorRampItemList( myColorRampItemList );
610 // Draw image
611 const int mySize = 100;
612 QPixmap myPalettePixmap( mySize, mySize );
613 QPainter myQPainter( &myPalettePixmap );
614
615 QImage myQImage = QImage( mySize, mySize, QImage::Format_RGB32 );
616 myQImage.fill( 0 );
617 myPalettePixmap.fill();
618
619 const double myStep = ( static_cast< double >( myColorRampItemList.size() ) - 1 ) / static_cast< double >( mySize * mySize );
620 double myValue = 0.0;
621 for ( int myRow = 0; myRow < mySize; myRow++ )
622 {
623 QRgb *myLineBuffer = reinterpret_cast< QRgb * >( myQImage.scanLine( myRow ) );
624 for ( int myCol = 0; myCol < mySize; myCol++ )
625 {
626 myValue = myStep * static_cast< double >( myCol + myRow * mySize );
627 int c1, c2, c3, c4;
628 myShader.shade( myValue, &c1, &c2, &c3, &c4 );
629 myLineBuffer[ myCol ] = qRgba( c1, c2, c3, c4 );
630 }
631 }
632
633 myQPainter.drawImage( 0, 0, myQImage );
634 return myPalettePixmap;
635 }
636 const QPixmap myNullPixmap;
637 return myNullPixmap;
638 }
639 else
640 {
641 //invalid layer was requested
642 const QPixmap myNullPixmap;
643 return myNullPixmap;
644 }
645}
646
653
655{
657
658// We return one raster pixel per map unit pixel
659// One raster pixel can have several raster units...
660
661// We can only use one of the mGeoTransform[], so go with the
662// horisontal one.
663
664 if ( mDataProvider &&
665 mDataProvider->capabilities() & Qgis::RasterInterfaceCapability::Size && !qgsDoubleNear( mDataProvider->xSize(), 0.0 ) )
666 {
667 return mDataProvider->extent().width() / mDataProvider->xSize();
668 }
669 return 1;
670}
671
673{
675
676 if ( mDataProvider &&
677 mDataProvider->capabilities() & Qgis::RasterInterfaceCapability::Size && !qgsDoubleNear( mDataProvider->ySize(), 0.0 ) )
678 {
679 return mDataProvider->extent().height() / mDataProvider->ySize();
680 }
681 return 1;
682}
683
684void QgsRasterLayer::setOpacity( double opacity )
685{
687
688 if ( !mPipe->renderer() || mPipe->renderer()->opacity() == opacity )
689 return;
690
691 mPipe->renderer()->setOpacity( opacity );
692 emit opacityChanged( opacity );
694}
695
697{
699
700 return mPipe->renderer() ? mPipe->renderer()->opacity() : 1.0;
701}
702
703void QgsRasterLayer::init()
704{
706
708
709 whileBlocking( this )->setLegend( QgsMapLayerLegend::defaultRasterLegend( this ) );
710
711 setRendererForDrawingStyle( Qgis::RasterDrawingStyle::Undefined );
712
713 //Initialize the last view port structure, should really be a class
714 mLastViewPort.mWidth = 0;
715 mLastViewPort.mHeight = 0;
716}
717
719{
721
722 QgsDebugMsgLevel( QStringLiteral( "Entered" ), 4 );
723 setValid( false ); // assume the layer is invalid until we determine otherwise
724
725 // deletes pipe elements (including data provider)
726 mPipe = std::make_unique< QgsRasterPipe >();
727 mDataProvider = nullptr;
728
729 // XXX should I check for and possibly delete any pre-existing providers?
730 // XXX How often will that scenario occur?
731
732 mProviderKey = provider;
733 // set the layer name (uppercase first character)
734 if ( ! mLayerName.isEmpty() ) // XXX shouldn't this happen in parent?
735 {
737 }
738
739 //mBandCount = 0;
740
741 if ( mPreloadedProvider )
742 {
743 mDataProvider = qobject_cast< QgsRasterDataProvider * >( mPreloadedProvider.release() );
744 }
745 else
746 {
747 std::unique_ptr< QgsScopedRuntimeProfile > profile;
748 if ( QgsApplication::profiler()->groupIsActive( QStringLiteral( "projectload" ) ) )
749 profile = std::make_unique< QgsScopedRuntimeProfile >( tr( "Create %1 provider" ).arg( provider ), QStringLiteral( "projectload" ) );
750
751 mDataProvider = qobject_cast< QgsRasterDataProvider * >( QgsProviderRegistry::instance()->createProvider( mProviderKey, mDataSource, options, flags ) );
752 }
753
754 if ( !mDataProvider )
755 {
756 //QgsMessageLog::logMessage( tr( "Cannot instantiate the data provider" ), tr( "Raster" ) );
757 appendError( ERR( tr( "Cannot instantiate the '%1' data provider" ).arg( mProviderKey ) ) );
758 return;
759 }
760 QgsDebugMsgLevel( QStringLiteral( "Data provider created" ), 4 );
761 mDataProvider->setParent( this );
762
763 // Set data provider into pipe even if not valid so that it is deleted with pipe (with layer)
764 mPipe->set( mDataProvider );
765 if ( !mDataProvider->isValid() )
766 {
767 setError( mDataProvider->error() );
768 appendError( ERR( tr( "Provider is not valid (provider: %1, URI: %2" ).arg( mProviderKey, mDataSource ) ) );
769 return;
770 }
771
773 {
774 setMetadata( mDataProvider->layerMetadata() );
775 QgsDebugMsgLevel( QStringLiteral( "Set Data provider QgsLayerMetadata identifier[%1]" ).arg( metadata().identifier() ), 4 );
776 }
777
778 if ( provider == QLatin1String( "gdal" ) )
779 {
780 // make sure that the /vsigzip or /vsizip is added to uri, if applicable
781 mDataSource = mDataProvider->dataSourceUri();
782 }
783
785 {
786 // get the extent
787 const QgsRectangle mbr = mDataProvider->extent();
788
789 // store the extent
790 setExtent( mbr );
791 }
792
793 // upper case the first letter of the layer name
794 QgsDebugMsgLevel( "mLayerName: " + name(), 4 );
795
796 // set up the raster drawing style
797 // Do not set any 'sensible' style here, the style is set later
798
799 // Setup source CRS
800 setCrs( QgsCoordinateReferenceSystem( mDataProvider->crs() ) );
801
802 QgsDebugMsgLevel( "using wkt:\n" + crs().toWkt( Qgis::CrsWktVariant::Preferred ), 4 );
803
804 //defaults - Needs to be set after the Contrast list has been build
805 //Try to read the default contrast enhancement from the config file
806
807 //decide what type of layer this is...
808 //TODO Change this to look at the color interp and palette interp to decide which type of layer it is
809 QgsDebugMsgLevel( "bandCount = " + QString::number( mDataProvider->bandCount() ), 4 );
810 QgsDebugMsgLevel( "dataType = " + qgsEnumValueToKey< Qgis::DataType >( mDataProvider->dataType( 1 ) ), 4 );
811 const int bandCount = mDataProvider->bandCount();
812 if ( bandCount > 2 )
813 {
815 }
816 else if ( bandCount == 2 )
817 {
818 // handle singleband gray with alpha
819 auto colorInterpretationIsGrayOrUndefined = []( Qgis::RasterColorInterpretation interpretation )
820 {
821 return interpretation == Qgis::RasterColorInterpretation::GrayIndex
823 };
824
825 if ( ( colorInterpretationIsGrayOrUndefined( mDataProvider->colorInterpretation( 1 ) ) && mDataProvider->colorInterpretation( 2 ) == Qgis::RasterColorInterpretation::AlphaBand )
826 || ( mDataProvider->colorInterpretation( 1 ) == Qgis::RasterColorInterpretation::AlphaBand && colorInterpretationIsGrayOrUndefined( mDataProvider->colorInterpretation( 2 ) ) ) )
827 {
829 }
830 else
831 {
833 }
834 }
835 else if ( mDataProvider->dataType( 1 ) == Qgis::DataType::ARGB32
836 || mDataProvider->dataType( 1 ) == Qgis::DataType::ARGB32_Premultiplied )
837 {
839 }
842 {
843 mRasterType = Qgis::RasterLayerType::Palette;
844 }
845 else
846 {
848 }
849
850 QgsDebugMsgLevel( "mRasterType = " + qgsEnumValueToKey( mRasterType ), 4 );
851
852 // Raster Attribute Table logic to load from provider or same basename + vat.dbf file.
853 QString errorMessage;
854 bool hasRat { mDataProvider->readNativeAttributeTable( &errorMessage ) };
855 if ( ! hasRat )
856 {
857 errorMessage.clear();
858 QgsDebugMsgLevel( "Native Raster Raster Attribute Table read failed " + errorMessage, 2 );
859 if ( QFile::exists( mDataProvider->dataSourceUri( ) + ".vat.dbf" ) )
860 {
861 std::unique_ptr<QgsRasterAttributeTable> rat = std::make_unique<QgsRasterAttributeTable>();
862 hasRat = rat->readFromFile( mDataProvider->dataSourceUri( ) + ".vat.dbf", &errorMessage );
863 if ( hasRat )
864 {
865 if ( rat->isValid( &errorMessage ) )
866 {
867 mDataProvider->setAttributeTable( 1, rat.release() );
868 QgsDebugMsgLevel( "DBF Raster Attribute Table successfully read from " + mDataProvider->dataSourceUri( ) + ".vat.dbf", 2 );
869 }
870 else
871 {
872 QgsDebugMsgLevel( "DBF Raster Attribute Table is not valid, skipping: " + errorMessage, 2 );
873 }
874 }
875 else
876 {
877 QgsDebugMsgLevel( "DBF Raster Attribute Table read failed " + errorMessage, 2 );
878 }
879 }
880 }
881 else
882 {
883 QgsDebugMsgLevel( "Native Raster Attribute Table read success", 2 );
884 }
885
886 switch ( mRasterType )
887 {
889 {
890 QgsDebugMsgLevel( "Setting drawing style to SingleBandColorDataStyle " + qgsEnumValueToKey( Qgis::RasterDrawingStyle::SingleBandColorData ), 4 );
891 setRendererForDrawingStyle( Qgis::RasterDrawingStyle::SingleBandColorData );
892 break;
893 }
895 {
897 {
898 setRendererForDrawingStyle( Qgis::RasterDrawingStyle::PalettedColor ); //sensible default
899 }
901 {
902 setRendererForDrawingStyle( Qgis::RasterDrawingStyle::SingleBandPseudoColor );
903 // Load color table
904 const QList<QgsColorRampShader::ColorRampItem> colorTable = mDataProvider->colorTable( 1 );
906 if ( r )
907 {
908 // TODO: this should go somewhere else
909 QgsRasterShader *shader = new QgsRasterShader();
910 QgsColorRampShader *colorRampShader = new QgsColorRampShader();
912 colorRampShader->setColorRampItemList( colorTable );
913 shader->setRasterShaderFunction( colorRampShader );
914 r->setShader( shader );
915 }
916 }
917 else
918 {
919 setRendererForDrawingStyle( Qgis::RasterDrawingStyle::SingleBandGray ); //sensible default
920 }
921 break;
922 }
924 {
925 setRendererForDrawingStyle( Qgis::RasterDrawingStyle::MultiBandColor ); //sensible default
926 break;
927 }
929 {
930 setRendererForDrawingStyle( Qgis::RasterDrawingStyle::SingleBandGray ); //sensible default
931 break;
932 }
933 }
934
935 // Auto set alpha band
936 for ( int bandNo = 1; bandNo <= mDataProvider->bandCount(); bandNo++ )
937 {
938 if ( mDataProvider->colorInterpretation( bandNo ) == Qgis::RasterColorInterpretation::AlphaBand )
939 {
940 if ( auto *lRenderer = mPipe->renderer() )
941 {
942 lRenderer->setAlphaBand( bandNo );
943 }
944 break;
945 }
946 }
947
948 // brightness filter
950 mPipe->set( brightnessFilter );
951
952 // hue/saturation filter
954 mPipe->set( hueSaturationFilter );
955
956 // resampler (must be after renderer)
958 mPipe->set( resampleFilter );
959
961 {
962 const QgsSettings settings;
963 QString resampling = settings.value( QStringLiteral( "/Raster/defaultZoomedInResampling" ), QStringLiteral( "nearest neighbour" ) ).toString();
964 if ( resampling == QLatin1String( "bilinear" ) )
965 {
968 }
969 else if ( resampling == QLatin1String( "cubic" ) )
970 {
973 }
974 resampling = settings.value( QStringLiteral( "/Raster/defaultZoomedOutResampling" ), QStringLiteral( "nearest neighbour" ) ).toString();
975 if ( resampling == QLatin1String( "bilinear" ) )
976 {
979 }
980
981 const double maxOversampling = QgsRasterLayer::settingsRasterDefaultOversampling->value();
982 resampleFilter->setMaxOversampling( maxOversampling );
983 mDataProvider->setMaxOversampling( maxOversampling );
984
987 {
989 }
990 else
991 {
993 }
994 }
995
996 // projector (may be anywhere in pipe)
997 QgsRasterProjector *projector = new QgsRasterProjector;
998 mPipe->set( projector );
999
1000 // Set default identify format - use the richest format available
1001 const Qgis::RasterInterfaceCapabilities capabilities = mDataProvider->capabilities();
1004 {
1005 // HTML is usually richest
1006 identifyFormat = Qgis::RasterIdentifyFormat::Html;
1007 }
1008 else if ( capabilities & Qgis::RasterInterfaceCapability::IdentifyFeature )
1009 {
1010 identifyFormat = Qgis::RasterIdentifyFormat::Feature;
1011 }
1012 else if ( capabilities & Qgis::RasterInterfaceCapability::IdentifyText )
1013 {
1014 identifyFormat = Qgis::RasterIdentifyFormat::Text;
1015 }
1016 else if ( capabilities & Qgis::RasterInterfaceCapability::IdentifyValue )
1017 {
1018 identifyFormat = Qgis::RasterIdentifyFormat::Value;
1019 }
1020 setCustomProperty( QStringLiteral( "identify/format" ), QgsRasterDataProvider::identifyFormatName( identifyFormat ) );
1021
1023 {
1024 if ( properties->containsElevationData() )
1025 {
1026 mElevationProperties->setEnabled( true );
1027 }
1028 }
1029
1030 // Store timestamp
1031 // TODO move to provider
1032 mLastModified = lastModified( mDataSource );
1033
1034 // Do a passthrough for the status bar text
1036
1037 //mark the layer as valid
1038 setValid( true );
1039
1040 if ( mDataProvider->supportsSubsetString() )
1041 connect( this, &QgsRasterLayer::subsetStringChanged, this, &QgsMapLayer::configChanged, Qt::UniqueConnection );
1042 else
1044
1045
1046 QgsDebugMsgLevel( QStringLiteral( "exiting." ), 4 );
1047
1048}
1049
1050void QgsRasterLayer::setDataSourcePrivate( const QString &dataSource, const QString &baseName, const QString &provider,
1052{
1054
1055 const bool hadRenderer( renderer() );
1056
1057 QDomImplementation domImplementation;
1058 QDomDocumentType documentType;
1059 QString errorMsg;
1060
1061 bool loadDefaultStyleFlag = false;
1063 {
1064 loadDefaultStyleFlag = true;
1065 }
1066
1067 // Store the original style
1068 if ( hadRenderer && ! loadDefaultStyleFlag )
1069 {
1070 documentType = domImplementation.createDocumentType(
1071 QStringLiteral( "qgis" ), QStringLiteral( "http://mrcc.com/qgis.dtd" ), QStringLiteral( "SYSTEM" ) );
1072
1073 QDomDocument doc = QDomDocument( documentType );
1074 QDomElement styleElem = doc.createElement( QStringLiteral( "qgis" ) );
1075 styleElem.setAttribute( QStringLiteral( "version" ), Qgis::version() );
1076 const QgsReadWriteContext writeContext;
1077 if ( ! writeSymbology( styleElem, doc, errorMsg, writeContext ) )
1078 {
1079 QgsDebugError( QStringLiteral( "Could not store symbology for layer %1: %2" )
1080 .arg( name(),
1081 errorMsg ) );
1082 }
1083 else
1084 {
1085 doc.appendChild( styleElem );
1086
1087 mOriginalStyleDocument = doc;
1088 mOriginalStyleElement = styleElem;
1089 }
1090 }
1091
1092 if ( mDataProvider )
1093 closeDataProvider();
1094
1095 init();
1096
1097 for ( int i = mPipe->size() - 1; i >= 0; --i )
1098 {
1099 mPipe->remove( i );
1100 }
1101
1102 mDataSource = dataSource;
1103 mLayerName = baseName;
1104
1105 setDataProvider( provider, options, flags );
1106
1107 if ( mDataProvider )
1108 mDataProvider->setDataSourceUri( mDataSource );
1109
1110 if ( isValid() )
1111 {
1112 // load default style
1113 bool defaultLoadedFlag = false;
1114 bool restoredStyle = false;
1115 if ( loadDefaultStyleFlag )
1116 {
1117 loadDefaultStyle( defaultLoadedFlag );
1118 }
1119 else if ( !mOriginalStyleElement.isNull() ) // Restore the style
1120 {
1121 QgsReadWriteContext readContext;
1122 if ( ! readSymbology( mOriginalStyleElement, errorMsg, readContext ) )
1123 {
1124 QgsDebugError( QStringLiteral( "Could not restore symbology for layer %1: %2" )
1125 .arg( name() )
1126 .arg( errorMsg ) );
1127
1128 }
1129 else
1130 {
1131 restoredStyle = true;
1132 emit repaintRequested();
1134 emit rendererChanged();
1135 }
1136 }
1137
1138 if ( !defaultLoadedFlag && !restoredStyle )
1139 {
1141 }
1142 }
1143}
1144
1145void QgsRasterLayer::writeRasterAttributeTableExternalPaths( QDomNode &layerNode, QDomDocument &doc, const QgsReadWriteContext &context ) const
1146{
1148
1149 if ( attributeTableCount() > 0 )
1150 {
1151 QDomElement elem = doc.createElement( QStringLiteral( "FileBasedAttributeTables" ) );
1152 for ( int bandNo = 1; bandNo <= bandCount(); bandNo++ )
1153 {
1154 if ( QgsRasterAttributeTable *rat = attributeTable( bandNo ); rat && ! rat->filePath().isEmpty() )
1155 {
1156 QDomElement ratElem = doc.createElement( QStringLiteral( "AttributeTable" ) );
1157 ratElem.setAttribute( QStringLiteral( "band" ), bandNo );
1158 ratElem.setAttribute( QStringLiteral( "path" ), context.pathResolver().writePath( rat->filePath( ) ) );
1159 elem.appendChild( ratElem );
1160 }
1161 }
1162 layerNode.appendChild( elem );
1163 }
1164}
1165
1166void QgsRasterLayer::readRasterAttributeTableExternalPaths( const QDomNode &layerNode, QgsReadWriteContext &context ) const
1167{
1168 const QDomElement ratsElement = layerNode.firstChildElement( QStringLiteral( "FileBasedAttributeTables" ) );
1169 if ( !ratsElement.isNull() && ratsElement.childNodes().count() > 0 )
1170 {
1171 const QDomNodeList ratElements { ratsElement.childNodes() };
1172 for ( int idx = 0; idx < ratElements.count(); idx++ )
1173 {
1174 const QDomNode ratElement { ratElements.at( idx ) };
1175 if ( ratElement.attributes().contains( QStringLiteral( "band" ) )
1176 && ratElement.attributes().contains( QStringLiteral( "path" ) ) )
1177 {
1178 bool ok;
1179 const int band { ratElement.attributes().namedItem( QStringLiteral( "band" ) ).nodeValue().toInt( &ok ) };
1180
1181 // Check band is ok
1182 if ( ! ok || band <= 0 || band > bandCount() )
1183 {
1184 QgsMessageLog::logMessage( tr( "Error reading raster attribute table: invalid band %1." ).arg( band ), tr( "Raster" ) );
1185 continue;
1186 }
1187
1188 const QString path { context.pathResolver().readPath( ratElement.attributes().namedItem( QStringLiteral( "path" ) ).nodeValue() ) };
1189 if ( ! QFile::exists( path ) )
1190 {
1191 QgsMessageLog::logMessage( tr( "Error loading raster attribute table, file not found: %1." ).arg( path ), tr( "Raster" ) );
1192 continue;
1193 }
1194
1195 std::unique_ptr<QgsRasterAttributeTable> rat = std::make_unique<QgsRasterAttributeTable>();
1196 QString errorMessage;
1197 if ( ! rat->readFromFile( path, &errorMessage ) )
1198 {
1199 QgsMessageLog::logMessage( tr( "Error loading raster attribute table from path %1: %2" ).arg( path, errorMessage ), tr( "Raster" ) );
1200 continue;
1201 }
1202
1203 // All good, set the RAT
1204 mDataProvider->setAttributeTable( band, rat.release() );
1205 }
1206 }
1207 }
1208}
1209
1210void QgsRasterLayer::closeDataProvider()
1211{
1213
1214 setValid( false );
1215 mPipe->remove( mDataProvider );
1216 mDataProvider = nullptr;
1217}
1218
1220 const QgsRasterMinMaxOrigin &mmo,
1222 const QgsRectangle &extent,
1223 int sampleSize,
1224 double &min, double &max )
1225{
1227
1228 min = std::numeric_limits<double>::quiet_NaN();
1229 max = std::numeric_limits<double>::quiet_NaN();
1230 if ( !mDataProvider )
1231 return;
1232
1234 {
1235 QgsRasterBandStats myRasterBandStats = mDataProvider->bandStatistics( band, Qgis::RasterBandStatistic::Min | Qgis::RasterBandStatistic::Max, extent, sampleSize );
1236 // Check if statistics were actually gathered, None means a failure
1237 if ( myRasterBandStats.statsGathered == static_cast< int >( Qgis::RasterBandStatistic::NoStatistic ) )
1238 {
1239 // Best guess we can do
1240 switch ( mDataProvider->dataType( band ) )
1241 {
1243 {
1244 myRasterBandStats.minimumValue = 0;
1245 myRasterBandStats.maximumValue = 255;
1246 break;
1247 }
1249 {
1250 myRasterBandStats.minimumValue = std::numeric_limits<int8_t>::lowest();
1251 myRasterBandStats.maximumValue = std::numeric_limits<int8_t>::max();
1252 break;
1253 }
1255 {
1256 myRasterBandStats.minimumValue = 0;
1257 myRasterBandStats.maximumValue = std::numeric_limits<uint16_t>::max();
1258 break;
1259 }
1261 {
1262 myRasterBandStats.minimumValue = 0;
1263 myRasterBandStats.maximumValue = std::numeric_limits<uint32_t>::max();
1264 break;
1265 }
1268 {
1269 myRasterBandStats.minimumValue = std::numeric_limits<int16_t>::lowest();
1270 myRasterBandStats.maximumValue = std::numeric_limits<int16_t>::max();
1271 break;
1272 }
1275 {
1276 myRasterBandStats.minimumValue = std::numeric_limits<int32_t>::lowest();
1277 myRasterBandStats.maximumValue = std::numeric_limits<int32_t>::max();
1278 break;
1279 }
1282 {
1283 myRasterBandStats.minimumValue = std::numeric_limits<float_t>::lowest();
1284 myRasterBandStats.maximumValue = std::numeric_limits<float_t>::max();
1285 break;
1286 }
1289 {
1290 myRasterBandStats.minimumValue = std::numeric_limits<double_t>::lowest();
1291 myRasterBandStats.maximumValue = std::numeric_limits<double_t>::max();
1292 break;
1293 }
1297 {
1298 // Nothing to guess
1299 break;
1300 }
1301 }
1302 }
1303 min = myRasterBandStats.minimumValue;
1304 max = myRasterBandStats.maximumValue;
1305 }
1306 else if ( limits == Qgis::RasterRangeLimit::StdDev )
1307 {
1308 const QgsRasterBandStats myRasterBandStats = mDataProvider->bandStatistics( band, Qgis::RasterBandStatistic::Mean | Qgis::RasterBandStatistic::StdDev, extent, sampleSize );
1309 min = myRasterBandStats.mean - ( mmo.stdDevFactor() * myRasterBandStats.stdDev );
1310 max = myRasterBandStats.mean + ( mmo.stdDevFactor() * myRasterBandStats.stdDev );
1311 }
1312 else if ( limits == Qgis::RasterRangeLimit::CumulativeCut )
1313 {
1314 const double myLower = mmo.cumulativeCutLower();
1315 const double myUpper = mmo.cumulativeCutUpper();
1316 QgsDebugMsgLevel( QStringLiteral( "myLower = %1 myUpper = %2" ).arg( myLower ).arg( myUpper ), 4 );
1317 mDataProvider->cumulativeCut( band, myLower, myUpper, min, max, extent, sampleSize );
1318 }
1319 QgsDebugMsgLevel( QStringLiteral( "band = %1 min = %2 max = %3" ).arg( band ).arg( min ).arg( max ), 4 );
1320
1321}
1322
1324{
1326
1327 return mDataProvider ? mDataProvider->ignoreExtents() : false;
1328}
1329
1336
1343
1345{
1347
1349 limits,
1350 extent,
1351 sampleSize,
1352 generateLookupTableFlag,
1353 mPipe->renderer() );
1354}
1355
1358 const QgsRectangle &extent,
1359 int sampleSize,
1360 bool generateLookupTableFlag,
1361 QgsRasterRenderer *rasterRenderer )
1362{
1364
1365 QgsDebugMsgLevel( QStringLiteral( "theAlgorithm = %1 limits = %2 extent.isEmpty() = %3" ).arg( algorithm ).arg( qgsEnumValueToKey( limits ) ).arg( extent.isEmpty() ), 4 );
1366 if ( !rasterRenderer || !mDataProvider )
1367 {
1368 return;
1369 }
1370
1371 QList<int> myBands;
1372 QList<QgsContrastEnhancement *> myEnhancements;
1373 QgsRasterMinMaxOrigin myMinMaxOrigin;
1374 QgsRasterRenderer *myRasterRenderer = nullptr;
1375 QgsSingleBandGrayRenderer *myGrayRenderer = nullptr;
1376 QgsSingleBandPseudoColorRenderer *myPseudoColorRenderer = nullptr;
1377 QgsMultiBandColorRenderer *myMultiBandRenderer = nullptr;
1378 const QString rendererType = rasterRenderer->type();
1379 if ( rendererType == QLatin1String( "singlebandgray" ) )
1380 {
1381 myGrayRenderer = dynamic_cast<QgsSingleBandGrayRenderer *>( rasterRenderer );
1382 if ( !myGrayRenderer )
1383 {
1384 return;
1385 }
1386 myBands << myGrayRenderer->inputBand();
1387 myRasterRenderer = myGrayRenderer;
1388 myMinMaxOrigin = myGrayRenderer->minMaxOrigin();
1389 }
1390 else if ( rendererType == QLatin1String( "multibandcolor" ) )
1391 {
1392 myMultiBandRenderer = dynamic_cast<QgsMultiBandColorRenderer *>( rasterRenderer );
1393 if ( !myMultiBandRenderer )
1394 {
1395 return;
1396 }
1397 myBands << myMultiBandRenderer->redBand() << myMultiBandRenderer->greenBand() << myMultiBandRenderer->blueBand();
1398 myRasterRenderer = myMultiBandRenderer;
1399 myMinMaxOrigin = myMultiBandRenderer->minMaxOrigin();
1400 }
1401 else if ( rendererType == QLatin1String( "singlebandpseudocolor" ) )
1402 {
1403 myPseudoColorRenderer = dynamic_cast<QgsSingleBandPseudoColorRenderer *>( rasterRenderer );
1404 if ( !myPseudoColorRenderer )
1405 {
1406 return;
1407 }
1408 myBands << myPseudoColorRenderer->inputBand();
1409 myRasterRenderer = myPseudoColorRenderer;
1410 myMinMaxOrigin = myPseudoColorRenderer->minMaxOrigin();
1411 }
1412 else
1413 {
1414 return;
1415 }
1416
1417 for ( const int myBand : std::as_const( myBands ) )
1418 {
1419 if ( myBand != -1 )
1420 {
1421 const Qgis::DataType myType = static_cast< Qgis::DataType >( mDataProvider->dataType( myBand ) );
1422 std::unique_ptr<QgsContrastEnhancement> myEnhancement( new QgsContrastEnhancement( static_cast< Qgis::DataType >( myType ) ) );
1423 myEnhancement->setContrastEnhancementAlgorithm( algorithm, generateLookupTableFlag );
1424
1425 double min;
1426 double max;
1427 computeMinMax( myBand, myMinMaxOrigin, limits, extent, sampleSize, min, max );
1428
1429 if ( rendererType == QLatin1String( "singlebandpseudocolor" ) )
1430 {
1431 // This is not necessary, but clang-tidy thinks it is.
1432 if ( ! myPseudoColorRenderer )
1433 {
1434 return;
1435 }
1436 // Do not overwrite min/max with NaN if they were already set,
1437 // for example when the style was already loaded from a raster attribute table
1438 // in that case we need to respect the style from the attribute table and do
1439 // not perform any reclassification.
1440 bool minMaxChanged { false };
1441 if ( ! std::isnan( min ) )
1442 {
1443 myPseudoColorRenderer->setClassificationMin( min );
1444 minMaxChanged = true;
1445 }
1446
1447 if ( ! std::isnan( max ) )
1448 {
1449 myPseudoColorRenderer->setClassificationMax( max );
1450 minMaxChanged = true;
1451 }
1452
1453 if ( minMaxChanged && myPseudoColorRenderer->shader() )
1454 {
1455 QgsColorRampShader *colorRampShader = dynamic_cast<QgsColorRampShader *>( myPseudoColorRenderer->shader()->rasterShaderFunction() );
1456 if ( colorRampShader )
1457 {
1458 colorRampShader->classifyColorRamp( myPseudoColorRenderer->inputBand(), extent, myPseudoColorRenderer->input() );
1459 }
1460 }
1461 }
1462 else
1463 {
1464 myEnhancement->setMinimumValue( min );
1465 myEnhancement->setMaximumValue( max );
1466 myEnhancements.append( myEnhancement.release() );
1467 }
1468 }
1469 else
1470 {
1471 myEnhancements.append( nullptr );
1472 }
1473 }
1474
1475 // Again, second check is redundant but clang-tidy doesn't agree
1476 if ( rendererType == QLatin1String( "singlebandgray" ) && myGrayRenderer )
1477 {
1478 if ( myEnhancements.first() ) myGrayRenderer->setContrastEnhancement( myEnhancements.takeFirst() );
1479 }
1480 else if ( rendererType == QLatin1String( "multibandcolor" ) && myMultiBandRenderer )
1481 {
1482 if ( myEnhancements.first() ) myMultiBandRenderer->setRedContrastEnhancement( myEnhancements.takeFirst() );
1483 if ( myEnhancements.first() ) myMultiBandRenderer->setGreenContrastEnhancement( myEnhancements.takeFirst() );
1484 if ( myEnhancements.first() ) myMultiBandRenderer->setBlueContrastEnhancement( myEnhancements.takeFirst() );
1485 }
1486
1487 //delete all remaining unused enhancements
1488 qDeleteAll( myEnhancements );
1489
1490 myMinMaxOrigin.setLimits( limits );
1491 if ( extent != QgsRectangle() &&
1492 myMinMaxOrigin.extent() == Qgis::RasterRangeExtent::WholeRaster )
1493 {
1495 }
1496 if ( myRasterRenderer )
1497 {
1498 myRasterRenderer->setMinMaxOrigin( myMinMaxOrigin );
1499 }
1500
1501 if ( rasterRenderer == renderer() )
1502 {
1503 emit repaintRequested();
1505 emit rendererChanged();
1506 }
1507}
1508
1510{
1512
1513 QgsSingleBandGrayRenderer *singleBandRenderer = nullptr;
1514 QgsMultiBandColorRenderer *multiBandRenderer = nullptr;
1515 const QgsContrastEnhancement *ce = nullptr;
1516 if ( ( singleBandRenderer = dynamic_cast<QgsSingleBandGrayRenderer *>( renderer() ) ) )
1517 {
1518 ce = singleBandRenderer->contrastEnhancement();
1519 }
1520 else if ( ( multiBandRenderer = dynamic_cast<QgsMultiBandColorRenderer *>( renderer() ) ) )
1521 {
1522 ce = multiBandRenderer->redContrastEnhancement();
1523 }
1524
1525 if ( ce )
1526 {
1531 extent,
1532 static_cast<int>( SAMPLE_SIZE ),
1533 true,
1534 renderer() );
1535 }
1536 else
1537 {
1539 Qgis::RasterRangeLimit myLimits;
1540 if ( defaultContrastEnhancementSettings( myAlgorithm, myLimits ) )
1541 {
1543 myLimits,
1544 extent,
1545 static_cast<int>( SAMPLE_SIZE ),
1546 true,
1547 renderer() );
1548 }
1549 }
1550}
1551
1553{
1555
1556 if ( !isValid() || !mDataProvider )
1557 {
1558 QgsDebugMsgLevel( QStringLiteral( "invoked with invalid layer or null mDataProvider" ), 3 );
1559 return customProperty( QStringLiteral( "storedSubsetString" ) ).toString();
1560 }
1561 if ( !mDataProvider->supportsSubsetString() )
1562 {
1563 return QString();
1564 }
1565 return mDataProvider->subsetString();
1566}
1567
1568bool QgsRasterLayer::setSubsetString( const QString &subset )
1569{
1571
1572 if ( !isValid() || !mDataProvider )
1573 {
1574 QgsDebugMsgLevel( QStringLiteral( "invoked with invalid layer or null mDataProvider or while editing" ), 3 );
1575 setCustomProperty( QStringLiteral( "storedSubsetString" ), subset );
1576 return false;
1577 }
1578
1579 if ( !mDataProvider->supportsSubsetString() )
1580 {
1581 return false;
1582 }
1583
1584 if ( subset == mDataProvider->subsetString() )
1585 return true;
1586
1587 const bool res = mDataProvider->setSubsetString( subset );
1588
1589 // get the updated data source string from the provider
1590 mDataSource = mDataProvider->dataSourceUri();
1591
1592 if ( res )
1593 {
1594 setExtent( mDataProvider->extent() );
1595 QList<double> minValues;
1596 QList<double> maxValues;
1597 const QgsRasterMinMaxOrigin &minMaxOrigin = renderer()->minMaxOrigin();
1598 for ( const int bandIdx : renderer()->usesBands() )
1599 {
1600 double min;
1601 double max;
1602
1603 computeMinMax( bandIdx, minMaxOrigin, minMaxOrigin.limits(),
1604 extent(), static_cast<int>( QgsRasterLayer::SAMPLE_SIZE ),
1605 min, max );
1606 minValues.append( min );
1607 maxValues.append( max );
1608 }
1609 renderer()->refresh( extent(), minValues, maxValues, true );
1610 emit subsetStringChanged();
1611 }
1612
1613 return res;
1614}
1615
1618 Qgis::RasterRangeLimit &myLimits ) const
1619{
1621
1622 const QgsSettings mySettings;
1623
1624 QString key;
1625 QString defaultAlg;
1626 QString defaultLimits;
1627
1628 // TODO: we should not test renderer class here, move it somehow to renderers
1629 if ( dynamic_cast<QgsSingleBandGrayRenderer *>( renderer() ) )
1630 {
1631 key = QStringLiteral( "singleBand" );
1636 }
1637 else if ( dynamic_cast<QgsMultiBandColorRenderer *>( renderer() ) )
1638 {
1639 if ( QgsRasterBlock::typeSize( dataProvider()->sourceDataType( 1 ) ) == 1 )
1640 {
1641 key = QStringLiteral( "multiBandSingleByte" );
1646 }
1647 else
1648 {
1649 key = QStringLiteral( "multiBandMultiByte" );
1654 }
1655 }
1656
1657 if ( key.isEmpty() )
1658 {
1659 QgsDebugMsgLevel( QStringLiteral( "No default contrast enhancement for this drawing style" ), 2 );
1661 myLimits = QgsRasterMinMaxOrigin::limitsFromString( QString() );
1662 return false;
1663 }
1664 QgsDebugMsgLevel( "key = " + key, 4 );
1665
1666 const QString myAlgorithmString = mySettings.value( "/Raster/defaultContrastEnhancementAlgorithm/" + key, defaultAlg ).toString();
1667 QgsDebugMsgLevel( "myAlgorithmString = " + myAlgorithmString, 4 );
1668
1669 myAlgorithm = QgsContrastEnhancement::contrastEnhancementAlgorithmFromString( myAlgorithmString );
1670
1671 const QString myLimitsString = mySettings.value( "/Raster/defaultContrastEnhancementLimits/" + key, defaultLimits ).toString();
1672 QgsDebugMsgLevel( "myLimitsString = " + myLimitsString, 4 );
1673 myLimits = QgsRasterMinMaxOrigin::limitsFromString( myLimitsString );
1674
1675 return true;
1676}
1677
1679{
1681
1682 QgsDebugMsgLevel( QStringLiteral( "Entered" ), 4 );
1683
1685 Qgis::RasterRangeLimit myLimits;
1686 defaultContrastEnhancementSettings( myAlgorithm, myLimits );
1687
1688 setContrastEnhancement( myAlgorithm, myLimits );
1689}
1690
1691void QgsRasterLayer::setLayerOrder( QStringList const &layers )
1692{
1694
1695 QgsDebugMsgLevel( QStringLiteral( "entered." ), 4 );
1696
1697 if ( mDataProvider )
1698 {
1699 QgsDebugMsgLevel( QStringLiteral( "About to mDataProvider->setLayerOrder(layers)." ), 4 );
1700 mDataProvider->setLayerOrder( layers );
1701 }
1702
1703}
1704
1705void QgsRasterLayer::setSubLayerVisibility( const QString &name, bool vis )
1706{
1708
1709 if ( mDataProvider )
1710 {
1711 QgsDebugMsgLevel( QStringLiteral( "About to mDataProvider->setSubLayerVisibility(name, vis)." ), 4 );
1712 mDataProvider->setSubLayerVisibility( name, vis );
1713 }
1714}
1715
1717{
1719
1720 if ( !mDataProvider )
1721 return QDateTime();
1722 return mDataProvider->timestamp();
1723}
1724
1726{
1728
1729 if ( auto *lRenderer = mPipe->renderer() )
1730 {
1731 if ( !lRenderer->accept( visitor ) )
1732 return false;
1733 }
1734 return true;
1735}
1736
1738{
1740
1741 return mLabelsEnabled && static_cast< bool >( mLabeling );
1742}
1743
1745{
1747
1748 mLabelsEnabled = enabled;
1749}
1750
1752{
1754
1755 return mLabeling.get();
1756}
1757
1764
1766{
1768
1769 if ( mLabeling.get() == labeling )
1770 return;
1771
1772 mLabeling.reset( labeling );
1774}
1775
1776bool QgsRasterLayer::writeSld( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QVariantMap &props ) const
1777{
1779
1780 Q_UNUSED( errorMessage )
1781
1782 QVariantMap localProps = QVariantMap( props );
1784 {
1785 // TODO: QgsSymbolLayerUtils::mergeScaleDependencies generate SE only and not SLD1.0
1787 }
1788
1789 if ( isSpatial() ) // TODO: does it make sense this control?
1790 {
1791 // store constraints
1792 QDomElement constraintElem = doc.createElement( QStringLiteral( "sld:LayerFeatureConstraints" ) );
1793 node.appendChild( constraintElem );
1794
1795 const QDomElement featureTypeConstraintElem = doc.createElement( QStringLiteral( "sld:FeatureTypeConstraint" ) );
1796 constraintElem.appendChild( featureTypeConstraintElem );
1797
1798 QDomElement userStyleElem = doc.createElement( QStringLiteral( "sld:UserStyle" ) );
1799 node.appendChild( userStyleElem );
1800
1801 if ( !name().isEmpty() )
1802 {
1803 QDomElement nameElem = doc.createElement( QStringLiteral( "sld:Name" ) );
1804 nameElem.appendChild( doc.createTextNode( name() ) );
1805 userStyleElem.appendChild( nameElem );
1806 }
1807
1808 const QString abstract = !metadata().abstract().isEmpty() ? metadata().abstract() : serverProperties()->abstract();
1809 if ( !abstract.isEmpty() )
1810 {
1811 QDomElement abstractElem = doc.createElement( QStringLiteral( "sld:Abstract" ) );
1812 abstractElem.appendChild( doc.createTextNode( abstract ) );
1813 userStyleElem.appendChild( abstractElem );
1814 }
1815
1816 const QString title = !metadata().title().isEmpty() ? metadata().title() : serverProperties()->title();
1817 if ( !title.isEmpty() )
1818 {
1819 QDomElement titleElem = doc.createElement( QStringLiteral( "sld:Title" ) );
1820 titleElem.appendChild( doc.createTextNode( title ) );
1821 userStyleElem.appendChild( titleElem );
1822 }
1823
1824 QDomElement featureTypeStyleElem = doc.createElement( QStringLiteral( "sld:FeatureTypeStyle" ) );
1825 userStyleElem.appendChild( featureTypeStyleElem );
1826
1827#if 0
1828 // TODO: Is there a way to fill it's value with the named style?
1829 // by default <sld:Name> under <sld:FeatureTypeStyle> can have 0 occurrences
1830 // the same happen for tags:
1831 // sld:Title
1832 // sld:Abstract
1833 // sld:FeatureTypeName
1834 // sld:SemanticTypeIdentifier
1835 QDomElement typeStyleNameElem = doc.createElement( QStringLiteral( "sld:Name" ) );
1836 featureTypeStyleElem.appendChild( typeStyleNameElem );
1837#endif
1838
1839 QDomElement typeStyleRuleElem = doc.createElement( QStringLiteral( "sld:Rule" ) );
1840 featureTypeStyleElem.appendChild( typeStyleRuleElem );
1841
1842 // add ScaleDenominator tags
1844 {
1845 // note that denominator is the inverted value of scale
1846 if ( maximumScale() != 0.0 )
1847 {
1848 QDomElement minScaleElem = doc.createElement( QStringLiteral( "sld:MinScaleDenominator" ) );
1849 minScaleElem.appendChild( doc.createTextNode( QString::number( maximumScale() ) ) );
1850 typeStyleRuleElem.appendChild( minScaleElem );
1851 }
1852
1853 QDomElement maxScaleElem = doc.createElement( QStringLiteral( "sld:MaxScaleDenominator" ) );
1854 maxScaleElem.appendChild( doc.createTextNode( QString::number( minimumScale() ) ) );
1855 typeStyleRuleElem.appendChild( maxScaleElem );
1856 }
1857
1858 // export renderer dependent tags
1859 mPipe->renderer()->toSld( doc, typeStyleRuleElem, localProps );
1860
1861 // inject raster layer parameters in RasterSymbolizer tag because
1862 // they belongs to rasterlayer and not to the renderer => avoid to
1863 // pass many parameters value via localProps
1864 const QDomNodeList elements = typeStyleRuleElem.elementsByTagName( QStringLiteral( "sld:RasterSymbolizer" ) );
1865 if ( elements.size() != 0 )
1866 {
1867 // there SHOULD be only one
1868 QDomElement rasterSymbolizerElem = elements.at( 0 ).toElement();
1869
1870 // lamda helper used below to reduce code redundancy
1871 auto vendorOptionWriter = [&]( QString name, QString value )
1872 {
1873 QDomElement vendorOptionElem = doc.createElement( QStringLiteral( "sld:VendorOption" ) );
1874 vendorOptionElem.setAttribute( QStringLiteral( "name" ), name );
1875 vendorOptionElem.appendChild( doc.createTextNode( value ) );
1876 rasterSymbolizerElem.appendChild( vendorOptionElem );
1877 };
1878
1880 {
1881 vendorOptionWriter( QStringLiteral( "invertColors" ), QString::number( 1 ) );
1882 }
1883
1884 // add greyScale rendering mode if set
1886 {
1887 QString property;
1888 switch ( hueSaturationFilter()->grayscaleMode() )
1889 {
1891 property = QStringLiteral( "lightness" );
1892 break;
1894 property = QStringLiteral( "luminosity" );
1895 break;
1897 property = QStringLiteral( "average" );
1898 break;
1900 // added just to avoid travis fail
1901 break;
1902 }
1903 if ( !property.isEmpty() )
1904 vendorOptionWriter( QStringLiteral( "grayScale" ), property );
1905 }
1906
1907 // add Hue, Saturation and Lighting values in props is Hue filter is set
1908 if ( hueSaturationFilter() && hueSaturationFilter()->colorizeOn() )
1909 {
1910 vendorOptionWriter( QStringLiteral( "colorizeOn" ), QString::number( hueSaturationFilter()->colorizeOn() ) );
1911 vendorOptionWriter( QStringLiteral( "colorizeRed" ), QString::number( hueSaturationFilter()->colorizeColor().red() ) );
1912 vendorOptionWriter( QStringLiteral( "colorizeGreen" ), QString::number( hueSaturationFilter()->colorizeColor().green() ) );
1913 vendorOptionWriter( QStringLiteral( "colorizeBlue" ), QString::number( hueSaturationFilter()->colorizeColor().blue() ) );
1914 if ( hueSaturationFilter()->colorizeStrength() != 100.0 )
1915 vendorOptionWriter( QStringLiteral( "colorizeStrength" ), QString::number( hueSaturationFilter()->colorizeStrength() / 100.0 ) );
1916 vendorOptionWriter( QStringLiteral( "saturation" ), QString::number( hueSaturationFilter()->colorizeColor().saturationF() ) );
1917 }
1918 else
1919 {
1920 // saturation != 0 (default value)
1921 if ( hueSaturationFilter()->saturation() != 0 )
1922 {
1923 // normlize value [-100:100] -> [0:1]
1924 const int s = hueSaturationFilter()->saturation();
1925 const double sF = ( s - ( -100.0 ) ) / ( 100.0 - ( -100.0 ) );
1926 vendorOptionWriter( QStringLiteral( "saturation" ), QString::number( sF ) );
1927 }
1928 }
1929
1930 // brightness != 0 (default value)
1931 if ( brightnessFilter()->brightness() != 0 )
1932 {
1933 // normalize value [-255:255] -> [0:1]
1934 const int b = brightnessFilter()->brightness();
1935 const double bF = ( b - ( -255.0 ) ) / ( 255.0 - ( -255.0 ) );
1936 vendorOptionWriter( QStringLiteral( "brightness" ), QString::number( bF ) );
1937 }
1938
1939 // contrast != 0 (default value)
1940 if ( brightnessFilter()->contrast() != 0 )
1941 {
1942 // normlize value [-100:100] -> [0:1]
1943 const int c = brightnessFilter()->contrast();
1944 const double cF = ( c - ( -100.0 ) ) / ( 100.0 - ( -100.0 ) );
1945 vendorOptionWriter( QStringLiteral( "contrast" ), QString::number( cF ) );
1946 }
1947
1948#if 0
1949 // TODO: check if the below mapping formula make sense to map QGIS contrast with SLD gamma value
1950 //
1951 // add SLD1.0 ContrastEnhancement GammaValue = QGIS Contrast
1952 // SLD1.0 does only define 1 as neutral/center double value but does not define range.
1953 // because https://en.wikipedia.org/wiki/Gamma_correction assumed gamma is >0.
1954 // whilst QGIS has a -100/100 values centered in 0 => QGIS contrast value will be scaled in the
1955 // following way:
1956 // [-100,0] => [0,1] and [0,100] => [1,100]
1957 // an alternative could be scale [-100,100] => (0,2]
1958 //
1959 if ( newProps.contains( QStringLiteral( "contrast" ) ) )
1960 {
1961 double gamma;
1962 double contrast = newProps[ QStringLiteral( "contrast" ) ].toDouble();
1963 double percentage = ( contrast - ( -100.0 ) ) / ( 100.0 - ( -100.0 ) );
1964 if ( percentage <= 0.5 )
1965 {
1966 // stretch % to [0-1]
1967 gamma = percentage / 0.5;
1968 }
1969 else
1970 {
1971 gamma = contrast;
1972 }
1973
1974 QDomElement globalContrastEnhancementElem = doc.createElement( QStringLiteral( "sld:ContrastEnhancement" ) );
1975 rasterSymolizerElem.appendChild( globalContrastEnhancementElem );
1976
1977 QDomElement gammaValueElem = doc.createElement( QStringLiteral( "sld:GammaValue" ) );
1978 gammaValueElem.appendChild( doc.createTextNode( QString::number( gamma ) ) );
1979 globalContrastEnhancementElem.appendChild( gammaValueElem );
1980 }
1981#endif
1982 }
1983 }
1984 return true;
1985}
1986
1988{
1990
1991 QgsDebugMsgLevel( QStringLiteral( "Entered" ), 4 );
1992 if ( !renderer )
1993 {
1994 return;
1995 }
1996
1997 mPipe->set( renderer );
1998 emit rendererChanged();
2000}
2001
2003{
2005
2006 return mPipe->renderer();
2007}
2008
2010{
2012
2013 return mPipe->resampleFilter();
2014}
2015
2017{
2019
2020 return mPipe->brightnessFilter();
2021}
2022
2024{
2026
2027 return mPipe->hueSaturationFilter();
2028}
2029
2030void QgsRasterLayer::showStatusMessage( QString const &message )
2031{
2033
2034 // QgsDebugMsgLevel(QString("entered with '%1'.").arg(theMessage), 2);
2035
2036 // Pass-through
2037 // TODO: See if we can connect signal-to-signal. This is a kludge according to the Qt doc.
2038 emit statusChanged( message );
2039}
2040
2042{
2044
2045 if ( mDataProvider )
2046 mDataProvider->setTransformContext( transformContext );
2048}
2049
2050QStringList QgsRasterLayer::subLayers() const
2051{
2053
2054 if ( ! mDataProvider )
2055 return QStringList();
2056 return mDataProvider->subLayers();
2057}
2058
2059// this function should be used when rendering with the MTR engine introduced in 2.3, as QPixmap is not thread safe (see bug #9626)
2060// note: previewAsImage and previewAsPixmap should use a common low-level fct QgsRasterLayer::previewOnPaintDevice( QSize size, QColor bgColor, QPaintDevice &device )
2061QImage QgsRasterLayer::previewAsImage( QSize size, const QColor &bgColor, QImage::Format format )
2062{
2064
2065 QImage image( size, format );
2066
2067 if ( ! isValid( ) )
2068 return QImage();
2069
2070 if ( image.format() == QImage::Format_Indexed8 )
2071 {
2072 image.setColor( 0, bgColor.rgba() );
2073 image.fill( 0 ); //defaults to white, set to transparent for rendering on a map
2074 }
2075 else
2076 {
2077 image.fill( bgColor );
2078 }
2079
2080 QgsRasterViewPort *rasterViewPort = new QgsRasterViewPort();
2081
2082 double mapUnitsPerPixel;
2083 double x = 0.0;
2084 double y = 0.0;
2085 const QgsRectangle extent = mDataProvider->extent();
2086 if ( extent.width() / extent.height() >= static_cast< double >( image.width() ) / image.height() )
2087 {
2088 mapUnitsPerPixel = extent.width() / image.width();
2089 y = ( image.height() - extent.height() / mapUnitsPerPixel ) / 2;
2090 }
2091 else
2092 {
2093 mapUnitsPerPixel = extent.height() / image.height();
2094 x = ( image.width() - extent.width() / mapUnitsPerPixel ) / 2;
2095 }
2096
2097 const double pixelWidth = extent.width() / mapUnitsPerPixel;
2098 const double pixelHeight = extent.height() / mapUnitsPerPixel;
2099
2100 rasterViewPort->mTopLeftPoint = QgsPointXY( x, y );
2101 rasterViewPort->mBottomRightPoint = QgsPointXY( pixelWidth, pixelHeight );
2102 rasterViewPort->mWidth = image.width();
2103 rasterViewPort->mHeight = image.height();
2104
2105 rasterViewPort->mDrawnExtent = extent;
2106 rasterViewPort->mSrcCRS = QgsCoordinateReferenceSystem(); // will be invalid
2107 rasterViewPort->mDestCRS = QgsCoordinateReferenceSystem(); // will be invalid
2108
2109 QgsMapToPixel *mapToPixel = new QgsMapToPixel( mapUnitsPerPixel );
2110
2111 QPainter *painter = new QPainter( &image );
2112 draw( painter, rasterViewPort, mapToPixel );
2113 delete rasterViewPort;
2114 delete mapToPixel;
2115
2116 painter->end();
2117 delete painter;
2118
2119 return image;
2120}
2121
2122bool QgsRasterLayer::readSymbology( const QDomNode &layer_node, QString &errorMessage,
2124{
2126
2127 Q_UNUSED( errorMessage )
2128 // TODO: implement categories for raster layer
2129
2130 QDomElement rasterRendererElem;
2131
2132 const QDomElement layerElement = layer_node.toElement();
2133 readCommonStyle( layerElement, context, categories );
2134
2135 // pipe considers Symbology and Rendering components, why it's always handled as one
2136 if ( categories.testFlag( Symbology ) || categories.testFlag( Rendering ) )
2137 {
2138 // pipe element was introduced in the end of 1.9 development when there were
2139 // already many project files in use so we support 1.9 backward compatibility
2140 // even it was never officially released -> use pipe element if present, otherwise
2141 // use layer node
2142 QDomNode pipeNode = layer_node.firstChildElement( QStringLiteral( "pipe" ) );
2143 if ( pipeNode.isNull() ) // old project
2144 {
2145 pipeNode = layer_node;
2146 }
2147
2148 //rasterlayerproperties element there -> old format (1.8 and early 1.9)
2149 if ( !layer_node.firstChildElement( QStringLiteral( "rasterproperties" ) ).isNull() )
2150 {
2151 //copy node because layer_node is const
2152 QDomNode layerNodeCopy = layer_node.cloneNode();
2153 QDomDocument doc = layerNodeCopy.ownerDocument();
2154 QDomElement rasterPropertiesElem = layerNodeCopy.firstChildElement( QStringLiteral( "rasterproperties" ) );
2155 QgsProjectFileTransform::convertRasterProperties( doc, layerNodeCopy, rasterPropertiesElem,
2156 this );
2157 rasterRendererElem = layerNodeCopy.firstChildElement( QStringLiteral( "rasterrenderer" ) );
2158 QgsDebugMsgLevel( doc.toString(), 4 );
2159 }
2160 else
2161 {
2162 rasterRendererElem = pipeNode.firstChildElement( QStringLiteral( "rasterrenderer" ) );
2163 }
2164
2165 if ( !rasterRendererElem.isNull() )
2166 {
2167 const QString rendererType = rasterRendererElem.attribute( QStringLiteral( "type" ) );
2168 QgsRasterRendererRegistryEntry rendererEntry;
2169 if ( mDataProvider && QgsApplication::rasterRendererRegistry()->rendererData( rendererType, rendererEntry ) )
2170 {
2171 QgsRasterRenderer *renderer = rendererEntry.rendererCreateFunction( rasterRendererElem, mDataProvider );
2172 mPipe->set( renderer );
2173 }
2174 }
2175
2176 //brightness
2178 mPipe->set( brightnessFilter );
2179
2180 //brightness coefficient
2181 const QDomElement brightnessElem = pipeNode.firstChildElement( QStringLiteral( "brightnesscontrast" ) );
2182 if ( !brightnessElem.isNull() )
2183 {
2184 brightnessFilter->readXml( brightnessElem );
2185 }
2186
2187 //hue/saturation
2189 mPipe->set( hueSaturationFilter );
2190
2191 //saturation coefficient
2192 const QDomElement hueSaturationElem = pipeNode.firstChildElement( QStringLiteral( "huesaturation" ) );
2193 if ( !hueSaturationElem.isNull() )
2194 {
2195 hueSaturationFilter->readXml( hueSaturationElem );
2196 }
2197
2198 //resampler
2200 mPipe->set( resampleFilter );
2201
2202 //max oversampling
2203 const QDomElement resampleElem = pipeNode.firstChildElement( QStringLiteral( "rasterresampler" ) );
2204 if ( !resampleElem.isNull() )
2205 {
2206 resampleFilter->readXml( resampleElem );
2207 }
2208
2209 //provider
2210 if ( mDataProvider )
2211 {
2212 const QDomElement providerElem = pipeNode.firstChildElement( QStringLiteral( "provider" ) );
2213 if ( !providerElem.isNull() )
2214 {
2215 mDataProvider->readXml( providerElem );
2216 }
2217 }
2218
2219 // Resampling stage
2220 const QDomNode resamplingStageElement = pipeNode.namedItem( QStringLiteral( "resamplingStage" ) );
2221 if ( !resamplingStageElement.isNull() )
2222 {
2223 const QDomElement e = resamplingStageElement.toElement();
2224 if ( e.text() == QLatin1String( "provider" ) )
2226 else if ( e.text() == QLatin1String( "resamplingFilter" ) )
2228 }
2229
2230 // get and set the blend mode if it exists
2231 const QDomNode blendModeNode = layer_node.namedItem( QStringLiteral( "blendMode" ) );
2232 if ( !blendModeNode.isNull() )
2233 {
2234 const QDomElement e = blendModeNode.toElement();
2235 setBlendMode( QgsPainting::getCompositionMode( static_cast< Qgis::BlendMode >( e.text().toInt() ) ) );
2236 }
2237
2238 const QDomElement elemDataDefinedProperties = layer_node.firstChildElement( QStringLiteral( "pipe-data-defined-properties" ) );
2239 if ( !elemDataDefinedProperties.isNull() )
2240 mPipe->dataDefinedProperties().readXml( elemDataDefinedProperties, QgsRasterPipe::propertyDefinitions() );
2241 }
2242
2243 // read labeling definition
2244 if ( categories.testFlag( Labeling ) )
2245 {
2246 QgsReadWriteContextCategoryPopper p = context.enterCategory( tr( "Labeling" ) );
2247
2248 QDomElement labelingElement = layer_node.firstChildElement( QStringLiteral( "labeling" ) );
2249 if ( !labelingElement.isNull() )
2250 {
2252 mLabelsEnabled = layer_node.toElement().attribute( QStringLiteral( "labelsEnabled" ), QStringLiteral( "0" ) ).toInt();
2254 }
2255 }
2256
2257 if ( categories.testFlag( MapTips ) )
2258 {
2259 QDomElement mapTipElem = layer_node.namedItem( QStringLiteral( "mapTip" ) ).toElement();
2260 setMapTipTemplate( mapTipElem.text() );
2261 setMapTipsEnabled( mapTipElem.attribute( QStringLiteral( "enabled" ), QStringLiteral( "1" ) ).toInt() == 1 );
2262 }
2263
2264 // read attribute table attribute table paths
2265 if ( categories.testFlag( AttributeTable ) )
2266 {
2267 readRasterAttributeTableExternalPaths( layer_node, context );
2268 }
2269
2270 emit rendererChanged();
2272
2273 return true;
2274}
2275
2276bool QgsRasterLayer::readStyle( const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories )
2277{
2279
2280 return readSymbology( node, errorMessage, context, categories );
2281}
2282
2283bool QgsRasterLayer::readXml( const QDomNode &layer_node, QgsReadWriteContext &context )
2284{
2286
2287 QgsDebugMsgLevel( QStringLiteral( "Entered" ), 4 );
2288 // Make sure to read the file first so stats etc are initialized properly!
2289
2290 //process provider key
2291 const QDomNode pkeyNode = layer_node.namedItem( QStringLiteral( "provider" ) );
2292
2293 if ( pkeyNode.isNull() )
2294 {
2295 mProviderKey = QStringLiteral( "gdal" );
2296 }
2297 else
2298 {
2299 const QDomElement pkeyElt = pkeyNode.toElement();
2300 mProviderKey = pkeyElt.text();
2301 if ( mProviderKey.isEmpty() )
2302 {
2303 mProviderKey = QStringLiteral( "gdal" );
2304 }
2305 }
2306
2307 // Open the raster source based on provider and datasource
2308
2309 // Go down the raster-data-provider paradigm
2310
2311 // Collect provider-specific information
2312
2313 const QDomNode rpNode = layer_node.namedItem( QStringLiteral( "rasterproperties" ) );
2314
2315 if ( mProviderKey == QLatin1String( "wms" ) )
2316 {
2317 // >>> BACKWARD COMPATIBILITY < 1.9
2318 // The old WMS URI format does not contain all the information, we add them here.
2319 if ( !mDataSource.contains( QLatin1String( "crs=" ) ) && !mDataSource.contains( QLatin1String( "format=" ) ) )
2320 {
2321 QgsDebugMsgLevel( QStringLiteral( "Old WMS URI format detected -> adding params" ), 4 );
2322 QgsDataSourceUri uri;
2324 QDomElement layerElement = rpNode.firstChildElement( QStringLiteral( "wmsSublayer" ) );
2325 while ( !layerElement.isNull() )
2326 {
2327 // TODO: sublayer visibility - post-0.8 release timeframe
2328
2329 // collect name for the sublayer
2330 uri.setParam( QStringLiteral( "layers" ), layerElement.namedItem( QStringLiteral( "name" ) ).toElement().text() );
2331
2332 // collect style for the sublayer
2333 uri.setParam( QStringLiteral( "styles" ), layerElement.namedItem( QStringLiteral( "style" ) ).toElement().text() );
2334
2335 layerElement = layerElement.nextSiblingElement( QStringLiteral( "wmsSublayer" ) );
2336 }
2337
2338 // Collect format
2339 uri.setParam( QStringLiteral( "format" ), rpNode.namedItem( QStringLiteral( "wmsFormat" ) ).toElement().text() );
2340
2341 // WMS CRS URL param should not be mixed with that assigned to the layer.
2342 // In the old WMS URI version there was no CRS and layer crs().authid() was used.
2343 uri.setParam( QStringLiteral( "crs" ), crs().authid() );
2344 mDataSource = uri.encodedUri();
2345 }
2346 // <<< BACKWARD COMPATIBILITY < 1.9
2347 }
2348
2350 {
2351 const QgsDataProvider::ProviderOptions providerOptions { context.transformContext() };
2353
2355 {
2356 const QDomNode extentNode = layer_node.namedItem( QStringLiteral( "extent" ) );
2357 if ( !extentNode.isNull() )
2358 {
2359 // get the extent
2360 const QgsRectangle mbr = QgsXmlUtils::readRectangle( extentNode.toElement() );
2361
2362 // store the extent
2363 setExtent( mbr );
2364 }
2365 }
2366 setDataProvider( mProviderKey, providerOptions, flags );
2367 }
2368
2369 mOriginalStyleElement = layer_node.namedItem( QStringLiteral( "originalStyle" ) ).firstChildElement();
2370 if ( mOriginalStyleElement.isNull() )
2371 mOriginalStyleElement = layer_node.toElement();
2372 mOriginalStyleDocument = layer_node.ownerDocument();
2373
2374 if ( ! mDataProvider )
2375 {
2377 {
2378 QgsDebugError( QStringLiteral( "Raster data provider could not be created for %1" ).arg( mDataSource ) );
2379 return false;
2380 }
2381 }
2382
2383 QString error;
2384 const bool res = readSymbology( layer_node, error, context );
2385
2386 // old wms settings we need to correct
2387 if ( res && mProviderKey == QLatin1String( "wms" ) && !renderer() )
2388 {
2389 setRendererForDrawingStyle( Qgis::RasterDrawingStyle::SingleBandColorData );
2390 }
2391
2392 // Check timestamp
2393 // This was probably introduced to reload completely raster if data changed and
2394 // reset completely symbology to reflect new data type etc. It creates however
2395 // problems, because user defined symbology is complete lost if data file time
2396 // changed (the content may be the same). See also 6900.
2397#if 0
2398 QDomNode stampNode = layer_node.namedItem( "timestamp" );
2399 if ( !stampNode.isNull() )
2400 {
2401 QDateTime stamp = QDateTime::fromString( stampNode.toElement().text(), Qt::ISODate );
2402 // TODO: very bad, we have to load twice!!! Make QgsDataProvider::timestamp() static?
2403 if ( stamp < mDataProvider->dataTimestamp() )
2404 {
2405 QgsDebugMsgLevel( QStringLiteral( "data changed, reload provider" ), 3 );
2406 closeDataProvider();
2407 init();
2409 if ( !isValid() ) return false;
2410 }
2411 }
2412#endif
2413
2414 // Load user no data value
2415 const QDomElement noDataElement = layer_node.firstChildElement( QStringLiteral( "noData" ) );
2416
2417 const QDomNodeList noDataBandList = noDataElement.elementsByTagName( QStringLiteral( "noDataList" ) );
2418
2419 for ( int i = 0; mDataProvider && i < noDataBandList.size(); ++i )
2420 {
2421 const QDomElement bandElement = noDataBandList.at( i ).toElement();
2422 bool ok;
2423 const int bandNo = bandElement.attribute( QStringLiteral( "bandNo" ) ).toInt( &ok );
2424 QgsDebugMsgLevel( QStringLiteral( "bandNo = %1" ).arg( bandNo ), 4 );
2425 if ( ok && ( bandNo > 0 ) && ( bandNo <= mDataProvider->bandCount() ) )
2426 {
2427 mDataProvider->setUseSourceNoDataValue( bandNo, bandElement.attribute( QStringLiteral( "useSrcNoData" ) ).toInt() );
2428 QgsRasterRangeList myNoDataRangeList;
2429
2430 const QDomNodeList rangeList = bandElement.elementsByTagName( QStringLiteral( "noDataRange" ) );
2431
2432 myNoDataRangeList.reserve( rangeList.size() );
2433 for ( int j = 0; j < rangeList.size(); ++j )
2434 {
2435 const QDomElement rangeElement = rangeList.at( j ).toElement();
2436 const QgsRasterRange myNoDataRange( rangeElement.attribute( QStringLiteral( "min" ) ).toDouble(),
2437 rangeElement.attribute( QStringLiteral( "max" ) ).toDouble() );
2438 QgsDebugMsgLevel( QStringLiteral( "min = %1 %2" ).arg( rangeElement.attribute( "min" ) ).arg( myNoDataRange.min() ), 4 );
2439 myNoDataRangeList << myNoDataRange;
2440 }
2441 mDataProvider->setUserNoDataValue( bandNo, myNoDataRangeList );
2442 }
2443 }
2444
2445 readRasterAttributeTableExternalPaths( layer_node, context );
2446
2447 readStyleManager( layer_node );
2448
2449 return res;
2450}
2451
2452bool QgsRasterLayer::writeSymbology( QDomNode &layer_node, QDomDocument &document, QString &errorMessage,
2453 const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
2454{
2456
2457 Q_UNUSED( errorMessage )
2458 // TODO: implement categories for raster layer
2459
2460 QDomElement layerElement = layer_node.toElement();
2461
2462 writeCommonStyle( layerElement, document, context, categories );
2463
2464 if ( categories.testFlag( Labeling ) )
2465 {
2466 if ( mLabeling )
2467 {
2468 QDomElement labelingElement = mLabeling->save( document, context );
2469 layerElement.appendChild( labelingElement );
2470 }
2471 if ( mLabelsEnabled )
2472 layerElement.setAttribute( QStringLiteral( "labelsEnabled" ), QStringLiteral( "1" ) );
2473 }
2474
2475 // save map tip
2476 if ( categories.testFlag( MapTips ) )
2477 {
2478 QDomElement mapTipElem = document.createElement( QStringLiteral( "mapTip" ) );
2479 mapTipElem.setAttribute( QStringLiteral( "enabled" ), mapTipsEnabled() );
2480 QDomText mapTipText = document.createTextNode( mapTipTemplate() );
2481 mapTipElem.appendChild( mapTipText );
2482 layer_node.toElement().appendChild( mapTipElem );
2483 }
2484
2485 // save attribute table attribute table paths
2486 if ( categories.testFlag( AttributeTable ) )
2487 {
2488 writeRasterAttributeTableExternalPaths( layer_node, document, context );
2489 }
2490
2491 // pipe considers Symbology and Rendering components, why it's always handled as one
2492 if ( categories.testFlag( Symbology ) || categories.testFlag( Rendering ) )
2493 {
2494 // Store pipe members into pipe element, in future, it will be
2495 // possible to add custom filters into the pipe
2496 QDomElement pipeElement = document.createElement( QStringLiteral( "pipe" ) );
2497
2498 for ( int i = 0; i < mPipe->size(); i++ )
2499 {
2500 QgsRasterInterface *interface = mPipe->at( i );
2501 if ( !interface ) continue;
2502 interface->writeXml( document, pipeElement );
2503 }
2504
2505 QDomElement elemDataDefinedProperties = document.createElement( QStringLiteral( "pipe-data-defined-properties" ) );
2506 mPipe->dataDefinedProperties().writeXml( elemDataDefinedProperties, QgsRasterPipe::propertyDefinitions() );
2507 layer_node.appendChild( elemDataDefinedProperties );
2508
2509 QDomElement resamplingStageElement = document.createElement( QStringLiteral( "resamplingStage" ) );
2510 const QDomText resamplingStageText = document.createTextNode( resamplingStage() == Qgis::RasterResamplingStage::Provider ? QStringLiteral( "provider" ) : QStringLiteral( "resamplingFilter" ) );
2511 resamplingStageElement.appendChild( resamplingStageText );
2512 pipeElement.appendChild( resamplingStageElement );
2513
2514 layer_node.appendChild( pipeElement );
2515
2516 if ( !isValid() && !mOriginalStyleElement.isNull() )
2517 {
2518 QDomElement originalStyleElement = document.createElement( QStringLiteral( "originalStyle" ) );
2519 originalStyleElement.appendChild( mOriginalStyleElement );
2520 layer_node.appendChild( originalStyleElement );
2521 }
2522
2523 // add blend mode node
2524 QDomElement blendModeElement = document.createElement( QStringLiteral( "blendMode" ) );
2525 const QDomText blendModeText = document.createTextNode( QString::number( static_cast< int >( QgsPainting::getBlendModeEnum( blendMode() ) ) ) );
2526 blendModeElement.appendChild( blendModeText );
2527 layer_node.appendChild( blendModeElement );
2528 }
2529
2530 return true;
2531}
2532
2533bool QgsRasterLayer::writeStyle( QDomNode &node, QDomDocument &doc, QString &errorMessage,
2534 const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
2535{
2537
2538 return writeSymbology( node, doc, errorMessage, context, categories );
2539}
2540
2541bool QgsRasterLayer::writeXml( QDomNode &layer_node,
2542 QDomDocument &document,
2543 const QgsReadWriteContext &context ) const
2544{
2546
2547 if ( !mDataProvider )
2548 return false;
2549
2550 // first get the layer element so that we can append the type attribute
2551
2552 QDomElement mapLayerNode = layer_node.toElement();
2553
2554 if ( mapLayerNode.isNull() || "maplayer" != mapLayerNode.nodeName() )
2555 {
2556 QgsMessageLog::logMessage( tr( "<maplayer> not found." ), tr( "Raster" ) );
2557 return false;
2558 }
2559
2560 mapLayerNode.setAttribute( QStringLiteral( "type" ), QgsMapLayerFactory::typeToString( Qgis::LayerType::Raster ) );
2561
2562 // add provider node
2563
2564 QDomElement provider = document.createElement( QStringLiteral( "provider" ) );
2565 const QDomText providerText = document.createTextNode( mProviderKey );
2566 provider.appendChild( providerText );
2567 layer_node.appendChild( provider );
2568
2569 // User no data
2570 QDomElement noData = document.createElement( QStringLiteral( "noData" ) );
2571
2572 for ( int bandNo = 1; bandNo <= mDataProvider->bandCount(); bandNo++ )
2573 {
2574 QDomElement noDataRangeList = document.createElement( QStringLiteral( "noDataList" ) );
2575 noDataRangeList.setAttribute( QStringLiteral( "bandNo" ), bandNo );
2576 noDataRangeList.setAttribute( QStringLiteral( "useSrcNoData" ), mDataProvider->useSourceNoDataValue( bandNo ) );
2577
2578 const auto constUserNoDataValues = mDataProvider->userNoDataValues( bandNo );
2579 for ( const QgsRasterRange &range : constUserNoDataValues )
2580 {
2581 QDomElement noDataRange = document.createElement( QStringLiteral( "noDataRange" ) );
2582
2583 noDataRange.setAttribute( QStringLiteral( "min" ), QgsRasterBlock::printValue( range.min() ) );
2584 noDataRange.setAttribute( QStringLiteral( "max" ), QgsRasterBlock::printValue( range.max() ) );
2585 noDataRangeList.appendChild( noDataRange );
2586 }
2587
2588 noData.appendChild( noDataRangeList );
2589
2590 }
2591 if ( noData.hasChildNodes() )
2592 {
2593 layer_node.appendChild( noData );
2594 }
2595
2596 // Store file-based raster attribute table paths (if any)
2597 writeRasterAttributeTableExternalPaths( layer_node, document, context );
2598
2599 writeStyleManager( layer_node, document );
2600
2601 serverProperties()->writeXml( layer_node, document );
2602
2603 //write out the symbology
2604 QString errorMsg;
2605 return writeSymbology( layer_node, document, errorMsg, context );
2606}
2607
2608
2609QString QgsRasterLayer::encodedSource( const QString &source, const QgsReadWriteContext &context ) const
2610{
2612
2614}
2615
2616QString QgsRasterLayer::decodedSource( const QString &source, const QString &provider, const QgsReadWriteContext &context ) const
2617{
2619
2620 return QgsProviderRegistry::instance()->relativeToAbsoluteUri( provider, source, context );
2621}
2622
2624{
2626
2627 if ( !mDataProvider ) return 0;
2628 return mDataProvider->xSize();
2629}
2630
2632{
2634
2635 if ( !mDataProvider ) return 0;
2636 return mDataProvider->ySize();
2637}
2638
2640{
2642
2643 mPipe->setResamplingStage( stage );
2644}
2645
2647{
2649
2650 return mPipe->resamplingStage();
2651}
2652
2653bool QgsRasterLayer::update()
2654{
2656
2657 QgsDebugMsgLevel( QStringLiteral( "entered." ), 4 );
2658 // Check if data changed
2659 if ( mDataProvider && mDataProvider->dataTimestamp() > mDataProvider->timestamp() )
2660 {
2661 QgsDebugMsgLevel( QStringLiteral( "reload data" ), 4 );
2662 closeDataProvider();
2663 init();
2664 const QgsDataProvider::ProviderOptions providerOptions;
2667 {
2669 }
2670 setDataProvider( mProviderKey, providerOptions, flags );
2671 emit dataChanged();
2672 }
2673 return isValid();
2674}
2675
2676#undef ERR
The Qgis class provides global constants for use throughout the application.
Definition qgis.h:54
static QString version()
Version string.
Definition qgis.cpp:259
@ 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:1380
@ 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:1454
@ 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:4506
@ 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:4600
BlendMode
Blending modes defining the available composition modes that can be used when painting.
Definition qgis.h:4657
@ 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:2181
@ 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:4439
@ 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:4559
@ 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.
Manipulates raster or point cloud pixel values so that they enhanceContrast or clip into a specified ...
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
This class 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.
Class for storing the component parts of a RDBMS 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.
Class for metadata formatter.
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.
void writeXml(QDomNode &layer_node, QDomDocument &document) const
Saves server properties to xml under the layer node.
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:76
QString name
Definition qgsmaplayer.h:80
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:83
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:82
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:90
@ 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:89
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)
Adds a message to the log instance (and creates it if necessary).
Renderer for multiband images with the color components.
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.
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.
A class to represent 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.
The QgsRasterAttributeTable class 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.
QString providerType() const
[ data provider interface ] Which provider is being used for this Raster Layer?
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...
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.
This class describes the origin of min/max values.
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.
Raster values range container.
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.
The class is used as a container of context for various read/write operations on other 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
This class is a composition of two QSettings instances:
Definition qgssettings.h:64
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.
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:6257
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition qgis.h:6066
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition qgis.h:5970
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:39
#define QgsDebugError(str)
Definition qgslogger.h:38
#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.