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

Generated by: LCOV version 1.14