Skip to content

Commit 5280a24

Browse files
committed
gdalmdiminfo: display overviews
1 parent fb4ab8a commit 5280a24

File tree

3 files changed

+104
-11
lines changed

3 files changed

+104
-11
lines changed

apps/data/gdalmdiminfo_output.schema.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@
6767
},
6868
"structural_info": {
6969
"$ref": "#/definitions/structural_info"
70+
},
71+
"overviews": {
72+
"$ref": "#/definitions/overviews"
7073
}
7174
},
7275
"additionalProperties": false
@@ -326,6 +329,20 @@
326329
]
327330
},
328331

332+
"overviews": {
333+
"type": "array",
334+
"items": {
335+
"oneOf": [
336+
{
337+
"type": "string"
338+
},
339+
{
340+
"$ref": "#/definitions/array"
341+
}
342+
]
343+
}
344+
},
345+
329346
"srs": {
330347
"type": "object",
331348
"properties": {

apps/gdalmdiminfo_lib.cpp

Lines changed: 67 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ static void DumpArray(const std::shared_ptr<GDALGroup> &rootGroup,
2727
CPLJSonStreamingWriter &serializer,
2828
const GDALMultiDimInfoOptions *psOptions,
2929
std::set<std::string> &alreadyDumpedDimensions,
30-
bool bOutputObjType, bool bOutputName);
30+
std::set<std::string> &alreadyDumpedArrays,
31+
bool bOutputObjType, bool bOutputName,
32+
bool bOutputOverviews);
3133

3234
/************************************************************************/
3335
/* GDALMultiDimInfoOptions */
@@ -760,13 +762,15 @@ DumpDimensions(const std::shared_ptr<GDALGroup> &rootGroup,
760762
std::set<std::string> alreadyDumpedDimensionsLocal(
761763
alreadyDumpedDimensions);
762764
alreadyDumpedDimensionsLocal.insert(std::move(osFullname));
765+
std::set<std::string> alreadyDumpedArrays;
763766

764767
auto indexingVariableContext(serializer.MakeObjectContext());
765768
serializer.AddObjKey(poIndexingVariable->GetName());
766769
DumpArray(rootGroup, poIndexingVariable, serializer, psOptions,
767-
alreadyDumpedDimensionsLocal,
770+
alreadyDumpedDimensionsLocal, alreadyDumpedArrays,
768771
/* bOutputObjType = */ false,
769-
/* bOutputName = */ false);
772+
/* bOutputName = */ false,
773+
/* bOutputOverviews = */ false);
770774
}
771775
}
772776
}
@@ -806,8 +810,19 @@ static void DumpArray(const std::shared_ptr<GDALGroup> &rootGroup,
806810
CPLJSonStreamingWriter &serializer,
807811
const GDALMultiDimInfoOptions *psOptions,
808812
std::set<std::string> &alreadyDumpedDimensions,
809-
bool bOutputObjType, bool bOutputName)
813+
std::set<std::string> &alreadyDumpedArrays,
814+
bool bOutputObjType, bool bOutputName,
815+
bool bOutputOverviews)
810816
{
817+
// Protection against infinite recursion
818+
if (cpl::contains(alreadyDumpedArrays, array->GetFullName()))
819+
{
820+
CPLError(CE_Failure, CPLE_AppDefined, "%s already visited",
821+
array->GetFullName().c_str());
822+
return;
823+
}
824+
alreadyDumpedArrays.insert(array->GetFullName());
825+
811826
auto objectContext(serializer.MakeObjectContext());
812827
if (bOutputObjType)
813828
{
@@ -980,6 +995,40 @@ static void DumpArray(const std::shared_ptr<GDALGroup> &rootGroup,
980995
serializer.Add(static_cast<std::uint64_t>(nValidCount));
981996
}
982997
}
998+
999+
if (bOutputOverviews)
1000+
{
1001+
const int nOverviews = array->GetOverviewCount();
1002+
if (nOverviews > 0)
1003+
{
1004+
serializer.AddObjKey("overviews");
1005+
auto overviewsContext(serializer.MakeArrayContext());
1006+
for (int i = 0; i < nOverviews; ++i)
1007+
{
1008+
if (auto poOvrArray = array->GetOverview(i))
1009+
{
1010+
bool bIsStandalone = false;
1011+
{
1012+
CPLErrorStateBackuper oBackuper(CPLQuietErrorHandler);
1013+
bIsStandalone =
1014+
rootGroup->OpenMDArrayFromFullname(
1015+
poOvrArray->GetFullName()) == nullptr;
1016+
}
1017+
if (bIsStandalone)
1018+
{
1019+
DumpArray(rootGroup, poOvrArray, serializer, psOptions,
1020+
alreadyDumpedDimensions, alreadyDumpedArrays,
1021+
bOutputObjType, bOutputName,
1022+
bOutputOverviews);
1023+
}
1024+
else
1025+
{
1026+
serializer.Add(poOvrArray->GetFullName());
1027+
}
1028+
}
1029+
}
1030+
}
1031+
}
9831032
}
9841033

