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