LCOV - code coverage report
Current view: top level - frmts/derived - deriveddataset.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 82 83 98.8 %
Date: 2025-10-01 17:07:58 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL
       4             :  * Purpose:  Implementation of derived subdatasets
       5             :  * Author:   Julien Michel <julien dot michel at cnes dot fr>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2016 Julien Michel <julien dot michel at cnes dot fr>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  *****************************************************************************/
      12             : #include "../vrt/vrtdataset.h"
      13             : #include "gdal_frmts.h"
      14             : #include "gdal_pam.h"
      15             : #include "gdal_priv.h"
      16             : #include "derivedlist.h"
      17             : 
      18          34 : class DerivedDataset final : public VRTDataset
      19             : {
      20             :   public:
      21             :     DerivedDataset(int nXSize, int nYSize);
      22             : 
      23             :     ~DerivedDataset() override;
      24             : 
      25             :     static int Identify(GDALOpenInfo *);
      26             :     static GDALDataset *Open(GDALOpenInfo *);
      27             : };
      28             : 
      29          17 : DerivedDataset::DerivedDataset(int nXSize, int nYSize)
      30          17 :     : VRTDataset(nXSize, nYSize)
      31             : {
      32          17 :     poDriver = nullptr;
      33          17 :     SetWritable(FALSE);
      34          17 : }
      35             : 
      36             : DerivedDataset::~DerivedDataset() = default;
      37             : 
      38       89295 : int DerivedDataset::Identify(GDALOpenInfo *poOpenInfo)
      39             : {
      40             :     /* Try to open original dataset */
      41      178586 :     CPLString filename(poOpenInfo->pszFilename);
      42             : 
      43             :     /* DERIVED_SUBDATASET should be first domain */
      44       89301 :     const size_t dsds_pos = filename.find("DERIVED_SUBDATASET:");
      45             : 
      46       89291 :     if (dsds_pos != 0)
      47             :     {
      48             :         /* Unable to Open in this case */
      49       89270 :         return FALSE;
      50             :     }
      51             : 
      52          21 :     return TRUE;
      53             : }
      54             : 
      55          21 : GDALDataset *DerivedDataset::Open(GDALOpenInfo *poOpenInfo)
      56             : {
      57             :     /* Try to open original dataset */
      58          42 :     CPLString filename(poOpenInfo->pszFilename);
      59             : 
      60             :     /* DERIVED_SUBDATASET should be first domain */
      61          21 :     const size_t dsds_pos = filename.find("DERIVED_SUBDATASET:");
      62          21 :     const size_t nPrefixLen = strlen("DERIVED_SUBDATASET:");
      63             : 
      64          21 :     if (dsds_pos != 0)
      65             :     {
      66             :         /* Unable to Open in this case */
      67           0 :         return nullptr;
      68             :     }
      69             : 
      70             :     /* Next, we need to now which derived dataset to compute */
      71          21 :     const size_t alg_pos = filename.find(":", nPrefixLen + 1);
      72          21 :     if (alg_pos == std::string::npos)
      73             :     {
      74             :         /* Unable to Open if we do not find the name of the derived dataset */
      75           1 :         return nullptr;
      76             :     }
      77             : 
      78          40 :     CPLString odDerivedName = filename.substr(nPrefixLen, alg_pos - nPrefixLen);
      79             : 
      80          20 :     CPLDebug("DerivedDataset::Open", "Derived dataset requested: %s",
      81             :              odDerivedName.c_str());
      82             : 
      83          40 :     CPLString pixelFunctionName = "";
      84          20 :     bool datasetFound = false;
      85             : 
      86          20 :     unsigned int nbSupportedDerivedDS(0);
      87          20 :     GDALDataType type = GDT_Float64;
      88             : 
      89             :     const DerivedDatasetDescription *poDDSDesc =
      90          20 :         GDALGetDerivedDatasetDescriptions(&nbSupportedDerivedDS);
      91             : 
      92         160 :     for (unsigned int derivedId = 0; derivedId < nbSupportedDerivedDS;
      93             :          ++derivedId)
      94             :     {
      95         140 :         if (odDerivedName == poDDSDesc[derivedId].pszDatasetName)
      96             :         {
      97          19 :             datasetFound = true;
      98          19 :             pixelFunctionName = poDDSDesc[derivedId].pszPixelFunction;
      99             :             type =
     100          19 :                 GDALGetDataTypeByName(poDDSDesc[derivedId].pszOutputPixelType);
     101             :         }
     102             :     }
     103             : 
     104          20 :     if (!datasetFound)
     105             :     {
     106           1 :         return nullptr;
     107             :     }
     108             : 
     109             :     CPLString odFilename =
     110          38 :         filename.substr(alg_pos + 1, filename.size() - alg_pos);
     111             : 
     112             :     auto poTmpDS = std::unique_ptr<GDALDataset>(
     113          38 :         GDALDataset::Open(odFilename, GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR));
     114             : 
     115          19 :     if (poTmpDS == nullptr)
     116           1 :         return nullptr;
     117             : 
     118          18 :     int nbBands = poTmpDS->GetRasterCount();
     119             : 
     120          18 :     if (nbBands == 0)
     121             :     {
     122           1 :         return nullptr;
     123             :     }
     124             : 
     125          17 :     int nRows = poTmpDS->GetRasterYSize();
     126          17 :     int nCols = poTmpDS->GetRasterXSize();
     127             : 
     128          17 :     DerivedDataset *poDS = new DerivedDataset(nCols, nRows);
     129             : 
     130             :     // Transfer metadata
     131          17 :     poDS->SetMetadata(poTmpDS->GetMetadata());
     132             : 
     133          17 :     char **papszRPC = poTmpDS->GetMetadata("RPC");
     134          17 :     if (papszRPC)
     135             :     {
     136           1 :         poDS->SetMetadata(papszRPC, "RPC");
     137             :     }
     138             : 
     139             :     // Transfer projection
     140          17 :     poDS->SetProjection(poTmpDS->GetProjectionRef());
     141             : 
     142             :     // Transfer geotransform
     143          17 :     GDALGeoTransform gt;
     144          17 :     if (poTmpDS->GetGeoTransform(gt) == CE_None)
     145             :     {
     146           9 :         poDS->SetGeoTransform(gt);
     147             :     }
     148             : 
     149             :     // Transfer GCPs
     150          17 :     const char *gcpProjection = poTmpDS->GetGCPProjection();
     151          17 :     int nbGcps = poTmpDS->GetGCPCount();
     152          17 :     poDS->SetGCPs(nbGcps, poTmpDS->GetGCPs(), gcpProjection);
     153             : 
     154             :     // Map bands
     155          34 :     for (int nBand = 1; nBand <= nbBands; ++nBand)
     156             :     {
     157             :         VRTDerivedRasterBand *poBand =
     158          17 :             new VRTDerivedRasterBand(poDS, nBand, type, nCols, nRows);
     159          17 :         poDS->SetBand(nBand, poBand);
     160             : 
     161          17 :         poBand->SetPixelFunctionName(pixelFunctionName);
     162          17 :         poBand->SetSourceTransferType(
     163             :             poTmpDS->GetRasterBand(nBand)->GetRasterDataType());
     164             : 
     165          17 :         poBand->AddComplexSource(odFilename, nBand, 0, 0, nCols, nRows, 0, 0,
     166             :                                  nCols, nRows);
     167             :     }
     168             : 
     169             :     // If dataset is a real file, initialize overview manager
     170             :     VSIStatBufL sStat;
     171          17 :     if (VSIStatL(odFilename, &sStat) == 0)
     172             :     {
     173          34 :         CPLString path = CPLGetPathSafe(odFilename);
     174          34 :         CPLString ovrFileName = "DERIVED_DATASET_" + odDerivedName + "_" +
     175          34 :                                 CPLGetFilename(odFilename);
     176          34 :         CPLString ovrFilePath = CPLFormFilenameSafe(path, ovrFileName, nullptr);
     177             : 
     178          17 :         poDS->oOvManager.Initialize(poDS, ovrFilePath);
     179             :     }
     180             : 
     181          17 :     return poDS;
     182             : }
     183             : 
     184        2033 : void GDALRegister_Derived()
     185             : {
     186        2033 :     if (GDALGetDriverByName("DERIVED") != nullptr)
     187         283 :         return;
     188             : 
     189        1750 :     GDALDriver *poDriver = new GDALDriver();
     190             : 
     191        1750 :     poDriver->SetDescription("DERIVED");
     192             : #ifdef GDAL_DCAP_RASTER
     193        1750 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     194             : #endif
     195        1750 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
     196        1750 :                               "Derived datasets using VRT pixel functions");
     197        1750 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC,
     198        1750 :                               "drivers/raster/derived.html");
     199        1750 :     poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "NO");
     200             : 
     201        1750 :     poDriver->pfnOpen = DerivedDataset::Open;
     202        1750 :     poDriver->pfnIdentify = DerivedDataset::Identify;
     203             : 
     204        1750 :     GetGDALDriverManager()->RegisterDriver(poDriver);
     205             : }

Generated by: LCOV version 1.14