Coverage Report

Created: 2026-02-14 06:52

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