LCOV - code coverage report
Current view: top level - core/providers/gdal - qgsgdalprovider.h (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 1 2 50.0 %
Date: 2021-04-10 08:29:14 Functions: 0 0 -
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /***************************************************************************
       2                 :            :       qgsgdalprovider.h  -  QGIS Data provider for
       3                 :            :                            GDAL rasters
       4                 :            :                              -------------------
       5                 :            :     begin                : November, 2010
       6                 :            :     copyright            : (C) 2010 by Radim Blazek
       7                 :            :     email                : radim dot blazek at gmail dot com
       8                 :            :  ***************************************************************************/
       9                 :            : 
      10                 :            : /***************************************************************************
      11                 :            :  *                                                                         *
      12                 :            :  *   This program is free software; you can redistribute it and/or modify  *
      13                 :            :  *   it under the terms of the GNU General Public License as published by  *
      14                 :            :  *   the Free Software Foundation; either version 2 of the License, or     *
      15                 :            :  *   (at your option) any later version.                                   *
      16                 :            :  *                                                                         *
      17                 :            :  ***************************************************************************/
      18                 :            : 
      19                 :            : #ifndef QGSGDALPROVIDER_H
      20                 :            : #define QGSGDALPROVIDER_H
      21                 :            : 
      22                 :            : #include "qgscoordinatereferencesystem.h"
      23                 :            : #include "qgsdataitem.h"
      24                 :            : #include "qgsrasterdataprovider.h"
      25                 :            : #include "qgsgdalproviderbase.h"
      26                 :            : #include "qgsrectangle.h"
      27                 :            : #include "qgscolorrampshader.h"
      28                 :            : #include "qgsrasterbandstats.h"
      29                 :            : #include "qgsprovidermetadata.h"
      30                 :            : 
      31                 :            : #include <QString>
      32                 :            : #include <QStringList>
      33                 :            : #include <QDomElement>
      34                 :            : #include <QMap>
      35                 :            : #include <QVector>
      36                 :            : 
      37                 :            : #include "qgis_sip.h"
      38                 :            : 
      39                 :            : ///@cond PRIVATE
      40                 :            : #define SIP_NO_FILE
      41                 :            : 
      42                 :            : class QMutex;
      43                 :            : 
      44                 :            : class QgsRasterPyramid;
      45                 :            : 
      46                 :            : /**
      47                 :            :  * \ingroup core
      48                 :            :  * \brief A call back function for showing progress of gdal operations.
      49                 :            :  */
      50                 :            : int CPL_STDCALL progressCallback( double dfComplete,
      51                 :            :                                   const char *pszMessage,
      52                 :            :                                   void *pProgressArg );
      53                 :            : 
      54                 :            : 
      55                 :            : class QgsCoordinateTransform;
      56                 :            : 
      57                 :            : /**
      58                 :            :  *
      59                 :            :  * \brief Data provider for GDAL layers.
      60                 :            :  *
      61                 :            :  * This provider implements the interface defined in the QgsDataProvider class
      62                 :            :  * to provide access to spatial data residing in a GDAL layers.
      63                 :            :  *
      64                 :            : */
      65                 :            : class QgsGdalProvider final: public QgsRasterDataProvider, QgsGdalProviderBase
      66                 :            : {
      67                 :          0 :     Q_OBJECT
      68                 :            : 
      69                 :            :   public:
      70                 :            : 
      71                 :            :     /**
      72                 :            :      * Constructor for the provider.
      73                 :            :      *
      74                 :            :      * \param   uri         file name
      75                 :            :      * \param   update      whether to open in update mode
      76                 :            :      * \param   newDataset  handle of newly created dataset.
      77                 :            :      *
      78                 :            :      */
      79                 :            :     QgsGdalProvider( const QString &uri, const QgsDataProvider::ProviderOptions &providerOptions, bool update = false, GDALDatasetH newDataset = nullptr );
      80                 :            : 
      81                 :            :     //! Create invalid provider with error
      82                 :            :     QgsGdalProvider( const QString &uri, const QgsError &error );
      83                 :            : 
      84                 :            :     ~QgsGdalProvider() override;
      85                 :            : 
      86                 :            :     /**
      87                 :            :      * Gets the data source specification. This may be a path or a protocol
      88                 :            :      * connection string
      89                 :            :      * \param expandAuthConfig Whether to expand any assigned authentication configuration
      90                 :            :      * \returns data source specification
      91                 :            :      * \note The default authentication configuration expansion is FALSE. This keeps credentials
      92                 :            :      * out of layer data source URIs and project files. Expansion should be specifically done
      93                 :            :      * only when needed within a provider
      94                 :            :      */
      95                 :            :     QString dataSourceUri( bool expandAuthConfig = false ) const override;
      96                 :            : 
      97                 :            :     /**
      98                 :            :      * Clone the provider.
      99                 :            :      *
     100                 :            :      * The underlying GDAL dataset is shared among the main provider and its
     101                 :            :      * clones.
     102                 :            :      */
     103                 :            :     QgsGdalProvider *clone() const override;
     104                 :            : 
     105                 :            :     QString name() const override;
     106                 :            : 
     107                 :            :     /**
     108                 :            :      * GDAL data provider key
     109                 :            :      * \since QGIS 3.10
     110                 :            :      */
     111                 :            :     static QString providerKey();
     112                 :            : 
     113                 :            :     /**
     114                 :            :      * This helper checks to see whether the file name appears to be a valid
     115                 :            :      * raster file name.  If the file name looks like it could be valid,
     116                 :            :      * but some sort of error occurs in processing the file, the error is
     117                 :            :      * returned in \a retErrMsg.
     118                 :            :      * \since QGIS 3.10
     119                 :            :      */
     120                 :            :     static bool isValidRasterFileName( QString const &fileNameQString, QString &retErrMsg );
     121                 :            : 
     122                 :            :     /**
     123                 :            :      * Gets creation options metadata for a given format
     124                 :            :      * \since QGIS 3.10
     125                 :            :      */
     126                 :            :     static QString helpCreationOptionsFormat( QString format );
     127                 :            : 
     128                 :            :     QString description() const override;
     129                 :            :     QgsRasterDataProvider::ProviderCapabilities providerCapabilities() const override;
     130                 :            :     QgsCoordinateReferenceSystem crs() const override;
     131                 :            :     QgsRectangle extent() const override;
     132                 :            :     bool isValid() const override;
     133                 :            :     QgsRasterIdentifyResult identify( const QgsPointXY &point, QgsRaster::IdentifyFormat format, const QgsRectangle &boundingBox = QgsRectangle(), int width = 0, int height = 0, int dpi = 96 ) override;
     134                 :            :     double sample( const QgsPointXY &point, int band, bool *ok = nullptr, const QgsRectangle &boundingBox = QgsRectangle(), int width = 0, int height = 0, int dpi = 96 ) override;
     135                 :            :     QString lastErrorTitle() override;
     136                 :            :     QString lastError() override;
     137                 :            :     int capabilities() const override;
     138                 :            :     Qgis::DataType dataType( int bandNo ) const override;
     139                 :            :     Qgis::DataType sourceDataType( int bandNo ) const override;
     140                 :            :     int bandCount() const override;
     141                 :            :     int colorInterpretation( int bandNo ) const override;
     142                 :            :     int xBlockSize() const override;
     143                 :            :     int yBlockSize() const override;
     144                 :            :     int xSize() const override;
     145                 :            :     int ySize() const override;
     146                 :            :     QString generateBandName( int bandNumber ) const override;
     147                 :            : 
     148                 :            :     // Reimplemented from QgsRasterDataProvider to bypass second resampling (more efficient for local file based sources)
     149                 :            :     QgsRasterBlock *block( int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback *feedback = nullptr ) override;
     150                 :            : 
     151                 :            :     bool readBlock( int bandNo, int xBlock, int yBlock, void *data ) override;
     152                 :            :     bool readBlock( int bandNo, QgsRectangle  const &viewExtent, int width, int height, void *data, QgsRasterBlockFeedback *feedback = nullptr ) override;
     153                 :            : 
     154                 :            :     double bandScale( int bandNo ) const override;
     155                 :            :     double bandOffset( int bandNo ) const override;
     156                 :            :     QList<QgsColorRampShader::ColorRampItem> colorTable( int bandNo )const override;
     157                 :            :     QString htmlMetadata() override;
     158                 :            :     QStringList subLayers() const override;
     159                 :            :     static QStringList subLayers( GDALDatasetH dataset );
     160                 :            : 
     161                 :            :     bool hasStatistics( int bandNo,
     162                 :            :                         int stats = QgsRasterBandStats::All,
     163                 :            :                         const QgsRectangle &boundingBox = QgsRectangle(),
     164                 :            :                         int sampleSize = 0 ) override;
     165                 :            : 
     166                 :            :     QgsRasterBandStats bandStatistics( int bandNo,
     167                 :            :                                        int stats = QgsRasterBandStats::All,
     168                 :            :                                        const QgsRectangle &boundingBox = QgsRectangle(),
     169                 :            :                                        int sampleSize = 0, QgsRasterBlockFeedback *feedback = nullptr ) override;
     170                 :            : 
     171                 :            :     bool hasHistogram( int bandNo,
     172                 :            :                        int binCount = 0,
     173                 :            :                        double minimum = std::numeric_limits<double>::quiet_NaN(),
     174                 :            :                        double maximum = std::numeric_limits<double>::quiet_NaN(),
     175                 :            :                        const QgsRectangle &boundingBox = QgsRectangle(),
     176                 :            :                        int sampleSize = 0,
     177                 :            :                        bool includeOutOfRange = false ) override;
     178                 :            : 
     179                 :            :     QgsRasterHistogram histogram( int bandNo,
     180                 :            :                                   int binCount = 0,
     181                 :            :                                   double minimum = std::numeric_limits<double>::quiet_NaN(),
     182                 :            :                                   double maximum = std::numeric_limits<double>::quiet_NaN(),
     183                 :            :                                   const QgsRectangle &boundingBox = QgsRectangle(),
     184                 :            :                                   int sampleSize = 0,
     185                 :            :                                   bool includeOutOfRange = false, QgsRasterBlockFeedback *feedback = nullptr ) override;
     186                 :            : 
     187                 :            :     QString buildPyramids( const QList<QgsRasterPyramid> &rasterPyramidList,
     188                 :            :                            const QString &resamplingMethod = "NEAREST",
     189                 :            :                            QgsRaster::RasterPyramidsFormat format = QgsRaster::PyramidsGTiff,
     190                 :            :                            const QStringList &createOptions = QStringList(),
     191                 :            :                            QgsRasterBlockFeedback *feedback = nullptr ) override;
     192                 :            :     QList<QgsRasterPyramid> buildPyramidList( const QList<int> &overviewList = QList<int>() ) override;
     193                 :            : 
     194                 :            :     static QMap<QString, QString> supportedMimes();
     195                 :            : 
     196                 :            :     bool isEditable() const override;
     197                 :            :     bool setEditable( bool enabled ) override;
     198                 :            :     bool write( void *data, int band, int width, int height, int xOffset, int yOffset ) override;
     199                 :            : 
     200                 :            :     bool setNoDataValue( int bandNo, double noDataValue ) override;
     201                 :            :     bool remove() override;
     202                 :            : 
     203                 :            :     QString validateCreationOptions( const QStringList &createOptions, const QString &format ) override;
     204                 :            :     QString validatePyramidsConfigOptions( QgsRaster::RasterPyramidsFormat pyramidsFormat,
     205                 :            :                                            const QStringList &configOptions, const QString &fileFormat ) override;
     206                 :            : 
     207                 :            :     QgsPoint transformCoordinates( const QgsPoint &point, TransformType type ) override;
     208                 :            : 
     209                 :            :     bool enableProviderResampling( bool enable ) override { mProviderResamplingEnabled = enable; return true; }
     210                 :            :     bool setZoomedInResamplingMethod( ResamplingMethod method ) override { mZoomedInResamplingMethod = method; return true; }
     211                 :            :     bool setZoomedOutResamplingMethod( ResamplingMethod method ) override { mZoomedOutResamplingMethod = method; return true; }
     212                 :            :     bool setMaxOversampling( double factor ) override { mMaxOversampling = factor; return true; }
     213                 :            : 
     214                 :            :   private:
     215                 :            :     QgsGdalProvider( const QgsGdalProvider &other );
     216                 :            :     QgsGdalProvider &operator=( const QgsGdalProvider & ) = delete;
     217                 :            : 
     218                 :            :     //! Whether mGdalDataset and mGdalBaseDataset have been attempted to be set
     219                 :            :     bool mHasInit = false;
     220                 :            : 
     221                 :            :     //! Open mGdalDataset/mGdalBaseDataset if needed.
     222                 :            :     bool initIfNeeded();
     223                 :            : 
     224                 :            :     // There are 2 cloning mechanisms.
     225                 :            :     // * Either the cloned provider use the same GDAL handles as the main provider
     226                 :            :     //   instance, in which case *mpRefCounter is used to count how many providers
     227                 :            :     //    use the main provider. And *mpMutex is used to protect access to the
     228                 :            :     //   GDAL resource.
     229                 :            :     // * Or the cloned provider use its own GDAL handles, but with a cache mechanism
     230                 :            :     //   to avoid constant opening/closing of datasets. In that case *mpParent is
     231                 :            :     //   used to point to the main provider, and *mpLightRefCounter to count how
     232                 :            :     //   many providers point to that main provider.
     233                 :            : 
     234                 :            :     // reference counter to know how many main and shared provider instances are linked
     235                 :            :     QAtomicInt *mpRefCounter = nullptr;
     236                 :            : 
     237                 :            :     // mutex to protect access to mGdalDataset among main and shared provider instances
     238                 :            : #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
     239                 :            :     QMutex *mpMutex = nullptr;
     240                 :            : #else
     241                 :            :     QRecursiveMutex *mpMutex = nullptr;
     242                 :            : #endif
     243                 :            : 
     244                 :            : 
     245                 :            :     // pointer to a QgsGdalProvider* that is the parent. Note when *mpParent == this, we are the parent.
     246                 :            :     QgsGdalProvider **mpParent = nullptr;
     247                 :            : 
     248                 :            :     // reference counter to know how many main and related provider instances are linked
     249                 :            :     mutable QAtomicInt *mpLightRefCounter = nullptr;
     250                 :            : 
     251                 :            :     // update mode
     252                 :            :     bool mUpdate;
     253                 :            : 
     254                 :            :     //! Do some initialization on the dataset (e.g. handling of south-up datasets)
     255                 :            :     void initBaseDataset();
     256                 :            : 
     257                 :            :     /**
     258                 :            :      * Flag indicating if the layer data source is a valid layer
     259                 :            :      */
     260                 :            :     bool mValid = false;
     261                 :            : 
     262                 :            :     //! \brief Whether this raster has overviews / pyramids or not
     263                 :            :     bool mHasPyramids = false;
     264                 :            : 
     265                 :            :     /**
     266                 :            :      * \brief Gdal data types used to represent data in in QGIS,
     267                 :            :      * may be longer than source data type to keep nulls
     268                 :            :      * indexed from 0
     269                 :            :      */
     270                 :            :     QList<GDALDataType> mGdalDataType;
     271                 :            : 
     272                 :            :     QgsRectangle mExtent;
     273                 :            :     int mWidth = 0;
     274                 :            :     int mHeight = 0;
     275                 :            :     int mXBlockSize = 0;
     276                 :            :     int mYBlockSize = 0;
     277                 :            :     int mBandCount = 1;
     278                 :            : 
     279                 :            :     //mutable QList<bool> mMinMaxComputed;
     280                 :            : 
     281                 :            :     // List of estimated min values, index 0 for band 1
     282                 :            :     //mutable QList<double> mMinimum;
     283                 :            : 
     284                 :            :     // List of estimated max values, index 0 for band 1
     285                 :            :     //mutable QList<double> mMaximum;
     286                 :            : 
     287                 :            :     //! \brief Pointer to the gdaldataset
     288                 :            :     GDALDatasetH mGdalBaseDataset = nullptr;
     289                 :            : 
     290                 :            :     //! \brief Pointer to the gdaldataset (possibly warped vrt)
     291                 :            :     GDALDatasetH mGdalDataset = nullptr;
     292                 :            : 
     293                 :            :     //! \brief Values for mapping pixel to world coordinates. Contents of this array are the same as the GDAL adfGeoTransform
     294                 :            :     double mGeoTransform[6];
     295                 :            : 
     296                 :            :     QgsCoordinateReferenceSystem mCrs;
     297                 :            : 
     298                 :            :     QList<QgsRasterPyramid> mPyramidList;
     299                 :            : 
     300                 :            :     //! \brief sublayers list saved for subsequent access
     301                 :            :     QStringList mSubLayers;
     302                 :            : 
     303                 :            :     //! Whether a per-dataset mask band is exposed as an alpha band for the point of view of the rest of the application.
     304                 :            :     bool mMaskBandExposedAsAlpha = false;
     305                 :            : 
     306                 :            :     //! \brief Driver short name.
     307                 :            :     // It is kept in case the driver would be de-registered after the provider has been created.
     308                 :            :     // Which is a very dangerous situation (see #29212)
     309                 :            :     QString mDriverName;
     310                 :            : 
     311                 :            :     //! Wrapper for GDALGetRasterBand() that takes into account mMaskBandExposedAsAlpha.
     312                 :            :     GDALRasterBandH getBand( int bandNo ) const;
     313                 :            : 
     314                 :            :     //! \brief Close data set and release related data
     315                 :            :     void closeDataset();
     316                 :            : 
     317                 :            :     //! Pair of GDAL base dataset and "real" dataset handles.
     318                 :            :     struct DatasetPair
     319                 :            :     {
     320                 :            :       GDALDatasetH mGdalBaseDataset;
     321                 :            :       GDALDatasetH mGdalDataset;
     322                 :            :     };
     323                 :            : 
     324                 :            :     // Dataset cache
     325                 :            :     static QHash< QgsGdalProvider *, QVector<DatasetPair> > mgDatasetCache;
     326                 :            : 
     327                 :            :     // Number of cached datasets in mgDatasetCache ( == sum(iter.value().size() )
     328                 :            :     static int mgDatasetCacheSize;
     329                 :            : 
     330                 :            :     //! Add handles to the cache if possible for the specified parent provider, in which case true is returned. If false returned, then the handles should be processed appropriately by the caller
     331                 :            :     static bool cacheGdalHandlesForLaterReuse( QgsGdalProvider *provider, GDALDatasetH gdalBaseDataset, GDALDatasetH gdalDataset );
     332                 :            : 
     333                 :            :     //! Gets cached handles for the specified provider, in which case true is returned and 2 handles are set.
     334                 :            :     static bool getCachedGdalHandles( QgsGdalProvider *provider, GDALDatasetH &gdalBaseDataset, GDALDatasetH &gdalDataset );
     335                 :            : 
     336                 :            :     //! Close all cached dataset for the specified provider.
     337                 :            :     static void closeCachedGdalHandlesFor( QgsGdalProvider *provider );
     338                 :            : 
     339                 :            :     /**
     340                 :            :      * Converts a world (\a x, \a y) coordinate to a pixel \a row and \a col.
     341                 :            :      */
     342                 :            :     bool worldToPixel( double x, double y, int &col, int &row ) const;
     343                 :            : 
     344                 :            :     bool mStatisticsAreReliable = false;
     345                 :            : 
     346                 :            :     /**
     347                 :            :      * Closes and reinits dataset
     348                 :            :     */
     349                 :            :     void reloadProviderData() override;
     350                 :            : 
     351                 :            :     //! Instance of GDAL transformer function used in transformCoordinates() for conversion between image and layer coordinates
     352                 :            :     void *mGdalTransformerArg = nullptr;
     353                 :            : 
     354                 :            :     bool canDoResampling(
     355                 :            :       int bandNo,
     356                 :            :       const QgsRectangle &reqExtent,
     357                 :            :       int bufferWidthPix,
     358                 :            :       int bufferHeightPix );
     359                 :            : };
     360                 :            : 
     361                 :            : /**
     362                 :            :  * Metadata of the GDAL data provider
     363                 :            :  */
     364                 :          6 : class QgsGdalProviderMetadata final: public QgsProviderMetadata
     365                 :            : {
     366                 :            :   public:
     367                 :            :     QgsGdalProviderMetadata();
     368                 :            :     QVariantMap decodeUri( const QString &uri ) const override;
     369                 :            :     QString encodeUri( const QVariantMap &parts ) const override;
     370                 :            :     bool uriIsBlocklisted( const QString &uri ) const override;
     371                 :            :     QgsGdalProvider *createProvider( const QString &uri, const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags = QgsDataProvider::ReadFlags() ) override;
     372                 :            :     QgsGdalProvider *createRasterDataProvider(
     373                 :            :       const QString &uri,
     374                 :            :       const QString &format,
     375                 :            :       int nBands,
     376                 :            :       Qgis::DataType type,
     377                 :            :       int width,
     378                 :            :       int height,
     379                 :            :       double *geoTransform,
     380                 :            :       const QgsCoordinateReferenceSystem &crs,
     381                 :            :       const QStringList &createOptions ) override;
     382                 :            :     QString filters( FilterType type ) override;
     383                 :            :     QList< QgsDataItemProvider * > dataItemProviders() const override;
     384                 :            :     QList<QPair<QString, QString> > pyramidResamplingMethods() override;
     385                 :            :     ProviderCapabilities providerCapabilities() const override;
     386                 :            : };
     387                 :            : 
     388                 :            : ///@endcond
     389                 :            : #endif

Generated by: LCOV version 1.14