Coverage Report

Created: 2026-02-14 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/apps/gdalalg_mdim_convert.cpp
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  GDAL
4
 * Purpose:  gdal "mdim convert" subcommand
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_mdim_convert.h"
14
15
#include "cpl_conv.h"
16
#include "gdal_priv.h"
17
#include "gdal_utils.h"
18
19
//! @cond Doxygen_Suppress
20
21
#ifndef _
22
0
#define _(x) (x)
23
#endif
24
25
/************************************************************************/
26
/*         GDALMdimConvertAlgorithm::GDALMdimConvertAlgorithm()         */
27
/************************************************************************/
28
29
GDALMdimConvertAlgorithm::GDALMdimConvertAlgorithm()
30
0
    : GDALAlgorithm(NAME, DESCRIPTION, HELP_URL)
31
0
{
32
0
    AddProgressArg();
33
0
    AddOutputFormatArg(&m_outputFormat)
34
0
        .AddMetadataItem(GAAMDI_REQUIRED_CAPABILITIES,
35
0
                         {GDAL_DCAP_CREATE_MULTIDIMENSIONAL});
36
0
    AddOpenOptionsArg(&m_openOptions);
37
0
    AddInputFormatsArg(&m_inputFormats)
38
0
        .AddMetadataItem(GAAMDI_REQUIRED_CAPABILITIES,
39
0
                         {GDAL_ALG_DCAP_RASTER_OR_MULTIDIM_RASTER});
40
0
    AddInputDatasetArg(&m_inputDataset,
41
0
                       GDAL_OF_RASTER | GDAL_OF_MULTIDIM_RASTER);
42
0
    AddOutputDatasetArg(&m_outputDataset, GDAL_OF_MULTIDIM_RASTER);
43
0
    AddCreationOptionsArg(&m_creationOptions);
44
0
    AddOverwriteArg(&m_overwrite);
45
46
0
    {
47
0
        auto &arg = AddArg("array", 0,
48
0
                           _("Select a single array instead of converting the "
49
0
                             "whole dataset."),
50
0
                           &m_arrays)
51
0
                        .SetMetaVar("<ARRAY-SPEC>")
52
0
                        .SetPackedValuesAllowed(false);
53
54
0
        arg.SetAutoCompleteFunction(
55
0
            [this](const std::string &)
56
0
            {
57
0
                std::vector<std::string> ret;
58
59
0
                if (auto poDS = std::unique_ptr<GDALDataset>(GDALDataset::Open(
60
0
                        m_inputDataset.GetName().c_str(),
61
0
                        GDAL_OF_MULTIDIM_RASTER, nullptr, nullptr, nullptr)))
62
0
                {
63
0
                    if (auto poRG = poDS->GetRootGroup())
64
0
                    {
65
0
                        ret = poRG->GetMDArrayFullNamesRecursive();
66
0
                    }
67
0
                }
68
69
0
                return ret;
70
0
            });
71
0
    }
72
73
0
    {
74
0
        auto &arg = AddArg("array-option", 0,
75
0
                           _("Option passed to GDALGroup::GetMDArrayNames() to "
76
0
                             "filter arrays."),
77
0
                           &m_arrayOptions)
78
0
                        .SetMetaVar("<KEY>=<VALUE>")
79
0
                        .SetPackedValuesAllowed(false);
80
0
        arg.AddValidationAction([this, &arg]()
81
0
                                { return ParseAndValidateKeyValue(arg); });
82
83
0
        arg.SetAutoCompleteFunction(
84
0
            [this](const std::string &currentValue)
85
0
            {
86
0
                std::vector<std::string> ret;
87
88
0
                if (auto poDS = std::unique_ptr<GDALDataset>(GDALDataset::Open(
89
0
                        m_inputDataset.GetName().c_str(),
90
0
                        GDAL_OF_MULTIDIM_RASTER, nullptr, nullptr, nullptr)))
91
0
                {
92
0
                    if (auto poDriver = poDS->GetDriver())
93
0
                    {
94
0
                        if (const char *pszXML = poDriver->GetMetadataItem(
95
0
                                GDAL_DMD_MULTIDIM_ARRAY_OPENOPTIONLIST))
96
0
                        {
97
0
                            AddOptionsSuggestions(pszXML, 0, currentValue, ret);
98
0
                        }
99
0
                    }
100
0
                }
101
102
0
                return ret;
103
0
            });
104
0
    }
105
106
0
    AddArg("group", 0,
107
0
           _("Select a single group instead of converting the whole dataset."),
108
0
           &m_groups)
109
0
        .SetMetaVar("<GROUP-SPEC>")
110
0
        .SetPackedValuesAllowed(false);
111
112
0
    AddArg("subset", 0, _("Select a subset of the data."), &m_subsets)
113
0
        .SetMetaVar("<SUBSET-SPEC>")
114
0
        .SetPackedValuesAllowed(false);
115
116
0
    AddArg("scale-axes", 0,
117
0
           _("Applies a integral scale factor to one or several dimensions"),
118
0
           &m_scaleAxes)
119
0
        .SetMetaVar("<SCALEAXES-SPEC>")
120
0
        .SetPackedValuesAllowed(false);
121
122
0
    AddArg("strict", 0, _("Turn warnings into failures."), &m_strict);
123
0
}
124
125
/************************************************************************/
126
/*                 GDALMdimConvertAlgorithm::RunImpl()                  */
127
/************************************************************************/
128
129
bool GDALMdimConvertAlgorithm::RunImpl(GDALProgressFunc pfnProgress,
130
                                       void *pProgressData)
