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