Coverage Report

Created: 2026-07-25 06:50

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