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-05-02 22:57:13 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             :  * Permission is hereby granted, free of charge, to any person obtaining a
      11             :  * copy of this software and associated documentation files (the "Software"),
      12             :  * to deal in the Software without restriction, including without limitation
      13             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      14             :  * and/or sell copies of the Software, and to permit persons to whom the
      15             :  * Software is furnished to do so, subject to the following conditions:
      16             :  *
      17             :  * The above copyright notice and this permission notice shall be included
      18             :  * in all copies or substantial portions of the Software.
      19             :  *
      20             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      21             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      22             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      23             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      24             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      25             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      26             :  * DEALINGS IN THE SOFTWARE.
      27             :  *****************************************************************************/
      28             : #include "../vrt/vrtdataset.h"
      29             : #include "gdal_pam.h"
      30             : #include "derivedlist.h"
      31             : 
      32             : class DerivedDataset final : public VRTDataset
      33             : {
      34             :   public:
      35             :     DerivedDataset(int nXSize, int nYSize);
      36             : 
      37          30 :     ~DerivedDataset()
      38          15 :     {
      39          30 :     }
      40             : 
      41             :     static int Identify(GDALOpenInfo *);
      42             :     static GDALDataset *Open(GDALOpenInfo *);
      43             : };
      44             : 
      45          15 : DerivedDataset::DerivedDataset(int nXSize, int nYSize)
      46          15 :     : VRTDataset(nXSize, nYSize)
      47             : {
      48          15 :     poDriver = nullptr;
      49          15 :     SetWritable(FALSE);
      50          15 : }
      51             : 
      52       70948 : int DerivedDataset::Identify(GDALOpenInfo *poOpenInfo)
      53             : {
      54             :     /* Try to open original dataset */
      55      141887 :     CPLString filename(poOpenInfo->pszFilename);
      56             : 
      57             :     /* DERIVED_SUBDATASET should be first domain */
      58       70947 :     const size_t dsds_pos = filename.find("DERIVED_SUBDATASET:");
      59             : 
      60       70939 :     if (dsds_pos != 0)
      61             :     {
      62             :         /* Unable to Open in this case */
      63       70907 :         return FALSE;
      64             :     }
      65             : 
      66          32 :     return TRUE;
      67             : }
      68             : 
      69          19 : GDALDataset *DerivedDataset::Open(GDALOpenInfo *poOpenInfo)
      70             : {
      71             :     /* Try to open original dataset */
      72          38 :     CPLString filename(poOpenInfo->pszFilename);
      73             : 
      74             :     /* DERIVED_SUBDATASET should be first domain */
      75          19 :     const size_t dsds_pos = filename.find("DERIVED_SUBDATASET:");
      76          19 :     const size_t nPrefixLen = strlen("DERIVED_SUBDATASET:");
      77             : 
      78          19 :     if (dsds_pos != 0)
      79             :     {
      80             :         /* Unable to Open in this case */
      81           0 :         return nullptr;
      82             :     }
      83             : 
      84             :     /* Next, we need to now which derived dataset to compute */
      85          19 :     const size_t alg_pos = filename.find(":", nPrefixLen + 1);
      86          19 :     if (alg_pos == std::string::npos)
      87             :     {
      88             :         /* Unable to Open if we do not find the name of the derived dataset */
      89           1 :         return nullptr;
      90             :     }
      91             : 
      92          36 :     CPLString odDerivedName = filename.substr(nPrefixLen, alg_pos - nPrefixLen);
      93             : 
      94          18 :     CPLDebug("DerivedDataset::Open", "Derived dataset requested: %s",
      95             :              odDerivedName.c_str());
      96             : 
      97          36 :     CPLString pixelFunctionName = "";
      98          18 :     bool datasetFound = false;
      99             : 
     100          18 :     unsigned int nbSupportedDerivedDS(0);
     101          18 :     GDALDataType type = GDT_Float64;
     102             : 
     103             :     const DerivedDatasetDescription *poDDSDesc =
     104          18 :         GDALGetDerivedDatasetDescriptions(&nbSupportedDerivedDS);
     105             : 
     106         144 :     for (unsigned int derivedId = 0; derivedId < nbSupportedDerivedDS;
     107             :          ++derivedId)
     108             :     {
     109         126 :         if (odDerivedName == poDDSDesc[derivedId].pszDatasetName)
     110             :         {
     111          17 :             datasetFound = true;
     112          17 :             pixelFunctionName = poDDSDesc[derivedId].pszPixelFunction;
     113             :             type =
     114          17 :                 GDALGetDataTypeByName(poDDSDesc[derivedId].pszOutputPixelType);
     115             :         }
     116             :     }
     117             : 
     118          18 :     if (!datasetFound)
     119             :     {
     120           1 :         return nullptr;
     121             :     }
     122             : 
     123             :     CPLString odFilename =
     124          34 :         filename.substr(alg_pos + 1, filename.size() - alg_pos);
     125             : 
     126          17 :     GDALDataset *poTmpDS = (GDALDataset *)GDALOpen(odFilename, GA_ReadOnly);
     127             : 
     128          17 :     if (poTmpDS == nullptr)
     129           1 :         return nullptr;
     130             : 
     131          16 :     int nbBands = poTmpDS->GetRasterCount();
     132             : 
     133          16 :     if (nbBands == 0)
     134             :     {
     135           1 :         GDALClose(poTmpDS);
     136           1 :         return nullptr;
     137             :     }
     138             : 
     139          15 :     int nRows = poTmpDS->GetRasterYSize();
     140          15 :     int nCols = poTmpDS->GetRasterXSize();
     141             : 
     142          15 :     DerivedDataset *poDS = new DerivedDataset(nCols, nRows);
     143             : 
     144             :     // Transfer metadata
     145          15 :     poDS->SetMetadata(poTmpDS->GetMetadata());
     146             : 
     147          15 :     char **papszRPC = poTmpDS->GetMetadata("RPC");
     148          15 :     if (papszRPC)
     149             :     {
     150           1 :         poDS->SetMetadata(papszRPC, "RPC");
     151             :     }
     152             : 
     153             :     // Transfer projection
     154          15 :     poDS->SetProjection(poTmpDS->GetProjectionRef());
     155             : 
     156             :     // Transfer geotransform
     157             :     double padfTransform[6];
     158          15 :     CPLErr transformOk = poTmpDS->GetGeoTransform(padfTransform);
     159             : 
     160          15 :     if (transformOk == CE_None)
     161             :     {
     162           7 :         poDS->SetGeoTransform(padfTransform);
     163             :     }
     164             : 
     165             :     // Transfer GCPs
     166          15 :     const char *gcpProjection = poTmpDS->GetGCPProjection();
     167          15 :     int nbGcps = poTmpDS->GetGCPCount();
     168          15 :     poDS->SetGCPs(nbGcps, poTmpDS->GetGCPs(), gcpProjection);
     169             : 
     170             :     // Map bands
     171          30 :     for (int nBand = 1; nBand <= nbBands; ++nBand)
     172             :     {
     173             :         VRTDerivedRasterBand *poBand =
     174          15 :             new VRTDerivedRasterBand(poDS, nBand, type, nCols, nRows);
     175          15 :         poDS->SetBand(nBand, poBand);
     176             : 
     177          15 :         poBand->SetPixelFunctionName(pixelFunctionName);
     178          15 :         poBand->SetSourceTransferType(
     179             :             poTmpDS->GetRasterBand(nBand)->GetRasterDataType());
     180             : 
     181          15 :         poBand->AddComplexSource(odFilename, nBand, 0, 0, nCols, nRows, 0, 0,
     182             :                                  nCols, nRows);
     183             :     }
     184             : 
     185          15 :     GDALClose(poTmpDS);
     186             : 
     187             :     // If dataset is a real file, initialize overview manager
     188             :     VSIStatBufL sStat;
     189          15 :     if (VSIStatL(odFilename, &sStat) == 0)
     190             :     {
     191          30 :         CPLString path = CPLGetPath(odFilename);
     192          30 :         CPLString ovrFileName = "DERIVED_DATASET_" + odDerivedName + "_" +
     193          30 :                                 CPLGetFilename(odFilename);
     194          30 :         CPLString ovrFilePath = CPLFormFilename(path, ovrFileName, nullptr);
     195             : 
     196          15 :         poDS->oOvManager.Initialize(poDS, ovrFilePath);
     197             :     }
     198             : 
     199          15 :     return poDS;
     200             : }
     201             : 
     202        1512 : void GDALRegister_Derived()
     203             : {
     204        1512 :     if (GDALGetDriverByName("DERIVED") != nullptr)
     205         295 :         return;
     206             : 
     207        1217 :     GDALDriver *poDriver = new GDALDriver();
     208             : 
     209        1217 :     poDriver->SetDescription("DERIVED");
     210             : #ifdef GDAL_DCAP_RASTER
     211        1217 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     212             : #endif
     213        1217 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
     214        1217 :                               "Derived datasets using VRT pixel functions");
     215        1217 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC,
     216        1217 :                               "drivers/raster/derived.html");
     217        1217 :     poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "NO");
     218             : 
     219        1217 :     poDriver->pfnOpen = DerivedDataset::Open;
     220        1217 :     poDriver->pfnIdentify = DerivedDataset::Identify;
     221             : 
     222        1217 :     GetGDALDriverManager()->RegisterDriver(poDriver);
     223             : }

Generated by: LCOV version 1.14