QGIS API Documentation 3.99.0-Master (26c88405ac0)
Loading...
Searching...
No Matches
qgsrasterlayer.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsrasterlayer.cpp - description
3 -------------------
4begin : Sat Jun 22 2002
5copyright : (C) 2003 by Tim Sutton, Steve Halasz and Gary E.Sherman
6email : tim at linfiniti.com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17#include "qgsrasterlayer.h"
18
19#include <cmath>
20#include <cstdio>
21#include <limits>
22#include <typeinfo>
23
24#include "qgsapplication.h"
27#include "qgscolorrampshader.h"
30#include "qgsdatasourceuri.h"
31#include "qgsgdalprovider.h"
34#include "qgslogger.h"
35#include "qgsmaplayerfactory.h"
36#include "qgsmaplayerlegend.h"
37#include "qgsmaptopixel.h"
38#include "qgsmessagelog.h"
40#include "qgspainting.h"
41#include "qgspathresolver.h"
43#include "qgsproviderregistry.h"
45#include "qgsrasterdrawer.h"
46#include "qgsrasteriterator.h"
47#include "qgsrasterlabeling.h"
52#include "qgsrasterpipe.h"
53#include "qgsrasterprojector.h"
54#include "qgsrasterrange.h"
57#include "qgsrastershader.h"
58#include "qgsreadwritecontext.h"
59#include "qgsrectangle.h"
60#include "qgsrendercontext.h"
61#include "qgsruntimeprofiler.h"
62#include "qgssettings.h"
64#include "qgssettingstree.h"
67#include "qgssldexportcontext.h"
68#include "qgssymbollayerutils.h"
69#include "qgsthreadingutils.h"
70#include "qgsxmlutils.h"
71
72#include <QApplication>
73#include <QCursor>
74#include <QDir>
75#include <QDomElement>
76#include <QDomNode>
77#include <QFile>
78#include <QFileInfo>
79#include <QFont>
80#include <QFontMetrics>
81#include <QFrame>
82#include <QImage>
83#include <QLabel>
84#include <QList>
85#include <QPainter>
86#include <QPixmap>
87#include <QRegularExpression>
88#include <QSlider>
89#include <QUrl>
90
91#include "moc_qgsrasterlayer.cpp"
92
95
96#define ERR(message) QGS_ERROR_MESSAGE(message,"Raster layer")
97
98const double QgsRasterLayer::SAMPLE_SIZE = 250000;
99
106
113
115 : QgsMapLayer( Qgis::LayerType::Raster )
116 , QSTRING_NOT_SET( QStringLiteral( "Not Set" ) )
117 , TRSTRING_NOT_SET( tr( "Not Set" ) )
118 , mTemporalProperties( new QgsRasterLayerTemporalProperties( this ) )
119 , mElevationProperties( new QgsRasterLayerElevationProperties( this ) )
120 , mPipe( std::make_unique< QgsRasterPipe >() )
121{
122 init();
123 setValid( false );
124}
125
127 const QString &baseName,
128 const QString &providerKey,
129 const LayerOptions &options )
130 : QgsMapLayer( Qgis::LayerType::Raster, baseName, uri )
131 // Constant that signals property not used.
132 , QSTRING_NOT_SET( QStringLiteral( "Not Set" ) )
133 , TRSTRING_NOT_SET( tr( "Not Set" ) )
134 , mTemporalProperties( new QgsRasterLayerTemporalProperties( this ) )
135 , mElevationProperties( new QgsRasterLayerElevationProperties( this ) )
136 , mPipe( std::make_unique< QgsRasterPipe >() )
137{
139
140 QgsDebugMsgLevel( QStringLiteral( "Entered" ), 4 );
141 setProviderType( providerKey );
142
143 const QgsDataProvider::ProviderOptions providerOptions { options.transformContext };
144 Qgis::DataProviderReadFlags providerFlags;
145 if ( options.loadDefaultStyle )
146 {
148 }
149
150 setDataSource( uri, baseName, providerKey, providerOptions, providerFlags );
151
152 if ( isValid() )
153 {
154 mTemporalProperties->setDefaultsFromDataProviderTemporalCapabilities( mDataProvider->temporalCapabilities() );
155 }
156
157} // QgsRasterLayer ctor
158
160{
161 emit willBeDeleted();
162
163 mLabeling.reset();
164
165 setValid( false );
166 // Note: provider and other interfaces are owned and deleted by pipe
167}
168
170{
172
174 if ( mDataProvider )
175 {
176 options.transformContext = mDataProvider->transformContext();
177 }
178 auto layer = std::make_unique< QgsRasterLayer >( source(), name(), mProviderKey, options );
179 QgsMapLayer::clone( layer.get() );
180 layer->mElevationProperties = mElevationProperties->clone();
181 layer->mElevationProperties->setParent( layer.get() );
182 layer->setMapTipTemplate( mapTipTemplate() );
183 layer->setMapTipsEnabled( mapTipsEnabled() );
184
185 // do not clone data provider which is the first element in pipe
186 for ( int i = 1; i < mPipe->size(); i++ )
187 {
188 if ( mPipe->at( i ) )
189 layer->pipe()->set( mPipe->at( i )->clone() );
190 }
191 layer->pipe()->setDataDefinedProperties( mPipe->dataDefinedProperties() );
192 layer->setResamplingStage( mPipe->resamplingStage() );
193 if ( mDataProvider && layer->dataProvider() )
194 {
195 layer->dataProvider()->setZoomedInResamplingMethod( mDataProvider->zoomedInResamplingMethod() );
196 layer->dataProvider()->setZoomedOutResamplingMethod( mDataProvider->zoomedOutResamplingMethod() );
197 }
198
199 layer->setLabelsEnabled( mLabelsEnabled );
200 if ( mLabeling )
201 layer->setLabeling( mLabeling->clone() );
202
203 return layer.release();
204}
205
207{
209
210 if ( !mElevationProperties->isEnabled() )
211 return nullptr;
212
213 return new QgsRasterLayerProfileGenerator( this, request );
214}
215
217//
218// Static Methods and members
219//
221
222bool QgsRasterLayer::isValidRasterFileName( const QString &fileNameQString, QString &retErrMsg )
223{
224 const bool myIsValid = QgsGdalProvider::isValidRasterFileName( fileNameQString, retErrMsg );
225 return myIsValid;
226}
227
228bool QgsRasterLayer::isValidRasterFileName( QString const &fileNameQString )
229{
230 QString retErrMsg;
231 return isValidRasterFileName( fileNameQString, retErrMsg );
232}
233
234QDateTime QgsRasterLayer::lastModified( QString const &name )
235{
236 QgsDebugMsgLevel( "name=" + name, 4 );
237 QDateTime t;
238
239 const QFileInfo fi( name );
240
241 // Is it file?
242 if ( !fi.exists() )
243 return t;
244
245 t = fi.lastModified();
246
247 QgsDebugMsgLevel( "last modified = " + t.toString(), 4 );
248
249 return t;
250}
251
258
259// typedef for the QgsDataProvider class factory
261
263//
264// Non Static Public methods
265//
267
269{
271
272 if ( !mDataProvider ) return 0;
273 return mDataProvider->bandCount();
274}
275
276QString QgsRasterLayer::bandName( int bandNo ) const
277{
279
280 if ( !mDataProvider ) return QString();
281 return mDataProvider->generateBandName( bandNo );
282}
283
285{
287
288 if ( !mDataProvider )
289 return nullptr;
290 return mDataProvider->attributeTable( bandNoInt );
291}
292
294{
296
297 if ( !mDataProvider )
298 return 0;
299
300 int ratCount { 0 };
301 for ( int bandNo = 1; bandNo <= bandCount(); ++bandNo )
302 {
303 if ( attributeTable( bandNo ) )
304 {
305 ratCount++;
306 }
307 }
308 return ratCount;
309}
310
317
318void QgsRasterLayer::setRendererForDrawingStyle( Qgis::RasterDrawingStyle drawingStyle )
319{
321
322 setRenderer( QgsApplication::rasterRendererRegistry()->defaultRendererForDrawingStyle( drawingStyle, mDataProvider ) );
323}
324
331
333{
335
336 return mDataProvider;
337}
338
340{
342
343 if ( mDataProvider )
344 {
345 mDataProvider->reloadData();
346 }
347}
348
355
356
357void QgsRasterLayer::draw( QPainter *theQPainter,
358 QgsRasterViewPort *rasterViewPort,
359 const QgsMapToPixel *qgsMapToPixel )
360{
362
363 QgsDebugMsgLevel( QStringLiteral( " 3 arguments" ), 4 );
364 QElapsedTimer time;
365 time.start();
366 //
367 //
368 // The goal here is to make as many decisions as possible early on (outside of the rendering loop)
369 // so that we can maximise performance of the rendering process. So now we check which drawing
370 // procedure to use :
371 //
372
373 QgsRasterProjector *projector = mPipe->projector();
374 bool restoreOldResamplingStage = false;
375 const Qgis::RasterResamplingStage oldResamplingState = resamplingStage();
376 // TODO add a method to interface to get provider and get provider
377 // params in QgsRasterProjector
378
379 if ( projector )
380 {
381 // Force provider resampling if reprojection is needed
382 if ( mDataProvider &&
383 ( mDataProvider->providerCapabilities() & Qgis::RasterProviderCapability::ProviderHintCanPerformProviderResampling ) &&
384 rasterViewPort->mSrcCRS != rasterViewPort->mDestCRS &&
385 oldResamplingState != Qgis::RasterResamplingStage::Provider )
386 {
387 restoreOldResamplingStage = true;
389 }
390 projector->setCrs( rasterViewPort->mSrcCRS, rasterViewPort->mDestCRS, rasterViewPort->mTransformContext );
391 }
392
393 // Drawer to pipe?
394 QgsRasterIterator iterator( mPipe->last() );
395 QgsRasterDrawer drawer( &iterator );
396 drawer.draw( theQPainter, rasterViewPort, qgsMapToPixel );
397
398 if ( restoreOldResamplingStage )
399 {
400 setResamplingStage( oldResamplingState );
401 }
402
403 QgsDebugMsgLevel( QStringLiteral( "total raster draw time (ms): %1" ).arg( time.elapsed(), 5 ), 4 );
404}
405
407{
409
410 QgsRasterRenderer *renderer = mPipe->renderer();
411 return renderer ? renderer->legendSymbologyItems() : QList< QPair< QString, QColor > >();;
412}
413
415{
417
418 if ( !mDataProvider )
419 return QString();
420
421 const QgsLayerMetadataFormatter htmlFormatter( metadata() );
422 QString myMetadata = QStringLiteral( "<html><head></head>\n<body>\n" );
423
424 myMetadata += generalHtmlMetadata();
425
426 // Begin Provider section
427 myMetadata += QStringLiteral( "<h1>" ) + tr( "Information from provider" ) + QStringLiteral( "</h1>\n<hr>\n" ) + QStringLiteral( "<table class=\"list-view\">\n" );
428
429 myMetadata += QStringLiteral( "\n" ) %
430 // Extent
431 QStringLiteral( "<tr><td class=\"highlight\">" ) % tr( "Extent" ) % QStringLiteral( "</td><td>" ) % extent().toString() % QStringLiteral( "</td></tr>\n" ) %
432
433 // Raster Width
434 QStringLiteral( "<tr><td class=\"highlight\">" ) % tr( "Width" ) % QStringLiteral( "</td><td>" );
435 if ( dataProvider()->capabilities() & Qgis::RasterInterfaceCapability::Size )
436 myMetadata += QString::number( width() );
437 else
438 myMetadata += tr( "n/a" );
439 myMetadata += QStringLiteral( "</td></tr>\n" ) %
440
441 // Raster height
442 QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Height" ) + QStringLiteral( "</td><td>" );
443 if ( dataProvider()->capabilities() & Qgis::RasterInterfaceCapability::Size )
444 myMetadata += QString::number( height() );
445 else
446 myMetadata += tr( "n/a" );
447 myMetadata += QStringLiteral( "</td></tr>\n" ) %
448
449 // Data type
450 QStringLiteral( "<tr><td class=\"highlight\">" ) % tr( "Data type" ) % QStringLiteral( "</td><td>" );
451 // Just use the first band
452 switch ( mDataProvider->sourceDataType( 1 ) )
453 {
455 myMetadata += tr( "Byte - Eight bit unsigned integer" );
456 break;
458 myMetadata += tr( "Int8 - Eight bit signed integer" );
459 break;
461 myMetadata += tr( "UInt16 - Sixteen bit unsigned integer " );
462 break;
464 myMetadata += tr( "Int16 - Sixteen bit signed integer " );
465 break;
467 myMetadata += tr( "UInt32 - Thirty two bit unsigned integer " );
468 break;
470 myMetadata += tr( "Int32 - Thirty two bit signed integer " );
471 break;
473 myMetadata += tr( "Float32 - Thirty two bit floating point " );
474 break;
476 myMetadata += tr( "Float64 - Sixty four bit floating point " );
477 break;
479 myMetadata += tr( "CInt16 - Complex Int16 " );
480 break;
482 myMetadata += tr( "CInt32 - Complex Int32 " );
483 break;
485 myMetadata += tr( "CFloat32 - Complex Float32 " );
486 break;
488 myMetadata += tr( "CFloat64 - Complex Float64 " );
489 break;
490 default:
491 myMetadata += tr( "Could not determine raster data type." );
492 }
493 myMetadata += QStringLiteral( "</td></tr>\n" ) %
494
495 // Insert provider-specific (e.g. WMS-specific) metadata
496 mDataProvider->htmlMetadata() %
497
498 // End Provider section
499 QStringLiteral( "</table>\n<br><br>" );
500
501 // CRS
502 myMetadata += crsHtmlMetadata();
503
504 // Identification section
505 myMetadata += QStringLiteral( "<h1>" ) % tr( "Identification" ) % QStringLiteral( "</h1>\n<hr>\n" ) %
506 htmlFormatter.identificationSectionHtml() %
507 QStringLiteral( "<br><br>\n" ) %
508
509 // extent section
510 QStringLiteral( "<h1>" ) % tr( "Extent" ) % QStringLiteral( "</h1>\n<hr>\n" ) %
511 htmlFormatter.extentSectionHtml( ) %
512 QStringLiteral( "<br><br>\n" ) %
513
514 // Start the Access section
515 QStringLiteral( "<h1>" ) % tr( "Access" ) % QStringLiteral( "</h1>\n<hr>\n" ) %
516 htmlFormatter.accessSectionHtml( ) %
517 QStringLiteral( "<br><br>\n" ) %
518
519 // Bands section
520 QStringLiteral( "</table>\n<br><br><h1>" ) % tr( "Bands" ) % QStringLiteral( "</h1>\n<hr>\n<table class=\"list-view\">\n" ) %
521
522 // Band count
523 QStringLiteral( "<tr><td class=\"highlight\">" ) % tr( "Band count" ) % QStringLiteral( "</td><td>" ) % QString::number( bandCount() ) % QStringLiteral( "</td></tr>\n" );
524
525 // Band table
526 myMetadata += QStringLiteral( "</table>\n<br><table width=\"100%\" class=\"tabular-view\">\n" ) %
527 QStringLiteral( "<tr><th>" ) % tr( "Number" ) % QStringLiteral( "</th><th>" ) % tr( "Band" ) % QStringLiteral( "</th><th>" ) % tr( "NoData" ) % QStringLiteral( "</th><th>" ) %
528 tr( "Min" ) % QStringLiteral( "</th><th>" ) % tr( "Max" ) % QStringLiteral( "</th></tr>\n" );
529
530 QgsRasterDataProvider *provider = const_cast< QgsRasterDataProvider * >( mDataProvider );
531 for ( int i = 1; i <= bandCount(); i++ )
532 {
533 QString rowClass;
534 if ( i % 2 )
535 rowClass = QStringLiteral( "class=\"odd-row\"" );
536
537 myMetadata += QStringLiteral( "<tr " ) % rowClass % QStringLiteral( "><td>" ) % QString::number( i ) % QStringLiteral( "</td><td>" ) % bandName( i ) % QStringLiteral( "</td><td>" );
538
539 if ( dataProvider()->sourceHasNoDataValue( i ) )
540 myMetadata += QString::number( dataProvider()->sourceNoDataValue( i ) );
541 else
542 myMetadata += tr( "n/a" );
543 myMetadata += QLatin1String( "</td>" );
544
545 if ( provider->hasStatistics( i, Qgis::RasterBandStatistic::Min | Qgis::RasterBandStatistic::Max, provider->extent(), static_cast<int>( SAMPLE_SIZE ) ) )
546 {
547 const QgsRasterBandStats myRasterBandStats = provider->bandStatistics( i, Qgis::RasterBandStatistic::Min | Qgis::RasterBandStatistic::Max, provider->extent(), static_cast<int>( SAMPLE_SIZE ) );
548 myMetadata += QStringLiteral( "<td>" ) % QString::number( myRasterBandStats.minimumValue, 'f', 10 ) % QStringLiteral( "</td>" ) %
549 QStringLiteral( "<td>" ) % QString::number( myRasterBandStats.maximumValue, 'f', 10 ) % QStringLiteral( "</td>" );
550 }
551 else
552 {
553 myMetadata += QStringLiteral( "<td>" ) % tr( "n/a" ) % QStringLiteral( "</td><td>" ) % tr( "n/a" ) % QStringLiteral( "</td>" );
554 }
555
556 myMetadata += QLatin1String( "</tr>\n" );
557 }
558
559 //close previous bands table
560 myMetadata += QStringLiteral( "</table>\n<br><br>" ) %
561
562 // Start the contacts section
563 QStringLiteral( "<h1>" ) % tr( "Contacts" ) % QStringLiteral( "</h1>\n<hr>\n" ) %
564 htmlFormatter.contactsSectionHtml( ) %
565 QStringLiteral( "<br><br>\n" ) %
566
567 // Start the links section
568 QStringLiteral( "<h1>" ) % tr( "References" ) % QStringLiteral( "</h1>\n<hr>\n" ) %
569 htmlFormatter.linksSectionHtml( ) %
570 QStringLiteral( "<br><br>\n" ) %
571
572 // Start the history section
573 QStringLiteral( "<h1>" ) % tr( "History" ) % QStringLiteral( "</h1>\n<hr>\n" ) %
574 htmlFormatter.historySectionHtml( ) %
575 QStringLiteral( "<br><br>\n" ) %
577 QStringLiteral( "\n</body>\n</html>\n" );
578 return myMetadata;
579}
580
582{
584
586 if ( mDataProvider && ( mDataProvider->flags() & Qgis::DataProviderFlag::IsBasemapSource ) )
587 {
589 }
590 return res;
591}
592
593QPixmap QgsRasterLayer::paletteAsPixmap( int bandNumber )
594{
596
597 //TODO: This function should take dimensions
598 QgsDebugMsgLevel( QStringLiteral( "entered." ), 4 );
599
600 // Only do this for the GDAL provider?
601 // Maybe WMS can do this differently using QImage::numColors and QImage::color()
602 if ( mDataProvider &&
603 mDataProvider->colorInterpretation( bandNumber ) == Qgis::RasterColorInterpretation::PaletteIndex )
604 {
605 QgsDebugMsgLevel( QStringLiteral( "....found paletted image" ), 4 );
606 QgsColorRampShader myShader;
607 const QList<QgsColorRampShader::ColorRampItem> myColorRampItemList = mDataProvider->colorTable( bandNumber );
608 if ( !myColorRampItemList.isEmpty() )
609 {
610 QgsDebugMsgLevel( QStringLiteral( "....got color ramp item list" ), 4 );
611 myShader.setColorRampItemList( myColorRampItemList );
613 // Draw image
614 const int mySize = 100;
615 QPixmap myPalettePixmap( mySize, mySize );
616 QPainter myQPainter( &myPalettePixmap );
617
618 QImage myQImage = QImage( mySize, mySize, QImage::Format_RGB32 );
619 myQImage.fill( 0 );
620 myPalettePixmap.fill();
621
622 const double myStep = ( static_cast< double >( myColorRampItemList.size() ) - 1 ) / static_cast< double >( mySize * mySize );
623 double myValue = 0.0;
624 for ( int myRow = 0; myRow < mySize; myRow++ )
625 {
626 QRgb *myLineBuffer = reinterpret_cast< QRgb * >( myQImage.scanLine( myRow ) );
627 for ( int myCol = 0; myCol < mySize; myCol++ )
628 {
629 myValue = myStep * static_cast< double >( myCol + myRow * mySize );
630 int c1, c2, c3, c4;
631 myShader.shade( myValue, &c1, &c2, &c3, &c4 );
632 myLineBuffer[ myCol ] = qRgba( c1, c2, c3, c4 );
633 }
634 }
635
636 myQPainter.drawImage( 0, 0, myQImage );
637 return myPalettePixmap;
638 }
639 const QPixmap myNullPixmap;
640 return myNullPixmap;
641 }
642 else
643 {
644 //invalid layer was requested
645 const QPixmap myNullPixmap;
646 return myNullPixmap;
647 }
648}
649
651{
653
654// We return one raster pixel per map unit pixel
655// One raster pixel can have several raster units...
656
657// We can only use one of the mGeoTransform[], so go with the
658// horisontal one.
659
660 if ( mDataProvider &&
661 mDataProvider->capabilities() & Qgis::RasterInterfaceCapability::Size && !qgsDoubleNear( mDataProvider->xSize(), 0.0 ) )
662 {
663 return mDataProvider->extent().width() / mDataProvider->xSize();
664 }
665 return 1;
666}
667
669{
671
672 if ( mDataProvider &&
673 mDataProvider->capabilities() & Qgis::RasterInterfaceCapability::Size && !qgsDoubleNear( mDataProvider->ySize(), 0.0 ) )
674 {
675 return mDataProvider->extent().height() / mDataProvider->ySize();
676 }
677 return 1;
678}
679
681{
683
684 if ( !mPipe->renderer() || mPipe->renderer()->opacity() == opacity )
685 return;
686
687 mPipe->renderer()->setOpacity( opacity );
688 emit opacityChanged( opacity );
690}
691
693{
695
696 return mPipe->renderer() ? mPipe->renderer()->opacity() : 1.0;
697}
698
699void QgsRasterLayer::init()
700{
702
704
705 whileBlocking( this )->setLegend( QgsMapLayerLegend::defaultRasterLegend( this ) );
706
707 setRendererForDrawingStyle( Qgis::RasterDrawingStyle::Undefined );
708
709 //Initialize the last view port structure, should really be a class
710 mLastViewPort.mWidth = 0;
711 mLastViewPort.mHeight = 0;
712}
713
715{
717
718 QgsDebugMsgLevel( QStringLiteral( "Entered" ), 4 );
719 setValid( false ); // assume the layer is invalid until we determine otherwise
720
721 // deletes pipe elements (including data provider)
722 mPipe = std::make_unique< QgsRasterPipe >();
723 mDataProvider = nullptr;
724
725 // XXX should I check for and possibly delete any pre-existing providers?
726 // XXX How often will that scenario occur?
727
728 mProviderKey = provider;
729 // set the layer name (uppercase first character)
730 if ( ! mLayerName.isEmpty() ) // XXX shouldn't this happen in parent?
731 {
733 }
734
735 //mBandCount = 0;
736
737 if ( mPreloadedProvider )
738 {
739 mDataProvider = qobject_cast< QgsRasterDataProvider * >( mPreloadedProvider.release() );
740 }
741 else
742 {
743 std::unique_ptr< QgsScopedRuntimeProfile > profile;
744 if ( QgsApplication::profiler()->groupIsActive( QStringLiteral( "projectload" ) ) )
745 profile = std::make_unique< QgsScopedRuntimeProfile >( tr( "Create %1 provider" ).arg( provider ), QStringLiteral( "projectload" ) );
746
747 mDataProvider = qobject_cast< QgsRasterDataProvider * >( QgsProviderRegistry::instance()->createProvider( mProviderKey, mDataSource, options, flags ) );
748 }
749
750 if ( !mDataProvider )
751 {
752 //QgsMessageLog::logMessage( tr( "Cannot instantiate the data provider" ), tr( "Raster" ) );
753 appendError( ERR( tr( "Cannot instantiate the '%1' data provider" ).arg( mProviderKey ) ) );
754 return;
755 }
756 QgsDebugMsgLevel( QStringLiteral( "Data provider created" ), 4 );
757 mDataProvider->setParent( this );
758
759 // Set data provider into pipe even if not valid so that it is deleted with pipe (with layer)
760 if ( !mPipe->set( mDataProvider ) )
761 {
762 // data provider has been deleted by the pipe
763 mDataProvider = nullptr;
764 appendError( ERR( tr( "Could not insert provider into layer pipe (provider: %1, URI: %2)" ).arg( mProviderKey, mDataSource ) ) );
765 return;
766 }
767
768 if ( !mDataProvider->isValid() )
769 {
770 setError( mDataProvider->error() );
771 appendError( ERR( tr( "Provider is not valid (provider: %1, URI: %2)" ).arg( mProviderKey, mDataSource ) ) );
772 return;
773 }
774
775 if ( mDataProvider->providerCapabilities() & Qgis::RasterProviderCapability::ReadLayerMetadata )
776 {
777 setMetadata( mDataProvider->layerMetadata() );
778 QgsDebugMsgLevel( QStringLiteral( "Set Data provider QgsLayerMetadata identifier[%1]" ).arg( metadata().identifier() ), 4 );
779 }
780
781 if ( provider == QLatin1String( "gdal" ) )
782 {
783 // make sure that the /vsigzip or /vsizip is added to uri, if applicable
784 mDataSource = mDataProvider->dataSourceUri();
785 }
786
788 {
789 // get the extent
790 const QgsRectangle mbr = mDataProvider->extent();
791
792 // store the extent
793 setExtent( mbr );
794 }
795
796 // upper case the first letter of the layer name
797 QgsDebugMsgLevel( "mLayerName: " + name(), 4 );
798
799 // set up the raster drawing style
800 // Do not set any 'sensible' style here, the style is set later
801
802 // Setup source CRS
803 setCrs( QgsCoordinateReferenceSystem( mDataProvider->crs() ) );
804
805 QgsDebugMsgLevel( "using wkt:\n" + crs().toWkt( Qgis::CrsWktVariant::Preferred ), 4 );
806
807 //defaults - Needs to be set after the Contrast list has been build
808 //Try to read the default contrast enhancement from the config file
809
810 //decide what type of layer this is...
811 //TODO Change this to look at the color interp and palette interp to decide which type of layer it is
812 QgsDebugMsgLevel( "bandCount = " + QString::number( mDataProvider->bandCount() ), 4 );
813 QgsDebugMsgLevel( "dataType = " + qgsEnumValueToKey< Qgis::DataType >( mDataProvider->dataType( 1 ) ), 4 );
814 const int bandCount = mDataProvider->bandCount();
815 if ( bandCount > 2 )
816 {
818 }
819 else if ( bandCount == 2 )
820 {
821 // handle singleband gray and paletted with alpha
822 auto colorInterpretationIsGrayOrUndefined = []( Qgis::RasterColorInterpretation interpretation )
823 {
824 return interpretation == Qgis::RasterColorInterpretation::GrayIndex
826 };
827
828 auto colorInterpretationIsPaletted = []( Qgis::RasterColorInterpretation interpretation )
829 {
830 return interpretation == Qgis::RasterColorInterpretation::PaletteIndex
832 };
833
834 if ( ( colorInterpretationIsGrayOrUndefined( mDataProvider->colorInterpretation( 1 ) ) && mDataProvider->colorInterpretation( 2 ) == Qgis::RasterColorInterpretation::AlphaBand )
835 || ( mDataProvider->colorInterpretation( 1 ) == Qgis::RasterColorInterpretation::AlphaBand && colorInterpretationIsGrayOrUndefined( mDataProvider->colorInterpretation( 2 ) ) ) )
836 {
838 }
839 else if ( ( colorInterpretationIsPaletted( mDataProvider->colorInterpretation( 1 ) ) && mDataProvider->colorInterpretation( 2 ) == Qgis::RasterColorInterpretation::AlphaBand )
840 || ( mDataProvider->colorInterpretation( 1 ) == Qgis::RasterColorInterpretation::AlphaBand && colorInterpretationIsPaletted( mDataProvider->colorInterpretation( 2 ) ) ) )
841 {
842 mRasterType = Qgis::RasterLayerType::Palette;
843 }
844 else
845 {
847 }
848 }
849 else if ( mDataProvider->dataType( 1 ) == Qgis::DataType::ARGB32
850 || mDataProvider->dataType( 1 ) == Qgis::DataType::ARGB32_Premultiplied )
851 {
853 }
854 else if ( mDataProvider->colorInterpretation( 1 ) == Qgis::RasterColorInterpretation::PaletteIndex
855 || mDataProvider->colorInterpretation( 1 ) == Qgis::RasterColorInterpretation::ContinuousPalette )
856 {
857 mRasterType = Qgis::RasterLayerType::Palette;
858 }
859 else
860 {
862 }
863
864 QgsDebugMsgLevel( "mRasterType = " + qgsEnumValueToKey( mRasterType ), 4 );
865
866 // Raster Attribute Table logic to load from provider or same basename + vat.dbf file.
867 QString errorMessage;
868 bool hasRat { mDataProvider->readNativeAttributeTable( &errorMessage ) };
869 if ( ! hasRat )
870 {
871 errorMessage.clear();
872 QgsDebugMsgLevel( "Native Raster Raster Attribute Table read failed " + errorMessage, 2 );
873 if ( QFile::exists( mDataProvider->dataSourceUri( ) + ".vat.dbf" ) )
874 {
875 auto rat = std::make_unique<QgsRasterAttributeTable>();
876 hasRat = rat->readFromFile( mDataProvider->dataSourceUri( ) + ".vat.dbf", &errorMessage );
877 if ( hasRat )
878 {
879 if ( rat->isValid( &errorMessage ) )
880 {
881 mDataProvider->setAttributeTable( 1, rat.release() );
882 QgsDebugMsgLevel( "DBF Raster Attribute Table successfully read from " + mDataProvider->dataSourceUri( ) + ".vat.dbf", 2 );
883 }
884 else
885 {
886 QgsDebugMsgLevel( "DBF Raster Attribute Table is not valid, skipping: " + errorMessage, 2 );
887 }
888 }
889 else
890 {
891 QgsDebugMsgLevel( "DBF Raster Attribute Table read failed " + errorMessage, 2 );
892 }
893 }
894 }
895 else
896 {
897 QgsDebugMsgLevel( "Native Raster Attribute Table read success", 2 );
898 }
899
900 switch ( mRasterType )
901 {
903 {
904 QgsDebugMsgLevel( "Setting drawing style to SingleBandColorDataStyle " + qgsEnumValueToKey( Qgis::RasterDrawingStyle::SingleBandColorData ), 4 );
905 setRendererForDrawingStyle( Qgis::RasterDrawingStyle::SingleBandColorData );
906 break;
907 }
909 {
910 if ( mDataProvider->colorInterpretation( 1 ) == Qgis::RasterColorInterpretation::PaletteIndex )
911 {
912 setRendererForDrawingStyle( Qgis::RasterDrawingStyle::PalettedColor ); //sensible default
913 }
914 else if ( mDataProvider->colorInterpretation( 1 ) == Qgis::RasterColorInterpretation::ContinuousPalette )
915 {
916 setRendererForDrawingStyle( Qgis::RasterDrawingStyle::SingleBandPseudoColor );
917 // Load color table
918 const QList<QgsColorRampShader::ColorRampItem> colorTable = mDataProvider->colorTable( 1 );
920 if ( r )
921 {
922 // TODO: this should go somewhere else
923 QgsRasterShader *shader = new QgsRasterShader();
924 QgsColorRampShader *colorRampShader = new QgsColorRampShader();
926 colorRampShader->setColorRampItemList( colorTable );
927 shader->setRasterShaderFunction( colorRampShader );
928 r->setShader( shader );
929 }
930 }
931 else
932 {
933 setRendererForDrawingStyle( Qgis::RasterDrawingStyle::SingleBandGray ); //sensible default
934 }
935 break;
936 }
938 {
939 setRendererForDrawingStyle( Qgis::RasterDrawingStyle::MultiBandColor ); //sensible default
940 break;
941 }
943 {
944 setRendererForDrawingStyle( Qgis::RasterDrawingStyle::SingleBandGray ); //sensible default
945 break;
946 }
947 }
948
949 // Auto set alpha band
950 for ( int bandNo = 1; bandNo <= mDataProvider->bandCount(); bandNo++ )
951 {
952 if ( mDataProvider->colorInterpretation( bandNo ) == Qgis::RasterColorInterpretation::AlphaBand )
953 {
954 if ( auto *lRenderer = mPipe->renderer() )
955 {
956 lRenderer->setAlphaBand( bandNo );
957 }
958 break;
959 }
960 }
961
962 // brightness filter
964 mPipe->set( brightnessFilter );
965
966 // hue/saturation filter
968 mPipe->set( hueSaturationFilter );
969
970 // resampler (must be after renderer)
972 if ( mPipe->set( resampleFilter ) && mDataProvider->providerCapabilities() & Qgis::RasterProviderCapability::ProviderHintBenefitsFromResampling )
973 {
974 const QgsSettings settings;
975 QString resampling = settings.value( QStringLiteral( "/Raster/defaultZoomedInResampling" ), QStringLiteral( "nearest neighbour" ) ).toString();
976 if ( resampling == QLatin1String( "bilinear" ) )
977 {
978 resampleFilter->setZoomedInResampler( new QgsBilinearRasterResampler() );
979 mDataProvider->setZoomedInResamplingMethod( Qgis::RasterResamplingMethod::Bilinear );
980 }
981 else if ( resampling == QLatin1String( "cubic" ) )
982 {
983 resampleFilter->setZoomedInResampler( new QgsCubicRasterResampler() );
984 mDataProvider->setZoomedInResamplingMethod( Qgis::RasterResamplingMethod::Cubic );
985 }
986 resampling = settings.value( QStringLiteral( "/Raster/defaultZoomedOutResampling" ), QStringLiteral( "nearest neighbour" ) ).toString();
987 if ( resampling == QLatin1String( "bilinear" ) )
988 {
989 resampleFilter->setZoomedOutResampler( new QgsBilinearRasterResampler() );
990 mDataProvider->setZoomedOutResamplingMethod( Qgis::RasterResamplingMethod::Bilinear );
991 }
992
993 const double maxOversampling = QgsRasterLayer::settingsRasterDefaultOversampling->value();
994 resampleFilter->setMaxOversampling( maxOversampling );
995 mDataProvider->setMaxOversampling( maxOversampling );
996
997 if ( ( mDataProvider->providerCapabilities() & Qgis::RasterProviderCapability::ProviderHintCanPerformProviderResampling ) &&
999 {
1001 }
1002 else
1003 {
1005 }
1006 }
1007
1008 // projector (may be anywhere in pipe)
1009 QgsRasterProjector *projector = new QgsRasterProjector;
1010 mPipe->set( projector );
1011
1012 // Set default identify format - use the richest format available
1013 const Qgis::RasterInterfaceCapabilities capabilities = mDataProvider->capabilities();
1016 {
1017 // HTML is usually richest
1018 identifyFormat = Qgis::RasterIdentifyFormat::Html;
1019 }
1020 else if ( capabilities & Qgis::RasterInterfaceCapability::IdentifyFeature )
1021 {
1022 identifyFormat = Qgis::RasterIdentifyFormat::Feature;
1023 }
1024 else if ( capabilities & Qgis::RasterInterfaceCapability::IdentifyText )
1025 {
1026 identifyFormat = Qgis::RasterIdentifyFormat::Text;
1027 }
1028 else if ( capabilities & Qgis::RasterInterfaceCapability::IdentifyValue )
1029 {
1030 identifyFormat = Qgis::RasterIdentifyFormat::Value;
1031 }
1032 setCustomProperty( QStringLiteral( "identify/format" ), QgsRasterDataProvider::identifyFormatName( identifyFormat ) );
1033
1034 if ( QgsRasterDataProviderElevationProperties *properties = mDataProvider->elevationProperties() )
1035 {
1036 if ( properties->containsElevationData() )
1037 {
1038 mElevationProperties->setEnabled( true );
1039 }
1040 }
1041
1042 // Store timestamp
1043 // TODO move to provider
1044 mLastModified = lastModified( mDataSource );
1045
1046 // Do a passthrough for the status bar text
1048
1049 //mark the layer as valid
1050 setValid( true );
1051
1052 if ( mDataProvider->supportsSubsetString() )
1053 connect( this, &QgsRasterLayer::subsetStringChanged, this, &QgsMapLayer::configChanged, Qt::UniqueConnection );
1054 else
1056
1057
1058 QgsDebugMsgLevel( QStringLiteral( "exiting." ), 4 );
1059
1060}
1061
1062void QgsRasterLayer::setDataSourcePrivate( const QString &dataSource, const QString &baseName, const QString &provider,
1064{
1066
1067 const bool hadRenderer( renderer() );
1068
1069 QDomImplementation domImplementation;
1070 QDomDocumentType documentType;
1071 QString errorMsg;
1072
1073 bool loadDefaultStyleFlag = false;
1075 {
1076 loadDefaultStyleFlag = true;
1077 }
1078
1079 // Store the original style
1080 if ( hadRenderer && ! loadDefaultStyleFlag )
1081 {
1082 documentType = domImplementation.createDocumentType(
1083 QStringLiteral( "qgis" ), QStringLiteral( "http://mrcc.com/qgis.dtd" ), QStringLiteral( "SYSTEM" ) );
1084
1085 QDomDocument doc = QDomDocument( documentType );
1086 QDomElement styleElem = doc.createElement( QStringLiteral( "qgis" ) );
1087 styleElem.setAttribute( QStringLiteral( "version" ), Qgis::version() );
1088 const QgsReadWriteContext writeContext;
1089 if ( ! writeSymbology( styleElem, doc, errorMsg, writeContext ) )
1090 {
1091 QgsDebugError( QStringLiteral( "Could not store symbology for layer %1: %2" )
1092 .arg( name(),
1093 errorMsg ) );
1094 }
1095 else
1096 {
1097 doc.appendChild( styleElem );
1098
1099 mOriginalStyleDocument = doc;
1100 mOriginalStyleElement = styleElem;
1101 }
1102 }
1103
1104 if ( mDataProvider )
1105 closeDataProvider();
1106
1107 init();
1108
1109 for ( int i = mPipe->size() - 1; i >= 0; --i )
1110 {
1111 mPipe->remove( i );
1112 }
1113
1114 mDataSource = dataSource;
1115 mLayerName = baseName;
1116
1117 setDataProvider( provider, options, flags );
1118
1119 if ( mDataProvider )
1120 mDataProvider->setDataSourceUri( mDataSource );
1121
1122 if ( isValid() )
1123 {
1124 // load default style
1125 bool defaultLoadedFlag = false;
1126 bool restoredStyle = false;
1127 if ( loadDefaultStyleFlag )
1128 {
1129 loadDefaultStyle( defaultLoadedFlag );
1130 }
1131 else if ( !mOriginalStyleElement.isNull() ) // Restore the style
1132 {
1133 QgsReadWriteContext readContext;
1134 if ( ! readSymbology( mOriginalStyleElement, errorMsg, readContext ) )
1135 {
1136 QgsDebugError( QStringLiteral( "Could not restore symbology for layer %1: %2" )
1137 .arg( name() )
1138 .arg( errorMsg ) );
1139
1140 }
1141 else
1142 {
1143 restoredStyle = true;
1144 emit repaintRequested();
1146 emit rendererChanged();
1147 }
1148 }
1149
1150 if ( !defaultLoadedFlag && !restoredStyle )
1151 {
1153 }
1154 }
1155}
1156
1157void QgsRasterLayer::writeRasterAttributeTableExternalPaths( QDomNode &layerNode, QDomDocument &doc, const QgsReadWriteContext &context ) const
1158{
1160
1161 if ( attributeTableCount() > 0 )
1162 {
1163 QDomElement elem = doc.createElement( QStringLiteral( "FileBasedAttributeTables" ) );
1164 for ( int bandNo = 1; bandNo <= bandCount(); bandNo++ )
1165 {
1166 if ( QgsRasterAttributeTable *rat = attributeTable( bandNo ); rat && ! rat->filePath().isEmpty() )
1167 {
1168 QDomElement ratElem = doc.createElement( QStringLiteral( "AttributeTable" ) );
1169 ratElem.setAttribute( QStringLiteral( "band" ), bandNo );
1170 ratElem.setAttribute( QStringLiteral( "path" ), context.pathResolver().writePath( rat->filePath( ) ) );
1171 elem.appendChild( ratElem );
1172 }
1173 }
1174 layerNode.appendChild( elem );
1175 }
1176}
1177
1178void QgsRasterLayer::readRasterAttributeTableExternalPaths( const QDomNode &layerNode, QgsReadWriteContext &context ) const
1179{
1180 const QDomElement ratsElement = layerNode.firstChildElement( QStringLiteral( "FileBasedAttributeTables" ) );
1181 if ( !ratsElement.isNull() && ratsElement.childNodes().count() > 0 )
1182 {
1183 const QDomNodeList ratElements { ratsElement.childNodes() };
1184 for ( int idx = 0; idx < ratElements.count(); idx++ )
1185 {
1186 const QDomNode ratElement { ratElements.at( idx ) };
1187 if ( ratElement.attributes().contains( QStringLiteral( "band" ) )
1188 && ratElement.attributes().contains( QStringLiteral( "path" ) ) )
1189 {
1190 bool ok;
1191 const int band { ratElement.attributes().namedItem( QStringLiteral( "band" ) ).nodeValue().toInt( &ok ) };
1192
1193 // Check band is ok
1194 if ( ! ok || band <= 0 || band > bandCount() )
1195 {
1196 QgsMessageLog::logMessage( tr( "Error reading raster attribute table: invalid band %1." ).arg( band ), tr( "Raster" ) );
1197 continue;
1198 }
1199
1200 const QString path { context.pathResolver().readPath( ratElement.attributes().namedItem( QStringLiteral( "path" ) ).nodeValue() ) };
1201 if ( ! QFile::exists( path ) )
1202 {
1203 QgsMessageLog::logMessage( tr( "Error loading raster attribute table, file not found: %1." ).arg( path ), tr( "Raster" ) );
1204 continue;
1205 }
1206
1207 auto rat = std::make_unique<QgsRasterAttributeTable>();
1208 QString errorMessage;
1209 if ( ! rat->readFromFile( path, &errorMessage ) )
1210 {
1211 QgsMessageLog::logMessage( tr( "Error loading raster attribute table from path %1: %2" ).arg( path, errorMessage ), tr( "Raster" ) );
1212 continue;
1213 }
1214
1215 // All good, set the RAT
1216 mDataProvider->setAttributeTable( band, rat.release() );
1217 }
1218 }
1219 }
1220}
1221
1222void QgsRasterLayer::closeDataProvider()
1223{
1225
1226 setValid( false );
1227 mPipe->remove( mDataProvider );
1228 mDataProvider = nullptr;
1229}
1230
1232 const QgsRasterMinMaxOrigin &mmo,
1234 const QgsRectangle &extent,
1235 int sampleSize,
1236 double &min, double &max )
1237{
1239
1240 min = std::numeric_limits<double>::quiet_NaN();
1241 max = std::numeric_limits<double>::quiet_NaN();
1242 if ( !mDataProvider )
1243 return;
1244
1246 {
1247 QgsRasterBandStats myRasterBandStats = mDataProvider->bandStatistics( band, Qgis::RasterBandStatistic::Min | Qgis::RasterBandStatistic::Max, extent, sampleSize );
1248 // Check if statistics were actually gathered, None means a failure
1249 if ( myRasterBandStats.statsGathered == static_cast< int >( Qgis::RasterBandStatistic::NoStatistic ) )
1250 {
1251 // Best guess we can do
1252 switch ( mDataProvider->dataType( band ) )
1253 {
1255 {
1256 myRasterBandStats.minimumValue = 0;
1257 myRasterBandStats.maximumValue = 255;
1258 break;
1259 }
1261 {
1262 myRasterBandStats.minimumValue = std::numeric_limits<int8_t>::lowest();
1263 myRasterBandStats.maximumValue = std::numeric_limits<int8_t>::max();
1264 break;
1265 }
1267 {
1268 myRasterBandStats.minimumValue = 0;
1269 myRasterBandStats.maximumValue = std::numeric_limits<uint16_t>::max();
1270 break;
1271 }
1273 {
1274 myRasterBandStats.minimumValue = 0;
1275 myRasterBandStats.maximumValue = std::numeric_limits<uint32_t>::max();
1276 break;
1277 }
1280 {
1281 myRasterBandStats.minimumValue = std::numeric_limits<int16_t>::lowest();
1282 myRasterBandStats.maximumValue = std::numeric_limits<int16_t>::max();
1283 break;
1284 }
1287 {
1288 myRasterBandStats.minimumValue = std::numeric_limits<int32_t>::lowest();
1289 myRasterBandStats.maximumValue = std::numeric_limits<int32_t>::max();
1290 break;
1291 }
1294 {
1295 myRasterBandStats.minimumValue = std::numeric_limits<float_t>::lowest();
1296 myRasterBandStats.maximumValue = std::numeric_limits<float_t>::max();
1297 break;
1298 }
1301 {
1302 myRasterBandStats.minimumValue = std::numeric_limits<double_t>::lowest();
1303 myRasterBandStats.maximumValue = std::numeric_limits<double_t>::max();
1304 break;
1305 }
1309 {
1310 // Nothing to guess
1311 break;
1312 }
1313 }
1314 }
1315 min = myRasterBandStats.minimumValue;
1316 max = myRasterBandStats.maximumValue;
1317 }
1318 else if ( limits == Qgis::RasterRangeLimit::StdDev )
1319 {
1320 const QgsRasterBandStats myRasterBandStats = mDataProvider->bandStatistics( band, Qgis::RasterBandStatistic::Mean | Qgis::RasterBandStatistic::StdDev, extent, sampleSize );
1321 min = myRasterBandStats.mean - ( mmo.stdDevFactor() * myRasterBandStats.stdDev );
1322 max = myRasterBandStats.mean + ( mmo.stdDevFactor() * myRasterBandStats.stdDev );
1323 }
1324 else if ( limits == Qgis::RasterRangeLimit::CumulativeCut )
1325 {
1326 const double myLower = mmo.cumulativeCutLower();
1327 const double myUpper = mmo.cumulativeCutUpper();
1328 QgsDebugMsgLevel( QStringLiteral( "myLower = %1 myUpper = %2" ).arg( myLower ).arg( myUpper ), 4 );
1329 mDataProvider->cumulativeCut( band, myLower, myUpper, min, max, extent, sampleSize );
1330 }
1331 QgsDebugMsgLevel( QStringLiteral( "band = %1 min = %2 max = %3" ).arg( band ).arg( min ).arg( max ), 4 );
1332
1333}
1334
1336{
1338
1339 return mDataProvider ? mDataProvider->ignoreExtents() : false;
1340}
1341
1348
1355
1357{
1359
1361 limits,
1362 extent,
1363 sampleSize,
1364 generateLookupTableFlag,
1365 mPipe->renderer() );
1366}
1367
1370 const QgsRectangle &extent,
1371 int sampleSize,
1372 bool generateLookupTableFlag,
1373 QgsRasterRenderer *rasterRenderer )
1374{
1376
1377 QgsDebugMsgLevel( QStringLiteral( "theAlgorithm = %1 limits = %2 extent.isEmpty() = %3" ).arg( algorithm ).arg( qgsEnumValueToKey( limits ) ).arg( extent.isEmpty() ), 4 );
1378 if ( !rasterRenderer || !mDataProvider )
1379 {
1380 return;
1381 }
1382
1383 QList<int> myBands;
1384 QList<QgsContrastEnhancement *> myEnhancements;
1385 QgsRasterMinMaxOrigin myMinMaxOrigin;
1386 QgsRasterRenderer *myRasterRenderer = nullptr;
1387 QgsSingleBandGrayRenderer *myGrayRenderer = nullptr;
1388 QgsSingleBandPseudoColorRenderer *myPseudoColorRenderer = nullptr;
1389 QgsMultiBandColorRenderer *myMultiBandRenderer = nullptr;
1390 const QString rendererType = rasterRenderer->type();
1391 if ( rendererType == QLatin1String( "singlebandgray" ) )
1392 {
1393 myGrayRenderer = dynamic_cast<QgsSingleBandGrayRenderer *>( rasterRenderer );
1394 if ( !myGrayRenderer )
1395 {
1396 return;
1397 }
1398 myBands << myGrayRenderer->inputBand();
1399 myRasterRenderer = myGrayRenderer;
1400 myMinMaxOrigin = myGrayRenderer->minMaxOrigin();
1401 }
1402 else if ( rendererType == QLatin1String( "multibandcolor" ) )
1403 {
1404 myMultiBandRenderer = dynamic_cast<QgsMultiBandColorRenderer *>( rasterRenderer );
1405 if ( !myMultiBandRenderer )
1406 {
1407 return;
1408 }
1409 myBands << myMultiBandRenderer->redBand() << myMultiBandRenderer->greenBand() << myMultiBandRenderer->blueBand();
1410 myRasterRenderer = myMultiBandRenderer;
1411 myMinMaxOrigin = myMultiBandRenderer->minMaxOrigin();
1412 }
1413 else if ( rendererType == QLatin1String( "singlebandpseudocolor" ) )
1414 {
1415 myPseudoColorRenderer = dynamic_cast<QgsSingleBandPseudoColorRenderer *>( rasterRenderer );
1416 if ( !myPseudoColorRenderer )
1417 {
1418 return;
1419 }
1420 myBands << myPseudoColorRenderer->inputBand();
1421 myRasterRenderer = myPseudoColorRenderer;
1422 myMinMaxOrigin = myPseudoColorRenderer->minMaxOrigin();
1423 }
1424 else
1425 {
1426 return;
1427 }
1428
1429 for ( const int myBand : std::as_const( myBands ) )
1430 {
1431 if ( myBand != -1 )
1432 {
1433 const Qgis::DataType myType = static_cast< Qgis::DataType >( mDataProvider->dataType( myBand ) );
1434 auto myEnhancement = std::make_unique<QgsContrastEnhancement>( static_cast< Qgis::DataType >( myType ) );
1435 myEnhancement->setContrastEnhancementAlgorithm( algorithm, generateLookupTableFlag );
1436
1437 double min;
1438 double max;
1439 computeMinMax( myBand, myMinMaxOrigin, limits, extent, sampleSize, min, max );
1440
1441 if ( rendererType == QLatin1String( "singlebandpseudocolor" ) )
1442 {
1443 // This is not necessary, but clang-tidy thinks it is.
1444 if ( ! myPseudoColorRenderer )
1445 {
1446 return;
1447 }
1448 // Do not overwrite min/max with NaN if they were already set,
1449 // for example when the style was already loaded from a raster attribute table
1450 // in that case we need to respect the style from the attribute table and do
1451 // not perform any reclassification.
1452 bool minMaxChanged { false };
1453 if ( ! std::isnan( min ) )
1454 {
1455 myPseudoColorRenderer->setClassificationMin( min );
1456 minMaxChanged = true;
1457 }
1458
1459 if ( ! std::isnan( max ) )
1460 {
1461 myPseudoColorRenderer->setClassificationMax( max );
1462 minMaxChanged = true;
1463 }
1464
1465 if ( minMaxChanged && myPseudoColorRenderer->shader() )
1466 {
1467 QgsColorRampShader *colorRampShader = dynamic_cast<QgsColorRampShader *>( myPseudoColorRenderer->shader()->rasterShaderFunction() );
1468 if ( colorRampShader )
1469 {
1470 colorRampShader->classifyColorRamp( myPseudoColorRenderer->inputBand(), extent, myPseudoColorRenderer->input() );
1471 }
1472 }
1473 }
1474 else
1475 {
1476 myEnhancement->setMinimumValue( min );
1477 myEnhancement->setMaximumValue( max );
1478 myEnhancements.append( myEnhancement.release() );
1479 }
1480 }
1481 else
1482 {
1483 myEnhancements.append( nullptr );
1484 }
1485 }
1486
1487 // Again, second check is redundant but clang-tidy doesn't agree
1488 if ( rendererType == QLatin1String( "singlebandgray" ) && myGrayRenderer )
1489 {
1490 if ( myEnhancements.first() ) myGrayRenderer->setContrastEnhancement( myEnhancements.takeFirst() );
1491 }
1492 else if ( rendererType == QLatin1String( "multibandcolor" ) && myMultiBandRenderer )
1493 {
1494 if ( myEnhancements.first() ) myMultiBandRenderer->setRedContrastEnhancement( myEnhancements.takeFirst() );
1495 if ( myEnhancements.first() ) myMultiBandRenderer->setGreenContrastEnhancement( myEnhancements.takeFirst() );
1496 if ( myEnhancements.first() ) myMultiBandRenderer->setBlueContrastEnhancement( myEnhancements.takeFirst() );
1497 }
1498
1499 //delete all remaining unused enhancements
1500 qDeleteAll( myEnhancements );
1501
1502 myMinMaxOrigin.setLimits( limits );
1503 if ( extent != QgsRectangle() &&
1504 myMinMaxOrigin.extent() == Qgis::RasterRangeExtent::WholeRaster )
1505 {
1507 }
1508 if ( myRasterRenderer )
1509 {
1510 myRasterRenderer->setMinMaxOrigin( myMinMaxOrigin );
1511 }
1512
1513 if ( rasterRenderer == renderer() )
1514 {
1515 emit repaintRequested();
1517 emit rendererChanged();
1518 }
1519}
1520
1522{
1524
1525 QgsSingleBandGrayRenderer *singleBandRenderer = nullptr;
1526 QgsMultiBandColorRenderer *multiBandRenderer = nullptr;
1527 const QgsContrastEnhancement *ce = nullptr;
1528 if ( ( singleBandRenderer = dynamic_cast<QgsSingleBandGrayRenderer *>( renderer() ) ) )
1529 {
1530 ce = singleBandRenderer->contrastEnhancement();
1531 }
1532 else if ( ( multiBandRenderer = dynamic_cast<QgsMultiBandColorRenderer *>( renderer() ) ) )
1533 {
1534 ce = multiBandRenderer->redContrastEnhancement();
1535 }
1536
1537 if ( ce )
1538 {
1541 renderer()->minMaxOrigin().limits() == Qgis::RasterRangeLimit::NotSet ?
1542 Qgis::RasterRangeLimit::MinimumMaximum : renderer()->minMaxOrigin().limits(),
1543 extent,
1544 static_cast<int>( SAMPLE_SIZE ),
1545 true,
1546 renderer() );
1547 }
1548 else
1549 {
1551 Qgis::RasterRangeLimit myLimits;
1552 if ( defaultContrastEnhancementSettings( myAlgorithm, myLimits ) )
1553 {
1555 myLimits,
1556 extent,
1557 static_cast<int>( SAMPLE_SIZE ),
1558 true,
1559 renderer() );
1560 }
1561 }
1562}
1563
1565{
1567
1568 if ( !isValid() || !mDataProvider )
1569 {
1570 QgsDebugMsgLevel( QStringLiteral( "invoked with invalid layer or null mDataProvider" ), 3 );
1571 return customProperty( QStringLiteral( "storedSubsetString" ) ).toString();
1572 }
1573 if ( !mDataProvider->supportsSubsetString() )
1574 {
1575 return QString();
1576 }
1577 return mDataProvider->subsetString();
1578}
1579
1580bool QgsRasterLayer::setSubsetString( const QString &subset )
1581{
1583
1584 if ( !isValid() || !mDataProvider )
1585 {
1586 QgsDebugMsgLevel( QStringLiteral( "invoked with invalid layer or null mDataProvider or while editing" ), 3 );
1587 setCustomProperty( QStringLiteral( "storedSubsetString" ), subset );
1588 return false;
1589 }
1590
1591 if ( !mDataProvider->supportsSubsetString() )
1592 {
1593 return false;
1594 }
1595
1596 if ( subset == mDataProvider->subsetString() )
1597 return true;
1598
1599 const bool res = mDataProvider->setSubsetString( subset );
1600
1601 // get the updated data source string from the provider
1602 mDataSource = mDataProvider->dataSourceUri();
1603
1604 if ( res )
1605 {
1606 setExtent( mDataProvider->extent() );
1607 QList<double> minValues;
1608 QList<double> maxValues;
1609 const QgsRasterMinMaxOrigin &minMaxOrigin = renderer()->minMaxOrigin();
1610 for ( const int bandIdx : renderer()->usesBands() )
1611 {
1612 double min;
1613 double max;
1614
1615 computeMinMax( bandIdx, minMaxOrigin, minMaxOrigin.limits(),
1616 extent(), static_cast<int>( QgsRasterLayer::SAMPLE_SIZE ),
1617 min, max );
1618 minValues.append( min );
1619 maxValues.append( max );
1620 }
1621 renderer()->refresh( extent(), minValues, maxValues, true );
1622 emit subsetStringChanged();
1623 }
1624
1625 return res;
1626}
1627
1630 Qgis::RasterRangeLimit &myLimits ) const
1631{
1633
1634 const QgsSettings mySettings;
1635
1636 QString key;
1637 QString defaultAlg;
1638 QString defaultLimits;
1639
1640 // TODO: we should not test renderer class here, move it somehow to renderers
1641 if ( dynamic_cast<QgsSingleBandGrayRenderer *>( renderer() ) )
1642 {
1643 key = QStringLiteral( "singleBand" );
1648 }
1649 else if ( dynamic_cast<QgsMultiBandColorRenderer *>( renderer() ) )
1650 {
1651 if ( QgsRasterBlock::typeSize( dataProvider()->sourceDataType( 1 ) ) == 1 )
1652 {
1653 key = QStringLiteral( "multiBandSingleByte" );
1658 }
1659 else
1660 {
1661 key = QStringLiteral( "multiBandMultiByte" );
1666 }
1667 }
1668
1669 if ( key.isEmpty() )
1670 {
1671 QgsDebugMsgLevel( QStringLiteral( "No default contrast enhancement for this drawing style" ), 2 );
1673 myLimits = QgsRasterMinMaxOrigin::limitsFromString( QString() );
1674 return false;
1675 }
1676 QgsDebugMsgLevel( "key = " + key, 4 );
1677
1678 const QString myAlgorithmString = mySettings.value( "/Raster/defaultContrastEnhancementAlgorithm/" + key, defaultAlg ).toString();
1679 QgsDebugMsgLevel( "myAlgorithmString = " + myAlgorithmString, 4 );
1680
1681 myAlgorithm = QgsContrastEnhancement::contrastEnhancementAlgorithmFromString( myAlgorithmString );
1682
1683 const QString myLimitsString = mySettings.value( "/Raster/defaultContrastEnhancementLimits/" + key, defaultLimits ).toString();
1684 QgsDebugMsgLevel( "myLimitsString = " + myLimitsString, 4 );
1685 myLimits = QgsRasterMinMaxOrigin::limitsFromString( myLimitsString );
1686
1687 return true;
1688}
1689
1691{
1693
1694 QgsDebugMsgLevel( QStringLiteral( "Entered" ), 4 );
1695
1697 Qgis::RasterRangeLimit myLimits;
1698 defaultContrastEnhancementSettings( myAlgorithm, myLimits );
1699
1700 setContrastEnhancement( myAlgorithm, myLimits );
1701}
1702
1703void QgsRasterLayer::setLayerOrder( QStringList const &layers )
1704{
1706
1707 QgsDebugMsgLevel( QStringLiteral( "entered." ), 4 );
1708
1709 if ( mDataProvider )
1710 {
1711 QgsDebugMsgLevel( QStringLiteral( "About to mDataProvider->setLayerOrder(layers)." ), 4 );
1712 mDataProvider->setLayerOrder( layers );
1713 }
1714
1715}
1716
1717void QgsRasterLayer::setSubLayerVisibility( const QString &name, bool vis )
1718{
1720
1721 if ( mDataProvider )
1722 {
1723 QgsDebugMsgLevel( QStringLiteral( "About to mDataProvider->setSubLayerVisibility(name, vis)." ), 4 );
1724 mDataProvider->setSubLayerVisibility( name, vis );
1725 }
1726}
1727
1729{
1731
1732 if ( !mDataProvider )
1733 return QDateTime();
1734 return mDataProvider->timestamp();
1735}
1736
1738{
1740
1741 if ( auto *lRenderer = mPipe->renderer() )
1742 {
1743 if ( !lRenderer->accept( visitor ) )
1744 return false;
1745 }
1746 return true;
1747}
1748
1750{
1752
1753 return mLabelsEnabled && static_cast< bool >( mLabeling );
1754}
1755
1757{
1759
1760 mLabelsEnabled = enabled;
1761}
1762
1764{
1766
1767 return mLabeling.get();
1768}
1769
1776
1778{
1780
1781 if ( mLabeling.get() == labeling )
1782 return;
1783
1784 mLabeling.reset( labeling );
1786}
1787
1788bool QgsRasterLayer::writeSld( QDomNode &node, QDomDocument &doc, QString &, const QVariantMap &props ) const
1789{
1791 QgsSldExportContext context;
1792 context.setExtraProperties( props );
1793 writeSld( node, doc, context );
1794 return true;
1795}
1796
1797bool QgsRasterLayer::writeSld( QDomNode &node, QDomDocument &doc, QgsSldExportContext &context ) const
1798{
1800
1801 QVariantMap localProps = context.extraProperties();
1803 {
1804 // TODO: QgsSymbolLayerUtils::mergeScaleDependencies generate SE only and not SLD1.0
1806 }
1807 context.setExtraProperties( localProps );
1808
1809 if ( isSpatial() ) // TODO: does it make sense this control?
1810 {
1811 // store constraints
1812 QDomElement constraintElem = doc.createElement( QStringLiteral( "sld:LayerFeatureConstraints" ) );
1813 node.appendChild( constraintElem );
1814
1815 const QDomElement featureTypeConstraintElem = doc.createElement( QStringLiteral( "sld:FeatureTypeConstraint" ) );
1816 constraintElem.appendChild( featureTypeConstraintElem );
1817
1818 QDomElement userStyleElem = doc.createElement( QStringLiteral( "sld:UserStyle" ) );
1819 node.appendChild( userStyleElem );
1820
1821 if ( !name().isEmpty() )
1822 {
1823 QDomElement nameElem = doc.createElement( QStringLiteral( "sld:Name" ) );
1824 nameElem.appendChild( doc.createTextNode( name() ) );
1825 userStyleElem.appendChild( nameElem );
1826 }
1827
1828 const QString abstract = !metadata().abstract().isEmpty() ? metadata().abstract() : serverProperties()->abstract();
1829 if ( !abstract.isEmpty() )
1830 {
1831 QDomElement abstractElem = doc.createElement( QStringLiteral( "sld:Abstract" ) );
1832 abstractElem.appendChild( doc.createTextNode( abstract ) );
1833 userStyleElem.appendChild( abstractElem );
1834 }
1835
1836 const QString title = !metadata().title().isEmpty() ? metadata().title() : serverProperties()->title();
1837 if ( !title.isEmpty() )
1838 {
1839 QDomElement titleElem = doc.createElement( QStringLiteral( "sld:Title" ) );
1840 titleElem.appendChild( doc.createTextNode( title ) );
1841 userStyleElem.appendChild( titleElem );
1842 }
1843
1844 QDomElement featureTypeStyleElem = doc.createElement( QStringLiteral( "sld:FeatureTypeStyle" ) );
1845 userStyleElem.appendChild( featureTypeStyleElem );
1846
1847#if 0
1848 // TODO: Is there a way to fill it's value with the named style?
1849 // by default <sld:Name> under <sld:FeatureTypeStyle> can have 0 occurrences
1850 // the same happen for tags:
1851 // sld:Title
1852 // sld:Abstract
1853 // sld:FeatureTypeName
1854 // sld:SemanticTypeIdentifier
1855 QDomElement typeStyleNameElem = doc.createElement( QStringLiteral( "sld:Name" ) );
1856 featureTypeStyleElem.appendChild( typeStyleNameElem );
1857#endif
1858
1859 QDomElement typeStyleRuleElem = doc.createElement( QStringLiteral( "sld:Rule" ) );
1860 featureTypeStyleElem.appendChild( typeStyleRuleElem );
1861
1862 // add ScaleDenominator tags
1864 {
1865 // note that denominator is the inverted value of scale
1866 if ( maximumScale() != 0.0 )
1867 {
1868 QDomElement minScaleElem = doc.createElement( QStringLiteral( "sld:MinScaleDenominator" ) );
1869 minScaleElem.appendChild( doc.createTextNode( QString::number( maximumScale() ) ) );
1870 typeStyleRuleElem.appendChild( minScaleElem );
1871 }
1872
1873 QDomElement maxScaleElem = doc.createElement( QStringLiteral( "sld:MaxScaleDenominator" ) );
1874 maxScaleElem.appendChild( doc.createTextNode( QString::number( minimumScale() ) ) );
1875 typeStyleRuleElem.appendChild( maxScaleElem );
1876 }
1877
1878 // export renderer dependent tags
1879 mPipe->renderer()->toSld( doc, typeStyleRuleElem, context );
1880
1881 // inject raster layer parameters in RasterSymbolizer tag because
1882 // they belongs to rasterlayer and not to the renderer => avoid to
1883 // pass many parameters value via localProps
1884 const QDomNodeList elements = typeStyleRuleElem.elementsByTagName( QStringLiteral( "sld:RasterSymbolizer" ) );
1885 if ( elements.size() != 0 )
1886 {
1887 // there SHOULD be only one
1888 QDomElement rasterSymbolizerElem = elements.at( 0 ).toElement();
1889
1890 // lamda helper used below to reduce code redundancy
1891 auto vendorOptionWriter = [&]( QString name, QString value )
1892 {
1893 QDomElement vendorOptionElem = doc.createElement( QStringLiteral( "sld:VendorOption" ) );
1894 vendorOptionElem.setAttribute( QStringLiteral( "name" ), name );
1895 vendorOptionElem.appendChild( doc.createTextNode( value ) );
1896 rasterSymbolizerElem.appendChild( vendorOptionElem );
1897 };
1898
1899 if ( hueSaturationFilter()->invertColors() )
1900 {
1901 vendorOptionWriter( QStringLiteral( "invertColors" ), QString::number( 1 ) );
1902 }
1903
1904 // add greyScale rendering mode if set
1906 {
1907 QString property;
1908 switch ( hueSaturationFilter()->grayscaleMode() )
1909 {
1911 property = QStringLiteral( "lightness" );
1912 break;
1914 property = QStringLiteral( "luminosity" );
1915 break;
1917 property = QStringLiteral( "average" );
1918 break;
1920 // added just to avoid travis fail
1921 break;
1922 }
1923 if ( !property.isEmpty() )
1924 vendorOptionWriter( QStringLiteral( "grayScale" ), property );
1925 }
1926
1927 // add Hue, Saturation and Lighting values in props is Hue filter is set
1928 if ( hueSaturationFilter() && hueSaturationFilter()->colorizeOn() )
1929 {
1930 vendorOptionWriter( QStringLiteral( "colorizeOn" ), QString::number( hueSaturationFilter()->colorizeOn() ) );
1931 vendorOptionWriter( QStringLiteral( "colorizeRed" ), QString::number( hueSaturationFilter()->colorizeColor().red() ) );
1932 vendorOptionWriter( QStringLiteral( "colorizeGreen" ), QString::number( hueSaturationFilter()->colorizeColor().green() ) );
1933 vendorOptionWriter( QStringLiteral( "colorizeBlue" ), QString::number( hueSaturationFilter()->colorizeColor().blue() ) );
1934 if ( hueSaturationFilter()->colorizeStrength() != 100.0 )
1935 vendorOptionWriter( QStringLiteral( "colorizeStrength" ), QString::number( hueSaturationFilter()->colorizeStrength() / 100.0 ) );
1936 vendorOptionWriter( QStringLiteral( "saturation" ), QString::number( hueSaturationFilter()->colorizeColor().saturationF() ) );
1937 }
1938 else
1939 {
1940 // saturation != 0 (default value)
1941 if ( hueSaturationFilter()->saturation() != 0 )
1942 {
1943 // normlize value [-100:100] -> [0:1]
1944 const int s = hueSaturationFilter()->saturation();
1945 const double sF = ( s - ( -100.0 ) ) / ( 100.0 - ( -100.0 ) );
1946 vendorOptionWriter( QStringLiteral( "saturation" ), QString::number( sF ) );
1947 }
1948 }
1949
1950 // brightness != 0 (default value)
1951 if ( brightnessFilter()->brightness() != 0 )
1952 {
1953 // normalize value [-255:255] -> [0:1]
1954 const int b = brightnessFilter()->brightness();
1955 const double bF = ( b - ( -255.0 ) ) / ( 255.0 - ( -255.0 ) );
1956 vendorOptionWriter( QStringLiteral( "brightness" ), QString::number( bF ) );
1957 }
1958
1959 // contrast != 0 (default value)
1960 if ( brightnessFilter()->contrast() != 0 )
1961 {
1962 // normlize value [-100:100] -> [0:1]
1963 const int c = brightnessFilter()->contrast();
1964 const double cF = ( c - ( -100.0 ) ) / ( 100.0 - ( -100.0 ) );
1965 vendorOptionWriter( QStringLiteral( "contrast" ), QString::number( cF ) );
1966 }
1967
1968#if 0
1969 // TODO: check if the below mapping formula make sense to map QGIS contrast with SLD gamma value
1970 // add SLD1.0 ContrastEnhancement GammaValue = QGIS Contrast
1971 // SLD1.0 does only define 1 as neutral/center double value but does not define range.
1972 // because https://en.wikipedia.org/wiki/Gamma_correction assumed gamma is >0.
1973 // whilst QGIS has a -100/100 values centered in 0 => QGIS contrast value will be scaled in the
1974 // following way:
1975 // [-100,0] => [0,1] and [0,100] => [1,100]
1976 // an alternative could be scale [-100,100] => (0,2]
1977 //
1978 if ( newProps.contains( QStringLiteral( "contrast" ) ) )
1979 {
1980 double gamma;
1981 double contrast = newProps[ QStringLiteral( "contrast" ) ].toDouble();
1982 double percentage = ( contrast - ( -100.0 ) ) / ( 100.0 - ( -100.0 ) );
1983 if ( percentage <= 0.5 )
1984 {
1985 // stretch % to [0-1]
1986 gamma = percentage / 0.5;
1987 }
1988 else
1989 {
1990 gamma = contrast;
1991 }
1992
1993 QDomElement globalContrastEnhancementElem = doc.createElement( QStringLiteral( "sld:ContrastEnhancement" ) );
1994 rasterSymolizerElem.appendChild( globalContrastEnhancementElem );
1995
1996 QDomElement gammaValueElem = doc.createElement( QStringLiteral( "sld:GammaValue" ) );
1997 gammaValueElem.appendChild( doc.createTextNode( QString::number( gamma ) ) );
1998 globalContrastEnhancementElem.appendChild( gammaValueElem );
1999 }
2000#endif
2001 }
2002 }
2003 return true;
2004}
2005
2007{
2009
2010 QgsDebugMsgLevel( QStringLiteral( "Entered" ), 4 );
2011 if ( !renderer )
2012 {
2013 return;
2014 }
2015
2016 mPipe->set( renderer );
2017 emit rendererChanged();
2019}
2020
2022{
2024
2025 return mPipe->renderer();
2026}
2027
2029{
2031
2032 return mPipe->resampleFilter();
2033}
2034
2036{
2038
2039 return mPipe->brightnessFilter();
2040}
2041
2043{
2045
2046 return mPipe->hueSaturationFilter();
2047}
2048
2049void QgsRasterLayer::showStatusMessage( QString const &message )
2050{
2052
2053 // QgsDebugMsgLevel(QString("entered with '%1'.").arg(theMessage), 2);
2054
2055 // Pass-through
2056 // TODO: See if we can connect signal-to-signal. This is a kludge according to the Qt doc.
2057 emit statusChanged( message );
2058}
2059
2061{
2063
2064 if ( mDataProvider )
2065 mDataProvider->setTransformContext( transformContext );
2067}
2068
2069QStringList QgsRasterLayer::subLayers() const
2070{
2072
2073 if ( ! mDataProvider )
2074 return QStringList();
2075 return mDataProvider->subLayers();
2076}
2077
2078// this function should be used when rendering with the MTR engine introduced in 2.3, as QPixmap is not thread safe (see bug #9626)
2079// note: previewAsImage and previewAsPixmap should use a common low-level fct QgsRasterLayer::previewOnPaintDevice( QSize size, QColor bgColor, QPaintDevice &device )
2080QImage QgsRasterLayer::previewAsImage( QSize size, const QColor &bgColor, QImage::Format format )
2081{
2083
2084 QImage image( size, format );
2085
2086 if ( ! isValid( ) )
2087 return QImage();
2088
2089 if ( image.format() == QImage::Format_Indexed8 )
2090 {
2091 image.setColor( 0, bgColor.rgba() );
2092 image.fill( 0 ); //defaults to white, set to transparent for rendering on a map
2093 }
2094 else
2095 {
2096 image.fill( bgColor );
2097 }
2098
2099 QgsRasterViewPort *rasterViewPort = new QgsRasterViewPort();
2100
2101 double mapUnitsPerPixel;
2102 double x = 0.0;
2103 double y = 0.0;
2104 const QgsRectangle extent = mDataProvider->extent();
2105 if ( extent.width() / extent.height() >= static_cast< double >( image.width() ) / image.height() )
2106 {
2107 mapUnitsPerPixel = extent.width() / image.width();
2108 y = ( image.height() - extent.height() / mapUnitsPerPixel ) / 2;
2109 }
2110 else
2111 {
2112 mapUnitsPerPixel = extent.height() / image.height();
2113 x = ( image.width() - extent.width() / mapUnitsPerPixel ) / 2;
2114 }
2115
2116 const double pixelWidth = extent.width() / mapUnitsPerPixel;
2117 const double pixelHeight = extent.height() / mapUnitsPerPixel;
2118
2119 rasterViewPort->mTopLeftPoint = QgsPointXY( x, y );
2120 rasterViewPort->mBottomRightPoint = QgsPointXY( pixelWidth, pixelHeight );
2121 rasterViewPort->mWidth = image.width();
2122 rasterViewPort->mHeight = image.height();
2123
2124 rasterViewPort->mDrawnExtent = extent;
2125 rasterViewPort->mSrcCRS = QgsCoordinateReferenceSystem(); // will be invalid
2126 rasterViewPort->mDestCRS = QgsCoordinateReferenceSystem(); // will be invalid
2127
2128 QgsMapToPixel *mapToPixel = new QgsMapToPixel( mapUnitsPerPixel );
2129
2130 QPainter *painter = new QPainter( &image );
2131 draw( painter, rasterViewPort, mapToPixel );
2132 delete rasterViewPort;
2133 delete mapToPixel;
2134
2135 painter->end();
2136 delete painter;
2137
2138 return image;
2139}
2140
2141bool QgsRasterLayer::readSymbology( const QDomNode &layer_node, QString &errorMessage,
2143{
2145
2146 Q_UNUSED( errorMessage )
2147 // TODO: implement categories for raster layer
2148
2149 QDomElement rasterRendererElem;
2150
2151 const QDomElement layerElement = layer_node.toElement();
2152 readCommonStyle( layerElement, context, categories );
2153
2154 // pipe considers Symbology and Rendering components, why it's always handled as one
2155 if ( categories.testFlag( Symbology ) || categories.testFlag( Rendering ) )
2156 {
2157 // pipe element was introduced in the end of 1.9 development when there were
2158 // already many project files in use so we support 1.9 backward compatibility
2159 // even it was never officially released -> use pipe element if present, otherwise
2160 // use layer node
2161 QDomNode pipeNode = layer_node.firstChildElement( QStringLiteral( "pipe" ) );
2162 if ( pipeNode.isNull() ) // old project
2163 {
2164 pipeNode = layer_node;
2165 }
2166
2167 //rasterlayerproperties element there -> old format (1.8 and early 1.9)
2168 if ( !layer_node.firstChildElement( QStringLiteral( "rasterproperties" ) ).isNull() )
2169 {
2170 //copy node because layer_node is const
2171 QDomNode layerNodeCopy = layer_node.cloneNode();
2172 QDomDocument doc = layerNodeCopy.ownerDocument();
2173 QDomElement rasterPropertiesElem = layerNodeCopy.firstChildElement( QStringLiteral( "rasterproperties" ) );
2174 QgsProjectFileTransform::convertRasterProperties( doc, layerNodeCopy, rasterPropertiesElem,
2175 this );
2176 rasterRendererElem = layerNodeCopy.firstChildElement( QStringLiteral( "rasterrenderer" ) );
2177 QgsDebugMsgLevel( doc.toString(), 4 );
2178 }
2179 else
2180 {
2181 rasterRendererElem = pipeNode.firstChildElement( QStringLiteral( "rasterrenderer" ) );
2182 }
2183
2184 if ( !rasterRendererElem.isNull() )
2185 {
2186 const QString rendererType = rasterRendererElem.attribute( QStringLiteral( "type" ) );
2187 QgsRasterRendererRegistryEntry rendererEntry;
2188 if ( mDataProvider && QgsApplication::rasterRendererRegistry()->rendererData( rendererType, rendererEntry ) )
2189 {
2190 QgsRasterRenderer *renderer = rendererEntry.rendererCreateFunction( rasterRendererElem, mDataProvider );
2191 mPipe->set( renderer );
2192 }
2193 }
2194
2195 //brightness
2197 if ( mPipe->set( brightnessFilter ) )
2198 {
2199 const QDomElement brightnessElem = pipeNode.firstChildElement( QStringLiteral( "brightnesscontrast" ) );
2200 if ( !brightnessElem.isNull() )
2201 {
2202 brightnessFilter->readXml( brightnessElem );
2203 }
2204 }
2205
2206 //hue/saturation
2208 if ( mPipe->set( hueSaturationFilter ) )
2209 {
2210 const QDomElement hueSaturationElem = pipeNode.firstChildElement( QStringLiteral( "huesaturation" ) );
2211 if ( !hueSaturationElem.isNull() )
2212 {
2213 hueSaturationFilter->readXml( hueSaturationElem );
2214 }
2215 }
2216
2217 //resampler
2219 if ( mPipe->set( resampleFilter ) )
2220 {
2221 const QDomElement resampleElem = pipeNode.firstChildElement( QStringLiteral( "rasterresampler" ) );
2222 if ( !resampleElem.isNull() )
2223 {
2224 resampleFilter->readXml( resampleElem );
2225 }
2226 }
2227
2228 //provider
2229 if ( mDataProvider )
2230 {
2231 const QDomElement providerElem = pipeNode.firstChildElement( QStringLiteral( "provider" ) );
2232 if ( !providerElem.isNull() )
2233 {
2234 mDataProvider->readXml( providerElem );
2235 }
2236 }
2237
2238 // Resampling stage
2239 const QDomNode resamplingStageElement = pipeNode.namedItem( QStringLiteral( "resamplingStage" ) );
2240 if ( !resamplingStageElement.isNull() )
2241 {
2242 const QDomElement e = resamplingStageElement.toElement();
2243 if ( e.text() == QLatin1String( "provider" ) )
2245 else if ( e.text() == QLatin1String( "resamplingFilter" ) )
2247 }
2248
2249 // get and set the blend mode if it exists
2250 const QDomNode blendModeNode = layer_node.namedItem( QStringLiteral( "blendMode" ) );
2251 if ( !blendModeNode.isNull() )
2252 {
2253 const QDomElement e = blendModeNode.toElement();
2254 setBlendMode( QgsPainting::getCompositionMode( static_cast< Qgis::BlendMode >( e.text().toInt() ) ) );
2255 }
2256
2257 const QDomElement elemDataDefinedProperties = layer_node.firstChildElement( QStringLiteral( "pipe-data-defined-properties" ) );
2258 if ( !elemDataDefinedProperties.isNull() )
2259 mPipe->dataDefinedProperties().readXml( elemDataDefinedProperties, QgsRasterPipe::propertyDefinitions() );
2260 }
2261
2262 // read labeling definition
2263 if ( categories.testFlag( Labeling ) )
2264 {
2265 QgsReadWriteContextCategoryPopper p = context.enterCategory( tr( "Labeling" ) );
2266
2267 QDomElement labelingElement = layer_node.firstChildElement( QStringLiteral( "labeling" ) );
2268 if ( !labelingElement.isNull() )
2269 {
2271 mLabelsEnabled = layer_node.toElement().attribute( QStringLiteral( "labelsEnabled" ), QStringLiteral( "0" ) ).toInt();
2273 }
2274 }
2275
2276 if ( categories.testFlag( MapTips ) )
2277 {
2278 QDomElement mapTipElem = layer_node.namedItem( QStringLiteral( "mapTip" ) ).toElement();
2279 setMapTipTemplate( mapTipElem.text() );
2280 setMapTipsEnabled( mapTipElem.attribute( QStringLiteral( "enabled" ), QStringLiteral( "1" ) ).toInt() == 1 );
2281 }
2282
2283 // read attribute table attribute table paths
2284 if ( categories.testFlag( AttributeTable ) )
2285 {
2286 readRasterAttributeTableExternalPaths( layer_node, context );
2287 }
2288
2289 if ( categories.testFlag( Legend ) )
2290 {
2291 QgsReadWriteContextCategoryPopper p = context.enterCategory( tr( "Legend" ) );
2292
2293 const QDomElement legendElem = layer_node.firstChildElement( QStringLiteral( "legend" ) );
2294 QgsMapLayerLegend *rasterLegend = legend();
2295 if ( rasterLegend && !legendElem.isNull() )
2296 {
2297 rasterLegend->readXml( legendElem, context );
2298 }
2299 else if ( rasterLegend )
2300 {
2301 // Temporary fix for #63346 because legend was not saved if empty
2303 }
2304 }
2305
2306 emit rendererChanged();
2308
2309 return true;
2310}
2311
2312bool QgsRasterLayer::readStyle( const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories )
2313{
2315
2316 return readSymbology( node, errorMessage, context, categories );
2317}
2318
2319bool QgsRasterLayer::readXml( const QDomNode &layer_node, QgsReadWriteContext &context )
2320{
2322
2323 QgsDebugMsgLevel( QStringLiteral( "Entered" ), 4 );
2324 // Make sure to read the file first so stats etc are initialized properly!
2325
2326 //process provider key
2327 const QDomNode pkeyNode = layer_node.namedItem( QStringLiteral( "provider" ) );
2328
2329 if ( pkeyNode.isNull() )
2330 {
2331 mProviderKey = QStringLiteral( "gdal" );
2332 }
2333 else
2334 {
2335 const QDomElement pkeyElt = pkeyNode.toElement();
2336 mProviderKey = pkeyElt.text();
2337 if ( mProviderKey.isEmpty() )
2338 {
2339 mProviderKey = QStringLiteral( "gdal" );
2340 }
2341 }
2342
2343 // Open the raster source based on provider and datasource
2344
2345 // Go down the raster-data-provider paradigm
2346
2347 // Collect provider-specific information
2348
2349 const QDomNode rpNode = layer_node.namedItem( QStringLiteral( "rasterproperties" ) );
2350
2351 if ( mProviderKey == QLatin1String( "wms" ) )
2352 {
2353 // >>> BACKWARD COMPATIBILITY < 1.9
2354 // The old WMS URI format does not contain all the information, we add them here.
2355 if ( !mDataSource.contains( QLatin1String( "crs=" ) ) && !mDataSource.contains( QLatin1String( "format=" ) ) )
2356 {
2357 QgsDebugMsgLevel( QStringLiteral( "Old WMS URI format detected -> adding params" ), 4 );
2358 QgsDataSourceUri uri;
2360 QDomElement layerElement = rpNode.firstChildElement( QStringLiteral( "wmsSublayer" ) );
2361 while ( !layerElement.isNull() )
2362 {
2363 // TODO: sublayer visibility - post-0.8 release timeframe
2364
2365 // collect name for the sublayer
2366 uri.setParam( QStringLiteral( "layers" ), layerElement.namedItem( QStringLiteral( "name" ) ).toElement().text() );
2367
2368 // collect style for the sublayer
2369 uri.setParam( QStringLiteral( "styles" ), layerElement.namedItem( QStringLiteral( "style" ) ).toElement().text() );
2370
2371 layerElement = layerElement.nextSiblingElement( QStringLiteral( "wmsSublayer" ) );
2372 }
2373
2374 // Collect format
2375 uri.setParam( QStringLiteral( "format" ), rpNode.namedItem( QStringLiteral( "wmsFormat" ) ).toElement().text() );
2376
2377 // WMS CRS URL param should not be mixed with that assigned to the layer.
2378 // In the old WMS URI version there was no CRS and layer crs().authid() was used.
2379 uri.setParam( QStringLiteral( "crs" ), crs().authid() );
2380 mDataSource = uri.encodedUri();
2381 }
2382 // <<< BACKWARD COMPATIBILITY < 1.9
2383 }
2384
2386 {
2387 const QgsDataProvider::ProviderOptions providerOptions { context.transformContext() };
2389
2391 {
2392 const QDomNode extentNode = layer_node.namedItem( QStringLiteral( "extent" ) );
2393 if ( !extentNode.isNull() )
2394 {
2395 // get the extent
2396 const QgsRectangle mbr = QgsXmlUtils::readRectangle( extentNode.toElement() );
2397
2398 // store the extent
2399 setExtent( mbr );
2400 }
2401 }
2402 setDataProvider( mProviderKey, providerOptions, flags );
2403 }
2404
2405 mOriginalStyleElement = layer_node.namedItem( QStringLiteral( "originalStyle" ) ).firstChildElement();
2406 if ( mOriginalStyleElement.isNull() )
2407 mOriginalStyleElement = layer_node.toElement();
2408 mOriginalStyleDocument = layer_node.ownerDocument();
2409
2410 if ( ! mDataProvider )
2411 {
2413 {
2414 QgsDebugError( QStringLiteral( "Raster data provider could not be created for %1" ).arg( mDataSource ) );
2415 return false;
2416 }
2417 }
2418
2419 QString error;
2420 const bool res = readSymbology( layer_node, error, context );
2421
2422 // old wms settings we need to correct
2423 if ( res && mProviderKey == QLatin1String( "wms" ) && !renderer() )
2424 {
2425 setRendererForDrawingStyle( Qgis::RasterDrawingStyle::SingleBandColorData );
2426 }
2427
2428 // Check timestamp
2429 // This was probably introduced to reload completely raster if data changed and
2430 // reset completely symbology to reflect new data type etc. It creates however
2431 // problems, because user defined symbology is complete lost if data file time
2432 // changed (the content may be the same). See also 6900.
2433#if 0
2434 QDomNode stampNode = layer_node.namedItem( "timestamp" );
2435 if ( !stampNode.isNull() )
2436 {
2437 QDateTime stamp = QDateTime::fromString( stampNode.toElement().text(), Qt::ISODate );
2438 // TODO: very bad, we have to load twice!!! Make QgsDataProvider::timestamp() static?
2439 if ( stamp < mDataProvider->dataTimestamp() )
2440 {
2441 QgsDebugMsgLevel( QStringLiteral( "data changed, reload provider" ), 3 );
2442 closeDataProvider();
2443 init();
2445 if ( !isValid() ) return false;
2446 }
2447 }
2448#endif
2449
2450 // Load user no data value
2451 const QDomElement noDataElement = layer_node.firstChildElement( QStringLiteral( "noData" ) );
2452
2453 const QDomNodeList noDataBandList = noDataElement.elementsByTagName( QStringLiteral( "noDataList" ) );
2454
2455 for ( int i = 0; mDataProvider && i < noDataBandList.size(); ++i )
2456 {
2457 const QDomElement bandElement = noDataBandList.at( i ).toElement();
2458 bool ok;
2459 const int bandNo = bandElement.attribute( QStringLiteral( "bandNo" ) ).toInt( &ok );
2460 QgsDebugMsgLevel( QStringLiteral( "bandNo = %1" ).arg( bandNo ), 4 );
2461 if ( ok && ( bandNo > 0 ) && ( bandNo <= mDataProvider->bandCount() ) )
2462 {
2463 mDataProvider->setUseSourceNoDataValue( bandNo, bandElement.attribute( QStringLiteral( "useSrcNoData" ) ).toInt() );
2464 QgsRasterRangeList myNoDataRangeList;
2465
2466 const QDomNodeList rangeList = bandElement.elementsByTagName( QStringLiteral( "noDataRange" ) );
2467
2468 myNoDataRangeList.reserve( rangeList.size() );
2469 for ( int j = 0; j < rangeList.size(); ++j )
2470 {
2471 const QDomElement rangeElement = rangeList.at( j ).toElement();
2472 const QgsRasterRange myNoDataRange( rangeElement.attribute( QStringLiteral( "min" ) ).toDouble(),
2473 rangeElement.attribute( QStringLiteral( "max" ) ).toDouble() );
2474 QgsDebugMsgLevel( QStringLiteral( "min = %1 %2" ).arg( rangeElement.attribute( "min" ) ).arg( myNoDataRange.min() ), 4 );
2475 myNoDataRangeList << myNoDataRange;
2476 }
2477 mDataProvider->setUserNoDataValue( bandNo, myNoDataRangeList );
2478 }
2479 }
2480
2481 readRasterAttributeTableExternalPaths( layer_node, context );
2482
2483 readStyleManager( layer_node );
2484
2485 return res;
2486}
2487
2488bool QgsRasterLayer::writeSymbology( QDomNode &layer_node, QDomDocument &document, QString &errorMessage,
2489 const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
2490{
2492
2493 Q_UNUSED( errorMessage )
2494 // TODO: implement categories for raster layer
2495
2496 QDomElement layerElement = layer_node.toElement();
2497
2498 writeCommonStyle( layerElement, document, context, categories );
2499
2500 if ( categories.testFlag( Labeling ) )
2501 {
2502 if ( mLabeling )
2503 {
2504 QDomElement labelingElement = mLabeling->save( document, context );
2505 layerElement.appendChild( labelingElement );
2506 }
2507 if ( mLabelsEnabled )
2508 layerElement.setAttribute( QStringLiteral( "labelsEnabled" ), QStringLiteral( "1" ) );
2509 }
2510
2511 // save map tip
2512 if ( categories.testFlag( MapTips ) )
2513 {
2514 QDomElement mapTipElem = document.createElement( QStringLiteral( "mapTip" ) );
2515 mapTipElem.setAttribute( QStringLiteral( "enabled" ), mapTipsEnabled() );
2516 QDomText mapTipText = document.createTextNode( mapTipTemplate() );
2517 mapTipElem.appendChild( mapTipText );
2518 layer_node.toElement().appendChild( mapTipElem );
2519 }
2520
2521 // save attribute table attribute table paths
2522 if ( categories.testFlag( AttributeTable ) )
2523 {
2524 writeRasterAttributeTableExternalPaths( layer_node, document, context );
2525 }
2526
2527 // pipe considers Symbology and Rendering components, why it's always handled as one
2528 if ( categories.testFlag( Symbology ) || categories.testFlag( Rendering ) )
2529 {
2530 // Store pipe members into pipe element, in future, it will be
2531 // possible to add custom filters into the pipe
2532 QDomElement pipeElement = document.createElement( QStringLiteral( "pipe" ) );
2533
2534 for ( int i = 0; i < mPipe->size(); i++ )
2535 {
2536 QgsRasterInterface *interface = mPipe->at( i );
2537 if ( !interface ) continue;
2538 interface->writeXml( document, pipeElement );
2539 }
2540
2541 QDomElement elemDataDefinedProperties = document.createElement( QStringLiteral( "pipe-data-defined-properties" ) );
2542 mPipe->dataDefinedProperties().writeXml( elemDataDefinedProperties, QgsRasterPipe::propertyDefinitions() );
2543 layer_node.appendChild( elemDataDefinedProperties );
2544
2545 QDomElement resamplingStageElement = document.createElement( QStringLiteral( "resamplingStage" ) );
2546 const QDomText resamplingStageText = document.createTextNode( resamplingStage() == Qgis::RasterResamplingStage::Provider ? QStringLiteral( "provider" ) : QStringLiteral( "resamplingFilter" ) );
2547 resamplingStageElement.appendChild( resamplingStageText );
2548 pipeElement.appendChild( resamplingStageElement );
2549
2550 layer_node.appendChild( pipeElement );
2551
2552 if ( !isValid() && !mOriginalStyleElement.isNull() )
2553 {
2554 QDomElement originalStyleElement = document.createElement( QStringLiteral( "originalStyle" ) );
2555 originalStyleElement.appendChild( mOriginalStyleElement );
2556 layer_node.appendChild( originalStyleElement );
2557 }
2558
2559 // add blend mode node
2560 QDomElement blendModeElement = document.createElement( QStringLiteral( "blendMode" ) );
2561 const QDomText blendModeText = document.createTextNode( QString::number( static_cast< int >( QgsPainting::getBlendModeEnum( blendMode() ) ) ) );
2562 blendModeElement.appendChild( blendModeText );
2563 layer_node.appendChild( blendModeElement );
2564 }
2565
2566 if ( categories.testFlag( Legend ) && legend() )
2567 {
2568 QDomElement legendElement = legend()->writeXml( document, context );
2569 if ( !legendElement.isNull() )
2570 layer_node.appendChild( legendElement );
2571 }
2572
2573 return true;
2574}
2575
2576bool QgsRasterLayer::writeStyle( QDomNode &node, QDomDocument &doc, QString &errorMessage,
2577 const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
2578{
2580
2581 return writeSymbology( node, doc, errorMessage, context, categories );
2582}
2583
2584bool QgsRasterLayer::writeXml( QDomNode &layer_node,
2585 QDomDocument &document,
2586 const QgsReadWriteContext &context ) const
2587{
2589
2590 if ( !mDataProvider )
2591 return false;
2592
2593 // first get the layer element so that we can append the type attribute
2594
2595 QDomElement mapLayerNode = layer_node.toElement();
2596
2597 if ( mapLayerNode.isNull() || "maplayer" != mapLayerNode.nodeName() )
2598 {
2599 QgsMessageLog::logMessage( tr( "<maplayer> not found." ), tr( "Raster" ) );
2600 return false;
2601 }
2602
2603 mapLayerNode.setAttribute( QStringLiteral( "type" ), QgsMapLayerFactory::typeToString( Qgis::LayerType::Raster ) );
2604
2605 // add provider node
2606
2607 QDomElement provider = document.createElement( QStringLiteral( "provider" ) );
2608 const QDomText providerText = document.createTextNode( mProviderKey );
2609 provider.appendChild( providerText );
2610 layer_node.appendChild( provider );
2611
2612 // User no data
2613 QDomElement noData = document.createElement( QStringLiteral( "noData" ) );
2614
2615 for ( int bandNo = 1; bandNo <= mDataProvider->bandCount(); bandNo++ )
2616 {
2617 QDomElement noDataRangeList = document.createElement( QStringLiteral( "noDataList" ) );
2618 noDataRangeList.setAttribute( QStringLiteral( "bandNo" ), bandNo );
2619 noDataRangeList.setAttribute( QStringLiteral( "useSrcNoData" ), mDataProvider->useSourceNoDataValue( bandNo ) );
2620
2621 const auto constUserNoDataValues = mDataProvider->userNoDataValues( bandNo );
2622 for ( const QgsRasterRange &range : constUserNoDataValues )
2623 {
2624 QDomElement noDataRange = document.createElement( QStringLiteral( "noDataRange" ) );
2625
2626 noDataRange.setAttribute( QStringLiteral( "min" ), QgsRasterBlock::printValue( range.min() ) );
2627 noDataRange.setAttribute( QStringLiteral( "max" ), QgsRasterBlock::printValue( range.max() ) );
2628 noDataRangeList.appendChild( noDataRange );
2629 }
2630
2631 noData.appendChild( noDataRangeList );
2632
2633 }
2634 if ( noData.hasChildNodes() )
2635 {
2636 layer_node.appendChild( noData );
2637 }
2638
2639 // Store file-based raster attribute table paths (if any)
2640 writeRasterAttributeTableExternalPaths( layer_node, document, context );
2641
2642 writeStyleManager( layer_node, document );
2643
2644 //write out the symbology
2645 QString errorMsg;
2646 return writeSymbology( layer_node, document, errorMsg, context );
2647}
2648
2649
2656
2657QString QgsRasterLayer::decodedSource( const QString &source, const QString &provider, const QgsReadWriteContext &context ) const
2658{
2660
2661 return QgsProviderRegistry::instance()->relativeToAbsoluteUri( provider, source, context );
2662}
2663
2665{
2667
2668 if ( !mDataProvider ) return 0;
2669 return mDataProvider->xSize();
2670}
2671
2673{
2675
2676 if ( !mDataProvider ) return 0;
2677 return mDataProvider->ySize();
2678}
2679
2681{
2683
2684 mPipe->setResamplingStage( stage );
2685}
2686
2688{
2690
2691 return mPipe->resamplingStage();
2692}
2693
2694bool QgsRasterLayer::update()
2695{
2697
2698 QgsDebugMsgLevel( QStringLiteral( "entered." ), 4 );
2699 // Check if data changed
2700 if ( mDataProvider && mDataProvider->dataTimestamp() > mDataProvider->timestamp() )
2701 {
2702 QgsDebugMsgLevel( QStringLiteral( "reload data" ), 4 );
2703 closeDataProvider();
2704 init();
2705 const QgsDataProvider::ProviderOptions providerOptions;
2708 {
2710 }
2711 setDataProvider( mProviderKey, providerOptions, flags );
2712 emit dataChanged();
2713 }
2714 return isValid();
2715}
2716
2717#undef ERR
Provides global constants and enumerations for use throughout the application.
Definition qgis.h:56
static QString version()
Version string.
Definition qgis.cpp:677
@ IsBasemapLayer
Layer is considered a 'basemap' layer, and certain properties of the layer should be ignored when cal...
Definition qgis.h:2281
RasterResamplingStage
Stage at which raster resampling occurs.
Definition qgis.h:1470
@ Provider
Resampling occurs in Provider.
Definition qgis.h:1472
@ ResampleFilter
Resampling occurs in ResamplingFilter.
Definition qgis.h:1471
@ ProviderHintBenefitsFromResampling
Provider benefits from resampling and should apply user default resampling settings.
Definition qgis.h:4890
@ ProviderHintCanPerformProviderResampling
Provider can perform resampling (to be opposed to post rendering resampling).
Definition qgis.h:4891
@ ReadLayerMetadata
Provider can read layer metadata from data store. Since QGIS 3.0. See QgsDataProvider::layerMetadata(...
Definition qgis.h:4888
@ Palette
Palette.
Definition qgis.h:4765
@ MultiBand
Multi band.
Definition qgis.h:4766
@ SingleBandColorData
Single band containing color data.
Definition qgis.h:4767
@ GrayOrUndefined
Gray or undefined.
Definition qgis.h:4764
RasterRangeLimit
Describes the limits used to compute raster ranges (min/max values).
Definition qgis.h:1544
@ CumulativeCut
Range is [ min + cumulativeCutLower() * (max - min), min + cumulativeCutUpper() * (max - min) ].
Definition qgis.h:1548
@ StdDev
Range is [ mean - stdDevFactor() * stddev, mean + stdDevFactor() * stddev ].
Definition qgis.h:1547
@ MinimumMaximum
Real min-max values.
Definition qgis.h:1546
@ NotSet
User defined.
Definition qgis.h:1545
@ Linear
Interpolates the color between two class breaks linearly.
Definition qgis.h:1426
@ Discrete
Assigns the color of the higher class for every pixel between two class breaks.
Definition qgis.h:1427
@ IsBasemapSource
Associated source should be considered a 'basemap' layer. See Qgis::MapLayerProperty::IsBasemapLayer.
Definition qgis.h:2309
@ Bilinear
Bilinear (2x2 kernel) resampling.
Definition qgis.h:1486
@ Cubic
Cubic Convolution Approximation (4x4 kernel) resampling.
Definition qgis.h:1487
RasterDrawingStyle
Raster drawing styles.
Definition qgis.h:4779
@ SingleBandGray
A single band image drawn as a range of gray colors.
Definition qgis.h:4781
@ SingleBandColorData
ARGB values rendered directly.
Definition qgis.h:4790
@ MultiBandColor
A layer containing 2 or more bands, mapped to RGB color space. In the case of a multiband with only t...
Definition qgis.h:4789
@ PalettedColor
A "Palette" image drawn using color table.
Definition qgis.h:4783
@ SingleBandPseudoColor
A single band image drawn using a pseudocolor algorithm.
Definition qgis.h:4782
@ Undefined
Undefined.
Definition qgis.h:4780
QFlags< RasterInterfaceCapability > RasterInterfaceCapabilities
Raster interface capabilities.
Definition qgis.h:4873
BlendMode
Blending modes defining the available composition modes that can be used when painting.
Definition qgis.h:4930
@ Size
Original data source size (and thus resolution) is known, it is not always available,...
Definition qgis.h:4855
@ IdentifyValue
Numerical values.
Definition qgis.h:4860
@ IdentifyFeature
WMS GML -> feature.
Definition qgis.h:4863
QFlags< DataProviderReadFlag > DataProviderReadFlags
Flags which control data provider construction.
Definition qgis.h:486
@ ExcludeByDefault
If set, the layer should not be included in legends by default, and must be manually added by a user.
Definition qgis.h:4555
@ StdDev
Standard deviation.
Definition qgis.h:5946
@ NoStatistic
No statistic.
Definition qgis.h:5940
DataType
Raster data types.
Definition qgis.h:372
@ CInt32
Complex Int32.
Definition qgis.h:383
@ Float32
Thirty two bit floating point (float).
Definition qgis.h:380
@ CFloat64
Complex Float64.
Definition qgis.h:385
@ Int16
Sixteen bit signed integer (qint16).
Definition qgis.h:377
@ ARGB32_Premultiplied
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32_Premultiplied.
Definition qgis.h:387
@ Int8
Eight bit signed integer (qint8) (added in QGIS 3.30).
Definition qgis.h:375
@ UInt16
Sixteen bit unsigned integer (quint16).
Definition qgis.h:376
@ Byte
Eight bit unsigned integer (quint8).
Definition qgis.h:374
@ UnknownDataType
Unknown or unspecified type.
Definition qgis.h:373
@ ARGB32
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32.
Definition qgis.h:386
@ Int32
Thirty two bit signed integer (qint32).
Definition qgis.h:379
@ Float64
Sixty four bit floating point (double).
Definition qgis.h:381
@ CFloat32
Complex Float32.
Definition qgis.h:384
@ CInt16
Complex Int16.
Definition qgis.h:382
@ UInt32
Thirty two bit unsigned integer (quint32).
Definition qgis.h:378
@ Raster
Raster layer.
Definition qgis.h:192
@ WholeRaster
Whole raster is used to compute statistics.
Definition qgis.h:1561
@ FixedCanvas
Current extent of the canvas (at the time of computation) is used to compute statistics.
Definition qgis.h:1562
QFlags< MapLayerProperty > MapLayerProperties
Map layer properties.
Definition qgis.h:2285
@ LoadDefaultStyle
Reset the layer's style to the default for the datasource.
Definition qgis.h:470
@ SkipGetExtent
Skip the extent from provider.
Definition qgis.h:471
@ TrustDataSource
Trust datasource config (primary key unicity, geometry type and srid, etc). Improves provider load ti...
Definition qgis.h:468
RasterColorInterpretation
Raster color interpretation.
Definition qgis.h:4712
@ AlphaBand
Alpha (0=transparent, 255=opaque).
Definition qgis.h:4719
@ PaletteIndex
Paletted (see associated color table).
Definition qgis.h:4715
@ ContinuousPalette
Continuous palette, QGIS addition, GRASS.
Definition qgis.h:4730
RasterIdentifyFormat
Raster identify formats.
Definition qgis.h:4832
@ Feature
WMS GML/JSON -> feature.
Definition qgis.h:4837
@ Value
Numerical pixel value.
Definition qgis.h:4834
@ Undefined
Undefined.
Definition qgis.h:4833
@ Preferred
Preferred format, matching the most recent WKT ISO standard. Currently an alias to WKT2_2019,...
Definition qgis.h:2439
QString abstract() const
Returns a free-form description of the resource.
QString title() const
Returns the human readable name of the resource, typically displayed in search results.
Abstract base class for objects which generate elevation profiles.
Abstract base class for labeling settings for raster layers.
static QgsAbstractRasterLayerLabeling * createFromElement(const QDomElement &element, const QgsReadWriteContext &context)
Tries to create an instance of an implementation based on the XML data.
static QgsRasterRendererRegistry * rasterRendererRegistry()
Returns the application's raster renderer registry, used for managing raster layer renderers.
static QgsRuntimeProfiler * profiler()
Returns the application runtime profiler.
Brightness/contrast and gamma correction filter pipe for rasters.
int contrast() const
Returns current contrast level.
int brightness() const
Returns current brightness level.
A ramp shader will color a raster pixel based on a list of values ranges in a ramp.
bool shade(double value, int *returnRedValue, int *returnGreenValue, int *returnBlueValue, int *returnAlphaValue) const override
Generates an new RGBA value based on one input value.
void classifyColorRamp(int classes=0, int band=-1, const QgsRectangle &extent=QgsRectangle(), QgsRasterInterface *input=nullptr)
Classify color ramp shader.
void setColorRampType(Qgis::ShaderInterpolationMethod colorRampType)
Sets the color ramp interpolation method.
void setColorRampItemList(const QList< QgsColorRampShader::ColorRampItem > &list)
Sets a custom color map.
Handles contrast enhancement and clipping.
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
Represents a coordinate reference system (CRS).
Contains information about the context in which a coordinate transform is executed.
Cubic Raster Resampler.
Abstract base class for spatial data provider implementations.
Stores the component parts of a 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.
Formats layer metadata into HTML.
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.
An abstract interface for implementations of legends for one map layer.
virtual void readXml(const QDomElement &elem, const QgsReadWriteContext &context)
Reads configuration from a DOM element previously written by writeXml().
virtual QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const
Writes configuration to a DOM element, to be used later with readXml().
static QgsMapLayerLegend * defaultRasterLegend(QgsRasterLayer *rl)
Create new legend implementation for raster layer.
void setFlag(Qgis::MapLayerLegendFlag flag, bool on=true)
Enables or disables a particular flag (other flags are not affected).
Base class for utility classes that encapsulate information necessary for rendering of map layers.
QString title() const
Returns the title of the layer used by QGIS Server in GetCapabilities request.
QString abstract() const
Returns the abstract of the layerused by QGIS Server in GetCapabilities request.
Base class for storage of map layer temporal properties.
QString name
Definition qgsmaplayer.h:84
void readStyleManager(const QDomNode &layerNode)
Read style manager's configuration (if any). To be called by subclasses.
void setError(const QgsError &error)
Sets error message.
void writeStyleManager(QDomNode &layerNode, QDomDocument &doc) const
Write style manager's configuration (if exists). To be called by subclasses.
QgsMapLayerLegend * legend() const
Can be nullptr.
virtual QgsRectangle extent() const
Returns the extent of the layer.
QString source() const
Returns the source for the layer.
Q_INVOKABLE QVariant customProperty(const QString &value, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer.
void setBlendMode(QPainter::CompositionMode blendMode)
Set the blending mode used for rendering a layer.
void configChanged()
Emitted whenever the configuration is changed.
static Qgis::DataProviderReadFlags providerReadFlags(const QDomNode &layerNode, QgsMapLayer::ReadFlags layerReadFlags)
Returns provider read flag deduced from layer read flags layerReadFlags and a dom node layerNode that...
QgsCoordinateReferenceSystem crs
Definition qgsmaplayer.h:87
QgsMapLayerServerProperties * serverProperties()
Returns QGIS Server Properties for the map layer.
virtual QString loadDefaultStyle(bool &resultFlag)
Retrieve the default style for this layer if one exists (either as a .qml file on disk or as a record...
void setDataSource(const QString &dataSource, const QString &baseName=QString(), const QString &provider=QString(), bool loadDefaultStyleFlag=false)
Updates the data source of the layer.
QString mLayerName
Name of the layer - used for display.
void triggerRepaint(bool deferredUpdate=false)
Will advise the map canvas (and any other interested party) that this layer requires to be repainted.
QString crsHtmlMetadata() const
Returns a HTML fragment containing the layer's CRS metadata, for use in the htmlMetadata() method.
QgsLayerMetadata metadata
Definition qgsmaplayer.h:86
Q_DECL_DEPRECATED QString abstract() const
Returns the abstract of the layer used by QGIS Server in GetCapabilities request.
QgsMapLayer(Qgis::LayerType type=Qgis::LayerType::Vector, const QString &name=QString(), const QString &source=QString())
Constructor for QgsMapLayer.
QPainter::CompositionMode blendMode() const
Returns the current blending mode for a layer.
void statusChanged(const QString &status)
Emit a signal with status (e.g. to be caught by QgisApp and display a msg on status bar).
virtual void setMetadata(const QgsLayerMetadata &metadata)
Sets the layer's metadata store.
QFlags< StyleCategory > StyleCategories
Q_INVOKABLE void setCustomProperty(const QString &key, const QVariant &value)
Set a custom property for layer.
QString mProviderKey
Data provider key (name of the data provider).
QgsCoordinateTransformContext transformContext() const
Returns the layer data provider coordinate transform context or a default transform context if the la...
std::unique_ptr< QgsDataProvider > mPreloadedProvider
Optionally used when loading a project, it is released when the layer is effectively created.
void rendererChanged()
Signal emitted when renderer is changed.
Q_DECL_DEPRECATED QString title() const
Returns the title of the layer used by QGIS Server in GetCapabilities request.
virtual QgsError error() const
Gets current status error.
QgsMapLayer::LayerFlags flags
Definition qgsmaplayer.h:96
bool hasScaleBasedVisibility() const
Returns whether scale based visibility is enabled for the layer.
void opacityChanged(double opacity)
Emitted when the layer's opacity is changed, where opacity is a value between 0 (transparent) and 1 (...
void emitStyleChanged()
Triggers an emission of the styleChanged() signal.
void dataChanged()
Data of layer changed.
void willBeDeleted()
Emitted in the destructor when the layer is about to be deleted, but it is still in a perfectly valid...
virtual QgsMapLayer * clone() const =0
Returns a new instance equivalent to this one except for the id which is still unique.
void setName(const QString &name)
Set the display name of the layer.
virtual void setExtent(const QgsRectangle &rect)
Sets the extent.
void appendError(const QgsErrorMessage &error)
Add error message.
QString mDataSource
Data source description string, varies by layer type.
void setMapTipsEnabled(bool enabled)
Enable or disable map tips for this layer.
@ FlagReadExtentFromXml
Read extent from xml and skip get extent from provider.
@ FlagTrustLayerMetadata
Trust layer metadata. Improves layer load time by skipping expensive checks like primary key unicity,...
@ FlagDontResolveLayers
Don't resolve layer paths or create data providers for layers.
void setValid(bool valid)
Sets whether layer is valid or not.
void readCommonStyle(const QDomElement &layerElement, const QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories)
Read style data common to all layer types.
QgsMapLayer::ReadFlags mReadFlags
Read flags. It's up to the subclass to respect these when restoring state from XML.
double minimumScale() const
Returns the minimum map scale (i.e.
void repaintRequested(bool deferredUpdate=false)
By emitting this signal the layer tells that either appearance or content have been changed and any v...
void setMapTipTemplate(const QString &mapTipTemplate)
The mapTip is a pretty, html representation for feature information.
bool mapTipsEnabled
Definition qgsmaplayer.h:94
@ AttributeTable
Attribute table settings: choice and order of columns, conditional styling.
@ Symbology
Symbology.
@ MapTips
Map tips.
@ Rendering
Rendering: scale visibility, simplify method, opacity.
@ Legend
Legend settings.
@ Labeling
Labeling.
void setProviderType(const QString &providerType)
Sets the providerType (provider key).
QString customPropertyHtmlMetadata() const
Returns an HTML fragment containing custom property information, for use in the htmlMetadata() method...
QString generalHtmlMetadata() const
Returns an HTML fragment containing general metadata information, for use in the htmlMetadata() metho...
void writeCommonStyle(QDomElement &layerElement, QDomDocument &document, const QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories) const
Write style data common to all layer types.
double maximumScale() const
Returns the maximum map scale (i.e.
void invalidateWgs84Extent()
Invalidates the WGS84 extent.
QString mapTipTemplate
Definition qgsmaplayer.h:93
bool mShouldValidateCrs
true if the layer's CRS should be validated and invalid CRSes are not permitted.
void setCrs(const QgsCoordinateReferenceSystem &srs, bool emitSignal=true)
Sets layer's spatial reference system.
Perform transforms between map coordinates and device coordinates.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE())
Adds a message to the log instance (and creates it if necessary).
Renderer for multiband images with the color components.
int blueBand() const
Returns the band number 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.
int redBand() const
Returns the band number for the red channel.
int greenBand() const
Returns the band number for the green channel.
static Qgis::BlendMode getBlendModeEnum(QPainter::CompositionMode blendMode)
Returns a Qgis::BlendMode corresponding to a QPainter::CompositionMode.
static QPainter::CompositionMode getCompositionMode(Qgis::BlendMode blendMode)
Returns a QPainter::CompositionMode corresponding to a Qgis::BlendMode.
QString writePath(const QString &filename) const
Prepare a filename to save it to the project file.
QString readPath(const QString &filename) const
Turn filename read from the project file to an absolute path.
Represents a 2D point.
Definition qgspointxy.h:60
Encapsulates properties and constraints relating to fetching elevation profiles from different source...
static void convertRasterProperties(QDomDocument &doc, QDomNode &parentNode, QDomElement &rasterPropertiesElem, QgsRasterLayer *rlayer)
QString absoluteToRelativeUri(const QString &providerKey, const QString &uri, const QgsReadWriteContext &context) const
Converts absolute path(s) to relative path(s) in the given provider-specific URI.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
QString relativeToAbsoluteUri(const QString &providerKey, const QString &uri, const QgsReadWriteContext &context) const
Converts relative path(s) to absolute path(s) in the given provider-specific URI.
Represents a Raster Attribute Table (RAT).
QString filePath() const
Returns the (possibly empty) path of the file-based RAT, the path is set when a RAT is read or writte...
The RasterBandStats struct is a container for statistics about a single raster band.
double mean
The mean cell value for the band. NO_DATA values are excluded.
double stdDev
The standard deviation of the cell values.
double minimumValue
The minimum cell value in the raster band.
Qgis::RasterBandStatistics statsGathered
Collected statistics.
double maximumValue
The maximum cell value in the raster band.
static int typeSize(Qgis::DataType dataType)
Returns the size in bytes for the specified dataType.
static QString printValue(double value, bool localized=false)
Print double value with all necessary significant digits.
Handles elevation related properties for a raster data provider.
Base class for raster data providers.
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.
QDateTime dataTimestamp() const override
Current time stamp of data source.
void statusChanged(const QString &) const
Emit a message to be displayed on status bar, usually used by network providers (WMS,...
static QString identifyFormatName(Qgis::RasterIdentifyFormat format)
Converts a raster identify format to a string name.
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.
Q_DECL_DEPRECATED QgsRasterBandStats bandStatistics(int bandNo, int stats, const QgsRectangle &extent=QgsRectangle(), int sampleSize=0, QgsRasterBlockFeedback *feedback=nullptr)
Returns the band statistics.
Q_DECL_DEPRECATED bool hasStatistics(int bandNo, int stats, const QgsRectangle &extent=QgsRectangle(), int sampleSize=0)
Returns true if histogram is available (cached, already calculated).
virtual void writeXml(QDomDocument &doc, QDomElement &parentElem) const
Write base class members to xml.
virtual QgsRasterInterface * input() const
Current input.
Iterator for sequentially processing raster cells.
Raster layer specific subclass of QgsMapLayerElevationProperties.
Implementation of QgsAbstractProfileGenerator for raster layers.
Implementation of threaded rendering for raster layers.
Implementation of map layer temporal properties for raster layers.
QString htmlMetadata() const override
Obtain a formatted HTML string containing assorted metadata for this layer.
bool canCreateRasterAttributeTable()
Returns true if the raster renderer is suitable for creation of a raster attribute table.
void subsetStringChanged()
Emitted when the layer's subset string has changed.
Qgis::MapLayerProperties properties() const override
Returns the map layer properties of this layer.
QString encodedSource(const QString &source, const QgsReadWriteContext &context) const override
Called by writeLayerXML(), used by derived classes to encode provider's specific data source to proje...
const QgsAbstractRasterLayerLabeling * labeling() const
Access to const labeling configuration.
Q_DECL_DEPRECATED QgsLegendColorList legendSymbologyItems() const
Returns a list with classification items (Text and color).
QgsMapLayerRenderer * createMapRenderer(QgsRenderContext &rendererContext) override
Returns new instance of QgsMapLayerRenderer that will be used for rendering of given context.
void showStatusMessage(const QString &message)
QgsRasterAttributeTable * attributeTable(int bandNumber) const
Returns the (possibly NULL) raster attribute table for the given band bandNumber.
virtual bool setSubsetString(const QString &subset)
Sets the string (typically sql) used to define a subset of the layer.
QgsRasterResampleFilter * resampleFilter() const
Returns the raster's resample filter.
bool writeSymbology(QDomNode &, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories) const override
Write the style for the layer into the document provided.
QgsRasterLayer * clone() const override
Returns a new instance equivalent to this one.
void setResamplingStage(Qgis::RasterResamplingStage stage)
Select which stage of the pipe should apply resampling.
Qgis::RasterResamplingStage resamplingStage() const
Returns which stage of the pipe should apply resampling.
static const QgsSettingsEntryBool * settingsRasterDefaultEarlyResampling
int attributeTableCount() const
Returns the number of attribute tables for the raster by counting the number of bands that have an as...
void refreshContrastEnhancement(const QgsRectangle &extent)
Refresh contrast enhancement with new extent.
int height() const
Returns the height of the (unclipped) raster.
static const Qgis::RasterRangeLimit SINGLE_BAND_MIN_MAX_LIMITS
Default enhancement limits for single band raster.
Q_DECL_DEPRECATED void setDataProvider(const QString &provider)
Set the data provider.
static const QgsContrastEnhancement::ContrastEnhancementAlgorithm MULTIPLE_BAND_SINGLE_BYTE_ENHANCEMENT_ALGORITHM
Default enhancement algorithm for multiple band raster of type Byte.
int bandCount() const
Returns the number of bands in this layer.
QgsMapLayerTemporalProperties * temporalProperties() override
Returns the layer's temporal properties.
bool ignoreExtents() const
If the ignoreExtent flag is set, the layer will also render outside the bounding box reported by the ...
QString decodedSource(const QString &source, const QString &provider, const QgsReadWriteContext &context) const override
Called by readLayerXML(), used by derived classes to decode provider's specific data source from proj...
double opacity() const final
Returns the opacity for the layer, where opacity is a value between 0 (totally transparent) and 1....
void computeMinMax(int band, const QgsRasterMinMaxOrigin &mmo, Qgis::RasterRangeLimit limits, const QgsRectangle &extent, int sampleSize, double &min, double &max)
Compute the min max values along band according to MinMaxOrigin parameters mmo and extent.
bool labelsEnabled() const
Returns whether the layer contains labels which are enabled and should be drawn.
void setSubLayerVisibility(const QString &name, bool vis) override
Set the visibility of the given sublayer name.
static const QgsSettingsEntryDouble * settingsRasterDefaultOversampling
void setLabeling(QgsAbstractRasterLayerLabeling *labeling)
Sets labeling configuration.
virtual QString subsetString() const
Returns the string (typically sql) used to define a subset of the layer.
QgsAbstractProfileGenerator * createProfileGenerator(const QgsProfileRequest &request) override
Given a profile request, returns a new profile generator ready for generating elevation profiles.
QgsBrightnessContrastFilter * brightnessFilter() const
Returns the raster's brightness/contrast filter.
bool writeXml(QDomNode &layer_node, QDomDocument &doc, const QgsReadWriteContext &context) const override
Called by writeLayerXML(), used by children to write state specific to them to project files.
bool writeStyle(QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories) const override
Write just the symbology information for the layer into the document.
double rasterUnitsPerPixelX() const
Returns the number of raster units per each raster pixel in X axis.
void reload() override
Synchronises with changes in the datasource.
bool accept(QgsStyleEntityVisitorInterface *visitor) const override
Accepts the specified symbology visitor, causing it to visit all symbols associated with the layer.
QImage previewAsImage(QSize size, const QColor &bgColor=Qt::white, QImage::Format format=QImage::Format_ARGB32_Premultiplied)
Draws a preview of the rasterlayer into a QImage.
QStringList subLayers() const override
Returns the sublayers of this layer.
static const Qgis::RasterRangeLimit MULTIPLE_BAND_MULTI_BYTE_MIN_MAX_LIMITS
Default enhancement limits for multiple band raster of type different from Byte.
void setContrastEnhancement(QgsContrastEnhancement::ContrastEnhancementAlgorithm algorithm, Qgis::RasterRangeLimit limits=Qgis::RasterRangeLimit::MinimumMaximum, const QgsRectangle &extent=QgsRectangle(), int sampleSize=QgsRasterLayer::SAMPLE_SIZE, bool generateLookupTableFlag=true)
Set contrast enhancement algorithm.
void setDefaultContrastEnhancement()
Sets the default contrast enhancement.
QgsRasterRenderer * renderer() const
Returns the raster's renderer.
static const double SAMPLE_SIZE
Default sample size (number of pixels) for estimated statistics/histogram calculation.
static const QgsContrastEnhancement::ContrastEnhancementAlgorithm MULTIPLE_BAND_MULTI_BYTE_ENHANCEMENT_ALGORITHM
Default enhancement algorithm for multiple band raster of type different from Byte.
static const Qgis::RasterRangeLimit MULTIPLE_BAND_SINGLE_BYTE_MIN_MAX_LIMITS
Default enhancement limits for multiple band raster of type Byte.
bool readXml(const QDomNode &layer_node, QgsReadWriteContext &context) override
Called by readLayerXML(), used by children to read state specific to them from project files.
void setLabelsEnabled(bool enabled)
Sets whether labels should be enabled for the layer.
QString bandName(int bandNoInt) const
Returns the name of a band given its number.
QgsRasterDataProvider * dataProvider() override
Returns the source data provider.
static bool isValidRasterFileName(const QString &fileNameQString, QString &retError)
This helper checks to see whether the file name appears to be a valid raster file name.
bool isSpatial() const override
Returns true if the layer is considered a spatial layer, ie it has some form of geometry associated w...
void setOpacity(double opacity) final
Sets the opacity for the layer, where opacity is a value between 0 (totally transparent) and 1....
double rasterUnitsPerPixelY() const
Returns the number of raster units per each raster pixel in Y axis.
int width() const
Returns the width of the (unclipped) raster.
QgsMapLayerElevationProperties * elevationProperties() override
Returns the layer's elevation properties.
bool readSymbology(const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories) override
Read the symbology for the current layer from the DOM node supplied.
void draw(QPainter *theQPainter, QgsRasterViewPort *myRasterViewPort, const QgsMapToPixel *qgsMapToPixel=nullptr)
This is an overloaded version of the draw() function that is called by both draw() and thumbnailAsPix...
Q_DECL_DEPRECATED 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.
void setTransformContext(const QgsCoordinateTransformContext &transformContext) override
Sets the coordinate transform context to transformContext.
void setRenderer(QgsRasterRenderer *renderer)
Sets the raster's renderer.
QgsRasterLayer()
Constructor. Provider is not set.
void setLayerOrder(const QStringList &layers) override
Reorders the previously selected sublayers of this layer from bottom to top.
bool defaultContrastEnhancementSettings(QgsContrastEnhancement::ContrastEnhancementAlgorithm &myAlgorithm, Qgis::RasterRangeLimit &myLimits) const
Returns default contrast enhancement settings for that type of raster.
QgsHueSaturationFilter * hueSaturationFilter() const
Returns the raster's hue/saturation filter.
bool readStyle(const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories) override
Read the style for the current layer from the DOM node supplied.
QPixmap paletteAsPixmap(int bandNumber=1)
Returns a 100x100 pixmap of the color palette.
Describes the origin of minimum and maximum values in a raster.
static QString limitsString(Qgis::RasterRangeLimit limits)
Returns a string to serialize Limits.
void setLimits(Qgis::RasterRangeLimit limits)
Sets the limits.
void setExtent(Qgis::RasterRangeExtent extent)
Sets the extent.
double cumulativeCutLower() const
Returns the lower bound of cumulative cut method (between 0 and 1).
Qgis::RasterRangeExtent extent() const
Returns the raster extent.
double stdDevFactor() const
Returns the factor f so that the min/max range is [ mean - f * stddev , mean + f * stddev ].
double cumulativeCutUpper() const
Returns the upper bound of cumulative cut method (between 0 and 1).
static Qgis::RasterRangeLimit limitsFromString(const QString &limits)
Deserialize Limits.
Qgis::RasterRangeLimit limits() const
Returns the raster limits.
Contains a pipeline of raster interfaces for sequential raster processing.
static QgsPropertiesDefinition propertyDefinitions()
Returns the definitions for data defined properties available for use in raster pipes.
Implements approximate projection support for optimised raster transformation.
Q_DECL_DEPRECATED void setCrs(const QgsCoordinateReferenceSystem &srcCRS, const QgsCoordinateReferenceSystem &destCRS, int srcDatumTransform=-1, int destDatumTransform=-1)
Sets the source and destination CRS.
Represents a range of raster values between min and max, optionally including the min and max value.
double min() const
Returns the minimum value for the range.
Raster renderer pipe that applies colors to a raster.
virtual QString type() const
Returns a unique string representation of the renderer type.
virtual bool canCreateRasterAttributeTable() const
Returns true if the renderer is suitable for attribute table creation.
void setMinMaxOrigin(const QgsRasterMinMaxOrigin &origin)
Sets origin of min/max values.
const QgsRasterMinMaxOrigin & minMaxOrigin() const
Returns const reference to origin of min/max values.
virtual bool refresh(const QgsRectangle &extent, const QList< double > &min, const QList< double > &max, bool forceRefresh=false)
Refreshes the renderer according to the min and max values associated with the extent.
Resample filter pipe for rasters.
Interface for all raster shaders.
void setRasterShaderFunction(QgsRasterShaderFunction *function)
A public method that allows the user to set their own shader function.
Allows entering a context category and takes care of leaving this category on deletion of the class.
A container for the context for various read/write operations on objects.
QgsReadWriteContextCategoryPopper enterCategory(const QString &category, const QString &details=QString()) const
Push a category to the stack.
QgsCoordinateTransformContext transformContext() const
Returns data provider coordinate transform context.
const QgsPathResolver & pathResolver() const
Returns path resolver for conversion between relative and absolute paths.
A rectangle specified with double values.
Q_INVOKABLE QString toString(int precision=16) const
Returns a string representation of form xmin,ymin : xmax,ymax Coordinates will be truncated to the sp...
Contains information about the context of a rendering operation.
A boolean settings entry.
A double settings entry.
static QgsSettingsTreeNode * sTreeRaster
Stores settings for use within QGIS.
Definition qgssettings.h:65
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
Raster renderer pipe for single band gray.
void setContrastEnhancement(QgsContrastEnhancement *ce)
Takes ownership.
int inputBand() const override
Returns the input band for the renderer, or -1 if no input band is available.
Raster renderer pipe for single band pseudocolor.
void setShader(QgsRasterShader *shader)
Takes ownership of the shader.
QgsRasterShader * shader()
Returns the raster shader.
int inputBand() const override
Returns the input band for the renderer, or -1 if no input band is available.
Holds SLD export options and other information related to SLD export of a QGIS layer style.
void setExtraProperties(const QVariantMap &properties)
Sets the open ended set of properties that can drive/inform the SLD encoding.
QVariantMap extraProperties() const
Returns the open ended set of properties that can drive/inform the SLD encoding.
An interface for classes which can visit style entity (e.g.
static void mergeScaleDependencies(double mScaleMinDenom, double mScaleMaxDenom, QVariantMap &props)
Merges the local scale limits, if any, with the ones already in the map, if any.
static QgsRectangle readRectangle(const QDomElement &element)
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into allowing algorithms to be written in pure substantial changes are required in order to port existing x Processing algorithms for QGIS x The most significant changes are outlined not GeoAlgorithm For algorithms which operate on features one by consider subclassing the QgsProcessingFeatureBasedAlgorithm class This class allows much of the boilerplate code for looping over features from a vector layer to be bypassed and instead requires implementation of a processFeature method Ensure that your algorithm(or algorithm 's parent class) implements the new pure virtual createInstance(self) call
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
Definition qgis.h:6798
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
Definition qgis.h:6607
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition qgis.h:6511
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:61
#define QgsDebugError(str)
Definition qgslogger.h:57
#define ERR(message)
QgsDataProvider * classFactoryFunction_t(const QString *, const QgsDataProvider::ProviderOptions &options)
QList< QPair< QString, QColor > > QgsLegendColorList
QList< QgsRasterRange > QgsRasterRangeList
#define QGIS_PROTECT_QOBJECT_THREAD_ACCESS
Setting options for creating vector data providers.
Setting options for loading raster layers.
bool skipCrsValidation
Controls whether the layer is allowed to have an invalid/unknown CRS.
bool loadDefaultStyle
Sets to true if the default layer style should be loaded.
QgsCoordinateTransformContext transformContext
Coordinate transform context.
Registry for raster renderer entries.
QgsRasterRendererCreateFunc rendererCreateFunction
This class provides details of the viewable area that a raster will be rendered into.
qgssize mHeight
Height, number of rows to be rendered.
QgsCoordinateReferenceSystem mDestCRS
Target (map) coordinate system.
QgsPointXY mBottomRightPoint
Coordinate (in output device coordinate system) of bottom right corner of the part of the raster that...
QgsPointXY mTopLeftPoint
Coordinate (in output device coordinate system) of top left corner of the part of the raster that is ...
QgsCoordinateReferenceSystem mSrcCRS
Source (layer) coordinate system.
QgsRectangle mDrawnExtent
Intersection of current map extent and layer extent, in map (destination) CRS.
QgsCoordinateTransformContext mTransformContext
Coordinate transform context.
qgssize mWidth
Width, number of columns to be rendered.