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