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