LCOV - code coverage report
Current view: top level - apps - gdalalg_raster_edit.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 91 91 100.0 %
Date: 2025-02-20 10:14:44 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL
       4             :  * Purpose:  "edit" 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_edit.h"
      14             : 
      15             : #include "gdal_priv.h"
      16             : #include "gdal_utils.h"
      17             : 
      18             : //! @cond Doxygen_Suppress
      19             : 
      20             : #ifndef _
      21             : #define _(x) (x)
      22             : #endif
      23             : 
      24             : /************************************************************************/
      25             : /*          GDALRasterEditAlgorithm::GDALRasterEditAlgorithm()          */
      26             : /************************************************************************/
      27             : 
      28          26 : GDALRasterEditAlgorithm::GDALRasterEditAlgorithm(bool standaloneStep)
      29             :     : GDALRasterPipelineStepAlgorithm(
      30             :           NAME, DESCRIPTION, HELP_URL,
      31             :           // Avoid automatic addition of input/output arguments
      32          26 :           /*standaloneStep = */ false)
      33             : {
      34          26 :     if (standaloneStep)
      35             :     {
      36             :         AddArg("dataset", 0, _("Dataset (in-place updated)"), &m_dataset,
      37          30 :                GDAL_OF_RASTER | GDAL_OF_UPDATE)
      38          15 :             .SetPositional()
      39          15 :             .SetRequired();
      40          15 :         m_standaloneStep = true;
      41             :     }
      42             : 
      43          52 :     AddArg("crs", 0, _("Override CRS (without reprojection)"), &m_overrideCrs)
      44          52 :         .AddHiddenAlias("a_srs")
      45          26 :         .SetIsCRSArg(/*noneAllowed=*/true);
      46             : 
      47          26 :     AddBBOXArg(&m_bbox);
      48             : 
      49             :     {
      50             :         auto &arg = AddArg("metadata", 0, _("Add/update dataset metadata item"),
      51          52 :                            &m_metadata)
      52          26 :                         .SetMetaVar("<KEY>=<VALUE>");
      53           3 :         arg.AddValidationAction([this, &arg]()
      54          29 :                                 { return ValidateKeyValue(arg); });
      55          26 :         arg.AddHiddenAlias("mo");
      56             :     }
      57             : 
      58             :     AddArg("unset-metadata", 0, _("Remove dataset metadata item"),
      59          52 :            &m_unsetMetadata)
      60          26 :         .SetMetaVar("<KEY>");
      61          26 : }
      62             : 
      63             : /************************************************************************/
      64             : /*                GDALRasterEditAlgorithm::RunImpl()                    */
      65             : /************************************************************************/
      66             : 
      67          17 : bool GDALRasterEditAlgorithm::RunImpl(GDALProgressFunc pfnProgress,
      68             :                                       void *pProgressData)
      69             : {
      70          17 :     if (m_standaloneStep)
      71             :     {
      72          12 :         auto poDS = m_dataset.GetDatasetRef();
      73          12 :         CPLAssert(poDS);
      74          12 :         if (poDS->GetAccess() != GA_Update)
      75             :         {
      76           1 :             ReportError(CE_Failure, CPLE_AppDefined,
      77             :                         "Dataset should be opened in update mode");
      78           1 :             return false;
      79             :         }
      80             : 
      81          11 :         if (m_overrideCrs == "null" || m_overrideCrs == "none")
      82             :         {
      83           2 :             if (poDS->SetSpatialRef(nullptr) != CE_None)
      84             :             {
      85           1 :                 ReportError(CE_Failure, CPLE_AppDefined,
      86             :                             "SetSpatialRef(%s) failed", m_overrideCrs.c_str());
      87           1 :                 return false;
      88             :             }
      89             :         }
      90           9 :         else if (!m_overrideCrs.empty())
      91             :         {
      92           2 :             OGRSpatialReference oSRS;
      93           2 :             oSRS.SetFromUserInput(m_overrideCrs.c_str());
      94           2 :             oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
      95           2 :             if (poDS->SetSpatialRef(&oSRS) != CE_None)
      96             :             {
      97           1 :                 ReportError(CE_Failure, CPLE_AppDefined,
      98             :                             "SetSpatialRef(%s) failed", m_overrideCrs.c_str());
      99           1 :                 return false;
     100             :             }
     101             :         }
     102             : 
     103           9 :         if (!m_bbox.empty())
     104             :         {
     105           3 :             if (poDS->GetRasterXSize() == 0 || poDS->GetRasterYSize() == 0)
     106             :             {
     107           1 :                 ReportError(
     108             :                     CE_Failure, CPLE_AppDefined,
     109             :                     "Cannot set extent because dataset has 0x0 dimension");
     110           2 :                 return false;
     111             :             }
     112             :             double adfGT[6];
     113           2 :             adfGT[0] = m_bbox[0];
     114           2 :             adfGT[1] = (m_bbox[2] - m_bbox[0]) / poDS->GetRasterXSize();
     115           2 :             adfGT[2] = 0;
     116           2 :             adfGT[3] = m_bbox[3];
     117           2 :             adfGT[4] = 0;
     118           2 :             adfGT[5] = -(m_bbox[3] - m_bbox[1]) / poDS->GetRasterYSize();
     119           2 :             if (poDS->SetGeoTransform(adfGT) != CE_None)
     120             :             {
     121           1 :                 ReportError(CE_Failure, CPLE_AppDefined,
     122             :                             "Setting extent failed");
     123           1 :                 return false;
     124             :             }
     125             :         }
     126             : 
     127          14 :         const CPLStringList aosMD(m_metadata);
     128           9 :         for (const auto &[key, value] : cpl::IterateNameValue(aosMD))
     129             :         {
     130           3 :             if (poDS->SetMetadataItem(key, value) != CE_None)
     131             :             {
     132           1 :                 ReportError(CE_Failure, CPLE_AppDefined,
     133             :                             "SetMetadataItem('%s', '%s') failed", key, value);
     134           1 :                 return false;
     135             :             }
     136             :         }
     137             : 
     138           7 :         for (const std::string &key : m_unsetMetadata)
     139             :         {
     140           2 :             if (poDS->SetMetadataItem(key.c_str(), nullptr) != CE_None)
     141             :             {
     142           1 :                 ReportError(CE_Failure, CPLE_AppDefined,
     143             :                             "SetMetadataItem('%s', NULL) failed", key.c_str());
     144           1 :                 return false;
     145             :             }
     146             :         }
     147             : 
     148           5 :         return true;
     149             :     }
     150             :     else
     151             :     {
     152           5 :         return RunStep(pfnProgress, pProgressData);
     153             :     }
     154             : }
     155             : 
     156             : /************************************************************************/
     157             : /*                GDALRasterEditAlgorithm::RunStep()                    */
     158             : /************************************************************************/
     159             : 
     160           5 : bool GDALRasterEditAlgorithm::RunStep(GDALProgressFunc, void *)
     161             : {
     162           5 :     CPLAssert(m_inputDataset.GetDatasetRef());
     163           5 :     CPLAssert(m_outputDataset.GetName().empty());
     164           5 :     CPLAssert(!m_outputDataset.GetDatasetRef());
     165             : 
     166           5 :     CPLStringList aosOptions;
     167           5 :     aosOptions.AddString("-of");
     168           5 :     aosOptions.AddString("VRT");
     169           5 :     if (!m_overrideCrs.empty())
     170             :     {
     171           2 :         aosOptions.AddString("-a_srs");
     172           2 :         aosOptions.AddString(m_overrideCrs.c_str());
     173             :     }
     174           5 :     if (!m_bbox.empty())
     175             :     {
     176           1 :         aosOptions.AddString("-a_ullr");
     177           1 :         aosOptions.AddString(CPLSPrintf("%.17g", m_bbox[0]));  // upper-left X
     178           1 :         aosOptions.AddString(CPLSPrintf("%.17g", m_bbox[3]));  // upper-left Y
     179           1 :         aosOptions.AddString(CPLSPrintf("%.17g", m_bbox[2]));  // lower-right X
     180           1 :         aosOptions.AddString(CPLSPrintf("%.17g", m_bbox[1]));  // lower-right Y
     181             :     }
     182             : 
     183           7 :     for (const auto &val : m_metadata)
     184             :     {
     185           2 :         aosOptions.AddString("-mo");
     186           2 :         aosOptions.AddString(val.c_str());
     187             :     }
     188             : 
     189           6 :     for (const std::string &key : m_unsetMetadata)
     190             :     {
     191           1 :         aosOptions.AddString("-mo");
     192           1 :         aosOptions.AddString((key + "=").c_str());
     193             :     }
     194             : 
     195             :     GDALTranslateOptions *psOptions =
     196           5 :         GDALTranslateOptionsNew(aosOptions.List(), nullptr);
     197             : 
     198           5 :     GDALDatasetH hSrcDS = GDALDataset::ToHandle(m_inputDataset.GetDatasetRef());
     199             :     auto poRetDS =
     200           5 :         GDALDataset::FromHandle(GDALTranslate("", hSrcDS, psOptions, nullptr));
     201           5 :     GDALTranslateOptionsFree(psOptions);
     202           5 :     const bool ok = poRetDS != nullptr;
     203           5 :     if (ok)
     204           5 :         m_outputDataset.Set(std::unique_ptr<GDALDataset>(poRetDS));
     205             : 
     206          10 :     return ok;
     207             : }
     208             : 
     209             : //! @endcond

Generated by: LCOV version 1.14