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