Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: GDAL 4 : * Purpose: "scale" 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_scale.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 : /* GDALRasterScaleAlgorithm::GDALRasterScaleAlgorithm() */ 28 : /************************************************************************/ 29 : 30 101 : GDALRasterScaleAlgorithm::GDALRasterScaleAlgorithm(bool standaloneStep) 31 : : GDALRasterPipelineStepAlgorithm(NAME, DESCRIPTION, HELP_URL, 32 101 : standaloneStep) 33 : { 34 101 : AddOutputDataTypeArg(&m_type); 35 : AddBandArg(&m_band, 36 101 : _("Select band to restrict the scaling (1-based index)")); 37 202 : AddArg("input-min", 0, _("Minimum value of the source range"), &m_srcMin) 38 202 : .SetMutualDependencyGroup("input-max-min") 39 101 : .AddHiddenAlias("src-min"); 40 202 : AddArg("input-max", 0, _("Maximum value of the source range"), &m_srcMax) 41 202 : .SetMutualDependencyGroup("input-max-min") 42 101 : .AddHiddenAlias("src-max"); 43 : AddArg("output-min", 0, _("Minimum value of the destination range"), 44 202 : &m_dstMin) 45 202 : .SetMutualDependencyGroup("output-max-min") 46 101 : .AddHiddenAlias("dst-min"); 47 : AddArg("output-max", 0, _("Maximum value of the destination range"), 48 202 : &m_dstMax) 49 202 : .SetMutualDependencyGroup("output-max-min") 50 101 : .AddHiddenAlias("dst-max"); 51 : AddArg("exponent", 0, 52 : _("Exponent to apply non-linear scaling with a power function"), 53 101 : &m_exponent); 54 : AddArg("no-clip", 0, 55 101 : _("Do not clip input values to [innput-min, input-max]"), &m_noClip); 56 101 : } 57 : 58 : /************************************************************************/ 59 : /* GDALRasterScaleAlgorithm::RunStep() */ 60 : /************************************************************************/ 61 : 62 17 : bool GDALRasterScaleAlgorithm::RunStep(GDALPipelineStepRunContext &) 63 : { 64 17 : auto poSrcDS = m_inputDataset[0].GetDatasetRef(); 65 17 : CPLAssert(poSrcDS); 66 17 : CPLAssert(m_outputDataset.GetName().empty()); 67 17 : CPLAssert(!m_outputDataset.GetDatasetRef()); 68 : 69 34 : CPLStringList aosOptions; 70 17 : aosOptions.AddString("-of"); 71 17 : aosOptions.AddString("VRT"); 72 17 : if (!m_type.empty()) 73 : { 74 1 : aosOptions.AddString("-ot"); 75 1 : aosOptions.AddString(m_type.c_str()); 76 : } 77 2 : aosOptions.AddString(m_band > 0 ? CPLSPrintf("-scale_%d", m_band) 78 19 : : "-scale"); 79 : 80 17 : CPLAssert((std::isnan(m_srcMax) && std::isnan(m_srcMin)) || 81 : (!std::isnan(m_srcMax) && !std::isnan(m_srcMin))); 82 : 83 17 : if (!std::isnan(m_srcMin)) 84 : { 85 8 : CPLAssert(!std::isnan(m_srcMax)); 86 8 : aosOptions.AddString(CPLSPrintf("%.17g", m_srcMin)); 87 8 : aosOptions.AddString(CPLSPrintf("%.17g", m_srcMax)); 88 : } 89 : 90 17 : CPLAssert((std::isnan(m_dstMax) && std::isnan(m_dstMin)) || 91 : (!std::isnan(m_dstMax) && !std::isnan(m_dstMin))); 92 17 : if (!std::isnan(m_dstMin)) 93 : { 94 8 : if (std::isnan(m_srcMin)) 95 : { 96 1 : aosOptions.AddString("NaN"); 97 1 : aosOptions.AddString("NaN"); 98 : } 99 8 : aosOptions.AddString(CPLSPrintf("%.17g", m_dstMin)); 100 8 : aosOptions.AddString(CPLSPrintf("%.17g", m_dstMax)); 101 : } 102 : 103 17 : if (!std::isnan(m_exponent)) 104 : { 105 1 : aosOptions.AddString(m_band > 0 ? CPLSPrintf("-exponent_%d", m_band) 106 4 : : "-exponent"); 107 3 : aosOptions.AddString(CPLSPrintf("%.17g", m_exponent)); 108 : } 109 14 : else if (!m_noClip) 110 : { 111 1 : aosOptions.AddString(m_band > 0 ? CPLSPrintf("-exponent_%d", m_band) 112 14 : : "-exponent"); 113 13 : aosOptions.AddString("1"); 114 : } 115 : 116 17 : if (m_noClip) 117 : { 118 2 : aosOptions.AddString("--no-clip"); 119 : } 120 : 121 : GDALTranslateOptions *psOptions = 122 17 : GDALTranslateOptionsNew(aosOptions.List(), nullptr); 123 : 124 : auto poOutDS = std::unique_ptr<GDALDataset>(GDALDataset::FromHandle( 125 17 : GDALTranslate("", GDALDataset::ToHandle(poSrcDS), psOptions, nullptr))); 126 17 : GDALTranslateOptionsFree(psOptions); 127 17 : const bool bRet = poOutDS != nullptr; 128 17 : if (poOutDS) 129 : { 130 17 : m_outputDataset.Set(std::move(poOutDS)); 131 : } 132 : 133 34 : return bRet; 134 : } 135 : 136 : GDALRasterScaleAlgorithmStandalone::~GDALRasterScaleAlgorithmStandalone() = 137 : default; 138 : 139 : //! @endcond