From e889a2e3cea6297f7b15a756f704dd21956d6177 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Mon, 6 Jan 2025 20:35:01 +0100 Subject: [PATCH 1/7] GTiff: make sure to handle both COMPRESSION_JXL and COMPRESSION_JXL_DNG_1_7 --- .../data/gtiff/byte_jxl_deprecated_50002.tif | Bin 0 -> 778 bytes .../data/gtiff/byte_jxl_dng_1_7_52546.tif | Bin 0 -> 778 bytes autotest/gcore/tiff_read.py | 22 +++++++++++++++++ frmts/gtiff/gt_overview.cpp | 6 +++-- frmts/gtiff/gtiffdataset.cpp | 3 ++- frmts/gtiff/gtiffdataset_read.cpp | 23 ++++++++++++------ frmts/gtiff/gtiffdataset_write.cpp | 11 ++++++--- 7 files changed, 52 insertions(+), 13 deletions(-) create mode 100644 autotest/gcore/data/gtiff/byte_jxl_deprecated_50002.tif create mode 100644 autotest/gcore/data/gtiff/byte_jxl_dng_1_7_52546.tif diff --git a/autotest/gcore/data/gtiff/byte_jxl_deprecated_50002.tif b/autotest/gcore/data/gtiff/byte_jxl_deprecated_50002.tif new file mode 100644 index 0000000000000000000000000000000000000000..ff444755fc22d756a995b67f45f7ab95d2a7822e GIT binary patch literal 778 zcmebD)MDUZU|-qGR53%@L5CR_*r05X9zjMHuwDfw1_n_i zaWNsfCAu4alAXWUp^$W>5gKj{w;l+nE?- zfNU0^T@6c^7}f#V=YSXlY}{QOeSA|(5>paO679GY6l^?8QgapZ5_3~+m7M*31A<(G zgFXHI;)7hnT!Vr=ojiR!Ln4(FQu1>XGxKbfJbfMAUE_m8fM$nUo_)>dZVJFb!fe zg2SF27$gujFrdL=Oe`DQMM3f$8{63!L>btCQOL;9r_8_uqQf&-z_g~apQDSBxq`kz zXo#;uReoNof}x>b4Op;-;Xl_50Ra(nCJq)xh5}}94HL0>+NvrdQ&<$7B%5=jg*luj zOf!&hbNS1pz_{i@2tz=Rej`Hz5HfVI%#2!nZLV4Ddal{>+0CmT{JPD1_~@EuRRN~Y zM@+P;gbg=kZ?KxUo_W!;uWFmRzi|AwImuJvxIo1x)87Al^Y%o+YJ>Px_vjY!4LtwV z4AjfFd&(SB*2$3WYWS6D!R&Kqmj;j3WA{W2*1HQHMRdNKWx$i^ctKCJXzk`4;baq~ zJ|i(jUJYr>kL=+k0`(&76JH!_ZN9qT$lWW#Av`HuO~v^uPrZG!{n=~br3yie{hR>h CGOYIi literal 0 HcmV?d00001 diff --git a/autotest/gcore/data/gtiff/byte_jxl_dng_1_7_52546.tif b/autotest/gcore/data/gtiff/byte_jxl_dng_1_7_52546.tif new file mode 100644 index 0000000000000000000000000000000000000000..704677ac10a88f2814229335086e8197210bbbb2 GIT binary patch literal 778 zcmebD)MDUZU|-qGR53%@PG=by*r05X9zjMHuwDfw1_n_i zaWNsfCAu4alAXWUp^$W>5gKj{w;l+nE?- zfNU0^T@6c^7}f#V=YSXlY}{QOeSA|(5>paO679GY6l^?8QgapZ5_3~+m7M*31A<(G zgFXHI;)7hnT!Vr=ojiR!Ln4(FQu1>XGxKbfJbfMAUE_m8fM$nUo_)>dZVJFb!fe zg2SF27$gujFrdL=Oe`DQMM3f$8{63!L>btCQOL;9r_8_uqQf&-z_g~apQDSBxq`kz zXo#;uReoNof}x>b4Op;-;Xl_50Ra(nCJq)xh5}}94HL0>+NvrdQ&<$7B%5=jg*luj zOf!&hbNS1pz_{i@2tz=Rej`Hz5HfVI%#2!nZLV4Ddal{>+0CmT{JPD1_~@EuRRN~Y zM@+P;gbg=kZ?KxUo_W!;uWFmRzi|AwImuJvxIo1x)87Al^Y%o+YJ>Px_vjY!4LtwV z4AjfFd&(SB*2$3WYWS6D!R&Kqmj;j3WA{W2*1HQHMRdNKWx$i^ctKCJXzk`4;baq~ zJ|i(jUJYr>kL=+k0`(&76JH!_ZN9qT$lWW#Av`HuO~v^uPrZG!{n=~br3yie{hR>Q CFs$(a literal 0 HcmV?d00001 diff --git a/autotest/gcore/tiff_read.py b/autotest/gcore/tiff_read.py index a6f9352aaa59..500d05398930 100755 --- a/autotest/gcore/tiff_read.py +++ b/autotest/gcore/tiff_read.py @@ -4681,6 +4681,28 @@ def test_tiff_jxl_read_for_files_created_before_6393(): assert gdal.GetLastErrorMsg() == "" +############################################################################### +# Test reading Compression=50002 deprecated value + + +@pytest.mark.require_creation_option("GTiff", "JXL") +def test_tiff_read_jxl_deprecated_50002(): + ds = gdal.Open("data/gtiff/byte_jxl_deprecated_50002.tif") + assert ds.GetMetadataItem("COMPRESSION", "IMAGE_STRUCTURE") == "JXL" + assert ds.GetRasterBand(1).Checksum() == 4672 + + +############################################################################### +# Test reading Compression=52546 value used in DNG 1.7 + + +@pytest.mark.require_creation_option("GTiff", "JXL") +def test_tiff_read_jxl_dng_1_7_52546(): + ds = gdal.Open("data/gtiff/byte_jxl_dng_1_7_52546.tif") + assert ds.GetMetadataItem("COMPRESSION", "IMAGE_STRUCTURE") == "JXL" + assert ds.GetRasterBand(1).Checksum() == 4672 + + ############################################################################### # Test multi-threaded decoding diff --git a/frmts/gtiff/gt_overview.cpp b/frmts/gtiff/gt_overview.cpp index 2e86afea2a5d..001273ee9614 100644 --- a/frmts/gtiff/gt_overview.cpp +++ b/frmts/gtiff/gt_overview.cpp @@ -521,7 +521,8 @@ CPLErr GTIFFBuildOverviewsEx(const char *pszFilename, int nBands, nPlanarConfig = PLANARCONFIG_CONTIG; } else if (nCompression == COMPRESSION_WEBP || - nCompression == COMPRESSION_JXL) + nCompression == COMPRESSION_JXL || + nCompression == COMPRESSION_JXL_DNG_1_7) { nPlanarConfig = PLANARCONFIG_CONTIG; } @@ -1036,7 +1037,8 @@ CPLErr GTIFFBuildOverviewsEx(const char *pszFilename, int nBands, } #if HAVE_JXL - if (nCompression == COMPRESSION_JXL) + if (nCompression == COMPRESSION_JXL || + nCompression == COMPRESSION_JXL_DNG_1_7) { if (const char *pszJXLLossLess = GetOptionValue("JXL_LOSSLESS", "JXL_LOSSLESS_OVERVIEW")) diff --git a/frmts/gtiff/gtiffdataset.cpp b/frmts/gtiff/gtiffdataset.cpp index ee65ece7df1e..26d1f917d28c 100644 --- a/frmts/gtiff/gtiffdataset.cpp +++ b/frmts/gtiff/gtiffdataset.cpp @@ -949,7 +949,8 @@ void GTiffDataset::RestoreVolatileParameters(TIFF *hTIFF) if (m_bWebPLossless && m_nCompression == COMPRESSION_WEBP) TIFFSetField(hTIFF, TIFFTAG_WEBP_LOSSLESS, 1); #ifdef HAVE_JXL - if (m_nCompression == COMPRESSION_JXL) + if (m_nCompression == COMPRESSION_JXL || + m_nCompression == COMPRESSION_JXL_DNG_1_7) { TIFFSetField(hTIFF, TIFFTAG_JXL_LOSSYNESS, m_bJXLLossless ? JXL_LOSSLESS : JXL_LOSSY); diff --git a/frmts/gtiff/gtiffdataset_read.cpp b/frmts/gtiff/gtiffdataset_read.cpp index 6bf8134c6374..dab5fd33f2c4 100644 --- a/frmts/gtiff/gtiffdataset_read.cpp +++ b/frmts/gtiff/gtiffdataset_read.cpp @@ -210,7 +210,9 @@ CPLErr GTiffDataset::ReadCompressedData(const char *pszFormat, int nXOff, m_nPhotometric != PHOTOMETRIC_SEPARATED)) || (m_nCompression == COMPRESSION_WEBP && EQUAL(aosTokens[0], "WEBP")) || - (m_nCompression == COMPRESSION_JXL && EQUAL(aosTokens[0], "JXL"))) + ((m_nCompression == COMPRESSION_JXL || + m_nCompression == COMPRESSION_JXL_DNG_1_7) && + EQUAL(aosTokens[0], "JXL"))) { std::string osDetailedFormat = aosTokens[0]; @@ -987,6 +989,7 @@ bool GTiffDataset::IsMultiThreadedReadCompatible() const m_nCompression == COMPRESSION_ZSTD || m_nCompression == COMPRESSION_LERC || m_nCompression == COMPRESSION_JXL || + m_nCompression == COMPRESSION_JXL_DNG_1_7 || m_nCompression == COMPRESSION_WEBP || m_nCompression == COMPRESSION_JPEG); } @@ -5576,7 +5579,8 @@ CPLErr GTiffDataset::OpenOffset(TIFF *hTIFFIn, toff_t nDirOffsetIn, m_dfMaxZErrorOverview = CPLAtof(pszValue); } #if HAVE_JXL - else if (m_nCompression == COMPRESSION_JXL && + else if ((m_nCompression == COMPRESSION_JXL || + m_nCompression == COMPRESSION_JXL_DNG_1_7) && EQUAL(pszKey, "COMPRESSION_REVERSIBILITY")) { if (EQUAL(pszValue, "LOSSLESS")) @@ -5584,7 +5588,8 @@ CPLErr GTiffDataset::OpenOffset(TIFF *hTIFFIn, toff_t nDirOffsetIn, else if (EQUAL(pszValue, "LOSSY")) m_bJXLLossless = false; } - else if (m_nCompression == COMPRESSION_JXL && + else if ((m_nCompression == COMPRESSION_JXL || + m_nCompression == COMPRESSION_JXL_DNG_1_7) && EQUAL(pszKey, "JXL_DISTANCE")) { const double dfVal = CPLAtof(pszValue); @@ -5597,7 +5602,8 @@ CPLErr GTiffDataset::OpenOffset(TIFF *hTIFFIn, toff_t nDirOffsetIn, m_fJXLDistance = static_cast(dfVal); } } - else if (m_nCompression == COMPRESSION_JXL && + else if ((m_nCompression == COMPRESSION_JXL || + m_nCompression == COMPRESSION_JXL_DNG_1_7) && EQUAL(pszKey, "JXL_ALPHA_DISTANCE")) { const double dfVal = CPLAtof(pszValue); @@ -5609,7 +5615,8 @@ CPLErr GTiffDataset::OpenOffset(TIFF *hTIFFIn, toff_t nDirOffsetIn, m_fJXLAlphaDistance = static_cast(dfVal); } } - else if (m_nCompression == COMPRESSION_JXL && + else if ((m_nCompression == COMPRESSION_JXL || + m_nCompression == COMPRESSION_JXL_DNG_1_7) && EQUAL(pszKey, "JXL_EFFORT")) { const int nEffort = atoi(pszValue); @@ -5786,7 +5793,8 @@ CPLErr GTiffDataset::OpenOffset(TIFF *hTIFFIn, toff_t nDirOffsetIn, } } #ifdef HAVE_JXL - else if (m_nCompression == COMPRESSION_JXL) + else if (m_nCompression == COMPRESSION_JXL || + m_nCompression == COMPRESSION_JXL_DNG_1_7) { const char *pszReversibility = GetMetadataItem("COMPRESSION_REVERSIBILITY", "IMAGE_STRUCTURE"); @@ -6381,7 +6389,8 @@ const char *GTiffDataset::GetMetadataItem(const char *pszName, if (pszDomain != nullptr && EQUAL(pszDomain, "IMAGE_STRUCTURE")) { if ((m_nCompression == COMPRESSION_WEBP || - m_nCompression == COMPRESSION_JXL) && + m_nCompression == COMPRESSION_JXL || + m_nCompression == COMPRESSION_JXL_DNG_1_7) && EQUAL(pszName, "COMPRESSION_REVERSIBILITY") && m_oGTiffMDMD.GetMetadataItem("COMPRESSION_REVERSIBILITY", "IMAGE_STRUCTURE") == nullptr) diff --git a/frmts/gtiff/gtiffdataset_write.cpp b/frmts/gtiff/gtiffdataset_write.cpp index de4c48002ed7..aa45e94280fc 100644 --- a/frmts/gtiff/gtiffdataset_write.cpp +++ b/frmts/gtiff/gtiffdataset_write.cpp @@ -1357,6 +1357,7 @@ bool GTiffDataset::SubmitCompressionJob(int nStripOrTile, GByte *pabyData, m_nCompression == COMPRESSION_ZSTD || m_nCompression == COMPRESSION_LERC || m_nCompression == COMPRESSION_JXL || + m_nCompression == COMPRESSION_JXL_DNG_1_7 || m_nCompression == COMPRESSION_WEBP || m_nCompression == COMPRESSION_JPEG)) { @@ -5255,7 +5256,9 @@ TIFF *GTiffDataset::CreateLL(const char *pszFilename, int nXSize, int nYSize, } #ifdef HAVE_JXL - if (l_nCompression == COMPRESSION_JXL && eType != GDT_Float32) + if ((l_nCompression == COMPRESSION_JXL || + l_nCompression == COMPRESSION_JXL_DNG_1_7) && + eType != GDT_Float32) { // Reflects tif_jxl's GetJXLDataType() if (eType != GDT_Byte && eType != GDT_UInt16) @@ -5899,7 +5902,8 @@ TIFF *GTiffDataset::CreateLL(const char *pszFilename, int nXSize, int nYSize, TIFFSetField(l_hTIFF, TIFFTAG_LERC_MAXZERROR, l_dfMaxZError); } #if HAVE_JXL - if (l_nCompression == COMPRESSION_JXL) + if (l_nCompression == COMPRESSION_JXL || + l_nCompression == COMPRESSION_JXL_DNG_1_7) { TIFFSetField(l_hTIFF, TIFFTAG_JXL_LOSSYNESS, l_bJXLLossless ? JXL_LOSSLESS : JXL_LOSSY); @@ -7883,7 +7887,8 @@ GDALDataset *GTiffDataset::CreateCopy(const char *pszFilename, TIFFSetField(l_hTIFF, TIFFTAG_LERC_MAXZERROR, poDS->m_dfMaxZError); } #if HAVE_JXL - if (l_nCompression == COMPRESSION_JXL) + if (l_nCompression == COMPRESSION_JXL || + l_nCompression == COMPRESSION_JXL_DNG_1_7) { TIFFSetField(l_hTIFF, TIFFTAG_JXL_LOSSYNESS, poDS->m_bJXLLossless ? JXL_LOSSLESS : JXL_LOSSY); From 7b708889f6b0d5c82f5a3032462814fca4229a71 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Mon, 6 Jan 2025 20:41:02 +0100 Subject: [PATCH 2/7] GTiff: when using COMPRESS=JXL, switch to use DNG 1.7 compress=52546 value --- frmts/gtiff/geotiff.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/frmts/gtiff/geotiff.cpp b/frmts/gtiff/geotiff.cpp index 877feb1dc7e7..cd6b97b74eff 100644 --- a/frmts/gtiff/geotiff.cpp +++ b/frmts/gtiff/geotiff.cpp @@ -1063,8 +1063,10 @@ static const struct {COMPRESSION_LERC, "LERC_DEFLATE", true}, {COMPRESSION_LERC, "LERC_ZSTD", true}, COMPRESSION_ENTRY(WEBP, true), - COMPRESSION_ENTRY(JXL, true), - COMPRESSION_ENTRY(JXL_DNG_1_7, true), + // COMPRESSION_JXL_DNG_1_7 must be *before* COMPRESSION_JXL + {COMPRESSION_JXL_DNG_1_7, "JXL", true}, + {COMPRESSION_JXL, "JXL", + true}, // deprecated. No longer used for writing since GDAL 3.11 // Compression methods in read-only COMPRESSION_ENTRY(OJPEG, false), From 8357b10f05a1d642a18bd62ee81126883b2e38c5 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Tue, 7 Jan 2025 04:45:52 +0100 Subject: [PATCH 3/7] Coverity Scan fixes --- frmts/libertiff/libertiffdataset.cpp | 4 +++- gcore/gdalalgorithm.cpp | 8 ++++---- gcore/gdalalgorithm.h | 2 +- gcore/gdalmultidim.cpp | 4 ++-- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/frmts/libertiff/libertiffdataset.cpp b/frmts/libertiff/libertiffdataset.cpp index df1a276877c8..099ecad3abc0 100644 --- a/frmts/libertiff/libertiffdataset.cpp +++ b/frmts/libertiff/libertiffdataset.cpp @@ -58,6 +58,7 @@ struct LIBERTIFFDatasetFileReader final : public LIBERTIFF_NS::FileReader uint64_t size() const override { + // coverity[missing_lock,lock_evasion] if (m_nFileSize == 0) { std::lock_guard oLock(m_oMutex); @@ -342,6 +343,7 @@ class LIBERTIFFBand final : public GDALPamRasterBand CPLDebug("LIBERTIFF", "GetLockedBlockRef() called"); } std::lock_guard oLock(m_oMutexBlockCache); + // coverity[sleep] return GDALRasterBand::GetLockedBlockRef(nXBlockOff, nYBlockOff, bJustInitialize); } @@ -1246,7 +1248,7 @@ bool LIBERTIFFDataset::ReadBlock(GByte *pabyBlockData, int nBlockXOff, if constexpr (sizeof(size_t) < sizeof(uint64_t)) { - if (size64 > std::numeric_limits::max()) + if (size64 > std::numeric_limits::max() - 1) { CPLError(CE_Failure, CPLE_NotSupported, "Too large strile"); return false; diff --git a/gcore/gdalalgorithm.cpp b/gcore/gdalalgorithm.cpp index 5fbc3ba7b21f..9f138cf5683a 100644 --- a/gcore/gdalalgorithm.cpp +++ b/gcore/gdalalgorithm.cpp @@ -2258,7 +2258,7 @@ GDALAlgorithm::AddOpenOptionsArg(std::vector *pValue) { auto poDM = GetGDALDriverManager(); auto &datasetValue = inputArg->Get(); - const auto osDSName = datasetValue.GetName(); + const auto &osDSName = datasetValue.GetName(); const std::string osExt = CPLGetExtension(osDSName.c_str()); if (!osExt.empty()) { @@ -2575,7 +2575,7 @@ GDALAlgorithm::AddCreationOptionsArg(std::vector *pValue) { auto poDM = GetGDALDriverManager(); auto &datasetValue = outputArg->Get(); - const auto osDSName = datasetValue.GetName(); + const auto &osDSName = datasetValue.GetName(); const std::string osExt = CPLGetExtension(osDSName.c_str()); if (!osExt.empty()) { @@ -2665,7 +2665,7 @@ GDALAlgorithm::AddLayerCreationOptionsArg(std::vector *pValue) { auto poDM = GetGDALDriverManager(); auto &datasetValue = outputArg->Get(); - const auto osDSName = datasetValue.GetName(); + const auto &osDSName = datasetValue.GetName(); const std::string osExt = CPLGetExtension(osDSName.c_str()); if (!osExt.empty()) { @@ -3247,7 +3247,7 @@ std::string GDALAlgorithm::GetUsageAsJSON() const if (subAlg->m_displayInJSONUsage) { CPLJSONDocument oSubDoc; - oSubDoc.LoadMemory(subAlg->GetUsageAsJSON()); + CPL_IGNORE_RET_VAL(oSubDoc.LoadMemory(subAlg->GetUsageAsJSON())); jSubAlgorithms.Add(oSubDoc.GetRoot()); } } diff --git a/gcore/gdalalgorithm.h b/gcore/gdalalgorithm.h index 44d0a9ecbf73..a42024f971d5 100644 --- a/gcore/gdalalgorithm.h +++ b/gcore/gdalalgorithm.h @@ -1627,7 +1627,7 @@ class CPL_DLL GDALInConstructionAlgorithmArg final : public GDALAlgorithmArg GDALInConstructionAlgorithmArg &SetAutoCompleteFunction( std::function(const std::string &)> f) { - m_autoCompleteFunction = f; + m_autoCompleteFunction = std::move(f); return *this; } diff --git a/gcore/gdalmultidim.cpp b/gcore/gdalmultidim.cpp index cda4be4d99f7..c47f215896bf 100644 --- a/gcore/gdalmultidim.cpp +++ b/gcore/gdalmultidim.cpp @@ -9514,12 +9514,12 @@ GDALDatasetFromArray *GDALDatasetFromArray::Create( BandImageryMetadata &item = aoBandImageryMetadata[iExtraDimIdx]; if (oJsonItem.GetName() == "CENTRAL_WAVELENGTH_UM") { - item.poCentralWavelengthArray = poArray; + item.poCentralWavelengthArray = std::move(poArray); item.dfCentralWavelengthToMicrometer = dfConvToUM; } else { - item.poFWHMArray = poArray; + item.poFWHMArray = std::move(poArray); item.dfFWHMToMicrometer = dfConvToUM; } } From 241cff9bab4daa530c40b5eb12d40cb2cb51c5b2 Mon Sep 17 00:00:00 2001 From: Jayprajapati19 Date: Tue, 7 Jan 2025 12:39:13 +0530 Subject: [PATCH 4/7] Fix GDALGCPsToGeoTransform documentation and usage in tests --- autotest/gcore/gcps2geotransform.py | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/autotest/gcore/gcps2geotransform.py b/autotest/gcore/gcps2geotransform.py index 917c42df8d5e..e2cbdd775699 100755 --- a/autotest/gcore/gcps2geotransform.py +++ b/autotest/gcore/gcps2geotransform.py @@ -14,13 +14,11 @@ ############################################################################### import gdaltest - from osgeo import gdal ############################################################################### # Helper to make gcps - def _list2gcps(src_list): gcp_list = [] for src_tuple in src_list: @@ -32,11 +30,9 @@ def _list2gcps(src_list): gcp_list.append(gcp) return gcp_list - ############################################################################### # Test simple exact case of turning GCPs into a GeoTransform. - def test_gcps2gt_1(): gt = gdal.GCPsToGeoTransform( @@ -52,11 +48,9 @@ def test_gcps2gt_1(): gt, (400000.0, 100.0, 0.0, 370000.0, 0.0, -10.0), 0.000001 ) - ############################################################################### # Similar but non-exact. - def test_gcps2gt_2(): gt = gdal.GCPsToGeoTransform( @@ -73,14 +67,12 @@ def test_gcps2gt_2(): gt, (400000.0, 100.0, 0.0, 370000.0025, -5e-05, -9.999975), 0.000001 ) - ############################################################################### # bApproxOK false, and no good solution. - def test_gcps2gt_3(): - approx_ok = 0 + approx_ok = False gt = gdal.GCPsToGeoTransform( _list2gcps( [ @@ -94,11 +86,9 @@ def test_gcps2gt_3(): ) assert gt is None, "Expected failure when no good solution." - ############################################################################### # Single point - Should return None. - def test_gcps2gt_4(): gt = gdal.GCPsToGeoTransform( @@ -110,11 +100,9 @@ def test_gcps2gt_4(): ) assert gt is None, "Expected failure for single GCP." - ############################################################################### # Two points - simple offset and scale, no rotation. - def test_gcps2gt_5(): gt = gdal.GCPsToGeoTransform( @@ -129,11 +117,9 @@ def test_gcps2gt_5(): gt, (400000.0, 100.0, 0.0, 370000.0, 0.0, -10.0), 0.000001 ) - ############################################################################### # Special case for four points in a particular order. Exact result. - def test_gcps2gt_6(): gt = gdal.GCPsToGeoTransform( @@ -148,11 +134,9 @@ def test_gcps2gt_6(): ) gdaltest.check_geotransform(gt, (0.0, 1.0, 0.0, 0.0, 0.0, 1.0), 0.000001) - ############################################################################### # Try a case that is hard to do without normalization. - def test_gcps2gt_7(): gt = gdal.GCPsToGeoTransform( @@ -167,11 +151,9 @@ def test_gcps2gt_7(): ) gdaltest.check_geotransform(gt, (0.0, 1.0, 0.0, 0.0, 0.0, 1.0), 0.000001) - ############################################################################### # A fairly messy real world case without a easy to predict result. - def test_gcps2gt_8(): gt = gdal.GCPsToGeoTransform( From ba93604e3fcd47cb6b2406f1cebde4027d7c8e59 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Tue, 7 Jan 2025 14:37:55 +0100 Subject: [PATCH 5/7] typo fix --- frmts/gtiff/gtiffrasterband_read.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frmts/gtiff/gtiffrasterband_read.cpp b/frmts/gtiff/gtiffrasterband_read.cpp index c29be2bc98f4..44097ff8fc31 100644 --- a/frmts/gtiff/gtiffrasterband_read.cpp +++ b/frmts/gtiff/gtiffrasterband_read.cpp @@ -1071,7 +1071,7 @@ void *GTiffRasterBand::CacheMultiRange(int nXOff, int nYOff, int nXSize, VSILFILE *fp = VSI_TIFFGetVSILFile(th); - // An error in VSIFReadMultiRangeL() will not be criticial, + // An error in VSIFReadMultiRangeL() will not be critical, // as this method is an optimization, and if it fails, // tile-by-tile data acquisition will be done, so we can // temporary turn failures into warnings. From 955c342b513c5879082455d585578e84e2624537 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Tue, 7 Jan 2025 15:20:19 +0100 Subject: [PATCH 6/7] Fix pre-commit issue --- autotest/gcore/gcps2geotransform.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/autotest/gcore/gcps2geotransform.py b/autotest/gcore/gcps2geotransform.py index e2cbdd775699..db803924d632 100755 --- a/autotest/gcore/gcps2geotransform.py +++ b/autotest/gcore/gcps2geotransform.py @@ -14,11 +14,13 @@ ############################################################################### import gdaltest + from osgeo import gdal ############################################################################### # Helper to make gcps + def _list2gcps(src_list): gcp_list = [] for src_tuple in src_list: @@ -30,9 +32,11 @@ def _list2gcps(src_list): gcp_list.append(gcp) return gcp_list + ############################################################################### # Test simple exact case of turning GCPs into a GeoTransform. + def test_gcps2gt_1(): gt = gdal.GCPsToGeoTransform( @@ -48,9 +52,11 @@ def test_gcps2gt_1(): gt, (400000.0, 100.0, 0.0, 370000.0, 0.0, -10.0), 0.000001 ) + ############################################################################### # Similar but non-exact. + def test_gcps2gt_2(): gt = gdal.GCPsToGeoTransform( @@ -67,9 +73,11 @@ def test_gcps2gt_2(): gt, (400000.0, 100.0, 0.0, 370000.0025, -5e-05, -9.999975), 0.000001 ) + ############################################################################### # bApproxOK false, and no good solution. + def test_gcps2gt_3(): approx_ok = False @@ -86,9 +94,11 @@ def test_gcps2gt_3(): ) assert gt is None, "Expected failure when no good solution." + ############################################################################### # Single point - Should return None. + def test_gcps2gt_4(): gt = gdal.GCPsToGeoTransform( @@ -100,9 +110,11 @@ def test_gcps2gt_4(): ) assert gt is None, "Expected failure for single GCP." + ############################################################################### # Two points - simple offset and scale, no rotation. + def test_gcps2gt_5(): gt = gdal.GCPsToGeoTransform( @@ -117,9 +129,11 @@ def test_gcps2gt_5(): gt, (400000.0, 100.0, 0.0, 370000.0, 0.0, -10.0), 0.000001 ) + ############################################################################### # Special case for four points in a particular order. Exact result. + def test_gcps2gt_6(): gt = gdal.GCPsToGeoTransform( @@ -134,9 +148,11 @@ def test_gcps2gt_6(): ) gdaltest.check_geotransform(gt, (0.0, 1.0, 0.0, 0.0, 0.0, 1.0), 0.000001) + ############################################################################### # Try a case that is hard to do without normalization. + def test_gcps2gt_7(): gt = gdal.GCPsToGeoTransform( @@ -151,9 +167,11 @@ def test_gcps2gt_7(): ) gdaltest.check_geotransform(gt, (0.0, 1.0, 0.0, 0.0, 0.0, 1.0), 0.000001) + ############################################################################### # A fairly messy real world case without a easy to predict result. + def test_gcps2gt_8(): gt = gdal.GCPsToGeoTransform( From 1646133c445fad204b1bc57862f7a9c6dd263433 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Tue, 7 Jan 2025 16:24:41 +0100 Subject: [PATCH 7/7] LIBERTIFF: error out on invalid datasets --- frmts/libertiff/libertiffdataset.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/frmts/libertiff/libertiffdataset.cpp b/frmts/libertiff/libertiffdataset.cpp index 099ecad3abc0..5b496081fac8 100644 --- a/frmts/libertiff/libertiffdataset.cpp +++ b/frmts/libertiff/libertiffdataset.cpp @@ -2173,6 +2173,13 @@ bool LIBERTIFFDataset::Open(std::unique_ptr image) } const GDALDataType eDT = ComputeGDALDataType(); + if (eDT == GDT_Unknown) + { + CPLDebug("LIBERTIFF", + "BitsPerSample = %u and SampleFormat=%u unhandled", + m_image->bitsPerSample(), m_image->sampleFormat()); + return false; + } // Deal with Predictor tag if (m_image->predictor() == 2)