Skip to content

Commit ab27316

Browse files
committed
S102: fix opening products with no uncertainty
1 parent 8e46598 commit ab27316

File tree

2 files changed

+92
-46
lines changed

2 files changed

+92
-46
lines changed

frmts/hdf5/hdf5drivercore.cpp

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -264,30 +264,48 @@ static bool IdentifySxx(GDALOpenInfo *poOpenInfo, const char *pszDriverName,
264264
// Works at least on:
265265
// - /vsis3/noaa-s102-pds/ed2.1.0/national_bathymetric_source/boston/dcf2/tiles/102US00_US4MA1GC.h5
266266
// - https://datahub.admiralty.co.uk/portal/sharing/rest/content/items/6fd07bde26124d48820b6dee60695389/data (S-102_Liverpool_Trial_Cells.zip)
267-
const int nLenMainGroup =
268-
static_cast<int>(strlen(pszMainGroupName) + 1);
269-
const int nLenGroupF = static_cast<int>(strlen("Group_F\0") + 1);
267+
const int nLenMainGroup = static_cast<int>(strlen(pszMainGroupName));
268+
const int nLenGroupF = static_cast<int>(strlen("Group_F"));
269+
const int nLenProductSpecification =
270+
static_cast<int>(strlen("productSpecification"));
270271
bool bFoundMainGroup = false;
271272
bool bFoundGroupF = false;
272-
for (int i = 0;
273-
i < poOpenInfo->nHeaderBytes - std::max(nLenMainGroup, nLenGroupF);
274-
++i)
273+
bool bFoundProductSpecification = false;
274+
for (int iTry = 0; iTry < 2; ++iTry)
275275
{
276-
if (poOpenInfo->pabyHeader[i] == pszMainGroupName[0] &&
277-
memcmp(poOpenInfo->pabyHeader + i, pszMainGroupName,
278-
nLenMainGroup) == 0)
276+
for (int i = 0; i <= poOpenInfo->nHeaderBytes - nLenGroupF; ++i)
279277
{
280-
bFoundMainGroup = true;
281-
if (bFoundGroupF)
282-
return true;
278+
if (poOpenInfo->pabyHeader[i] == pszMainGroupName[0] &&
279+
i <= poOpenInfo->nHeaderBytes - nLenMainGroup &&
280+
memcmp(poOpenInfo->pabyHeader + i, pszMainGroupName,
281+
nLenMainGroup) == 0)
282+
{
283+
bFoundMainGroup = true;
284+
if (bFoundGroupF)
285+
return true;
286+
}
287+
if (poOpenInfo->pabyHeader[i] == 'G' &&
288+
memcmp(poOpenInfo->pabyHeader + i, "Group_F", nLenGroupF) ==
289+
0)
290+
{
291+
bFoundGroupF = true;
292+
if (bFoundMainGroup)
293+
return true;
294+
}
295+
if (poOpenInfo->pabyHeader[i] == 'p' &&
296+
i <= poOpenInfo->nHeaderBytes - nLenProductSpecification &&
297+
memcmp(poOpenInfo->pabyHeader + i, "productSpecification",
298+
nLenProductSpecification) == 0)
299+
{
300+
// For 102DE00OS08J.H5
301+
bFoundProductSpecification = true;
302+
}
283303
}
284-
if (poOpenInfo->pabyHeader[i] == 'G' &&
285-
memcmp(poOpenInfo->pabyHeader + i, "Group_F\0", nLenGroupF) ==
286-
0)
304+
if (!(iTry == 0 && bFoundProductSpecification &&
305+
poOpenInfo->nHeaderBytes == 1024 &&
306+
poOpenInfo->TryToIngest(4096)))
287307
{
288-
bFoundGroupF = true;
289-
if (bFoundMainGroup)
290-
return true;
308+
break;
291309
}
292310
}
293311
}

frmts/hdf5/s102dataset.cpp

Lines changed: 56 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,11 @@ GDALDataset *S102Dataset::Open(GDALOpenInfo *poOpenInfo)
199199
auto poBathymetryCoverage01 = poRootGroup->OpenGroupFromFullname(
200200
"/BathymetryCoverage/BathymetryCoverage.01");
201201
if (!poBathymetryCoverage01)
202+
{
203+
CPLError(CE_Failure, CPLE_AppDefined,
204+
"S102: Cannot find /BathymetryCoverage/BathymetryCoverage.01");
202205
return nullptr;
206+
}
203207

204208
const bool bNorthUp = CPLTestBool(
205209
CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "NORTH_UP", "YES"));
@@ -225,18 +229,34 @@ GDALDataset *S102Dataset::Open(GDALOpenInfo *poOpenInfo)
225229

