diff --git a/autotest/gdrivers/data/hdf5/deflate.h5 b/autotest/gdrivers/data/hdf5/deflate.h5 new file mode 100644 index 000000000000..f32e29f9c80f Binary files /dev/null and b/autotest/gdrivers/data/hdf5/deflate.h5 differ diff --git a/autotest/gdrivers/hdf5multidim.py b/autotest/gdrivers/hdf5multidim.py index 64dac532c916..6f1f003c326f 100755 --- a/autotest/gdrivers/hdf5multidim.py +++ b/autotest/gdrivers/hdf5multidim.py @@ -827,3 +827,16 @@ def test_hdf5_multidim_eos_swath_no_explicit_dimension_map(): coordinates[1].GetFullName() == "/HDFEOS/SWATHS/MySwath/Geolocation Fields/Latitude" ) + + +############################################################################### +# Test GetBlockSize() and GetStructuralInfo() + + +def test_hdf5_multidim_block_size_structural_info(): + + ds = gdal.OpenEx("data/hdf5/deflate.h5", gdal.OF_MULTIDIM_RASTER) + rg = ds.GetRootGroup() + var = rg.OpenMDArray("Band1") + assert var.GetBlockSize() == [1, 2] + assert var.GetStructuralInfo() == {"COMPRESSION": "DEFLATE", "FILTER": "SHUFFLE"} diff --git a/frmts/hdf5/hdf5multidim.cpp b/frmts/hdf5/hdf5multidim.cpp index 07d6be6c4e25..1bca9766cec8 100644 --- a/frmts/hdf5/hdf5multidim.cpp +++ b/frmts/hdf5/hdf5multidim.cpp @@ -293,6 +293,7 @@ class HDF5Array final : public GDALMDArray mutable bool m_bHasDimensionLabels = false; std::shared_ptr m_poSRS{}; haddr_t m_nOffset; + mutable CPLStringList m_aosStructuralInfo{}; HDF5Array(const std::string &osParentName, const std::string &osName, const std::shared_ptr &poShared, @@ -365,6 +366,10 @@ class HDF5Array final : public GDALMDArray std::vector> GetAttributes(CSLConstList papszOptions = nullptr) const override; + std::vector GetBlockSize() const override; + + CSLConstList GetStructuralInfo() const override; + const void *GetRawNoDataValue() const override { return m_abyNoData.empty() ? nullptr : m_abyNoData.data(); @@ -1808,6 +1813,85 @@ HDF5Array::GetAttributes(CSLConstList papszOptions) const return m_oListAttributes; } +/************************************************************************/ +/* GetBlockSize() */ +/************************************************************************/ + +std::vector HDF5Array::GetBlockSize() const +{ + HDF5_GLOBAL_LOCK(); + + const auto nDimCount = GetDimensionCount(); + std::vector res(nDimCount); + if (res.empty()) + return res; + + const hid_t nListId = H5Dget_create_plist(m_hArray); + if (nListId > 0) + { + if (H5Pget_layout(nListId) == H5D_CHUNKED) + { + std::vector anChunkDims(nDimCount); + const int nDimSize = H5Pget_chunk( + nListId, static_cast(nDimCount), &anChunkDims[0]); + if (static_cast(nDimSize) == nDimCount) + { + for (size_t i = 0; i < nDimCount; ++i) + { + res[i] = anChunkDims[i]; + } + } + } + + H5Pclose(nListId); + } + + return res; +} + +/************************************************************************/ +/* GetStructuralInfo() */ +/************************************************************************/ + +CSLConstList HDF5Array::GetStructuralInfo() const +{ + if (m_aosStructuralInfo.empty()) + { + HDF5_GLOBAL_LOCK(); + const hid_t nListId = H5Dget_create_plist(m_hArray); + if (nListId > 0) + { + const int nFilters = H5Pget_nfilters(nListId); + for (int i = 0; i < nFilters; ++i) + { + unsigned int flags = 0; + size_t cd_nelmts = 0; + char szName[64 + 1] = {0}; + const auto eFilter = H5Pget_filter( + nListId, i, &flags, &cd_nelmts, nullptr, 64, szName); + if (eFilter == H5Z_FILTER_DEFLATE) + { + m_aosStructuralInfo.SetNameValue("COMPRESSION", "DEFLATE"); + } + else if (eFilter == H5Z_FILTER_SZIP) + { + m_aosStructuralInfo.SetNameValue("COMPRESSION", "SZIP"); + } + else if (eFilter == H5Z_FILTER_SHUFFLE) + { + m_aosStructuralInfo.SetNameValue("FILTER", "SHUFFLE"); + } + else + { + CPLDebug("HDF5", "Filter used: %s", szName); + } + } + H5Pclose(nListId); + } + } + return m_aosStructuralInfo.List(); +} + /************************************************************************/ /* CopyBuffer() */ /************************************************************************/