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

Generated by: LCOV version 1.14