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_nodata_to_alpha.cpp
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  GDAL
4
 * Purpose:  "nodata-to-alpha" 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_nodata_to_alpha.h"
14
15
#include "gdal_priv.h"
16
#include "gdal_utils.h"
17
18
//! @cond Doxygen_Suppress
19
20
#ifndef _
21
0
#define _(x) (x)
22
#endif
23
24
/************************************************************************/
25
/* GDALRasterNoDataToAlphaAlgorithm::GDALRasterNoDataToAlphaAlgorithm() */
26
/************************************************************************/
27
28
GDALRasterNoDataToAlphaAlgorithm::GDALRasterNoDataToAlphaAlgorithm(
29
    bool standaloneStep)
30
0
    : GDALRasterPipelineStepAlgorithm(NAME, DESCRIPTION, HELP_URL,
31
0
                                      standaloneStep)
32
0
{
33
0
    AddArg("nodata", 0,
34
0
           _("Override nodata value of input band(s) "
35
0
             "(numeric value, 'nan', 'inf', '-inf')"),
36
0
           &m_nodata);
37
0
}
38
39
/************************************************************************/
40
/*             GDALRasterNoDataToAlphaAlgorithm::RunStep()              */
41
/************************************************************************/
42
43
bool GDALRasterNoDataToAlphaAlgorithm::RunStep(GDALPipelineStepRunContext &)
44
0
{
45
0
    GDALDataset *poSrcDS = m_inputDataset[0].GetDatasetRef();
46
0
    CPLAssert(poSrcDS);
47
0
    CPLAssert(m_outputDataset.GetName().empty());
48
0
    CPLAssert(!m_outputDataset.GetDatasetRef());
49
50
0
    if (!m_nodata.empty())
51
0
    {
52
0
        CPLStringList aosOptions;
53
0
        aosOptions.AddString("-of");
54
0
        aosOptions.AddString("VRT");
55
56
0
        if (m_nodata.size() == 1)
57
0
        {
58
0
            aosOptions.AddString("-a_nodata");
59
0
            aosOptions.AddString(CPLSPrintf("%.17g", m_nodata[0]));
60
0
        }
61
0
        else
62
0
        {
63
0
            if (m_nodata.size() !=
64
0
                static_cast<size_t>(poSrcDS->GetRasterCount()))
65
0
            {
66
0
                ReportError(CE_Failure, CPLE_IllegalArg,
67
0
                            "There should be %d nodata values given the input "
68
0
                            "dataset has %d bands",
69
0
                            poSrcDS->GetRasterCount(),
70
0
                            poSrcDS->GetRasterCount());
71
0
                return false;
72
0
            }
73
0
            aosOptions.AddString("-mo");
74
0
            std::string nodataValues("NODATA_VALUES=");
75
0
            for (size_t i = 0; i < m_nodata.size(); ++i)
76
0
            {
77
0
                if (i > 0)
78
0
                    nodataValues += ' ';
79
0
                nodataValues += CPLSPrintf("%.17g", m_nodata[i]);
80
0
            }
81
0
            aosOptions.AddString(nodataValues.c_str());
82
0
        }
83
84
0
        GDALTranslateOptions *psOptions =
85
0
            GDALTranslateOptionsNew(aosOptions.List(), nullptr);
86
0
        if (psOptions)
87
0
        {
88
0
            m_tempDS.reset(GDALDataset::FromHandle(GDALTranslate(
89
0
                "", GDALDataset::ToHandle(poSrcDS), psOptions, nullptr)));
90
0
            GDALTranslateOptionsFree(psOptions);
91
0
        }
92
0
        poSrcDS = m_tempDS.get();
93
0
    }
94
95
0
    bool bRet = poSrcDS != nullptr;
96
0
    if (poSrcDS)
97
0
    {
98
0
        CPLStringList aosOptions;
99
0
        aosOptions.AddString("-of");
100
0
        aosOptions.AddString("VRT");
101
102
0
        if (poSrcDS->GetRasterCount() > 0 &&
103
0
            poSrcDS->GetRasterBand(1)->GetMaskFlags() != GMF_ALL_VALID &&
104
0
            poSrcDS->GetRasterBand(1)->GetMaskFlags() !=
105
0
                (GMF_ALPHA | GMF_PER_DATASET))
106
0
        {
107
0
            aosOptions.AddString("-a_nodata");
108
0
            aosOptions.AddString("none");
109
110
0
            for (int i = 1; i <= poSrcDS->GetRasterCount(); ++i)
111
0
            {
112
0
                aosOptions.AddString("-b");
113
0
                aosOptions.AddString(CPLSPrintf("%d", i));
114
0
            }
115
0
            aosOptions.AddString("-b");
116
0
            aosOptions.AddString("mask");
117
118
0
            aosOptions.AddString(
119
0
                CPLSPrintf("-colorinterp_%d", poSrcDS->GetRasterCount() + 1));
120
0
            aosOptions.AddString("alpha");
121
0
        }
122
123
0
        std::unique_ptr<GDALDataset> poOutDS;
124
0
        GDALTranslateOptions *psOptions =
125
0
            GDALTranslateOptionsNew(aosOptions.List(), nullptr);
126
0
        if (psOptions)
127
0
        {
128
0
            poOutDS.reset(GDALDataset::FromHandle(GDALTranslate(
129
0
                "", GDALDataset::ToHandle(poSrcDS), psOptions, nullptr)));
130
0
            GDALTranslateOptionsFree(psOptions);
131
132
0
            poOutDS->GetRasterBand(1)->GetMaskFlags();
133
0
        }
134
0
        bRet = poOutDS != nullptr;
135
0
        if (poOutDS)
136
0
        {
137
0
            m_outputDataset.Set(std::move(poOutDS));
138
0
        }
139
0
    }
140
141
0
    return bRet;
142
0
}
143
144
GDALRasterNoDataToAlphaAlgorithmStandalone::
145
0
    ~GDALRasterNoDataToAlphaAlgorithmStandalone() = default;
146
147
//! @endcond