131
0
{
132
0
    CPLAssert(m_inputDataset.GetDatasetRef());
133
0
    CPLAssert(!m_outputDataset.GetDatasetRef());
134
135
0
    CPLStringList aosOptions;
136
0
    if (!m_outputFormat.empty())
137
0
    {
138
0
        aosOptions.AddString("-of");
139
0
        aosOptions.AddString(m_outputFormat.c_str());
140
0
    }
141
0
    if (m_overwrite)
142
0
    {
143
0
        aosOptions.AddString("--overwrite");
144
0
    }
145
0
    else
146
0
    {
147
0
        aosOptions.AddString("--no-overwrite");
148
0
    }
149
0
    if (m_strict)
150
0
    {
151
0
        aosOptions.AddString("-strict");
152
0
    }
153
0
    for (const auto &array : m_arrays)
154
0
    {
155
0
        aosOptions.AddString("-array");
156
0
        aosOptions.AddString(array.c_str());
157
0
    }
158
0
    for (const auto &opt : m_arrayOptions)
159
0
    {
160
0
        aosOptions.AddString("-arrayoption");
161
0
        aosOptions.AddString(opt.c_str());
162
0
    }
163
0
    for (const auto &group : m_groups)
164
0
    {
165
0
        aosOptions.AddString("-group");
166
0
        aosOptions.AddString(group.c_str());
167
0
    }
168
0
    for (const auto &subset : m_subsets)
169
0
    {
170
0
        aosOptions.AddString("-subset");
171
0
        aosOptions.AddString(subset.c_str());
172
0
    }
173
174
0
    std::string scaleAxes;
175
0
    for (const auto &scaleAxis : m_scaleAxes)
176
0
    {
177
0
        if (!scaleAxes.empty())
178
0
            scaleAxes += ',';
179
0
        scaleAxes += scaleAxis;
180
0
    }
181
0
    if (!scaleAxes.empty())
182
0
    {
183
0
        aosOptions.AddString("-scaleaxes");
184
0
        aosOptions.AddString(scaleAxes.c_str());
185
0
    }
186
187
0
    for (const auto &co : m_creationOptions)
188
0
    {
189
0
        aosOptions.AddString("-co");
190
0
        aosOptions.AddString(co.c_str());
191
0
    }
192
193
0
    GDALMultiDimTranslateOptions *psOptions =
194
0
        GDALMultiDimTranslateOptionsNew(aosOptions.List(), nullptr);
195
0
    GDALMultiDimTranslateOptionsSetProgress(psOptions, pfnProgress,
196
0
                                            pProgressData);
197
198
0
    auto hSrcDS = GDALDataset::ToHandle(m_inputDataset.GetDatasetRef());
199
0
    auto poOutDS = std::unique_ptr<GDALDataset>(GDALDataset::FromHandle(
200
0
        GDALMultiDimTranslate(m_outputDataset.GetName().c_str(), nullptr, 1,
201
0
                              &hSrcDS, psOptions, nullptr)));
202
0
    GDALMultiDimTranslateOptionsFree(psOptions);
203
0
    if (!poOutDS)
204
0
        return false;
205
206
0
    m_outputDataset.Set(std::move(poOutDS));
207
208
0
    return true;
209
0
}
210
211
//! @endcond