LCOV - code coverage report
Current view: top level - frmts/derived - deriveddataset.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 86 87 98.9 %
Date: 2024-11-21 22:18:42 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             : class DerivedDataset final : public VRTDataset
      17             : {
      18             :   public:
      19             :     DerivedDataset(int nXSize, int nYSize);
      20             : 
      21          34 :     ~DerivedDataset()
      22          17 :     {
      23          34 :     }
      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       76096 : int DerivedDataset::Identify(GDALOpenInfo *poOpenInfo)
      37             : {
      38             :     /* Try to open original dataset */
      39      152183 :     CPLString filename(poOpenInfo->pszFilename);
      40             : 
      41             :     /* DERIVED_SUBDATASET should be first domain */
      42       76094 :     const size_t dsds_pos = filename.find("DERIVED_SUBDATASET:");
      43             : 
      44       76087 :     if (dsds_pos != 0)
      45             :     {
      46             :         /* Unable to Open in this case */
      47       76057 :         return FALSE;
      48             :     }
      49             : 
      50          30 :     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          19 :     GDALDataset *poTmpDS = (GDALDataset *)GDALOpen(odFilename, GA_ReadOnly);
     111             : 
     112          19 :     if (poTmpDS == nullptr)
     113           1 :         return nullptr;
     114             : 
     115          18 :     int nbBands = poTmpDS->GetRasterCount();
     116             : 
     117          18 :     if (nbBands == 0)
     118             :     {
     119           1 :         GDALClose(poTmpDS);
     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             :     double padfTransform[6];
     142          17 :     CPLErr transformOk = poTmpDS->GetGeoTransform(padfTransform);
     143             : 
     144          17 :     if (transformOk == CE_None)
     145             :     {
     146           9 :         poDS->SetGeoTransform(padfTransform);
     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          17 :     GDALClose(poTmpDS);
     170             : 
     171             :     // If dataset is a real file, initialize overview manager
     172             :     VSIStatBufL sStat;
     173          17 :     if (VSIStatL(odFilename, &sStat) == 0)
     174             :     {
     175          34 :         CPLString path = CPLGetPath(odFilename);
     176          34 :         CPLString ovrFileName = "DERIVED_DATASET_" + odDerivedName + "_" +
     177          34 :                                 CPLGetFilename(odFilename);
     178          34 :         CPLString ovrFilePath = CPLFormFilename(path, ovrFileName, nullptr);
     179             : 
     180          17 :         poDS->oOvManager.Initialize(poDS, ovrFilePath);
     181             :     }
     182             : 
     183          17 :     return poDS;
     184             : }
     185             : 
     186        1595 : void GDALRegister_Derived()
     187             : {
     188        1595 :     if (GDALGetDriverByName("DERIVED") != nullptr)
     189         302 :         return;
     190             : 
     191        1293 :     GDALDriver *poDriver = new GDALDriver();
     192             : 
     193        1293 :     poDriver->SetDescription("DERIVED");
     194             : #ifdef GDAL_DCAP_RASTER
     195        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     196             : #endif
     197        1293 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
     198        1293 :                               "Derived datasets using VRT pixel functions");
     199        1293 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC,
     200        1293 :                               "drivers/raster/derived.html");
     201        1293 :     poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "NO");
     202             : 
     203        1293 :     poDriver->pfnOpen = DerivedDataset::Open;
     204        1293 :     poDriver->pfnIdentify = DerivedDataset::Identify;
     205             : 
     206        1293 :     GetGDALDriverManager()->RegisterDriver(poDriver);
     207             : }

Generated by: LCOV version 1.14