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