From 3621158eb7b2e7ba6f12bc548ab8686d0f43c9ec Mon Sep 17 00:00:00 2001 From: Momtchil Momtchev Date: Thu, 8 Aug 2024 14:15:16 +0200 Subject: [PATCH 1/4] try polyfilling on Node 16 --- test/_common.ts | 6 ++++++ test/tsconfig.test.json | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/test/_common.ts b/test/_common.ts index 893dd8e89..5eb4b6ced 100644 --- a/test/_common.ts +++ b/test/_common.ts @@ -1,6 +1,12 @@ import * as gdal from 'gdal-async' +import structuredClone from '@ungap/structured-clone' console.log(`GDAL Version: ${gdal.version}, source: ${gdal.bundled ? 'bundled' : 'system library'}`) +if (!('structuredClone' in globalThis)) { + console.log('Using a JS implementation of structuredClone') + // eslint-disable-next-line @typescript-eslint/no-explicit-any + globalThis.structuredClone = structuredClone as any +} // gc tracing try { diff --git a/test/tsconfig.test.json b/test/tsconfig.test.json index e1676a168..f7d1a8706 100644 --- a/test/tsconfig.test.json +++ b/test/tsconfig.test.json @@ -2,6 +2,7 @@ "compilerOptions": { "downlevelIteration": true, "strict": true, - "strictNullChecks": true + "strictNullChecks": true, + "esModuleInterop": true } } From 880ae676d08ea9dd6a8a9e5ef8e49fd53377d194 Mon Sep 17 00:00:00 2001 From: Momtchil Momtchev Date: Thu, 8 Aug 2024 19:35:04 +0200 Subject: [PATCH 2/4] remove esModuleInterop and use a namespace import --- test/_common.ts | 2 +- test/tsconfig.test.json | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/test/_common.ts b/test/_common.ts index 5eb4b6ced..c58d7db35 100644 --- a/test/_common.ts +++ b/test/_common.ts @@ -1,5 +1,5 @@ import * as gdal from 'gdal-async' -import structuredClone from '@ungap/structured-clone' +import * as structuredClone from '@ungap/structured-clone' console.log(`GDAL Version: ${gdal.version}, source: ${gdal.bundled ? 'bundled' : 'system library'}`) if (!('structuredClone' in globalThis)) { diff --git a/test/tsconfig.test.json b/test/tsconfig.test.json index f7d1a8706..e1676a168 100644 --- a/test/tsconfig.test.json +++ b/test/tsconfig.test.json @@ -2,7 +2,6 @@ "compilerOptions": { "downlevelIteration": true, "strict": true, - "strictNullChecks": true, - "esModuleInterop": true + "strictNullChecks": true } } From 33a8a4606aff3558df4c6db24a5621aa8cb19d0a Mon Sep 17 00:00:00 2001 From: Momtchil Momtchev Date: Thu, 8 Aug 2024 20:14:43 +0200 Subject: [PATCH 3/4] try loading the polyfill in the eslint config file --- test/_common.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/test/_common.ts b/test/_common.ts index c58d7db35..893dd8e89 100644 --- a/test/_common.ts +++ b/test/_common.ts @@ -1,12 +1,6 @@ import * as gdal from 'gdal-async' -import * as structuredClone from '@ungap/structured-clone' console.log(`GDAL Version: ${gdal.version}, source: ${gdal.bundled ? 'bundled' : 'system library'}`) -if (!('structuredClone' in globalThis)) { - console.log('Using a JS implementation of structuredClone') - // eslint-disable-next-line @typescript-eslint/no-explicit-any - globalThis.structuredClone = structuredClone as any -} // gc tracing try { From 86107f717b92ce55f4ddacb46b9c97e11f65528e Mon Sep 17 00:00:00 2001 From: Momtchil Momtchev Date: Fri, 16 Aug 2024 21:34:45 +0200 Subject: [PATCH 4/4] update GDAL to 3.9.2 --- CHANGELOG.md | 5 + deps/libgdal.sh | 2 +- deps/libgdal/gdal/.travis.yml | 36 +- deps/libgdal/gdal/CITATION.cff | 4 +- deps/libgdal/gdal/VERSION | 2 +- deps/libgdal/gdal/alg/contour.cpp | 8 + deps/libgdal/gdal/alg/gdal_crs.cpp | 16 + deps/libgdal/gdal/alg/gdalsievefilter.cpp | 93 ++- deps/libgdal/gdal/alg/gdaltransformer.cpp | 7 +- deps/libgdal/gdal/apps/argparse/argparse.hpp | 7 +- .../apps/data/gdalinfo_output.schema.json | 6 +- deps/libgdal/gdal/apps/gdal_rasterize_lib.cpp | 87 ++- deps/libgdal/gdal/apps/gdal_translate_lib.cpp | 49 +- deps/libgdal/gdal/apps/gdalbuildvrt_lib.cpp | 15 + deps/libgdal/gdal/apps/gdalinfo_lib.cpp | 8 +- deps/libgdal/gdal/apps/gdallocationinfo.cpp | 11 +- deps/libgdal/gdal/apps/gdalwarp_lib.cpp | 33 +- deps/libgdal/gdal/apps/ogr2ogr_lib.cpp | 81 +- deps/libgdal/gdal/apps/ogrinfo_lib.cpp | 27 +- deps/libgdal/gdal/apps/sozip.cpp | 7 + deps/libgdal/gdal/apps/test_ogrsf.cpp | 188 ++++- .../gdal/cmake/helpers/GdalDriverHelper.cmake | 41 +- .../gdal/cmake/helpers/configure.cmake | 8 +- .../gdal/frmts/aaigrid/aaigriddataset.cpp | 3 +- .../gdal/frmts/basisu_ktx2/CMakeLists.txt | 3 +- .../gdal/frmts/basisu_ktx2/basisudrivercore.h | 8 +- .../gdal/frmts/basisu_ktx2/ktx2drivercore.h | 8 +- deps/libgdal/gdal/frmts/dds/CMakeLists.txt | 3 +- deps/libgdal/gdal/frmts/dds/ddsdrivercore.h | 8 +- deps/libgdal/gdal/frmts/ecw/CMakeLists.txt | 3 +- deps/libgdal/gdal/frmts/ecw/ecwdrivercore.h | 16 +- .../gdal/frmts/esric/esric_dataset.cpp | 360 +++++++-- deps/libgdal/gdal/frmts/exr/CMakeLists.txt | 3 +- deps/libgdal/gdal/frmts/exr/exrdrivercore.h | 8 +- deps/libgdal/gdal/frmts/fits/CMakeLists.txt | 3 +- deps/libgdal/gdal/frmts/fits/fitsdrivercore.h | 8 +- .../gdal/frmts/georaster/CMakeLists.txt | 3 +- .../frmts/georaster/georasterdrivercore.h | 8 +- deps/libgdal/gdal/frmts/gif/CMakeLists.txt | 3 +- deps/libgdal/gdal/frmts/gif/gifdrivercore.h | 12 +- deps/libgdal/gdal/frmts/grib/CMakeLists.txt | 3 +- deps/libgdal/gdal/frmts/grib/gribdataset.cpp | 100 ++- deps/libgdal/gdal/frmts/grib/gribdrivercore.h | 8 +- deps/libgdal/gdal/frmts/gta/CMakeLists.txt | 3 +- deps/libgdal/gdal/frmts/gta/gtadrivercore.h | 9 +- deps/libgdal/gdal/frmts/gtiff/cogdriver.cpp | 30 +- deps/libgdal/gdal/frmts/gtiff/gt_overview.cpp | 14 +- deps/libgdal/gdal/frmts/gtiff/gt_overview.h | 3 +- deps/libgdal/gdal/frmts/gtiff/gt_wkt_srs.cpp | 317 ++++---- .../gdal/frmts/gtiff/gtiffdataset_read.cpp | 30 +- .../gdal/frmts/gtiff/gtiffdataset_write.cpp | 82 +- .../frmts/gtiff/gtiffrasterband_write.cpp | 37 +- .../frmts/gtiff/libgeotiff/geo_normalize.c | 33 +- .../frmts/gtiff/libgeotiff/geo_normalize.h | 12 +- .../gdal/frmts/gtiff/libgeotiff/geotiff.h | 2 +- .../frmts/gtiff/libgeotiff/geotiff_proj4.c | 2 +- .../gdal/frmts/gtiff/libtiff/tif_hash_set.c | 4 +- deps/libgdal/gdal/frmts/hdf4/CMakeLists.txt | 3 +- deps/libgdal/gdal/frmts/hdf4/hdf4drivercore.h | 18 +- deps/libgdal/gdal/frmts/hdf5/CMakeLists.txt | 3 +- .../gdal/frmts/hdf5/gh5_convenience.cpp | 11 + deps/libgdal/gdal/frmts/hdf5/hdf5_api.h | 4 + deps/libgdal/gdal/frmts/hdf5/hdf5dataset.cpp | 68 ++ deps/libgdal/gdal/frmts/hdf5/hdf5dataset.h | 4 +- deps/libgdal/gdal/frmts/hdf5/hdf5drivercore.h | 43 +- .../gdal/frmts/hdf5/hdf5imagedataset.cpp | 154 +++- deps/libgdal/gdal/frmts/hdf5/hdf5multidim.cpp | 63 +- deps/libgdal/gdal/frmts/heif/CMakeLists.txt | 3 +- deps/libgdal/gdal/frmts/heif/heifdrivercore.h | 9 +- deps/libgdal/gdal/frmts/jp2kak/CMakeLists.txt | 3 +- .../gdal/frmts/jp2kak/jp2kakdrivercore.h | 8 +- .../libgdal/gdal/frmts/jp2lura/CMakeLists.txt | 3 +- .../gdal/frmts/jp2lura/jp2luradrivercore.h | 8 +- deps/libgdal/gdal/frmts/jpeg/CMakeLists.txt | 1 + deps/libgdal/gdal/frmts/jpeg/jpegdrivercore.h | 11 +- deps/libgdal/gdal/frmts/jpeg/jpgdataset.cpp | 11 +- deps/libgdal/gdal/frmts/jpegxl/CMakeLists.txt | 3 +- deps/libgdal/gdal/frmts/jpegxl/jpegxl.cpp | 3 +- .../gdal/frmts/jpegxl/jpegxldrivercore.h | 8 +- .../libgdal/gdal/frmts/jpipkak/CMakeLists.txt | 3 +- .../gdal/frmts/jpipkak/jpipkakdrivercore.h | 5 +- deps/libgdal/gdal/frmts/kea/CMakeLists.txt | 3 +- deps/libgdal/gdal/frmts/kea/keaband.cpp | 12 +- deps/libgdal/gdal/frmts/kea/keaband.h | 4 +- deps/libgdal/gdal/frmts/kea/keadataset.h | 4 +- deps/libgdal/gdal/frmts/kea/keadrivercore.h | 8 +- deps/libgdal/gdal/frmts/mrf/CMakeLists.txt | 1 + deps/libgdal/gdal/frmts/mrf/mrfdrivercore.h | 8 +- deps/libgdal/gdal/frmts/mrsid/CMakeLists.txt | 3 +- .../gdal/frmts/mrsid/mrsiddrivercore.h | 15 +- deps/libgdal/gdal/frmts/msg/CMakeLists.txt | 3 +- deps/libgdal/gdal/frmts/msg/msgdrivercore.h | 5 +- deps/libgdal/gdal/frmts/netcdf/CMakeLists.txt | 10 +- .../gdal/frmts/netcdf/netcdfdataset.cpp | 97 ++- .../gdal/frmts/netcdf/netcdfdrivercore.cpp | 19 +- .../gdal/frmts/netcdf/netcdfdrivercore.h | 9 +- .../gdal/frmts/netcdf/netcdfmultidim.cpp | 27 +- .../libgdal/gdal/frmts/netcdf/netcdfvirtual.h | 3 +- deps/libgdal/gdal/frmts/nitf/CMakeLists.txt | 1 + deps/libgdal/gdal/frmts/nitf/nitfdrivercore.h | 8 +- .../libgdal/gdal/frmts/nitf/nitfwritejpeg.cpp | 32 +- .../gdal/frmts/northwood/northwood.cpp | 10 +- .../gdal/frmts/ogcapi/gdalogcapidataset.cpp | 29 +- .../gdal/frmts/openjpeg/CMakeLists.txt | 3 +- .../gdal/frmts/openjpeg/openjpegdrivercore.h | 5 +- deps/libgdal/gdal/frmts/pcidsk/CMakeLists.txt | 3 +- .../gdal/frmts/pcidsk/pcidskdrivercore.h | 8 +- .../gdal/frmts/pcraster/CMakeLists.txt | 3 +- .../gdal/frmts/pcraster/pcrasterdrivercore.h | 8 +- deps/libgdal/gdal/frmts/pdf/CMakeLists.txt | 3 +- deps/libgdal/gdal/frmts/pdf/gdal_pdf.h | 18 +- deps/libgdal/gdal/frmts/pdf/pdfdataset.cpp | 4 +- deps/libgdal/gdal/frmts/pdf/pdfdrivercore.h | 11 +- .../libgdal/gdal/frmts/pdf/pdfreadvectors.cpp | 405 ++++++---- deps/libgdal/gdal/frmts/pdf/pdfsdk_headers.h | 16 +- deps/libgdal/gdal/frmts/pds/CMakeLists.txt | 1 + deps/libgdal/gdal/frmts/pds/pdsdrivercore.h | 47 +- deps/libgdal/gdal/frmts/png/CMakeLists.txt | 3 +- deps/libgdal/gdal/frmts/png/pngdrivercore.h | 8 +- .../gdal/frmts/postgisraster/CMakeLists.txt | 3 +- .../postgisraster/postgisrasterdrivercore.h | 13 +- .../gdal/frmts/rasterlite/CMakeLists.txt | 3 +- .../frmts/rasterlite/rasterlitedrivercore.h | 8 +- .../gdal/frmts/srtmhgt/srtmhgtdataset.cpp | 22 +- .../gdal/frmts/stacit/stacitdataset.cpp | 125 ++- deps/libgdal/gdal/frmts/tiledb/CMakeLists.txt | 3 +- .../gdal/frmts/tiledb/tiledbdrivercore.h | 5 +- .../gdal/frmts/vrt/gdaltileindexdataset.cpp | 58 +- deps/libgdal/gdal/frmts/vrt/vrtdataset.h | 38 +- deps/libgdal/gdal/frmts/vrt/vrtfilters.cpp | 20 +- deps/libgdal/gdal/frmts/vrt/vrtsources.cpp | 135 ++-- deps/libgdal/gdal/frmts/wcs/CMakeLists.txt | 3 +- deps/libgdal/gdal/frmts/wcs/wcsdataset110.cpp | 7 + deps/libgdal/gdal/frmts/wcs/wcsdrivercore.h | 8 +- deps/libgdal/gdal/frmts/webp/CMakeLists.txt | 3 +- deps/libgdal/gdal/frmts/webp/webpdrivercore.h | 8 +- deps/libgdal/gdal/frmts/wms/CMakeLists.txt | 3 +- deps/libgdal/gdal/frmts/wms/wmsdrivercore.h | 8 +- deps/libgdal/gdal/frmts/wmts/CMakeLists.txt | 3 +- deps/libgdal/gdal/frmts/wmts/wmtsdataset.cpp | 142 ++-- deps/libgdal/gdal/frmts/wmts/wmtsdrivercore.h | 8 +- deps/libgdal/gdal/frmts/zarr/CMakeLists.txt | 3 +- deps/libgdal/gdal/frmts/zarr/zarr_array.cpp | 29 +- deps/libgdal/gdal/frmts/zarr/zarrdrivercore.h | 8 +- deps/libgdal/gdal/gcore/gdal_misc.cpp | 18 +- deps/libgdal/gdal/gcore/gdal_priv.h | 84 +- .../gdal/gcore/gdal_priv_templates.hpp | 132 +++- deps/libgdal/gdal/gcore/gdal_version.h | 6 +- .../gcore/gdal_version_full/gdal_version.h | 6 +- deps/libgdal/gdal/gcore/gdaldriver.cpp | 1 + deps/libgdal/gdal/gcore/gdalmultidim.cpp | 11 + .../libgdal/gdal/gcore/gdalnodatamaskband.cpp | 94 ++- deps/libgdal/gdal/gcore/gdalrasterband.cpp | 75 +- deps/libgdal/gdal/gcore/overview.cpp | 717 +++++++++--------- deps/libgdal/gdal/gcore/rasterio.cpp | 114 ++- deps/libgdal/gdal/ogr/ogr_srs_esri.cpp | 62 +- deps/libgdal/gdal/ogr/ogr_srs_usgs.cpp | 23 +- deps/libgdal/gdal/ogr/ogrfeature.cpp | 62 +- deps/libgdal/gdal/ogr/ogrgeometry.cpp | 99 +-- .../gdal/ogr/ogrsf_frmts/arrow/CMakeLists.txt | 3 +- .../ogrsf_frmts/arrow/ogrfeatherdrivercore.h | 12 +- .../ogr/ogrsf_frmts/avc/ogravcbinlayer.cpp | 6 +- .../gdal/ogr/ogrsf_frmts/cad/CMakeLists.txt | 3 +- .../ogr/ogrsf_frmts/cad/ogrcaddrivercore.h | 5 +- .../gdal/ogr/ogrsf_frmts/carto/CMakeLists.txt | 3 +- .../ogrsf_frmts/carto/ogrcartodrivercore.h | 8 +- .../gdal/ogr/ogrsf_frmts/dwg/CMakeLists.txt | 3 +- .../ogr/ogrsf_frmts/dwg/ogrdgnv8drivercore.h | 8 +- .../ogr/ogrsf_frmts/dwg/ogrdwgdrivercore.h | 8 +- .../dxf/ogrdxf_polyline_smooth.cpp | 14 +- .../ogr/ogrsf_frmts/elastic/CMakeLists.txt | 3 +- .../elastic/ogrelasticdrivercore.h | 9 +- .../ogrsf_frmts/elastic/ogrelasticlayer.cpp | 8 +- .../ogr/ogrsf_frmts/filegdb/CMakeLists.txt | 3 +- .../ogr/ogrsf_frmts/filegdb/FGdbDriverCore.h | 11 +- .../ogr/ogrsf_frmts/filegdb/FGdbLayer.cpp | 2 + .../flatgeobuf/ogrflatgeobuflayer.cpp | 6 +- .../ogr/ogrsf_frmts/generic/ogr_gensql.cpp | 116 ++- .../gdal/ogr/ogrsf_frmts/generic/ogrlayer.cpp | 245 ++++-- .../ogr/ogrsf_frmts/generic/ogrlayerarrow.cpp | 44 +- .../ogr/ogrsf_frmts/geojson/ogr_geojson.h | 6 + .../ogrsf_frmts/geojson/ogresrijsonreader.cpp | 29 +- .../geojson/ogrgeojsondatasource.cpp | 4 +- .../ogrsf_frmts/geojson/ogrgeojsondriver.cpp | 136 ++-- .../ogrsf_frmts/geojson/ogrgeojsonlayer.cpp | 37 +- .../ogrsf_frmts/geojson/ogrgeojsonutils.cpp | 129 +++- .../ogr/ogrsf_frmts/geojson/ogrgeojsonutils.h | 2 +- .../geojson/ogrgeojsonwritelayer.cpp | 49 +- .../gdal/ogr/ogrsf_frmts/gml/gmlhandler.cpp | 15 +- .../gdal/ogr/ogrsf_frmts/gml/gmlreaderp.h | 5 + .../ogr/ogrsf_frmts/gml/hugefileresolver.cpp | 56 +- .../gdal/ogr/ogrsf_frmts/gml/ogr_gml.h | 18 +- .../ogr/ogrsf_frmts/gml/ogrgmldatasource.cpp | 91 ++- .../gdal/ogr/ogrsf_frmts/gml/ogrgmllayer.cpp | 34 +- .../gdal/ogr/ogrsf_frmts/gmlas/CMakeLists.txt | 3 +- .../gdal/ogr/ogrsf_frmts/gmlas/ogr_gmlas.h | 2 +- .../ogrsf_frmts/gmlas/ogrgmlasdrivercore.h | 8 +- .../gmlas/ogrgmlasschemaanalyzer.cpp | 50 +- .../ogr/ogrsf_frmts/gmlas/ogrgmlasutils.cpp | 5 +- .../gpkg/ogrgeopackagetablelayer.cpp | 4 +- .../ogr/ogrsf_frmts/gtfs/ogrgtfsdriver.cpp | 16 +- .../gdal/ogr/ogrsf_frmts/hana/CMakeLists.txt | 3 +- .../ogr/ogrsf_frmts/hana/ogrhanadrivercore.h | 16 +- .../gdal/ogr/ogrsf_frmts/idb/CMakeLists.txt | 3 +- .../ogr/ogrsf_frmts/idb/ogridbdrivercore.h | 8 +- .../ogrsf_frmts/jsonfg/ogrjsonfgdataset.cpp | 12 +- .../ogr/ogrsf_frmts/libkml/CMakeLists.txt | 3 +- .../gdal/ogr/ogrsf_frmts/libkml/ogr_libkml.h | 6 +- .../libkml/ogrlibkmldatasource.cpp | 92 ++- .../ogrsf_frmts/libkml/ogrlibkmldrivercore.h | 8 +- .../libkml/ogrlibkmlfeaturestyle.cpp | 121 +-- .../ogr/ogrsf_frmts/libkml/ogrlibkmlfield.cpp | 7 + .../gdal/ogr/ogrsf_frmts/mem/ogr_mem.h | 1 + .../gdal/ogr/ogrsf_frmts/mem/ogrmemlayer.cpp | 3 +- .../ogrsf_frmts/miramon/data/MM_m_idofic.csv | 92 ++- .../miramon/mm_gdal_driver_structs.h | 23 +- .../ogrsf_frmts/miramon/mm_gdal_functions.c | 44 +- .../ogrsf_frmts/miramon/mm_gdal_functions.h | 3 +- .../gdal/ogr/ogrsf_frmts/miramon/mm_wrlayr.c | 181 ++++- .../ogrsf_frmts/miramon/ogrmiramonlayer.cpp | 297 ++++---- .../ogr/ogrsf_frmts/mitab/mitab_datfile.cpp | 64 +- .../ogrsf_frmts/mitab/mitab_imapinfofile.cpp | 12 +- .../gdal/ogr/ogrsf_frmts/mitab/mitab_priv.h | 6 +- .../ogr/ogrsf_frmts/mitab/mitab_tabfile.cpp | 23 +- .../ogrsf_frmts/mitab/mitab_tabseamless.cpp | 2 + .../ogr/ogrsf_frmts/mitab/mitab_tabview.cpp | 2 + .../ogr/ogrsf_frmts/mongodbv3/CMakeLists.txt | 3 +- .../mongodbv3/ogrmongodbv3drivercore.h | 9 +- .../ogrsf_frmts/mssqlspatial/CMakeLists.txt | 3 +- .../mssqlspatial/ogrmssqlspatialdrivercore.h | 9 +- .../ogr/ogrsf_frmts/mvt/ogrmvtdataset.cpp | 2 + .../gdal/ogr/ogrsf_frmts/mysql/CMakeLists.txt | 3 +- .../ogrsf_frmts/mysql/ogrmysqldrivercore.h | 8 +- .../gdal/ogr/ogrsf_frmts/oci/CMakeLists.txt | 2 +- .../ogr/ogrsf_frmts/oci/ogrocidrivercore.h | 8 +- .../gdal/ogr/ogrsf_frmts/odbc/CMakeLists.txt | 3 +- .../ogr/ogrsf_frmts/odbc/ogrodbcdrivercore.h | 13 +- .../gdal/ogr/ogrsf_frmts/ods/ogr_ods.h | 14 +- .../ogr/ogrsf_frmts/ods/ogrodsdatasource.cpp | 98 ++- .../gdal/ogr/ogrsf_frmts/ods/ogrodsdriver.cpp | 3 + .../gdal/ogr/ogrsf_frmts/ogdi/CMakeLists.txt | 3 +- .../ogr/ogrsf_frmts/ogdi/ogrogdidrivercore.h | 5 +- .../ogrsf_frmts/openfilegdb/CMakeLists.txt | 3 +- .../ogrsf_frmts/openfilegdb/filegdbindex.cpp | 75 +- .../ogrsf_frmts/openfilegdb/filegdbtable.cpp | 78 +- .../ogrsf_frmts/openfilegdb/filegdbtable.h | 39 +- .../openfilegdb/filegdbtable_write.cpp | 17 +- .../openfilegdb/filegdbtable_write_fields.cpp | 66 +- .../openfilegdb/ogropenfilegdbdatasource.cpp | 14 +- .../ogropenfilegdbdatasource_write.cpp | 318 +++++--- .../openfilegdb/ogropenfilegdbdrivercore.h | 11 +- .../openfilegdb/ogropenfilegdblayer.cpp | 36 +- .../openfilegdb/ogropenfilegdblayer_write.cpp | 62 +- .../openfilegdb/test_ofgdb_write.cpp | 41 +- .../ogr/ogrsf_frmts/osm/ogrosmdatasource.cpp | 5 +- .../ogr/ogrsf_frmts/parquet/CMakeLists.txt | 3 +- .../parquet/ogrparquetdrivercore.h | 8 +- .../parquet/ogrparquetwriterlayer.cpp | 6 +- .../gdal/ogr/ogrsf_frmts/pg/CMakeLists.txt | 3 +- deps/libgdal/gdal/ogr/ogrsf_frmts/pg/ogr_pg.h | 9 +- .../ogr/ogrsf_frmts/pg/ogrpgdatasource.cpp | 216 +++++- .../gdal/ogr/ogrsf_frmts/pg/ogrpgdrivercore.h | 8 +- .../gdal/ogr/ogrsf_frmts/pg/ogrpglayer.cpp | 2 +- .../ogr/ogrsf_frmts/pg/ogrpgtablelayer.cpp | 75 +- .../gdal/ogr/ogrsf_frmts/pgdump/ogr_pgdump.h | 6 + .../pgdump/ogrpgdumpdatasource.cpp | 37 +- .../ogr/ogrsf_frmts/pgdump/ogrpgdumplayer.cpp | 95 ++- .../ogr/ogrsf_frmts/plscenes/CMakeLists.txt | 3 +- .../plscenes/ogrplscenesdrivercore.h | 8 +- .../gdal/ogr/ogrsf_frmts/shape/dbfopen.c | 11 +- .../ogr/ogrsf_frmts/shape/ogrshapelayer.cpp | 78 +- .../gdal/ogr/ogrsf_frmts/shape/sbnsearch.c | 2 +- .../gdal/ogr/ogrsf_frmts/shape/shpopen.c | 14 +- .../gdal/ogr/ogrsf_frmts/shape/shptree.c | 2 +- .../gdal/ogr/ogrsf_frmts/sosi/CMakeLists.txt | 3 +- .../ogr/ogrsf_frmts/sosi/ogrsosidrivercore.h | 8 +- .../ogrsf_frmts/sqlite/ogrsqliteutility.cpp | 105 ++- .../gdal/ogr/ogrsf_frmts/vfk/CMakeLists.txt | 3 +- .../ogr/ogrsf_frmts/vfk/ogrvfkdrivercore.h | 8 +- .../ogr/ogrsf_frmts/wfs/ogroapifdriver.cpp | 176 +++-- .../gdal/ogr/ogrsf_frmts/xls/CMakeLists.txt | 3 +- .../ogr/ogrsf_frmts/xls/ogrxlsdrivercore.h | 5 +- .../gdal/ogr/ogrsf_frmts/xlsx/ogr_xlsx.h | 8 + .../ogrsf_frmts/xlsx/ogrxlsxdatasource.cpp | 148 +++- .../ogr/ogrsf_frmts/xlsx/ogrxlsxdriver.cpp | 3 + deps/libgdal/gdal/ogr/ogrspatialreference.cpp | 136 +++- deps/libgdal/gdal/ogr/swq.cpp | 13 +- deps/libgdal/gdal/ogr/swq_op_general.cpp | 13 +- deps/libgdal/gdal/ogr/swq_select.cpp | 3 +- deps/libgdal/gdal/port/cpl_aws.cpp | 55 +- deps/libgdal/gdal/port/cpl_http.cpp | 1 - .../gdal/port/cpl_json_streaming_parser.cpp | 14 +- .../gdal/port/cpl_json_streaming_parser.h | 2 + deps/libgdal/gdal/port/cpl_path.cpp | 76 +- deps/libgdal/gdal/port/cpl_recode.cpp | 7 +- .../libgdal/gdal/port/cpl_vsil_libarchive.cpp | 2 + deps/libgdal/gdal/port/cpl_vsil_win32.cpp | 9 + .../gdal/third_party/LercLib/BitStuffer2.cpp | 14 + .../libgdal_gdal_port_cpl_zlib_header.h.diff | 12 +- 299 files changed, 6982 insertions(+), 3000 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a30ddac1..cc2a2513a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [3.9.2] + +### Added + - GDAL 3.9.2 + ## [3.9.0] 2024-06-24 ### Added diff --git a/deps/libgdal.sh b/deps/libgdal.sh index 61fb01fc3..6c027eab9 100755 --- a/deps/libgdal.sh +++ b/deps/libgdal.sh @@ -5,7 +5,7 @@ set -eu DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd "$DIR/libgdal" -GDAL_VERSION=3.9.0 +GDAL_VERSION=3.9.2 GDAL_VERSION_SUFFIX= dir_gdal=./gdal dir_formats_gyp=./gyp-formats diff --git a/deps/libgdal/gdal/.travis.yml b/deps/libgdal/gdal/.travis.yml index 546aaf9e8..930210c39 100644 --- a/deps/libgdal/gdal/.travis.yml +++ b/deps/libgdal/gdal/.travis.yml @@ -26,24 +26,24 @@ matrix: - BUILD_NAME=s390x - DETAILS="" - - os: linux - arch: arm64-graviton2 - virt: lxd - group: edge - compiler: gcc - language: cpp - sudo: false - dist: jammy - cache: - apt: true - directories: - - $HOME/.ccache - apt: - packages: - - ccache - env: - - BUILD_NAME=graviton2 - - DETAILS= + #- os: linux + # arch: arm64-graviton2 + # virt: lxd + # group: edge + # compiler: gcc + # language: cpp + # sudo: false + # dist: jammy + # cache: + # apt: true + # directories: + # - $HOME/.ccache + # apt: + # packages: + # - ccache + # env: + # - BUILD_NAME=graviton2 + # - DETAILS= before_install: - if ! git diff --name-only $TRAVIS_COMMIT_RANGE | grep -qvE '(.rst)$'; then travis_terminate 0; fi diff --git a/deps/libgdal/gdal/CITATION.cff b/deps/libgdal/gdal/CITATION.cff index 1f035ff76..e89453ce2 100644 --- a/deps/libgdal/gdal/CITATION.cff +++ b/deps/libgdal/gdal/CITATION.cff @@ -2,8 +2,8 @@ cff-version: 1.2.0 message: Please cite this software using these metadata or in the CITATION file. type: software title: GDAL -version: 3.9.0 -date-released: 2024-05-06 +version: 3.9.2 +date-released: 2024-08-13 doi: 10.5281/zenodo.5884351 abstract: GDAL is a translator library for raster and vector geospatial data formats that is released under an MIT style Open Source License by the Open diff --git a/deps/libgdal/gdal/VERSION b/deps/libgdal/gdal/VERSION index a5c4c7633..2009c7dfa 100644 --- a/deps/libgdal/gdal/VERSION +++ b/deps/libgdal/gdal/VERSION @@ -1 +1 @@ -3.9.0 +3.9.2 diff --git a/deps/libgdal/gdal/alg/contour.cpp b/deps/libgdal/gdal/alg/contour.cpp index 34f29761b..c95b28e41 100644 --- a/deps/libgdal/gdal/alg/contour.cpp +++ b/deps/libgdal/gdal/alg/contour.cpp @@ -562,6 +562,14 @@ CPLErr GDALContourGenerateEx(GDALRasterBandH hBand, void *hLayer, if (opt) { contourInterval = CPLAtof(opt); + // Written this way to catch NaN as well. + if (!(contourInterval > 0)) + { + CPLError(CE_Failure, CPLE_AppDefined, + "Invalid value for LEVEL_INTERVAL. Should be strictly " + "positive."); + return CE_Failure; + } } double contourBase = 0.0; diff --git a/deps/libgdal/gdal/alg/gdal_crs.cpp b/deps/libgdal/gdal/alg/gdal_crs.cpp index 74ea4ceff..9c134f0b6 100644 --- a/deps/libgdal/gdal/alg/gdal_crs.cpp +++ b/deps/libgdal/gdal/alg/gdal_crs.cpp @@ -220,6 +220,22 @@ static void *GDALCreateGCPTransformerEx(int nGCPCount, psInfo->nRefCount = 1; psInfo->asGCPs = gdal::GCP::fromC(pasGCPList, nGCPCount); + if (nGCPCount == 2 && nReqOrder == 1 && + psInfo->asGCPs[0].X() != psInfo->asGCPs[1].X() && + psInfo->asGCPs[0].Y() != psInfo->asGCPs[1].Y()) + { + // Assumes that the 2 GCPs form opposite corners of a rectangle, + // and synthetize a 3rd corner + gdal::GCP newGCP; + newGCP.X() = psInfo->asGCPs[1].X(); + newGCP.Y() = psInfo->asGCPs[0].Y(); + newGCP.Pixel() = psInfo->asGCPs[1].Pixel(); + newGCP.Line() = psInfo->asGCPs[0].Line(); + psInfo->asGCPs.emplace_back(std::move(newGCP)); + + nGCPCount = 3; + pasGCPList = gdal::GCP::c_ptr(psInfo->asGCPs); + } memcpy(psInfo->sTI.abySignature, GDAL_GTI2_SIGNATURE, strlen(GDAL_GTI2_SIGNATURE)); diff --git a/deps/libgdal/gdal/alg/gdalsievefilter.cpp b/deps/libgdal/gdal/alg/gdalsievefilter.cpp index a3c60a0cd..5d11f9710 100644 --- a/deps/libgdal/gdal/alg/gdalsievefilter.cpp +++ b/deps/libgdal/gdal/alg/gdalsievefilter.cpp @@ -33,7 +33,6 @@ #include #include -#include #include #include #include @@ -211,30 +210,36 @@ CPLErr CPL_STDCALL GDALSieveFilter(GDALRasterBandH hSrcBand, /* -------------------------------------------------------------------- */ int nXSize = GDALGetRasterBandXSize(hSrcBand); int nYSize = GDALGetRasterBandYSize(hSrcBand); - auto *panLastLineVal = static_cast( - VSI_MALLOC2_VERBOSE(sizeof(std::int64_t), nXSize)); - auto *panThisLineVal = static_cast( - VSI_MALLOC2_VERBOSE(sizeof(std::int64_t), nXSize)); - auto *panLastLineId = - static_cast(VSI_MALLOC2_VERBOSE(sizeof(GInt32), nXSize)); - auto *panThisLineId = - static_cast(VSI_MALLOC2_VERBOSE(sizeof(GInt32), nXSize)); - auto *panThisLineWriteVal = static_cast( - VSI_MALLOC2_VERBOSE(sizeof(std::int64_t), nXSize)); - GByte *pabyMaskLine = hMaskBand != nullptr - ? static_cast(VSI_MALLOC_VERBOSE(nXSize)) - : nullptr; + auto panLastLineValKeeper = std::unique_ptr( + static_cast( + VSI_MALLOC2_VERBOSE(sizeof(std::int64_t), nXSize))); + auto panThisLineValKeeper = std::unique_ptr( + static_cast( + VSI_MALLOC2_VERBOSE(sizeof(std::int64_t), nXSize))); + auto panLastLineIdKeeper = std::unique_ptr( + static_cast(VSI_MALLOC2_VERBOSE(sizeof(GInt32), nXSize))); + auto panThisLineIdKeeper = std::unique_ptr( + static_cast(VSI_MALLOC2_VERBOSE(sizeof(GInt32), nXSize))); + auto panThisLineWriteValKeeper = + std::unique_ptr( + static_cast( + VSI_MALLOC2_VERBOSE(sizeof(std::int64_t), nXSize))); + auto pabyMaskLineKeeper = std::unique_ptr( + hMaskBand != nullptr ? static_cast(VSI_MALLOC_VERBOSE(nXSize)) + : nullptr); + + auto panLastLineVal = panLastLineValKeeper.get(); + auto panThisLineVal = panThisLineValKeeper.get(); + auto panLastLineId = panLastLineIdKeeper.get(); + auto panThisLineId = panThisLineIdKeeper.get(); + auto panThisLineWriteVal = panThisLineWriteValKeeper.get(); + auto pabyMaskLine = pabyMaskLineKeeper.get(); + if (panLastLineVal == nullptr || panThisLineVal == nullptr || panLastLineId == nullptr || panThisLineId == nullptr || panThisLineWriteVal == nullptr || (hMaskBand != nullptr && pabyMaskLine == nullptr)) { - CPLFree(panThisLineId); - CPLFree(panLastLineId); - CPLFree(panThisLineVal); - CPLFree(panLastLineVal); - CPLFree(panThisLineWriteVal); - CPLFree(pabyMaskLine); return CE_Failure; } @@ -316,12 +321,28 @@ CPLErr CPL_STDCALL GDALSieveFilter(GDALRasterBandH hSrcBand, if (eErr == CE_None) oFirstEnum.CompleteMerges(); + /* -------------------------------------------------------------------- */ + /* Check if there are polygons */ + /* -------------------------------------------------------------------- */ + if (!oFirstEnum.panPolyIdMap || !oFirstEnum.panPolyValue) + { + // Can happen if all pixels are masked + if (hSrcBand == hDstBand) + { + pfnProgress(1.0, "", pProgressArg); + return CE_None; + } + else + { + return GDALRasterBandCopyWholeRaster(hSrcBand, hDstBand, nullptr, + pfnProgress, pProgressArg); + } + } + /* -------------------------------------------------------------------- */ /* Push the sizes of merged polygon fragments into the */ /* merged polygon id's count. */ /* -------------------------------------------------------------------- */ - assert(oFirstEnum.panPolyIdMap != nullptr); // for Coverity - assert(oFirstEnum.panPolyValue != nullptr); // for Coverity for (int iPoly = 0; iPoly < oFirstEnum.nNextPolygonId; iPoly++) { if (oFirstEnum.panPolyIdMap[iPoly] != iPoly) @@ -346,10 +367,16 @@ CPLErr CPL_STDCALL GDALSieveFilter(GDALRasterBandH hSrcBand, GDALRasterPolygonEnumerator oSecondEnum(nConnectedness); std::vector anBigNeighbour; - anBigNeighbour.resize(anPolySizes.size()); - - for (int iPoly = 0; iPoly < static_cast(anPolySizes.size()); iPoly++) - anBigNeighbour[iPoly] = -1; + try + { + anBigNeighbour.resize(anPolySizes.size(), -1); + } + catch (const std::exception &) + { + CPLError(CE_Failure, CPLE_OutOfMemory, "%s: Out of memory", + __FUNCTION__); + return CE_Failure; + } /* ==================================================================== */ /* Second pass ... identify the largest neighbour for each */ @@ -540,9 +567,7 @@ CPLErr CPL_STDCALL GDALSieveFilter(GDALRasterBandH hSrcBand, /* ==================================================================== */ oSecondEnum.Clear(); - for (int iY = 0; oFirstEnum.panPolyIdMap != nullptr && // for Coverity - eErr == CE_None && iY < nYSize; - iY++) + for (int iY = 0; eErr == CE_None && iY < nYSize; iY++) { /* -------------------------------------------------------------------- */ @@ -627,15 +652,5 @@ CPLErr CPL_STDCALL GDALSieveFilter(GDALRasterBandH hSrcBand, } } - /* -------------------------------------------------------------------- */ - /* Cleanup */ - /* -------------------------------------------------------------------- */ - CPLFree(panThisLineId); - CPLFree(panLastLineId); - CPLFree(panThisLineVal); - CPLFree(panLastLineVal); - CPLFree(panThisLineWriteVal); - CPLFree(pabyMaskLine); - return eErr; } diff --git a/deps/libgdal/gdal/alg/gdaltransformer.cpp b/deps/libgdal/gdal/alg/gdaltransformer.cpp index bff7c93cc..263fbc2fa 100644 --- a/deps/libgdal/gdal/alg/gdaltransformer.cpp +++ b/deps/libgdal/gdal/alg/gdaltransformer.cpp @@ -1482,7 +1482,12 @@ static void InsertCenterLong(GDALDatasetH hDS, OGRSpatialReference *poSRS, adfGeoTransform[0] + nXSize * adfGeoTransform[1] + nYSize * adfGeoTransform[2])); - if (dfMaxLong - dfMinLong > 360.0) + const double dfEpsilon = + std::max(std::fabs(adfGeoTransform[1]), std::fabs(adfGeoTransform[2])); + // If the raster covers more than 360 degree (allow an extra pixel), + // give up + constexpr double RELATIVE_EPSILON = 0.05; // for numeric precision issues + if (dfMaxLong - dfMinLong > 360.0 + dfEpsilon * (1 + RELATIVE_EPSILON)) return; /* -------------------------------------------------------------------- */ diff --git a/deps/libgdal/gdal/apps/argparse/argparse.hpp b/deps/libgdal/gdal/apps/argparse/argparse.hpp index 118e2145c..0a66f37e0 100644 --- a/deps/libgdal/gdal/apps/argparse/argparse.hpp +++ b/deps/libgdal/gdal/apps/argparse/argparse.hpp @@ -968,7 +968,8 @@ class Argument { std::bind(is_optional, std::placeholders::_1, m_prefix_chars)); dist = static_cast(std::distance(start, end)); if (dist < num_args_min) { - throw std::runtime_error("Too few arguments"); + throw std::runtime_error("Too few arguments for '" + + std::string(m_used_name) + "'."); } } @@ -1357,6 +1358,10 @@ class Argument { * '+' '-' */ static bool is_decimal_literal(std::string_view s) { + if (s == "inf") { + return true; + } + auto is_digit = [](auto c) constexpr { switch (c) { case '0': diff --git a/deps/libgdal/gdal/apps/data/gdalinfo_output.schema.json b/deps/libgdal/gdal/apps/data/gdalinfo_output.schema.json index 166a490d9..a4c50c780 100644 --- a/deps/libgdal/gdal/apps/data/gdalinfo_output.schema.json +++ b/deps/libgdal/gdal/apps/data/gdalinfo_output.schema.json @@ -277,7 +277,7 @@ }, "stac": { - "$comment": "Derived from https://raw.githubusercontent.com/stac-extensions/projection/main/json-schema/schema.json#/definitions/fields, https://raw.githubusercontent.com/stac-extensions/eo/main/json-schema/schema.json#/definitions/bands and https://raw.githubusercontent.com/stac-extensions/eo/main/json-schema/schema.json#/definitions/bands", + "$comment": "Derived from https://raw.githubusercontent.com/stac-extensions/projection/main/json-schema/schema.json#/definitions/fields, https://raw.githubusercontent.com/stac-extensions/eo/v1.1.0/json-schema/schema.json#/definitions/bands and https://raw.githubusercontent.com/stac-extensions/eo/v1.1.0/json-schema/schema.json#/definitions/bands", "type": "object", "properties": { "proj:epsg": { @@ -334,10 +334,10 @@ } }, "eo:bands": { - "$ref": "https://raw.githubusercontent.com/stac-extensions/eo/main/json-schema/schema.json#/definitions/bands" + "$ref": "https://raw.githubusercontent.com/stac-extensions/eo/v1.1.0/json-schema/schema.json#/definitions/bands" }, "raster:bands": { - "$ref": "https://raw.githubusercontent.com/stac-extensions/eo/main/json-schema/schema.json#/definitions/bands" + "$ref": "https://raw.githubusercontent.com/stac-extensions/eo/v1.1.0/json-schema/schema.json#/definitions/bands" } }, "additionalProperties": false diff --git a/deps/libgdal/gdal/apps/gdal_rasterize_lib.cpp b/deps/libgdal/gdal/apps/gdal_rasterize_lib.cpp index 39913ad30..493922ee1 100644 --- a/deps/libgdal/gdal/apps/gdal_rasterize_lib.cpp +++ b/deps/libgdal/gdal/apps/gdal_rasterize_lib.cpp @@ -482,7 +482,7 @@ static GDALDatasetH CreateOutputDataset( OGREnvelope sEnvelop, GDALDriverH hDriver, const char *pszDest, int nXSize, int nYSize, double dfXRes, double dfYRes, bool bTargetAlignedPixels, int nBandCount, GDALDataType eOutputType, char **papszCreationOptions, - const std::vector &adfInitVals, int bNoDataSet, double dfNoData) + const std::vector &adfInitVals, const char *pszNoData) { bool bFirstLayer = true; char *pszWKT = nullptr; @@ -598,12 +598,16 @@ static GDALDatasetH CreateOutputDataset( } }*/ - if (bNoDataSet) + if (pszNoData) { for (int iBand = 0; iBand < nBandCount; iBand++) { GDALRasterBandH hBand = GDALGetRasterBand(hDstDS, iBand + 1); - GDALSetRasterNoDataValue(hBand, dfNoData); + if (GDALGetRasterDataType(hBand) == GDT_Int64) + GDALSetRasterNoDataValueAsInt64(hBand, + CPLAtoGIntBig(pszNoData)); + else + GDALSetRasterNoDataValue(hBand, CPLAtof(pszNoData)); } } @@ -649,8 +653,7 @@ struct GDALRasterizeOptions char **papszCreationOptions; GDALDataType eOutputType; std::vector adfInitVals; - int bNoDataSet; - double dfNoData; + char *pszNoData; OGREnvelope sEnvelop; int nXSize, nYSize; OGRSpatialReferenceH hSRS; @@ -790,6 +793,36 @@ GDALDatasetH GDALRasterize(const char *pszDest, GDALDatasetH hDstDS, } } + const auto GetOutputDataType = [&](OGRLayerH hLayer) + { + CPLAssert(bCreateOutput); + CPLAssert(hDriver); + GDALDataType eOutputType = psOptions->eOutputType; + if (eOutputType == GDT_Unknown && + psOptions->pszBurnAttribute != nullptr) + { + OGRFeatureDefnH hLayerDefn = OGR_L_GetLayerDefn(hLayer); + const int iBurnField = + OGR_FD_GetFieldIndex(hLayerDefn, psOptions->pszBurnAttribute); + if (iBurnField >= 0 && OGR_Fld_GetType(OGR_FD_GetFieldDefn( + hLayerDefn, iBurnField)) == OFTInteger64) + { + const char *pszMD = GDALGetMetadataItem( + hDriver, GDAL_DMD_CREATIONDATATYPES, nullptr); + if (pszMD && CPLStringList(CSLTokenizeString2(pszMD, " ", 0)) + .FindString("Int64") >= 0) + { + eOutputType = GDT_Int64; + } + } + } + if (eOutputType == GDT_Unknown) + { + eOutputType = GDT_Float64; + } + return eOutputType; + }; + /* -------------------------------------------------------------------- */ /* Process SQL request. */ /* -------------------------------------------------------------------- */ @@ -806,25 +839,7 @@ GDALDatasetH GDALRasterize(const char *pszDest, GDALDatasetH hDstDS, std::vector ahLayers; ahLayers.push_back(hLayer); - GDALDataType eOutputType = psOptions->eOutputType; - if (eOutputType == GDT_Unknown && - psOptions->pszBurnAttribute != nullptr) - { - OGRFeatureDefnH hLayerDefn = OGR_L_GetLayerDefn(hLayer); - int iBurnField = OGR_FD_GetFieldIndex( - hLayerDefn, psOptions->pszBurnAttribute); - if (iBurnField >= 0 && - OGR_Fld_GetType(OGR_FD_GetFieldDefn( - hLayerDefn, iBurnField)) == OFTInteger64) - { - eOutputType = GDT_Int64; - } - } - if (eOutputType == GDT_Unknown) - { - eOutputType = GDT_Float64; - } - + const GDALDataType eOutputType = GetOutputDataType(hLayer); hDstDS = CreateOutputDataset( ahLayers, psOptions->hSRS, psOptions->sEnvelop, hDriver, pszDest, psOptions->nXSize, psOptions->nYSize, @@ -832,7 +847,7 @@ GDALDatasetH GDALRasterize(const char *pszDest, GDALDatasetH hDstDS, psOptions->bTargetAlignedPixels, static_cast(psOptions->anBandList.size()), eOutputType, psOptions->papszCreationOptions, psOptions->adfInitVals, - psOptions->bNoDataSet, psOptions->dfNoData); + psOptions->pszNoData); if (hDstDS == nullptr) { GDALDatasetReleaseResultSet(hSrcDataset, hLayer); @@ -882,18 +897,10 @@ GDALDatasetH GDALRasterize(const char *pszDest, GDALDatasetH hDstDS, GDALRasterizeOptionsFree(psOptionsToFree); return nullptr; } - if (eOutputType == GDT_Unknown && - psOptions->pszBurnAttribute != nullptr) + if (eOutputType == GDT_Unknown) { - OGRFeatureDefnH hLayerDefn = OGR_L_GetLayerDefn(hLayer); - int iBurnField = OGR_FD_GetFieldIndex( - hLayerDefn, psOptions->pszBurnAttribute); - if (iBurnField >= 0 && - OGR_Fld_GetType(OGR_FD_GetFieldDefn( - hLayerDefn, iBurnField)) == OFTInteger64) - { + if (GetOutputDataType(hLayer) == GDT_Int64) eOutputType = GDT_Int64; - } } ahLayers.push_back(hLayer); @@ -910,7 +917,7 @@ GDALDatasetH GDALRasterize(const char *pszDest, GDALDatasetH hDstDS, psOptions->dfYRes, psOptions->bTargetAlignedPixels, static_cast(psOptions->anBandList.size()), eOutputType, psOptions->papszCreationOptions, psOptions->adfInitVals, - psOptions->bNoDataSet, psOptions->dfNoData); + psOptions->pszNoData); if (hDstDS == nullptr) { GDALRasterizeOptionsFree(psOptionsToFree); @@ -1020,8 +1027,7 @@ GDALRasterizeOptionsNew(char **papszArgv, psOptions->dfXRes = 0; psOptions->dfYRes = 0; psOptions->eOutputType = GDT_Unknown; - psOptions->bNoDataSet = FALSE; - psOptions->dfNoData = 0; + psOptions->pszNoData = nullptr; psOptions->nXSize = 0; psOptions->nYSize = 0; psOptions->hSRS = nullptr; @@ -1195,8 +1201,8 @@ GDALRasterizeOptionsNew(char **papszArgv, } else if (i < argc - 1 && EQUAL(papszArgv[i], "-a_nodata")) { - psOptions->dfNoData = CPLAtof(papszArgv[i + 1]); - psOptions->bNoDataSet = TRUE; + CPLFree(psOptions->pszNoData); + psOptions->pszNoData = CPLStrdup(papszArgv[i + 1]); i += 1; psOptions->bCreateOutput = true; } @@ -1472,6 +1478,7 @@ void GDALRasterizeOptionsFree(GDALRasterizeOptions *psOptions) CPLFree(psOptions->pszDialect); CPLFree(psOptions->pszBurnAttribute); CPLFree(psOptions->pszWHERE); + CPLFree(psOptions->pszNoData); OSRDestroySpatialReference(psOptions->hSRS); delete psOptions; diff --git a/deps/libgdal/gdal/apps/gdal_translate_lib.cpp b/deps/libgdal/gdal/apps/gdal_translate_lib.cpp index c8a5f2612..79f1e4895 100644 --- a/deps/libgdal/gdal/apps/gdal_translate_lib.cpp +++ b/deps/libgdal/gdal/apps/gdal_translate_lib.cpp @@ -2385,12 +2385,7 @@ GDALDatasetH GDALTranslate(const char *pszDest, GDALDatasetH hSrcDataset, { const double dfNoData = CPLAtof(psOptions->osNoData.c_str()); - if (dfNoData >= static_cast( - std::numeric_limits::min()) && - dfNoData <= static_cast( - std::numeric_limits::max()) && - dfNoData == - static_cast(static_cast(dfNoData))) + if (GDALIsValueExactAs(dfNoData)) { poVRTBand->SetNoDataValueAsInt64( static_cast(dfNoData)); @@ -2428,12 +2423,7 @@ GDALDatasetH GDALTranslate(const char *pszDest, GDALDatasetH hSrcDataset, { const double dfNoData = CPLAtof(psOptions->osNoData.c_str()); - if (dfNoData >= static_cast( - std::numeric_limits::min()) && - dfNoData <= static_cast( - std::numeric_limits::max()) && - dfNoData == static_cast( - static_cast(dfNoData))) + if (GDALIsValueExactAs(dfNoData)) { poVRTBand->SetNoDataValueAsUInt64( static_cast(dfNoData)); @@ -2554,7 +2544,10 @@ GDALDatasetH GDALTranslate(const char *pszDest, GDALDatasetH hSrcDataset, /* Write to the output file using CopyCreate(). */ /* -------------------------------------------------------------------- */ if (EQUAL(psOptions->osFormat.c_str(), "VRT") && - psOptions->aosCreateOptions.empty()) + (psOptions->aosCreateOptions.empty() || + (psOptions->aosCreateOptions.size() == 2 && + psOptions->aosCreateOptions.FetchNameValue("BLOCKXSIZE") && + psOptions->aosCreateOptions.FetchNameValue("BLOCKYSIZE")))) { poVDS->SetDescription(pszDest); hOutDS = GDALDataset::ToHandle(poVDS); @@ -3039,19 +3032,6 @@ GDALTranslateOptionsGetParser(GDALTranslateOptions *psOptions, argParser->add_argument("-a_nodata") .metavar("|none") - .action( - [psOptions](const std::string &s) - { - if (EQUAL(s.c_str(), "none")) - { - psOptions->bUnsetNoData = true; - } - else - { - psOptions->bSetNoData = true; - psOptions->osNoData = s; - } - }) .help(_("Assign a specified nodata value to output bands.")); argParser->add_argument("-a_gt") @@ -3390,6 +3370,23 @@ GDALTranslateOptionsNew(char **papszArgv, psOptions->anColorInterp[nIndex] = GetColorInterp(papszArgv[i]); } + // argparser will be confused if the value of a string argument + // starts with a negative sign. + else if (EQUAL(papszArgv[i], "-a_nodata") && papszArgv[i + 1]) + { + ++i; + const std::string s = papszArgv[i]; + if (EQUAL(s.c_str(), "none")) + { + psOptions->bUnsetNoData = true; + } + else + { + psOptions->bSetNoData = true; + psOptions->osNoData = s; + } + } + else { aosArgv.AddString(papszArgv[i]); diff --git a/deps/libgdal/gdal/apps/gdalbuildvrt_lib.cpp b/deps/libgdal/gdal/apps/gdalbuildvrt_lib.cpp index ae642786f..31e720fcc 100644 --- a/deps/libgdal/gdal/apps/gdalbuildvrt_lib.cpp +++ b/deps/libgdal/gdal/apps/gdalbuildvrt_lib.cpp @@ -2268,6 +2268,21 @@ GDALBuildVRTOptionsNew(char **papszArgv, psOptionsForBinary->osDstFilename = papszArgv[i + 1]; ++i; } + // argparser will be confused if the value of a string argument + // starts with a negative sign. + else if (EQUAL(papszArgv[i], "-srcnodata") && i + 1 < nArgc) + { + ++i; + psOptions->osSrcNoData = papszArgv[i]; + } + // argparser will be confused if the value of a string argument + // starts with a negative sign. + else if (EQUAL(papszArgv[i], "-vrtnodata") && i + 1 < nArgc) + { + ++i; + psOptions->osVRTNoData = papszArgv[i]; + } + else { aosArgv.AddString(papszArgv[i]); diff --git a/deps/libgdal/gdal/apps/gdalinfo_lib.cpp b/deps/libgdal/gdal/apps/gdalinfo_lib.cpp index 8aa00d02b..e357e76e2 100644 --- a/deps/libgdal/gdal/apps/gdalinfo_lib.cpp +++ b/deps/libgdal/gdal/apps/gdalinfo_lib.cpp @@ -639,10 +639,12 @@ char *GDALInfo(GDALDatasetH hDataset, const GDALInfoOptions *psOptions) { std::string osCoordinateEpoch = CPLSPrintf("%f", dfCoordinateEpoch); - if (osCoordinateEpoch.find('.') != std::string::npos) + const size_t nDotPos = osCoordinateEpoch.find('.'); + if (nDotPos != std::string::npos) { - while (osCoordinateEpoch.back() == '0') - osCoordinateEpoch.resize(osCoordinateEpoch.size() - 1); + while (osCoordinateEpoch.size() > nDotPos + 2 && + osCoordinateEpoch.back() == '0') + osCoordinateEpoch.pop_back(); } Concat(osStr, psOptions->bStdoutOutput, "Coordinate epoch: %s\n", osCoordinateEpoch.c_str()); diff --git a/deps/libgdal/gdal/apps/gdallocationinfo.cpp b/deps/libgdal/gdal/apps/gdallocationinfo.cpp index 1ec5ae30b..ff2bf26cc 100644 --- a/deps/libgdal/gdal/apps/gdallocationinfo.cpp +++ b/deps/libgdal/gdal/apps/gdallocationinfo.cpp @@ -342,6 +342,8 @@ MAIN_START(argc, argv) while (inputAvailable) { int iPixel, iLine; + const double dfXIn = dfGeoX; + const double dfYIn = dfGeoY; if (hCT) { @@ -411,7 +413,7 @@ MAIN_START(argc, argv) } else if (bEcho) { - printf("%d%s%d%s", iPixel, osFieldSep.c_str(), iLine, + printf("%.15g%s%.15g%s", dfXIn, osFieldSep.c_str(), dfYIn, osFieldSep.c_str()); } @@ -424,7 +426,12 @@ MAIN_START(argc, argv) osXML += "Location is off this file! No further details " "to report."; else if (bValOnly) - printf("\n"); + { + for (int i = 1; i < static_cast(anBandList.size()); i++) + { + printf("%s", osFieldSep.c_str()); + } + } else if (!bQuiet) printf("\nLocation is off this file! No further details to " "report.\n"); diff --git a/deps/libgdal/gdal/apps/gdalwarp_lib.cpp b/deps/libgdal/gdal/apps/gdalwarp_lib.cpp index c2e82d772..b79dbf15b 100644 --- a/deps/libgdal/gdal/apps/gdalwarp_lib.cpp +++ b/deps/libgdal/gdal/apps/gdalwarp_lib.cpp @@ -3680,6 +3680,18 @@ static GDALDatasetH GDALWarpCreateOutput( return nullptr; } + // Examine desired overview level and retrieve the corresponding dataset + // if it exists. + std::unique_ptr oDstDSOverview; + if (psOptions->nOvLevel >= 0) + { + oDstDSOverview.reset(GDALCreateOverviewDataset( + GDALDataset::FromHandle(hSrcDS), psOptions->nOvLevel, + /* bThisLevelOnly = */ true)); + if (oDstDSOverview) + hSrcDS = oDstDSOverview.get(); + } + /* -------------------------------------------------------------------- */ /* Check if the source dataset shares some files with the dest @@ -4110,6 +4122,7 @@ static GDALDatasetH GDALWarpCreateOutput( { nOptions |= GDAL_SWO_FORCE_SQUARE_PIXEL; } + if (GDALSuggestedWarpOutput2(hSrcDS, psInfo->pfnTransform, hTransformArg, adfThisGeoTransform, &nThisPixels, &nThisLines, adfExtent, @@ -5731,15 +5744,15 @@ GDALWarpAppOptionsGetParser(GDALWarpAppOptions *psOptions, else psOptions->dfWarpMemoryLimit = CPLAtofM(s.c_str()); }) - .help(_("Error threshold.")); + .help(_("Set max warp memory.")); argParser->add_argument("-srcnodata") - .metavar("[ ...]") + .metavar("\"[ ]...\"") .store_into(psOptions->osSrcNodata) .help(_("Nodata masking values for input bands.")); argParser->add_argument("-dstnodata") - .metavar("[ ...]") + .metavar("\"[ ]...\"") .store_into(psOptions->osDstNodata) .help(_("Nodata masking values for output bands.")); @@ -6113,6 +6126,20 @@ GDALWarpAppOptionsNew(char **papszArgv, } psOptions->bCreateOutput = true; } + // argparser will be confused if the value of a string argument + // starts with a negative sign. + else if (EQUAL(papszArgv[i], "-srcnodata") && i + 1 < nArgc) + { + ++i; + psOptions->osSrcNodata = papszArgv[i]; + } + // argparser will be confused if the value of a string argument + // starts with a negative sign. + else if (EQUAL(papszArgv[i], "-dstnodata") && i + 1 < nArgc) + { + ++i; + psOptions->osDstNodata = papszArgv[i]; + } else { aosArgv.AddString(papszArgv[i]); diff --git a/deps/libgdal/gdal/apps/ogr2ogr_lib.cpp b/deps/libgdal/gdal/apps/ogr2ogr_lib.cpp index 3650db61a..7839b5934 100644 --- a/deps/libgdal/gdal/apps/ogr2ogr_lib.cpp +++ b/deps/libgdal/gdal/apps/ogr2ogr_lib.cpp @@ -2641,6 +2641,10 @@ GDALDatasetH GDALVectorTranslate(const char *pszDest, GDALDatasetH hDstDS, } } + // Automatically close poODS on error, if it has been created by this + // method. + GDALDatasetUniquePtr poODSUniquePtr(hDstDS == nullptr ? poODS : nullptr); + // Some syntaxic sugar to make "ogr2ogr [-f PostgreSQL] PG:dbname=.... // source [srclayer] -lco OVERWRITE=YES" work like "ogr2ogr -overwrite // PG:dbname=.... source [srclayer]" The former syntax used to work at @@ -2658,8 +2662,6 @@ GDALDatasetH GDALVectorTranslate(const char *pszDest, GDALDatasetH hDstDS, { CPLError(CE_Failure, CPLE_AppDefined, "-append and -lco OVERWRITE=YES are mutually exclusive"); - if (hDstDS == nullptr) - GDALClose(poODS); return nullptr; } bOverwrite = true; @@ -2707,8 +2709,6 @@ GDALDatasetH GDALVectorTranslate(const char *pszDest, GDALDatasetH hDstDS, CPLError(CE_Failure, CPLE_AppDefined, "Failed to process SRS definition: %s", psOptions->osOutputSRSDef.c_str()); - if (hDstDS == nullptr) - GDALClose(poODS); return nullptr; } oOutputSRSHolder.get()->SetCoordinateEpoch( @@ -2729,8 +2729,6 @@ GDALDatasetH GDALVectorTranslate(const char *pszDest, GDALDatasetH hDstDS, CPLError(CE_Failure, CPLE_AppDefined, "Failed to process SRS definition: %s", psOptions->osSourceSRSDef.c_str()); - if (hDstDS == nullptr) - GDALClose(poODS); return nullptr; } oSourceSRS.SetCoordinateEpoch(psOptions->dfSourceCoordinateEpoch); @@ -2741,17 +2739,16 @@ GDALDatasetH GDALVectorTranslate(const char *pszDest, GDALDatasetH hDstDS, /* Create a transformation object from the source to */ /* destination coordinate system. */ /* -------------------------------------------------------------------- */ - GCPCoordTransformation *poGCPCoordTrans = nullptr; + std::unique_ptr poGCPCoordTrans; if (psOptions->oGCPs.nGCPCount > 0) { - poGCPCoordTrans = new GCPCoordTransformation( + poGCPCoordTrans = std::make_unique( psOptions->oGCPs.nGCPCount, psOptions->oGCPs.pasGCPs, psOptions->nTransformOrder, poSourceSRS ? poSourceSRS : oOutputSRSHolder.get()); if (!(poGCPCoordTrans->IsValid())) { - delete poGCPCoordTrans; - poGCPCoordTrans = nullptr; + return nullptr; } } @@ -2805,7 +2802,7 @@ GDALDatasetH GDALVectorTranslate(const char *pszDest, GDALDatasetH hDstDS, oTranslator.m_poOutputSRS = oOutputSRSHolder.get(); oTranslator.m_bNullifyOutputSRS = psOptions->bNullifyOutputSRS; oTranslator.m_poUserSourceSRS = poSourceSRS; - oTranslator.m_poGCPCoordTrans = poGCPCoordTrans; + oTranslator.m_poGCPCoordTrans = poGCPCoordTrans.get(); oTranslator.m_eGType = psOptions->eGType; oTranslator.m_eGeomTypeConversion = psOptions->eGeomTypeConversion; oTranslator.m_bMakeValid = psOptions->bMakeValid; @@ -2977,9 +2974,6 @@ GDALDatasetH GDALVectorTranslate(const char *pszDest, GDALDatasetH hDstDS, { CPLError(CE_Failure, CPLE_AppDefined, "-splitlistfields not supported in this mode"); - if (hDstDS == nullptr) - GDALClose(poODS); - delete poGCPCoordTrans; return nullptr; } @@ -2992,9 +2986,6 @@ GDALDatasetH GDALVectorTranslate(const char *pszDest, GDALDatasetH hDstDS, { CPLError(CE_Failure, CPLE_AppDefined, "Couldn't fetch requested layer %s!", pszLayer); - if (hDstDS == nullptr) - GDALClose(poODS); - delete poGCPCoordTrans; return nullptr; } } @@ -3044,9 +3035,6 @@ GDALDatasetH GDALVectorTranslate(const char *pszDest, GDALDatasetH hDstDS, { CPLError(CE_Failure, CPLE_AppDefined, "Couldn't fetch advertised layer %d!", iLayer); - if (hDstDS == nullptr) - GDALClose(poODS); - delete poGCPCoordTrans; return nullptr; } @@ -3085,9 +3073,6 @@ GDALDatasetH GDALVectorTranslate(const char *pszDest, GDALDatasetH hDstDS, { CPLError(CE_Failure, CPLE_AppDefined, "Couldn't fetch advertised layer %d!", iLayer); - if (hDstDS == nullptr) - GDALClose(poODS); - delete poGCPCoordTrans; return nullptr; } @@ -3106,9 +3091,6 @@ GDALDatasetH GDALVectorTranslate(const char *pszDest, GDALDatasetH hDstDS, poLayer->GetName()); if (!psOptions->bSkipFailures) { - if (hDstDS == nullptr) - GDALClose(poODS); - delete poGCPCoordTrans; return nullptr; } } @@ -3133,8 +3115,8 @@ GDALDatasetH GDALVectorTranslate(const char *pszDest, GDALDatasetH hDstDS, while (true) { OGRLayer *poFeatureLayer = nullptr; - OGRFeature *poFeature = poDS->GetNextFeature( - &poFeatureLayer, nullptr, pfnProgress, pProgressArg); + auto poFeature = std::unique_ptr(poDS->GetNextFeature( + &poFeatureLayer, nullptr, pfnProgress, pProgressArg)); if (poFeature == nullptr) break; std::map::const_iterator oIter = @@ -3142,7 +3124,7 @@ GDALDatasetH GDALVectorTranslate(const char *pszDest, GDALDatasetH hDstDS, if (oIter == oMapLayerToIdx.end()) { // Feature in a layer that is not a layer of interest. - OGRFeature::DestroyFeature(poFeature); + // nothing to do } else { @@ -3170,10 +3152,6 @@ GDALDatasetH GDALVectorTranslate(const char *pszDest, GDALDatasetH hDstDS, if (psInfo == nullptr && !psOptions->bSkipFailures) { - if (hDstDS == nullptr) - GDALClose(poODS); - delete poGCPCoordTrans; - OGRFeature::DestroyFeature(poFeature); return nullptr; } @@ -3186,9 +3164,9 @@ GDALDatasetH GDALVectorTranslate(const char *pszDest, GDALDatasetH hDstDS, int iLayer = oIter->second; TargetLayerInfo *psInfo = pasAssocLayers[iLayer].psInfo.get(); if ((psInfo == nullptr || - !oTranslator.Translate(poFeature, psInfo, 0, nullptr, - nTotalEventsDone, nullptr, nullptr, - psOptions.get())) && + !oTranslator.Translate(poFeature.release(), psInfo, 0, + nullptr, nTotalEventsDone, nullptr, + nullptr, psOptions.get())) && !psOptions->bSkipFailures) { CPLError( @@ -3201,8 +3179,6 @@ GDALDatasetH GDALVectorTranslate(const char *pszDest, GDALDatasetH hDstDS, nRetCode = 1; break; } - if (psInfo == nullptr) - OGRFeature::DestroyFeature(poFeature); } } // while true @@ -3230,9 +3206,6 @@ GDALDatasetH GDALVectorTranslate(const char *pszDest, GDALDatasetH hDstDS, if (psInfo == nullptr && !psOptions->bSkipFailures) { - if (hDstDS == nullptr) - GDALClose(poODS); - delete poGCPCoordTrans; return nullptr; } @@ -3262,9 +3235,6 @@ GDALDatasetH GDALVectorTranslate(const char *pszDest, GDALDatasetH hDstDS, { CPLError(CE_Failure, CPLE_AppDefined, "Couldn't fetch advertised layer %d!", iLayer); - if (hDstDS == nullptr) - GDALClose(poODS); - delete poGCPCoordTrans; return nullptr; } if (!poDS->IsLayerPrivate(iLayer)) @@ -3294,9 +3264,6 @@ GDALDatasetH GDALVectorTranslate(const char *pszDest, GDALDatasetH hDstDS, psOptions->aosLayers[iLayer]); if (!psOptions->bSkipFailures) { - if (hDstDS == nullptr) - GDALClose(poODS); - delete poGCPCoordTrans; return nullptr; } } @@ -3346,9 +3313,6 @@ GDALDatasetH GDALVectorTranslate(const char *pszDest, GDALDatasetH hDstDS, psOptions->osWHERE.c_str(), poLayer->GetName()); if (!psOptions->bSkipFailures) { - if (hDstDS == nullptr) - GDALClose(poODS); - delete poGCPCoordTrans; return nullptr; } } @@ -3502,8 +3466,6 @@ GDALDatasetH GDALVectorTranslate(const char *pszDest, GDALDatasetH hDstDS, } } - delete poGCPCoordTrans; - // Note: this guarantees that the file can be opened in a consistent state, // without requiring to close poODS, only if the driver declares // DCAP_FLUSHCACHE_CONSISTENT_STATE @@ -3511,10 +3473,13 @@ GDALDatasetH GDALVectorTranslate(const char *pszDest, GDALDatasetH hDstDS, nRetCode = 1; if (nRetCode == 0) - return GDALDataset::ToHandle(poODS); + { + if (hDstDS) + return hDstDS; + else + return GDALDataset::ToHandle(poODSUniquePtr.release()); + } - if (hDstDS == nullptr) - GDALClose(poODS); return nullptr; } @@ -4550,8 +4515,10 @@ SetupTargetLayer::Setup(OGRLayer *poSrcLayer, const char *pszNewLayerName, oGeomFieldDefn.SetSpatialRef(poOutputSRS); oGeomFieldDefn.SetCoordinatePrecision(oCoordPrec); oGeomFieldDefn.SetNullable(bGeomFieldNullable); - poDstLayer = m_poDstDS->CreateLayer(pszNewLayerName, &oGeomFieldDefn, - papszLCOTemp); + poDstLayer = m_poDstDS->CreateLayer( + pszNewLayerName, + eGCreateLayerType == wkbNone ? nullptr : &oGeomFieldDefn, + papszLCOTemp); CSLDestroy(papszLCOTemp); if (poDstLayer == nullptr) diff --git a/deps/libgdal/gdal/apps/ogrinfo_lib.cpp b/deps/libgdal/gdal/apps/ogrinfo_lib.cpp index e287a7cb7..42538bc65 100644 --- a/deps/libgdal/gdal/apps/ogrinfo_lib.cpp +++ b/deps/libgdal/gdal/apps/ogrinfo_lib.cpp @@ -1191,10 +1191,12 @@ static void ReportOnLayer(CPLString &osRet, CPLJSONObject &oLayer, { std::string osCoordinateEpoch = CPLSPrintf("%f", dfCoordinateEpoch); - if (osCoordinateEpoch.find('.') != std::string::npos) + const size_t nDotPos = osCoordinateEpoch.find('.'); + if (nDotPos != std::string::npos) { - while (osCoordinateEpoch.back() == '0') - osCoordinateEpoch.resize(osCoordinateEpoch.size() - 1); + while (osCoordinateEpoch.size() > nDotPos + 2 && + osCoordinateEpoch.back() == '0') + osCoordinateEpoch.pop_back(); } Concat(osRet, psOptions->bStdoutOutput, "Coordinate epoch: %s\n", osCoordinateEpoch.c_str()); @@ -2427,15 +2429,16 @@ static std::unique_ptr GDALVectorInfoOptionsGetParser( }) .help(_("Format/driver name(s) to try when opening the input file.")); - argParser->add_argument("filename") - .nargs(argparse::nargs_pattern::optional) - .action( - [psOptionsForBinary](const std::string &s) - { - if (psOptionsForBinary) - psOptionsForBinary->osFilename = s; - }) - .help(_("The data source to open.")); + auto &argFilename = argParser->add_argument("filename") + .action( + [psOptionsForBinary](const std::string &s) + { + if (psOptionsForBinary) + psOptionsForBinary->osFilename = s; + }) + .help(_("The data source to open.")); + if (!psOptionsForBinary) + argFilename.nargs(argparse::nargs_pattern::optional); argParser->add_argument("layer") .remaining() diff --git a/deps/libgdal/gdal/apps/sozip.cpp b/deps/libgdal/gdal/apps/sozip.cpp index f5d6f10a1..1381e158b 100644 --- a/deps/libgdal/gdal/apps/sozip.cpp +++ b/deps/libgdal/gdal/apps/sozip.cpp @@ -623,7 +623,14 @@ MAIN_START(nArgc, papszArgv) if (!bVerbose && !bQuiet) { +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wnull-dereference" +#endif anFileSizes.resize(aosFiles.size()); +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#endif for (size_t i = 0; i < aosFiles.size(); ++i) { if (VSIStatL(aosFiles[i].c_str(), &sBuf) == 0) diff --git a/deps/libgdal/gdal/apps/test_ogrsf.cpp b/deps/libgdal/gdal/apps/test_ogrsf.cpp index 9b2edcaf3..3f4592b4f 100644 --- a/deps/libgdal/gdal/apps/test_ogrsf.cpp +++ b/deps/libgdal/gdal/apps/test_ogrsf.cpp @@ -2001,7 +2001,7 @@ static int TestOGRLayerRandomWrite(OGRLayer *poLayer) { int bRet = TRUE; - OGRFeature *papoFeatures[5], *poFeature; + OGRFeature *papoFeatures[5]; memset(papoFeatures, 0, sizeof(papoFeatures)); @@ -2086,25 +2086,27 @@ static int TestOGRLayerRandomWrite(OGRLayer *poLayer) /* -------------------------------------------------------------------- */ /* Now re-read feature 2 to verify the effect stuck. */ /* -------------------------------------------------------------------- */ - poFeature = LOG_ACTION(poLayer->GetFeature(nFID5)); - if (poFeature == nullptr) - { - bRet = FALSE; - printf("ERROR: Attempt to GetFeature( nFID5 ) failed.\n"); - goto end; - } - if (!poFeature->Equal(papoFeatures[1])) - { - bRet = FALSE; - poFeature->DumpReadable(stderr); - papoFeatures[1]->DumpReadable(stderr); - printf("ERROR: Written feature didn't seem to retain value.\n"); - } - else if (bVerbose) { - printf("INFO: Random write test passed.\n"); + auto poFeature = + std::unique_ptr(LOG_ACTION(poLayer->GetFeature(nFID5))); + if (poFeature == nullptr) + { + bRet = FALSE; + printf("ERROR: Attempt to GetFeature( nFID5 ) failed.\n"); + goto end; + } + if (!poFeature->Equal(papoFeatures[1])) + { + bRet = FALSE; + poFeature->DumpReadable(stderr); + papoFeatures[1]->DumpReadable(stderr); + printf("ERROR: Written feature didn't seem to retain value.\n"); + } + else if (bVerbose) + { + printf("INFO: Random write test passed.\n"); + } } - DestroyFeatureAndNullify(poFeature); /* -------------------------------------------------------------------- */ /* Re-invert the features to restore to original state */ @@ -2130,6 +2132,156 @@ static int TestOGRLayerRandomWrite(OGRLayer *poLayer) printf("ERROR: Attempt to restore SetFeature(4) failed.\n"); } + /* -------------------------------------------------------------------- */ + /* Test UpdateFeature() */ + /* -------------------------------------------------------------------- */ + + if (bRet) + { + int nOldVal = 0; + std::string osOldVal; + int iUpdatedFeature = -1; + int iUpdatedField = -1; + std::unique_ptr poUpdatedFeature; + + for (int iFeature = 0; iUpdatedFeature < 0 && iFeature < 5; iFeature++) + { + for (int iField = 0; + iField < poLayer->GetLayerDefn()->GetFieldCount(); ++iField) + { + if (papoFeatures[iFeature]->IsFieldSetAndNotNull(iField)) + { + if (poLayer->GetLayerDefn() + ->GetFieldDefn(iField) + ->GetType() == OFTInteger) + { + iUpdatedFeature = iFeature; + iUpdatedField = iField; + nOldVal = + papoFeatures[iFeature]->GetFieldAsInteger(iField); + poUpdatedFeature.reset(papoFeatures[iFeature]->Clone()); + poUpdatedFeature->SetField(iField, 0xBEEF); + break; + } + else if (poLayer->GetLayerDefn() + ->GetFieldDefn(iField) + ->GetType() == OFTString) + { + iUpdatedFeature = iFeature; + iUpdatedField = iField; + osOldVal = + papoFeatures[iFeature]->GetFieldAsString(iField); + poUpdatedFeature.reset(papoFeatures[iFeature]->Clone()); + poUpdatedFeature->SetField(iField, "0xBEEF"); + break; + } + } + } + } + + if (poUpdatedFeature) + { + if (LOG_ACTION(poLayer->UpdateFeature(poUpdatedFeature.get(), 1, + &iUpdatedField, 0, nullptr, + false)) != OGRERR_NONE) + { + bRet = FALSE; + printf("ERROR: UpdateFeature() failed.\n"); + } + if (bRet) + { + LOG_ACTION(poLayer->ResetReading()); + for (int iFeature = 0; iFeature < 5; iFeature++) + { + auto poFeature = std::unique_ptr(LOG_ACTION( + poLayer->GetFeature(papoFeatures[iFeature]->GetFID()))); + if (iFeature != iUpdatedFeature) + { + if (!poFeature || + !poFeature->Equal(papoFeatures[iFeature])) + { + bRet = false; + printf("ERROR: UpdateFeature() test: " + "!poFeature->Equals(papoFeatures[iFeature]) " + "unexpected.\n"); + if (poFeature) + poFeature->DumpReadable(stdout); + papoFeatures[iFeature]->DumpReadable(stdout); + } + } + } + + auto poFeature = + std::unique_ptr(LOG_ACTION(poLayer->GetFeature( + papoFeatures[iUpdatedFeature]->GetFID()))); + if (!poFeature) + { + bRet = FALSE; + printf("ERROR: at line %d", __LINE__); + goto end; + } + if (poLayer->GetLayerDefn() + ->GetFieldDefn(iUpdatedField) + ->GetType() == OFTInteger) + { + if (poFeature->GetFieldAsInteger(iUpdatedField) != 0xBEEF) + { + bRet = FALSE; + printf("ERROR: Did not get expected field value after " + "UpdateFeature().\n"); + } + poFeature->SetField(iUpdatedField, nOldVal); + } + else if (poLayer->GetLayerDefn() + ->GetFieldDefn(iUpdatedField) + ->GetType() == OFTString) + { + if (!EQUAL(poFeature->GetFieldAsString(iUpdatedField), + "0xBEEF")) + { + bRet = FALSE; + printf("ERROR: Did not get expected field value after " + "UpdateFeature().\n"); + } + poFeature->SetField(iUpdatedField, osOldVal.c_str()); + } + else + { + CPLAssert(false); + } + + if (LOG_ACTION(poLayer->UpdateFeature( + poFeature.get(), 1, &iUpdatedField, 0, nullptr, + false)) != OGRERR_NONE) + { + bRet = FALSE; + printf("ERROR: UpdateFeature() failed.\n"); + } + + poFeature.reset(LOG_ACTION(poLayer->GetFeature( + papoFeatures[iUpdatedFeature]->GetFID()))); + if (!poFeature) + { + bRet = FALSE; + printf("ERROR: at line %d", __LINE__); + goto end; + } + if (!poFeature->Equal(papoFeatures[iUpdatedFeature])) + { + bRet = false; + printf("ERROR: UpdateFeature() test: " + "!poFeature->Equals(papoFeatures[iUpdatedFeature]) " + "unexpected.\n"); + } + } + } + else + { + if (bVerbose) + printf("INFO: Could not test UpdateFeature().\n"); + } + } + end: /* -------------------------------------------------------------------- */ /* Cleanup. */ diff --git a/deps/libgdal/gdal/cmake/helpers/GdalDriverHelper.cmake b/deps/libgdal/gdal/cmake/helpers/GdalDriverHelper.cmake index 49ff81093..b352ae1ca 100644 --- a/deps/libgdal/gdal/cmake/helpers/GdalDriverHelper.cmake +++ b/deps/libgdal/gdal/cmake/helpers/GdalDriverHelper.cmake @@ -12,6 +12,8 @@ GdalDriverHelper Symptoms add_gdal_driver( TARGET [SOURCES [[...]]] + [CORE_SOURCES [[...]]] + NO_SHARED_SYMBOL_WITH_CORE BUILTIN | PLUGIN_CAPABLE | [PLUGIN_CAPABLE_IF ] [NO_DEPS] ) @@ -31,6 +33,34 @@ GdalDriverHelper The NO_DEPS option express that the driver has no non-core external dependencies. + The CORE_SOURCES option points to a list of files that are used for deferred plugin + loading (cf RFC 96 https://gdal.org/development/rfc/rfc96_deferred_plugin_loading.html), + when the driver is built as a plugin. + Those files are build in libgdal so it has access to plugin metadata and the + identification method, and are typically exported so that the driver can also + access them. + However it has been found that this resulted in the inability of building a + plugin for a libgdal that hadn't been built with any form of support for it, + which is undesirable. + Starting with GDAL 3.9.1, NO_SHARED_SYMBOL_WITH_CORE must also be declared + when CORE_SOURCES is declared, so that the files pointed by CORE_SOURCES + are built twice: once in libgdal with a "GDAL_core_" prefix, and another time + in the plugin itself with a "GDAL_driver_" prefix, by using the + PLUGIN_SYMBOL_NAME() macro of gdal_priv.h + + Example in ogrocidrivercore.h: + + #define OGROCIDriverIdentify \ + PLUGIN_SYMBOL_NAME(OGROCIDriverIdentify) + #define OGROCIDriverSetCommonMetadata \ + PLUGIN_SYMBOL_NAME(OGROCIDriverSetCommonMetadata) + + int OGROCIDriverIdentify(GDALOpenInfo *poOpenInfo); + + void OGROCIDriverSetCommonMetadata(GDALDriver *poDriver); + + + There are several examples to show how to write build cmake script. ex.1 Driver which is referenced by other drivers @@ -91,7 +121,7 @@ function(_set_driver_core_sources _KEY _DRIVER_TARGET) endfunction() function(add_gdal_driver) - set(_options BUILTIN PLUGIN_CAPABLE NO_DEPS STRONG_CXX_WFLAGS CXX_WFLAGS_EFFCXX NO_CXX_WFLAGS) + set(_options BUILTIN PLUGIN_CAPABLE NO_DEPS STRONG_CXX_WFLAGS CXX_WFLAGS_EFFCXX NO_CXX_WFLAGS NO_SHARED_SYMBOL_WITH_CORE) set(_oneValueArgs TARGET DESCRIPTION DEF PLUGIN_CAPABLE_IF DRIVER_NAME_OPTION) set(_multiValueArgs SOURCES CORE_SOURCES) cmake_parse_arguments(_DRIVER "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) @@ -254,6 +284,15 @@ function(add_gdal_driver) set_property(GLOBAL APPEND PROPERTY PLUGIN_MODULES ${_DRIVER_TARGET}) if (_DRIVER_CORE_SOURCES) + if (_DRIVER_NO_SHARED_SYMBOL_WITH_CORE) + foreach(f IN LISTS _DRIVER_CORE_SOURCES) + # Create a separate source file, to make sure we get a different object file + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/for_driver_${f}" "#include \"${CMAKE_CURRENT_SOURCE_DIR}/${f}\"") + target_sources(${_DRIVER_TARGET} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/for_driver_${f}") + endforeach() + else() + message(FATAL_ERROR "Driver ${_DRIVER_TARGET} should declare DRIVER_NO_SHARED_SYMBOL_WITH_CORE") + endif() _set_driver_core_sources(${_KEY} ${_DRIVER_TARGET} ${_DRIVER_CORE_SOURCES}) endif () diff --git a/deps/libgdal/gdal/cmake/helpers/configure.cmake b/deps/libgdal/gdal/cmake/helpers/configure.cmake index 6aee8f7d6..55b1df0f6 100644 --- a/deps/libgdal/gdal/cmake/helpers/configure.cmake +++ b/deps/libgdal/gdal/cmake/helpers/configure.cmake @@ -226,13 +226,13 @@ else () #endif #include #include - int main() { struct _stat64 buf; _wstat64( \"\", &buf ); return 0; } + int main() { struct _stat64 buf; wchar_t path = 0; _wstat64( &path, &buf ); return 0; } " - NO_UNIX_STDIO_64) + WINDOWS_STAT64) - if (NO_UNIX_STDIO_64) + if (WINDOWS_STAT64) set(VSI_STAT64 _stat64) - set(VSI_STAT64_T __stat64) + set(VSI_STAT64_T _stat64) endif () check_function_exists(fopen64 HAVE_FOPEN64) diff --git a/deps/libgdal/gdal/frmts/aaigrid/aaigriddataset.cpp b/deps/libgdal/gdal/frmts/aaigrid/aaigriddataset.cpp index 098a8a47f..4fc099611 100644 --- a/deps/libgdal/gdal/frmts/aaigrid/aaigriddataset.cpp +++ b/deps/libgdal/gdal/frmts/aaigrid/aaigriddataset.cpp @@ -606,6 +606,7 @@ int AAIGDataset::ParseHeader(const char *pszHeader, const char *pszDataType) if (pszDataType == nullptr && (strchr(pszNoData, '.') != nullptr || strchr(pszNoData, ',') != nullptr || + std::isnan(dfNoDataValue) || std::numeric_limits::min() > dfNoDataValue || dfNoDataValue > std::numeric_limits::max())) { @@ -718,7 +719,7 @@ int GRASSASCIIDataset::ParseHeader(const char *pszHeader, dfNoDataValue = CPLAtofM(pszNoData); if (pszDataType == nullptr && (strchr(pszNoData, '.') != nullptr || - strchr(pszNoData, ',') != nullptr || + strchr(pszNoData, ',') != nullptr || std::isnan(dfNoDataValue) || std::numeric_limits::min() > dfNoDataValue || dfNoDataValue > std::numeric_limits::max())) { diff --git a/deps/libgdal/gdal/frmts/basisu_ktx2/CMakeLists.txt b/deps/libgdal/gdal/frmts/basisu_ktx2/CMakeLists.txt index 4811ac8e8..413f9558c 100644 --- a/deps/libgdal/gdal/frmts/basisu_ktx2/CMakeLists.txt +++ b/deps/libgdal/gdal/frmts/basisu_ktx2/CMakeLists.txt @@ -8,7 +8,8 @@ add_gdal_driver(TARGET gdal_BASISU_KTX2 ktx2drivercore.cpp commoncore.cpp STRONG_CXX_WFLAGS - PLUGIN_CAPABLE) + PLUGIN_CAPABLE + NO_SHARED_SYMBOL_WITH_CORE) if(NOT TARGET gdal_BASISU_KTX2) return() diff --git a/deps/libgdal/gdal/frmts/basisu_ktx2/basisudrivercore.h b/deps/libgdal/gdal/frmts/basisu_ktx2/basisudrivercore.h index ca2610a6c..26723f7e4 100644 --- a/deps/libgdal/gdal/frmts/basisu_ktx2/basisudrivercore.h +++ b/deps/libgdal/gdal/frmts/basisu_ktx2/basisudrivercore.h @@ -33,8 +33,12 @@ constexpr const char *BASISU_DRIVER_NAME = "BASISU"; -int CPL_DLL BASISUDriverIdentify(GDALOpenInfo *poOpenInfo); +#define BASISUDriverIdentify PLUGIN_SYMBOL_NAME(BASISUDriverIdentify) +#define BASISUDriverSetCommonMetadata \ + PLUGIN_SYMBOL_NAME(BASISUDriverSetCommonMetadata) -void CPL_DLL BASISUDriverSetCommonMetadata(GDALDriver *poDriver); +int BASISUDriverIdentify(GDALOpenInfo *poOpenInfo); + +void BASISUDriverSetCommonMetadata(GDALDriver *poDriver); #endif diff --git a/deps/libgdal/gdal/frmts/basisu_ktx2/ktx2drivercore.h b/deps/libgdal/gdal/frmts/basisu_ktx2/ktx2drivercore.h index e5070a8fb..23729a5e0 100644 --- a/deps/libgdal/gdal/frmts/basisu_ktx2/ktx2drivercore.h +++ b/deps/libgdal/gdal/frmts/basisu_ktx2/ktx2drivercore.h @@ -33,8 +33,12 @@ constexpr const char *KTX2_DRIVER_NAME = "KTX2"; -int CPL_DLL KTX2DriverIdentify(GDALOpenInfo *poOpenInfo); +#define KTX2DriverIdentify PLUGIN_SYMBOL_NAME(KTX2DriverIdentify) +#define KTX2DriverSetCommonMetadata \ + PLUGIN_SYMBOL_NAME(KTX2DriverSetCommonMetadata) -void CPL_DLL KTX2DriverSetCommonMetadata(GDALDriver *poDriver); +int KTX2DriverIdentify(GDALOpenInfo *poOpenInfo); + +void KTX2DriverSetCommonMetadata(GDALDriver *poDriver); #endif diff --git a/deps/libgdal/gdal/frmts/dds/CMakeLists.txt b/deps/libgdal/gdal/frmts/dds/CMakeLists.txt index a74fb7062..23f3ac064 100644 --- a/deps/libgdal/gdal/frmts/dds/CMakeLists.txt +++ b/deps/libgdal/gdal/frmts/dds/CMakeLists.txt @@ -1,7 +1,8 @@ add_gdal_driver(TARGET gdal_DDS SOURCES ddsdataset.cpp CORE_SOURCES ddsdrivercore.cpp - PLUGIN_CAPABLE) + PLUGIN_CAPABLE + NO_SHARED_SYMBOL_WITH_CORE) if(NOT TARGET gdal_DDS) return() diff --git a/deps/libgdal/gdal/frmts/dds/ddsdrivercore.h b/deps/libgdal/gdal/frmts/dds/ddsdrivercore.h index d500e944f..31f4274aa 100644 --- a/deps/libgdal/gdal/frmts/dds/ddsdrivercore.h +++ b/deps/libgdal/gdal/frmts/dds/ddsdrivercore.h @@ -36,8 +36,12 @@ constexpr const char *DRIVER_NAME = "DDS"; #define DDS_SIGNATURE "DDS " -int CPL_DLL DDSDriverIdentify(GDALOpenInfo *poOpenInfo); +#define DDSDriverIdentify PLUGIN_SYMBOL_NAME(DDSDriverIdentify) +#define DDSDriverSetCommonMetadata \ + PLUGIN_SYMBOL_NAME(DDSDriverSetCommonMetadata) -void CPL_DLL DDSDriverSetCommonMetadata(GDALDriver *poDriver); +int DDSDriverIdentify(GDALOpenInfo *poOpenInfo); + +void DDSDriverSetCommonMetadata(GDALDriver *poDriver); #endif diff --git a/deps/libgdal/gdal/frmts/ecw/CMakeLists.txt b/deps/libgdal/gdal/frmts/ecw/CMakeLists.txt index ec8fdf98d..8369bad24 100644 --- a/deps/libgdal/gdal/frmts/ecw/CMakeLists.txt +++ b/deps/libgdal/gdal/frmts/ecw/CMakeLists.txt @@ -4,7 +4,8 @@ add_gdal_driver( SOURCES ${SOURCE} CORE_SOURCES ecwdrivercore.cpp DRIVER_NAME_OPTION ECW - DEF FRMT_ecw PLUGIN_CAPABLE) + DEF FRMT_ecw PLUGIN_CAPABLE + NO_SHARED_SYMBOL_WITH_CORE) if(TARGET gdal_ECW_JP2ECW_core) target_include_directories(gdal_ECW_JP2ECW_core PRIVATE $) diff --git a/deps/libgdal/gdal/frmts/ecw/ecwdrivercore.h b/deps/libgdal/gdal/frmts/ecw/ecwdrivercore.h index 2d99273c3..dedc043a0 100644 --- a/deps/libgdal/gdal/frmts/ecw/ecwdrivercore.h +++ b/deps/libgdal/gdal/frmts/ecw/ecwdrivercore.h @@ -35,12 +35,20 @@ constexpr const char *ECW_DRIVER_NAME = "ECW"; constexpr const char *JP2ECW_DRIVER_NAME = "JP2ECW"; -int CPL_DLL ECWDatasetIdentifyECW(GDALOpenInfo *poOpenInfo); +#define ECWDatasetIdentifyECW PLUGIN_SYMBOL_NAME(ECWDatasetIdentifyECW) +#define ECWDatasetIdentifyJPEG2000 \ + PLUGIN_SYMBOL_NAME(ECWDatasetIdentifyJPEG2000) +#define ECWDriverSetCommonMetadata \ + PLUGIN_SYMBOL_NAME(ECWDriverSetCommonMetadata) +#define JP2ECWDriverSetCommonMetadata \ + PLUGIN_SYMBOL_NAME(JP2ECWDriverSetCommonMetadata) -int CPL_DLL ECWDatasetIdentifyJPEG2000(GDALOpenInfo *poOpenInfo); +int ECWDatasetIdentifyECW(GDALOpenInfo *poOpenInfo); -void CPL_DLL ECWDriverSetCommonMetadata(GDALDriver *poDriver); +int ECWDatasetIdentifyJPEG2000(GDALOpenInfo *poOpenInfo); -void CPL_DLL JP2ECWDriverSetCommonMetadata(GDALDriver *poDriver); +void ECWDriverSetCommonMetadata(GDALDriver *poDriver); + +void JP2ECWDriverSetCommonMetadata(GDALDriver *poDriver); #endif diff --git a/deps/libgdal/gdal/frmts/esric/esric_dataset.cpp b/deps/libgdal/gdal/frmts/esric/esric_dataset.cpp index c8e9867a0..c92d7132d 100644 --- a/deps/libgdal/gdal/frmts/esric/esric_dataset.cpp +++ b/deps/libgdal/gdal/frmts/esric/esric_dataset.cpp @@ -34,6 +34,8 @@ #include #include #include "cpl_json.h" +#include "gdal_proxy.h" +#include "gdal_utils.h" using namespace std; @@ -67,9 +69,29 @@ static int IdentifyJSON(GDALOpenInfo *poOpenInfo) if (!ENDS_WITH_CI(poOpenInfo->pszFilename, "root.json")) return false; #endif - CPLString header(reinterpret_cast(poOpenInfo->pabyHeader), - poOpenInfo->nHeaderBytes); - return (CPLString::npos != header.find("tileBundlesPath")); + for (int i = 0; i < 2; ++i) + { + const std::string osHeader( + reinterpret_cast(poOpenInfo->pabyHeader), + poOpenInfo->nHeaderBytes); + if (std::string::npos != osHeader.find("tileBundlesPath")) + { + return true; + } + // If we didn't find tileBundlesPath i, the first bytes, but find + // other elements typically of .tpkx, then ingest more bytes and + // retry + constexpr int MORE_BYTES = 8192; + if (poOpenInfo->nHeaderBytes < MORE_BYTES && + (std::string::npos != osHeader.find("tileInfo") || + std::string::npos != osHeader.find("tileImageInfo"))) + { + poOpenInfo->TryToIngest(MORE_BYTES); + } + else + break; + } + return false; } // Without full XML parsing, weak, might still fail @@ -180,6 +202,8 @@ class ECDataset final : public GDALDataset } static GDALDataset *Open(GDALOpenInfo *poOpenInfo); + static GDALDataset *Open(GDALOpenInfo *poOpenInfo, + const char *pszDescription); protected: double GeoTransform[6]; @@ -196,9 +220,13 @@ class ECDataset final : public GDALDataset CPLErr InitializeFromJSON(const CPLJSONObject &oRoot); CPLString compression; std::vector resolutions; + int m_nMinLOD = 0; OGRSpatialReference oSRS; std::vector tilebuffer; // Last read tile, decompressed std::vector filebuffer; // raw tile buffer + + OGREnvelope m_sInitialExtent{}; + OGREnvelope m_sFullExtent{}; }; class ECBand final : public GDALRasterBand @@ -260,6 +288,8 @@ CPLErr ECDataset::Initialize(CPLXMLNode *CacheInfo) TSZ = static_cast(CPLAtof(CPLGetXMLValue(TCI, "TileCols", "256"))); if (TSZ != CPLAtof(CPLGetXMLValue(TCI, "TileRows", "256"))) throw CPLString("Non-square tiles are not supported"); + if (TSZ < 0 || TSZ > 8192) + throw CPLString("Unsupported TileCols value"); CPLXMLNode *LODInfo = CPLGetXMLNode(TCI, "LODInfos.LODInfo"); double res = 0; @@ -332,6 +362,58 @@ CPLErr ECDataset::Initialize(CPLXMLNode *CacheInfo) return error; } +static std::unique_ptr +CreateSRS(const CPLJSONObject &oSRSRoot) +{ + auto poSRS = std::make_unique(); + + bool bSuccess = false; + const int nCode = oSRSRoot.GetInteger("wkid"); + // The concept of LatestWKID is explained in + // https://support.esri.com/en/technical-article/000013950 + const int nLatestCode = oSRSRoot.GetInteger("latestWkid"); + + // Try first with nLatestWKID as there is a higher chance it is a + // EPSG code and not an ESRI one. + if (nLatestCode > 0) + { + if (nLatestCode > 32767) + { + if (poSRS->SetFromUserInput(CPLSPrintf("ESRI:%d", nLatestCode)) == + OGRERR_NONE) + { + bSuccess = true; + } + } + else if (poSRS->importFromEPSG(nLatestCode) == OGRERR_NONE) + { + bSuccess = true; + } + } + if (!bSuccess && nCode > 0) + { + if (nCode > 32767) + { + if (poSRS->SetFromUserInput(CPLSPrintf("ESRI:%d", nCode)) == + OGRERR_NONE) + { + bSuccess = true; + } + } + else if (poSRS->importFromEPSG(nCode) == OGRERR_NONE) + { + bSuccess = true; + } + } + if (!bSuccess) + { + return nullptr; + } + + poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); + return poSRS; +} + CPLErr ECDataset::InitializeFromJSON(const CPLJSONObject &oRoot) { CPLErr error = CE_None; @@ -347,20 +429,23 @@ CPLErr ECDataset::InitializeFromJSON(const CPLJSONObject &oRoot) TSZ = oRoot.GetInteger("tileInfo/rows"); if (TSZ != oRoot.GetInteger("tileInfo/cols")) throw CPLString("Non-square tiles are not supported"); + if (TSZ < 0 || TSZ > 8192) + throw CPLString("Unsupported tileInfo/rows value"); - auto oLODs = oRoot.GetArray("tileInfo/lods"); + const auto oLODs = oRoot.GetArray("tileInfo/lods"); double res = 0; // we need to skip levels that don't have bundle files - int minLOD = oRoot.GetInteger("minLOD"); - int maxLOD = oRoot.GetInteger("maxLOD"); - int level = 0; + m_nMinLOD = oRoot.GetInteger("minLOD"); + if (m_nMinLOD < 0 || m_nMinLOD >= 31) + throw CPLString("Invalid minLOD"); + const int maxLOD = std::min(oRoot.GetInteger("maxLOD"), 31); for (const auto &oLOD : oLODs) { res = oLOD.GetDouble("resolution"); if (!(res > 0)) throw CPLString("Can't parse resolution for LOD"); - level = oLOD.GetInteger("level"); - if (level >= minLOD && level <= maxLOD) + const int level = oLOD.GetInteger("level"); + if (level >= m_nMinLOD && level <= maxLOD) { resolutions.push_back(res); } @@ -369,50 +454,14 @@ CPLErr ECDataset::InitializeFromJSON(const CPLJSONObject &oRoot) if (resolutions.empty()) throw CPLString("Can't parse lods"); - bool bSuccess = false; - const int nCode = oRoot.GetInteger("spatialReference/wkid"); - // The concept of LatestWKID is explained in - // https://support.esri.com/en/technical-article/000013950 - const int nLatestCode = oRoot.GetInteger("spatialReference/latestWkid"); - - // Try first with nLatestWKID as there is a higher chance it is a - // EPSG code and not an ESRI one. - if (nLatestCode > 0) - { - if (nLatestCode > 32767) - { - if (oSRS.SetFromUserInput(CPLSPrintf("ESRI:%d", nLatestCode)) == - OGRERR_NONE) - { - bSuccess = true; - } - } - else if (oSRS.importFromEPSG(nLatestCode) == OGRERR_NONE) - { - bSuccess = true; - } - } - if (!bSuccess && nCode > 0) { - if (nCode > 32767) - { - if (oSRS.SetFromUserInput(CPLSPrintf("ESRI:%d", nCode)) == - OGRERR_NONE) - { - bSuccess = true; - } - } - else if (oSRS.importFromEPSG(nCode) == OGRERR_NONE) + auto poSRS = CreateSRS(oRoot.GetObj("spatialReference")); + if (!poSRS) { - bSuccess = true; + throw CPLString("Invalid Spatial Reference"); } + oSRS = std::move(*poSRS); } - if (!bSuccess) - { - throw CPLString("Invalid Spatial Reference"); - } - - oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); // resolution is the smallest figure res = resolutions[0]; @@ -440,6 +489,59 @@ CPLErr ECDataset::InitializeFromJSON(const CPLJSONObject &oRoot) compression = oRoot.GetString("tileImageInfo/format"); SetMetadataItem("COMPRESS", compression.c_str(), "IMAGE_STRUCTURE"); + auto oInitialExtent = oRoot.GetObj("initialExtent"); + if (oInitialExtent.IsValid() && + oInitialExtent.GetType() == CPLJSONObject::Type::Object) + { + m_sInitialExtent.MinX = oInitialExtent.GetDouble("xmin"); + m_sInitialExtent.MinY = oInitialExtent.GetDouble("ymin"); + m_sInitialExtent.MaxX = oInitialExtent.GetDouble("xmax"); + m_sInitialExtent.MaxY = oInitialExtent.GetDouble("ymax"); + auto oSRSRoot = oInitialExtent.GetObj("spatialReference"); + if (oSRSRoot.IsValid()) + { + auto poSRS = CreateSRS(oSRSRoot); + if (!poSRS) + { + throw CPLString( + "Invalid Spatial Reference in initialExtent"); + } + if (!poSRS->IsSame(&oSRS)) + { + CPLError(CE_Warning, CPLE_AppDefined, + "Ignoring initialExtent, because its SRS is " + "different from the main one"); + m_sInitialExtent = OGREnvelope(); + } + } + } + + auto oFullExtent = oRoot.GetObj("fullExtent"); + if (oFullExtent.IsValid() && + oFullExtent.GetType() == CPLJSONObject::Type::Object) + { + m_sFullExtent.MinX = oFullExtent.GetDouble("xmin"); + m_sFullExtent.MinY = oFullExtent.GetDouble("ymin"); + m_sFullExtent.MaxX = oFullExtent.GetDouble("xmax"); + m_sFullExtent.MaxY = oFullExtent.GetDouble("ymax"); + auto oSRSRoot = oFullExtent.GetObj("spatialReference"); + if (oSRSRoot.IsValid()) + { + auto poSRS = CreateSRS(oSRSRoot); + if (!poSRS) + { + throw CPLString("Invalid Spatial Reference in fullExtent"); + } + if (!poSRS->IsSame(&oSRS)) + { + CPLError(CE_Warning, CPLE_AppDefined, + "Ignoring fullExtent, because its SRS is " + "different from the main one"); + m_sFullExtent = OGREnvelope(); + } + } + } + nBands = EQUAL(compression, "JPEG") ? 3 : 4; for (int i = 1; i <= nBands; i++) { @@ -462,7 +564,71 @@ CPLErr ECDataset::InitializeFromJSON(const CPLJSONObject &oRoot) return error; } +class ESRICProxyRasterBand final : public GDALProxyRasterBand +{ + private: + GDALRasterBand *m_poUnderlyingBand = nullptr; + + protected: + GDALRasterBand *RefUnderlyingRasterBand(bool /*bForceOpen*/) const override + { + return m_poUnderlyingBand; + } + + public: + explicit ESRICProxyRasterBand(GDALRasterBand *poUnderlyingBand) + : m_poUnderlyingBand(poUnderlyingBand) + { + nBand = poUnderlyingBand->GetBand(); + eDataType = poUnderlyingBand->GetRasterDataType(); + nRasterXSize = poUnderlyingBand->GetXSize(); + nRasterYSize = poUnderlyingBand->GetYSize(); + poUnderlyingBand->GetBlockSize(&nBlockXSize, &nBlockYSize); + } +}; + +class ESRICProxyDataset final : public GDALProxyDataset +{ + private: + std::unique_ptr m_poUnderlyingDS{}; + CPLStringList m_aosFileList{}; + + protected: + GDALDataset *RefUnderlyingDataset() const override + { + return m_poUnderlyingDS.get(); + } + + public: + ESRICProxyDataset(GDALDataset *poUnderlyingDS, const char *pszDescription) + : m_poUnderlyingDS(poUnderlyingDS) + { + nRasterXSize = poUnderlyingDS->GetRasterXSize(); + nRasterYSize = poUnderlyingDS->GetRasterYSize(); + for (int i = 0; i < poUnderlyingDS->GetRasterCount(); ++i) + SetBand(i + 1, new ESRICProxyRasterBand( + poUnderlyingDS->GetRasterBand(i + 1))); + m_aosFileList.AddString(pszDescription); + } + + GDALDriver *GetDriver() override + { + return GDALDriver::FromHandle(GDALGetDriverByName("ESRIC")); + } + + char **GetFileList() override + { + return CSLDuplicate(m_aosFileList.List()); + } +}; + GDALDataset *ECDataset::Open(GDALOpenInfo *poOpenInfo) +{ + return Open(poOpenInfo, poOpenInfo->pszFilename); +} + +GDALDataset *ECDataset::Open(GDALOpenInfo *poOpenInfo, + const char *pszDescription) { if (IdentifyXML(poOpenInfo)) { @@ -503,10 +669,8 @@ GDALDataset *ECDataset::Open(GDALOpenInfo *poOpenInfo) poOpenInfo->pszFilename + "}/root.json") .c_str(), GA_ReadOnly); - auto poDS = Open(&oOpenInfo); - if (poDS) - poDS->SetDescription(poOpenInfo->pszFilename); - return poDS; + oOpenInfo.papszOpenOptions = poOpenInfo->papszOpenOptions; + return Open(&oOpenInfo, pszDescription); } CPLJSONDocument oJSONDocument; @@ -524,7 +688,7 @@ GDALDataset *ECDataset::Open(GDALOpenInfo *poOpenInfo) return nullptr; } - auto ds = new ECDataset(); + auto ds = std::make_unique(); auto tileBundlesPath = oRoot.GetString("tileBundlesPath"); // Strip leading relative path indicator (if present) if (tileBundlesPath.substr(0, 2) == "./") @@ -537,10 +701,76 @@ GDALDataset *ECDataset::Open(GDALOpenInfo *poOpenInfo) CPLErr error = ds->InitializeFromJSON(oRoot); if (CE_None != error) { - delete ds; - ds = nullptr; + return nullptr; } - return ds; + + const bool bIsFullExtentValid = + (ds->m_sFullExtent.IsInit() && + ds->m_sFullExtent.MinX < ds->m_sFullExtent.MaxX && + ds->m_sFullExtent.MinY < ds->m_sFullExtent.MaxY); + const char *pszExtentSource = + CSLFetchNameValue(poOpenInfo->papszOpenOptions, "EXTENT_SOURCE"); + + CPLStringList aosOptions; + if ((!pszExtentSource && bIsFullExtentValid) || + (pszExtentSource && EQUAL(pszExtentSource, "FULL_EXTENT"))) + { + if (!bIsFullExtentValid) + { + CPLError(CE_Failure, CPLE_AppDefined, + "fullExtent is not valid"); + return nullptr; + } + aosOptions.AddString("-projwin"); + aosOptions.AddString(CPLSPrintf("%.18g", ds->m_sFullExtent.MinX)); + aosOptions.AddString(CPLSPrintf("%.18g", ds->m_sFullExtent.MaxY)); + aosOptions.AddString(CPLSPrintf("%.18g", ds->m_sFullExtent.MaxX)); + aosOptions.AddString(CPLSPrintf("%.18g", ds->m_sFullExtent.MinY)); + } + else if (pszExtentSource && EQUAL(pszExtentSource, "INITIAL_EXTENT")) + { + const bool bIsInitialExtentValid = + (ds->m_sInitialExtent.IsInit() && + ds->m_sInitialExtent.MinX < ds->m_sInitialExtent.MaxX && + ds->m_sInitialExtent.MinY < ds->m_sInitialExtent.MaxY); + if (!bIsInitialExtentValid) + { + CPLError(CE_Failure, CPLE_AppDefined, + "initialExtent is not valid"); + return nullptr; + } + aosOptions.AddString("-projwin"); + aosOptions.AddString( + CPLSPrintf("%.18g", ds->m_sInitialExtent.MinX)); + aosOptions.AddString( + CPLSPrintf("%.18g", ds->m_sInitialExtent.MaxY)); + aosOptions.AddString( + CPLSPrintf("%.18g", ds->m_sInitialExtent.MaxX)); + aosOptions.AddString( + CPLSPrintf("%.18g", ds->m_sInitialExtent.MinY)); + } + + if (!aosOptions.empty()) + { + aosOptions.AddString("-of"); + aosOptions.AddString("VRT"); + aosOptions.AddString("-co"); + aosOptions.AddString(CPLSPrintf("BLOCKXSIZE=%d", ds->TSZ)); + aosOptions.AddString("-co"); + aosOptions.AddString(CPLSPrintf("BLOCKYSIZE=%d", ds->TSZ)); + auto psOptions = + GDALTranslateOptionsNew(aosOptions.List(), nullptr); + auto hDS = GDALTranslate("", GDALDataset::ToHandle(ds.release()), + psOptions, nullptr); + GDALTranslateOptionsFree(psOptions); + if (!hDS) + { + return nullptr; + } + return new ESRICProxyDataset(GDALDataset::FromHandle(hDS), + pszDescription); + } + return ds.release(); } return nullptr; } @@ -592,7 +822,7 @@ ECBand::ECBand(ECDataset *parent, int b, int level) double factor = parent->resolutions[0] / parent->resolutions[lvl]; nRasterXSize = static_cast(parent->nRasterXSize * factor + 0.5); nRasterYSize = static_cast(parent->nRasterYSize * factor + 0.5); - nBlockXSize = nBlockYSize = 256; + nBlockXSize = nBlockYSize = parent->TSZ; // Default color interpretation assert(b - 1 >= 0); @@ -632,7 +862,8 @@ CPLErr ECBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pData) buffer.resize(nBytes * parent->nBands); - int lxx = static_cast(parent->resolutions.size() - lvl - 1); + const int lxx = parent->m_nMinLOD + + static_cast(parent->resolutions.size() - lvl - 1); int bx, by; bx = (nBlockXOff / BSZ) * BSZ; by = (nBlockYOff / BSZ) * BSZ; @@ -823,6 +1054,17 @@ void CPL_DLL GDALRegister_ESRIC() poDriver->SetMetadataItem(GDAL_DMD_EXTENSIONS, "json tpkx"); + poDriver->SetMetadataItem( + GDAL_DMD_OPENOPTIONLIST, + "" + " " + ""); poDriver->pfnIdentify = ESRIC::Identify; poDriver->pfnOpen = ESRIC::ECDataset::Open; poDriver->pfnDelete = ESRIC::Delete; diff --git a/deps/libgdal/gdal/frmts/exr/CMakeLists.txt b/deps/libgdal/gdal/frmts/exr/CMakeLists.txt index 2c8b919d8..09646867b 100644 --- a/deps/libgdal/gdal/frmts/exr/CMakeLists.txt +++ b/deps/libgdal/gdal/frmts/exr/CMakeLists.txt @@ -1,7 +1,8 @@ add_gdal_driver(TARGET gdal_EXR SOURCES exrdataset.cpp CORE_SOURCES exrdrivercore.cpp - PLUGIN_CAPABLE) + PLUGIN_CAPABLE + NO_SHARED_SYMBOL_WITH_CORE) if(NOT TARGET gdal_EXR) return() diff --git a/deps/libgdal/gdal/frmts/exr/exrdrivercore.h b/deps/libgdal/gdal/frmts/exr/exrdrivercore.h index bfbd5846a..3a4426459 100644 --- a/deps/libgdal/gdal/frmts/exr/exrdrivercore.h +++ b/deps/libgdal/gdal/frmts/exr/exrdrivercore.h @@ -32,8 +32,12 @@ constexpr const char *DRIVER_NAME = "EXR"; -int CPL_DLL EXRDriverIdentify(GDALOpenInfo *poOpenInfo); +#define EXRDriverIdentify PLUGIN_SYMBOL_NAME(EXRDriverIdentify) +#define EXRDriverSetCommonMetadata \ + PLUGIN_SYMBOL_NAME(EXRDriverSetCommonMetadata) -void CPL_DLL EXRDriverSetCommonMetadata(GDALDriver *poDriver); +int EXRDriverIdentify(GDALOpenInfo *poOpenInfo); + +void EXRDriverSetCommonMetadata(GDALDriver *poDriver); #endif diff --git a/deps/libgdal/gdal/frmts/fits/CMakeLists.txt b/deps/libgdal/gdal/frmts/fits/CMakeLists.txt index 356b7b735..8e723c0a1 100644 --- a/deps/libgdal/gdal/frmts/fits/CMakeLists.txt +++ b/deps/libgdal/gdal/frmts/fits/CMakeLists.txt @@ -1,7 +1,8 @@ add_gdal_driver(TARGET gdal_FITS SOURCES fitsdataset.cpp CORE_SOURCES fitsdrivercore.cpp - PLUGIN_CAPABLE) + PLUGIN_CAPABLE + NO_SHARED_SYMBOL_WITH_CORE) if(NOT TARGET gdal_FITS) return() diff --git a/deps/libgdal/gdal/frmts/fits/fitsdrivercore.h b/deps/libgdal/gdal/frmts/fits/fitsdrivercore.h index 1f3cee6e7..651f82149 100644 --- a/deps/libgdal/gdal/frmts/fits/fitsdrivercore.h +++ b/deps/libgdal/gdal/frmts/fits/fitsdrivercore.h @@ -35,8 +35,12 @@ constexpr const char *DRIVER_NAME = "FITS"; -int CPL_DLL FITSDriverIdentify(GDALOpenInfo *poOpenInfo); +#define FITSDriverIdentify PLUGIN_SYMBOL_NAME(FITSDriverIdentify) +#define FITSDriverSetCommonMetadata \ + PLUGIN_SYMBOL_NAME(FITSDriverSetCommonMetadata) -void CPL_DLL FITSDriverSetCommonMetadata(GDALDriver *poDriver); +int FITSDriverIdentify(GDALOpenInfo *poOpenInfo); + +void FITSDriverSetCommonMetadata(GDALDriver *poDriver); #endif diff --git a/deps/libgdal/gdal/frmts/georaster/CMakeLists.txt b/deps/libgdal/gdal/frmts/georaster/CMakeLists.txt index 0161ed1d5..8f5eaa4a1 100644 --- a/deps/libgdal/gdal/frmts/georaster/CMakeLists.txt +++ b/deps/libgdal/gdal/frmts/georaster/CMakeLists.txt @@ -3,7 +3,8 @@ add_gdal_driver( SOURCES georaster_dataset.cpp georaster_priv.h georaster_rasterband.cpp georaster_wrapper.cpp oci_wrapper.cpp cpl_vsil_ocilob.cpp CORE_SOURCES georasterdrivercore.cpp - DEF FRMT_georaster PLUGIN_CAPABLE_IF "NOT GDAL_USE_ZLIB_INTERNAL\\\;NOT GDAL_USE_JPEG_INTERNAL") + DEF FRMT_georaster PLUGIN_CAPABLE_IF "NOT GDAL_USE_ZLIB_INTERNAL\\\;NOT GDAL_USE_JPEG_INTERNAL" + NO_SHARED_SYMBOL_WITH_CORE) if(NOT TARGET gdal_GEOR) return() diff --git a/deps/libgdal/gdal/frmts/georaster/georasterdrivercore.h b/deps/libgdal/gdal/frmts/georaster/georasterdrivercore.h index f932f572c..ced8486dc 100644 --- a/deps/libgdal/gdal/frmts/georaster/georasterdrivercore.h +++ b/deps/libgdal/gdal/frmts/georaster/georasterdrivercore.h @@ -35,8 +35,12 @@ constexpr const char *DRIVER_NAME = "GeoRaster"; -int CPL_DLL GEORDriverIdentify(GDALOpenInfo *poOpenInfo); +#define GEORDriverIdentify PLUGIN_SYMBOL_NAME(GEORDriverIdentify) +#define GEORDriverSetCommonMetadata \ + PLUGIN_SYMBOL_NAME(GEORDriverSetCommonMetadata) -void CPL_DLL GEORDriverSetCommonMetadata(GDALDriver *poDriver); +int GEORDriverIdentify(GDALOpenInfo *poOpenInfo); + +void GEORDriverSetCommonMetadata(GDALDriver *poDriver); #endif diff --git a/deps/libgdal/gdal/frmts/gif/CMakeLists.txt b/deps/libgdal/gdal/frmts/gif/CMakeLists.txt index 0900fb087..486e0f992 100644 --- a/deps/libgdal/gdal/frmts/gif/CMakeLists.txt +++ b/deps/libgdal/gdal/frmts/gif/CMakeLists.txt @@ -2,7 +2,8 @@ add_gdal_driver( TARGET gdal_GIF SOURCES gifabstractdataset.h gifabstractdataset.cpp biggifdataset.cpp gifdataset.cpp CORE_SOURCES gifdrivercore.cpp - PLUGIN_CAPABLE) + PLUGIN_CAPABLE + NO_SHARED_SYMBOL_WITH_CORE) if(NOT TARGET gdal_GIF) return() diff --git a/deps/libgdal/gdal/frmts/gif/gifdrivercore.h b/deps/libgdal/gdal/frmts/gif/gifdrivercore.h index 08b203bd3..419ff379c 100644 --- a/deps/libgdal/gdal/frmts/gif/gifdrivercore.h +++ b/deps/libgdal/gdal/frmts/gif/gifdrivercore.h @@ -36,10 +36,16 @@ constexpr const char *GIF_DRIVER_NAME = "GIF"; constexpr const char *BIGGIF_DRIVER_NAME = "BIGGIF"; -int CPL_DLL GIFDriverIdentify(GDALOpenInfo *poOpenInfo); +#define GIFDriverIdentify PLUGIN_SYMBOL_NAME(GIFDriverIdentify) +#define BIGGIFDriverSetCommonMetadata \ + PLUGIN_SYMBOL_NAME(BIGGIFDriverSetCommonMetadata) +#define GIFDriverSetCommonMetadata \ + PLUGIN_SYMBOL_NAME(GIFDriverSetCommonMetadata) -void CPL_DLL BIGGIFDriverSetCommonMetadata(GDALDriver *poDriver); +int GIFDriverIdentify(GDALOpenInfo *poOpenInfo); -void CPL_DLL GIFDriverSetCommonMetadata(GDALDriver *poDriver); +void BIGGIFDriverSetCommonMetadata(GDALDriver *poDriver); + +void GIFDriverSetCommonMetadata(GDALDriver *poDriver); #endif diff --git a/deps/libgdal/gdal/frmts/grib/CMakeLists.txt b/deps/libgdal/gdal/frmts/grib/CMakeLists.txt index 7bfb56ac8..16023f731 100644 --- a/deps/libgdal/gdal/frmts/grib/CMakeLists.txt +++ b/deps/libgdal/gdal/frmts/grib/CMakeLists.txt @@ -50,7 +50,8 @@ add_gdal_driver( gribdrivercore.cpp PLUGIN_CAPABLE_IF "NOT GDAL_USE_PNG_INTERNAL\\\;NOT GDAL_USE_ZLIB_INTERNAL" - NO_DEPS) + NO_DEPS + NO_SHARED_SYMBOL_WITH_CORE) if(NOT TARGET gdal_GRIB) return() diff --git a/deps/libgdal/gdal/frmts/grib/gribdataset.cpp b/deps/libgdal/gdal/frmts/grib/gribdataset.cpp index 5b1a7db85..7a9c4499b 100644 --- a/deps/libgdal/gdal/frmts/grib/gribdataset.cpp +++ b/deps/libgdal/gdal/frmts/grib/gribdataset.cpp @@ -922,11 +922,16 @@ char **GRIBRasterBand::GetMetadata(const char *pszDomain) const char *GRIBRasterBand::GetMetadataItem(const char *pszName, const char *pszDomain) { - FindMetaData(); - if (m_nGribVersion == 2 && - CPLTestBool(CPLGetConfigOption("GRIB_PDS_ALL_BANDS", "ON"))) + if (!((!pszDomain || pszDomain[0] == 0) && + (EQUAL(pszName, "STATISTICS_MINIMUM") || + EQUAL(pszName, "STATISTICS_MAXIMUM")))) { - FindPDSTemplateGRIB2(); + FindMetaData(); + if (m_nGribVersion == 2 && + CPLTestBool(CPLGetConfigOption("GRIB_PDS_ALL_BANDS", "ON"))) + { + FindPDSTemplateGRIB2(); + } } return GDALPamRasterBand::GetMetadataItem(pszName, pszDomain); } @@ -1156,7 +1161,8 @@ class InventoryWrapperGrib : public gdal::grib::InventoryWrapper class InventoryWrapperSidecar : public gdal::grib::InventoryWrapper { public: - explicit InventoryWrapperSidecar(VSILFILE *fp) + explicit InventoryWrapperSidecar(VSILFILE *fp, uint64_t nStartOffset, + int64_t nSize) : gdal::grib::InventoryWrapper() { result_ = -1; @@ -1164,26 +1170,25 @@ class InventoryWrapperSidecar : public gdal::grib::InventoryWrapper size_t length = static_cast(VSIFTellL(fp)); if (length > 4 * 1024 * 1024) return; - std::string psSidecar; - psSidecar.resize(length); + std::string osSidecar; + osSidecar.resize(length); VSIFSeekL(fp, 0, SEEK_SET); - if (VSIFReadL(&psSidecar[0], length, 1, fp) != 1) + if (VSIFReadL(&osSidecar[0], length, 1, fp) != 1) return; - CPLStringList aosMsgs( - CSLTokenizeString2(psSidecar.c_str(), "\n", + const CPLStringList aosMsgs( + CSLTokenizeString2(osSidecar.c_str(), "\n", CSLT_PRESERVEQUOTES | CSLT_STRIPLEADSPACES)); - inv_len_ = aosMsgs.size(); inv_ = static_cast( - CPLMalloc(inv_len_ * sizeof(inventoryType))); + CPLCalloc(aosMsgs.size(), sizeof(inventoryType))); - for (size_t i = 0; i < inv_len_; ++i) + for (const char *pszMsg : aosMsgs) { // We are parsing // "msgNum[.subgNum]:start:dontcare:name1:name2:name3" For NOMADS: // "msgNum[.subgNum]:start:reftime:var:level:time" - CPLStringList aosTokens(CSLTokenizeString2( - aosMsgs[i], ":", CSLT_PRESERVEQUOTES | CSLT_ALLOWEMPTYTOKENS)); + const CPLStringList aosTokens(CSLTokenizeString2( + pszMsg, ":", CSLT_PRESERVEQUOTES | CSLT_ALLOWEMPTYTOKENS)); CPLStringList aosNum; if (aosTokens.size() < 6) @@ -1200,7 +1205,7 @@ class InventoryWrapperSidecar : public gdal::grib::InventoryWrapper goto err_sidecar; if (aosNum.size() < 2) - inv_[i].subgNum = 0; + inv_[inv_len_].subgNum = 0; else { auto subgNum = strtol(aosNum[1], &endptr, 10); @@ -1211,21 +1216,29 @@ class InventoryWrapperSidecar : public gdal::grib::InventoryWrapper // .idx file use a 1-based indexing, whereas DEGRIB uses a // 0-based one subgNum--; - inv_[i].subgNum = static_cast(subgNum); + inv_[inv_len_].subgNum = static_cast(subgNum); } - inv_[i].start = strtoll(aosTokens[1], &endptr, 10); + inv_[inv_len_].start = strtoll(aosTokens[1], &endptr, 10); if (*endptr != 0) goto err_sidecar; - inv_[i].unitName = nullptr; - inv_[i].comment = nullptr; - inv_[i].element = nullptr; - inv_[i].shortFstLevel = nullptr; + if (inv_[inv_len_].start < nStartOffset) + continue; + if (nSize > 0 && inv_[inv_len_].start >= nStartOffset + nSize) + break; + + inv_[inv_len_].start -= nStartOffset; + + inv_[inv_len_].unitName = nullptr; + inv_[inv_len_].comment = nullptr; + inv_[inv_len_].element = nullptr; + inv_[inv_len_].shortFstLevel = nullptr; // This is going into the description field -> // the only one available before loading the metadata - inv_[i].longFstLevel = VSIStrdup(CPLSPrintf( + inv_[inv_len_].longFstLevel = VSIStrdup(CPLSPrintf( "%s:%s:%s", aosTokens[3], aosTokens[4], aosTokens[5])); + ++inv_len_; continue; @@ -1233,8 +1246,7 @@ class InventoryWrapperSidecar : public gdal::grib::InventoryWrapper CPLDebug("GRIB", "Failed parsing sidecar entry '%s', " "falling back to constructing an inventory", - aosMsgs[i]); - inv_len_ = static_cast(i); + pszMsg); return; } @@ -1309,22 +1321,43 @@ GRIBDataset::Inventory(VSILFILE *fp, GDALOpenInfo *poOpenInfo) std::unique_ptr pInventories; VSIFSeekL(fp, 0, SEEK_SET); - CPLString sSideCarFilename = CPLString(poOpenInfo->pszFilename) + ".idx"; + std::string osSideCarFilename(poOpenInfo->pszFilename); + uint64_t nStartOffset = 0; + int64_t nSize = -1; + if (STARTS_WITH(poOpenInfo->pszFilename, "/vsisubfile/")) + { + const char *pszPtr = poOpenInfo->pszFilename + strlen("/vsisubfile/"); + const char *pszComma = strchr(pszPtr, ','); + if (pszComma) + { + const CPLStringList aosTokens(CSLTokenizeString2( + std::string(pszPtr, pszComma - pszPtr).c_str(), "_", 0)); + if (aosTokens.size() == 2) + { + nStartOffset = std::strtoull(aosTokens[0], nullptr, 10); + nSize = std::strtoll(aosTokens[1], nullptr, 10); + osSideCarFilename = pszComma + 1; + } + } + } + osSideCarFilename += ".idx"; VSILFILE *fpSideCar = nullptr; if (CPLTestBool(CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "USE_IDX", "YES")) && - ((fpSideCar = VSIFOpenL(sSideCarFilename, "rb")) != nullptr)) + ((fpSideCar = VSIFOpenL(osSideCarFilename.c_str(), "rb")) != nullptr)) { CPLDebug("GRIB", "Reading inventories from sidecar file %s", - sSideCarFilename.c_str()); + osSideCarFilename.c_str()); // Contains an GRIB2 message inventory of the file. - pInventories = std::make_unique(fpSideCar); + pInventories = std::make_unique( + fpSideCar, nStartOffset, nSize); if (pInventories->result() <= 0 || pInventories->length() == 0) pInventories = nullptr; VSIFCloseL(fpSideCar); } else - CPLDebug("GRIB", "Failed opening sidecar %s", sSideCarFilename.c_str()); + CPLDebug("GRIB", "Failed opening sidecar %s", + osSideCarFilename.c_str()); if (pInventories == nullptr) { @@ -2021,7 +2054,14 @@ void GRIBArray::Finalize(GRIBGroup *poGroup, inventoryType *psInv) attr->Write("validity_time"); } +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wnull-dereference" +#endif m_dims.insert(m_dims.begin(), poDimTime); +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#endif if (m_poSRS) { auto mapping = m_poSRS->GetDataAxisToSRSAxisMapping(); diff --git a/deps/libgdal/gdal/frmts/grib/gribdrivercore.h b/deps/libgdal/gdal/frmts/grib/gribdrivercore.h index 98e0a820c..d745bd6ed 100644 --- a/deps/libgdal/gdal/frmts/grib/gribdrivercore.h +++ b/deps/libgdal/gdal/frmts/grib/gribdrivercore.h @@ -34,8 +34,12 @@ constexpr const char *DRIVER_NAME = "GRIB"; -int CPL_DLL GRIBDriverIdentify(GDALOpenInfo *poOpenInfo); +#define GRIBDriverIdentify PLUGIN_SYMBOL_NAME(GRIBDriverIdentify) +#define GRIBDriverSetCommonMetadata \ + PLUGIN_SYMBOL_NAME(GRIBDriverSetCommonMetadata) -void CPL_DLL GRIBDriverSetCommonMetadata(GDALDriver *poDriver); +int GRIBDriverIdentify(GDALOpenInfo *poOpenInfo); + +void GRIBDriverSetCommonMetadata(GDALDriver *poDriver); #endif diff --git a/deps/libgdal/gdal/frmts/gta/CMakeLists.txt b/deps/libgdal/gdal/frmts/gta/CMakeLists.txt index 7d3649a8f..68428bb75 100644 --- a/deps/libgdal/gdal/frmts/gta/CMakeLists.txt +++ b/deps/libgdal/gdal/frmts/gta/CMakeLists.txt @@ -1,7 +1,8 @@ add_gdal_driver(TARGET gdal_GTA SOURCES gta_headers.h gtadataset.cpp CORE_SOURCES gtadrivercore.cpp - PLUGIN_CAPABLE) + PLUGIN_CAPABLE + NO_SHARED_SYMBOL_WITH_CORE) if(NOT TARGET gdal_GTA) return() diff --git a/deps/libgdal/gdal/frmts/gta/gtadrivercore.h b/deps/libgdal/gdal/frmts/gta/gtadrivercore.h index 1d8336aa8..536fdec9f 100644 --- a/deps/libgdal/gdal/frmts/gta/gtadrivercore.h +++ b/deps/libgdal/gdal/frmts/gta/gtadrivercore.h @@ -34,8 +34,13 @@ constexpr const char *DRIVER_NAME = "GTA"; -int CPL_DLL GTADriverIdentify(GDALOpenInfo *poOpenInfo); +#define GTADriverIdentify PLUGIN_SYMBOL_NAME(GTADriverIdentify) -void CPL_DLL GTADriverSetCommonMetadata(GDALDriver *poDriver); +#define GTADriverSetCommonMetadata \ + PLUGIN_SYMBOL_NAME(GTADriverSetCommonMetadata) + +int GTADriverIdentify(GDALOpenInfo *poOpenInfo); + +void GTADriverSetCommonMetadata(GDALDriver *poDriver); #endif diff --git a/deps/libgdal/gdal/frmts/gtiff/cogdriver.cpp b/deps/libgdal/gdal/frmts/gtiff/cogdriver.cpp index 063742b42..f5c5045ac 100644 --- a/deps/libgdal/gdal/frmts/gtiff/cogdriver.cpp +++ b/deps/libgdal/gdal/frmts/gtiff/cogdriver.cpp @@ -737,19 +737,25 @@ GDALCOGCreator::~GDALCOGCreator() // may reference the later m_poRGBMaskDS.reset(); - if (m_poReprojectedDS) + // Config option just for testing purposes + const bool bDeleteTempFiles = + CPLTestBool(CPLGetConfigOption("COG_DELETE_TEMP_FILES", "YES")); + if (bDeleteTempFiles) { - CPLString osProjectedDSName(m_poReprojectedDS->GetDescription()); - m_poReprojectedDS.reset(); - VSIUnlink(osProjectedDSName); - } - if (!m_osTmpOverviewFilename.empty()) - { - VSIUnlink(m_osTmpOverviewFilename); - } - if (!m_osTmpMskOverviewFilename.empty()) - { - VSIUnlink(m_osTmpMskOverviewFilename); + if (m_poReprojectedDS) + { + CPLString osProjectedDSName(m_poReprojectedDS->GetDescription()); + m_poReprojectedDS.reset(); + VSIUnlink(osProjectedDSName); + } + if (!m_osTmpOverviewFilename.empty()) + { + VSIUnlink(m_osTmpOverviewFilename); + } + if (!m_osTmpMskOverviewFilename.empty()) + { + VSIUnlink(m_osTmpMskOverviewFilename); + } } } diff --git a/deps/libgdal/gdal/frmts/gtiff/gt_overview.cpp b/deps/libgdal/gdal/frmts/gtiff/gt_overview.cpp index 38ca89e43..c125ab091 100644 --- a/deps/libgdal/gdal/frmts/gtiff/gt_overview.cpp +++ b/deps/libgdal/gdal/frmts/gtiff/gt_overview.cpp @@ -203,7 +203,8 @@ toff_t GTIFFWriteDirectory(TIFF *hTIFF, int nSubfileType, int nXSize, /************************************************************************/ void GTIFFBuildOverviewMetadata(const char *pszResampling, - GDALDataset *poBaseDS, CPLString &osMetadata) + GDALDataset *poBaseDS, bool bIsForMaskBand, + CPLString &osMetadata) { osMetadata = ""; @@ -216,7 +217,11 @@ void GTIFFBuildOverviewMetadata(const char *pszResampling, osMetadata += ""; } - if (poBaseDS->GetMetadataItem("INTERNAL_MASK_FLAGS_1")) + if (bIsForMaskBand) + { + osMetadata += "2"; + } + else if (poBaseDS->GetMetadataItem("INTERNAL_MASK_FLAGS_1")) { for (int iBand = 0; iBand < 200; iBand++) { @@ -771,7 +776,10 @@ CPLErr GTIFFBuildOverviewsEx(const char *pszFilename, int nBands, GDALDataset *poBaseDS = papoBandList[0]->GetDataset(); if (poBaseDS) { - GTIFFBuildOverviewMetadata(pszResampling, poBaseDS, osMetadata); + const bool bIsForMaskBand = + nBands == 1 && papoBandList[0]->IsMaskBand(); + GTIFFBuildOverviewMetadata(pszResampling, poBaseDS, bIsForMaskBand, + osMetadata); } if (poBaseDS != nullptr && poBaseDS->GetRasterCount() == nBands) diff --git a/deps/libgdal/gdal/frmts/gtiff/gt_overview.h b/deps/libgdal/gdal/frmts/gtiff/gt_overview.h index 9014662e6..5b56f4929 100644 --- a/deps/libgdal/gdal/frmts/gtiff/gt_overview.h +++ b/deps/libgdal/gdal/frmts/gtiff/gt_overview.h @@ -53,7 +53,8 @@ toff_t GTIFFWriteDirectory(TIFF *hTIFF, int nSubfileType, int nXSize, bool bDeferStrileArrayWriting); void GTIFFBuildOverviewMetadata(const char *pszResampling, - GDALDataset *poBaseDS, CPLString &osMetadata); + GDALDataset *poBaseDS, bool bIsForMaskBand, + CPLString &osMetadata); CPLErr GTIFFBuildOverviewsEx(const char *pszFilename, int nBands, GDALRasterBand *const *papoBandList, diff --git a/deps/libgdal/gdal/frmts/gtiff/gt_wkt_srs.cpp b/deps/libgdal/gdal/frmts/gtiff/gt_wkt_srs.cpp index 756625394..919829f2d 100644 --- a/deps/libgdal/gdal/frmts/gtiff/gt_wkt_srs.cpp +++ b/deps/libgdal/gdal/frmts/gtiff/gt_wkt_srs.cpp @@ -1397,6 +1397,43 @@ OGRSpatialReferenceH GTIFGetOGISDefnAsOSR(GTIF *hGTIF, GTIFDefn *psDefn) for (; i < 10; i++) adfParam[i] = 0.0; +#if LIBGEOTIFF_VERSION <= 1730 + // libgeotiff <= 1.7.3 is unfortunately inconsistent. When it synthetizes the + // projection parameters from the EPSG ProjectedCRS code, it returns + // them normalized in degrees. But when it gets them from + // ProjCoordTransGeoKey and other Proj....GeoKey's it return them in + // a raw way, that is in the units of GeogAngularUnitSizeGeoKey + // The below oSRS.SetXXXXX() methods assume the angular projection + // parameters to be in degrees, so convert them to degrees in that later case. + // From GDAL 3.0 to 3.9.0, we didn't do that conversion... + // And all versions of GDAL <= 3.9.0 when writing those geokeys, wrote + // them as degrees, hence this GTIFF_READ_ANGULAR_PARAMS_IN_DEGREE + // config option that can be set to YES to avoid that conversion and + // assume that the angular parameters have been written as degree. + if (GDALGTIFKeyGetSHORT(hGTIF, ProjCoordTransGeoKey, &tmp, 0, 1) && + !CPLTestBool(CPLGetConfigOption( + "GTIFF_READ_ANGULAR_PARAMS_IN_DEGREE", "NO"))) + { + adfParam[0] *= psDefn->UOMAngleInDegrees; + adfParam[1] *= psDefn->UOMAngleInDegrees; + adfParam[2] *= psDefn->UOMAngleInDegrees; + adfParam[3] *= psDefn->UOMAngleInDegrees; + } +#else + // If GTIFF_READ_ANGULAR_PARAMS_IN_DEGREE=YES (non-nominal case), undo + // the conversion to degrees, that has been done by libgeotiff > 1.7.3 + if (GDALGTIFKeyGetSHORT(hGTIF, ProjCoordTransGeoKey, &tmp, 0, 1) && + psDefn->UOMAngleInDegrees != 0 && psDefn->UOMAngleInDegrees != 1 && + CPLTestBool(CPLGetConfigOption( + "GTIFF_READ_ANGULAR_PARAMS_IN_DEGREE", "NO"))) + { + adfParam[0] /= psDefn->UOMAngleInDegrees; + adfParam[1] /= psDefn->UOMAngleInDegrees; + adfParam[2] /= psDefn->UOMAngleInDegrees; + adfParam[3] /= psDefn->UOMAngleInDegrees; + } +#endif + /* -------------------------------------------------------------------- */ /* Translation the fundamental projection. */ @@ -2150,6 +2187,31 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, } #endif + double dfAngUnitValue = 0; + std::string osAngUnitName; + if (bHasEllipsoid) + { + const char *angUnitNameTmp = ""; + dfAngUnitValue = poSRS->GetAngularUnits(&angUnitNameTmp); + osAngUnitName = angUnitNameTmp; + } + + // Convert angular projection parameters from its normalized value in degree + // to the units of GeogAngularUnitsGeoKey. + // Note: for GDAL <= 3.9.0, we always have written them in degrees ! + // We can set GTIFF_WRITE_ANGULAR_PARAMS_IN_DEGREE=YES to get that + // non-conformant behavior... + const auto ConvertAngularParam = [dfAngUnitValue](double dfValInDeg) + { + constexpr double DEG_TO_RAD = M_PI / 180.0; + return dfAngUnitValue != 0 && + std::fabs(dfAngUnitValue - DEG_TO_RAD) > 1e-10 && + !CPLTestBool(CPLGetConfigOption( + "GTIFF_WRITE_ANGULAR_PARAMS_IN_DEGREE", "NO")) + ? dfValInDeg * DEG_TO_RAD / dfAngUnitValue + : dfValInDeg; + }; + const char *pszProjection = poSRSCompatibleOfWKT1->GetAttrValue("PROJECTION"); if (nPCS != KvUserDefined) @@ -2191,20 +2253,20 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_AlbersEqualArea); GTIFKeySet(psGTIF, ProjStdParallelGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_STANDARD_PARALLEL_1, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_STANDARD_PARALLEL_1, 0.0))); GTIFKeySet(psGTIF, ProjStdParallel2GeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_STANDARD_PARALLEL_2, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_STANDARD_PARALLEL_2, 0.0))); GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_CENTER, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_CENTER, 0.0))); GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LONGITUDE_OF_CENTER, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LONGITUDE_OF_CENTER, 0.0))); GTIFKeySet( psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, @@ -2267,12 +2329,12 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_TransverseMercator); GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_ORIGIN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_ORIGIN, 0.0))); GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_CENTRAL_MERIDIAN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_CENTRAL_MERIDIAN, 0.0))); GTIFKeySet( psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1, @@ -2298,12 +2360,12 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_TransvMercator_SouthOriented); GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_ORIGIN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_ORIGIN, 0.0))); GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_CENTRAL_MERIDIAN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_CENTRAL_MERIDIAN, 0.0))); GTIFKeySet( psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1, @@ -2330,17 +2392,18 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_Mercator); GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_ORIGIN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_ORIGIN, 0.0))); GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_CENTRAL_MERIDIAN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_CENTRAL_MERIDIAN, 0.0))); if (EQUAL(pszProjection, SRS_PT_MERCATOR_2SP)) - GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_STANDARD_PARALLEL_1, 0.0)); + GTIFKeySet( + psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1, + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_STANDARD_PARALLEL_1, 0.0))); else GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1, poSRSCompatibleOfWKT1->GetNormProjParm( @@ -2366,12 +2429,12 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_ObliqueStereographic); GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_ORIGIN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_ORIGIN, 0.0))); GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_CENTRAL_MERIDIAN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_CENTRAL_MERIDIAN, 0.0))); GTIFKeySet( psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1, @@ -2397,12 +2460,12 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_Stereographic); GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_ORIGIN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_ORIGIN, 0.0))); GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_CENTRAL_MERIDIAN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_CENTRAL_MERIDIAN, 0.0))); GTIFKeySet( psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1, @@ -2428,12 +2491,12 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_PolarStereographic); GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_ORIGIN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_ORIGIN, 0.0))); GTIFKeySet(psGTIF, ProjStraightVertPoleLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_CENTRAL_MERIDIAN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_CENTRAL_MERIDIAN, 0.0))); GTIFKeySet( psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1, @@ -2459,19 +2522,19 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_ObliqueMercator); GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_CENTER, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_CENTER, 0.0))); GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LONGITUDE_OF_CENTER, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LONGITUDE_OF_CENTER, 0.0))); GTIFKeySet(psGTIF, ProjAzimuthAngleGeoKey, TYPE_DOUBLE, 1, poSRSCompatibleOfWKT1->GetNormProjParm(SRS_PP_AZIMUTH, 0.0)); GTIFKeySet(psGTIF, ProjRectifiedGridAngleGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_RECTIFIED_GRID_ANGLE, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_RECTIFIED_GRID_ANGLE, 0.0))); GTIFKeySet( psGTIF, ProjScaleAtCenterGeoKey, TYPE_DOUBLE, 1, @@ -2498,19 +2561,19 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_HotineObliqueMercatorAzimuthCenter); GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_CENTER, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_CENTER, 0.0))); GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LONGITUDE_OF_CENTER, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LONGITUDE_OF_CENTER, 0.0))); GTIFKeySet(psGTIF, ProjAzimuthAngleGeoKey, TYPE_DOUBLE, 1, poSRSCompatibleOfWKT1->GetNormProjParm(SRS_PP_AZIMUTH, 0.0)); GTIFKeySet(psGTIF, ProjRectifiedGridAngleGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_RECTIFIED_GRID_ANGLE, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_RECTIFIED_GRID_ANGLE, 0.0))); GTIFKeySet( psGTIF, ProjScaleAtCenterGeoKey, TYPE_DOUBLE, 1, @@ -2536,12 +2599,12 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_ObliqueMercator_Laborde); GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_CENTER, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_CENTER, 0.0))); GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LONGITUDE_OF_CENTER, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LONGITUDE_OF_CENTER, 0.0))); GTIFKeySet(psGTIF, ProjAzimuthAngleGeoKey, TYPE_DOUBLE, 1, poSRSCompatibleOfWKT1->GetNormProjParm(SRS_PP_AZIMUTH, 0.0)); @@ -2570,12 +2633,12 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_CassiniSoldner); GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_ORIGIN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_ORIGIN, 0.0))); GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_CENTRAL_MERIDIAN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_CENTRAL_MERIDIAN, 0.0))); GTIFKeySet( psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, @@ -2597,20 +2660,20 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_EquidistantConic); GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_STANDARD_PARALLEL_1, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_STANDARD_PARALLEL_1, 0.0))); GTIFKeySet(psGTIF, ProjStdParallel2GeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_STANDARD_PARALLEL_2, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_STANDARD_PARALLEL_2, 0.0))); GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_CENTER, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_CENTER, 0.0))); GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LONGITUDE_OF_CENTER, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LONGITUDE_OF_CENTER, 0.0))); GTIFKeySet( psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, @@ -2662,12 +2725,12 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_AzimuthalEquidistant); GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_CENTER, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_CENTER, 0.0))); GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LONGITUDE_OF_CENTER, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LONGITUDE_OF_CENTER, 0.0))); GTIFKeySet( psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, @@ -2689,12 +2752,12 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_MillerCylindrical); GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_CENTER, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_CENTER, 0.0))); GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LONGITUDE_OF_CENTER, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LONGITUDE_OF_CENTER, 0.0))); GTIFKeySet( psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, @@ -2716,16 +2779,16 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_Equirectangular); GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_ORIGIN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_ORIGIN, 0.0))); GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_CENTRAL_MERIDIAN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_CENTRAL_MERIDIAN, 0.0))); GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_STANDARD_PARALLEL_1, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_STANDARD_PARALLEL_1, 0.0))); GTIFKeySet( psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, @@ -2746,12 +2809,12 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_Gnomonic); GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_ORIGIN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_ORIGIN, 0.0))); GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_CENTRAL_MERIDIAN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_CENTRAL_MERIDIAN, 0.0))); GTIFKeySet( psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, @@ -2773,12 +2836,12 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_LambertAzimEqualArea); GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_CENTER, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_CENTER, 0.0))); GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LONGITUDE_OF_CENTER, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LONGITUDE_OF_CENTER, 0.0))); GTIFKeySet( psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, @@ -2800,12 +2863,12 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_Orthographic); GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_ORIGIN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_ORIGIN, 0.0))); GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_CENTRAL_MERIDIAN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_CENTRAL_MERIDIAN, 0.0))); GTIFKeySet( psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, @@ -2827,12 +2890,12 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_NewZealandMapGrid); GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_ORIGIN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_ORIGIN, 0.0))); GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_CENTRAL_MERIDIAN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_CENTRAL_MERIDIAN, 0.0))); GTIFKeySet( psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, @@ -2853,8 +2916,8 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_Robinson); GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LONGITUDE_OF_CENTER, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LONGITUDE_OF_CENTER, 0.0))); GTIFKeySet( psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, @@ -2875,8 +2938,8 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_Sinusoidal); GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LONGITUDE_OF_CENTER, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LONGITUDE_OF_CENTER, 0.0))); GTIFKeySet( psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, @@ -2898,8 +2961,8 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_VanDerGrinten); GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_CENTRAL_MERIDIAN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_CENTRAL_MERIDIAN, 0.0))); GTIFKeySet( psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, @@ -2921,20 +2984,20 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_LambertConfConic_2SP); GTIFKeySet(psGTIF, ProjFalseOriginLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_ORIGIN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_ORIGIN, 0.0))); GTIFKeySet(psGTIF, ProjFalseOriginLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_CENTRAL_MERIDIAN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_CENTRAL_MERIDIAN, 0.0))); GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_STANDARD_PARALLEL_1, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_STANDARD_PARALLEL_1, 0.0))); GTIFKeySet(psGTIF, ProjStdParallel2GeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_STANDARD_PARALLEL_2, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_STANDARD_PARALLEL_2, 0.0))); GTIFKeySet( psGTIF, ProjFalseOriginEastingGeoKey, TYPE_DOUBLE, 1, @@ -2956,12 +3019,12 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_LambertConfConic_1SP); GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_LATITUDE_OF_ORIGIN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_LATITUDE_OF_ORIGIN, 0.0))); GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_CENTRAL_MERIDIAN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_CENTRAL_MERIDIAN, 0.0))); GTIFKeySet( psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1, @@ -2987,12 +3050,12 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, CT_CylindricalEqualArea); GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_CENTRAL_MERIDIAN, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_CENTRAL_MERIDIAN, 0.0))); GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1, - poSRSCompatibleOfWKT1->GetNormProjParm( - SRS_PP_STANDARD_PARALLEL_1, 0.0)); + ConvertAngularParam(poSRSCompatibleOfWKT1->GetNormProjParm( + SRS_PP_STANDARD_PARALLEL_1, 0.0))); GTIFKeySet( psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, @@ -3133,38 +3196,36 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, /* Write angular units. */ /* -------------------------------------------------------------------- */ - const char *angUnitName = ""; if (bHasEllipsoid && (nGCS == KvUserDefined || eVersion == GEOTIFF_VERSION_1_0)) { - double angUnitValue = poSRS->GetAngularUnits(&angUnitName); - if (EQUAL(angUnitName, "Degree")) + if (EQUAL(osAngUnitName.c_str(), "Degree")) GTIFKeySet(psGTIF, GeogAngularUnitsGeoKey, TYPE_SHORT, 1, Angular_Degree); - else if (EQUAL(angUnitName, "arc-second")) + else if (EQUAL(osAngUnitName.c_str(), "arc-second")) GTIFKeySet(psGTIF, GeogAngularUnitsGeoKey, TYPE_SHORT, 1, Angular_Arc_Second); - else if (EQUAL(angUnitName, "arc-minute")) + else if (EQUAL(osAngUnitName.c_str(), "arc-minute")) GTIFKeySet(psGTIF, GeogAngularUnitsGeoKey, TYPE_SHORT, 1, Angular_Arc_Minute); - else if (EQUAL(angUnitName, "grad")) + else if (EQUAL(osAngUnitName.c_str(), "grad")) GTIFKeySet(psGTIF, GeogAngularUnitsGeoKey, TYPE_SHORT, 1, Angular_Grad); - else if (EQUAL(angUnitName, "gon")) + else if (EQUAL(osAngUnitName.c_str(), "gon")) GTIFKeySet(psGTIF, GeogAngularUnitsGeoKey, TYPE_SHORT, 1, Angular_Gon); - else if (EQUAL(angUnitName, "radian")) + else if (EQUAL(osAngUnitName.c_str(), "radian")) GTIFKeySet(psGTIF, GeogAngularUnitsGeoKey, TYPE_SHORT, 1, Angular_Radian); - // else if (EQUAL(angUnitName, "microradian")) + // else if (EQUAL(osAngUnitName.c_str(), "microradian")) // GTIFKeySet(psGTIF, GeogAngularUnitsGeoKey, TYPE_SHORT, 1, // 9109); else { // GeogCitationGeoKey may be rewritten if the gcs is user defined. - oMapAsciiKeys[GeogCitationGeoKey] = angUnitName; + oMapAsciiKeys[GeogCitationGeoKey] = osAngUnitName; GTIFKeySet(psGTIF, GeogAngularUnitSizeGeoKey, TYPE_DOUBLE, 1, - angUnitValue); + dfAngUnitValue); } } @@ -3275,8 +3336,8 @@ int GTIFSetFromOGISDefnEx(GTIF *psGTIF, OGRSpatialReferenceH hSRS, if (nGCS == KvUserDefined && CPLTestBool(CPLGetConfigOption("GTIFF_ESRI_CITATION", "YES"))) { - SetGeogCSCitation(psGTIF, oMapAsciiKeys, poSRS, angUnitName, - nDatum, nSpheroid); + SetGeogCSCitation(psGTIF, oMapAsciiKeys, poSRS, + osAngUnitName.c_str(), nDatum, nSpheroid); } } } diff --git a/deps/libgdal/gdal/frmts/gtiff/gtiffdataset_read.cpp b/deps/libgdal/gdal/frmts/gtiff/gtiffdataset_read.cpp index 9d2dcb8e2..6838293b1 100644 --- a/deps/libgdal/gdal/frmts/gtiff/gtiffdataset_read.cpp +++ b/deps/libgdal/gdal/frmts/gtiff/gtiffdataset_read.cpp @@ -750,11 +750,33 @@ static void CPL_STDCALL ThreadDecompressionFuncErrorHandler( psContext->nYCrbCrSubSampling1); } } - if (psContext->pExtraSamples) + if (poDS->m_nPlanarConfig == PLANARCONFIG_CONTIG) { - TIFFSetField(hTIFFTmp, TIFFTAG_EXTRASAMPLES, - psContext->nExtraSampleCount, - psContext->pExtraSamples); + if (psContext->pExtraSamples) + { + TIFFSetField(hTIFFTmp, TIFFTAG_EXTRASAMPLES, + psContext->nExtraSampleCount, + psContext->pExtraSamples); + } + else + { + const int nSamplesAccountedFor = + poDS->m_nPhotometric == PHOTOMETRIC_RGB ? 3 + : poDS->m_nPhotometric == PHOTOMETRIC_MINISBLACK ? 1 + : 0; + if (nSamplesAccountedFor > 0 && + poDS->m_nSamplesPerPixel > nSamplesAccountedFor) + { + // If the input image is not compliant regarndig ExtraSamples, + // generate a synthetic one to avoid gazillons of warnings + const auto nExtraSampleCount = static_cast( + poDS->m_nSamplesPerPixel - nSamplesAccountedFor); + std::vector anExtraSamples( + nExtraSampleCount, EXTRASAMPLE_UNSPECIFIED); + TIFFSetField(hTIFFTmp, TIFFTAG_EXTRASAMPLES, + nExtraSampleCount, anExtraSamples.data()); + } + } } TIFFWriteCheck(hTIFFTmp, FALSE, "ThreadDecompressionFunc"); TIFFWriteDirectory(hTIFFTmp); diff --git a/deps/libgdal/gdal/frmts/gtiff/gtiffdataset_write.cpp b/deps/libgdal/gdal/frmts/gtiff/gtiffdataset_write.cpp index 12867f2d7..a79d8ee8f 100644 --- a/deps/libgdal/gdal/frmts/gtiff/gtiffdataset_write.cpp +++ b/deps/libgdal/gdal/frmts/gtiff/gtiffdataset_write.cpp @@ -73,6 +73,13 @@ static constexpr const char szPROFILE_BASELINE[] = "BASELINE"; static constexpr const char szPROFILE_GeoTIFF[] = "GeoTIFF"; static constexpr const char szPROFILE_GDALGeoTIFF[] = "GDALGeoTIFF"; +// Due to libgeotiff/xtiff.c declaring TIFFTAG_GEOTIEPOINTS with field_readcount +// and field_writecount == -1 == TIFF_VARIABLE, we are limited to writing +// 65535 values in that tag. That could potentially be overcome by changing the tag +// declaration to using TIFF_VARIABLE2 where the count is a uint32_t. +constexpr int knMAX_GCP_COUNT = + static_cast(std::numeric_limits::max() / 6); + enum { ENDIANNESS_NATIVE, @@ -1714,10 +1721,7 @@ static void DiscardLsb(GByte *pabyBuffer, GPtrDiff_t nBytes, int iBand, if (nBitsPerSample == 8 && nSampleFormat == SAMPLEFORMAT_UINT) { uint8_t nNoDataValue = 0; - if (bHasNoData && - dfNoDataValue >= std::numeric_limits::min() && - dfNoDataValue <= std::numeric_limits::max() && - dfNoDataValue == static_cast(dfNoDataValue)) + if (bHasNoData && GDALIsValueExactAs(dfNoDataValue)) { nNoDataValue = static_cast(dfNoDataValue); } @@ -1799,9 +1803,7 @@ static void DiscardLsb(GByte *pabyBuffer, GPtrDiff_t nBytes, int iBand, else if (nBitsPerSample == 8 && nSampleFormat == SAMPLEFORMAT_INT) { int8_t nNoDataValue = 0; - if (bHasNoData && dfNoDataValue >= std::numeric_limits::min() && - dfNoDataValue <= std::numeric_limits::max() && - dfNoDataValue == static_cast(dfNoDataValue)) + if (bHasNoData && GDALIsValueExactAs(dfNoDataValue)) { nNoDataValue = static_cast(dfNoDataValue); } @@ -1816,10 +1818,7 @@ static void DiscardLsb(GByte *pabyBuffer, GPtrDiff_t nBytes, int iBand, else if (nBitsPerSample == 16 && nSampleFormat == SAMPLEFORMAT_INT) { int16_t nNoDataValue = 0; - if (bHasNoData && - dfNoDataValue >= std::numeric_limits::min() && - dfNoDataValue <= std::numeric_limits::max() && - dfNoDataValue == static_cast(dfNoDataValue)) + if (bHasNoData && GDALIsValueExactAs(dfNoDataValue)) { nNoDataValue = static_cast(dfNoDataValue); } @@ -1834,10 +1833,7 @@ static void DiscardLsb(GByte *pabyBuffer, GPtrDiff_t nBytes, int iBand, else if (nBitsPerSample == 16 && nSampleFormat == SAMPLEFORMAT_UINT) { uint16_t nNoDataValue = 0; - if (bHasNoData && - dfNoDataValue >= std::numeric_limits::min() && - dfNoDataValue <= std::numeric_limits::max() && - dfNoDataValue == static_cast(dfNoDataValue)) + if (bHasNoData && GDALIsValueExactAs(dfNoDataValue)) { nNoDataValue = static_cast(dfNoDataValue); } @@ -1852,10 +1848,7 @@ static void DiscardLsb(GByte *pabyBuffer, GPtrDiff_t nBytes, int iBand, else if (nBitsPerSample == 32 && nSampleFormat == SAMPLEFORMAT_INT) { int32_t nNoDataValue = 0; - if (bHasNoData && - dfNoDataValue >= std::numeric_limits::min() && - dfNoDataValue <= std::numeric_limits::max() && - dfNoDataValue == static_cast(dfNoDataValue)) + if (bHasNoData && GDALIsValueExactAs(dfNoDataValue)) { nNoDataValue = static_cast(dfNoDataValue); } @@ -1870,10 +1863,7 @@ static void DiscardLsb(GByte *pabyBuffer, GPtrDiff_t nBytes, int iBand, else if (nBitsPerSample == 32 && nSampleFormat == SAMPLEFORMAT_UINT) { uint32_t nNoDataValue = 0; - if (bHasNoData && - dfNoDataValue >= std::numeric_limits::min() && - dfNoDataValue <= std::numeric_limits::max() && - dfNoDataValue == static_cast(dfNoDataValue)) + if (bHasNoData && GDALIsValueExactAs(dfNoDataValue)) { nNoDataValue = static_cast(dfNoDataValue); } @@ -1890,13 +1880,7 @@ static void DiscardLsb(GByte *pabyBuffer, GPtrDiff_t nBytes, int iBand, // FIXME: we should not rely on dfNoDataValue when we support native // data type for nodata int64_t nNoDataValue = 0; - if (bHasNoData && - dfNoDataValue >= - static_cast(std::numeric_limits::min()) && - dfNoDataValue <= - static_cast(std::numeric_limits::max()) && - dfNoDataValue == - static_cast(static_cast(dfNoDataValue))) + if (bHasNoData && GDALIsValueExactAs(dfNoDataValue)) { nNoDataValue = static_cast(dfNoDataValue); } @@ -1913,13 +1897,7 @@ static void DiscardLsb(GByte *pabyBuffer, GPtrDiff_t nBytes, int iBand, // FIXME: we should not rely on dfNoDataValue when we support native // data type for nodata uint64_t nNoDataValue = 0; - if (bHasNoData && - dfNoDataValue >= - static_cast(std::numeric_limits::min()) && - dfNoDataValue <= - static_cast(std::numeric_limits::max()) && - dfNoDataValue == - static_cast(static_cast(dfNoDataValue))) + if (bHasNoData && GDALIsValueExactAs(dfNoDataValue)) { nNoDataValue = static_cast(dfNoDataValue); } @@ -2821,7 +2799,7 @@ CPLErr GTiffDataset::CreateOverviewsFromSrcOverviews(GDALDataset *poSrcDS, /* -------------------------------------------------------------------- */ CPLString osMetadata; - GTIFFBuildOverviewMetadata("NONE", this, osMetadata); + GTIFFBuildOverviewMetadata("NONE", this, false, osMetadata); int nCompression; uint16_t nPlanarConfig; @@ -3108,7 +3086,8 @@ CPLErr GTiffDataset::IBuildOverviews(const char *pszResampling, int nOverviews, /* -------------------------------------------------------------------- */ CPLString osMetadata; - GTIFFBuildOverviewMetadata(pszResampling, this, osMetadata); + const bool bIsForMaskBand = nBands == 1 && GetRasterBand(1)->IsMaskBand(); + GTIFFBuildOverviewMetadata(pszResampling, this, bIsForMaskBand, osMetadata); int nCompression; uint16_t nPlanarConfig; @@ -3695,7 +3674,8 @@ void GTiffDataset::WriteGeoTIFFInfo() else if (CPLFetchBool(m_papszCreationOptions, "WORLDFILE", false)) GDALWriteWorldFile(m_pszFilename, "wld", m_adfGeoTransform); } - else if (GetGCPCount() > 0) + else if (GetGCPCount() > 0 && GetGCPCount() <= knMAX_GCP_COUNT && + m_eProfile != GTiffProfile::BASELINE) { m_bNeedsRewrite = true; @@ -3719,9 +3699,8 @@ void GTiffDataset::WriteGeoTIFFInfo() } } - if (m_eProfile != GTiffProfile::BASELINE) - TIFFSetField(m_hTIFF, TIFFTAG_GEOTIEPOINTS, 6 * GetGCPCount(), - padfTiePoints); + TIFFSetField(m_hTIFF, TIFFTAG_GEOTIEPOINTS, 6 * GetGCPCount(), + padfTiePoints); CPLFree(padfTiePoints); } @@ -8463,7 +8442,6 @@ CPLErr GTiffDataset::SetGCPs(int nGCPCountIn, const GDAL_GCP *pasGCPListIn, m_bGeoTransformValid = false; m_bForceUnsetGTOrGCPs = true; } - if ((m_eProfile == GTiffProfile::BASELINE) && (GetPamFlags() & GPF_DISABLED) == 0) { @@ -8471,7 +8449,21 @@ CPLErr GTiffDataset::SetGCPs(int nGCPCountIn, const GDAL_GCP *pasGCPListIn, } else { - if (GDALPamDataset::GetGCPCount() > 0) + if (nGCPCountIn > knMAX_GCP_COUNT) + { + if (GDALPamDataset::GetGCPCount() == 0 && !m_aoGCPs.empty()) + { + m_bForceUnsetGTOrGCPs = true; + } + ReportError(CE_Warning, CPLE_AppDefined, + "Trying to write %d GCPs, whereas the maximum " + "supported in GeoTIFF tag is %d. " + "Falling back to writing them to PAM", + nGCPCountIn, knMAX_GCP_COUNT); + eErr = GDALPamDataset::SetGCPs(nGCPCountIn, pasGCPListIn, + poGCPSRS); + } + else if (GDALPamDataset::GetGCPCount() > 0) { // Cancel any existing GCPs from PAM file. GDALPamDataset::SetGCPs( diff --git a/deps/libgdal/gdal/frmts/gtiff/gtiffrasterband_write.cpp b/deps/libgdal/gdal/frmts/gtiff/gtiffrasterband_write.cpp index de8d09e69..0b7ee7dc8 100644 --- a/deps/libgdal/gdal/frmts/gtiff/gtiffrasterband_write.cpp +++ b/deps/libgdal/gdal/frmts/gtiff/gtiffrasterband_write.cpp @@ -34,6 +34,7 @@ #include #include "cpl_vsi_virtual.h" +#include "gdal_priv_templates.hpp" #include "gtiff.h" #include "tifvsi.h" @@ -705,6 +706,33 @@ CPLErr GTiffRasterBand::SetColorTable(GDALColorTable *poCT) CPLErr GTiffRasterBand::SetNoDataValue(double dfNoData) { + const auto SetNoDataMembers = [this, dfNoData]() + { + m_bNoDataSet = true; + m_dfNoDataValue = dfNoData; + + m_poGDS->m_bNoDataSet = true; + m_poGDS->m_dfNoDataValue = dfNoData; + + if (eDataType == GDT_Int64 && GDALIsValueExactAs(dfNoData)) + { + m_bNoDataSetAsInt64 = true; + m_nNoDataValueInt64 = static_cast(dfNoData); + + m_poGDS->m_bNoDataSetAsInt64 = true; + m_poGDS->m_nNoDataValueInt64 = static_cast(dfNoData); + } + else if (eDataType == GDT_UInt64 && + GDALIsValueExactAs(dfNoData)) + { + m_bNoDataSetAsUInt64 = true; + m_nNoDataValueUInt64 = static_cast(dfNoData); + + m_poGDS->m_bNoDataSetAsUInt64 = true; + m_poGDS->m_nNoDataValueUInt64 = static_cast(dfNoData); + } + }; + m_poGDS->LoadGeoreferencingAndPamIfNeeded(); if (m_poGDS->m_bNoDataSet && @@ -713,8 +741,7 @@ CPLErr GTiffRasterBand::SetNoDataValue(double dfNoData) { ResetNoDataValues(false); - m_bNoDataSet = true; - m_dfNoDataValue = dfNoData; + SetNoDataMembers(); return CE_None; } @@ -767,11 +794,7 @@ CPLErr GTiffRasterBand::SetNoDataValue(double dfNoData) { ResetNoDataValues(true); - m_poGDS->m_bNoDataSet = true; - m_poGDS->m_dfNoDataValue = dfNoData; - - m_bNoDataSet = true; - m_dfNoDataValue = dfNoData; + SetNoDataMembers(); } return eErr; diff --git a/deps/libgdal/gdal/frmts/gtiff/libgeotiff/geo_normalize.c b/deps/libgdal/gdal/frmts/gtiff/libgeotiff/geo_normalize.c index 11517462c..f16b67be4 100644 --- a/deps/libgdal/gdal/frmts/gtiff/libgeotiff/geo_normalize.c +++ b/deps/libgdal/gdal/frmts/gtiff/libgeotiff/geo_normalize.c @@ -2241,15 +2241,16 @@ static void GTIFFetchProjParms( GTIF * psGTIF, GTIFDefn * psDefn ) break; } + for( int iParam = 0; iParam < psDefn->nParms; iParam++ ) + { + switch( psDefn->ProjParmId[iParam] ) + { + /* -------------------------------------------------------------------- */ /* Normalize any linear parameters into meters. In GeoTIFF */ /* the linear projection parameter tags are normally in the */ /* units of the coordinate system described. */ /* -------------------------------------------------------------------- */ - for( int iParam = 0; iParam < psDefn->nParms; iParam++ ) - { - switch( psDefn->ProjParmId[iParam] ) - { case ProjFalseEastingGeoKey: case ProjFalseNorthingGeoKey: case ProjFalseOriginEastingGeoKey: @@ -2263,6 +2264,30 @@ static void GTIFFetchProjParms( GTIF * psGTIF, GTIFDefn * psDefn ) } break; +/* -------------------------------------------------------------------- */ +/* Normalize any angular parameters into degrees. In GeoTIFF */ +/* the angular projection parameter tags are normally in the */ +/* units of GeogAngularUnit. Note: this conversion is only done */ +/* since libgeotiff 1.7.4 */ +/* -------------------------------------------------------------------- */ + + case ProjStdParallel1GeoKey: + case ProjStdParallel2GeoKey: + case ProjNatOriginLongGeoKey: + case ProjNatOriginLatGeoKey: + case ProjFalseOriginLongGeoKey: + case ProjFalseOriginLatGeoKey: + case ProjCenterLongGeoKey: + case ProjCenterLatGeoKey: + case ProjStraightVertPoleLongGeoKey: + case ProjRectifiedGridAngleGeoKey: + if( psDefn->UOMAngleInDegrees != 0 + && psDefn->UOMAngleInDegrees != 1.0 ) + { + psDefn->ProjParm[iParam] *= psDefn->UOMAngleInDegrees; + } + break; + default: break; } diff --git a/deps/libgdal/gdal/frmts/gtiff/libgeotiff/geo_normalize.h b/deps/libgdal/gdal/frmts/gtiff/libgeotiff/geo_normalize.h index 87dd22c7e..79f588c81 100644 --- a/deps/libgdal/gdal/frmts/gtiff/libgeotiff/geo_normalize.h +++ b/deps/libgdal/gdal/frmts/gtiff/libgeotiff/geo_normalize.h @@ -121,9 +121,15 @@ typedef struct { int nParms; /** Projection parameter value. The identify of this parameter - is established from the corresponding entry in ProjParmId. The - value will be measured in meters, or decimal degrees if it is a - linear or angular measure. */ + is established from the corresponding entry in ProjParmId. + In GeoTIFF keys, the values of the projection parameters are expressed + in the units of ProjLinearUnitsGeoKey (for linear measures) or + GeogAngularUnitsGeoKey (for angular measures). + However, the value returned in ProjParam[] will be normalized to meters + or decimal degrees. + Note: until libgeotiff 1.7.3, the conversion to degrees for angular + measures was *not* done when ProjCoordTransGeoKey is present. + */ double ProjParm[MAX_GTIF_PROJPARMS]; /** Projection parameter identifier. For example ProjFalseEastingGeoKey. diff --git a/deps/libgdal/gdal/frmts/gtiff/libgeotiff/geotiff.h b/deps/libgdal/gdal/frmts/gtiff/libgeotiff/geotiff.h index 29f22917f..75de593c8 100644 --- a/deps/libgdal/gdal/frmts/gtiff/libgeotiff/geotiff.h +++ b/deps/libgdal/gdal/frmts/gtiff/libgeotiff/geotiff.h @@ -47,7 +47,7 @@ #define GEOTIFF_SPEC_1_1_MINOR_REVISION 1 /* Library version */ -#define LIBGEOTIFF_VERSION 1710 +#define LIBGEOTIFF_VERSION 1740 #include "geo_config.h" #include "geokeys.h" diff --git a/deps/libgdal/gdal/frmts/gtiff/libgeotiff/geotiff_proj4.c b/deps/libgdal/gdal/frmts/gtiff/libgeotiff/geotiff_proj4.c index 8e3812059..9d25a7c1a 100644 --- a/deps/libgdal/gdal/frmts/gtiff/libgeotiff/geotiff_proj4.c +++ b/deps/libgdal/gdal/frmts/gtiff/libgeotiff/geotiff_proj4.c @@ -85,7 +85,7 @@ static char **OSRProj4Tokenize( const char *pszFull ) if( pszFull == NULL ) return NULL; - char **papszTokens = (char **) calloc(sizeof(char*),nMaxTokens); + char **papszTokens = (char **) calloc(nMaxTokens, sizeof(char*)); char *pszFullWrk = CPLStrdup(pszFull); diff --git a/deps/libgdal/gdal/frmts/gtiff/libtiff/tif_hash_set.c b/deps/libgdal/gdal/frmts/gtiff/libtiff/tif_hash_set.c index 9792c63f4..81dea3fcf 100644 --- a/deps/libgdal/gdal/frmts/gtiff/libtiff/tif_hash_set.c +++ b/deps/libgdal/gdal/frmts/gtiff/libtiff/tif_hash_set.c @@ -146,7 +146,7 @@ TIFFHashSet *TIFFHashSetNew(TIFFHashSetHashFunc fnHashFunc, set->fnEqualFunc = fnEqualFunc ? fnEqualFunc : TIFFHashSetEqualPointer; set->fnFreeEltFunc = fnFreeEltFunc; set->nSize = 0; - set->tabList = (TIFFList **)(calloc(sizeof(TIFFList *), 53)); + set->tabList = (TIFFList **)(calloc(53, sizeof(TIFFList *))); if (set->tabList == NULL) { free(set); @@ -367,7 +367,7 @@ static bool TIFFHashSetRehash(TIFFHashSet *set) { int nNewAllocatedSize = anPrimes[set->nIndiceAllocatedSize]; TIFFList **newTabList = - (TIFFList **)(calloc(sizeof(TIFFList *), nNewAllocatedSize)); + (TIFFList **)(calloc(nNewAllocatedSize, sizeof(TIFFList *))); if (newTabList == NULL) return false; #ifdef HASH_DEBUG diff --git a/deps/libgdal/gdal/frmts/hdf4/CMakeLists.txt b/deps/libgdal/gdal/frmts/hdf4/CMakeLists.txt index fccc92138..3dc9521e2 100644 --- a/deps/libgdal/gdal/frmts/hdf4/CMakeLists.txt +++ b/deps/libgdal/gdal/frmts/hdf4/CMakeLists.txt @@ -18,7 +18,8 @@ set_property(SOURCE hdf-eos/EHapi.c hdf-eos/GDapi.c hdf-eos/SWapi.c PROPERTY SKI add_gdal_driver(TARGET gdal_HDF4 SOURCES ${_SOURCES} CORE_SOURCES hdf4drivercore.cpp - PLUGIN_CAPABLE) + PLUGIN_CAPABLE + NO_SHARED_SYMBOL_WITH_CORE) unset(_SOURCES) if(NOT TARGET gdal_HDF4) diff --git a/deps/libgdal/gdal/frmts/hdf4/hdf4drivercore.h b/deps/libgdal/gdal/frmts/hdf4/hdf4drivercore.h index 798be0263..eb99e6fdf 100644 --- a/deps/libgdal/gdal/frmts/hdf4/hdf4drivercore.h +++ b/deps/libgdal/gdal/frmts/hdf4/hdf4drivercore.h @@ -35,12 +35,22 @@ constexpr const char *HDF4_DRIVER_NAME = "HDF4"; constexpr const char *HDF4_IMAGE_DRIVER_NAME = "HDF4Image"; -int CPL_DLL HDF4DatasetIdentify(GDALOpenInfo *poOpenInfo); +#define HDF4DatasetIdentify PLUGIN_SYMBOL_NAME(HDF4DatasetIdentify) -int CPL_DLL HDF4ImageDatasetIdentify(GDALOpenInfo *poOpenInfo); +#define HDF4ImageDatasetIdentify PLUGIN_SYMBOL_NAME(HDF4ImageDatasetIdentify) -void CPL_DLL HDF4DriverSetCommonMetadata(GDALDriver *poDriver); +#define HDF4DriverSetCommonMetadata \ + PLUGIN_SYMBOL_NAME(HDF4DriverSetCommonMetadata) -void CPL_DLL HDF4ImageDriverSetCommonMetadata(GDALDriver *poDriver); +#define HDF4ImageDriverSetCommonMetadata \ + PLUGIN_SYMBOL_NAME(HDF4ImageDriverSetCommonMetadata) + +int HDF4DatasetIdentify(GDALOpenInfo *poOpenInfo); + +int HDF4ImageDatasetIdentify(GDALOpenInfo *poOpenInfo); + +void HDF4DriverSetCommonMetadata(GDALDriver *poDriver); + +void HDF4ImageDriverSetCommonMetadata(GDALDriver *poDriver); #endif diff --git a/deps/libgdal/gdal/frmts/hdf5/CMakeLists.txt b/deps/libgdal/gdal/frmts/hdf5/CMakeLists.txt index 85bf48585..284ae9c8d 100644 --- a/deps/libgdal/gdal/frmts/hdf5/CMakeLists.txt +++ b/deps/libgdal/gdal/frmts/hdf5/CMakeLists.txt @@ -21,7 +21,8 @@ set(SOURCE add_gdal_driver(TARGET gdal_HDF5 SOURCES ${SOURCE} CORE_SOURCES hdf5drivercore.cpp - PLUGIN_CAPABLE) + PLUGIN_CAPABLE + NO_SHARED_SYMBOL_WITH_CORE) set(GDAL_DATA_FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/bag_template.xml diff --git a/deps/libgdal/gdal/frmts/hdf5/gh5_convenience.cpp b/deps/libgdal/gdal/frmts/hdf5/gh5_convenience.cpp index 304032e08..e48b5c630 100644 --- a/deps/libgdal/gdal/frmts/hdf5/gh5_convenience.cpp +++ b/deps/libgdal/gdal/frmts/hdf5/gh5_convenience.cpp @@ -26,6 +26,7 @@ * DEALINGS IN THE SOFTWARE. ****************************************************************************/ +#include "cpl_float.h" #include "gh5_convenience.h" /************************************************************************/ @@ -209,6 +210,16 @@ bool GH5_FetchAttribute(hid_t loc_id, const char *pszAttrName, double &dfResult, pszAttrName, static_cast(nVal), dfResult); } } +#ifdef HDF5_HAVE_FLOAT16 + else if (H5Tequal(H5T_NATIVE_FLOAT16, hAttrNativeType)) + { + const uint16_t nVal16 = *((uint16_t *)buf); + const uint32_t nVal32 = CPLHalfToFloat(nVal16); + float fVal; + memcpy(&fVal, &nVal32, sizeof(fVal)); + dfResult = fVal; + } +#endif else if (H5Tequal(H5T_NATIVE_FLOAT, hAttrNativeType)) dfResult = *((float *)buf); else if (H5Tequal(H5T_NATIVE_DOUBLE, hAttrNativeType)) diff --git a/deps/libgdal/gdal/frmts/hdf5/hdf5_api.h b/deps/libgdal/gdal/frmts/hdf5/hdf5_api.h index 013534310..0b3110d2c 100644 --- a/deps/libgdal/gdal/frmts/hdf5/hdf5_api.h +++ b/deps/libgdal/gdal/frmts/hdf5/hdf5_api.h @@ -46,6 +46,10 @@ #include "hdf5.h" +#if defined(H5T_NATIVE_FLOAT16) && defined(H5_HAVE__FLOAT16) +#define HDF5_HAVE_FLOAT16 +#endif + #ifdef _MSC_VER #pragma warning(pop) #endif diff --git a/deps/libgdal/gdal/frmts/hdf5/hdf5dataset.cpp b/deps/libgdal/gdal/frmts/hdf5/hdf5dataset.cpp index 499b8a86c..64c1fea2e 100644 --- a/deps/libgdal/gdal/frmts/hdf5/hdf5dataset.cpp +++ b/deps/libgdal/gdal/frmts/hdf5/hdf5dataset.cpp @@ -44,6 +44,7 @@ #include "cpl_conv.h" #include "cpl_error.h" +#include "cpl_float.h" #include "cpl_string.h" #include "gdal.h" #include "gdal_frmts.h" @@ -201,6 +202,10 @@ GDALDataType HDF5Dataset::GetDataType(hid_t TypeID) return GDT_Unknown; #endif } +#ifdef HDF5_HAVE_FLOAT16 + else if (H5Tequal(H5T_NATIVE_FLOAT16, TypeID)) + return GDT_Float32; +#endif else if (H5Tequal(H5T_NATIVE_FLOAT, TypeID)) return GDT_Float32; else if (H5Tequal(H5T_NATIVE_DOUBLE, TypeID)) @@ -258,6 +263,10 @@ GDALDataType HDF5Dataset::GetDataType(hid_t TypeID) eDataType = GDT_Unknown; #endif } +#ifdef HDF5_HAVE_FLOAT16 + else if (H5Tequal(H5T_NATIVE_FLOAT16, ElemTypeID)) + eDataType = GDT_CFloat32; +#endif else if (H5Tequal(H5T_NATIVE_FLOAT, ElemTypeID)) eDataType = GDT_CFloat32; else if (H5Tequal(H5T_NATIVE_DOUBLE, ElemTypeID)) @@ -272,6 +281,32 @@ GDALDataType HDF5Dataset::GetDataType(hid_t TypeID) return GDT_Unknown; } +/************************************************************************/ +/* IsNativeCFloat16() */ +/************************************************************************/ + +/* static*/ bool HDF5Dataset::IsNativeCFloat16(hid_t hDataType) +{ +#ifdef HDF5_HAVE_FLOAT16 + // For complex the compound type must contain 2 elements + if (H5Tget_class(hDataType) != H5T_COMPOUND || + H5Tget_nmembers(hDataType) != 2) + return false; + + // For complex the native types of both elements should be the same + hid_t ElemTypeID = H5Tget_member_type(hDataType, 0); + hid_t Elem2TypeID = H5Tget_member_type(hDataType, 1); + const bool bRet = H5Tequal(ElemTypeID, H5T_NATIVE_FLOAT16) > 0 && + H5Tequal(Elem2TypeID, H5T_NATIVE_FLOAT16) > 0; + H5Tclose(ElemTypeID); + H5Tclose(Elem2TypeID); + return bRet; +#else + CPL_IGNORE_RET_VAL(hDataType); + return false; +#endif +} + /************************************************************************/ /* GetDataTypeName() */ /* */ @@ -304,6 +339,10 @@ const char *HDF5Dataset::GetDataTypeName(hid_t TypeID) return "32/64-bit integer"; else if (H5Tequal(H5T_NATIVE_ULONG, TypeID)) return "32/64-bit unsigned integer"; +#ifdef HDF5_HAVE_FLOAT16 + else if (H5Tequal(H5T_NATIVE_FLOAT16, TypeID)) + return "16-bit floating-point"; +#endif else if (H5Tequal(H5T_NATIVE_FLOAT, TypeID)) return "32-bit floating-point"; else if (H5Tequal(H5T_NATIVE_DOUBLE, TypeID)) @@ -348,6 +387,13 @@ const char *HDF5Dataset::GetDataTypeName(hid_t TypeID) H5Tclose(ElemTypeID); return "complex, 32/64-bit integer"; } +#ifdef HDF5_HAVE_FLOAT16 + else if (H5Tequal(H5T_NATIVE_FLOAT16, ElemTypeID)) + { + H5Tclose(ElemTypeID); + return "complex, 16-bit floating-point"; + } +#endif else if (H5Tequal(H5T_NATIVE_FLOAT, ElemTypeID)) { H5Tclose(ElemTypeID); @@ -1132,6 +1178,28 @@ static herr_t HDF5AttrIterate(hid_t hH5ObjID, const char *pszAttrName, psContext->m_osValue += szData; } } +#ifdef HDF5_HAVE_FLOAT16 + else if (H5Tequal(H5T_NATIVE_FLOAT16, hAttrNativeType) > 0) + { + for (hsize_t i = 0; i < nAttrElmts; i++) + { + const uint16_t nVal16 = static_cast(buf)[i]; + const uint32_t nVal32 = CPLHalfToFloat(nVal16); + float fVal; + memcpy(&fVal, &nVal32, sizeof(fVal)); + CPLsnprintf(szData, nDataLen, "%.8g", fVal); + if (psContext->m_osValue.size() > MAX_METADATA_LEN) + { + CPLError(CE_Warning, CPLE_OutOfMemory, + "Header data too long. Truncated"); + break; + } + if (i > 0) + psContext->m_osValue += ' '; + psContext->m_osValue += szData; + } + } +#endif else if (H5Tequal(H5T_NATIVE_FLOAT, hAttrNativeType) > 0) { for (hsize_t i = 0; i < nAttrElmts; i++) diff --git a/deps/libgdal/gdal/frmts/hdf5/hdf5dataset.h b/deps/libgdal/gdal/frmts/hdf5/hdf5dataset.h index dc9245b4c..646f7c6b6 100644 --- a/deps/libgdal/gdal/frmts/hdf5/hdf5dataset.h +++ b/deps/libgdal/gdal/frmts/hdf5/hdf5dataset.h @@ -240,8 +240,6 @@ class HDF5Dataset CPL_NON_FINAL : public GDALPamDataset char *CreatePath(HDF5GroupObjects *); static void DestroyH5Objects(HDF5GroupObjects *); - static const char *GetDataTypeName(hid_t); - /** * Reads an array of double attributes from the HDF5 metadata. * It reads the attributes directly on its binary form directly, @@ -275,6 +273,8 @@ class HDF5Dataset CPL_NON_FINAL : public GDALPamDataset static std::shared_ptr OpenGroup( const std::shared_ptr &poSharedResources); + static bool IsNativeCFloat16(hid_t hDataType); + static const char *GetDataTypeName(hid_t); static GDALDataType GetDataType(hid_t); }; diff --git a/deps/libgdal/gdal/frmts/hdf5/hdf5drivercore.h b/deps/libgdal/gdal/frmts/hdf5/hdf5drivercore.h index 7490b394b..f779ba154 100644 --- a/deps/libgdal/gdal/frmts/hdf5/hdf5drivercore.h +++ b/deps/libgdal/gdal/frmts/hdf5/hdf5drivercore.h @@ -43,28 +43,47 @@ constexpr const char *S104_DRIVER_NAME = "S104"; constexpr const char *S111_DRIVER_NAME = "S111"; -int CPL_DLL HDF5DatasetIdentify(GDALOpenInfo *poOpenInfo); +#define HDF5DatasetIdentify PLUGIN_SYMBOL_NAME(HDF5DatasetIdentify) +#define HDF5ImageDatasetIdentify PLUGIN_SYMBOL_NAME(HDF5ImageDatasetIdentify) +#define BAGDatasetIdentify PLUGIN_SYMBOL_NAME(BAGDatasetIdentify) +#define S102DatasetIdentify PLUGIN_SYMBOL_NAME(S102DatasetIdentify) +#define S104DatasetIdentify PLUGIN_SYMBOL_NAME(S104DatasetIdentify) +#define S111DatasetIdentify PLUGIN_SYMBOL_NAME(S111DatasetIdentify) +#define HDF5DriverSetCommonMetadata \ + PLUGIN_SYMBOL_NAME(HDF5DriverSetCommonMetadata) +#define HDF5ImageDriverSetCommonMetadata \ + PLUGIN_SYMBOL_NAME(HDF5ImageDriverSetCommonMetadata) +#define BAGDriverSetCommonMetadata \ + PLUGIN_SYMBOL_NAME(BAGDriverSetCommonMetadata) +#define S102DriverSetCommonMetadata \ + PLUGIN_SYMBOL_NAME(S102DriverSetCommonMetadata) +#define S104DriverSetCommonMetadata \ + PLUGIN_SYMBOL_NAME(S104DriverSetCommonMetadata) +#define S111DriverSetCommonMetadata \ + PLUGIN_SYMBOL_NAME(S111DriverSetCommonMetadata) -int CPL_DLL HDF5ImageDatasetIdentify(GDALOpenInfo *poOpenInfo); +int HDF5DatasetIdentify(GDALOpenInfo *poOpenInfo); -int CPL_DLL BAGDatasetIdentify(GDALOpenInfo *poOpenInfo); +int HDF5ImageDatasetIdentify(GDALOpenInfo *poOpenInfo); -int CPL_DLL S102DatasetIdentify(GDALOpenInfo *poOpenInfo); +int BAGDatasetIdentify(GDALOpenInfo *poOpenInfo); -int CPL_DLL S104DatasetIdentify(GDALOpenInfo *poOpenInfo); +int S102DatasetIdentify(GDALOpenInfo *poOpenInfo); -int CPL_DLL S111DatasetIdentify(GDALOpenInfo *poOpenInfo); +int S104DatasetIdentify(GDALOpenInfo *poOpenInfo); -void CPL_DLL HDF5DriverSetCommonMetadata(GDALDriver *poDriver); +int S111DatasetIdentify(GDALOpenInfo *poOpenInfo); -void CPL_DLL HDF5ImageDriverSetCommonMetadata(GDALDriver *poDriver); +void HDF5DriverSetCommonMetadata(GDALDriver *poDriver); -void CPL_DLL BAGDriverSetCommonMetadata(GDALDriver *poDriver); +void HDF5ImageDriverSetCommonMetadata(GDALDriver *poDriver); -void CPL_DLL S102DriverSetCommonMetadata(GDALDriver *poDriver); +void BAGDriverSetCommonMetadata(GDALDriver *poDriver); -void CPL_DLL S104DriverSetCommonMetadata(GDALDriver *poDriver); +void S102DriverSetCommonMetadata(GDALDriver *poDriver); -void CPL_DLL S111DriverSetCommonMetadata(GDALDriver *poDriver); +void S104DriverSetCommonMetadata(GDALDriver *poDriver); + +void S111DriverSetCommonMetadata(GDALDriver *poDriver); #endif diff --git a/deps/libgdal/gdal/frmts/hdf5/hdf5imagedataset.cpp b/deps/libgdal/gdal/frmts/hdf5/hdf5imagedataset.cpp index f25d1ea2d..37364c3be 100644 --- a/deps/libgdal/gdal/frmts/hdf5/hdf5imagedataset.cpp +++ b/deps/libgdal/gdal/frmts/hdf5/hdf5imagedataset.cpp @@ -29,6 +29,7 @@ #include "hdf5_api.h" +#include "cpl_float.h" #include "cpl_string.h" #include "gdal_frmts.h" #include "gdal_pam.h" @@ -72,9 +73,10 @@ class HDF5ImageDataset final : public HDF5Dataset int dimensions; hid_t dataset_id; hid_t dataspace_id; - hsize_t size; - hid_t datatype; hid_t native; +#ifdef HDF5_HAVE_FLOAT16 + bool m_bConvertFromFloat16 = false; +#endif Hdf5ProductType iSubdatasetType; HDF5CSKProductEnum iCSKProductType; double adfGeoTransform[6]; @@ -209,9 +211,9 @@ class HDF5ImageDataset final : public HDF5Dataset /************************************************************************/ HDF5ImageDataset::HDF5ImageDataset() : dims(nullptr), maxdims(nullptr), poH5Objects(nullptr), ndims(0), - dimensions(0), dataset_id(-1), dataspace_id(-1), size(0), datatype(-1), - native(-1), iSubdatasetType(UNKNOWN_PRODUCT), - iCSKProductType(PROD_UNKNOWN), bHasGeoTransform(false) + dimensions(0), dataset_id(-1), dataspace_id(-1), native(-1), + iSubdatasetType(UNKNOWN_PRODUCT), iCSKProductType(PROD_UNKNOWN), + bHasGeoTransform(false) { m_oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); m_oGCPSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); @@ -236,8 +238,6 @@ HDF5ImageDataset::~HDF5ImageDataset() H5Dclose(dataset_id); if (dataspace_id > 0) H5Sclose(dataspace_id); - if (datatype > 0) - H5Tclose(datatype); if (native > 0) H5Tclose(native); @@ -465,6 +465,42 @@ CPLErr HDF5ImageRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, return CE_Failure; } +#ifdef HDF5_HAVE_FLOAT16 + if (eDataType == GDT_Float32 && poGDS->m_bConvertFromFloat16) + { + for (size_t i = static_cast(nBlockXSize) * nBlockYSize; i > 0; + /* do nothing */) + { + --i; + uint16_t nVal16; + memcpy(&nVal16, static_cast(pImage) + i, + sizeof(nVal16)); + const uint32_t nVal32 = CPLHalfToFloat(nVal16); + float fVal; + memcpy(&fVal, &nVal32, sizeof(fVal)); + *(static_cast(pImage) + i) = fVal; + } + } + else if (eDataType == GDT_CFloat32 && poGDS->m_bConvertFromFloat16) + { + for (size_t i = static_cast(nBlockXSize) * nBlockYSize; i > 0; + /* do nothing */) + { + --i; + for (int j = 1; j >= 0; --j) + { + uint16_t nVal16; + memcpy(&nVal16, static_cast(pImage) + 2 * i + j, + sizeof(nVal16)); + const uint32_t nVal32 = CPLHalfToFloat(nVal16); + float fVal; + memcpy(&fVal, &nVal32, sizeof(fVal)); + *(static_cast(pImage) + 2 * i + j) = fVal; + } + } + } +#endif + return CE_None; } @@ -482,6 +518,15 @@ CPLErr HDF5ImageRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff, { HDF5ImageDataset *poGDS = static_cast(poDS); +#ifdef HDF5_HAVE_FLOAT16 + if (poGDS->m_bConvertFromFloat16) + { + return GDALPamRasterBand::IRasterIO( + eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize, + eBufType, nPixelSpace, nLineSpace, psExtraArg); + } +#endif + const bool bIsBandInterleavedData = poGDS->ndims == 3 && poGDS->m_nOtherDimIndex == 0 && poGDS->GetYIndex() == 1 && poGDS->GetXIndex() == 2; @@ -763,6 +808,16 @@ CPLErr HDF5ImageDataset::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff, GDALRasterIOExtraArg *psExtraArg) { +#ifdef HDF5_HAVE_FLOAT16 + if (m_bConvertFromFloat16) + { + return HDF5Dataset::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, + pData, nBufXSize, nBufYSize, eBufType, + nBandCount, panBandMap, nPixelSpace, + nLineSpace, nBandSpace, psExtraArg); + } +#endif + const auto IsConsecutiveBands = [](const int *panVals, int nCount) { for (int i = 1; i < nCount; ++i) @@ -1023,9 +1078,25 @@ GDALDataset *HDF5ImageDataset::Open(GDALOpenInfo *poOpenInfo) static_cast(CPLCalloc(poDS->ndims, sizeof(hsize_t))); poDS->dimensions = H5Sget_simple_extent_dims(poDS->dataspace_id, poDS->dims, poDS->maxdims); - poDS->datatype = H5Dget_type(poDS->dataset_id); - poDS->size = H5Tget_size(poDS->datatype); - poDS->native = H5Tget_native_type(poDS->datatype, H5T_DIR_ASCEND); + auto datatype = H5Dget_type(poDS->dataset_id); + poDS->native = H5Tget_native_type(datatype, H5T_DIR_ASCEND); + H5Tclose(datatype); + + const auto eGDALDataType = poDS->GetDataType(poDS->native); + if (eGDALDataType == GDT_Unknown) + { + CPLError(CE_Failure, CPLE_AppDefined, "Unhandled HDF5 data type"); + delete poDS; + return nullptr; + } + +#ifdef HDF5_HAVE_FLOAT16 + if (H5Tequal(H5T_NATIVE_FLOAT16, poDS->native) || + IsNativeCFloat16(poDS->native)) + { + poDS->m_bConvertFromFloat16 = true; + } +#endif // CSK code in IdentifyProductType() and CreateProjections() // uses dataset metadata. @@ -1155,34 +1226,53 @@ GDALDataset *HDF5ImageDataset::Open(GDALOpenInfo *poOpenInfo) { HDF5Dataset::CreateMetadata(poDS->m_hHDF5, poDS->poH5Objects, H5G_DATASET, false, aosMetadata); - if (nBands > 1) + if (nBands > 1 && poDS->nRasterXSize != nBands && + poDS->nRasterYSize != nBands) { - // Logic specific of Planet data cubes with per-band metadata items - static const struct - { - const char *pszSrcName; - const char *pszDstName; - } asItems[] = { - {"calibration_coefficients", "calibration_coefficient"}, - {"center_wavelengths", "center_wavelength"}, - {"fwhm", "fwhm"}, - {"bad_band_list", "bad_band"}, - }; - - for (const auto &sItem : asItems) + // Heuristics to detect non-scalar attributes, that are intended + // to be attached to a specific band. + const CPLStringList aosMetadataDup(aosMetadata); + for (const auto &[pszKey, pszValue] : + cpl::IterateNameValue(aosMetadataDup)) { - const char *pszVal = - aosMetadata.FetchNameValue(sItem.pszSrcName); - if (pszVal) + const hid_t hAttrID = H5Aopen_name(poDS->dataset_id, pszKey); + const hid_t hAttrSpace = H5Aget_space(hAttrID); + if (H5Sget_simple_extent_ndims(hAttrSpace) == 1 && + H5Sget_simple_extent_npoints(hAttrSpace) == nBands) { - CPLStringList aosTokens(CSLTokenizeString2(pszVal, " ", 0)); + CPLStringList aosTokens( + CSLTokenizeString2(pszValue, " ", 0)); if (aosTokens.size() == nBands) { - oMapBandSpecificMetadata[sItem.pszDstName] = + std::string osAttrName(pszKey); + if (osAttrName.size() > strlen("_coefficients") && + osAttrName.substr(osAttrName.size() - + strlen("_coefficients")) == + "_coefficients") + { + osAttrName.pop_back(); + } + else if (osAttrName.size() > strlen("_wavelengths") && + osAttrName.substr(osAttrName.size() - + strlen("_wavelengths")) == + "_wavelengths") + { + osAttrName.pop_back(); + } + else if (osAttrName.size() > strlen("_list") && + osAttrName.substr(osAttrName.size() - + strlen("_list")) == "_list") + { + osAttrName.resize(osAttrName.size() - + strlen("_list")); + } + oMapBandSpecificMetadata[osAttrName] = std::move(aosTokens); - aosMetadata.SetNameValue(sItem.pszSrcName, nullptr); + aosMetadata.SetNameValue(pszKey, nullptr); } } + H5Sclose(hAttrSpace); + H5Aclose(hAttrID); } } } @@ -1241,8 +1331,8 @@ GDALDataset *HDF5ImageDataset::Open(GDALOpenInfo *poOpenInfo) for (int i = 0; i < nBands; i++) { - HDF5ImageRasterBand *const poBand = new HDF5ImageRasterBand( - poDS, i + 1, poDS->GetDataType(poDS->native)); + HDF5ImageRasterBand *const poBand = + new HDF5ImageRasterBand(poDS, i + 1, eGDALDataType); poDS->SetBand(i + 1, poBand); diff --git a/deps/libgdal/gdal/frmts/hdf5/hdf5multidim.cpp b/deps/libgdal/gdal/frmts/hdf5/hdf5multidim.cpp index fa27ff79a..f5a0704c4 100644 --- a/deps/libgdal/gdal/frmts/hdf5/hdf5multidim.cpp +++ b/deps/libgdal/gdal/frmts/hdf5/hdf5multidim.cpp @@ -29,6 +29,8 @@ #include "hdf5eosparser.h" #include "s100.h" +#include "cpl_float.h" + #include #include #include @@ -159,7 +161,16 @@ BuildDataType(hid_t hDataType, bool &bHasString, bool &bNonNativeDataType, const auto klass = H5Tget_class(hDataType); GDALDataType eDT = ::HDF5Dataset::GetDataType(hDataType); if (eDT != GDT_Unknown) + { +#ifdef HDF5_HAVE_FLOAT16 + if (H5Tequal(hDataType, H5T_NATIVE_FLOAT16) || + HDF5Dataset::IsNativeCFloat16(hDataType)) + { + bNonNativeDataType = true; + } +#endif return GDALExtendedDataType::Create(eDT); + } else if (klass == H5T_STRING) { bHasString = true; @@ -2326,9 +2337,44 @@ static void CopyValue(const GByte *pabySrcBuffer, hid_t hSrcDataType, { if (dstDataType.GetClass() != GEDTC_COMPOUND) { + const auto eSrcDataType = ::HDF5Dataset::GetDataType(hSrcDataType); // Typically source is complex data type - auto srcDataType(GDALExtendedDataType::Create( - ::HDF5Dataset::GetDataType(hSrcDataType))); +#ifdef HDF5_HAVE_FLOAT16 + if (eSrcDataType == GDT_CFloat32 && + ::HDF5Dataset::IsNativeCFloat16(hSrcDataType)) + { + if (dstDataType.GetNumericDataType() == GDT_CFloat32) + { + for (int j = 0; j <= 1; ++j) + { + uint16_t nVal16; + memcpy(&nVal16, pabySrcBuffer + j * sizeof(nVal16), + sizeof(nVal16)); + const uint32_t nVal32 = CPLHalfToFloat(nVal16); + memcpy(pabyDstBuffer + j * sizeof(float), &nVal32, + sizeof(nVal32)); + } + } + else if (dstDataType.GetNumericDataType() == GDT_CFloat64) + { + for (int j = 0; j <= 1; ++j) + { + uint16_t nVal16; + memcpy(&nVal16, pabySrcBuffer + j * sizeof(nVal16), + sizeof(nVal16)); + const uint32_t nVal32 = CPLHalfToFloat(nVal16); + float fVal; + memcpy(&fVal, &nVal32, sizeof(fVal)); + double dfVal = fVal; + memcpy(pabyDstBuffer + j * sizeof(double), &dfVal, + sizeof(dfVal)); + } + } + return; + } + +#endif + auto srcDataType(GDALExtendedDataType::Create(eSrcDataType)); if (srcDataType.GetClass() == GEDTC_NUMERIC && srcDataType.GetNumericDataType() != GDT_Unknown) { @@ -2364,6 +2410,19 @@ static void CopyValue(const GByte *pabySrcBuffer, hid_t hSrcDataType, CopyValue(pabySrcBuffer, hParent, pabyDstBuffer, dstDataType, {}); H5Tclose(hParent); } +#ifdef HDF5_HAVE_FLOAT16 + else if (H5Tequal(hSrcDataType, H5T_NATIVE_FLOAT16)) + { + uint16_t nVal16; + memcpy(&nVal16, pabySrcBuffer, sizeof(nVal16)); + const uint32_t nVal32 = CPLHalfToFloat(nVal16); + float fVal; + memcpy(&fVal, &nVal32, sizeof(fVal)); + GDALExtendedDataType::CopyValue( + &fVal, GDALExtendedDataType::Create(GDT_Float32), pabyDstBuffer, + dstDataType); + } +#endif else { GDALDataType eDT = ::HDF5Dataset::GetDataType(hSrcDataType); diff --git a/deps/libgdal/gdal/frmts/heif/CMakeLists.txt b/deps/libgdal/gdal/frmts/heif/CMakeLists.txt index 1947f0673..3ad5d9896 100644 --- a/deps/libgdal/gdal/frmts/heif/CMakeLists.txt +++ b/deps/libgdal/gdal/frmts/heif/CMakeLists.txt @@ -1,7 +1,8 @@ add_gdal_driver(TARGET gdal_HEIF SOURCES heifdataset.cpp CORE_SOURCES heifdrivercore.cpp - PLUGIN_CAPABLE) + PLUGIN_CAPABLE + NO_SHARED_SYMBOL_WITH_CORE) if(TARGET gdal_HEIF_core) target_include_directories(gdal_HEIF_core PRIVATE $) diff --git a/deps/libgdal/gdal/frmts/heif/heifdrivercore.h b/deps/libgdal/gdal/frmts/heif/heifdrivercore.h index f15ebf06e..1e1a8d437 100644 --- a/deps/libgdal/gdal/frmts/heif/heifdrivercore.h +++ b/deps/libgdal/gdal/frmts/heif/heifdrivercore.h @@ -32,8 +32,13 @@ constexpr const char *DRIVER_NAME = "HEIF"; -int CPL_DLL HEIFDriverIdentifySimplified(GDALOpenInfo *poOpenInfo); +#define HEIFDriverIdentifySimplified \ + PLUGIN_SYMBOL_NAME(HEIFDriverIdentifySimplified) +#define HEIFDriverSetCommonMetadata \ + PLUGIN_SYMBOL_NAME(HEIFDriverSetCommonMetadata) -void CPL_DLL HEIFDriverSetCommonMetadata(GDALDriver *poDriver); +int HEIFDriverIdentifySimplified(GDALOpenInfo *poOpenInfo); + +void HEIFDriverSetCommonMetadata(GDALDriver *poDriver); #endif diff --git a/deps/libgdal/gdal/frmts/jp2kak/CMakeLists.txt b/deps/libgdal/gdal/frmts/jp2kak/CMakeLists.txt index ee7bcc7cc..fa95a832a 100644 --- a/deps/libgdal/gdal/frmts/jp2kak/CMakeLists.txt +++ b/deps/libgdal/gdal/frmts/jp2kak/CMakeLists.txt @@ -5,7 +5,8 @@ add_gdal_driver(TARGET gdal_JP2KAK subfile_source.h vsil_target.h CORE_SOURCES jp2kakdrivercore.cpp - PLUGIN_CAPABLE) + PLUGIN_CAPABLE + NO_SHARED_SYMBOL_WITH_CORE) if(TARGET gdal_JP2KAK_core) target_include_directories(gdal_JP2KAK_core PRIVATE $) diff --git a/deps/libgdal/gdal/frmts/jp2kak/jp2kakdrivercore.h b/deps/libgdal/gdal/frmts/jp2kak/jp2kakdrivercore.h index f7a1b4bfe..79d6f2adb 100644 --- a/deps/libgdal/gdal/frmts/jp2kak/jp2kakdrivercore.h +++ b/deps/libgdal/gdal/frmts/jp2kak/jp2kakdrivercore.h @@ -38,8 +38,12 @@ constexpr unsigned char jp2_header[] = {0x00, 0x00, 0x00, 0x0c, 0x6a, 0x50, constexpr unsigned char jpc_header[] = {0xff, 0x4f}; -int CPL_DLL JP2KAKDatasetIdentify(GDALOpenInfo *poOpenInfo); +#define JP2KAKDatasetIdentify PLUGIN_SYMBOL_NAME(JP2KAKDatasetIdentify) +#define JP2KAKDriverSetCommonMetadata \ + PLUGIN_SYMBOL_NAME(JP2KAKDriverSetCommonMetadata) -void CPL_DLL JP2KAKDriverSetCommonMetadata(GDALDriver *poDriver); +int JP2KAKDatasetIdentify(GDALOpenInfo *poOpenInfo); + +void JP2KAKDriverSetCommonMetadata(GDALDriver *poDriver); #endif diff --git a/deps/libgdal/gdal/frmts/jp2lura/CMakeLists.txt b/deps/libgdal/gdal/frmts/jp2lura/CMakeLists.txt index 1d90c39f0..d9241c70d 100644 --- a/deps/libgdal/gdal/frmts/jp2lura/CMakeLists.txt +++ b/deps/libgdal/gdal/frmts/jp2lura/CMakeLists.txt @@ -8,7 +8,8 @@ add_gdal_driver( jp2lurarasterband.cpp CORE_SOURCES jp2luradrivercore.cpp - PLUGIN_CAPABLE) + PLUGIN_CAPABLE + NO_SHARED_SYMBOL_WITH_CORE) if(NOT TARGET gdal_JP2Lura) return() diff --git a/deps/libgdal/gdal/frmts/jp2lura/jp2luradrivercore.h b/deps/libgdal/gdal/frmts/jp2lura/jp2luradrivercore.h index 4bea64dde..bbe19452c 100644 --- a/deps/libgdal/gdal/frmts/jp2lura/jp2luradrivercore.h +++ b/deps/libgdal/gdal/frmts/jp2lura/jp2luradrivercore.h @@ -38,8 +38,12 @@ constexpr unsigned char jpc_header[] = {0xff, 0x4f, 0xff, 0x51}; // SOC + RSIZ markers constexpr unsigned char jp2_box_jp[] = {0x6a, 0x50, 0x20, 0x20}; /* 'jP ' */ -int CPL_DLL JP2LuraDriverIdentify(GDALOpenInfo *poOpenInfo); +#define JP2LuraDriverIdentify PLUGIN_SYMBOL_NAME(JP2LuraDriverIdentify) +#define JP2LuraDriverSetCommonMetadata \ + PLUGIN_SYMBOL_NAME(JP2LuraDriverSetCommonMetadata) -void CPL_DLL JP2LuraDriverSetCommonMetadata(GDALDriver *poDriver); +int JP2LuraDriverIdentify(GDALOpenInfo *poOpenInfo); + +void JP2LuraDriverSetCommonMetadata(GDALDriver *poDriver); #endif diff --git a/deps/libgdal/gdal/frmts/jpeg/CMakeLists.txt b/deps/libgdal/gdal/frmts/jpeg/CMakeLists.txt index 95710a13b..ae8127d4f 100644 --- a/deps/libgdal/gdal/frmts/jpeg/CMakeLists.txt +++ b/deps/libgdal/gdal/frmts/jpeg/CMakeLists.txt @@ -4,6 +4,7 @@ add_gdal_driver( CORE_SOURCES jpegdrivercore.cpp PLUGIN_CAPABLE_IF "NOT GDAL_USE_JPEG_INTERNAL\\\;NOT GDAL_USE_JPEG12_INTERNAL\\\;NOT GDAL_USE_ZLIB_INTERNAL" + NO_SHARED_SYMBOL_WITH_CORE ) if(TARGET gdal_JPEG_core) diff --git a/deps/libgdal/gdal/frmts/jpeg/jpegdrivercore.h b/deps/libgdal/gdal/frmts/jpeg/jpegdrivercore.h index 39570c89a..0dc3ccba0 100644 --- a/deps/libgdal/gdal/frmts/jpeg/jpegdrivercore.h +++ b/deps/libgdal/gdal/frmts/jpeg/jpegdrivercore.h @@ -37,10 +37,15 @@ constexpr const char *DRIVER_NAME = "JPEG"; -bool CPL_DLL JPEGDatasetIsJPEGLS(GDALOpenInfo *poOpenInfo); +#define JPEGDatasetIsJPEGLS PLUGIN_SYMBOL_NAME(JPEGDatasetIsJPEGLS) +#define JPEGDriverIdentify PLUGIN_SYMBOL_NAME(JPEGDriverIdentify) +#define JPEGDriverSetCommonMetadata \ + PLUGIN_SYMBOL_NAME(JPEGDriverSetCommonMetadata) -int CPL_DLL JPEGDriverIdentify(GDALOpenInfo *poOpenInfo); +bool JPEGDatasetIsJPEGLS(GDALOpenInfo *poOpenInfo); -void CPL_DLL JPEGDriverSetCommonMetadata(GDALDriver *poDriver); +int JPEGDriverIdentify(GDALOpenInfo *poOpenInfo); + +void JPEGDriverSetCommonMetadata(GDALDriver *poDriver); #endif diff --git a/deps/libgdal/gdal/frmts/jpeg/jpgdataset.cpp b/deps/libgdal/gdal/frmts/jpeg/jpgdataset.cpp index ce0a87be0..9ee903afb 100644 --- a/deps/libgdal/gdal/frmts/jpeg/jpgdataset.cpp +++ b/deps/libgdal/gdal/frmts/jpeg/jpgdataset.cpp @@ -331,7 +331,7 @@ void JPGDatasetCommon::ReadXMPMetadata() // Not a marker if (abyChunkHeader[0] != 0xFF) - continue; + break; // Stop on Start of Scan if (abyChunkHeader[1] == 0xDA) @@ -406,17 +406,18 @@ void JPGDatasetCommon::ReadFLIRMetadata() 1) break; + const int nMarkerLength = + abyChunkHeader[2] * 256 + abyChunkHeader[3] - 2; + nChunkLoc += 4 + nMarkerLength; + // Not a marker if (abyChunkHeader[0] != 0xFF) - continue; + break; // Stop on Start of Scan if (abyChunkHeader[1] == 0xDA) break; - int nMarkerLength = abyChunkHeader[2] * 256 + abyChunkHeader[3] - 2; - nChunkLoc += 4 + nMarkerLength; - if (abyChunkHeader[1] == 0xe1 && memcmp(abyChunkHeader + 4, "FLIR\0", 5) == 0) { diff --git a/deps/libgdal/gdal/frmts/jpegxl/CMakeLists.txt b/deps/libgdal/gdal/frmts/jpegxl/CMakeLists.txt index 52f3216b5..a30974550 100644 --- a/deps/libgdal/gdal/frmts/jpegxl/CMakeLists.txt +++ b/deps/libgdal/gdal/frmts/jpegxl/CMakeLists.txt @@ -2,7 +2,8 @@ add_gdal_driver( TARGET gdal_JPEGXL SOURCES jpegxl.cpp CORE_SOURCES jpegxldrivercore.cpp - PLUGIN_CAPABLE) + PLUGIN_CAPABLE + NO_SHARED_SYMBOL_WITH_CORE) function(declare_def DEF) if(TARGET gdal_JPEGXL) diff --git a/deps/libgdal/gdal/frmts/jpegxl/jpegxl.cpp b/deps/libgdal/gdal/frmts/jpegxl/jpegxl.cpp index 6d02817e0..c71f8390c 100644 --- a/deps/libgdal/gdal/frmts/jpegxl/jpegxl.cpp +++ b/deps/libgdal/gdal/frmts/jpegxl/jpegxl.cpp @@ -1838,7 +1838,8 @@ GDALDataset *JPEGXLDataset::CreateCopy(const char *pszFilename, nJPEGXLContent); size_t nInsertPos = 0; - if (abyData[0] == 0xff && abyData[1] == 0x0a) + if (abyData.size() >= 2 && abyData[0] == 0xff && + abyData[1] == 0x0a) { // If we get a "naked" codestream, insert it into a // ISOBMFF-based container diff --git a/deps/libgdal/gdal/frmts/jpegxl/jpegxldrivercore.h b/deps/libgdal/gdal/frmts/jpegxl/jpegxldrivercore.h index a1e702e4b..b45543ae2 100644 --- a/deps/libgdal/gdal/frmts/jpegxl/jpegxldrivercore.h +++ b/deps/libgdal/gdal/frmts/jpegxl/jpegxldrivercore.h @@ -33,8 +33,12 @@ constexpr const char *DRIVER_NAME = "JPEGXL"; -bool CPL_DLL IsJPEGXLContainer(GDALOpenInfo *poOpenInfo); +#define IsJPEGXLContainer PLUGIN_SYMBOL_NAME(IsJPEGXLContainer) +#define JPEGXLDriverSetCommonMetadata \ + PLUGIN_SYMBOL_NAME(JPEGXLDriverSetCommonMetadata) -void CPL_DLL JPEGXLDriverSetCommonMetadata(GDALDriver *poDriver); +bool IsJPEGXLContainer(GDALOpenInfo *poOpenInfo); + +void JPEGXLDriverSetCommonMetadata(GDALDriver *poDriver); #endif diff --git a/deps/libgdal/gdal/frmts/jpipkak/CMakeLists.txt b/deps/libgdal/gdal/frmts/jpipkak/CMakeLists.txt index db0257ebb..1dbeab2be 100644 --- a/deps/libgdal/gdal/frmts/jpipkak/CMakeLists.txt +++ b/deps/libgdal/gdal/frmts/jpipkak/CMakeLists.txt @@ -3,7 +3,8 @@ add_gdal_driver(TARGET gdal_JPIPKAK jpipkakdataset.h jpipkakdataset.cpp CORE_SOURCES jpipkakdrivercore.cpp - PLUGIN_CAPABLE) + PLUGIN_CAPABLE + NO_SHARED_SYMBOL_WITH_CORE) if(NOT TARGET gdal_JPIPKAK) return() diff --git a/deps/libgdal/gdal/frmts/jpipkak/jpipkakdrivercore.h b/deps/libgdal/gdal/frmts/jpipkak/jpipkakdrivercore.h index 6e4cebe16..4e8d71ae3 100644 --- a/deps/libgdal/gdal/frmts/jpipkak/jpipkakdrivercore.h +++ b/deps/libgdal/gdal/frmts/jpipkak/jpipkakdrivercore.h @@ -33,6 +33,9 @@ constexpr const char *DRIVER_NAME = "JPIPKAK"; -void CPL_DLL JPIPKAKDriverSetCommonMetadata(GDALDriver *poDriver); +#define JPIPKAKDriverSetCommonMetadata \ + PLUGIN_SYMBOL_NAME(JPIPKAKDriverSetCommonMetadata) + +void JPIPKAKDriverSetCommonMetadata(GDALDriver *poDriver); #endif diff --git a/deps/libgdal/gdal/frmts/kea/CMakeLists.txt b/deps/libgdal/gdal/frmts/kea/CMakeLists.txt index cee8da2f6..7570588a1 100644 --- a/deps/libgdal/gdal/frmts/kea/CMakeLists.txt +++ b/deps/libgdal/gdal/frmts/kea/CMakeLists.txt @@ -16,7 +16,8 @@ add_gdal_driver( libkea_headers.h CORE_SOURCES keadrivercore.cpp - PLUGIN_CAPABLE) + PLUGIN_CAPABLE + NO_SHARED_SYMBOL_WITH_CORE) if(TARGET gdal_KEA_core) target_include_directories(gdal_KEA_core PRIVATE ${HDF5_INCLUDE_DIRS}) diff --git a/deps/libgdal/gdal/frmts/kea/keaband.cpp b/deps/libgdal/gdal/frmts/kea/keaband.cpp index 905ec37d0..5b452c74a 100644 --- a/deps/libgdal/gdal/frmts/kea/keaband.cpp +++ b/deps/libgdal/gdal/frmts/kea/keaband.cpp @@ -399,7 +399,7 @@ void KEARasterBand::SetDescription(const char *pszDescription) try { this->m_pImageIO->setImageBandDescription(this->nBand, pszDescription); - GDALPamRasterBand::SetDescription(pszDescription); + GDALRasterBand::SetDescription(pszDescription); } catch (const kealib::KEAIOException &) { @@ -721,9 +721,9 @@ CPLErr KEARasterBand::GetDefaultHistogram(double *pdfMin, double *pdfMax, { if (bForce) { - return GDALPamRasterBand::GetDefaultHistogram(pdfMin, pdfMax, pnBuckets, - ppanHistogram, bForce, fn, - pProgressData); + return GDALRasterBand::GetDefaultHistogram(pdfMin, pdfMax, pnBuckets, + ppanHistogram, bForce, fn, + pProgressData); } else { @@ -1379,7 +1379,7 @@ GDALRasterBand *KEARasterBand::GetMaskBand() { // use the base class implementation - GDAL will delete // fprintf( stderr, "returning base GetMaskBand()\n" ); - m_pMaskBand = GDALPamRasterBand::GetMaskBand(); + m_pMaskBand = GDALRasterBand::GetMaskBand(); } } catch (const kealib::KEAException &) @@ -1399,7 +1399,7 @@ int KEARasterBand::GetMaskFlags() // need to return the base class one since we are using // the base class implementation of GetMaskBand() // fprintf( stderr, "returning base GetMaskFlags()\n" ); - return GDALPamRasterBand::GetMaskFlags(); + return GDALRasterBand::GetMaskFlags(); } } catch (const kealib::KEAException &) diff --git a/deps/libgdal/gdal/frmts/kea/keaband.h b/deps/libgdal/gdal/frmts/kea/keaband.h index 9ae18b5b3..882b5e528 100644 --- a/deps/libgdal/gdal/frmts/kea/keaband.h +++ b/deps/libgdal/gdal/frmts/kea/keaband.h @@ -31,14 +31,14 @@ #ifndef KEABAND_H #define KEABAND_H -#include "gdal_pam.h" +#include "gdal_priv.h" #include "keadataset.h" class KEAOverview; class KEAMaskBand; // Provides the implementation of a GDAL raster band -class KEARasterBand CPL_NON_FINAL : public GDALPamRasterBand +class KEARasterBand CPL_NON_FINAL : public GDALRasterBand { private: LockedRefCount *m_pRefCount = nullptr; // reference count of m_pImageIO diff --git a/deps/libgdal/gdal/frmts/kea/keadataset.h b/deps/libgdal/gdal/frmts/kea/keadataset.h index 63505b182..5f56ba5a4 100644 --- a/deps/libgdal/gdal/frmts/kea/keadataset.h +++ b/deps/libgdal/gdal/frmts/kea/keadataset.h @@ -31,14 +31,14 @@ #ifndef KEADATASET_H #define KEADATASET_H -#include "gdal_pam.h" +#include "gdal_priv.h" #include "cpl_multiproc.h" #include "libkea_headers.h" class LockedRefCount; // class that implements a GDAL dataset -class KEADataset final : public GDALPamDataset +class KEADataset final : public GDALDataset { static H5::H5File *CreateLL(const char *pszFilename, int nXSize, int nYSize, int nBands, GDALDataType eType, diff --git a/deps/libgdal/gdal/frmts/kea/keadrivercore.h b/deps/libgdal/gdal/frmts/kea/keadrivercore.h index 9db81e75c..fc208ff30 100644 --- a/deps/libgdal/gdal/frmts/kea/keadrivercore.h +++ b/deps/libgdal/gdal/frmts/kea/keadrivercore.h @@ -31,8 +31,12 @@ constexpr const char *DRIVER_NAME = "KEA"; -int CPL_DLL KEADriverIdentify(GDALOpenInfo *poOpenInfo); +#define KEADriverIdentify PLUGIN_SYMBOL_NAME(KEADriverIdentify) +#define KEADriverSetCommonMetadata \ + PLUGIN_SYMBOL_NAME(KEADriverSetCommonMetadata) -void CPL_DLL KEADriverSetCommonMetadata(GDALDriver *poDriver); +int KEADriverIdentify(GDALOpenInfo *poOpenInfo); + +void KEADriverSetCommonMetadata(GDALDriver *poDriver); #endif diff --git a/deps/libgdal/gdal/frmts/mrf/CMakeLists.txt b/deps/libgdal/gdal/frmts/mrf/CMakeLists.txt index 8a0f76f56..596381e70 100644 --- a/deps/libgdal/gdal/frmts/mrf/CMakeLists.txt +++ b/deps/libgdal/gdal/frmts/mrf/CMakeLists.txt @@ -14,6 +14,7 @@ add_gdal_driver( mrfdrivercore.cpp PLUGIN_CAPABLE_IF "NOT GDAL_USE_JPEG_INTERNAL\\\;NOT GDAL_USE_JPEG12_INTERNAL\\\;NOT GDAL_USE_LERC_INTERNAL\\\;NOT GDAL_USE_PNG_INTERNAL\\\;NOT GDAL_USE_TIFF_INTERNAL\\\;NOT GDAL_USE_ZLIB_INTERNAL" + NO_SHARED_SYMBOL_WITH_CORE ) if(TARGET gdal_MRF_core) diff --git a/deps/libgdal/gdal/frmts/mrf/mrfdrivercore.h b/deps/libgdal/gdal/frmts/mrf/mrfdrivercore.h index 87035d7ec..173cc8c9a 100644 --- a/deps/libgdal/gdal/frmts/mrf/mrfdrivercore.h +++ b/deps/libgdal/gdal/frmts/mrf/mrfdrivercore.h @@ -54,8 +54,12 @@ constexpr const char *DRIVER_NAME = "MRF"; -int CPL_DLL MRFDriverIdentify(GDALOpenInfo *poOpenInfo); +#define MRFDriverIdentify PLUGIN_SYMBOL_NAME(MRFDriverIdentify) +#define MRFDriverSetCommonMetadata \ + PLUGIN_SYMBOL_NAME(MRFDriverSetCommonMetadata) -void CPL_DLL MRFDriverSetCommonMetadata(GDALDriver *poDriver); +int MRFDriverIdentify(GDALOpenInfo *poOpenInfo); + +void MRFDriverSetCommonMetadata(GDALDriver *poDriver); #endif diff --git a/deps/libgdal/gdal/frmts/mrsid/CMakeLists.txt b/deps/libgdal/gdal/frmts/mrsid/CMakeLists.txt index 05f17a809..c91ab9d26 100644 --- a/deps/libgdal/gdal/frmts/mrsid/CMakeLists.txt +++ b/deps/libgdal/gdal/frmts/mrsid/CMakeLists.txt @@ -3,7 +3,8 @@ option(GDAL_ENABLE_DRIVER_JP2MRSID "Whether to enable JPEG2000 support with MrSI add_gdal_driver(TARGET gdal_MrSID SOURCES mrsidstream.h mrsidstream.cpp mrsiddataset.cpp CORE_SOURCES mrsiddrivercore.cpp - PLUGIN_CAPABLE_IF "NOT GDAL_USE_GEOTIFF_INTERNAL OR NOT GDAL_HIDE_INTERNAL_SYMBOLS") + PLUGIN_CAPABLE_IF "NOT GDAL_USE_GEOTIFF_INTERNAL OR NOT GDAL_HIDE_INTERNAL_SYMBOLS" + NO_SHARED_SYMBOL_WITH_CORE) if(TARGET gdal_MrSID_core) target_include_directories(gdal_MrSID_core PRIVATE $) diff --git a/deps/libgdal/gdal/frmts/mrsid/mrsiddrivercore.h b/deps/libgdal/gdal/frmts/mrsid/mrsiddrivercore.h index 6262c98bd..10b5e7e8d 100644 --- a/deps/libgdal/gdal/frmts/mrsid/mrsiddrivercore.h +++ b/deps/libgdal/gdal/frmts/mrsid/mrsiddrivercore.h @@ -35,12 +35,19 @@ constexpr const char *MRSID_DRIVER_NAME = "MrSID"; constexpr const char *JP2MRSID_DRIVER_NAME = "JP2MrSID"; -int CPL_DLL MrSIDIdentify(GDALOpenInfo *poOpenInfo); +#define MrSIDIdentify PLUGIN_SYMBOL_NAME(MrSIDIdentify) +#define MrSIDJP2Identify PLUGIN_SYMBOL_NAME(MrSIDJP2Identify) +#define MrSIDDriverSetCommonMetadata \ + PLUGIN_SYMBOL_NAME(MrSIDDriverSetCommonMetadata) +#define JP2MrSIDDriverSetCommonMetadata \ + PLUGIN_SYMBOL_NAME(JP2MrSIDDriverSetCommonMetadata) -int CPL_DLL MrSIDJP2Identify(GDALOpenInfo *poOpenInfo); +int MrSIDIdentify(GDALOpenInfo *poOpenInfo); -void CPL_DLL MrSIDDriverSetCommonMetadata(GDALDriver *poDriver); +int MrSIDJP2Identify(GDALOpenInfo *poOpenInfo); -void CPL_DLL JP2MrSIDDriverSetCommonMetadata(GDALDriver *poDriver); +void MrSIDDriverSetCommonMetadata(GDALDriver *poDriver); + +void JP2MrSIDDriverSetCommonMetadata(GDALDriver *poDriver); #endif diff --git a/deps/libgdal/gdal/frmts/msg/CMakeLists.txt b/deps/libgdal/gdal/frmts/msg/CMakeLists.txt index 2ef691eae..414a3ad4a 100644 --- a/deps/libgdal/gdal/frmts/msg/CMakeLists.txt +++ b/deps/libgdal/gdal/frmts/msg/CMakeLists.txt @@ -14,7 +14,8 @@ add_gdal_driver( xritheaderparser.h CORE_SOURCES msgdrivercore.cpp - PLUGIN_CAPABLE) + PLUGIN_CAPABLE + NO_SHARED_SYMBOL_WITH_CORE) if(NOT TARGET gdal_MSG) return() diff --git a/deps/libgdal/gdal/frmts/msg/msgdrivercore.h b/deps/libgdal/gdal/frmts/msg/msgdrivercore.h index 3a2f09aac..f4e1ab1cc 100644 --- a/deps/libgdal/gdal/frmts/msg/msgdrivercore.h +++ b/deps/libgdal/gdal/frmts/msg/msgdrivercore.h @@ -34,6 +34,9 @@ constexpr const char *DRIVER_NAME = "MSG"; -void CPL_DLL MSGDriverSetCommonMetadata(GDALDriver *poDriver); +#define MSGDriverSetCommonMetadata \ + PLUGIN_SYMBOL_NAME(MSGDriverSetCommonMetadata) + +void MSGDriverSetCommonMetadata(GDALDriver *poDriver); #endif diff --git a/deps/libgdal/gdal/frmts/netcdf/CMakeLists.txt b/deps/libgdal/gdal/frmts/netcdf/CMakeLists.txt index 892f34a81..506d905fd 100644 --- a/deps/libgdal/gdal/frmts/netcdf/CMakeLists.txt +++ b/deps/libgdal/gdal/frmts/netcdf/CMakeLists.txt @@ -12,7 +12,8 @@ set(_SOURCES add_gdal_driver(TARGET gdal_netCDF SOURCES ${_SOURCES} CORE_SOURCES netcdfdrivercore.cpp - PLUGIN_CAPABLE) + PLUGIN_CAPABLE + NO_SHARED_SYMBOL_WITH_CORE) unset(_SOURCES) function(declare_def DEF) @@ -21,6 +22,11 @@ function(declare_def DEF) endif() if(TARGET gdal_netCDF_core) target_compile_definitions(gdal_netCDF_core PRIVATE ${DEF}) + if(NetCDF_TARGET AND TARGET ${NetCDF_TARGET}) + target_include_directories(gdal_netCDF_core PRIVATE $) + target_compile_definitions(gdal_netCDF_core PRIVATE $) + target_compile_definitions(gdal_netCDF_core PRIVATE HAS_NETCDF_H) + endif() endif() endfunction() @@ -52,4 +58,4 @@ endif() gdal_standard_includes(gdal_netCDF) gdal_target_link_libraries(gdal_netCDF PRIVATE ${NetCDF_TARGET}) - +target_compile_definitions(gdal_netCDF PRIVATE HAS_NETCDF_H) diff --git a/deps/libgdal/gdal/frmts/netcdf/netcdfdataset.cpp b/deps/libgdal/gdal/frmts/netcdf/netcdfdataset.cpp index 69e030de6..2acb18e78 100644 --- a/deps/libgdal/gdal/frmts/netcdf/netcdfdataset.cpp +++ b/deps/libgdal/gdal/frmts/netcdf/netcdfdataset.cpp @@ -70,6 +70,7 @@ #include "cpl_time.h" #include "gdal.h" #include "gdal_frmts.h" +#include "gdal_priv_templates.hpp" #include "ogr_core.h" #include "ogr_srs_api.h" @@ -759,22 +760,12 @@ netCDFRasterBand::netCDFRasterBand(const netCDFRasterBand::CONSTRUCTOR_OPEN &, #ifdef NCDF_DEBUG CPLDebug("GDAL_netCDF", "SetNoDataValue(%f) read", dfNoData); #endif - if (eDataType == GDT_Int64 && - dfNoData >= - static_cast(std::numeric_limits::min()) && - dfNoData <= - static_cast(std::numeric_limits::max()) && - dfNoData == static_cast(static_cast(dfNoData))) + if (eDataType == GDT_Int64 && GDALIsValueExactAs(dfNoData)) { SetNoDataValueNoUpdate(static_cast(dfNoData)); } else if (eDataType == GDT_UInt64 && - dfNoData >= static_cast( - std::numeric_limits::min()) && - dfNoData <= static_cast( - std::numeric_limits::max()) && - dfNoData == - static_cast(static_cast(dfNoData))) + GDALIsValueExactAs(dfNoData)) { SetNoDataValueNoUpdate(static_cast(dfNoData)); } @@ -3901,6 +3892,56 @@ void netCDFDataset::SetProjectionFromVar( double xMinMax[2] = {0.0, 0.0}; double yMinMax[2] = {0.0, 0.0}; + const auto RoundMinMaxForFloatVals = + [](double &dfMin, double &dfMax, int nIntervals) + { + // Helps for a case where longitudes range from + // -179.99 to 180.0 with a 0.01 degree spacing. + // However as this is encoded in a float array, + // -179.99 is actually read as -179.99000549316406 as + // a double. Try to detect that and correct the rounding + + const auto IsAlmostInteger = [](double dfVal) + { + constexpr double THRESHOLD_INTEGER = 1e-3; + return std::fabs(dfVal - std::round(dfVal)) <= + THRESHOLD_INTEGER; + }; + + const double dfSpacing = (dfMax - dfMin) / nIntervals; + if (dfSpacing > 0) + { + const double dfInvSpacing = 1.0 / dfSpacing; + if (IsAlmostInteger(dfInvSpacing)) + { + const double dfRoundedSpacing = + 1.0 / std::round(dfInvSpacing); + const double dfMinDivRoundedSpacing = + dfMin / dfRoundedSpacing; + const double dfMaxDivRoundedSpacing = + dfMax / dfRoundedSpacing; + if (IsAlmostInteger(dfMinDivRoundedSpacing) && + IsAlmostInteger(dfMaxDivRoundedSpacing)) + { + const double dfRoundedMin = + std::round(dfMinDivRoundedSpacing) * + dfRoundedSpacing; + const double dfRoundedMax = + std::round(dfMaxDivRoundedSpacing) * + dfRoundedSpacing; + if (static_cast(dfMin) == + static_cast(dfRoundedMin) && + static_cast(dfMax) == + static_cast(dfRoundedMax)) + { + dfMin = dfRoundedMin; + dfMax = dfRoundedMax; + } + } + } + } + }; + if (!nc_get_att_double(nGroupDimXID, nVarDimXID, "actual_range", adfActualRange)) { @@ -3920,6 +3961,12 @@ void netCDFDataset::SetProjectionFromVar( xMinMax[0] = pdfXCoord[0]; xMinMax[1] = pdfXCoord[xdim - 1]; node_offset = 0; + + if (nc_var_dimx_datatype == NC_FLOAT) + { + RoundMinMaxForFloatVals(xMinMax[0], xMinMax[1], + poDS->nRasterXSize - 1); + } } if (!nc_get_att_double(nGroupDimYID, nVarDimYID, "actual_range", @@ -3941,6 +3988,12 @@ void netCDFDataset::SetProjectionFromVar( yMinMax[0] = pdfYCoord[0]; yMinMax[1] = pdfYCoord[ydim - 1]; node_offset = 0; + + if (nc_var_dimy_datatype == NC_FLOAT) + { + RoundMinMaxForFloatVals(yMinMax[0], yMinMax[1], + poDS->nRasterYSize - 1); + } } double dfCoordOffset = 0.0; @@ -8310,13 +8363,12 @@ GDALDataset *netCDFDataset::Open(GDALOpenInfo *poOpenInfo) bool bHasSimpleGeometries = false; // but not necessarily valid if (poDS->nCFVersion >= 1.8) { - poDS->bSGSupport = true; bHasSimpleGeometries = poDS->DetectAndFillSGLayers(cdfid); - poDS->vcdf.enableFullVirtualMode(); - } - else - { - poDS->bSGSupport = false; + if (bHasSimpleGeometries) + { + poDS->bSGSupport = true; + poDS->vcdf.enableFullVirtualMode(); + } } char szConventions[NC_MAX_NAME + 1]; @@ -9285,9 +9337,12 @@ GDALDataset *netCDFDataset::Create(const char *pszFilename, int nXSize, // Add Conventions, GDAL info and history. if (poDS->cdfid >= 0) { - const char *CF_Vector_Conv = poDS->bSGSupport - ? NCDF_CONVENTIONS_CF_V1_8 - : NCDF_CONVENTIONS_CF_V1_6; + const char *CF_Vector_Conv = + poDS->bSGSupport || + // Use of variable length strings require CF-1.8 + EQUAL(aosOptions.FetchNameValueDef("FORMAT", ""), "NC4") + ? NCDF_CONVENTIONS_CF_V1_8 + : NCDF_CONVENTIONS_CF_V1_6; poDS->bWriteGDALVersion = CPLTestBool( CSLFetchNameValueDef(papszOptions, "WRITE_GDAL_VERSION", "YES")); poDS->bWriteGDALHistory = CPLTestBool( diff --git a/deps/libgdal/gdal/frmts/netcdf/netcdfdrivercore.cpp b/deps/libgdal/gdal/frmts/netcdf/netcdfdrivercore.cpp index 9715a08e5..bb339c6ad 100644 --- a/deps/libgdal/gdal/frmts/netcdf/netcdfdrivercore.cpp +++ b/deps/libgdal/gdal/frmts/netcdf/netcdfdrivercore.cpp @@ -35,6 +35,19 @@ #include #include +#ifdef HAS_NETCDF_H +#include "netcdfdataset.h" +#ifdef NETCDF_HAS_NC2 +#define NETCDF_CORE_HAS_NC2 1 +#endif +#else +// We don't have an easy way to guess that without accessing netcdf.h, so +// assume it is present +#ifndef NETCDF_CORE_HAS_NC2 +#define NETCDF_CORE_HAS_NC2 1 +#endif +#endif + /************************************************************************/ /* netCDFIdentifyFormat() */ /************************************************************************/ @@ -377,7 +390,7 @@ void netCDFDriverSetCommonMetadata(GDALDriver *poDriver) "" "