LCOV - code coverage report
Current view: top level - apps - gdalalg_raster_color_map.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 72 75 96.0 %
Date: 2025-06-19 12:30:01 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL
       4             :  * Purpose:  "color-map" step of "raster pipeline"
       5             :  * Author:   Even Rouault <even dot rouault at spatialys.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2025, Even Rouault <even dot rouault at spatialys.com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "gdalalg_raster_color_map.h"
      14             : #include "gdalalg_raster_write.h"
      15             : 
      16             : #include "gdal_priv.h"
      17             : #include "gdal_utils.h"
      18             : 
      19             : #include <cmath>
      20             : 
      21             : //! @cond Doxygen_Suppress
      22             : 
      23             : #ifndef _
      24             : #define _(x) (x)
      25             : #endif
      26             : 
      27             : /************************************************************************/
      28             : /*        GDALRasterColorMapAlgorithm::GDALRasterColorMapAlgorithm()    */
      29             : /************************************************************************/
      30             : 
      31          40 : GDALRasterColorMapAlgorithm::GDALRasterColorMapAlgorithm(bool standaloneStep)
      32             :     : GDALRasterPipelineStepAlgorithm(NAME, DESCRIPTION, HELP_URL,
      33          40 :                                       standaloneStep)
      34             : {
      35          40 :     AddBandArg(&m_band).SetDefault(m_band);
      36          40 :     AddArg("color-map", 0, _("Color map filename"), &m_colorMap);
      37             :     AddArg("add-alpha", 0, _("Adds an alpha mask band to the destination."),
      38          40 :            &m_addAlpha);
      39             :     AddArg("color-selection", 0,
      40             :            _("How to compute output colors from input values"),
      41          80 :            &m_colorSelection)
      42          40 :         .SetChoices("interpolate", "exact", "nearest")
      43          40 :         .SetDefault(m_colorSelection);
      44          40 : }
      45             : 
      46             : /************************************************************************/
      47             : /*           GDALRasterColorMapAlgorithm::CanHandleNextStep()           */
      48             : /************************************************************************/
      49             : 
      50          32 : bool GDALRasterColorMapAlgorithm::CanHandleNextStep(
      51             :     GDALPipelineStepAlgorithm *poNextStep) const
      52             : {
      53          64 :     return poNextStep->GetName() == GDALRasterWriteAlgorithm::NAME &&
      54          64 :            poNextStep->GetOutputFormat() != "stream";
      55             : }
      56             : 
      57             : /************************************************************************/
      58             : /*               GDALRasterColorMapAlgorithm::RunStep()                 */
      59             : /************************************************************************/
      60             : 
      61          17 : bool GDALRasterColorMapAlgorithm::RunStep(GDALPipelineStepRunContext &ctxt)
      62             : {
      63          17 :     auto poSrcDS = m_inputDataset[0].GetDatasetRef();
      64          17 :     CPLAssert(poSrcDS);
      65          17 :     CPLAssert(m_outputDataset.GetName().empty());
      66          17 :     CPLAssert(!m_outputDataset.GetDatasetRef());
      67             : 
      68          34 :     CPLStringList aosOptions;
      69          34 :     std::string outputFilename;
      70          17 :     if (ctxt.m_poNextUsableStep)
      71             :     {
      72          16 :         CPLAssert(CanHandleNextStep(ctxt.m_poNextUsableStep));
      73          16 :         outputFilename = ctxt.m_poNextUsableStep->GetOutputDataset().GetName();
      74          16 :         const auto &format = ctxt.m_poNextUsableStep->GetOutputFormat();
      75          16 :         if (!format.empty())
      76             :         {
      77          16 :             aosOptions.AddString("-of");
      78          16 :             aosOptions.AddString(format.c_str());
      79             :         }
      80             : 
      81           0 :         for (const std::string &co :
      82          16 :              ctxt.m_poNextUsableStep->GetCreationOptions())
      83             :         {
      84           0 :             aosOptions.AddString("-co");
      85           0 :             aosOptions.AddString(co.c_str());
      86             :         }
      87             :     }
      88             :     else
      89             :     {
      90           1 :         aosOptions.AddString("-of");
      91           1 :         aosOptions.AddString("VRT");
      92             :     }
      93             : 
      94          17 :     aosOptions.AddString("-b");
      95          17 :     aosOptions.AddString(CPLSPrintf("%d", m_band));
      96             : 
      97          17 :     if (m_colorMap.empty())
      98             :     {
      99           7 :         if (poSrcDS->GetRasterBand(m_band)->GetColorTable() == nullptr)
     100             :         {
     101           1 :             ReportError(CE_Failure, CPLE_AppDefined,
     102             :                         "Input dataset has no color table and 'color-map' "
     103             :                         "option was not specified.");
     104           1 :             return false;
     105             :         }
     106             : 
     107           8 :         if (GetArg("color-selection")->IsExplicitlySet() &&
     108           2 :             m_colorSelection != "exact")
     109             :         {
     110           2 :             ReportError(
     111             :                 CE_Warning, CPLE_NotSupported,
     112             :                 "When using band color table, 'color-selection' is ignored");
     113             :         }
     114             : 
     115           6 :         aosOptions.AddString("-expand");
     116           6 :         aosOptions.AddString(m_addAlpha ? "rgba" : "rgb");
     117             : 
     118             :         GDALTranslateOptions *psOptions =
     119           6 :             GDALTranslateOptionsNew(aosOptions.List(), nullptr);
     120           6 :         if (ctxt.m_poNextUsableStep)
     121             :         {
     122           6 :             GDALTranslateOptionsSetProgress(psOptions, ctxt.m_pfnProgress,
     123             :                                             ctxt.m_pProgressData);
     124             :         }
     125             : 
     126             :         // Backup error state since GDALTranslate() resets it multiple times
     127           6 :         const auto nLastErrorNum = CPLGetLastErrorNo();
     128           6 :         const auto nLastErrorType = CPLGetLastErrorType();
     129          12 :         const std::string osLastErrorMsg = CPLGetLastErrorMsg();
     130           6 :         const auto nLastErrorCounter = CPLGetErrorCounter();
     131             : 
     132             :         auto poOutDS = std::unique_ptr<GDALDataset>(GDALDataset::FromHandle(
     133             :             GDALTranslate(outputFilename.c_str(),
     134           6 :                           GDALDataset::ToHandle(poSrcDS), psOptions, nullptr)));
     135             : 
     136           6 :         if (nLastErrorCounter > 0 && CPLGetErrorCounter() == 0)
     137             :         {
     138           2 :             CPLErrorSetState(nLastErrorType, nLastErrorNum,
     139             :                              osLastErrorMsg.c_str(), &nLastErrorCounter);
     140             :         }
     141             : 
     142           6 :         GDALTranslateOptionsFree(psOptions);
     143           6 :         const bool bRet = poOutDS != nullptr;
     144           6 :         if (poOutDS)
     145             :         {
     146           6 :             m_outputDataset.Set(std::move(poOutDS));
     147             :         }
     148             : 
     149           6 :         return bRet;
     150             :     }
     151             :     else
     152             :     {
     153          10 :         if (m_addAlpha)
     154           2 :             aosOptions.AddString("-alpha");
     155          10 :         if (m_colorSelection == "exact")
     156           2 :             aosOptions.AddString("-exact_color_entry");
     157           8 :         else if (m_colorSelection == "nearest")
     158           2 :             aosOptions.AddString("-nearest_color_entry");
     159             : 
     160             :         GDALDEMProcessingOptions *psOptions =
     161          10 :             GDALDEMProcessingOptionsNew(aosOptions.List(), nullptr);
     162          10 :         bool bOK = false;
     163          10 :         if (psOptions)
     164             :         {
     165          10 :             if (ctxt.m_poNextUsableStep)
     166             :             {
     167           9 :                 GDALDEMProcessingOptionsSetProgress(
     168             :                     psOptions, ctxt.m_pfnProgress, ctxt.m_pProgressData);
     169             :             }
     170             :             auto poOutDS = std::unique_ptr<GDALDataset>(
     171             :                 GDALDataset::FromHandle(GDALDEMProcessing(
     172             :                     outputFilename.c_str(), GDALDataset::ToHandle(poSrcDS),
     173          20 :                     "color-relief", m_colorMap.c_str(), psOptions, nullptr)));
     174          10 :             GDALDEMProcessingOptionsFree(psOptions);
     175          10 :             bOK = poOutDS != nullptr;
     176          10 :             if (poOutDS)
     177             :             {
     178          10 :                 m_outputDataset.Set(std::move(poOutDS));
     179             :             }
     180             :         }
     181          10 :         return bOK;
     182             :     }
     183             : }
     184             : 
     185             : GDALRasterColorMapAlgorithmStandalone::
     186             :     ~GDALRasterColorMapAlgorithmStandalone() = default;
     187             : 
     188             : //! @endcond

Generated by: LCOV version 1.14