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_info.cpp
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  GDAL
4
 * Purpose:  gdal "raster info" subcommand
5
 * Author:   Even Rouault <even dot rouault at spatialys.com>
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 2024, Even Rouault <even dot rouault at spatialys.com>
9
 *
10
 * SPDX-License-Identifier: MIT
11
 ****************************************************************************/
12
13
#include "gdalalg_raster_info.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
/*          GDALRasterInfoAlgorithm::GDALRasterInfoAlgorithm()          */
27
/************************************************************************/
28
29
GDALRasterInfoAlgorithm::GDALRasterInfoAlgorithm(bool standaloneStep,
30
                                                 bool openForMixedRasterVector)
31
0
    : GDALRasterPipelineStepAlgorithm(
32
0
          NAME, DESCRIPTION, HELP_URL,
33
0
          ConstructorOptions()
34
0
              .SetStandaloneStep(standaloneStep)
35
0
              .SetInputDatasetMaxCount(1)
36
0
              .SetAddDefaultArguments(false)
37
0
              .SetInputDatasetHelpMsg(_("Input raster dataset"))
38
0
              .SetInputDatasetAlias("dataset"))
39
0
{
40
0
    if (standaloneStep)
41
0
    {
42
0
        AddRasterInputArgs(openForMixedRasterVector,
43
0
                           /* hiddenForCLI = */ false);
44
0
    }
45
0
    else
46
0
    {
47
0
        AddRasterHiddenInputDatasetArg();
48
0
    }
49
50
0
    AddOutputFormatArg(&m_format).SetChoices("json", "text");
51
0
    AddArg("min-max", 0, _("Compute minimum and maximum value"), &m_minMax)
52
0
        .AddAlias("mm");
53
0
    AddArg("stats", 0, _("Retrieve or compute statistics, using all pixels"),
54
0
           &m_stats)
55
0
        .SetMutualExclusionGroup("stats");
56
0
    AddArg("approx-stats", 0,
57
0
           _("Retrieve or compute statistics, using a subset of pixels"),
58
0
           &m_approxStats)
59
0
        .SetMutualExclusionGroup("stats");
60
0
    AddArg("hist", 0, _("Retrieve or compute histogram"), &m_hist);
61
62
0
    AddArg("no-gcp", 0, _("Suppress ground control points list printing"),
63
0
           &m_noGCP)
64
0
        .SetCategory(GAAC_ADVANCED);
65
0
    AddArg("no-md", 0, _("Suppress metadata printing"), &m_noMD)
66
0
        .SetCategory(GAAC_ADVANCED);
67
0
    AddArg("no-ct", 0, _("Suppress color table printing"), &m_noCT)
68
0
        .SetCategory(GAAC_ADVANCED);
69
0
    AddArg("no-fl", 0, _("Suppress file list printing"), &m_noFL)
70
0
        .SetCategory(GAAC_ADVANCED);
71
0
    AddArg("checksum", 0, _("Compute pixel checksum"), &m_checksum)
72
0
        .SetCategory(GAAC_ADVANCED);
73
0
    AddArg("list-mdd", 0,
74
0
           _("List all metadata domains available for the dataset"), &m_listMDD)
75
0
        .AddAlias("list-metadata-domains")
76
0
        .SetCategory(GAAC_ADVANCED);
77
0
    AddArg("metadata-domain", 0,
78
0
           _("Report metadata for the specified domain. 'all' can be used to "
79
0
             "report metadata in all domains"),
80
0
           &m_mdd)
81
0
        .AddAlias("mdd")
82
0
        .SetCategory(GAAC_ADVANCED);
83
84
0
    AddArg("no-nodata", 0, _("Suppress retrieving nodata value"), &m_noNodata)
85
0
        .SetCategory(GAAC_ESOTERIC);
86
0
    AddArg("no-mask", 0, _("Suppress mask band information"), &m_noMask)
87
0
        .SetCategory(GAAC_ESOTERIC);
88
0
    AddArg("subdataset", 0,
89
0
           _("Use subdataset of specified index (starting at 1), instead of "
90
0
             "the source dataset itself"),
91
0
           &m_subDS)
92
0
        .SetCategory(GAAC_ESOTERIC)
93
0
        .SetMinValueIncluded(1);
94
95
0
    AddOutputStringArg(&m_output);
96
0
    AddStdoutArg(&m_stdout);
97
0
}
98
99
/************************************************************************/
100
/*                  GDALRasterInfoAlgorithm::RunStep()                  */
101
/************************************************************************/
102
103
bool GDALRasterInfoAlgorithm::RunStep(GDALPipelineStepRunContext &)
104
0
{
105
0
    CPLAssert(m_inputDataset.size() == 1);
106
0
    auto poSrcDS = m_inputDataset[0].GetDatasetRef();
107
0
    CPLAssert(poSrcDS);
108
109
0
    if (m_format.empty())
110
0
        m_format = IsCalledFromCommandLine() ? "text" : "json";
111
112
0
    CPLStringList aosOptions;
113
0
    if (m_format == "json")
114
0
        aosOptions.AddString("-json");
115
0
    if (m_minMax)
116
0
        aosOptions.AddString("-mm");
117
0
    if (m_stats)
118
0
        aosOptions.AddString("-stats");
119
0
    if (m_approxStats)
120
0
        aosOptions.AddString("-approx_stats");
121
0
    if (m_hist)
122
0
        aosOptions.AddString("-hist");
123
0
    if (m_noGCP)
124
0
        aosOptions.AddString("-nogcp");
125
0
    if (m_noMD)
126
0
        aosOptions.AddString("-nomd");
127
0
    if (m_noCT)
128
0
        aosOptions.AddString("-noct");
129
0
    if (m_noFL)
130
0
        aosOptions.AddString("-nofl");
131
0
    if (m_noMask)
132
0
        aosOptions.AddString("-nomask");
133
0
    if (m_noNodata)
134
0
        aosOptions.AddString("-nonodata");
135
0
    if (m_checksum)
136
0
        aosOptions.AddString("-checksum");
137
0
    if (m_listMDD)
138
0
        aosOptions.AddString("-listmdd");
139
0
    if (!m_mdd.empty())
140
0
    {
141
0
        aosOptions.AddString("-mdd");
142
0
        aosOptions.AddString(m_mdd.c_str());
143
0
    }
144
145
0
    GDALDatasetH hDS = GDALDataset::ToHandle(poSrcDS);
146
0
    std::unique_ptr<GDALDataset> poSubDataset;
147
148
0
    if (m_subDS > 0)
149
0
    {
150
0
        CSLConstList papszSubdatasets = GDALGetMetadata(hDS, "SUBDATASETS");
151
0
        const int nSubdatasets = CSLCount(papszSubdatasets) / 2;
152
0
        if (m_subDS > nSubdatasets)
153
0
        {
154
0
            CPLError(CE_Failure, CPLE_AppDefined,
155
0
                     "Invalid value for 'subdataset' argument. Should be "
156
0
                     "between 1 and %d",
157
0
                     nSubdatasets);
158
0
            return false;
159
0
        }
160
161
0
        char szKeyName[64];
162
0
        snprintf(szKeyName, sizeof(szKeyName), "SUBDATASET_%d_NAME", m_subDS);
163
0
        const std::string osSubDSName =
164
0
            CSLFetchNameValueDef(papszSubdatasets, szKeyName, "");
165
166
0
        poSubDataset.reset(GDALDataset::Open(
167
0
            osSubDSName.c_str(), GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR,
168
0
            nullptr, nullptr, nullptr));
169
0
        if (!poSubDataset)
170
0
            return false;
171
0
        hDS = GDALDataset::ToHandle(poSubDataset.get());
172
0
    }
173
174
0
    if (m_stdout)
175
0
    {
176
0
        aosOptions.AddString("-stdout");
177
0
    }
178
179
0
    GDALInfoOptions *psOptions = GDALInfoOptionsNew(aosOptions.List(), nullptr);
180
0
    char *ret = GDALInfo(hDS, psOptions);
181
0
    GDALInfoOptionsFree(psOptions);
182
0
    const bool bOK = ret != nullptr;
183
0
    if (ret)
184
0
    {
185
0
        m_output = ret;
186
0
    }
187
0
    CPLFree(ret);
188
189
0
    return bOK;
190
0
}
191
192
0
GDALRasterInfoAlgorithmStandalone::~GDALRasterInfoAlgorithmStandalone() =
193
    default;
194
195
//! @endcond