LCOV - code coverage report
Current view: top level - apps - gdalalg_raster_pipeline.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 248 255 97.3 %
Date: 2026-06-23 16:35:19 Functions: 13 13 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL
       4             :  * Purpose:  gdal "raster pipeline" subcommand
       5             :  * Author:   Even Rouault <even dot rouault at spatialys.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2024, Even Rouault <even dot rouault at spatialys.com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "gdalalg_raster_pipeline.h"
      14             : #include "gdalalg_external.h"
      15             : #include "gdalalg_materialize.h"
      16             : #include "gdalalg_raster_read.h"
      17             : #include "gdalalg_raster_calc.h"
      18             : #include "gdalalg_raster_aspect.h"
      19             : #include "gdalalg_raster_blend.h"
      20             : #include "gdalalg_raster_clean_collar.h"
      21             : #include "gdalalg_raster_clip.h"
      22             : #include "gdalalg_raster_color_map.h"
      23             : #include "gdalalg_raster_compare.h"
      24             : #include "gdalalg_raster_create.h"
      25             : #include "gdalalg_raster_edit.h"
      26             : #include "gdalalg_raster_fill_nodata.h"
      27             : #include "gdalalg_raster_hillshade.h"
      28             : #include "gdalalg_raster_info.h"
      29             : #include "gdalalg_raster_mosaic.h"
      30             : #include "gdalalg_raster_neighbors.h"
      31             : #include "gdalalg_raster_nodata_to_alpha.h"
      32             : #include "gdalalg_raster_overview.h"
      33             : #include "gdalalg_raster_pansharpen.h"
      34             : #include "gdalalg_raster_proximity.h"
      35             : #include "gdalalg_raster_reclassify.h"
      36             : #include "gdalalg_raster_reproject.h"
      37             : #include "gdalalg_raster_resize.h"
      38             : #include "gdalalg_raster_rgb_to_palette.h"
      39             : #include "gdalalg_raster_roughness.h"
      40             : #include "gdalalg_raster_scale.h"
      41             : #include "gdalalg_raster_select.h"
      42             : #include "gdalalg_raster_set_type.h"
      43             : #include "gdalalg_raster_sieve.h"
      44             : #include "gdalalg_raster_slope.h"
      45             : #include "gdalalg_raster_stack.h"
      46             : #include "gdalalg_raster_tile.h"
      47             : #include "gdalalg_raster_write.h"
      48             : #include "gdalalg_raster_tpi.h"
      49             : #include "gdalalg_raster_tri.h"
      50             : #include "gdalalg_raster_unscale.h"
      51             : #include "gdalalg_raster_update.h"
      52             : #include "gdalalg_raster_viewshed.h"
      53             : #include "gdalalg_tee.h"
      54             : 
      55             : #include "cpl_conv.h"
      56             : #include "cpl_progress.h"
      57             : #include "cpl_string.h"
      58             : #include "cpl_vsi.h"
      59             : #include "gdal_priv.h"
      60             : #include "gdal_utils.h"
      61             : 
      62             : #include <algorithm>
      63             : #include <array>
      64             : #include <cassert>
      65             : 
      66             : //! @cond Doxygen_Suppress
      67             : 
      68             : #ifndef _
      69             : #define _(x) (x)
      70             : #endif
      71             : 
      72             : GDALRasterAlgorithmStepRegistry::~GDALRasterAlgorithmStepRegistry() = default;
      73             : 
      74             : /************************************************************************/
      75             : /*  GDALRasterPipelineStepAlgorithm::GDALRasterPipelineStepAlgorithm()  */
      76             : /************************************************************************/
      77             : 
      78        2829 : GDALRasterPipelineStepAlgorithm::GDALRasterPipelineStepAlgorithm(
      79             :     const std::string &name, const std::string &description,
      80        2829 :     const std::string &helpURL, bool standaloneStep)
      81             :     : GDALRasterPipelineStepAlgorithm(
      82             :           name, description, helpURL,
      83        2829 :           ConstructorOptions().SetStandaloneStep(standaloneStep))
      84             : {
      85        2829 : }
      86             : 
      87             : /************************************************************************/
      88             : /*  GDALRasterPipelineStepAlgorithm::GDALRasterPipelineStepAlgorithm()  */
      89             : /************************************************************************/
      90             : 
      91        6764 : GDALRasterPipelineStepAlgorithm::GDALRasterPipelineStepAlgorithm(
      92             :     const std::string &name, const std::string &description,
      93        6764 :     const std::string &helpURL, const ConstructorOptions &options)
      94        6764 :     : GDALPipelineStepAlgorithm(name, description, helpURL, options)
      95             : {
      96        6764 :     if (m_standaloneStep)
      97             :     {
      98        3113 :         m_supportsStreamedOutput = true;
      99             : 
     100        3113 :         if (m_constructorOptions.addDefaultArguments)
     101             :         {
     102        1325 :             AddRasterInputArgs(false, false);
     103        1325 :             AddProgressArg();
     104        1325 :             AddRasterOutputArgs(false);
     105             :         }
     106             :     }
     107        3651 :     else if (m_constructorOptions.addDefaultArguments)
     108             :     {
     109        1624 :         AddRasterHiddenInputDatasetArg();
     110             :     }
     111        6764 : }
     112             : 
     113             : GDALRasterPipelineStepAlgorithm::~GDALRasterPipelineStepAlgorithm() = default;
     114             : 
     115             : /************************************************************************/
     116             : /*      GDALRasterPipelineStepAlgorithm::SetOutputVRTCompatible()       */
     117             : /************************************************************************/
     118             : 
     119         575 : void GDALRasterPipelineStepAlgorithm::SetOutputVRTCompatible(bool b)
     120             : {
     121         575 :     m_outputVRTCompatible = b;
     122         575 :     if (m_outputFormatArg)
     123             :     {
     124         338 :         m_outputFormatArg->AddMetadataItem(GAAMDI_VRT_COMPATIBLE,
     125         676 :                                            {b ? "true" : "false"});
     126             :     }
     127         575 : }
     128             : 
     129             : /************************************************************************/
     130             : /*      GDALRasterPipelineAlgorithm::GDALRasterPipelineAlgorithm()      */
     131             : /************************************************************************/
     132             : 
     133         192 : GDALRasterPipelineAlgorithm::GDALRasterPipelineAlgorithm(
     134         192 :     bool openForMixedRasterVector)
     135             :     : GDALAbstractPipelineAlgorithm(NAME, DESCRIPTION, HELP_URL,
     136           0 :                                     ConstructorOptions()
     137         192 :                                         .SetAddDefaultArguments(false)
     138         192 :                                         .SetInputDatasetRequired(false)
     139         192 :                                         .SetInputDatasetPositional(false)
     140         384 :                                         .SetInputDatasetMaxCount(INT_MAX))
     141             : {
     142         192 :     m_supportsStreamedOutput = true;
     143             : 
     144         192 :     AddRasterInputArgs(openForMixedRasterVector, /* hiddenForCLI = */ true);
     145         192 :     AddProgressArg();
     146         384 :     AddArg("pipeline", 0, _("Pipeline string"), &m_pipeline)
     147         192 :         .SetHiddenForCLI()
     148         192 :         .SetPositional();
     149         192 :     AddRasterOutputArgs(/* hiddenForCLI = */ true);
     150             : 
     151         192 :     AddOutputStringArg(&m_output).SetHiddenForCLI();
     152         192 :     AddStdoutArg(&m_stdout);
     153             : 
     154         192 :     RegisterAlgorithms(m_stepRegistry, false);
     155         192 : }
     156             : 
     157             : /************************************************************************/
     158             : /*          GDALRasterPipelineAlgorithm::RegisterAlgorithms()           */
     159             : /************************************************************************/
     160             : 
     161             : /* static */
     162         526 : void GDALRasterPipelineAlgorithm::RegisterAlgorithms(
     163             :     GDALRasterAlgorithmStepRegistry &registry, bool forMixedPipeline)
     164             : {
     165        1052 :     GDALAlgorithmRegistry::AlgInfo algInfo;
     166             : 
     167             :     const auto addSuffixIfNeeded =
     168        5260 :         [forMixedPipeline](const char *name) -> std::string
     169             :     {
     170        8600 :         return forMixedPipeline ? std::string(name).append(RASTER_SUFFIX)
     171       13860 :                                 : std::string(name);
     172         526 :     };
     173             : 
     174         526 :     registry.Register<GDALRasterReadAlgorithm>(
     175        1052 :         addSuffixIfNeeded(GDALRasterReadAlgorithm::NAME));
     176             : 
     177         526 :     registry.Register<GDALRasterCalcAlgorithm>();
     178         526 :     registry.Register<GDALRasterCreateAlgorithm>();
     179             : 
     180         526 :     registry.Register<GDALRasterNeighborsAlgorithm>();
     181             : 
     182         526 :     registry.Register<GDALRasterWriteAlgorithm>(
     183        1052 :         addSuffixIfNeeded(GDALRasterWriteAlgorithm::NAME));
     184             : 
     185         526 :     registry.Register<GDALRasterInfoAlgorithm>(
     186        1052 :         addSuffixIfNeeded(GDALRasterInfoAlgorithm::NAME));
     187             : 
     188         526 :     registry.Register<GDALRasterAspectAlgorithm>();
     189         526 :     registry.Register<GDALRasterBlendAlgorithm>();
     190             : 
     191         526 :     registry.Register<GDALRasterCleanCollarAlgorithm>();
     192         526 :     registry.Register<GDALRasterClipAlgorithm>(
     193        1052 :         addSuffixIfNeeded(GDALRasterClipAlgorithm::NAME));
     194             : 
     195         526 :     registry.Register<GDALRasterColorMapAlgorithm>();
     196         526 :     registry.Register<GDALRasterCompareAlgorithm>();
     197             : 
     198         526 :     registry.Register<GDALRasterEditAlgorithm>(
     199        1052 :         addSuffixIfNeeded(GDALRasterEditAlgorithm::NAME));
     200             : 
     201         526 :     registry.Register<GDALRasterNoDataToAlphaAlgorithm>();
     202         526 :     registry.Register<GDALRasterFillNodataAlgorithm>();
     203         526 :     registry.Register<GDALRasterHillshadeAlgorithm>();
     204             : 
     205         526 :     registry.Register<GDALMaterializeRasterAlgorithm>(
     206        1052 :         addSuffixIfNeeded(GDALMaterializeRasterAlgorithm::NAME));
     207             : 
     208         526 :     registry.Register<GDALRasterMosaicAlgorithm>();
     209         526 :     registry.Register<GDALRasterOverviewAlgorithm>();
     210         526 :     registry.Register<GDALRasterPansharpenAlgorithm>();
     211         526 :     registry.Register<GDALRasterProximityAlgorithm>();
     212         526 :     registry.Register<GDALRasterReclassifyAlgorithm>();
     213             : 
     214         526 :     registry.Register<GDALRasterReprojectAlgorithm>(
     215        1052 :         addSuffixIfNeeded(GDALRasterReprojectAlgorithm::NAME));
     216             : 
     217         526 :     registry.Register<GDALRasterResizeAlgorithm>();
     218         526 :     registry.Register<GDALRasterRGBToPaletteAlgorithm>();
     219         526 :     registry.Register<GDALRasterRoughnessAlgorithm>();
     220         526 :     registry.Register<GDALRasterScaleAlgorithm>();
     221             : 
     222         526 :     registry.Register<GDALRasterSelectAlgorithm>(
     223        1052 :         addSuffixIfNeeded(GDALRasterSelectAlgorithm::NAME));
     224             : 
     225         526 :     registry.Register<GDALRasterSetTypeAlgorithm>();
     226         526 :     registry.Register<GDALRasterSieveAlgorithm>();
     227         526 :     registry.Register<GDALRasterSlopeAlgorithm>();
     228         526 :     registry.Register<GDALRasterStackAlgorithm>();
     229         526 :     registry.Register<GDALRasterTileAlgorithm>();
     230         526 :     registry.Register<GDALRasterTPIAlgorithm>();
     231         526 :     registry.Register<GDALRasterTRIAlgorithm>();
     232         526 :     registry.Register<GDALRasterUnscaleAlgorithm>();
     233         526 :     registry.Register<GDALRasterUpdateAlgorithm>(
     234        1052 :         addSuffixIfNeeded(GDALRasterUpdateAlgorithm::NAME));
     235         526 :     registry.Register<GDALRasterViewshedAlgorithm>();
     236         526 :     registry.Register<GDALTeeRasterAlgorithm>(
     237        1052 :         addSuffixIfNeeded(GDALTeeRasterAlgorithm::NAME));
     238             : 
     239         526 :     if (!forMixedPipeline)
     240             :     {
     241         192 :         registry.Register<GDALExternalRasterAlgorithm>();
     242             :     }
     243         526 : }
     244             : 
     245             : /************************************************************************/
     246             : /*            GDALRasterPipelineAlgorithm::GetUsageForCLI()             */
     247             : /************************************************************************/
     248             : 
     249           8 : std::string GDALRasterPipelineAlgorithm::GetUsageForCLI(
     250             :     bool shortUsage, const UsageOptions &usageOptions) const
     251             : {
     252           8 :     UsageOptions stepUsageOptions;
     253           8 :     stepUsageOptions.isPipelineStep = true;
     254             : 
     255           8 :     if (!m_helpDocCategory.empty() && m_helpDocCategory != "main")
     256             :     {
     257           4 :         auto alg = GetStepAlg(m_helpDocCategory);
     258           2 :         if (alg)
     259             :         {
     260           2 :             alg->SetCallPath({m_helpDocCategory});
     261           1 :             alg->GetArg("help-doc")->Set(true);
     262           1 :             return alg->GetUsageForCLI(shortUsage, stepUsageOptions);
     263             :         }
     264             :         else
     265             :         {
     266           1 :             fprintf(stderr, "ERROR: unknown pipeline step '%s'\n",
     267             :                     m_helpDocCategory.c_str());
     268             :             return CPLSPrintf("ERROR: unknown pipeline step '%s'\n",
     269           1 :                               m_helpDocCategory.c_str());
     270             :         }
     271             :     }
     272             : 
     273           6 :     UsageOptions usageOptionsMain(usageOptions);
     274           6 :     usageOptionsMain.isPipelineMain = true;
     275             :     std::string ret =
     276          12 :         GDALAlgorithm::GetUsageForCLI(shortUsage, usageOptionsMain);
     277           6 :     if (shortUsage)
     278           2 :         return ret;
     279             : 
     280             :     ret += "\n<PIPELINE> is of the form: read|mosaic|stack [READ-OPTIONS] "
     281             :            "( ! <STEP-NAME> [STEP-OPTIONS] )* ! info|compare|tile|write "
     282           4 :            "[WRITE-OPTIONS]\n";
     283             : 
     284           4 :     if (m_helpDocCategory == "main")
     285             :     {
     286           1 :         return ret;
     287             :     }
     288             : 
     289           3 :     ret += '\n';
     290           3 :     ret += "Example: 'gdal raster pipeline --progress ! read in.tif ! \\\n";
     291           3 :     ret += "               reproject --output-crs=EPSG:32632 ! ";
     292           3 :     ret += "write out.tif --overwrite'\n";
     293           3 :     ret += '\n';
     294           3 :     ret += "Potential steps are:\n";
     295             : 
     296         123 :     for (const std::string &name : m_stepRegistry.GetNames())
     297             :     {
     298         240 :         auto alg = GetStepAlg(name);
     299         120 :         auto [options, maxOptLen] = alg->GetArgNamesForCLI();
     300         120 :         stepUsageOptions.maxOptLen =
     301         120 :             std::max(stepUsageOptions.maxOptLen, maxOptLen);
     302             :     }
     303             : 
     304             :     {
     305           3 :         const auto name = GDALRasterReadAlgorithm::NAME;
     306           3 :         ret += '\n';
     307           6 :         auto alg = GetStepAlg(name);
     308           6 :         alg->SetCallPath({name});
     309           3 :         ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
     310             :     }
     311         123 :     for (const std::string &name : m_stepRegistry.GetNames())
     312             :     {
     313         240 :         auto alg = GetStepAlg(name);
     314         120 :         assert(alg);
     315         138 :         if (alg->CanBeFirstStep() && !alg->CanBeMiddleStep() &&
     316         138 :             !alg->IsHidden() && name != GDALRasterReadAlgorithm::NAME)
     317             :         {
     318           9 :             ret += '\n';
     319          18 :             alg->SetCallPath({name});
     320           9 :             ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
     321             :         }
     322             :     }
     323         123 :     for (const std::string &name : m_stepRegistry.GetNames())
     324             :     {
     325         240 :         auto alg = GetStepAlg(name);
     326         120 :         assert(alg);
     327         120 :         if (alg->CanBeMiddleStep() && !alg->IsHidden())
     328             :         {
     329          96 :             ret += '\n';
     330         192 :             alg->SetCallPath({name});
     331          96 :             ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
     332             :         }
     333             :     }
     334         123 :     for (const std::string &name : m_stepRegistry.GetNames())
     335             :     {
     336         240 :         auto alg = GetStepAlg(name);
     337         120 :         assert(alg);
     338         141 :         if (alg->CanBeLastStep() && !alg->CanBeMiddleStep() &&
     339         141 :             !alg->IsHidden() && name != GDALRasterWriteAlgorithm::NAME)
     340             :         {
     341           9 :             ret += '\n';
     342          18 :             alg->SetCallPath({name});
     343           9 :             ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
     344             :         }
     345             :     }
     346             :     {
     347           3 :         const auto name = GDALRasterWriteAlgorithm::NAME;
     348           3 :         ret += '\n';
     349           6 :         auto alg = GetStepAlg(name);
     350           6 :         alg->SetCallPath({name});
     351           3 :         ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
     352             :     }
     353           3 :     ret += GetUsageForCLIEnd();
     354             : 
     355           3 :     return ret;
     356             : }
     357             : 
     358             : /************************************************************************/
     359             : /*          GDALRasterPipelineNonNativelyStreamingAlgorithm()           */
     360             : /************************************************************************/
     361             : 
     362         491 : GDALRasterPipelineNonNativelyStreamingAlgorithm::
     363             :     GDALRasterPipelineNonNativelyStreamingAlgorithm(
     364             :         const std::string &name, const std::string &description,
     365         491 :         const std::string &helpURL, bool standaloneStep)
     366             :     : GDALRasterPipelineStepAlgorithm(name, description, helpURL,
     367         491 :                                       standaloneStep)
     368             : {
     369         491 : }
     370             : 
     371         102 : GDALRasterPipelineNonNativelyStreamingAlgorithm::
     372             :     GDALRasterPipelineNonNativelyStreamingAlgorithm(
     373             :         const std::string &name, const std::string &description,
     374         102 :         const std::string &helpURL, const ConstructorOptions &options)
     375         102 :     : GDALRasterPipelineStepAlgorithm(name, description, helpURL, options)
     376             : {
     377         102 : }
     378             : 
     379             : /************************************************************************/
     380             : /*                   IsNativelyStreamingCompatible()                    */
     381             : /************************************************************************/
     382             : 
     383          50 : bool GDALRasterPipelineNonNativelyStreamingAlgorithm::
     384             :     IsNativelyStreamingCompatible() const
     385             : {
     386          50 :     return false;
     387             : }
     388             : 
     389             : /************************************************************************/
     390             : /*                    MustCreateOnDiskTempDataset()                     */
     391             : /************************************************************************/
     392             : 
     393          62 : static bool MustCreateOnDiskTempDataset(int nWidth, int nHeight, int nBands,
     394             :                                         GDALDataType eDT)
     395             : {
     396             :     // Config option mostly for autotest purposes
     397          62 :     if (CPLTestBool(CPLGetConfigOption(
     398             :             "GDAL_RASTER_PIPELINE_USE_GTIFF_FOR_TEMP_DATASET", "NO")))
     399           5 :         return true;
     400             : 
     401             :     // Allow up to 10% of RAM usage for temporary dataset
     402          57 :     const auto nRAM = CPLGetUsablePhysicalRAM() / 10;
     403          57 :     const int nDTSize = GDALGetDataTypeSizeBytes(eDT);
     404          57 :     const bool bOnDisk =
     405         114 :         nBands > 0 && nDTSize > 0 && nRAM > 0 &&
     406          57 :         static_cast<int64_t>(nWidth) * nHeight > nRAM / (nBands * nDTSize);
     407          57 :     return bOnDisk;
     408             : }
     409             : 
     410             : /************************************************************************/
     411             : /*                       CreateTemporaryDataset()                       */
     412             : /************************************************************************/
     413             : 
     414             : std::unique_ptr<GDALDataset>
     415          37 : GDALRasterPipelineNonNativelyStreamingAlgorithm::CreateTemporaryDataset(
     416             :     int nWidth, int nHeight, int nBands, GDALDataType eDT,
     417             :     bool bTiledIfPossible, GDALDataset *poSrcDSForMetadata, bool bCopyMetadata)
     418             : {
     419             :     const bool bOnDisk =
     420          37 :         MustCreateOnDiskTempDataset(nWidth, nHeight, nBands, eDT);
     421          37 :     const char *pszDriverName = bOnDisk ? "GTIFF" : "MEM";
     422             :     GDALDriver *poDriver =
     423          37 :         GetGDALDriverManager()->GetDriverByName(pszDriverName);
     424          74 :     CPLStringList aosOptions;
     425          74 :     std::string osTmpFilename;
     426          37 :     if (bOnDisk)
     427             :     {
     428             :         osTmpFilename =
     429           4 :             CPLGenerateTempFilenameSafe(
     430             :                 poSrcDSForMetadata
     431           4 :                     ? CPLGetBasenameSafe(poSrcDSForMetadata->GetDescription())
     432           2 :                           .c_str()
     433           4 :                     : "") +
     434           2 :             ".tif";
     435           2 :         if (bTiledIfPossible)
     436           2 :             aosOptions.SetNameValue("TILED", "YES");
     437             :         const char *pszCOList =
     438           2 :             poDriver->GetMetadataItem(GDAL_DMD_CREATIONOPTIONLIST);
     439             :         aosOptions.SetNameValue("COMPRESS",
     440           2 :                                 pszCOList && strstr(pszCOList, "ZSTD") ? "ZSTD"
     441           4 :                                                                        : "LZW");
     442           2 :         aosOptions.SetNameValue("SPARSE_OK", "YES");
     443             :     }
     444             :     std::unique_ptr<GDALDataset> poOutDS(
     445          37 :         poDriver ? poDriver->Create(osTmpFilename.c_str(), nWidth, nHeight,
     446          37 :                                     nBands, eDT, aosOptions.List())
     447          74 :                  : nullptr);
     448          37 :     if (poOutDS && bOnDisk)
     449             :     {
     450             :         // In file systems that allow it (all but Windows...), we want to
     451             :         // delete the temporary file as soon as soon as possible after
     452             :         // having open it, so that if someone kills the process there are
     453             :         // no temp files left over. If that unlink() doesn't succeed
     454             :         // (on Windows), then the file will eventually be deleted when
     455             :         // poTmpDS is cleaned due to MarkSuppressOnClose().
     456           0 :         VSIUnlink(osTmpFilename.c_str());
     457           0 :         poOutDS->MarkSuppressOnClose();
     458             :     }
     459             : 
     460          37 :     if (poOutDS && poSrcDSForMetadata)
     461             :     {
     462          35 :         poOutDS->SetSpatialRef(poSrcDSForMetadata->GetSpatialRef());
     463          35 :         GDALGeoTransform gt;
     464          35 :         if (poSrcDSForMetadata->GetGeoTransform(gt) == CE_None)
     465          30 :             poOutDS->SetGeoTransform(gt);
     466          35 :         if (const int nGCPCount = poSrcDSForMetadata->GetGCPCount())
     467             :         {
     468           0 :             const auto apsGCPs = poSrcDSForMetadata->GetGCPs();
     469           0 :             if (apsGCPs)
     470             :             {
     471           0 :                 poOutDS->SetGCPs(nGCPCount, apsGCPs,
     472           0 :                                  poSrcDSForMetadata->GetGCPSpatialRef());
     473             :             }
     474             :         }
     475          35 :         if (bCopyMetadata)
     476             :         {
     477          21 :             poOutDS->SetMetadata(poSrcDSForMetadata->GetMetadata());
     478             :         }
     479             :     }
     480             : 
     481          74 :     return poOutDS;
     482             : }
     483             : 
     484             : /************************************************************************/
     485             : /*                        CreateTemporaryCopy()                         */
     486             : /************************************************************************/
     487             : 
     488             : std::unique_ptr<GDALDataset>
     489          25 : GDALRasterPipelineNonNativelyStreamingAlgorithm::CreateTemporaryCopy(
     490             :     GDALAlgorithm *poAlg, GDALDataset *poSrcDS, int nSingleBand,
     491             :     bool bTiledIfPossible, GDALProgressFunc pfnProgress, void *pProgressData)
     492             : {
     493          25 :     const int nBands = nSingleBand > 0 ? 1 : poSrcDS->GetRasterCount();
     494             :     const auto eDT =
     495          25 :         nBands ? poSrcDS->GetRasterBand(1)->GetRasterDataType() : GDT_Unknown;
     496          25 :     const bool bOnDisk = MustCreateOnDiskTempDataset(
     497             :         poSrcDS->GetRasterXSize(), poSrcDS->GetRasterYSize(), nBands, eDT);
     498          25 :     const char *pszDriverName = bOnDisk ? "GTIFF" : "MEM";
     499             : 
     500          50 :     CPLStringList options;
     501          25 :     if (nSingleBand > 0)
     502             :     {
     503          25 :         options.AddString("-b");
     504          25 :         options.AddString(CPLSPrintf("%d", nSingleBand));
     505             :     }
     506             : 
     507          25 :     options.AddString("-of");
     508          25 :     options.AddString(pszDriverName);
     509             : 
     510          50 :     std::string osTmpFilename;
     511          25 :     if (bOnDisk)
     512             :     {
     513             :         osTmpFilename =
     514           3 :             CPLGenerateTempFilenameSafe(
     515           9 :                 CPLGetBasenameSafe(poSrcDS->GetDescription()).c_str()) +
     516           3 :             ".tif";
     517           3 :         if (bTiledIfPossible)
     518             :         {
     519           3 :             options.AddString("-co");
     520           3 :             options.AddString("TILED=YES");
     521             :         }
     522             : 
     523             :         GDALDriver *poDriver =
     524           3 :             GetGDALDriverManager()->GetDriverByName(pszDriverName);
     525             :         const char *pszCOList =
     526           3 :             poDriver ? poDriver->GetMetadataItem(GDAL_DMD_CREATIONOPTIONLIST)
     527           3 :                      : nullptr;
     528           3 :         options.AddString("-co");
     529           3 :         options.AddString(pszCOList && strstr(pszCOList, "ZSTD")
     530             :                               ? "COMPRESS=ZSTD"
     531           6 :                               : "COMPRESS=LZW");
     532             :     }
     533             : 
     534             :     GDALTranslateOptions *translateOptions =
     535          25 :         GDALTranslateOptionsNew(options.List(), nullptr);
     536             : 
     537          25 :     if (pfnProgress)
     538          12 :         GDALTranslateOptionsSetProgress(translateOptions, pfnProgress,
     539             :                                         pProgressData);
     540             : 
     541             :     std::unique_ptr<GDALDataset> poOutDS(GDALDataset::FromHandle(
     542             :         GDALTranslate(osTmpFilename.c_str(), GDALDataset::ToHandle(poSrcDS),
     543          25 :                       translateOptions, nullptr)));
     544          25 :     GDALTranslateOptionsFree(translateOptions);
     545             : 
     546          25 :     if (!poOutDS)
     547             :     {
     548           2 :         poAlg->ReportError(CE_Failure, CPLE_AppDefined,
     549             :                            "Failed to create temporary dataset");
     550             :     }
     551          23 :     else if (bOnDisk)
     552             :     {
     553             :         // In file systems that allow it (all but Windows...), we want to
     554             :         // delete the temporary file as soon as soon as possible after
     555             :         // having open it, so that if someone kills the process there are
     556             :         // no temp files left over. If that unlink() doesn't succeed
     557             :         // (on Windows), then the file will eventually be deleted when
     558             :         // poTmpDS is cleaned due to MarkSuppressOnClose().
     559           1 :         VSIUnlink(osTmpFilename.c_str());
     560           1 :         poOutDS->MarkSuppressOnClose();
     561             :     }
     562          50 :     return poOutDS;
     563             : }
     564             : 
     565             : //! @endcond

Generated by: LCOV version 1.14