From 2ac41d7c67f0d7c31aa4c0702a5153750a1b8ed8 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sun, 1 Sep 2024 13:42:28 +0200 Subject: [PATCH] GDALWarpResolveWorkingDataType(): ignore srcNoDataValue if it doesn't fit into the data type of the source band --- alg/gdalwarper.cpp | 26 ++++++++++++++++++++++++++ autotest/cpp/test_alg.cpp | 29 +++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/alg/gdalwarper.cpp b/alg/gdalwarper.cpp index d061cadb8736..e44ea097db10 100644 --- a/alg/gdalwarper.cpp +++ b/alg/gdalwarper.cpp @@ -1533,6 +1533,32 @@ void CPL_STDCALL GDALWarpResolveWorkingDataType(GDALWarpOptions *psOptions) psOptions->eWorkingDataType = GDT_Byte; + // If none of the provided input nodata values can be represented in the + // data type of the corresponding source band, ignore them. + if (psOptions->hSrcDS && psOptions->padfSrcNoDataReal) + { + int nCountInvalidSrcNoDataReal = 0; + for (int iBand = 0; iBand < psOptions->nBandCount; iBand++) + { + GDALRasterBandH hSrcBand = GDALGetRasterBand( + psOptions->hSrcDS, psOptions->panSrcBands[iBand]); + + if (hSrcBand && + !GDALIsValueExactAs(psOptions->padfSrcNoDataReal[iBand], + GDALGetRasterDataType(hSrcBand))) + { + nCountInvalidSrcNoDataReal++; + } + } + if (nCountInvalidSrcNoDataReal == psOptions->nBandCount) + { + CPLFree(psOptions->padfSrcNoDataReal); + psOptions->padfSrcNoDataReal = nullptr; + CPLFree(psOptions->padfSrcNoDataImag); + psOptions->padfSrcNoDataImag = nullptr; + } + } + for (int iBand = 0; iBand < psOptions->nBandCount; iBand++) { if (psOptions->hDstDS != nullptr) diff --git a/autotest/cpp/test_alg.cpp b/autotest/cpp/test_alg.cpp index d8c5d64a4b44..6d58a164164e 100644 --- a/autotest/cpp/test_alg.cpp +++ b/autotest/cpp/test_alg.cpp @@ -151,6 +151,35 @@ TEST_F(test_alg, GDALWarpResolveWorkingDataType_padfSrcNoDataReal) GDALDestroyWarpOptions(psOptions); } +// GDALWarpResolveWorkingDataType: effect of padfSrcNoDataReal +TEST_F(test_alg, GDALWarpResolveWorkingDataType_padfSrcNoDataReal_with_band) +{ + GDALDatasetUniquePtr poDS(GDALDriver::FromHandle(GDALGetDriverByName("MEM")) + ->Create("", 1, 1, 1, GDT_Byte, nullptr)); + GDALWarpOptions *psOptions = GDALCreateWarpOptions(); + psOptions->hSrcDS = GDALDataset::ToHandle(poDS.get()); + psOptions->nBandCount = 1; + psOptions->panSrcBands = + static_cast(CPLMalloc(psOptions->nBandCount * sizeof(int))); + psOptions->panSrcBands[0] = 1; + psOptions->padfSrcNoDataReal = + static_cast(CPLMalloc(sizeof(double))); + psOptions->padfSrcNoDataReal[0] = 0.0; + GDALWarpResolveWorkingDataType(psOptions); + EXPECT_EQ(psOptions->eWorkingDataType, GDT_Byte); + + psOptions->padfSrcNoDataReal[0] = -1.0; + GDALWarpResolveWorkingDataType(psOptions); + EXPECT_EQ(psOptions->eWorkingDataType, GDT_Byte); + + psOptions->eWorkingDataType = GDT_Unknown; + psOptions->padfSrcNoDataReal[0] = 2.0; + GDALWarpResolveWorkingDataType(psOptions); + EXPECT_EQ(psOptions->eWorkingDataType, GDT_Byte); + + GDALDestroyWarpOptions(psOptions); +} + // GDALWarpResolveWorkingDataType: effect of padfSrcNoDataImag TEST_F(test_alg, GDALWarpResolveWorkingDataType_padfSrcNoDataImag) {