Skip to content

Commit

Permalink
TIFF JXL: add support for Float16 and Compression=52546 which is JPEG…
Browse files Browse the repository at this point in the history
…XL from DNG 1.7 specification
  • Loading branch information
rouault committed Oct 26, 2024
1 parent f05ae5c commit e2e00f6
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 11 deletions.
17 changes: 17 additions & 0 deletions autotest/gcore/tiff_write.py
Original file line number Diff line number Diff line change
Expand Up @@ -9784,6 +9784,23 @@ def test_tiff_write_jpegxl_five_bands_lossless(tmp_vsimem):
assert ds.GetRasterBand(i + 1).Checksum() == 4672


###############################################################################


@pytest.mark.require_creation_option("GTiff", "JXL")
def test_tiff_write_jpegxl_float16(tmp_vsimem):

outfilename = str(tmp_vsimem / "test_tiff_write_jpegxl_float16")
src_ds = gdal.Open("data/float16.tif")
gdal.GetDriverByName("GTiff").CreateCopy(
outfilename, src_ds, options=["COMPRESS=JXL", "JXL_LOSSLESS=YES"]
)
ds = gdal.Open(outfilename)
assert ds.GetRasterBand(1).DataType == gdal.GDT_Float32
assert ds.GetRasterBand(1).GetMetadataItem("NBITS", "IMAGE_STRUCTURE") == "16"
assert ds.GetRasterBand(1).Checksum() == 4672


###############################################################################
# Test creating overviews with NaN nodata

Expand Down
7 changes: 7 additions & 0 deletions frmts/gtiff/geotiff.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -983,6 +983,7 @@ static void GTiffTagExtender(TIFF *tif)
static std::mutex oDeleteMutex;
#ifdef HAVE_JXL
static TIFFCodec *pJXLCodec = nullptr;
static TIFFCodec *pJXLCodecDNG17 = nullptr;
#endif

void GTiffOneTimeInit()
Expand All @@ -1000,6 +1001,8 @@ void GTiffOneTimeInit()
if (pJXLCodec == nullptr)
{
pJXLCodec = TIFFRegisterCODEC(COMPRESSION_JXL, "JXL", TIFFInitJXL);
pJXLCodecDNG17 =
TIFFRegisterCODEC(COMPRESSION_JXL_DNG_1_7, "JXL", TIFFInitJXL);
}
#endif

Expand All @@ -1024,6 +1027,9 @@ static void GDALDeregister_GTiff(GDALDriver *)
if (pJXLCodec)
TIFFUnRegisterCODEC(pJXLCodec);
pJXLCodec = nullptr;
if (pJXLCodecDNG17)
TIFFUnRegisterCODEC(pJXLCodecDNG17);
pJXLCodecDNG17 = nullptr;
#endif
}

Expand Down Expand Up @@ -1058,6 +1064,7 @@ static const struct
{COMPRESSION_LERC, "LERC_ZSTD", true},
COMPRESSION_ENTRY(WEBP, true),
COMPRESSION_ENTRY(JXL, true),
COMPRESSION_ENTRY(JXL_DNG_1_7, true),

