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