9851034
/************************************************************************/
@@ -991,7 +1040,8 @@ static void DumpArrays(const std::shared_ptr<GDALGroup> &rootGroup,
9911040
const std::vector<std::string> &arrayNames,
9921041
CPLJSonStreamingWriter &serializer,
9931042
const GDALMultiDimInfoOptions *psOptions,
994-
std::set<std::string> &alreadyDumpedDimensions)
1043+
std::set<std::string> &alreadyDumpedDimensions,
1044+
std::set<std::string> &alreadyDumpedArrays)
9951045
{
9961046
std::set<std::string> oSetNames;
9971047
auto objectContext(serializer.MakeObjectContext());
@@ -1005,7 +1055,8 @@ static void DumpArrays(const std::shared_ptr<GDALGroup> &rootGroup,
10051055
{
10061056
serializer.AddObjKey(array->GetName());
10071057
DumpArray(rootGroup, array, serializer, psOptions,
1008-
alreadyDumpedDimensions, false, false);
1058+
alreadyDumpedDimensions, alreadyDumpedArrays, false,
1059+
false, /* bOutputOverviews = */ true);
10091060
}
10101061
}
10111062
}
@@ -1020,6 +1071,7 @@ static void DumpGroup(const std::shared_ptr<GDALGroup> &rootGroup,
10201071
CPLJSonStreamingWriter &serializer,
10211072
const GDALMultiDimInfoOptions *psOptions,
10221073
std::set<std::string> &alreadyDumpedDimensions,
1074+
std::set<std::string> &alreadyDumpedArrays,
10231075
bool bOutputObjType, bool bOutputName)
10241076
{
10251077
auto objectContext(serializer.MakeObjectContext());
@@ -1083,7 +1135,7 @@ static void DumpGroup(const std::shared_ptr<GDALGroup> &rootGroup,
10831135
{
10841136
serializer.AddObjKey("arrays");
10851137
DumpArrays(rootGroup, group, arrayNames, serializer, psOptions,
1086-
alreadyDumpedDimensions);
1138+
alreadyDumpedDimensions, alreadyDumpedArrays);
10871139
}
10881140

10891141
auto papszStructuralInfo = group->GetStructuralInfo();
@@ -1107,7 +1159,8 @@ static void DumpGroup(const std::shared_ptr<GDALGroup> &rootGroup,
11071159
{
11081160
serializer.AddObjKey(subgroupName);
11091161
DumpGroup(rootGroup, subgroup, nullptr, serializer,
1110-
psOptions, alreadyDumpedDimensions, false, false);
1162+
psOptions, alreadyDumpedDimensions,
1163+
alreadyDumpedArrays, false, false);
11111164
}
11121165
}
11131166
}
@@ -1120,7 +1173,8 @@ static void DumpGroup(const std::shared_ptr<GDALGroup> &rootGroup,
11201173
if (subgroup)
11211174
{
11221175
DumpGroup(rootGroup, subgroup, nullptr, serializer,
1123-
psOptions, alreadyDumpedDimensions, false, true);
1176+
psOptions, alreadyDumpedDimensions,
1177+
alreadyDumpedArrays, false, true);
11241178
}
11251179
}
11261180
}
@@ -1270,6 +1324,7 @@ char *GDALMultiDimInfo(GDALDatasetH hDataset,
12701324
return nullptr;
12711325

12721326
std::set<std::string> alreadyDumpedDimensions;
1327+
std::set<std::string> alreadyDumpedArrays;
12731328
try
12741329
{
12751330
if (psOptions->osArrayName.empty())
@@ -1279,7 +1334,7 @@ char *GDALMultiDimInfo(GDALDatasetH hDataset,
12791334
if (poDriver)
12801335
pszDriverName = poDriver->GetDescription();
12811336
DumpGroup(group, group, pszDriverName, serializer, psOptions,
1282-
alreadyDumpedDimensions, true, true);
1337+
alreadyDumpedDimensions, alreadyDumpedArrays, true, true);
12831338
}
12841339
else
12851340
{
@@ -1306,7 +1361,8 @@ char *GDALMultiDimInfo(GDALDatasetH hDataset,
13061361
return nullptr;
13071362
}
13081363
DumpArray(group, array, serializer, psOptions,
1309-
alreadyDumpedDimensions, true, true);
1364+
alreadyDumpedDimensions, alreadyDumpedArrays, true, true,
1365+
true);
13101366
}
13111367
}
13121368
catch (const std::exception &e)

autotest/utilities/test_gdalmdiminfo_lib.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,3 +307,23 @@ def test_gdalmdiminfo_lib_null_string():
307307
"name": "/",
308308
"attributes": {"null_string": None},
309309
}
310+
311+
312+
###############################################################################
313+
314+
315+
@pytest.mark.require_driver("Zarr")
316+
def test_gdalmdiminfo_lib_overviews():
317+
318+
ds = gdal.OpenEx(
319+
"../gdrivers/data/zarr/v3/simple_multiscales/zarr.json", gdal.OF_MULTIDIM_RASTER
320+
)
321+
322+
ret = gdal.MultiDimInfo(ds)
323+
324+
assert ret["groups"]["level0"]["arrays"]["ar"]["overviews"] == [
325+
"/level1/ar",
326+
"/level2/ar",
327+
]
328+
329+
gdaltest.validate_json(ret, "gdalmdiminfo_output.schema.json")

0 commit comments

Comments
 (0)