// Compression methods in read-only
COMPRESSION_ENTRY(OJPEG, false),
Expand Down
24 changes: 17 additions & 7 deletions frmts/gtiff/gtiffdataset_write.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5267,23 +5267,33 @@ TIFF *GTiffDataset::CreateLL(const char *pszFilename, int nXSize, int nYSize,
const struct
{
GDALDataType eDT;
int nBitsPerSample;
std::vector<int> anBitsPerSample;
} asSupportedDTBitsPerSample[] = {
{GDT_Byte, 8},
{GDT_UInt16, 16},
{GDT_Float32, 32},
{GDT_Byte, {8}},
{GDT_UInt16, {16}},
{GDT_Float32, {16, 32}},
};

for (const auto &sSupportedDTBitsPerSample : asSupportedDTBitsPerSample)
{
if (eType == sSupportedDTBitsPerSample.eDT &&
l_nBitsPerSample != sSupportedDTBitsPerSample.nBitsPerSample)
std::find(sSupportedDTBitsPerSample.anBitsPerSample.begin(),
sSupportedDTBitsPerSample.anBitsPerSample.end(),
l_nBitsPerSample) ==
sSupportedDTBitsPerSample.anBitsPerSample.end())
{
std::string osBitsPerSample;
for (int nVal : sSupportedDTBitsPerSample.anBitsPerSample)
{
if (!osBitsPerSample.empty())
osBitsPerSample += ", ";
osBitsPerSample += CPLSPrintf("%d", nVal);
}
ReportError(
pszFilename, CE_Failure, CPLE_NotSupported,
"Bits per sample=%d not supported for JXL compression. "
"Only %d is supported for %s data type.",
l_nBitsPerSample, sSupportedDTBitsPerSample.nBitsPerSample,
"Only %s is supported for %s data type.",
l_nBitsPerSample, osBitsPerSample.c_str(),
GDALGetDataTypeName(eType));
return nullptr;
}
Expand Down
1 change: 1 addition & 0 deletions frmts/gtiff/libtiff/tiff.h
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ typedef enum
#define COMPRESSION_ZSTD 50000 /* ZSTD: WARNING not registered in Adobe-maintained registry */
#define COMPRESSION_WEBP 50001 /* WEBP: WARNING not registered in Adobe-maintained registry */
#define COMPRESSION_JXL 50002 /* JPEGXL: WARNING not registered in Adobe-maintained registry */
#define COMPRESSION_JXL_DNG_1_7 52546 /* JPEGXL from DNG 1.7 specification */
#define TIFFTAG_PHOTOMETRIC 262 /* photometric interpretation */
#define PHOTOMETRIC_MINISWHITE 0 /* min value is white */
#define PHOTOMETRIC_MINISBLACK 1 /* min value is black */
Expand Down
21 changes: 17 additions & 4 deletions frmts/gtiff/tif_jxl.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,16 @@ static int GetJXLDataType(TIFF *tif)
return JXL_TYPE_FLOAT;
}

TIFFErrorExtR(tif, module,
"Unsupported combination of SampleFormat and BitsPerSample");
if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP &&
td->td_bitspersample == 16)
{
return JXL_TYPE_FLOAT16;
}

TIFFErrorExtR(
tif, module,
"Unsupported combination of SampleFormat(=%d) and BitsPerSample(=%d)",
td->td_sampleformat, td->td_bitspersample);
return -1;
}

Expand All @@ -113,6 +121,8 @@ static int GetJXLDataTypeSize(JxlDataType dtype)
return 2;
case JXL_TYPE_FLOAT:
return 4;
case JXL_TYPE_FLOAT16:
return 2;
default:
return 0;
}
Expand Down Expand Up @@ -811,7 +821,10 @@ static int JXLPostEncode(TIFF *tif)
basic_info.orientation = JXL_ORIENT_IDENTITY;
if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP)
{
basic_info.exponent_bits_per_sample = 8;
if (td->td_bitspersample == 32)
basic_info.exponent_bits_per_sample = 8;
else
basic_info.exponent_bits_per_sample = 5;
}
else
{
Expand Down Expand Up @@ -1275,7 +1288,7 @@ int TIFFInitJXL(TIFF *tif, int scheme)
JXLState *sp;

(void)scheme;
assert(scheme == COMPRESSION_JXL);
assert(scheme == COMPRESSION_JXL || scheme == COMPRESSION_JXL_DNG_1_7);

/*
* Merge codec-specific tag information.
Expand Down
4 changes: 4 additions & 0 deletions frmts/gtiff/tif_jxl.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@
50002 /* JPEGXL: WARNING not registered in Adobe-maintained registry */
#endif

#ifndef COMPRESSION_JXL_DNG_1_7
#define COMPRESSION_JXL_DNG_1_7 52546 /* JPEGXL from DNG 1.7 specification */
#endif

#ifndef TIFFTAG_JXL_LOSSYNESS

/* Pseudo tags */
Expand Down

0 comments on commit e2e00f6

Please sign in to comment.