226230
auto poGroup001 = poBathymetryCoverage01->OpenGroup("Group_001");
227231
if (!poGroup001)
232+
{
233+
CPLError(CE_Failure, CPLE_AppDefined,
234+
"S102: Cannot find "
235+
"/BathymetryCoverage/BathymetryCoverage.01/Group_001");
228236
return nullptr;
237+
}
229238
auto poValuesArray = poGroup001->OpenMDArray("values");
230239
if (!poValuesArray || poValuesArray->GetDimensionCount() != 2)
240+
{
241+
CPLError(CE_Failure, CPLE_AppDefined,
242+
"S102: Cannot find "
243+
"/BathymetryCoverage/BathymetryCoverage.01/Group_001/values");
231244
return nullptr;
232-
245+
}
233246
const auto &oType = poValuesArray->GetDataType();
234247
if (oType.GetClass() != GEDTC_COMPOUND)
248+
{
249+
CPLError(CE_Failure, CPLE_AppDefined,
250+
"S102: Wrong type for "
251+
"/BathymetryCoverage/BathymetryCoverage.01/Group_001/values");
235252
return nullptr;
253+
}
236254
const auto &oComponents = oType.GetComponents();
237-
if (oComponents.size() != 2 || oComponents[0]->GetName() != "depth" ||
238-
oComponents[1]->GetName() != "uncertainty")
255+
if (oComponents.size() == 0 || oComponents[0]->GetName() != "depth")
239256
{
257+
CPLError(CE_Failure, CPLE_AppDefined,
258+
"S102: Wrong type for "
259+
"/BathymetryCoverage/BathymetryCoverage.01/Group_001/values");
240260
return nullptr;
241261
}
242262

@@ -288,11 +308,6 @@ GDALDataset *S102Dataset::Open(GDALOpenInfo *poOpenInfo)
288308
}
289309
}();
290310

291-
auto poUncertainty = poValuesArray->GetView("[\"uncertainty\"]");
292-
const double dfUncertaintyNoData = poUncertainty->GetNoDataValueAsDouble();
293-
auto poUncertaintyDS =
294-
std::unique_ptr<GDALDataset>(poUncertainty->AsClassicDataset(1, 0));
295-
296311
poDS->nRasterXSize = poDepthDS->GetRasterXSize();
297312
poDS->nRasterYSize = poDepthDS->GetRasterYSize();
298313

@@ -330,33 +345,46 @@ GDALDataset *S102Dataset::Open(GDALOpenInfo *poOpenInfo)
330345

331346
poDS->SetBand(1, poDepthBand);
332347

333-
// Create uncertainty band
334-
auto poUncertaintyBand = new S102RasterBand(std::move(poUncertaintyDS));
335-
poUncertaintyBand->SetDescription("uncertainty");
336-
337-
auto poMinimumUncertainty = poGroup001->GetAttribute("minimumUncertainty");
338-
if (poMinimumUncertainty &&
339-
poMinimumUncertainty->GetDataType().GetClass() == GEDTC_NUMERIC)
348+
const bool bHasUncertainty =
349+
oComponents.size() >= 2 && oComponents[1]->GetName() == "uncertainty";
350+
if (bHasUncertainty)
340351
{
341-
const double dfVal = poMinimumUncertainty->ReadAsDouble();
342-
if (dfVal != dfUncertaintyNoData)
352+
// Create uncertainty band
353+
auto poUncertainty = poValuesArray->GetView("[\"uncertainty\"]");
354+
const double dfUncertaintyNoData =
355+
poUncertainty->GetNoDataValueAsDouble();
356+
auto poUncertaintyDS =
357+
std::unique_ptr<GDALDataset>(poUncertainty->AsClassicDataset(1, 0));
358+
359+
auto poUncertaintyBand = new S102RasterBand(std::move(poUncertaintyDS));
360+
poUncertaintyBand->SetDescription("uncertainty");
361+
362+
auto poMinimumUncertainty =
363+
poGroup001->GetAttribute("minimumUncertainty");
364+
if (poMinimumUncertainty &&
365+
poMinimumUncertainty->GetDataType().GetClass() == GEDTC_NUMERIC)
343366
{
344-
poUncertaintyBand->m_dfMinimum = dfVal;
367+
const double dfVal = poMinimumUncertainty->ReadAsDouble();
368+
if (dfVal != dfUncertaintyNoData)
369+
{
370+
poUncertaintyBand->m_dfMinimum = dfVal;
371+
}
345372
}
346-
}
347373

348-
auto poMaximumUncertainty = poGroup001->GetAttribute("maximumUncertainty");
349-
if (poMaximumUncertainty &&
350-
poMaximumUncertainty->GetDataType().GetClass() == GEDTC_NUMERIC)
351-
{
352-
const double dfVal = poMaximumUncertainty->ReadAsDouble();
353-
if (dfVal != dfUncertaintyNoData)
374+
auto poMaximumUncertainty =
375+
poGroup001->GetAttribute("maximumUncertainty");
376+
if (poMaximumUncertainty &&
377+
poMaximumUncertainty->GetDataType().GetClass() == GEDTC_NUMERIC)
354378
{
355-
poUncertaintyBand->m_dfMaximum = dfVal;
379+
const double dfVal = poMaximumUncertainty->ReadAsDouble();
380+
if (dfVal != dfUncertaintyNoData)
381+
{
382+
poUncertaintyBand->m_dfMaximum = dfVal;
383+
}
356384
}
357-
}
358385

359-
poDS->SetBand(2, poUncertaintyBand);
386+
poDS->SetBand(2, poUncertaintyBand);
387+
}
360388

361389
poDS->GDALDataset::SetMetadataItem(GDALMD_AREA_OR_POINT, GDALMD_AOP_POINT);
362390

0 commit comments

Comments
 (0)