LCOV - code coverage report
Current view: top level - apps - gdalalg_raster_reproject.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 138 141 97.9 %
Date: 2025-03-28 11:40:40 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL
       4             :  * Purpose:  "reproject" step of "raster pipeline"
       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_reproject.h"
      14             : 
      15             : #include "gdal_priv.h"
      16             : #include "gdal_utils.h"
      17             : 
      18             : #include <cmath>
      19             : 
      20             : //! @cond Doxygen_Suppress
      21             : 
      22             : #ifndef _
      23             : #define _(x) (x)
      24             : #endif
      25             : 
      26             : /************************************************************************/
      27             : /*      GDALRasterReprojectAlgorithm::GDALRasterReprojectAlgorithm()    */
      28             : /************************************************************************/
      29             : 
      30          40 : GDALRasterReprojectAlgorithm::GDALRasterReprojectAlgorithm(bool standaloneStep)
      31             :     : GDALRasterPipelineStepAlgorithm(NAME, DESCRIPTION, HELP_URL,
      32          40 :                                       standaloneStep)
      33             : {
      34          80 :     AddArg("src-crs", 's', _("Source CRS"), &m_srsCrs)
      35          40 :         .SetIsCRSArg()
      36          40 :         .AddHiddenAlias("s_srs");
      37          80 :     AddArg("dst-crs", 'd', _("Destination CRS"), &m_dstCrs)
      38          40 :         .SetIsCRSArg()
      39          40 :         .AddHiddenAlias("t_srs");
      40          80 :     AddArg("resampling", 'r', _("Resampling method"), &m_resampling)
      41             :         .SetChoices("nearest", "bilinear", "cubic", "cubicspline", "lanczos",
      42             :                     "average", "rms", "mode", "min", "max", "med", "q1", "q3",
      43          40 :                     "sum")
      44          40 :         .SetDefault("nearest")
      45          40 :         .SetHiddenChoices("near");
      46             : 
      47             :     auto &resArg =
      48             :         AddArg("resolution", 0,
      49          80 :                _("Target resolution (in destination CRS units)"), &m_resolution)
      50          40 :             .SetMinCount(2)
      51          40 :             .SetMaxCount(2)
      52          40 :             .SetRepeatedArgAllowed(false)
      53          40 :             .SetDisplayHintAboutRepetition(false)
      54          80 :             .SetMetaVar("<xres>,<yres>")
      55          40 :             .SetMutualExclusionGroup("resolution-size");
      56             :     resArg.AddValidationAction(
      57           2 :         [&resArg]()
      58             :         {
      59           2 :             const auto &val = resArg.Get<std::vector<double>>();
      60           2 :             CPLAssert(val.size() == 2);
      61           2 :             if (!(val[0] > 0 && val[1] > 0))
      62             :             {
      63           1 :                 CPLError(CE_Failure, CPLE_AppDefined,
      64             :                          "Target resolution should be strictly positive.");
      65           1 :                 return false;
      66             :             }
      67           1 :             return true;
      68          40 :         });
      69             : 
      70          80 :     auto &sizeArg = AddArg("size", 0, _("Target size in pixels"), &m_size)
      71          40 :                         .SetMinCount(2)
      72          40 :                         .SetMaxCount(2)
      73          40 :                         .SetRepeatedArgAllowed(false)
      74          40 :                         .SetDisplayHintAboutRepetition(false)
      75          80 :                         .SetMetaVar("<width>,<height>")
      76          40 :                         .SetMutualExclusionGroup("resolution-size");
      77             :     sizeArg.AddValidationAction(
      78           1 :         [&sizeArg]()
      79             :         {
      80           1 :             const auto &val = sizeArg.Get<std::vector<int>>();
      81           1 :             CPLAssert(val.size() == 2);
      82           1 :             if (!(val[0] >= 0 && val[1] >= 0))
      83             :             {
      84           0 :                 CPLError(CE_Failure, CPLE_AppDefined,
      85             :                          "Target size should be positive or 0.");
      86           0 :                 return false;
      87             :             }
      88           1 :             return true;
      89          40 :         });
      90             : 
      91          40 :     AddBBOXArg(&m_bbox, _("Target bounding box (in destination CRS units)"));
      92          80 :     AddArg("bbox-crs", 0, _("CRS of target bounding box"), &m_bboxCrs)
      93          40 :         .SetIsCRSArg()
      94          40 :         .AddHiddenAlias("bbox_srs");
      95             : 
      96             :     AddArg("target-aligned-pixels", 0,
      97             :            _("Round target extent to target resolution"),
      98          80 :            &m_targetAlignedPixels)
      99          80 :         .AddHiddenAlias("tap")
     100          40 :         .SetCategory(GAAC_ADVANCED);
     101             :     AddArg("srcnodata", 0,
     102             :            _("Set nodata values for input bands ('None' to unset)."),
     103          80 :            &m_srcNoData)
     104          40 :         .SetMinCount(1)
     105          40 :         .SetRepeatedArgAllowed(false)
     106          40 :         .SetCategory(GAAC_ADVANCED);
     107             :     AddArg("dstnodata", 0,
     108             :            _("Set nodata values for output bands ('None' to unset)."),
     109          80 :            &m_dstNoData)
     110          40 :         .SetMinCount(1)
     111          40 :         .SetRepeatedArgAllowed(false)
     112          40 :         .SetCategory(GAAC_ADVANCED);
     113             :     AddArg("addalpha", 0,
     114             :            _("Adds an alpha mask band to the destination when the source "
     115             :              "raster have none."),
     116          80 :            &m_addAlpha)
     117          40 :         .SetCategory(GAAC_ADVANCED);
     118          80 :     AddArg("warp-option", 0, _("Warping option(s)"), &m_warpOptions)
     119          80 :         .AddAlias("wo")
     120          80 :         .SetMetaVar("<NAME>=<VALUE>")
     121          40 :         .SetCategory(GAAC_ADVANCED);
     122          80 :     AddArg("transform-option", 0, _("Transform option(s)"), &m_transformOptions)
     123          80 :         .AddAlias("to")
     124          80 :         .SetMetaVar("<NAME>=<VALUE>")
     125          40 :         .SetCategory(GAAC_ADVANCED);
     126          80 :     AddArg("error-threshold", 0, _("Error threshold"), &m_errorThreshold)
     127          80 :         .AddAlias("et")
     128          40 :         .SetCategory(GAAC_ADVANCED);
     129          40 : }
     130             : 
     131             : /************************************************************************/
     132             : /*            GDALRasterReprojectAlgorithm::RunStep()                   */
     133             : /************************************************************************/
     134             : 
     135          14 : bool GDALRasterReprojectAlgorithm::RunStep(GDALProgressFunc, void *)
     136             : {
     137          14 :     CPLAssert(m_inputDataset.GetDatasetRef());
     138          14 :     CPLAssert(m_outputDataset.GetName().empty());
     139          14 :     CPLAssert(!m_outputDataset.GetDatasetRef());
     140             : 
     141          28 :     CPLStringList aosOptions;
     142          14 :     aosOptions.AddString("-of");
     143          14 :     aosOptions.AddString("VRT");
     144          14 :     if (!m_srsCrs.empty())
     145             :     {
     146           5 :         aosOptions.AddString("-s_srs");
     147           5 :         aosOptions.AddString(m_srsCrs.c_str());
     148             :     }
     149          14 :     if (!m_dstCrs.empty())
     150             :     {
     151           6 :         aosOptions.AddString("-t_srs");
     152           6 :         aosOptions.AddString(m_dstCrs.c_str());
     153             :     }
     154          14 :     if (!m_resampling.empty())
     155             :     {
     156          14 :         aosOptions.AddString("-r");
     157          14 :         aosOptions.AddString(m_resampling.c_str());
     158             :     }
     159          14 :     if (!m_resolution.empty())
     160             :     {
     161           1 :         aosOptions.AddString("-tr");
     162           1 :         aosOptions.AddString(CPLSPrintf("%.17g", m_resolution[0]));
     163           1 :         aosOptions.AddString(CPLSPrintf("%.17g", m_resolution[1]));
     164             :     }
     165          14 :     if (!m_size.empty())
     166             :     {
     167           1 :         aosOptions.AddString("-ts");
     168           1 :         aosOptions.AddString(CPLSPrintf("%d", m_size[0]));
     169           1 :         aosOptions.AddString(CPLSPrintf("%d", m_size[1]));
     170             :     }
     171          14 :     if (!m_bbox.empty())
     172             :     {
     173           2 :         aosOptions.AddString("-te");
     174           2 :         aosOptions.AddString(CPLSPrintf("%.17g", m_bbox[0]));
     175           2 :         aosOptions.AddString(CPLSPrintf("%.17g", m_bbox[1]));
     176           2 :         aosOptions.AddString(CPLSPrintf("%.17g", m_bbox[2]));
     177           2 :         aosOptions.AddString(CPLSPrintf("%.17g", m_bbox[3]));
     178             :     }
     179          14 :     if (!m_bboxCrs.empty())
     180             :     {
     181           1 :         aosOptions.AddString("-te_srs");
     182           1 :         aosOptions.AddString(m_bboxCrs.c_str());
     183             :     }
     184          14 :     if (m_targetAlignedPixels)
     185             :     {
     186           1 :         aosOptions.AddString("-tap");
     187             :     }
     188          14 :     if (!m_srcNoData.empty())
     189             :     {
     190           1 :         aosOptions.push_back("-srcnodata");
     191           2 :         std::string s;
     192           2 :         for (const std::string &v : m_srcNoData)
     193             :         {
     194           1 :             if (!s.empty())
     195           0 :                 s += " ";
     196           1 :             s += v;
     197             :         }
     198           1 :         aosOptions.push_back(s);
     199             :     }
     200          14 :     if (!m_dstNoData.empty())
     201             :     {
     202           2 :         aosOptions.push_back("-dstnodata");
     203           4 :         std::string s;
     204           5 :         for (const std::string &v : m_dstNoData)
     205             :         {
     206           3 :             if (!s.empty())
     207           1 :                 s += " ";
     208           3 :             s += v;
     209             :         }
     210           2 :         aosOptions.push_back(s);
     211             :     }
     212          14 :     if (m_addAlpha)
     213             :     {
     214           1 :         aosOptions.AddString("-dstalpha");
     215             :     }
     216          15 :     for (const std::string &opt : m_warpOptions)
     217             :     {
     218           1 :         aosOptions.AddString("-wo");
     219           1 :         aosOptions.AddString(opt.c_str());
     220             :     }
     221          15 :     for (const std::string &opt : m_transformOptions)
     222             :     {
     223           1 :         aosOptions.AddString("-to");
     224           1 :         aosOptions.AddString(opt.c_str());
     225             :     }
     226          14 :     if (std::isfinite(m_errorThreshold))
     227             :     {
     228           1 :         aosOptions.AddString("-et");
     229           1 :         aosOptions.AddString(CPLSPrintf("%.17g", m_errorThreshold));
     230             :     }
     231             : 
     232             :     GDALWarpAppOptions *psOptions =
     233          14 :         GDALWarpAppOptionsNew(aosOptions.List(), nullptr);
     234             : 
     235          14 :     GDALDatasetH hSrcDS = GDALDataset::ToHandle(m_inputDataset.GetDatasetRef());
     236          14 :     auto poRetDS = GDALDataset::FromHandle(
     237             :         GDALWarp("", nullptr, 1, &hSrcDS, psOptions, nullptr));
     238          14 :     GDALWarpAppOptionsFree(psOptions);
     239          14 :     if (!poRetDS)
     240           3 :         return false;
     241             : 
     242          11 :     m_outputDataset.Set(std::unique_ptr<GDALDataset>(poRetDS));
     243             : 
     244          11 :     return true;
     245             : }
     246             : 
     247             : //! @endcond

Generated by: LCOV version 1.14