Skip to content

Commit 8b71ddc

Browse files
authored
Merge pull request OSGeo#12547 from rouault/FLIR_PNG_16bit
JPEG: read FLIR thermal image stored as 16-bit PNG with little-endian byte order
2 parents 1022a29 + a6967c2 commit 8b71ddc

File tree

5 files changed

+39
-5
lines changed

5 files changed

+39
-5
lines changed
7.17 KB
Loading

autotest/gdrivers/jpeg.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1341,6 +1341,17 @@ def test_jpeg_flir_png():
13411341
assert ds.GetRasterBand(1).Checksum() == 761
13421342

13431343

1344+
###############################################################################
1345+
# Open JPEG image with FLIR metadata and raw thermal image as PNG 16 bit
1346+
1347+
1348+
def test_jpeg_flir_png_16_bit():
1349+
1350+
ds = gdal.Open('JPEG:"data/jpeg/flir/FLIR_16bit.jpg":FLIR_RAW_THERMAL_IMAGE')
1351+
assert ds.GetRasterBand(1).DataType == gdal.GDT_UInt16
1352+
assert ds.GetRasterBand(1).ComputeRasterMinMax(False) == (65280, 65280)
1353+
1354+
13441355
###############################################################################
13451356
# Open JPEG image with FLIR metadata and raw thermal image as raw
13461357

frmts/jpeg/jpgdataset.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2905,7 +2905,14 @@ GDALDataset *JPGDatasetCommon::OpenFLIRRawThermalImage()
29052905
if (m_abyRawThermalImage.size() > 4 &&
29062906
memcmp(m_abyRawThermalImage.data(), "\x89PNG", 4) == 0)
29072907
{
2908-
auto poRawDS = GDALDataset::Open(osTmpFilename.c_str());
2908+
// FLIR 16-bit PNG have a wrong endianness.
2909+
// Cf https://exiftool.org/TagNames/FLIR.html: "Note that most FLIR
2910+
// cameras using the PNG format seem to write the 16-bit raw image data
2911+
// in the wrong byte order."
2912+
const char *const apszPNGOpenOptions[] = {
2913+
"@BYTE_ORDER_LITTLE_ENDIAN=YES", nullptr};
2914+
auto poRawDS = GDALDataset::Open(osTmpFilename.c_str(), GDAL_OF_RASTER,
2915+
nullptr, apszPNGOpenOptions, nullptr);
29092916
if (poRawDS == nullptr)
29102917
{
29112918
CPLError(CE_Failure, CPLE_AppDefined, "Invalid raw thermal image");

frmts/png/pngdataset.cpp

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1402,8 +1402,13 @@ CPLErr PNGDataset::LoadInterlacedChunk(int iLine)
14021402
bool bRet = safe_png_read_image(hPNG, png_rows, sSetJmpContext);
14031403

14041404
// Do swap on LSB machines. 16-bit PNG data is stored in MSB format.
1405+
if (bRet && nBitDepth == 16
14051406
#ifdef CPL_LSB
1406-
if (bRet && nBitDepth == 16)
1407+
&& !m_bByteOrderIsLittleEndian
1408+
#else
1409+
&& m_bByteOrderIsLittleEndian
1410+
#endif
1411+
)
14071412
{
14081413
for (int i = 0; i < GetRasterYSize(); i++)
14091414
{
@@ -1414,7 +1419,6 @@ CPLErr PNGDataset::LoadInterlacedChunk(int iLine)
14141419
}
14151420
}
14161421
}
1417-
#endif
14181422

14191423
CPLFree(png_rows);
14201424
CPLFree(dummy_row);
@@ -1492,10 +1496,16 @@ CPLErr PNGDataset::LoadScanline(int nLine)
14921496
nBufferLines = 1;
14931497

14941498
// Do swap on LSB machines. 16-bit PNG data is stored in MSB format.
1499+
if (nBitDepth == 16
14951500
#ifdef CPL_LSB
1496-
if (nBitDepth == 16)
1497-
GDALSwapWords(row, 2, GetRasterXSize() * GetRasterCount(), 2);
1501+
&& !m_bByteOrderIsLittleEndian
1502+
#else
1503+
&& m_bByteOrderIsLittleEndian
14981504
#endif
1505+
)
1506+
{
1507+
GDALSwapWords(row, 2, GetRasterXSize() * GetRasterCount(), 2);
1508+
}
14991509

15001510
return CE_None;
15011511
}
@@ -1973,6 +1983,10 @@ GDALDataset *PNGDataset::OpenStage2(GDALOpenInfo *poOpenInfo, PNGDataset *&poDS)
19731983
// Open overviews.
19741984
poDS->oOvManager.Initialize(poDS, poOpenInfo);
19751985

1986+
// Used by JPEG FLIR
1987+
poDS->m_bByteOrderIsLittleEndian = CPLTestBool(CSLFetchNameValueDef(
1988+
poOpenInfo->papszOpenOptions, "BYTE_ORDER_LITTLE_ENDIAN", "NO"));
1989+
19761990
return poDS;
19771991
}
19781992

frmts/png/pngdataset.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ class PNGDataset final : public GDALPamDataset
113113
int bHasReadICCMetadata;
114114
void LoadICCProfile();
115115

116+
bool m_bByteOrderIsLittleEndian = false;
117+
116118
static void WriteMetadataAsText(jmp_buf sSetJmpContext, png_structp hPNG,
117119
png_infop psPNGInfo, const char *pszKey,
118120
const char *pszValue);

0 commit comments

Comments
 (0)