LCOV - code coverage report
Current view: top level - frmts/vrt - vrtdriver.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 177 211 83.9 %
Date: 2024-05-06 22:33:47 Functions: 9 11 81.8 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  Virtual GDAL Datasets
       4             :  * Purpose:  Implementation of VRTDriver
       5             :  * Author:   Frank Warmerdam <warmerdam@pobox.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2003, Frank Warmerdam <warmerdam@pobox.com>
       9             :  * Copyright (c) 2009-2013, Even Rouault <even dot rouault at spatialys.com>
      10             :  *
      11             :  * Permission is hereby granted, free of charge, to any person obtaining a
      12             :  * copy of this software and associated documentation files (the "Software"),
      13             :  * to deal in the Software without restriction, including without limitation
      14             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15             :  * and/or sell copies of the Software, and to permit persons to whom the
      16             :  * Software is furnished to do so, subject to the following conditions:
      17             :  *
      18             :  * The above copyright notice and this permission notice shall be included
      19             :  * in all copies or substantial portions of the Software.
      20             :  *
      21             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27             :  * DEALINGS IN THE SOFTWARE.
      28             :  ****************************************************************************/
      29             : 
      30             : #include "vrtdataset.h"
      31             : 
      32             : #include "cpl_minixml.h"
      33             : #include "cpl_string.h"
      34             : #include "gdal_alg_priv.h"
      35             : #include "gdal_frmts.h"
      36             : 
      37             : #include <mutex>
      38             : 
      39             : /*! @cond Doxygen_Suppress */
      40             : 
      41             : /************************************************************************/
      42             : /*                             VRTDriver()                              */
      43             : /************************************************************************/
      44             : 
      45        2438 : VRTDriver::VRTDriver() : papszSourceParsers(nullptr)
      46             : {
      47             : #if 0
      48             :     pDeserializerData = GDALRegisterTransformDeserializer(
      49             :         "WarpedOverviewTransformer",
      50             :         VRTWarpedOverviewTransform,
      51             :         VRTDeserializeWarpedOverviewTransformer );
      52             : #endif
      53        2438 : }
      54             : 
      55             : /************************************************************************/
      56             : /*                             ~VRTDriver()                             */
      57             : /************************************************************************/
      58             : 
      59        3412 : VRTDriver::~VRTDriver()
      60             : 
      61             : {
      62        1706 :     CSLDestroy(papszSourceParsers);
      63        1706 :     VRTDerivedRasterBand::Cleanup();
      64             : #if 0
      65             :     if(  pDeserializerData )
      66             :     {
      67             :         GDALUnregisterTransformDeserializer( pDeserializerData );
      68             :     }
      69             : #endif
      70        3412 : }
      71             : 
      72             : /************************************************************************/
      73             : /*                      GetMetadataDomainList()                         */
      74             : /************************************************************************/
      75             : 
      76           0 : char **VRTDriver::GetMetadataDomainList()
      77             : {
      78           0 :     return BuildMetadataDomainList(GDALDriver::GetMetadataDomainList(), TRUE,
      79           0 :                                    "SourceParsers", nullptr);
      80             : }
      81             : 
      82             : /************************************************************************/
      83             : /*                            GetMetadata()                             */
      84             : /************************************************************************/
      85             : 
      86         467 : char **VRTDriver::GetMetadata(const char *pszDomain)
      87             : 
      88             : {
      89         467 :     if (pszDomain && EQUAL(pszDomain, "SourceParsers"))
      90           0 :         return papszSourceParsers;
      91             : 
      92         467 :     return GDALDriver::GetMetadata(pszDomain);
      93             : }
      94             : 
      95             : /************************************************************************/
      96             : /*                            SetMetadata()                             */
      97             : /************************************************************************/
      98             : 
      99           0 : CPLErr VRTDriver::SetMetadata(char **papszMetadata, const char *pszDomain)
     100             : 
     101             : {
     102           0 :     if (pszDomain && EQUAL(pszDomain, "SourceParsers"))
     103             :     {
     104           0 :         m_oMapSourceParser.clear();
     105           0 :         CSLDestroy(papszSourceParsers);
     106           0 :         papszSourceParsers = CSLDuplicate(papszMetadata);
     107           0 :         return CE_None;
     108             :     }
     109             : 
     110           0 :     return GDALDriver::SetMetadata(papszMetadata, pszDomain);
     111             : }
     112             : 
     113             : /************************************************************************/
     114             : /*                          AddSourceParser()                           */
     115             : /************************************************************************/
     116             : 
     117        7314 : void VRTDriver::AddSourceParser(const char *pszElementName,
     118             :                                 VRTSourceParser pfnParser)
     119             : 
     120             : {
     121        7314 :     m_oMapSourceParser[pszElementName] = pfnParser;
     122             : 
     123             :     // Below won't work on architectures with "capability pointers"
     124             : 
     125        7314 :     char szPtrValue[128] = {'\0'};
     126             :     void *ptr;
     127        7314 :     CPL_STATIC_ASSERT(sizeof(pfnParser) == sizeof(void *));
     128        7314 :     memcpy(&ptr, &pfnParser, sizeof(void *));
     129        7314 :     int nRet = CPLPrintPointer(szPtrValue, ptr, sizeof(szPtrValue));
     130        7314 :     szPtrValue[nRet] = 0;
     131             : 
     132        7314 :     papszSourceParsers =
     133        7314 :         CSLSetNameValue(papszSourceParsers, pszElementName, szPtrValue);
     134        7314 : }
     135             : 
     136             : /************************************************************************/
     137             : /*                            ParseSource()                             */
     138             : /************************************************************************/
     139             : 
     140             : VRTSource *
     141        3013 : VRTDriver::ParseSource(const CPLXMLNode *psSrc, const char *pszVRTPath,
     142             :                        std::map<CPLString, GDALDataset *> &oMapSharedSources)
     143             : 
     144             : {
     145             : 
     146        3013 :     if (psSrc == nullptr || psSrc->eType != CXT_Element)
     147             :     {
     148           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     149             :                  "Corrupt or empty VRT source XML document.");
     150           0 :         return nullptr;
     151             :     }
     152             : 
     153        3013 :     if (!m_oMapSourceParser.empty())
     154             :     {
     155        3013 :         auto oIter = m_oMapSourceParser.find(psSrc->pszValue);
     156        3013 :         if (oIter != m_oMapSourceParser.end())
     157             :         {
     158        1503 :             return oIter->second(psSrc, pszVRTPath, oMapSharedSources);
     159             :         }
     160        1510 :         return nullptr;
     161             :     }
     162             : 
     163             :     // Below won't work on architectures with "capability pointers"
     164             : 
     165             :     const char *pszParserFunc =
     166           0 :         CSLFetchNameValue(papszSourceParsers, psSrc->pszValue);
     167           0 :     if (pszParserFunc == nullptr)
     168           0 :         return nullptr;
     169             : 
     170             :     VRTSourceParser pfnParser;
     171           0 :     CPL_STATIC_ASSERT(sizeof(pfnParser) == sizeof(void *));
     172             :     void *ptr =
     173           0 :         CPLScanPointer(pszParserFunc, static_cast<int>(strlen(pszParserFunc)));
     174           0 :     memcpy(&pfnParser, &ptr, sizeof(void *));
     175             : 
     176           0 :     if (pfnParser == nullptr)
     177           0 :         return nullptr;
     178             : 
     179           0 :     return pfnParser(psSrc, pszVRTPath, oMapSharedSources);
     180             : }
     181             : 
     182             : /************************************************************************/
     183             : /*                           VRTCreateCopy()                            */
     184             : /************************************************************************/
     185             : 
     186         323 : static GDALDataset *VRTCreateCopy(const char *pszFilename, GDALDataset *poSrcDS,
     187             :                                   int /* bStrict */, char **papszOptions,
     188             :                                   GDALProgressFunc /* pfnProgress */,
     189             :                                   void * /* pProgressData */)
     190             : {
     191         323 :     CPLAssert(nullptr != poSrcDS);
     192             : 
     193             :     /* -------------------------------------------------------------------- */
     194             :     /*      If the source dataset is a virtual dataset then just write      */
     195             :     /*      it to disk as a special case to avoid extra layers of           */
     196             :     /*      indirection.                                                    */
     197             :     /* -------------------------------------------------------------------- */
     198         323 :     if (auto poSrcVRTDS = dynamic_cast<VRTDataset *>(poSrcDS))
     199             :     {
     200             : 
     201             :         /* --------------------------------------------------------------------
     202             :          */
     203             :         /*      Convert tree to a single block of XML text. */
     204             :         /* --------------------------------------------------------------------
     205             :          */
     206         104 :         char *pszVRTPath = CPLStrdup(CPLGetPath(pszFilename));
     207         104 :         poSrcVRTDS->UnsetPreservedRelativeFilenames();
     208         104 :         CPLXMLNode *psDSTree = poSrcVRTDS->SerializeToXML(pszVRTPath);
     209             : 
     210         104 :         char *pszXML = CPLSerializeXMLTree(psDSTree);
     211             : 
     212         104 :         CPLDestroyXMLNode(psDSTree);
     213             : 
     214         104 :         CPLFree(pszVRTPath);
     215             : 
     216             :         /* --------------------------------------------------------------------
     217             :          */
     218             :         /*      Write to disk. */
     219             :         /* --------------------------------------------------------------------
     220             :          */
     221         104 :         GDALDataset *pCopyDS = nullptr;
     222             : 
     223         104 :         if (0 != strlen(pszFilename))
     224             :         {
     225         102 :             VSILFILE *fpVRT = VSIFOpenL(pszFilename, "wb");
     226         102 :             if (fpVRT == nullptr)
     227             :             {
     228           1 :                 CPLError(CE_Failure, CPLE_AppDefined, "Cannot create %s",
     229             :                          pszFilename);
     230           1 :                 CPLFree(pszXML);
     231           1 :                 return nullptr;
     232             :             }
     233             : 
     234         101 :             bool bRet = VSIFWriteL(pszXML, strlen(pszXML), 1, fpVRT) > 0;
     235         101 :             if (VSIFCloseL(fpVRT) != 0)
     236           0 :                 bRet = false;
     237             : 
     238         101 :             if (bRet)
     239         101 :                 pCopyDS = GDALDataset::Open(
     240             :                     pszFilename,
     241             :                     GDAL_OF_RASTER | GDAL_OF_MULTIDIM_RASTER | GDAL_OF_UPDATE);
     242             :         }
     243             :         else
     244             :         {
     245             :             /* No destination file is given, so pass serialized XML directly. */
     246           2 :             pCopyDS = GDALDataset::Open(pszXML, GDAL_OF_RASTER |
     247             :                                                     GDAL_OF_MULTIDIM_RASTER |
     248             :                                                     GDAL_OF_UPDATE);
     249             :         }
     250             : 
     251         103 :         CPLFree(pszXML);
     252             : 
     253         103 :         return pCopyDS;
     254             :     }
     255             : 
     256             :     /* -------------------------------------------------------------------- */
     257             :     /*      Multidimensional raster ?                                       */
     258             :     /* -------------------------------------------------------------------- */
     259         438 :     auto poSrcGroup = poSrcDS->GetRootGroup();
     260         219 :     if (poSrcGroup != nullptr)
     261             :     {
     262             :         auto poDstDS = std::unique_ptr<GDALDataset>(
     263           4 :             VRTDataset::CreateMultiDimensional(pszFilename, nullptr, nullptr));
     264           2 :         if (!poDstDS)
     265           0 :             return nullptr;
     266           4 :         auto poDstGroup = poDstDS->GetRootGroup();
     267           2 :         if (!poDstGroup)
     268           0 :             return nullptr;
     269           2 :         if (GDALDriver::DefaultCreateCopyMultiDimensional(
     270           2 :                 poSrcDS, poDstDS.get(), false, nullptr, nullptr, nullptr) !=
     271             :             CE_None)
     272           0 :             return nullptr;
     273           2 :         return poDstDS.release();
     274             :     }
     275             : 
     276             :     /* -------------------------------------------------------------------- */
     277             :     /*      Create the virtual dataset.                                     */
     278             :     /* -------------------------------------------------------------------- */
     279         217 :     VRTDataset *poVRTDS = static_cast<VRTDataset *>(VRTDataset::Create(
     280             :         pszFilename, poSrcDS->GetRasterXSize(), poSrcDS->GetRasterYSize(), 0,
     281             :         GDT_Byte, papszOptions));
     282         217 :     if (poVRTDS == nullptr)
     283           0 :         return nullptr;
     284             : 
     285             :     /* -------------------------------------------------------------------- */
     286             :     /*      Do we have a geotransform?                                      */
     287             :     /* -------------------------------------------------------------------- */
     288         217 :     double adfGeoTransform[6] = {0.0};
     289             : 
     290         217 :     if (poSrcDS->GetGeoTransform(adfGeoTransform) == CE_None)
     291             :     {
     292         191 :         poVRTDS->SetGeoTransform(adfGeoTransform);
     293             :     }
     294             : 
     295             :     /* -------------------------------------------------------------------- */
     296             :     /*      Copy projection                                                 */
     297             :     /* -------------------------------------------------------------------- */
     298         217 :     poVRTDS->SetSpatialRef(poSrcDS->GetSpatialRef());
     299             : 
     300             :     /* -------------------------------------------------------------------- */
     301             :     /*      Emit dataset level metadata.                                    */
     302             :     /* -------------------------------------------------------------------- */
     303             :     const char *pszCopySrcMDD =
     304         217 :         CSLFetchNameValueDef(papszOptions, "COPY_SRC_MDD", "AUTO");
     305         217 :     char **papszSrcMDD = CSLFetchNameValueMultiple(papszOptions, "SRC_MDD");
     306         217 :     if (EQUAL(pszCopySrcMDD, "AUTO") || CPLTestBool(pszCopySrcMDD) ||
     307             :         papszSrcMDD)
     308             :     {
     309         217 :         if (!papszSrcMDD || CSLFindString(papszSrcMDD, "") >= 0 ||
     310           1 :             CSLFindString(papszSrcMDD, "_DEFAULT_") >= 0)
     311             :         {
     312         215 :             poVRTDS->SetMetadata(poSrcDS->GetMetadata());
     313             :         }
     314             : 
     315             :         /* -------------------------------------------------------------------- */
     316             :         /*      Copy any special domains that should be transportable.          */
     317             :         /* -------------------------------------------------------------------- */
     318         216 :         constexpr const char *apszDefaultDomains[] = {"RPC", "IMD",
     319             :                                                       "GEOLOCATION"};
     320         864 :         for (const char *pszDomain : apszDefaultDomains)
     321             :         {
     322         648 :             if (!papszSrcMDD || CSLFindString(papszSrcMDD, pszDomain) >= 0)
     323             :             {
     324         642 :                 char **papszMD = poSrcDS->GetMetadata(pszDomain);
     325         642 :                 if (papszMD)
     326           0 :                     poVRTDS->SetMetadata(papszMD, pszDomain);
     327             :             }
     328             :         }
     329             : 
     330         216 :         if ((!EQUAL(pszCopySrcMDD, "AUTO") && CPLTestBool(pszCopySrcMDD)) ||
     331             :             papszSrcMDD)
     332             :         {
     333           3 :             char **papszDomainList = poSrcDS->GetMetadataDomainList();
     334           3 :             constexpr const char *apszReservedDomains[] = {
     335             :                 "IMAGE_STRUCTURE", "DERIVED_SUBDATASETS"};
     336          15 :             for (char **papszIter = papszDomainList; papszIter && *papszIter;
     337             :                  ++papszIter)
     338             :             {
     339          12 :                 const char *pszDomain = *papszIter;
     340          18 :                 if (pszDomain[0] != 0 &&
     341           6 :                     (!papszSrcMDD ||
     342           6 :                      CSLFindString(papszSrcMDD, pszDomain) >= 0))
     343             :                 {
     344           5 :                     bool bCanCopy = true;
     345          20 :                     for (const char *pszOtherDomain : apszDefaultDomains)
     346             :                     {
     347          15 :                         if (EQUAL(pszDomain, pszOtherDomain))
     348             :                         {
     349           0 :                             bCanCopy = false;
     350           0 :                             break;
     351             :                         }
     352             :                     }
     353           5 :                     if (!papszSrcMDD)
     354             :                     {
     355           6 :                         for (const char *pszOtherDomain : apszReservedDomains)
     356             :                         {
     357           5 :                             if (EQUAL(pszDomain, pszOtherDomain))
     358             :                             {
     359           2 :                                 bCanCopy = false;
     360           2 :                                 break;
     361             :                             }
     362             :                         }
     363             :                     }
     364           5 :                     if (bCanCopy)
     365             :                     {
     366           3 :                         poVRTDS->SetMetadata(poSrcDS->GetMetadata(pszDomain),
     367           3 :                                              pszDomain);
     368             :                     }
     369             :                 }
     370             :             }
     371           3 :             CSLDestroy(papszDomainList);
     372             :         }
     373             :     }
     374         217 :     CSLDestroy(papszSrcMDD);
     375             : 
     376             :     {
     377             :         const char *pszInterleave =
     378         217 :             poSrcDS->GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE");
     379         217 :         if (pszInterleave)
     380             :         {
     381         168 :             poVRTDS->SetMetadataItem("INTERLEAVE", pszInterleave,
     382         168 :                                      "IMAGE_STRUCTURE");
     383             :         }
     384             :     }
     385             :     {
     386             :         const char *pszCompression =
     387         217 :             poSrcDS->GetMetadataItem("COMPRESSION", "IMAGE_STRUCTURE");
     388         217 :         if (pszCompression)
     389             :         {
     390           5 :             poVRTDS->SetMetadataItem("COMPRESSION", pszCompression,
     391           5 :                                      "IMAGE_STRUCTURE");
     392             :         }
     393             :     }
     394             : 
     395             :     /* -------------------------------------------------------------------- */
     396             :     /*      GCPs                                                            */
     397             :     /* -------------------------------------------------------------------- */
     398         217 :     if (poSrcDS->GetGCPCount() > 0)
     399             :     {
     400           1 :         poVRTDS->SetGCPs(poSrcDS->GetGCPCount(), poSrcDS->GetGCPs(),
     401           1 :                          poSrcDS->GetGCPSpatialRef());
     402             :     }
     403             : 
     404             :     /* -------------------------------------------------------------------- */
     405             :     /*      Loop over all the bands.                                        */
     406             :     /* -------------------------------------------------------------------- */
     407         501 :     for (int iBand = 0; iBand < poSrcDS->GetRasterCount(); iBand++)
     408             :     {
     409         284 :         GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand(iBand + 1);
     410             : 
     411             :         /* --------------------------------------------------------------------
     412             :          */
     413             :         /*      Create the band with the appropriate band type. */
     414             :         /* --------------------------------------------------------------------
     415             :          */
     416         568 :         CPLStringList aosAddBandOptions;
     417         284 :         int nBlockXSize = poVRTDS->GetBlockXSize();
     418         284 :         int nBlockYSize = poVRTDS->GetBlockYSize();
     419         284 :         if (!poVRTDS->IsBlockSizeSpecified())
     420             :         {
     421         283 :             poSrcBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
     422             :         }
     423             :         aosAddBandOptions.SetNameValue("BLOCKXSIZE",
     424         284 :                                        CPLSPrintf("%d", nBlockXSize));
     425             :         aosAddBandOptions.SetNameValue("BLOCKYSIZE",
     426         284 :                                        CPLSPrintf("%d", nBlockYSize));
     427         284 :         poVRTDS->AddBand(poSrcBand->GetRasterDataType(), aosAddBandOptions);
     428             : 
     429             :         VRTSourcedRasterBand *poVRTBand = static_cast<VRTSourcedRasterBand *>(
     430         284 :             poVRTDS->GetRasterBand(iBand + 1));
     431             : 
     432             :         /* --------------------------------------------------------------------
     433             :          */
     434             :         /*      Setup source mapping. */
     435             :         /* --------------------------------------------------------------------
     436             :          */
     437         284 :         poVRTBand->AddSimpleSource(poSrcBand);
     438             : 
     439             :         /* --------------------------------------------------------------------
     440             :          */
     441             :         /*      Emit various band level metadata. */
     442             :         /* --------------------------------------------------------------------
     443             :          */
     444         284 :         poVRTBand->CopyCommonInfoFrom(poSrcBand);
     445             : 
     446             :         const char *pszCompression =
     447         284 :             poSrcBand->GetMetadataItem("COMPRESSION", "IMAGE_STRUCTURE");
     448         284 :         if (pszCompression)
     449             :         {
     450           3 :             poVRTBand->SetMetadataItem("COMPRESSION", pszCompression,
     451           3 :                                        "IMAGE_STRUCTURE");
     452             :         }
     453             : 
     454             :         /* --------------------------------------------------------------------
     455             :          */
     456             :         /*      Add specific mask band. */
     457             :         /* --------------------------------------------------------------------
     458             :          */
     459         284 :         if ((poSrcBand->GetMaskFlags() &
     460         284 :              (GMF_PER_DATASET | GMF_ALL_VALID | GMF_NODATA)) == 0)
     461             :         {
     462             :             VRTSourcedRasterBand *poVRTMaskBand = new VRTSourcedRasterBand(
     463           0 :                 poVRTDS, 0, poSrcBand->GetMaskBand()->GetRasterDataType(),
     464           0 :                 poSrcDS->GetRasterXSize(), poSrcDS->GetRasterYSize());
     465           0 :             poVRTMaskBand->AddMaskBandSource(poSrcBand);
     466           0 :             poVRTBand->SetMaskBand(poVRTMaskBand);
     467             :         }
     468             :     }
     469             : 
     470             :     /* -------------------------------------------------------------------- */
     471             :     /*      Add dataset mask band                                           */
     472             :     /* -------------------------------------------------------------------- */
     473         217 :     if (poSrcDS->GetRasterCount() != 0 &&
     474         433 :         poSrcDS->GetRasterBand(1) != nullptr &&
     475         216 :         poSrcDS->GetRasterBand(1)->GetMaskFlags() == GMF_PER_DATASET)
     476             :     {
     477           2 :         GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand(1);
     478             :         VRTSourcedRasterBand *poVRTMaskBand = new VRTSourcedRasterBand(
     479           2 :             poVRTDS, 0, poSrcBand->GetMaskBand()->GetRasterDataType(),
     480           2 :             poSrcDS->GetRasterXSize(), poSrcDS->GetRasterYSize());
     481           2 :         poVRTMaskBand->AddMaskBandSource(poSrcBand);
     482           2 :         poVRTDS->SetMaskBand(poVRTMaskBand);
     483             :     }
     484             : 
     485         217 :     if (strcmp(pszFilename, "") != 0)
     486             :     {
     487         178 :         CPLErrorReset();
     488         178 :         poVRTDS->FlushCache(true);
     489         178 :         if (CPLGetLastErrorType() != CE_None)
     490             :         {
     491          11 :             delete poVRTDS;
     492          11 :             poVRTDS = nullptr;
     493             :         }
     494             :     }
     495             : 
     496         217 :     return poVRTDS;
     497             : }
     498             : 
     499             : /************************************************************************/
     500             : /*                          GDALRegister_VRT()                          */
     501             : /************************************************************************/
     502             : 
     503        4722 : void GDALRegister_VRT()
     504             : 
     505             : {
     506        4722 :     if (GDALGetDriverByName("VRT") != nullptr)
     507        3503 :         return;
     508             : 
     509             :     static std::once_flag flag;
     510        1219 :     std::call_once(flag,
     511        1218 :                    []()
     512             :                    {
     513             :                        // First register the pixel functions
     514        1218 :                        GDALRegisterDefaultPixelFunc();
     515             : 
     516             :                        // Register functions for VRTProcessedDataset
     517        1218 :                        GDALVRTRegisterDefaultProcessedDatasetFuncs();
     518        1218 :                    });
     519             : 
     520        1219 :     VRTDriver *poDriver = new VRTDriver();
     521             : 
     522        1219 :     poDriver->SetDescription("VRT");
     523        1219 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     524        1219 :     poDriver->SetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER, "YES");
     525        1219 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Virtual Raster");
     526        1219 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "vrt");
     527        1219 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/vrt.html");
     528        1219 :     poDriver->SetMetadataItem(
     529             :         GDAL_DMD_CREATIONDATATYPES,
     530             :         "Byte Int8 Int16 UInt16 Int32 UInt32 Int64 UInt64 "
     531             :         "Float32 Float64 "
     532        1219 :         "CInt16 CInt32 CFloat32 CFloat64");
     533        1219 :     poDriver->SetMetadataItem(
     534             :         GDAL_DMD_CREATIONOPTIONLIST,
     535             :         "<CreationOptionList>\n"
     536             :         "   <Option name='SUBCLASS' type='string-select' "
     537             :         "default='VRTDataset'>\n"
     538             :         "       <Value>VRTDataset</Value>\n"
     539             :         "       <Value>VRTWarpedDataset</Value>\n"
     540             :         "   </Option>\n"
     541             :         "   <Option name='BLOCKXSIZE' type='int' description='Block width'/>\n"
     542             :         "   <Option name='BLOCKYSIZE' type='int' description='Block height'/>\n"
     543        1219 :         "</CreationOptionList>\n");
     544             : 
     545        1219 :     poDriver->pfnOpen = VRTDataset::Open;
     546        1219 :     poDriver->pfnCreateCopy = VRTCreateCopy;
     547        1219 :     poDriver->pfnCreate = VRTDataset::Create;
     548        1219 :     poDriver->pfnCreateMultiDimensional = VRTDataset::CreateMultiDimensional;
     549        1219 :     poDriver->pfnIdentify = VRTDataset::Identify;
     550        1219 :     poDriver->pfnDelete = VRTDataset::Delete;
     551             : 
     552        1219 :     poDriver->SetMetadataItem(
     553             :         GDAL_DMD_OPENOPTIONLIST,
     554             :         "<OpenOptionList>"
     555             :         "  <Option name='ROOT_PATH' type='string' description='Root path to "
     556             :         "evaluate "
     557             :         "relative paths inside the VRT. Mainly useful for inlined VRT, or "
     558             :         "in-memory "
     559             :         "VRT, where their own directory does not make sense'/>"
     560        1219 :         "</OpenOptionList>");
     561             : 
     562        1219 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     563        1219 :     poDriver->SetMetadataItem(GDAL_DCAP_COORDINATE_EPOCH, "YES");
     564             : 
     565        1219 :     poDriver->AddSourceParser("SimpleSource", VRTParseCoreSources);
     566        1219 :     poDriver->AddSourceParser("ComplexSource", VRTParseCoreSources);
     567        1219 :     poDriver->AddSourceParser("AveragedSource", VRTParseCoreSources);
     568        1219 :     poDriver->AddSourceParser("NoDataFromMaskSource", VRTParseCoreSources);
     569        1219 :     poDriver->AddSourceParser("KernelFilteredSource", VRTParseFilterSources);
     570        1219 :     poDriver->AddSourceParser("ArraySource", VRTParseArraySource);
     571             : 
     572        1219 :     GetGDALDriverManager()->RegisterDriver(poDriver);
     573             : }
     574             : 
     575             : /*! @endcond */

Generated by: LCOV version 1.14