diff --git a/autotest/ogr/ogr_csv.py b/autotest/ogr/ogr_csv.py
index 13a0e359c31f..442808f44002 100755
--- a/autotest/ogr/ogr_csv.py
+++ b/autotest/ogr/ogr_csv.py
@@ -943,7 +943,7 @@ def test_ogr_csv_27():
feat.DumpReadable()
pytest.fail()
-
+
###############################################################################
# Check that we don't rewrite erroneously a file that has no header (#5161).
@@ -1197,7 +1197,7 @@ def test_ogr_csv_32():
f.DumpReadable()
pytest.fail()
-
+
###############################################################################
# Test Boolean, Int16 and Float32 support
@@ -1968,10 +1968,10 @@ def test_ogr_csv_47():
def test_ogr_csv_48():
- gdal.FileFromMemBuffer('/vsimem/ogr_csv_48.csvt', 'JsonStringList,JsonIntegerList,JsonInteger64List,JsonRealList\n')
+ gdal.FileFromMemBuffer('/vsimem/ogr_csv_48.csvt', 'JsonStringList,JsonStringList,JsonIntegerList,JsonInteger64List,JsonRealList\n')
gdal.FileFromMemBuffer('/vsimem/ogr_csv_48.csv',
- """stringlist,intlist,int64list,reallist
-"[""a"",null]","[1]","[1234567890123]","[0.125]"
+ """stringlist,emptystringlist,intlist,int64list,reallist
+"[""a"",null]",[],"[1]","[1234567890123]","[0.125]"
""")
gdal.VectorTranslate('/vsimem/ogr_csv_48_out.csv', '/vsimem/ogr_csv_48.csv', format='CSV', layerCreationOptions=['CREATE_CSVT=YES', 'LINEFORMAT=LF'])
@@ -1980,13 +1980,13 @@ def test_ogr_csv_48():
data = gdal.VSIFReadL(1, 10000, f).decode('ascii')
gdal.VSIFCloseL(f)
- assert data.startswith('stringlist,intlist,int64list,reallist\n"[ ""a"", """" ]",[ 1 ],[ 1234567890123 ],[ 0.125')
+ assert data.startswith('stringlist,emptystringlist,intlist,int64list,reallist\n"[ ""a"", """" ]",[],[ 1 ],[ 1234567890123 ],[ 0.125')
f = gdal.VSIFOpenL('/vsimem/ogr_csv_48_out.csvt', 'rb')
data = gdal.VSIFReadL(1, 10000, f).decode('ascii')
gdal.VSIFCloseL(f)
- assert data.startswith('JSonStringList,JSonIntegerList,JSonInteger64List,JSonRealList')
+ assert data.startswith('JSonStringList,JSonStringList,JSonIntegerList,JSonInteger64List,JSonRealList')
gdal.Unlink('/vsimem/ogr_csv_48.csv')
gdal.Unlink('/vsimem/ogr_csv_48.csvt')
diff --git a/autotest/ogr/ogr_gpkg.py b/autotest/ogr/ogr_gpkg.py
index 8c1c06d13468..5941252dc856 100755
--- a/autotest/ogr/ogr_gpkg.py
+++ b/autotest/ogr/ogr_gpkg.py
@@ -3400,16 +3400,17 @@ def test_ogr_gpkg_46():
f = ogr.Feature(lyr.GetLayerDefn())
f.SetGeometry(ogr.CreateGeometryFromWkt('POINT(1 1)'))
lyr.CreateFeature(f)
- # Note: those definitions of views are non conformant with GPKG 1.3 clarifications on views
+ # Note: this definition of a view is non conformant with GPKG 1.3 clarifications on views
ds.ExecuteSQL('CREATE VIEW my_view AS SELECT geom AS my_geom, fid AS my_fid FROM foo')
ds.ExecuteSQL("INSERT INTO gpkg_contents (table_name, identifier, data_type, srs_id) VALUES ( 'my_view', 'my_view', 'features', 0 )")
ds.ExecuteSQL("INSERT INTO gpkg_geometry_columns (table_name, column_name, geometry_type_name, srs_id, z, m) values ('my_view', 'my_geom', 'GEOMETRY', 0, 0, 0)")
+ # Note: this definition of a view is non conformant with GPKG 1.3 clarifications on views
ds.ExecuteSQL("CREATE VIEW my_view2 AS SELECT geom, fid AS OGC_FID, 'bla' as another_column FROM foo")
ds.ExecuteSQL("INSERT INTO gpkg_contents (table_name, identifier, data_type, srs_id) VALUES ( 'my_view2', 'my_view2', 'features', 0 )")
ds.ExecuteSQL("INSERT INTO gpkg_geometry_columns (table_name, column_name, geometry_type_name, srs_id, z, m) values ('my_view2', 'geom', 'GEOMETRY', 0, 0, 0)")
- ds.ExecuteSQL('CREATE VIEW my_view3 AS SELECT a.fid, a.geom, b.fid as fid2 FROM foo a, foo b')
+ ds.ExecuteSQL('CREATE VIEW my_view3 AS SELECT a.fid * 10000 + b.fid as my_fid, a.fid as fid1, a.geom, b.fid as fid2 FROM foo a, foo b')
ds.ExecuteSQL("INSERT INTO gpkg_contents (table_name, identifier, data_type, srs_id) VALUES ( 'my_view3', 'my_view3', 'features', 0 )")
ds.ExecuteSQL("INSERT INTO gpkg_geometry_columns (table_name, column_name, geometry_type_name, srs_id, z, m) values ('my_view3', 'geom', 'GEOMETRY', 0, 0, 0)")
@@ -3447,7 +3448,7 @@ def test_ogr_gpkg_46():
f = lyr.GetNextFeature()
assert f is None
- # View with FID
+ # View with FID in non-first position
lyr = ds.GetLayerByName('my_view2')
assert lyr.GetLayerDefn().GetFieldCount() == 1
assert lyr.GetFIDColumn() == 'OGC_FID'
@@ -3456,23 +3457,15 @@ def test_ogr_gpkg_46():
f.DumpReadable()
pytest.fail()
- # View without valid rowid
+ # View with FID in first position
lyr = ds.GetLayerByName('my_view3')
assert lyr.GetLayerDefn().GetFieldCount() == 2
f = lyr.GetNextFeature()
- if f.GetFID() != 0:
- f.DumpReadable()
- pytest.fail()
+ assert f.GetFID() == 10001
f = lyr.GetNextFeature()
- if f.GetFID() != 1:
- f.DumpReadable()
- pytest.fail()
- f2 = lyr.GetFeature(1)
- if not f.Equal(f2):
- f.DumpReadable()
- f2.DumpReadable()
- pytest.fail()
-
+ assert f.GetFID() == 10002
+ f2 = lyr.GetFeature(10002)
+ assert f.Equal(f2)
ds = None
gdaltest.gpkg_dr.DeleteDataSource('/vsimem/ogr_gpkg_46.gpkg')
diff --git a/autotest/ogr/ogr_plscenes.py b/autotest/ogr/ogr_plscenes.py
index 7926cff1137d..11701f59de31 100755
--- a/autotest/ogr/ogr_plscenes.py
+++ b/autotest/ogr/ogr_plscenes.py
@@ -141,7 +141,7 @@ def test_ogr_plscenes_data_v1_nominal():
assert ext == (-180.0, 180.0, -90.0, 90.0)
field_count = lyr.GetLayerDefn().GetFieldCount()
- assert field_count == 78
+ assert field_count == 106
# Regular /items/ fetching
gdal.FileFromMemBuffer("""/vsimem/data_v1/quick-search?_page_size=250&POSTFIELDS={"item_types":["PSOrthoTile"],"filter":{"type":"AndFilter","config":[]}}""",
@@ -517,7 +517,7 @@ def test_ogr_plscenes_data_v1_nominal():
for filename in fl:
gdal.Unlink(filename)
-
+
###############################################################################
# Test robustness to errors in Data V1 API
@@ -700,8 +700,9 @@ def test_ogr_plscenes_data_v1_live():
ds = None
- ds = gdal.Open('PLScenes:version=data_v1,itemtypes=%s,scene=%s,asset=%s' % (catalog, scene, asset_name))
- assert ds is not None
+ dsname = 'PLScenes:version=data_v1,itemtypes=%s,scene=%s,asset=%s' % (catalog, scene, asset_name)
+ ds = gdal.Open(dsname)
+ assert ds is not None, dsname
assert ds.RasterCount != 0
diff --git a/autotest/ogr/ogr_sqlite.py b/autotest/ogr/ogr_sqlite.py
index 47461c991db5..d13f7f1aa6b5 100755
--- a/autotest/ogr/ogr_sqlite.py
+++ b/autotest/ogr/ogr_sqlite.py
@@ -3105,6 +3105,13 @@ def test_ogr_sqlite_view_type():
assert lyr.GetLayerDefn().GetFieldCount() == 1
assert lyr.GetLayerDefn().GetFieldDefn(0).GetType() == ogr.OFTInteger
+ ds.ExecuteSQL('INSERT INTO t VALUES(1)')
+ f = lyr.GetNextFeature()
+ assert f['c'] == 1
+ lyr.ResetReading()
+ f = lyr.GetNextFeature()
+ assert f['c'] == 1
+
###############################################################################
#
diff --git a/gdal/GDALmake.opt.in b/gdal/GDALmake.opt.in
index a4764c15b508..68387724a88d 100644
--- a/gdal/GDALmake.opt.in
+++ b/gdal/GDALmake.opt.in
@@ -33,7 +33,7 @@ INSTALL_DIR = $(GDAL_ROOT)/install-sh -d
LIBS = @LIBS@ $(KAK_LIBS) $(DWG_LIBS) $(CURL_LIB) \
$(MRSID_LIBS) $(MRSID_LIDAR_LIBS) $(ECW_LIBS) $(INGRES_LIB) \
- $(PCIDSK_LIB) $(RASDAMAN_LIB) $(SOSI_LIB) \
+ $(PCIDSK_LIB) $(RASDAMAN_LIB) $(SOSI_LIB) $(BRUNSLI_LIB) \
$(OPENCL_LIB) $(JVM_LIB) $(LIBICONV) $(FGDB_LIB) $(LIBXML2_LIB) $(MONGODB_LIB) \
$(MONGOCXXV3_LIBS) $(JNI_LIB) $(HDFS_LIB)
@@ -459,6 +459,14 @@ RASDAMAN_ENABLED = @RASDAMAN_ENABLED@
RASDAMAN_INC = @RASDAMAN_INC@
RASDAMAN_LIB = @RASDAMAN_LIB@
+
+#
+# BRUNSLI (JPEG XL)
+#
+BRUNSLI_ENABLED = @BRUNSLI_ENABLED@
+BRUNSLI_INCLUDE = @BRUNSLI_INCLUDE@
+BRUNSLI_LIB = @BRUNSLI_LIB@
+
#
# PDF stuff
#
diff --git a/gdal/configure b/gdal/configure
index 127cf2a76a45..e843df6a0e60 100755
--- a/gdal/configure
+++ b/gdal/configure
@@ -642,6 +642,9 @@ USE_ONLY_CRYPTODLL_ALG
HAVE_CRYPTOPP
HAVE_ARMADILLO
RDB_SETTING
+BRUNSLI_LIB
+BRUNSLI_INCLUDE
+BRUNSLI_ENABLED
RASDAMAN_LIB
RASDAMAN_INC
RASDAMAN_ENABLED
@@ -1216,6 +1219,7 @@ with_mdb
with_jvm_lib
with_jvm_lib_add_rpath
with_rasdaman
+with_brunsli
with_rdb
with_armadillo
with_cryptopp
@@ -2227,6 +2231,7 @@ Optional Packages:
--with-jvm-lib=ARG ARG is dlopen or points to Java libjvm path
--with-jvm-lib-add-rpath Add the libjvm path to the RPATH (no by default)
--with-rasdaman=DIR Include rasdaman support (DIR is rasdaman's install dir).
+ --with-brunsli Include brunsli support via libbrunsli library
--with-rdb=ARG Include RDB support (ARG=no, yes or RDB SDK root path)
--with-armadillo=ARG Include Armadillo support for faster TPS transform computation (ARG=yes/no/path to armadillo install root) [default=no]
--with-cryptopp=ARG Include cryptopp support (ARG=yes, no or path)
@@ -41354,6 +41359,27 @@ RASDAMAN_LIB=$RASDAMAN_LIB
+
+# Check whether --with-brunsli was given.
+if test "${with_brunsli+set}" = set; then :
+ withval=$with_brunsli;
+fi
+
+
+BRUNSLI_ENABLED=no
+
+if test "$with_brunsli" != "" -a "$with_brunsli" != "no" ; then
+ BRUNSLI_ENABLED="yes"
+ BRUNSLI_ENABLED=$BRUNSLI_ENABLED
+
+ BRUNSLI_INCLUDE=-I$prefix/include
+
+ BRUNSLI_LIB="-lbrunslicommon -lbrunslienc -lbrunslidec -lbrotlicommon -lbrotlienc -lbrotlidec"
+
+fi
+
+
+
# Check whether --with-rdb was given.
if test "${with_rdb+set}" = set; then :
withval=$with_rdb;
@@ -45054,6 +45080,9 @@ echo " Kea support: ${HAVE_KEA}"
echo " LERC support: ${HAVE_LERC}"
+echo " libbrunsli support: ${BRUNSLI_ENABLED}"
+
+
echo " libdeflate support: ${LIBDEFLATE_SETTING}"
diff --git a/gdal/configure.ac b/gdal/configure.ac
index 401fe29f0058..89f6b5e2ae63 100644
--- a/gdal/configure.ac
+++ b/gdal/configure.ac
@@ -5594,6 +5594,22 @@ AC_SUBST(RASDAMAN_ENABLED,$RASDAMAN_ENABLED)
AC_SUBST(RASDAMAN_INC, $RASDAMAN_INC)
AC_SUBST(RASDAMAN_LIB, $RASDAMAN_LIB)
+
+dnl ---------------------------------------------------------------------------
+dnl brunsli support
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(brunsli,[ --with-brunsli Include brunsli support via libbrunsli library],,)
+
+BRUNSLI_ENABLED=no
+
+if test "$with_brunsli" != "" -a "$with_brunsli" != "no" ; then
+ BRUNSLI_ENABLED="yes"
+ AC_SUBST(BRUNSLI_ENABLED, $BRUNSLI_ENABLED)
+ AC_SUBST(BRUNSLI_INCLUDE, -I$prefix/include)
+ AC_SUBST(BRUNSLI_LIB, "-lbrunslicommon -lbrunslienc -lbrunslidec -lbrotlicommon -lbrotlienc -lbrotlidec")
+fi
+
dnl ---------------------------------------------------------------------------
dnl RDB support
dnl ---------------------------------------------------------------------------
@@ -6093,6 +6109,7 @@ LOC_MSG([ JPEG-Lossless/CharLS: ${HAVE_CHARLS}])
LOC_MSG([ Kakadu support: ${HAVE_KAKADU}])
LOC_MSG([ Kea support: ${HAVE_KEA}])
LOC_MSG([ LERC support: ${HAVE_LERC}])
+LOC_MSG([ libbrunsli support: ${BRUNSLI_ENABLED}])
LOC_MSG([ libdeflate support: ${LIBDEFLATE_SETTING}])
LOC_MSG([ LIBGEOTIFF support: ${GEOTIFF_SETTING}])
LOC_MSG([ LIBGIF support: ${GIF_SETTING}])
diff --git a/gdal/data/plscenesconf.json b/gdal/data/plscenesconf.json
index fd8a6edf2352..25349d0d379b 100644
--- a/gdal/data/plscenesconf.json
+++ b/gdal/data/plscenesconf.json
@@ -15,6 +15,7 @@
{ "name": "ground_control", "type": "boolean" },
{ "name": "gsd", "type": "double" },
{ "name": "heavy_haze_percent", "type": "double" },
+ { "name": "instrument", "type": "string" },
{ "name": "item_type", "type": "string" },
{ "name": "light_haze_percent", "type": "double" },
{ "name": "origin_x", "type": "double" },
@@ -22,7 +23,10 @@
{ "name": "pixel_resolution", "type": "double" },
{ "name": "provider", "type": "string" },
{ "name": "published", "type": "datetime" },
+ { "name": "publishing_stage", "type": "string" },
+ { "name": "quality_category", "type": "string" },
{ "name": "rows", "type": "int" },
+ { "name": "satellite_azimuth", "type": "double" },
{ "name": "satellite_id", "type": "string" },
{ "name": "shadow_percent", "type": "double" },
{ "name": "snow_ice_percent", "type": "double" },
@@ -37,10 +41,14 @@
],
"assets": [
"analytic",
+ "analytic_5b",
+ "analytic_5b_xml",
"analytic_dn",
"analytic_dn_xml",
+ "analytic_sr",
"analytic_xml",
"udm",
+ "udm2",
"visual",
"visual_xml"
]
@@ -74,12 +82,64 @@
],
"assets": [
"analytic",
+ "analytic_sr",
"analytic_xml",
"udm",
"visual",
"visual_xml"
]
},
+ "PSScene" : {
+ "fields": [
+ { "name": "acquired", "type": "datetime" },
+ { "name": "anomalous_pixels", "type": "double" },
+ { "name": "clear_confidence_percent", "type": "double" },
+ { "name": "clear_percent", "type": "double" },
+ { "name": "cloud_cover", "type": "double" },
+ { "name": "cloud_percent", "type": "double" },
+ { "name": "epsg_code", "type": "int" },
+ { "name": "ground_control", "type": "boolean" },
+ { "name": "gsd", "type": "double" },
+ { "name": "heavy_haze_percent", "type": "double" },
+ { "name": "instrument", "type": "string" },
+ { "name": "item_type", "type": "string" },
+ { "name": "light_haze_percent", "type": "double" },
+ { "name": "pixel_resolution", "type": "double" },
+ { "name": "provider", "type": "string" },
+ { "name": "published", "type": "datetime" },
+ { "name": "publishing_stage", "type": "string" },
+ { "name": "quality_category", "type": "string" },
+ { "name": "rows", "type": "int" },
+ { "name": "satellite_azimuth", "type": "double" },
+ { "name": "satellite_id", "type": "string" },
+ { "name": "shadow_percent", "type": "double" },
+ { "name": "snow_ice_percent", "type": "double" },
+ { "name": "strip_id", "type": "string" },
+ { "name": "sun_azimuth", "type": "double" },
+ { "name": "sun_elevation", "type": "double" },
+ { "name": "updated", "type": "datetime" },
+ { "name": "usable_data", "type": "double" },
+ { "name": "view_angle", "type": "double" },
+ { "name": "visible_confidence_percent", "type": "double" },
+ { "name": "visible_percent", "type": "double" }
+ ],
+ "assets": [
+ "ortho_analytic_4b",
+ "ortho_analytic_8b",
+ "ortho_analytic_8b_sr",
+ "ortho_analytic_8b_xml",
+ "ortho_analytic_4b_sr",
+ "ortho_analytic_4b_xml",
+ "basic_analytic_4b",
+ "basic_analytic_8b",
+ "basic_analytic_8b_xml",
+ "basic_analytic_4b_rpc",
+ "basic_analytic_4b_xml",
+ "basic_udm2",
+ "ortho_udm2",
+ "ortho_visual"
+ ]
+ },
"PSScene3Band" : {
"fields": [
{ "name": "acquired", "type": "datetime" },
@@ -96,8 +156,10 @@
{ "name": "pixel_resolution", "type": "double" },
{ "name": "provider", "type": "string" },
{ "name": "published", "type": "datetime" },
+ { "name": "publishing_stage", "type": "string" },
{ "name": "quality_category", "type": "string" },
{ "name": "rows", "type": "int" },
+ { "name": "satellite_azimuth", "type": "double" },
{ "name": "satellite_id", "type": "string" },
{ "name": "strip_id", "type": "string" },
{ "name": "sun_azimuth", "type": "double" },
@@ -118,7 +180,9 @@
"basic_analytic_rpc",
"basic_analytic_xml",
"basic_udm",
+ "basic_udm2",
"udm",
+ "udm2",
"visual",
"visual_xml"
]
@@ -127,27 +191,38 @@
"fields": [
{ "name": "acquired", "type": "datetime" },
{ "name": "anomalous_pixels", "type": "double" },
+ { "name": "clear_confidence_percent", "type": "int" },
+ { "name": "clear_percent", "type": "int" },
{ "name": "cloud_cover", "type": "double" },
+ { "name": "cloud_percent", "type": "int" },
{ "name": "columns", "type": "int" },
{ "name": "epsg_code", "type": "int" },
{ "name": "ground_control", "type": "boolean" },
{ "name": "gsd", "type": "double" },
+ { "name": "heavy_haze_percent", "type": "int" },
{ "name": "instrument", "type": "string" },
{ "name": "item_type", "type": "string" },
+ { "name": "light_haze_percent", "type": "int" },
{ "name": "origin_x", "type": "double" },
{ "name": "origin_y", "type": "double" },
{ "name": "pixel_resolution", "type": "double" },
{ "name": "provider", "type": "string" },
{ "name": "published", "type": "datetime" },
+ { "name": "publishing_stage", "type": "string" },
{ "name": "quality_category", "type": "string" },
{ "name": "rows", "type": "int" },
+ { "name": "satellite_azimuth", "type": "double" },
{ "name": "satellite_id", "type": "string" },
+ { "name": "shadow_percent", "type": "int" },
+ { "name": "snow_ice_percent", "type": "int" },
{ "name": "strip_id", "type": "string" },
{ "name": "sun_azimuth", "type": "double" },
{ "name": "sun_elevation", "type": "double" },
{ "name": "updated", "type": "datetime" },
{ "name": "usable_data", "type": "double" },
- { "name": "view_angle", "type": "double" }
+ { "name": "view_angle", "type": "double" },
+ { "name": "visible_confidence_percent", "type": "int" },
+ { "name": "visible_percent", "type": "int" }
],
"assets": [
"analytic",
@@ -167,7 +242,9 @@
"basic_analytic_xml",
"basic_analytic_xml_nitf",
"basic_udm",
- "udm"
+ "basic_udm2",
+ "udm",
+ "udm2"
]
},
"REScene" : {
@@ -215,6 +292,7 @@
{ "name": "acquired", "type": "datetime" },
{ "name": "anomalous_pixels", "type": "double" },
{ "name": "cloud_cover", "type": "double" },
+ { "name": "collection", "type": "int" },
{ "name": "columns", "type": "int" },
{ "name": "data_type", "type": "string" },
{ "name": "epsg_code", "type": "int" },
@@ -224,6 +302,8 @@
{ "name": "origin_x", "type": "double" },
{ "name": "origin_y", "type": "double" },
{ "name": "pixel_resolution", "type": "double" },
+ { "name": "processed", "type": "datetime" },
+ { "name": "product_id", "type": "string" },
{ "name": "provider", "type": "string" },
{ "name": "published", "type": "datetime" },
{ "name": "quality_category", "type": "string" },
@@ -302,68 +382,137 @@
"analytic_b10",
"analytic_b11",
"analytic_b12",
- "metadata_aux"
+ "metadata_aux",
+ "visual"
]
},
"SkySatScene" : {
"fields": [
{ "name": "acquired", "type": "datetime" },
{ "name": "anomalous_pixels", "type": "double" },
+ { "name": "camera_id", "type": "string" },
+ { "name": "clear_confidence_percent", "type": "int" },
+ { "name": "clear_percent", "type": "int" },
{ "name": "cloud_cover", "type": "double" },
+ { "name": "cloud_percent", "type": "int" },
+ { "name": "ground_control", "type": "boolean" },
{ "name": "gsd", "type": "double" },
+ { "name": "heavy_haze_percent", "type": "int" },
{ "name": "item_type", "type": "string" },
+ { "name": "light_haze_percent", "type": "int" },
+ { "name": "pixel_resolution", "type": "double" },
{ "name": "provider", "type": "string" },
{ "name": "published", "type": "datetime" },
+ { "name": "publishing_stage", "type": "string" },
{ "name": "quality_category", "type": "string" },
{ "name": "satellite_id", "type": "string" },
{ "name": "satellite_azimuth", "type": "double" },
+ { "name": "shadow_percent", "type": "int" },
+ { "name": "snow_ice_percent", "type": "int" },
{ "name": "strip_id", "type": "string" },
{ "name": "sun_azimuth", "type": "double" },
{ "name": "sun_elevation", "type": "double" },
{ "name": "updated", "type": "datetime" },
- { "name": "view_angle", "type": "double" }
+ { "name": "view_angle", "type": "double" },
+ { "name": "visible_confidence_percent", "type": "int" },
+ { "name": "visible_percent", "type": "int" }
],
"assets": [
+ "basic_analytic",
"basic_analytic_dn",
"basic_analytic_dn_rpc",
+ "basic_analytic_rpc",
+ "basic_analytic_udm",
+ "basic_analytic_udm2",
+ "basic_l1a_panchromatic_dn",
+ "basic_l1a_panchromatic_dn_rpc",
+ "basic_panchromatic",
"basic_panchromatic_dn",
"basic_panchromatic_dn_rpc",
- "basic_udm",
+ "basic_panchromatic_rpc",
+ "basic_panchromatic_udm2",
+ "ortho_analytic",
+ "ortho_analytic_sr",
"ortho_analytic_dn",
"ortho_analytic_udm",
- "ortho_visual",
+ "ortho_analytic_udm2",
+ "ortho_panchromatic",
"ortho_panchromatic_dn",
"ortho_panchromatic_udm",
+ "ortho_panchromatic_udm2",
"ortho_pansharpened",
- "ortho_pansharpened_udm"
+ "ortho_pansharpened_udm",
+ "ortho_pansharpened_udm2",
+ "ortho_visual"
]
},
"SkySatCollect" : {
"fields": [
{ "name": "acquired", "type": "datetime" },
+ { "name": "clear_confidence_percent", "type": "int" },
+ { "name": "clear_percent", "type": "int" },
{ "name": "cloud_cover", "type": "double" },
+ { "name": "cloud_percent", "type": "int" },
{ "name": "ground_control_ratio", "type": "double" },
{ "name": "gsd", "type": "double" },
+ { "name": "heavy_haze_percent", "type": "int" },
{ "name": "item_type", "type": "string" },
+ { "name": "light_haze_percent", "type": "int" },
+ { "name": "pixel_resolution", "type": "double" },
{ "name": "provider", "type": "string" },
{ "name": "published", "type": "datetime" },
+ { "name": "publishing_stage", "type": "string" },
{ "name": "quality_category", "type": "string" },
{ "name": "satellite_id", "type": "string" },
{ "name": "satellite_azimuth", "type": "double" },
+ { "name": "shadow_percent", "type": "int" },
+ { "name": "snow_ice_percent", "type": "int" },
{ "name": "strip_id", "type": "string" },
{ "name": "sun_azimuth", "type": "double" },
{ "name": "sun_elevation", "type": "double" },
{ "name": "updated", "type": "datetime" },
- { "name": "view_angle", "type": "double" }
+ { "name": "view_angle", "type": "double" },
+ { "name": "visible_confidence_percent", "type": "int" },
+ { "name": "visible_percent", "type": "int" }
],
"assets": [
+ "basic_l1a_all_frames",
+ "ortho_analytic",
+ "ortho_analytic_sr",
"ortho_analytic_dn",
"ortho_analytic_udm",
- "ortho_visual",
+ "ortho_analytic_udm2",
+ "ortho_panchromatic",
"ortho_panchromatic_dn",
"ortho_panchromatic_udm",
+ "ortho_panchromatic_udm2",
"ortho_pansharpened",
- "ortho_pansharpened_udm"
+ "ortho_pansharpened_udm",
+ "ortho_pansharpened_udm2",
+ "ortho_visual"
+ ]
+ },
+ "SkySatVideo" : {
+ "fields": [
+ { "name": "acquired", "type": "datetime" },
+ { "name": "camera_id", "type": "string" },
+ { "name": "item_type", "type": "string" },
+ { "name": "provider", "type": "string" },
+ { "name": "published", "type": "datetime" },
+ { "name": "publishing_stage", "type": "string" },
+ { "name": "quality_category", "type": "string" },
+ { "name": "satellite_azimuth", "type": "double" },
+ { "name": "satellite_id", "type": "string" },
+ { "name": "strip_id", "type": "string" },
+ { "name": "sun_azimuth", "type": "double" },
+ { "name": "sun_elevation", "type": "double" },
+ { "name": "updated", "type": "datetime" },
+ { "name": "view_angle", "type": "double" }
+ ],
+ "assets": [
+ "video_file",
+ "video_frames",
+ "video_metadata"
]
},
"Sentinel1" : {
diff --git a/gdal/doc/source/drivers/vector/plscenes.rst b/gdal/doc/source/drivers/vector/plscenes.rst
index 55e0ea20e7e9..1c42e40117e1 100644
--- a/gdal/doc/source/drivers/vector/plscenes.rst
+++ b/gdal/doc/source/drivers/vector/plscenes.rst
@@ -21,5 +21,5 @@ See Also
--------
- `Documentation of Planet Scenes Data API
- V1 `__
+ V1 `__
- :ref:`Raster PLMosaic / Planet Mosaics API driver `
diff --git a/gdal/doc/source/drivers/vector/plscenes_data_v1.rst b/gdal/doc/source/drivers/vector/plscenes_data_v1.rst
index 71d583028d4b..e8f416073659 100644
--- a/gdal/doc/source/drivers/vector/plscenes_data_v1.rst
+++ b/gdal/doc/source/drivers/vector/plscenes_data_v1.rst
@@ -207,5 +207,5 @@ See Also
- :ref:`General documentation page for PLScenes
driver `
- `Documentation of Planet Scenes Data API
- v1 `__
+ v1 `__
- :ref:`Raster PLMosaic / Planet Mosaics API driver `
diff --git a/gdal/doc/source/user/coordinate_epoch.rst b/gdal/doc/source/user/coordinate_epoch.rst
index b2591625d6cc..269ac99bb3f6 100644
--- a/gdal/doc/source/user/coordinate_epoch.rst
+++ b/gdal/doc/source/user/coordinate_epoch.rst
@@ -141,31 +141,6 @@ element.
-Shapefile
-+++++++++
-
-The coordinate epoch is encoded as a WKT:2019 string using the ``EPOCH`` subnode of the
-`COORDINATEMETADATA `__
-construct, and put in a sidecar file of extension ``wkt2``. This file has
-precedence over the ``prj`` sidecar file.
-
-::
-
- COORDINATEMETADATA[
- GEOGCRS["WGS 84 (G1762)",
- DYNAMIC[FRAMEEPOCH[2005.0]],
- DATUM["World Geodetic System 1984 (G1762)",
- ELLIPSOID["WGS 84",6378137,298.257223563,LENGTHUNIT["metre",1.0]]
- ],
- CS[ellipsoidal,3],
- AXIS["(lat)",north,ANGLEUNIT["degree",0.0174532925199433]],
- AXIS["(lon)",east,ANGLEUNIT["degree",0.0174532925199433]],
- AXIS["ellipsoidal height (h)",up,LENGTHUNIT["metre",1.0]]
- ],
- EPOCH[2016.47]
- ]
-
-
GDAL VRT
++++++++
diff --git a/gdal/doc/source/user/sql_sqlite_dialect.rst b/gdal/doc/source/user/sql_sqlite_dialect.rst
index facd389a5d12..2b222b32ebe8 100644
--- a/gdal/doc/source/user/sql_sqlite_dialect.rst
+++ b/gdal/doc/source/user/sql_sqlite_dialect.rst
@@ -62,8 +62,8 @@ the following syntax : "other_datasource_name"."layer_name".
SELECT p.*, NAME FROM poly p JOIN "idlink.dbf"."idlink" il USING (eas_id)
-If the master datasource is SQLite database (GeoPackage, SpatiaLite) it is necessary to
-use indirect SQLite dialect. Otherwise additional datasources are never opened but tables to
+If the master datasource is SQLite database (GeoPackage, SpatiaLite) it is necessary to
+use indirect SQLite dialect. Otherwise additional datasources are never opened but tables to
be used in joins are searched from the master database.
.. code-block:: shell
@@ -139,6 +139,25 @@ returns:
PRFEDEA (String) = 35043411
POLYGON ((479819.84375 4765180.5,479690.1875 4765259.5,[...],479819.84375 4765180.5))
+Feature id
+++++++++++
+
+The feature id is a special property of a feature and not treated
+as an attribute of the feature. In some cases it is convenient to be able to
+utilize the feature id in queries and result sets as a regular field. To do
+so use the name ``rowid``. The field wildcard expansions will not include
+the feature id, but it may be explicitly included using a syntax like:
+
+.. code-block::
+
+ SELECT rowid, * FROM nation
+
+It is of course possible to rename it:
+
+.. code-block::
+
+ SELECT rowid AS fid, * FROM nation
+
OGR_STYLE special field
+++++++++++++++++++++++
diff --git a/gdal/frmts/gtiff/libtiff/tif_jpeg.c b/gdal/frmts/gtiff/libtiff/tif_jpeg.c
index e596a3c40aed..907e537f8c8f 100644
--- a/gdal/frmts/gtiff/libtiff/tif_jpeg.c
+++ b/gdal/frmts/gtiff/libtiff/tif_jpeg.c
@@ -1733,123 +1733,30 @@ prepare_JPEGTables(TIFF* tif)
return (1);
}
-#if BITS_IN_JSAMPLE == 8
-/* The two below functions are borrowed to libjpeg, and work around a
- * bug of libjpeg-9d that no longer initializes default Huffman tables
- * in jpeg_set_defaults(). */
-
-/*
- * Huffman table setup routines
- */
-
-static void
-TIFF_add_huff_table (j_compress_ptr cinfo,
- JHUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val)
-/* Define a Huffman table */
-{
- int nsymbols, len;
-
- assert(*htblptr == NULL);
- *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
-
- /* Copy the number-of-symbols-of-each-code-length counts */
- memcpy((*htblptr)->bits, bits, sizeof((*htblptr)->bits));
-
- nsymbols = 0;
- for (len = 1; len <= 16; len++)
- nsymbols += bits[len];
-
- memcpy((*htblptr)->huffval, val, nsymbols);
-
- /* Initialize sent_table FALSE so table will be written to JPEG file. */
- (*htblptr)->sent_table = FALSE;
-}
-
-
+#if defined(JPEG_LIB_VERSION_MAJOR) && (JPEG_LIB_VERSION_MAJOR > 9 || \
+ (JPEG_LIB_VERSION_MAJOR == 9 && JPEG_LIB_VERSION_MINOR >= 4))
+/* This is a modified version of std_huff_tables() from jcparam.c
+ * in libjpeg-9d because it no longer initializes default Huffman
+ * tables in jpeg_set_defaults(). */
static void
TIFF_std_huff_tables (j_compress_ptr cinfo)
-/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
-/* IMPORTANT: these are only valid for 8-bit data precision! */
-{
- static const UINT8 bits_dc_luminance[17] =
- { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
- static const UINT8 val_dc_luminance[] =
- { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
-
- static const UINT8 bits_dc_chrominance[17] =
- { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
- static const UINT8 val_dc_chrominance[] =
- { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
-
- static const UINT8 bits_ac_luminance[17] =
- { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
- static const UINT8 val_ac_luminance[] =
- { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
- 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
- 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
- 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
- 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
- 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
- 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
- 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
- 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
- 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
- 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
- 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
- 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
- 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
- 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
- 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
- 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
- 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
- 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
- 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
- 0xf9, 0xfa };
-
- static const UINT8 bits_ac_chrominance[17] =
- { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
- static const UINT8 val_ac_chrominance[] =
- { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
- 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
- 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
- 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
- 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
- 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
- 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
- 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
- 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
- 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
- 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
- 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
- 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
- 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
- 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
- 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
- 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
- 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
- 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
- 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
- 0xf9, 0xfa };
+{
if( cinfo->dc_huff_tbl_ptrs[0] == NULL )
{
- TIFF_add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[0],
- bits_dc_luminance, val_dc_luminance);
+ (void) jpeg_std_huff_table((j_common_ptr) cinfo, TRUE, 0);
}
if( cinfo->ac_huff_tbl_ptrs[0] == NULL )
{
- TIFF_add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[0],
- bits_ac_luminance, val_ac_luminance);
+ (void) jpeg_std_huff_table((j_common_ptr) cinfo, FALSE, 0);
}
if( cinfo->dc_huff_tbl_ptrs[1] == NULL )
{
- TIFF_add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[1],
- bits_dc_chrominance, val_dc_chrominance);
+ (void) jpeg_std_huff_table((j_common_ptr) cinfo, TRUE, 1);
}
if( cinfo->ac_huff_tbl_ptrs[1] == NULL )
{
- TIFF_add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[1],
- bits_ac_chrominance, val_ac_chrominance);
+ (void) jpeg_std_huff_table((j_common_ptr) cinfo, FALSE, 1);
}
}
#endif
@@ -2024,7 +1931,8 @@ JPEGSetupEncode(TIFF* tif)
if( sp->jpegtables == NULL
|| memcmp(sp->jpegtables,"\0\0\0\0\0\0\0\0\0",8) == 0 )
{
-#if BITS_IN_JSAMPLE == 8
+#if defined(JPEG_LIB_VERSION_MAJOR) && (JPEG_LIB_VERSION_MAJOR > 9 || \
+ (JPEG_LIB_VERSION_MAJOR == 9 && JPEG_LIB_VERSION_MINOR >= 4))
if( (sp->jpegtablesmode & JPEGTABLESMODE_HUFF) != 0 &&
(sp->cinfo.c.dc_huff_tbl_ptrs[0] == NULL ||
sp->cinfo.c.dc_huff_tbl_ptrs[1] == NULL ||
@@ -2032,7 +1940,7 @@ JPEGSetupEncode(TIFF* tif)
sp->cinfo.c.ac_huff_tbl_ptrs[1] == NULL) )
{
/* libjpeg-9d no longer initializes default Huffman tables in */
- /* jpeg_set_defaults(), which is likely a bug. */
+ /* jpeg_set_defaults() */
TIFF_std_huff_tables(&sp->cinfo.c);
}
#endif
diff --git a/gdal/frmts/mrf/GNUmakefile b/gdal/frmts/mrf/GNUmakefile
index fa3cb93d5237..0a04212e8adf 100644
--- a/gdal/frmts/mrf/GNUmakefile
+++ b/gdal/frmts/mrf/GNUmakefile
@@ -48,6 +48,10 @@ XTRA_OPT := $(XTRA_OPT) -DLERC -I../../third_party/LercLib
SUBLIBS := lib-LERCV1
endif
+ifeq ($(BRUNSLI_ENABLED),yes)
+XTRA_OPT := $(XTRA_OPT) -DBRUNSLI $(BRUNSLI_INCLUDE)
+endif
+
CPPFLAGS := $(XTRA_OPT) $(CPPFLAGS)
default: $(PREDEPEND) $(OBJ:.o=.$(OBJ_EXT)) $(SUBLIBS)
diff --git a/gdal/frmts/mrf/JPEG_band.cpp b/gdal/frmts/mrf/JPEG_band.cpp
index b1d365c770a1..94aa28225eab 100644
--- a/gdal/frmts/mrf/JPEG_band.cpp
+++ b/gdal/frmts/mrf/JPEG_band.cpp
@@ -57,6 +57,7 @@
#include "marfa.h"
#include
+#include
CPL_C_START
#include
@@ -67,6 +68,13 @@ CPL_C_END
#include "BitMask2D.h"
#include "Packer_RLE.h"
+#if defined(BRUNSLI)
+#include
+#include
+#include
+#include
+#endif
+
NAMESPACE_MRF_START
typedef BitMap2D<> BitMask;
@@ -342,8 +350,28 @@ CPLErr JPEG_Codec::CompressJPEG(buf_mgr &dst, buf_mgr &src)
CPLFree(rowp);
CPLFree(buffer); // Safe to call on null
- // Figure out the size
- dst.size -= jmgr.free_in_buffer;
+ size_t fullsize = dst.size;
+ // Figure out the size of the JFIF
+ dst.size = fullsize - jmgr.free_in_buffer;
+
+#if defined(BRUNSLI)
+ if (!JFIF) {
+ brunsli::JPEGData bjpg;
+ if (!brunsli::ReadJpeg(reinterpret_cast(dst.buffer), dst.size, brunsli::JPEG_READ_ALL, &bjpg)) {
+ CPLError(CE_Failure, CPLE_AppDefined, "MRF: Error parsing JPEG before conversion to JPEG-XL");
+ return CE_Failure;
+ }
+ std::vector out;
+ out.resize(fullsize);
+ if (!brunsli::BrunsliEncodeJpeg(bjpg, out.data(), &fullsize)) {
+ CPLError(CE_Failure, CPLE_AppDefined, "MRF: JPEG-XL encoding error");
+ return CE_Failure;
+ }
+ // fullsize holds the JPEG XL output size
+ memcpy(dst.buffer, out.data(), fullsize);
+ dst.size = fullsize;
+ }
+#endif
return CE_None;
}
@@ -631,9 +659,67 @@ CPLErr JPEG_Codec::DecompressJPEG(buf_mgr& dst, buf_mgr& isrc)
char CHUNK_NAME[] = "Zen";
size_t CHUNK_NAME_SIZE = strlen(CHUNK_NAME) + 1;
+#if defined(BRUNSLI)
+// Append to end of out vector
+static size_t out_callback(void* out, const GByte* data, size_t size) {
+ auto outv = static_cast *>(out);
+ outv->insert(outv->end(), data, data + size);
+ return size;
+}
+#endif // BRUNSLI
+
+const static GUInt32 JPEG_SIG = 0xe0ffd8ff; // JPEG 4CC code
+const static GUInt32 BRUN_SIG = 0xd242040a; // Brunsli 4CC code, native
+
+static bool isbrunsli(const buf_mgr& src) {
+ GUInt32 signature;
+ memcpy(&signature, src.buffer, sizeof(signature));
+ if (BRUN_SIG == CPL_LSBWORD32(signature))
+ return true;
+ return false;
+}
+
+bool JPEG_Codec::IsJPEG(const buf_mgr& src)
+{
+ if (isbrunsli(src))
+ return true;
+ GUInt32 signature;
+ memcpy(&signature, src.buffer, sizeof(signature));
+ if (JPEG_SIG == CPL_LSBWORD32(signature))
+ return true;
+ return false;
+}
+
// Type dependent dispachers
CPLErr JPEG_Band::Decompress(buf_mgr &dst, buf_mgr &src) {
+ if (isbrunsli(src)) { // Need conversion to JPEG first
+#if !defined(BRUNSLI)
+ CPLError(CE_Failure, CPLE_NotSupported, "MRF: JPEG-XL content, yet this GDAL was not compiled with BRUNSLI support");
+ return CE_Failure;
+#else
+ std::vector out;
+ brunsli::JPEGData bjpg;
+ // This call reads the all the input data internally and stores it in the bjpg structure
+ auto status = brunsli::BrunsliDecodeJpeg(reinterpret_cast(src.buffer), src.size, &bjpg);
+ if (status != brunsli::BRUNSLI_OK) {
+ CPLError(CE_Failure, CPLE_AppDefined, "MRF: JPEG-XL (brunsli) tile decode failed");
+ return CE_Failure;
+ }
+
+ brunsli::JPEGOutput writer(out_callback, &out);
+
+ if (!brunsli::WriteJpeg(bjpg, writer)) {
+ CPLError(CE_Failure, CPLE_AppDefined, "MRF: JPEG-XL (brunsli) to JPEG conversion failed");
+ return CE_Failure;
+ }
+
+ buf_mgr jfif_src;
+ jfif_src.buffer = reinterpret_cast(out.data());
+ jfif_src.size = out.size();
+ return Decompress(dst, jfif_src); // Call itself with JFIF JPEG source
+#endif // BRUNSLI
+ }
#if defined(LIBJPEG_12_H)
if (GDT_Byte != img.dt)
return codec.DecompressJPEG12(dst, src);
@@ -678,10 +764,13 @@ JPEG_Band::JPEG_Band( MRFDataset *pDS, const ILImage &image,
codec.sameres = TRUE;
}
- if( GDT_Byte == image.dt )
- codec.optimize = GetOptlist().FetchBoolean("OPTIMIZE", FALSE);
- else
+ if( GDT_Byte == image.dt ) {
+ codec.optimize = GetOptlist().FetchBoolean("OPTIMIZE", FALSE) != FALSE;
+ codec.JFIF = GetOptlist().FetchBoolean("JFIF", FALSE) != FALSE;
+ }
+ else {
codec.optimize = true; // Required for 12bit
+ }
}
#endif
diff --git a/gdal/frmts/mrf/JPNG_band.cpp b/gdal/frmts/mrf/JPNG_band.cpp
index 20da48e8a80d..58888eef3777 100644
--- a/gdal/frmts/mrf/JPNG_band.cpp
+++ b/gdal/frmts/mrf/JPNG_band.cpp
@@ -86,16 +86,15 @@ static CPLErr initBuffer(buf_mgr &b) {
}
CPLErr JPNG_Band::Decompress(buf_mgr &dst, buf_mgr &src) {
- const static GUInt32 JPEG_SIG = 0xe0ffd8ff; // JPEG 4CC code
const static GUInt32 PNG_SIG = 0x474e5089; // PNG 4CC code
CPLErr retval = CE_None;
ILImage image(img);
GUInt32 signature;
- memcpy(&signature, src.buffer, sizeof(GUInt32));
+ memcpy(&signature, src.buffer, sizeof(signature));
// test against an LSB signature
- if (JPEG_SIG == CPL_LSBWORD32(signature)) {
+ if (JPEG_Codec::IsJPEG(src)) {
image.pagesize.c -= 1;
JPEG_Codec codec(image);
@@ -142,6 +141,7 @@ CPLErr JPNG_Band::Compress(buf_mgr &dst, buf_mgr &src) {
codec.rgb = rgb;
codec.optimize = optimize;
codec.sameres = sameres;
+ codec.JFIF = JFIF;
retval = codec.CompressJPEG(dst, temp);
}
else if (!AllAlpha<0>(src, image)) {
@@ -165,7 +165,8 @@ JPNG_Band::JPNG_Band( MRFDataset *pDS, const ILImage &image,
MRFRasterBand(pDS, image, b, level),
rgb(FALSE),
sameres(FALSE),
- optimize(false)
+ optimize(false),
+ JFIF(false)
{ // Check error conditions
if (image.dt != GDT_Byte) {
CPLError(CE_Failure, CPLE_NotSupported, "Data type not supported by MRF JPNG");
@@ -186,7 +187,8 @@ JPNG_Band::JPNG_Band( MRFDataset *pDS, const ILImage &image,
sameres = TRUE;
}
- optimize = GetOptlist().FetchBoolean("OPTIMIZE", FALSE);
+ optimize = GetOptlist().FetchBoolean("OPTIMIZE", FALSE) != FALSE;
+ JFIF = GetOptlist().FetchBoolean("JFIF", FALSE) != FALSE;
// PNGs and JPGs can be larger than the source, especially for
// small page size.
diff --git a/gdal/frmts/mrf/makefile.vc b/gdal/frmts/mrf/makefile.vc
index de52b53fc39c..91a5d35f6446 100644
--- a/gdal/frmts/mrf/makefile.vc
+++ b/gdal/frmts/mrf/makefile.vc
@@ -25,6 +25,14 @@ EXTRAFLAGS = -DLERC -ILERCV1 -I../../third_party/LercLib $(EXTRAFLAGS)
OBJ = $(LERC1) LERC_Band.obj $(OBJ)
!ENDIF
+# Brotli is needed for brunsli
+!IFDEF BRUNSLI_DIR
+!IFDEF BROTLI_DIR
+EXTRAFLAGS = $(EXTRAFLAGS) -DBRUNSLI -I$(BRUNSLI_INC)
+EXTRA_LINK_FLAGS = $(EXTRA_LINK_FLAGS) $(BRUNSLI_LIB)
+!ENDIF
+!ENDIF
+
!IFDEF JPEG_EXTERNAL_LIB
EXTRAFLAGS = -I$(JPEGDIR) $(EXTRAFLAGS)
!ELSE
diff --git a/gdal/frmts/mrf/marfa.h b/gdal/frmts/mrf/marfa.h
index 7e3211bb7375..4f0d73c7e697 100644
--- a/gdal/frmts/mrf/marfa.h
+++ b/gdal/frmts/mrf/marfa.h
@@ -643,11 +643,14 @@ class PNG_Band final: public MRFRasterBand {
class JPEG_Codec {
public:
- explicit JPEG_Codec(const ILImage &image) : img(image), sameres(FALSE), rgb(FALSE), optimize(false) {}
+ explicit JPEG_Codec(const ILImage &image) : img(image), sameres(FALSE), rgb(FALSE), optimize(false), JFIF(false) {}
CPLErr CompressJPEG(buf_mgr &dst, buf_mgr &src);
CPLErr DecompressJPEG(buf_mgr &dst, buf_mgr &src);
+ // Returns true for both JPEG and JPEG-XL (brunsli)
+ static bool IsJPEG(const buf_mgr& src);
+
#if defined(JPEG12_SUPPORTED) // Internal only
#define LIBJPEG_12_H "../jpeg/libjpeg12/jpeglib.h"
CPLErr CompressJPEG12(buf_mgr &dst, buf_mgr &src);
@@ -657,12 +660,14 @@ class JPEG_Codec {
const ILImage img;
// JPEG specific flags
- bool sameres;
- bool rgb;
- bool optimize;
+ bool sameres; // No color space subsample
+ bool rgb; // No conversion to YCbCr
+ bool optimize; // Optimize Huffman tables
+ bool JFIF; // Write JFIF only
private:
- JPEG_Codec& operator= (const JPEG_Codec& src); // not implemented. but suppress MSVC warning about 'assignment operator could not be generated'
+ // not implemented. but suppress MSVC warning about 'assignment operator could not be generated'
+ JPEG_Codec& operator= (const JPEG_Codec& src);
};
class JPEG_Band final: public MRFRasterBand {
@@ -690,7 +695,7 @@ class JPNG_Band final: public MRFRasterBand {
CPLErr CompressJPNG(buf_mgr &dst, buf_mgr &src);
CPLErr DecompressJPNG(buf_mgr &dst, buf_mgr &src);
- bool rgb, sameres, optimize;
+ bool rgb, sameres, optimize, JFIF;
};
class Raw_Band final: public MRFRasterBand {
diff --git a/gdal/frmts/mrf/mrf_util.cpp b/gdal/frmts/mrf/mrf_util.cpp
index e9864a20d9f5..6ad4f1843d01 100644
--- a/gdal/frmts/mrf/mrf_util.cpp
+++ b/gdal/frmts/mrf/mrf_util.cpp
@@ -575,7 +575,6 @@ void GDALRegister_mrf() {
" \n"
" "
" \n"
- " \n"
" \n"
" \n"
" \n"
@@ -595,6 +594,21 @@ void GDALRegister_mrf() {
" RGB"
" YCC"
" \n"
+ " "
"\n");
driver->SetMetadataItem(
diff --git a/gdal/frmts/openjpeg/openjpegdataset.cpp b/gdal/frmts/openjpeg/openjpegdataset.cpp
index 0f617b0d9edb..23fc520da2d5 100644
--- a/gdal/frmts/openjpeg/openjpegdataset.cpp
+++ b/gdal/frmts/openjpeg/openjpegdataset.cpp
@@ -206,6 +206,7 @@ class JP2OpenJPEGDataset final: public GDALJP2AbstractDataset
{
friend class JP2OpenJPEGRasterBand;
+ std::string m_osFilename;
VSILFILE *fp = nullptr; /* Large FILE API */
vsi_l_offset nCodeStreamStart = 0;
vsi_l_offset nCodeStreamLength = 0;
@@ -525,10 +526,10 @@ void JP2OpenJPEGDataset::JP2OpenJPEGReadBlockInThread(void* userdata)
int nPairs = (int)poJob->oPairs.size();
int nBandCount = poJob->nBandCount;
int* panBandMap = poJob->panBandMap;
- VSILFILE* fp = VSIFOpenL(poGDS->GetDescription(), "rb");
+ VSILFILE* fp = VSIFOpenL(poGDS->m_osFilename.c_str(), "rb");
if( fp == nullptr )
{
- CPLDebug("OPENJPEG", "Cannot open %s", poGDS->GetDescription());
+ CPLDebug("OPENJPEG", "Cannot open %s", poGDS->m_osFilename.c_str());
poJob->bSuccess = false;
//VSIFree(pDummy);
return;
@@ -1872,6 +1873,7 @@ GDALDataset *JP2OpenJPEGDataset::Open( GDALOpenInfo * poOpenInfo )
int iBand;
poDS = new JP2OpenJPEGDataset();
+ poDS->m_osFilename = poOpenInfo->pszFilename;
if( eCodecFormat == OPJ_CODEC_JP2 )
poDS->eAccess = poOpenInfo->eAccess;
poDS->eColorSpace = psImage->color_space;
@@ -2188,6 +2190,7 @@ GDALDataset *JP2OpenJPEGDataset::Open( GDALOpenInfo * poOpenInfo )
poDS->papoOverviewDS,
(poDS->nOverviewCount + 1) * sizeof(JP2OpenJPEGDataset*));
JP2OpenJPEGDataset* poODS = new JP2OpenJPEGDataset();
+ poODS->m_osFilename = poDS->m_osFilename;
poODS->nParentXSize = poDS->nRasterXSize;
poODS->nParentYSize = poDS->nRasterYSize;
poODS->SetDescription( poOpenInfo->pszFilename );
diff --git a/gdal/nmake.opt b/gdal/nmake.opt
index a2ab879796a4..326ed49b65a1 100644
--- a/gdal/nmake.opt
+++ b/gdal/nmake.opt
@@ -928,6 +928,16 @@ ADD_LIBS =
HAVE_LERC=internal
!ENDIF
+# Uncomment to build MRF with brunsli support
+# BRUNSLI_DIR = \brunsli
+# BROTLI_DIR = $(BRUNSLI_DIR)
+# BRUNSLI_INC = -I$(BRUNSLI_DIR)/include
+# BRUNSLI_LIB_DIR = $(BRUNSLI_DIR)/lib
+# BROTLI_LIB_DIR = $(BROTLI_DIR)/lib
+# BRUNSLI_LIB = $(BRUNSLI_LIB_DIR)/brunslicommon-static.lib $(BRUNSLI_LIB_DIR)/brunslienc-static.lib $(BRUNSLI_LIB_DIR)/brunslidec-static.lib
+# BROTLI_LIB = $(BROTLI_LIB_DIR)/brotlicommon-static.lib $(BROTLI_LIB_DIR)/brotlienc-static.lib $(BROTLI_LIB_DIR)/brotlidec-static.lib
+
+
# Comment out the following if you want to build JPEGLS with CHARLS support
#CHARLS_INC=-IE:\work\GIS\gdal\supportlibs\charls\include\
#CHARLS_LIB=e:\work\GIS\gdal\supportlibs\charls\bin\Release\x86\CharLS.lib
@@ -1156,5 +1166,5 @@ EXTERNAL_LIBS = $(OGDILIB) $(XERCES_LIB) $(EXPAT_LIB) $(OCI_LIB) $(PG_LIB) \
$(MRSID_LIDAR_LIB) $(LIBKML_LIBS) $(SOSI_LIBS) $(PDF_LIB_LINK) $(LZMA_LIBS) $(ZSTD_LIBS) \
$(LIBICONV_LIBRARY) $(WEBP_LIBS) $(TILEDB_LIBS) $(FGDB_LIB_LINK) $(FREEXL_LIBS) $(GTA_LIBS) \
$(INGRES_LIB) $(LIBXML2_LIB) $(PCRE_LIB) $(MONGODB_LIB_LINK) $(MONGODBV3_LIB_LINK) $(CRYPTOPP_LIB) $(OPENSSL_LIB) $(CHARLS_LIB) ws2_32.lib \
- $(RDB_LIB) $(CRUNCH_LIB) $(OPENEXR_LIB) $(HEIF_LIB) $(LERC_LIB) \
+ $(RDB_LIB) $(CRUNCH_LIB) $(OPENEXR_LIB) $(HEIF_LIB) $(LERC_LIB) $(BROTLI_LIB) $(BRUNSLI_LIB)\
kernel32.lib psapi.lib wbemuuid.lib
diff --git a/gdal/ogr/ogrfeature.cpp b/gdal/ogr/ogrfeature.cpp
index 448b56d6aba0..d0bcec624b04 100644
--- a/gdal/ogr/ogrfeature.cpp
+++ b/gdal/ogr/ogrfeature.cpp
@@ -3289,15 +3289,22 @@ char* OGRFeature::GetFieldAsSerializedJSon( int iField ) const
OGRFieldType eType = poFDefn->GetType();
if( eType == OFTStringList )
{
- json_object* poObj = json_object_new_array();
char** papszValues = GetFieldAsStringList(iField);
- for( int i=0; papszValues[i] != nullptr; i++)
+ if( papszValues == nullptr )
{
- json_object_array_add( poObj,
- json_object_new_string(papszValues[i]) );
+ pszRet = CPLStrdup("[]");
+ }
+ else
+ {
+ json_object* poObj = json_object_new_array();
+ for( int i=0; papszValues[i] != nullptr; i++)
+ {
+ json_object_array_add( poObj,
+ json_object_new_string(papszValues[i]) );
+ }
+ pszRet = CPLStrdup( json_object_to_json_string(poObj) );
+ json_object_put(poObj);
}
- pszRet = CPLStrdup( json_object_to_json_string(poObj) );
- json_object_put(poObj);
}
else if( eType == OFTIntegerList )
{
diff --git a/gdal/ogr/ogrsf_frmts/gpkg/ogrgeopackagetablelayer.cpp b/gdal/ogr/ogrsf_frmts/gpkg/ogrgeopackagetablelayer.cpp
index df0dd2ba5351..efffb29adf7c 100644
--- a/gdal/ogr/ogrsf_frmts/gpkg/ogrgeopackagetablelayer.cpp
+++ b/gdal/ogr/ogrsf_frmts/gpkg/ogrgeopackagetablelayer.cpp
@@ -140,29 +140,41 @@ OGRErr OGRGeoPackageTableLayer::BuildColumns()
{
CPLFree(panFieldOrdinals);
panFieldOrdinals = (int *) CPLMalloc( sizeof(int) * m_poFeatureDefn->GetFieldCount() );
+ int iCurCol = 0;
/* Always start with a primary key */
- CPLString soColumns = "m.";
- soColumns += m_pszFidColumn ?
- "\"" + SQLEscapeName(m_pszFidColumn) + "\"" : "_rowid_";
- iFIDCol = 0;
+ CPLString soColumns;
+ if( m_bIsTable || m_pszFidColumn != nullptr )
+ {
+ soColumns += "m.";
+ soColumns += m_pszFidColumn ?
+ "\"" + SQLEscapeName(m_pszFidColumn) + "\"" : "_rowid_";
+ iFIDCol = iCurCol;
+ iCurCol ++;
+ }
/* Add a geometry column if there is one (just one) */
if ( m_poFeatureDefn->GetGeomFieldCount() )
{
- soColumns += ", m.\"";
+ if( !soColumns.empty() )
+ soColumns += ", ";
+ soColumns += "m.\"";
soColumns += SQLEscapeName(m_poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef());
soColumns += "\"";
- iGeomCol = 1;
+ iGeomCol = iCurCol;
+ iCurCol ++;
}
/* Add all the attribute columns */
for( int i = 0; i < m_poFeatureDefn->GetFieldCount(); i++ )
{
- soColumns += ", m.\"";
+ if( !soColumns.empty() )
+ soColumns += ", ";
+ soColumns += "m.\"";
soColumns += SQLEscapeName(m_poFeatureDefn->GetFieldDefn(i)->GetNameRef());
soColumns += "\"";
- panFieldOrdinals[i] = 1 + (iGeomCol >= 0) + i;
+ panFieldOrdinals[i] = iCurCol;
+ iCurCol ++;
}
m_soColumns = soColumns;
@@ -1196,6 +1208,17 @@ void OGRGeoPackageTableLayer::InitView()
// We cannot just take the FID of a source table as
// a FID because of potential joins that would result
// in multiple records with same source FID.
+ CPLFree(m_pszFidColumn);
+ m_pszFidColumn = CPLStrdup(osColName);
+ m_poFeatureDefn->DeleteFieldDefn(
+ m_poFeatureDefn->GetFieldIndex(osColName));
+ }
+ else if( iCol == 0 &&
+ sqlite3_column_type( hStmt, iCol ) == SQLITE_INTEGER )
+ {
+ // Assume the first column of integer type is the FID column
+ // per the latest requirements of the GPKG spec
+ CPLFree(m_pszFidColumn);
m_pszFidColumn = CPLStrdup(osColName);
m_poFeatureDefn->DeleteFieldDefn(
m_poFeatureDefn->GetFieldIndex(osColName));
diff --git a/gdal/ogr/ogrsf_frmts/plscenes/ogrplscenesdatav1dataset.cpp b/gdal/ogr/ogrsf_frmts/plscenes/ogrplscenesdatav1dataset.cpp
index b330f8f1f62f..26037e405cfa 100644
--- a/gdal/ogr/ogrsf_frmts/plscenes/ogrplscenesdatav1dataset.cpp
+++ b/gdal/ogr/ogrsf_frmts/plscenes/ogrplscenesdatav1dataset.cpp
@@ -571,7 +571,7 @@ GDALDataset* OGRPLScenesDataV1Dataset::OpenRasterScene(GDALOpenInfo* poOpenInfo,
if( bUseVSICURL && !(STARTS_WITH(m_osBaseURL, "/vsimem/")) )
{
char* pszEscapedURL = CPLEscapeString(osRasterURL, -1, CPLES_URL);
- CPLString osTmpURL("/vsicurl?use_head=no&max_retry=3&empty_dir=yes&url=");
+ CPLString osTmpURL("/vsicurl?use_head=no&max_retry=3&empty_dir=yes&use_redirect_url_if_no_query_string_params=yes&url=");
osTmpURL += pszEscapedURL;
CPLFree(pszEscapedURL);
CPLDebug("PLSCENES", "URL = %s", osTmpURL.c_str());
@@ -594,6 +594,10 @@ GDALDataset* OGRPLScenesDataV1Dataset::OpenRasterScene(GDALOpenInfo* poOpenInfo,
papszAllowedDrivers = CSLAddString(papszAllowedDrivers, "PNG");
papszAllowedDrivers = CSLAddString(papszAllowedDrivers, "JPEG");
papszAllowedDrivers = CSLAddString(papszAllowedDrivers, "NITF");
+ papszAllowedDrivers = CSLAddString(papszAllowedDrivers, "JP2KAK");
+ papszAllowedDrivers = CSLAddString(papszAllowedDrivers, "JP2ECW");
+ papszAllowedDrivers = CSLAddString(papszAllowedDrivers, "JP2MrSID");
+ papszAllowedDrivers = CSLAddString(papszAllowedDrivers, "JP2OpenJPEG");
GDALDataset* poOutDS = (GDALDataset*) GDALOpenEx(osRasterURL, GDAL_OF_RASTER,
papszAllowedDrivers, nullptr, nullptr);
CSLDestroy(papszAllowedDrivers);
diff --git a/gdal/ogr/ogrsf_frmts/sqlite/ogr_sqlite.h b/gdal/ogr/ogrsf_frmts/sqlite/ogr_sqlite.h
index 1ee0e43488a3..d889a818fbc7 100644
--- a/gdal/ogr/ogrsf_frmts/sqlite/ogr_sqlite.h
+++ b/gdal/ogr/ogrsf_frmts/sqlite/ogr_sqlite.h
@@ -343,6 +343,8 @@ class OGRSQLiteLayer CPL_NON_FINAL: public OGRLayer, public IOGRSQLiteGetSpatial
class OGRSQLiteTableLayer final: public OGRSQLiteLayer
{
+ bool m_bIsTable = true;
+
int bLaunderColumnNames;
int bSpatialite2D;
@@ -407,8 +409,9 @@ class OGRSQLiteTableLayer final: public OGRSQLiteLayer
virtual ~OGRSQLiteTableLayer();
CPLErr Initialize( const char *pszTableName,
- int bIsVirtualShapeIn,
- int bDeferredCreation);
+ bool bIsTable,
+ bool bIsVirtualShapeIn,
+ bool bDeferredCreation);
void SetCreationParameters( const char *pszFIDColumnName,
OGRwkbGeometryType eGeomType,
const char *pszGeomFormat,
@@ -826,7 +829,8 @@ class OGRSQLiteDataSource final : public OGRSQLiteBaseDataSource
int Create( const char *, char **papszOptions );
int OpenTable( const char *pszTableName,
- int bIsVirtualShapeIn = FALSE );
+ bool IsTable,
+ bool bIsVirtualShape );
int OpenView( const char *pszViewName,
const char *pszViewGeometry,
const char *pszViewRowid,
diff --git a/gdal/ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp b/gdal/ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp
index 073765a7cc30..53a08f33693c 100644
--- a/gdal/ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp
+++ b/gdal/ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp
@@ -1586,7 +1586,7 @@ int OGRSQLiteDataSource::Open( GDALOpenInfo* poOpenInfo)
continue;
if( GDALDataset::GetLayerByName(pszTableName) == nullptr )
- OpenTable( pszTableName );
+ OpenTable( pszTableName, true, false );
if (bListAllTables)
CPLHashSetInsert(hSet, CPLStrdup(pszTableName));
@@ -1795,7 +1795,7 @@ int OGRSQLiteDataSource::Open( GDALOpenInfo* poOpenInfo)
}
if( GDALDataset::GetLayerByName(pszTableName) == nullptr )
- OpenTable( pszTableName);
+ OpenTable( pszTableName, true, false);
if (bListAllTables)
CPLHashSetInsert(hSet, CPLStrdup(pszTableName));
}
@@ -1906,10 +1906,10 @@ int OGRSQLiteDataSource::Open( GDALOpenInfo* poOpenInfo)
all_tables:
rc = sqlite3_get_table( hDB,
- "SELECT name FROM sqlite_master "
+ "SELECT name, type FROM sqlite_master "
"WHERE type IN ('table','view') "
"UNION ALL "
- "SELECT name FROM sqlite_temp_master "
+ "SELECT name, type FROM sqlite_temp_master "
"WHERE type IN ('table','view') "
"ORDER BY 1 "
"LIMIT 10000",
@@ -1928,9 +1928,13 @@ int OGRSQLiteDataSource::Open( GDALOpenInfo* poOpenInfo)
for( int iRow = 0; iRow < nRowCount; iRow++ )
{
- const char* pszTableName = papszResult[iRow+1];
+ const char* pszTableName = papszResult[2*(iRow+1)+0];
+ const char* pszType = papszResult[2*(iRow+1)+1];
if( pszTableName != nullptr && CPLHashSetLookup(hSet, pszTableName) == nullptr )
- OpenTable( pszTableName );
+ {
+ const bool bIsTable = pszType != nullptr && strcmp(pszType, "table") == 0;
+ OpenTable( pszTableName, bIsTable, false );
+ }
}
sqlite3_free_table(papszResult);
@@ -1970,7 +1974,7 @@ int OGRSQLiteDataSource::OpenVirtualTable(const char* pszName, const char* pszSQ
}
}
- if (OpenTable(pszName, pszVirtualShape != nullptr))
+ if (OpenTable(pszName, true, pszVirtualShape != nullptr))
{
OGRSQLiteLayer* poLayer = papoLayers[nLayers-1];
if( poLayer->GetLayerDefn()->GetGeomFieldCount() == 1 )
@@ -2005,14 +2009,15 @@ int OGRSQLiteDataSource::OpenVirtualTable(const char* pszName, const char* pszSQ
/************************************************************************/
int OGRSQLiteDataSource::OpenTable( const char *pszTableName,
- int bIsVirtualShapeIn )
+ bool bIsTable,
+ bool bIsVirtualShape )
{
/* -------------------------------------------------------------------- */
/* Create the layer object. */
/* -------------------------------------------------------------------- */
OGRSQLiteTableLayer *poLayer = new OGRSQLiteTableLayer( this );
- if( poLayer->Initialize( pszTableName, bIsVirtualShapeIn, FALSE) != CE_None )
+ if( poLayer->Initialize( pszTableName, bIsTable, bIsVirtualShape, false) != CE_None )
{
delete poLayer;
return FALSE;
@@ -2126,7 +2131,35 @@ OGRLayer *OGRSQLiteDataSource::GetLayerByName( const char* pszLayerName )
return apoInvisibleLayers[i];
}
- if( !OpenTable(pszLayerName) )
+ std::string osName(pszLayerName);
+ bool bIsTable = true;
+ for(int i = 0; i < 2; i++ )
+ {
+ char* pszSQL = sqlite3_mprintf("SELECT type FROM sqlite_master "
+ "WHERE type IN ('table', 'view') AND "
+ "lower(name) = lower('%q')",
+ osName.c_str());
+ int nRowCount = 0;
+ char** papszResult = nullptr;
+ CPL_IGNORE_RET_VAL(
+ sqlite3_get_table( hDB, pszSQL, &papszResult, &nRowCount, nullptr, nullptr ));
+ if( papszResult && nRowCount == 1 && papszResult[1] )
+ bIsTable = strcmp(papszResult[1], "table") == 0;
+ sqlite3_free_table(papszResult);
+ sqlite3_free(pszSQL);
+ if( i == 0 && nRowCount == 0 )
+ {
+ const auto nParenthesis = osName.find('(');
+ if( nParenthesis != std::string::npos && osName.back() == ')' )
+ {
+ osName.resize(nParenthesis);
+ continue;
+ }
+ }
+ break;
+ }
+
+ if( !OpenTable(pszLayerName, bIsTable, false) )
return nullptr;
poLayer = papoLayers[nLayers-1];
@@ -2168,7 +2201,7 @@ OGRLayer *OGRSQLiteDataSource::GetLayerByNameNotVisible( const char* pszLayerNam
/* Create the layer object. */
/* -------------------------------------------------------------------- */
OGRSQLiteTableLayer *poLayer = new OGRSQLiteTableLayer( this );
- if( poLayer->Initialize( pszLayerName, FALSE, FALSE) != CE_None )
+ if( poLayer->Initialize( pszLayerName, true, false, false) != CE_None )
{
delete poLayer;
return nullptr;
@@ -2695,7 +2728,7 @@ OGRSQLiteDataSource::ICreateLayer( const char * pszLayerNameIn,
/* -------------------------------------------------------------------- */
OGRSQLiteTableLayer *poLayer = new OGRSQLiteTableLayer( this );
- poLayer->Initialize( pszLayerName, FALSE, TRUE ) ;
+ poLayer->Initialize( pszLayerName, true, false, true ) ;
OGRSpatialReference* poSRSClone = poSRS;
if( poSRSClone )
{
diff --git a/gdal/ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp b/gdal/ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp
index ebbf8a00b541..cffe6bce227a 100644
--- a/gdal/ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp
+++ b/gdal/ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp
@@ -161,11 +161,13 @@ void OGRSQLiteTableLayer::ClearInsertStmt()
/************************************************************************/
CPLErr OGRSQLiteTableLayer::Initialize( const char *pszTableNameIn,
- int bIsVirtualShapeIn,
- int bDeferredCreationIn )
+ bool bIsTable,
+ bool bIsVirtualShapeIn,
+ bool bDeferredCreationIn )
{
SetDescription( pszTableNameIn );
+ m_bIsTable = bIsTable;
bIsVirtualShape = bIsVirtualShapeIn;
pszTableName = CPLStrdup(pszTableNameIn);
bDeferredCreation = bDeferredCreationIn;
@@ -338,7 +340,9 @@ CPLErr OGRSQLiteTableLayer::EstablishFeatureDefn(const char* pszGeomCol)
/* -------------------------------------------------------------------- */
const char *pszSQL =
- CPLSPrintf("SELECT _rowid_, * FROM '%s' LIMIT 1", pszEscapedTableName);
+ CPLSPrintf("SELECT %s* FROM '%s' LIMIT 1",
+ m_bIsTable ? "_rowid_, " : "",
+ pszEscapedTableName);
sqlite3_stmt *hColStmt = nullptr;
int rc = sqlite3_prepare_v2( hDB, pszSQL, -1, &hColStmt, nullptr );
@@ -371,8 +375,11 @@ CPLErr OGRSQLiteTableLayer::EstablishFeatureDefn(const char* pszGeomCol)
/* name if the rowid corresponds to another primary key */
/* column. */
/* -------------------------------------------------------------------- */
- CPLFree( pszFIDColumn );
- pszFIDColumn = CPLStrdup(SQLUnescape(sqlite3_column_name( hColStmt, 0 )));
+ if( m_bIsTable )
+ {
+ CPLFree( pszFIDColumn );
+ pszFIDColumn = CPLStrdup(SQLUnescape(sqlite3_column_name( hColStmt, 0 )));
+ }
/* -------------------------------------------------------------------- */
/* Collect the rest of the fields. */
@@ -737,9 +744,10 @@ OGRErr OGRSQLiteTableLayer::ResetStatement()
iNextShapeId = 0;
- osSQL.Printf( "SELECT _rowid_, * FROM '%s' %s",
- pszEscapedTableName,
- osWHERE.c_str() );
+ osSQL.Printf( "SELECT %s* FROM '%s' %s",
+ m_bIsTable ? "_rowid_, " : "",
+ pszEscapedTableName,
+ osWHERE.c_str() );
#ifdef DEBUG_VERBOSE
CPLDebug("SQLite", "%s", osSQL.c_str());
#endif
diff --git a/gdal/port/cpl_vsil_curl.cpp b/gdal/port/cpl_vsil_curl.cpp
index 7e400fd1fe66..b84e949b215a 100644
--- a/gdal/port/cpl_vsil_curl.cpp
+++ b/gdal/port/cpl_vsil_curl.cpp
@@ -272,6 +272,7 @@ static CPLString VSICurlGetURLFromFilename(const char* pszFilename,
int* pnMaxRetry,
double* pdfRetryDelay,
bool* pbUseHead,
+ bool* pbUseRedirectURLIfNoQueryStringParams,
bool* pbListDir,
bool* pbEmptyDir,
char*** ppapszHTTPOptions)
@@ -313,11 +314,17 @@ static CPLString VSICurlGetURLFromFilename(const char* pszFilename,
if( pdfRetryDelay )
*pdfRetryDelay = CPLAtof(pszValue);
}
- else if( EQUAL(pszKey, "use_head") )
+ else if( EQUAL(pszKey, "use_head") )
{
if( pbUseHead )
*pbUseHead = CPLTestBool(pszValue);
}
+ else if( EQUAL(pszKey, "use_redirect_url_if_no_query_string_params") )
+ {
+ /* Undocumented. Used by PLScenes driver */
+ if( pbUseRedirectURLIfNoQueryStringParams )
+ *pbUseRedirectURLIfNoQueryStringParams = CPLTestBool(pszValue);
+ }
else if( EQUAL(pszKey, "list_dir") )
{
if( pbListDir )
@@ -327,7 +334,7 @@ static CPLString VSICurlGetURLFromFilename(const char* pszFilename,
{
/* Undocumented. Used by PLScenes driver */
/* This more or less emulates the behavior of
- * GDAL_DISABLE_READDIR_ON_OPEN=EMPTY_DIR */
+ * GDAL_DISABLE_READDIR_ON_OPEN=EMPTY_DIR */
if( pbEmptyDir )
*pbEmptyDir = CPLTestBool(pszValue);
}
@@ -408,6 +415,7 @@ VSICurlHandle::VSICurlHandle( VSICurlFilesystemHandler* poFSIn,
&m_nMaxRetry,
&m_dfRetryDelay,
&m_bUseHead,
+ &m_bUseRedirectURLIfNoQueryStringParams,
nullptr, nullptr,
&m_papszHTTPOptions));
}
@@ -1028,6 +1036,13 @@ vsi_l_offset VSICurlHandle::GetFileSizeOrHeaders( bool bSetError, bool bGetHeade
CPLDebug(poFS->GetDebugKey(),
"Effective URL: %s", osEffectiveURL.c_str());
+ if( m_bUseRedirectURLIfNoQueryStringParams &&
+ osEffectiveURL.find('?') == std::string::npos )
+ {
+ oFileProp.osRedirectURL = osEffectiveURL;
+ poFS->SetCachedFileProp(m_pszURL, oFileProp);
+ }
+
// Is this is a redirect to a S3 URL?
if( VSICurlIsS3LikeSignedURL(osEffectiveURL) &&
!VSICurlIsS3LikeSignedURL(osURL) )
@@ -1383,6 +1398,12 @@ CPLString VSICurlHandle::GetRedirectURLIfValid(bool& bHasExpired)
bHasExpired = true;
}
}
+ else if( !oFileProp.osRedirectURL.empty() )
+ {
+ osURL = oFileProp.osRedirectURL;
+ bHasExpired = false;
+ }
+
return osURL;
}
@@ -3149,7 +3170,7 @@ VSIVirtualHandle* VSICurlFilesystemHandler::Open( const char *pszFilename,
bool bEmptyDir = false;
CPL_IGNORE_RET_VAL(
VSICurlGetURLFromFilename(pszFilename, nullptr, nullptr, nullptr,
- &bListDir, &bEmptyDir, nullptr));
+ nullptr, &bListDir, &bEmptyDir, nullptr));
const char* pszOptionVal =
CPLGetConfigOption( "GDAL_DISABLE_READDIR_ON_OPEN", "NO" );
@@ -3404,7 +3425,7 @@ char** VSICurlFilesystemHandler::ParseHTMLFileList( const char* pszFilename,
*pbGotFileList = false;
CPLString osURL(VSICurlGetURLFromFilename(pszFilename, nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr));
+ nullptr, nullptr, nullptr, nullptr));
const char* pszDir = nullptr;
if( STARTS_WITH_CI(osURL, "http://") )
pszDir = strchr(osURL.c_str() + strlen("http://"), '/');
@@ -3757,7 +3778,7 @@ static bool VSICurlParseFullFTPLine( char* pszLine,
CPLString
VSICurlFilesystemHandler::GetURLFromFilename( const CPLString& osFilename )
{
- return VSICurlGetURLFromFilename(osFilename, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
+ return VSICurlGetURLFromFilename(osFilename, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
}
/************************************************************************/
@@ -3788,7 +3809,7 @@ char** VSICurlFilesystemHandler::GetFileList(const char *pszDirname,
bool bListDir = true;
bool bEmptyDir = false;
CPLString osURL(
- VSICurlGetURLFromFilename(pszDirname, nullptr, nullptr, nullptr,
+ VSICurlGetURLFromFilename(pszDirname, nullptr, nullptr, nullptr, nullptr,
&bListDir, &bEmptyDir, nullptr));
if( bEmptyDir )
{
@@ -4081,7 +4102,7 @@ int VSICurlFilesystemHandler::Stat( const char *pszFilename,
bool bListDir = true;
bool bEmptyDir = false;
CPLString osURL(
- VSICurlGetURLFromFilename(pszFilename, nullptr, nullptr, nullptr,
+ VSICurlGetURLFromFilename(pszFilename, nullptr, nullptr, nullptr, nullptr,
&bListDir, &bEmptyDir, nullptr));
const char* pszOptionVal =
diff --git a/gdal/port/cpl_vsil_curl_class.h b/gdal/port/cpl_vsil_curl_class.h
index 99c48a9d15b7..7169cdb0fa11 100644
--- a/gdal/port/cpl_vsil_curl_class.h
+++ b/gdal/port/cpl_vsil_curl_class.h
@@ -348,6 +348,7 @@ class VSICurlHandle : public VSIVirtualHandle
virtual std::string DownloadRegion(vsi_l_offset startOffset, int nBlocks);
bool m_bUseHead = false;
+ bool m_bUseRedirectURLIfNoQueryStringParams = false;
int ReadMultiRangeSingleGet( int nRanges, void ** ppData,
const vsi_l_offset* panOffsets,