Skip to content

Commit

Permalink
OpenJPEG: add a TPSOT_COMPLIANT open option that defaults to YES
Browse files Browse the repository at this point in the history
Fixes the issue reported in https://lists.osgeo.org/pipermail/gdal-dev/2024-November/059805.html
Requires openjpeg >= uclouvain/openjpeg#1560 (likely 2.5.3 when it is released)
  • Loading branch information
rouault committed Nov 13, 2024
1 parent fbaa99c commit cf0260e
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 2 deletions.
10 changes: 10 additions & 0 deletions doc/source/drivers/raster/jp2openjpeg.rst
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,16 @@ The following open options are available:
the image is single-tiled. Note however that the tile size must not
exceed 2 GB since that's the limit supported by GDAL.

- .. oo:: TPSOT_COMPLIANT
:choices: YES, NO
:default: YES
:since: 3.11

(OpenJPEG >= 2.5.3) Assume that a multi-tilepart file is compliant with
respect to the TPSOT value. Turn that setting to NO only if you may deal
with non-compliant files such as the ones of https://github.com/uclouvain/openjpeg/pull/514 .
Default behavior prior to OpenJPEG 2.5.3 was equivalent to YES.

Creation Options
----------------

Expand Down
3 changes: 3 additions & 0 deletions frmts/openjpeg/openjpegdrivercore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ void OPENJPEGDriverSetCommonMetadata(GDALDriver *poDriver)
"description='Whether to always use the JPEG-2000 block size as "
"the "
"GDAL block size' default='NO'/>"
" <Option name='TPSOT_COMPLIANT' type='boolean' "
"description='Assume that a multi-tilepart file is compliant with "
"respect to the TPSOT value' default='YES'/>"
"</OpenOptionList>");

poDriver->SetMetadataItem(
Expand Down
19 changes: 18 additions & 1 deletion frmts/openjpeg/opjdatasetbase.h
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,8 @@ struct OPJCodecWrapper

bool setUpDecompress(CPL_UNUSED int numThreads,
vsi_l_offset nCodeStreamLength, uint32_t *nTileW,
uint32_t *nTileH, int *numResolutions)
uint32_t *nTileH, int *numResolutions,
[[maybe_unused]] bool bTPSOTCompliant)
{

OPJCodecWrapper codec;
Expand All @@ -328,6 +329,14 @@ struct OPJCodecWrapper

opj_dparameters_t decompressParams;
opj_set_default_decoder_parameters(&decompressParams);

#ifdef OPJ_DPARAMETERS_DISABLE_TPSOT_FIX
if (bTPSOTCompliant)
{
decompressParams.flags |= OPJ_DPARAMETERS_DISABLE_TPSOT_FIX;
}
#endif

if (!opj_setup_decoder(pCodec, &decompressParams))
{
opj_destroy_codec(pCodec);
Expand Down Expand Up @@ -819,6 +828,14 @@ struct JP2OPJDatasetBase : public JP2DatasetBase

opj_dparameters_t parameters;
opj_set_default_decoder_parameters(&parameters);

#ifdef OPJ_DPARAMETERS_DISABLE_TPSOT_FIX
if (m_bTPSOTCompliant)
{
parameters.flags |= OPJ_DPARAMETERS_DISABLE_TPSOT_FIX;
}
#endif

if (!opj_setup_decoder(codec->pCodec, &parameters))
{
CPLError(CE_Failure, CPLE_AppDefined,
Expand Down
7 changes: 6 additions & 1 deletion frmts/opjlike/jp2opjlikedataset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1302,12 +1302,15 @@ GDALDataset *JP2OPJLikeDataset<CODEC, BASE>::Open(GDALOpenInfo *poOpenInfo)
auto eCodecFormat = (nCodeStreamStart == 0) ? CODEC::cvtenum(JP2_CODEC_J2K)
: CODEC::cvtenum(JP2_CODEC_JP2);

const bool bTPSOTCompliant =
CPLFetchBool(poOpenInfo->papszOpenOptions, "TPSOT_COMPLIANT", true);

uint32_t nTileW = 0, nTileH = 0;
int numResolutions = 0;
CODEC localctx;
localctx.open(poOpenInfo->fpL, nCodeStreamStart);
if (!localctx.setUpDecompress(numThreads, nCodeStreamLength, &nTileW,
&nTileH, &numResolutions))
&nTileH, &numResolutions, bTPSOTCompliant))
return nullptr;

GDALDataType eDataType = GDT_Byte;
Expand Down Expand Up @@ -1381,6 +1384,7 @@ GDALDataset *JP2OPJLikeDataset<CODEC, BASE>::Open(GDALOpenInfo *poOpenInfo)
poDS->bIs420 = bIs420;
poDS->bSingleTiled = (poDS->nRasterXSize == (int)nTileW &&
poDS->nRasterYSize == (int)nTileH);
poDS->m_bTPSOTCompliant = bTPSOTCompliant;
poDS->m_nX0 = localctx.psImage->x0;
poDS->m_nY0 = localctx.psImage->y0;
poDS->m_nTileWidth = nTileW;
Expand Down Expand Up @@ -1748,6 +1752,7 @@ GDALDataset *JP2OPJLikeDataset<CODEC, BASE>::Open(GDALOpenInfo *poOpenInfo)
poODS->iLevel = poDS->nOverviewCount + 1;
poODS->bSingleTiled = poDS->bSingleTiled;
poODS->bUseSetDecodeArea = poDS->bUseSetDecodeArea;
poODS->m_bTPSOTCompliant = poDS->m_bTPSOTCompliant;
poODS->nRedIndex = poDS->nRedIndex;
poODS->nGreenIndex = poDS->nGreenIndex;
poODS->nBlueIndex = poDS->nBlueIndex;
Expand Down
1 change: 1 addition & 0 deletions frmts/opjlike/jp2opjlikedataset.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ struct JP2DatasetBase
int nThreads = -1;
bool bUseSetDecodeArea = false;
bool bSingleTiled = false;
bool m_bTPSOTCompliant = true;
int m_nBlocksToLoad = 0;
int m_nX0 = 0;
int m_nY0 = 0;
Expand Down

0 comments on commit cf0260e

Please sign in to comment.