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

Generated by: LCOV version 1.14