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