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