diff --git a/.github/workflows/ubuntu_24.04/expected_gdalinfo_formats.txt b/.github/workflows/ubuntu_24.04/expected_gdalinfo_formats.txt index 54759dcf3534..80c65710f227 100644 --- a/.github/workflows/ubuntu_24.04/expected_gdalinfo_formats.txt +++ b/.github/workflows/ubuntu_24.04/expected_gdalinfo_formats.txt @@ -74,7 +74,6 @@ Supported Formats: (ro:read-only, rw:read-write, +:update, v:virtual-I/O s:subda KMLSUPEROVERLAY -raster- (rwv): Kml Super Overlay (*.kml, *.kmz) WEBP -raster- (rwv): WEBP (*.webp) PDF -raster,vector- (rw+vs): Geospatial PDF (*.pdf) - Rasterlite -raster- (rwvs): Rasterlite (*.sqlite) MBTiles -raster,vector- (rw+v): MBTiles (*.mbtiles) PLMOSAIC -raster- (ro): Planet Labs Mosaics API CALS -raster- (rwv): CALS (Type 1) (*.cal, *.ct1) diff --git a/.github/workflows/windows_conda_expected_gdalinfo_formats.txt b/.github/workflows/windows_conda_expected_gdalinfo_formats.txt index 2077516a871d..d3c722d09f3a 100644 --- a/.github/workflows/windows_conda_expected_gdalinfo_formats.txt +++ b/.github/workflows/windows_conda_expected_gdalinfo_formats.txt @@ -75,7 +75,6 @@ Supported Formats: (ro:read-only, rw:read-write, +:update, v:virtual-I/O s:subda KMLSUPEROVERLAY -raster- (rwv): Kml Super Overlay (*.kml, *.kmz) WEBP -raster- (rwv): WEBP (*.webp) PDF -raster,vector- (rw+vs): Geospatial PDF (*.pdf) - Rasterlite -raster- (rwvs): Rasterlite (*.sqlite) MBTiles -raster,vector- (rw+v): MBTiles (*.mbtiles) PLMOSAIC -raster- (ro): Planet Labs Mosaics API CALS -raster- (rwv): CALS (Type 1) (*.cal, *.ct1) diff --git a/autotest/gdrivers/data/rasterlite/byte.rasterlite b/autotest/gdrivers/data/rasterlite/byte.rasterlite deleted file mode 100644 index 127347c31bcd..000000000000 Binary files a/autotest/gdrivers/data/rasterlite/byte.rasterlite and /dev/null differ diff --git a/autotest/gdrivers/data/rasterlite/byte.rasterlite.sql b/autotest/gdrivers/data/rasterlite/byte.rasterlite.sql deleted file mode 100644 index 8e9a39ed6a0b..000000000000 --- a/autotest/gdrivers/data/rasterlite/byte.rasterlite.sql +++ /dev/null @@ -1,11 +0,0 @@ --- SQL RASTERLITE -CREATE TABLE spatial_ref_sys (srid INTEGER PRIMARY KEY,auth_name,auth_srid,ref_sys_name,proj4text,srtext); -INSERT INTO spatial_ref_sys VALUES(26711,'epsg',26711,'NAD27 / UTM zone 11N','+proj=utm +zone=11 +datum=NAD27 +units=m +no_defs','PROJCS["NAD27 / UTM zone 11N",GEOGCS[NAD27,DATUM[North_American_Datum_1927,SPHEROID["Clarke 1866",6378206.4,294.9786982138982]],UNIT[degree,0.0174532925199433]],PROJECTION[Transverse_Mercator],PARAMETER[central_meridian,-117],PARAMETER[scale_factor,0.9996],PARAMETER[false_easting,500000],AUTHORITY[EPSG,26711]]'); -CREATE TABLE geometry_columns (f_table_name,f_geometry_column,geometry_type,coord_dimension,srid,spatial_index_enabled); -INSERT INTO geometry_columns VALUES('byte_metadata','geometry',3,2,26711,1); -CREATE TABLE byte_rasters (id INTEGER PRIMARY KEY,raster); -INSERT INTO byte_rasters VALUES(1,X'49492A00080000000B000001030001000000140000000101030001000000140000000201030001000000080000000301030001000000010000000601030001000000010000001101040001000000920000001501030001000000010000001601030001000000140000001701040001000000900100001C0103000100000001000000530103000100000001000000000000006B7B847384848C8484846B846B84846B7B739C9473846B7B9473A5738C6B7B7B63847B848484639C73848C847B738C6B8C73847B6B848473736B736B94847B7B7384847B737B737B6B73946B738C7384849C848C84847373737B947BA57B846B6B849C7BBDADAD949473947B6B8473849C637B738484CE6BC5AD948C8C8463847B738C848463847B84AD7B73947B9473947B8C7B6B7384736B73637B63B5636B7B7384737B847384847B7B846373637B8473736B8C8C638C63737B6B846B736B737B847B6B7B84848484847B63847B6B9463737B8CAD7B6B7B7B7B6B7B7B7B6B8C7B7B73735A6BAD6B6B6B6B63847B73AD94637B7B6B7B636BBDAD6B73736B638C6BAD8C9484846B7B6363736384638C73947B63847B948C8C6B8C5A6B736B5A637B7373737B7B9473946384A5949C7B6B6B6B738C637363636B7384735A7B73BDAD8C8CA573845A63735A63636B6384636B84849CB58CAD7B8463737B4A73637B8C9C84A58C8C63ADF7FFCE846B8C7B9484A5A5948C847B6B7B6B7BB5B59C949C9C9CB5849473846B6B6B6B6B73636B'); -CREATE TABLE byte_metadata (id INTEGER PRIMARY KEY,tile_id,width,height,pixel_x_size,pixel_y_size,geometry POLYGON); -INSERT INTO byte_metadata VALUES(1,0,20,20,60.0,60.0,X'0001576800000000000040E61A4100000000749C4C410000000000F91A4100000000CC9E4C417C0300000001000000050000000000000040E61A4100000000749C4C410000000040E61A4100000000CC9E4C410000000000F91A4100000000CC9E4C410000000000F91A4100000000749C4C410000000040E61A4100000000749C4C41FE'); -CREATE VIRTUAL TABLE idx_byte_metadata_geometry USING rtree(pkid, xmin, xmax, ymin, ymax); -INSERT INTO idx_byte_metadata_geometry SELECT rowid, ST_MinX(geometry), ST_MaxX(geometry), ST_MinY(geometry), ST_MaxY(geometry) FROM byte_metadata; diff --git a/autotest/gdrivers/data/rasterlite/rasterlite.sqlite b/autotest/gdrivers/data/rasterlite/rasterlite.sqlite deleted file mode 100644 index bc9bacbec793..000000000000 Binary files a/autotest/gdrivers/data/rasterlite/rasterlite.sqlite and /dev/null differ diff --git a/autotest/gdrivers/data/rasterlite/rasterlite_pct.sqlite b/autotest/gdrivers/data/rasterlite/rasterlite_pct.sqlite deleted file mode 100644 index b24fb9eab839..000000000000 Binary files a/autotest/gdrivers/data/rasterlite/rasterlite_pct.sqlite and /dev/null differ diff --git a/autotest/gdrivers/data/rasterlite/rasterlite_pyramids.sqlite b/autotest/gdrivers/data/rasterlite/rasterlite_pyramids.sqlite deleted file mode 100644 index 8d0ac323b97b..000000000000 Binary files a/autotest/gdrivers/data/rasterlite/rasterlite_pyramids.sqlite and /dev/null differ diff --git a/autotest/gdrivers/rasterlite.py b/autotest/gdrivers/rasterlite.py deleted file mode 100755 index 2f9f8d1ce5aa..000000000000 --- a/autotest/gdrivers/rasterlite.py +++ /dev/null @@ -1,355 +0,0 @@ -#!/usr/bin/env pytest -# -*- coding: utf-8 -*- -############################################################################### -# -# Project: GDAL/OGR Test Suite -# Purpose: Test read functionality for Rasterlite driver. -# Author: Even Rouault, -# -############################################################################### -# Copyright (c) 2009-2013, Even Rouault -# -# SPDX-License-Identifier: MIT -############################################################################### - -import gdaltest -import pytest - -from osgeo import gdal, ogr - -pytestmark = pytest.mark.require_driver("RASTERLITE") - - -@pytest.fixture(scope="module", autouse=True) -def setup(): - - # This is to speed-up the runtime of tests on EXT4 filesystems - # Do not use this for production environment if you care about data safety - # w.r.t system/OS crashes, unless you know what you are doing. - with gdal.config_option("OGR_SQLITE_SYNCHRONOUS", "OFF"): - yield - - -def has_spatialite(): - drv = ogr.GetDriverByName("SQLite") - return drv is not None and "SPATIALITE" in drv.GetMetadataItem( - "DMD_CREATIONOPTIONLIST" - ) - - -def sqlite_supports_rtree(tmp_path): - # Test if SQLite3 supports rtrees - ds2 = ogr.GetDriverByName("SQLite").CreateDataSource( - str(tmp_path / "testrtree.sqlite") - ) - gdal.ErrorReset() - ds2.ExecuteSQL("CREATE VIRTUAL TABLE testrtree USING rtree(id,minX,maxX,minY,maxY)") - - return "rtree" not in gdal.GetLastErrorMsg() - - -def sqlite_supports_rasterlite(): - - gdal.ErrorReset() - gdal.Open("data/rasterlite/rasterlite.sqlite") - - return "unsupported file format" not in gdal.GetLastErrorMsg() - - -############################################################################### -# Test opening a rasterlite DB without overviews - - -def test_rasterlite_2(tmp_path): - - if not sqlite_supports_rtree(tmp_path): - pytest.skip( - "Please upgrade your sqlite3 library to be able to read Rasterlite DBs (needs rtree support)!" - ) - - if not sqlite_supports_rasterlite(): - pytest.skip( - "Please upgrade your sqlite3 library to be able to read Rasterlite DBs!" - ) - - ds = gdal.Open("data/rasterlite/rasterlite.sqlite") - - if ds is None: - pytest.fail() - - assert ds.RasterCount == 3, "expected 3 bands" - - assert ds.GetRasterBand(1).GetOverviewCount() == 0, "did not expect overview" - - cs = ds.GetRasterBand(1).Checksum() - expected_cs = 11746 - assert ( - cs == expected_cs or cs == 11751 - ), "for band 1, cs = %d, different from expected_cs = %d" % (cs, expected_cs) - - cs = ds.GetRasterBand(2).Checksum() - expected_cs = 19843 - assert ( - cs == expected_cs or cs == 20088 or cs == 20083 - ), "for band 2, cs = %d, different from expected_cs = %d" % (cs, expected_cs) - - cs = ds.GetRasterBand(3).Checksum() - expected_cs = 48911 - assert ( - cs == expected_cs or cs == 47978 - ), "for band 3, cs = %d, different from expected_cs = %d" % (cs, expected_cs) - - assert ds.GetProjectionRef().find("WGS_1984") != -1, ( - "projection_ref = %s" % ds.GetProjectionRef() - ) - - gt = ds.GetGeoTransform() - expected_gt = ( - -180.0, - 360.0 / ds.RasterXSize, - 0.0, - 90.0, - 0.0, - -180.0 / ds.RasterYSize, - ) - - gdaltest.check_geotransform(gt, expected_gt, 1e-15) - - ds = None - - -############################################################################### -# Test opening a rasterlite DB with overviews - - -def test_rasterlite_3(): - - ds = gdal.Open("RASTERLITE:data/rasterlite/rasterlite_pyramids.sqlite,table=test") - - assert ds.RasterCount == 3, "expected 3 bands" - - assert ds.GetRasterBand(1).GetOverviewCount() == 1, "expected 1 overview" - - cs = ds.GetRasterBand(1).GetOverview(0).Checksum() - expected_cs = 59551 - assert ( - cs == expected_cs or cs == 59833 - ), "for overview of band 1, cs = %d, different from expected_cs = %d" % ( - cs, - expected_cs, - ) - - cs = ds.GetRasterBand(2).GetOverview(0).Checksum() - expected_cs = 59603 - assert ( - cs == expected_cs or cs == 59588 - ), "for overview of band 2, cs = %d, different from expected_cs = %d" % ( - cs, - expected_cs, - ) - - cs = ds.GetRasterBand(3).GetOverview(0).Checksum() - expected_cs = 42173 - assert ( - cs == expected_cs or cs == 42361 - ), "for overview of band 3, cs = %d, different from expected_cs = %d" % ( - cs, - expected_cs, - ) - - ds = None - - -############################################################################### -# Test opening a rasterlite DB with color table and user-defined spatial extent - - -def test_rasterlite_4(): - - ds = gdal.Open( - "RASTERLITE:data/rasterlite/rasterlite_pct.sqlite,minx=0,miny=0,maxx=180,maxy=90" - ) - - assert ds.RasterCount == 1, "expected 1 band" - - assert ds.RasterXSize == 169 and ds.RasterYSize == 85 - - ct = ds.GetRasterBand(1).GetRasterColorTable() - assert ct is not None, "did not get color table" - - cs = ds.GetRasterBand(1).Checksum() - expected_cs = 36473 - assert cs == expected_cs, "for band 1, cs = %d, different from expected_cs = %d" % ( - cs, - expected_cs, - ) - - ds = None - - -############################################################################### -# Test opening a rasterlite DB with color table and do color table expansion - - -def test_rasterlite_5(): - - ds = gdal.Open("RASTERLITE:data/rasterlite/rasterlite_pct.sqlite,bands=3") - - assert ds.RasterCount == 3, "expected 3 bands" - - ct = ds.GetRasterBand(1).GetRasterColorTable() - assert ct is None, "did not expect color table" - - cs = ds.GetRasterBand(1).Checksum() - expected_cs = 506 - assert cs == expected_cs, "for band 1, cs = %d, different from expected_cs = %d" % ( - cs, - expected_cs, - ) - - cs = ds.GetRasterBand(2).Checksum() - expected_cs = 3842 - assert cs == expected_cs, "for band 2, cs = %d, different from expected_cs = %d" % ( - cs, - expected_cs, - ) - - cs = ds.GetRasterBand(3).Checksum() - expected_cs = 59282 - assert cs == expected_cs, "for band 3, cs = %d, different from expected_cs = %d" % ( - cs, - expected_cs, - ) - - ds = None - - -############################################################################### -# Test CreateCopy() - - -@pytest.fixture() -def byte_sqlite(tmp_path): - byte_sqlite_path = str(tmp_path / "byte.sqlite") - byte_sqlite_dsn = f"RASTERLITE:{byte_sqlite_path},table=byte" - - with gdal.Open("data/byte.tif") as src_ds: - ds = gdal.GetDriverByName("RASTERLITE").CreateCopy(byte_sqlite_dsn, src_ds) - assert ds is not None - del ds - - return byte_sqlite_dsn - - -@pytest.mark.skipif(not has_spatialite(), reason="spatialite not available") -def test_rasterlite_6(byte_sqlite): - - # Test result of CreateCopy() - ds = gdal.Open(byte_sqlite) - assert ds is not None - - with gdal.Open("data/byte.tif") as src_ds: - assert ( - ds.GetRasterBand(1).Checksum() == src_ds.GetRasterBand(1).Checksum() - ), "Wrong checksum" - - expected_gt = src_ds.GetGeoTransform() - gt = ds.GetGeoTransform() - - gdaltest.check_geotransform(gt, expected_gt, 1e-5) - - assert "NAD27 / UTM zone 11N" in ds.GetProjectionRef(), "Wrong SRS" - - ds = None - - -############################################################################### -# Test BuildOverviews() - - -@pytest.mark.skipif(not has_spatialite(), reason="spatialite not available") -def test_rasterlite_7(byte_sqlite): - - ds = gdal.Open(byte_sqlite, gdal.GA_Update) - - # Resampling method is not taken into account - ds.BuildOverviews("NEAREST", overviewlist=[2, 4]) - - assert ( - ds.GetRasterBand(1).GetOverview(0).Checksum() == 1192 - ), "Wrong checksum for overview 0" - - assert ( - ds.GetRasterBand(1).GetOverview(1).Checksum() == 233 - ), "Wrong checksum for overview 1" - - # Reopen and test - ds = None - ds = gdal.Open(byte_sqlite) - - assert ( - ds.GetRasterBand(1).GetOverview(0).Checksum() == 1192 - ), "Wrong checksum for overview 0" - - assert ( - ds.GetRasterBand(1).GetOverview(1).Checksum() == 233 - ), "Wrong checksum for overview 1" - - ############################################################################### - # Test CleanOverviews() - - ds = gdal.Open(byte_sqlite, gdal.GA_Update) - - ds.BuildOverviews(overviewlist=[]) - - assert ds.GetRasterBand(1).GetOverviewCount() == 0 - - -############################################################################### -# Test BuildOverviews() with AVERAGE resampling - - -@pytest.mark.skipif(not has_spatialite(), reason="spatialite not available") -def test_rasterlite_11(byte_sqlite): - - ds = gdal.Open(byte_sqlite, gdal.GA_Update) - - # Resampling method is not taken into account - ds.BuildOverviews("AVERAGE", overviewlist=[2, 4]) - - # Reopen and test - ds = None - ds = gdal.Open(byte_sqlite) - - assert ( - ds.GetRasterBand(1).GetOverview(0).Checksum() == 1152 - ), "Wrong checksum for overview 0" - - assert ( - ds.GetRasterBand(1).GetOverview(1).Checksum() == 215 - ), "Wrong checksum for overview 1" - - -############################################################################### -# Test opening a .rasterlite file - - -@pytest.mark.skipif(not has_spatialite(), reason="spatialite not available") -def test_rasterlite_12(): - - ds = gdal.Open("data/rasterlite/byte.rasterlite") - assert ds.GetRasterBand(1).Checksum() == 4672, "validation failed" - - -############################################################################### -# Test opening a .rasterlite.sql file - - -@pytest.mark.skipif(not has_spatialite(), reason="spatialite not available") -def test_rasterlite_13(): - - if gdaltest.rasterlite_drv.GetMetadataItem("ENABLE_SQL_SQLITE_FORMAT") != "YES": - pytest.skip() - - ds = gdal.Open("data/rasterlite/byte.rasterlite.sql") - assert ds.GetRasterBand(1).Checksum() == 4672, "validation failed" diff --git a/doc/source/drivers/raster/index.rst b/doc/source/drivers/raster/index.rst index f35fede51cda..5ee25e2bbcb5 100644 --- a/doc/source/drivers/raster/index.rst +++ b/doc/source/drivers/raster/index.rst @@ -143,7 +143,6 @@ Raster drivers pnm postgisraster prf - rasterlite rasterlite2 r rdb diff --git a/doc/source/drivers/raster/rasterlite.rst b/doc/source/drivers/raster/rasterlite.rst deleted file mode 100644 index 6e6b35d89c60..000000000000 --- a/doc/source/drivers/raster/rasterlite.rst +++ /dev/null @@ -1,300 +0,0 @@ -.. _raster.rasterlite: - -================================================================================ -Rasterlite - Rasters in SQLite DB -================================================================================ - -.. shortname:: Rasterlite - -.. build_dependencies:: libsqlite3 - -The Rasterlite driver allows reading and -creating Rasterlite databases. - -| Those databases can be produced by the utilities of the - `rasterlite `__ distribution, such - as rasterlite_load, rasterlite_pyramids, .... -| The driver supports reading grayscale, paletted and RGB images stored - as GIF, PNG, TIFF or JPEG tiles. The driver also supports reading - overviews/pyramids, spatial reference system and spatial extent. - -GDAL/OGR must be compiled with OGR SQLite driver support. For read -support, linking against spatialite library is not required, but recent -enough sqlite3 library is needed to read rasterlite databases. -rasterlite library is not required either. - -For write support a new table, linking against spatialite library \*is\* -required. - -Although the Rasterlite documentation only mentions GIF, PNG, TIFF, JPEG -as compression formats for tiles, the -driver supports reading and writing internal tiles in any format handled -by GDAL. Furthermore, the Rasterlite driver also allow reading and -writing as many bands and as many band types as supported by the driver -for the internal tiles. - -Driver capabilities -------------------- - -.. supports_createcopy:: - -.. supports_georeferencing:: - -.. supports_virtualio:: - -Connection string syntax in read mode -------------------------------------- - -Syntax: 'rasterlitedb_name' or -'RASTERLITE:rasterlitedb_name[,table=raster_table_prefix][,minx=minx_val,miny=miny_val,maxx=maxx_val,maxy=maxy_val][,level=level_number] - -where : - -- *rasterlitedb_name* is the filename of the RasterLite DB. -- *raster_table_prefix* is the prefix of the raster table to open. For - each raster, there are 2 corresponding SQLite tables, suffixed with - \_rasters and \_metadata -- *minx_val,miny_val,maxx_val,maxy_val* set a user-defined extent - (expressed in coordinate system units) for the raster that can be - different from the default extent. -- *level_number* is the level of the pyramid/overview to open, 0 being - the base pyramid. - -Creation issues ---------------- - -The driver can create a new database if necessary, create a new raster -table if necessary and copy a source dataset into the specified raster -table. - -If data already exists in the raster table, the new data will be added. -You can use the WIPE=YES creation options to erase existing data. - -The driver does not support updating a block in an existing raster -table. It can only append new data. - -Syntax for the name of the output dataset: -'RASTERLITE:rasterlitedb_name,table=raster_table_prefix' or -'rasterlitedb_name' - -It is possible to specify only the DB name as in the later form, but -only if the database does not already exists. In that case, the raster -table name will be base on the DB name itself. - -Creation options -~~~~~~~~~~~~~~~~ - -|about-creation-options| -The following creation options are supported: - -- .. co:: WIPE - - Set to YES to erase all preexisting data - in the specified table - -- .. co:: TILED - - Set to NO if the source dataset must be - written as a single tile in the raster table - -- .. co:: BLOCKXSIZE - :choices: - :default: 256 - - Sets tile width. - -- .. co:: BLOCKYSIZE - :choices: - :default: 256 - - Sets tile height. - -- .. co:: DRIVER - :default: GTiff - - name of the GDAL - driver to use for storing tiles. - -- .. co:: COMPRESS - :choices: LZW, JPEG, DEFLATE, ... - - (GTiff driver) name of the - compression method - -- .. co:: PHOTOMETRIC - :choices: RGB, YCbCr, ... - - (GTiff driver) photometric interpretation - -- .. co:: QUALITY - :choices: [1-100] - :default: 75 - - (JPEG-compressed GTiff, JPEG and WEBP drivers) - JPEG/WEBP quality. - -Configuration options -~~~~~~~~~~~~~~~~~~~~~ - -|about-config-options| -The following configuration option is supported: - -- .. config:: RASTERLITE_OVR_OPTIONS - - Comma-separated list of creation options to be applied to overviews. - See `Overviews`_. - -Overviews ---------- - -The driver supports building (if the dataset is opened in update mode) -and reading internal overviews. - -If no internal overview is detected, the driver will try using external -overviews (.ovr files). - -Options can be used for internal overviews -building. They can be specified with the :config:`RASTERLITE_OVR_OPTIONS` -configuration option, as a comma separated list of the above creation -options. See below examples. - -All resampling methods supported by GDAL -overviews are available. - -Performance hints ------------------ - -Some of the performance hints of the OGR SQLite driver apply. In -particular setting the OGR_SQLITE_SYNCHRONOUS configuration option to -OFF when creating a dataset or adding overviews might increase -performance on some filesystems. - -After having added all the raster tables and building all the needed -overview levels, it is advised to run : - -:: - - ogrinfo rasterlitedb.sqlite -sql "VACUUM" - -in order to optimize the database, and increase read performances -afterwards. This is particularly true with big rasterlite datasets. Note -that the operation might take a long time. - -Examples --------- - -- Accessing a rasterlite DB with a single raster table : - - :: - - $ gdalinfo rasterlitedb.sqlite -noct - - Output: - - :: - - Driver: Rasterlite/Rasterlite - Files: rasterlitedb.sqlite - Size is 7200, 7200 - Coordinate System is: - GEOGCS["WGS 84", - DATUM["WGS_1984", - SPHEROID["WGS 84",6378137,298.257223563, - AUTHORITY["EPSG","7030"]], - AUTHORITY["EPSG","6326"]], - PRIMEM["Greenwich",0, - AUTHORITY["EPSG","8901"]], - UNIT["degree",0.01745329251994328, - AUTHORITY["EPSG","9122"]], - AUTHORITY["EPSG","4326"]] - Origin = (-5.000000000000000,55.000000000000000) - Pixel Size = (0.002083333333333,-0.002083333333333) - Metadata: - TILE_FORMAT=GIF - Image Structure Metadata: - INTERLEAVE=PIXEL - Corner Coordinates: - Upper Left ( -5.0000000, 55.0000000) ( 5d 0'0.00"W, 55d 0'0.00"N) - Lower Left ( -5.0000000, 40.0000000) ( 5d 0'0.00"W, 40d 0'0.00"N) - Upper Right ( 10.0000000, 55.0000000) ( 10d 0'0.00"E, 55d 0'0.00"N) - Lower Right ( 10.0000000, 40.0000000) ( 10d 0'0.00"E, 40d 0'0.00"N) - Center ( 2.5000000, 47.5000000) ( 2d30'0.00"E, 47d30'0.00"N) - Band 1 Block=480x480 Type=Byte, ColorInterp=Palette - Color Table (RGB with 256 entries) - -- Listing a multi-raster table DB : - - :: - - $ gdalinfo multirasterdb.sqlite - - Output: - - :: - - Driver: Rasterlite/Rasterlite - Files: - Size is 512, 512 - Coordinate System is `' - Subdatasets: - SUBDATASET_1_NAME=RASTERLITE:multirasterdb.sqlite,table=raster1 - SUBDATASET_1_DESC=RASTERLITE:multirasterdb.sqlite,table=raster1 - SUBDATASET_2_NAME=RASTERLITE:multirasterdb.sqlite,table=raster2 - SUBDATASET_2_DESC=RASTERLITE:multirasterdb.sqlite,table=raster2 - Corner Coordinates: - Upper Left ( 0.0, 0.0) - Lower Left ( 0.0, 512.0) - Upper Right ( 512.0, 0.0) - Lower Right ( 512.0, 512.0) - Center ( 256.0, 256.0) - -- Accessing a raster table within a multi-raster table DB: - - :: - - $ gdalinfo RASTERLITE:multirasterdb.sqlite,table=raster1 - -- Creating a new rasterlite DB with data encoded in JPEG tiles : - - :: - - $ gdal_translate -of Rasterlite source.tif RASTERLITE:my_db.sqlite,table=source -co DRIVER=JPEG - -- Creating internal overviews : - - :: - - $ gdaladdo RASTERLITE:my_db.sqlite,table=source 2 4 8 16 - -- Cleaning internal overviews : - - :: - - $ gdaladdo -clean RASTERLITE:my_db.sqlite,table=source - -- Creating external overviews in a .ovr file: - - :: - - $ gdaladdo -ro RASTERLITE:my_db.sqlite,table=source 2 4 8 16 - -- Creating internal overviews with options (GDAL 1.10 or later): - - :: - - $ gdaladdo RASTERLITE:my_db.sqlite,table=source 2 4 8 16 --config RASTERLITE_OVR_OPTIONS DRIVER=GTiff,COMPRESS=JPEG,PHOTOMETRIC=YCbCr - -: - -See Also --------- - -- `Spatialite and Rasterlite home - page `__ -- `Rasterlite - manual `__ -- `Rasterlite - howto `__ -- `Sample - databases `__ -- :ref:`OGR SQLite driver ` diff --git a/frmts/gdalallregister.cpp b/frmts/gdalallregister.cpp index c569711ba288..4dcdcdaad2a2 100644 --- a/frmts/gdalallregister.cpp +++ b/frmts/gdalallregister.cpp @@ -605,10 +605,6 @@ void CPL_STDCALL GDALAllRegister() GDALRegister_PDF(); #endif -#ifdef FRMT_rasterlite - GDALRegister_Rasterlite(); -#endif - #ifdef FRMT_mbtiles GDALRegister_MBTiles(); #endif diff --git a/frmts/rasterlite/CMakeLists.txt b/frmts/rasterlite/CMakeLists.txt deleted file mode 100644 index 0abf1a4fb754..000000000000 --- a/frmts/rasterlite/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -add_gdal_driver(TARGET gdal_Rasterlite - SOURCES - rasterlitedataset.h - rasterlitecreatecopy.cpp - rasterlitedataset.cpp - rasterliteoverviews.cpp - CORE_SOURCES - rasterlitedrivercore.cpp - PLUGIN_CAPABLE NO_DEPS - NO_SHARED_SYMBOL_WITH_CORE) - -if(NOT TARGET gdal_Rasterlite) - return() -endif() - -gdal_standard_includes(gdal_Rasterlite) -target_include_directories(gdal_Rasterlite PRIVATE ${GDAL_RASTER_FORMAT_SOURCE_DIR}/mem) diff --git a/frmts/rasterlite/rasterlitecreatecopy.cpp b/frmts/rasterlite/rasterlitecreatecopy.cpp deleted file mode 100644 index cb78648b3043..000000000000 --- a/frmts/rasterlite/rasterlitecreatecopy.cpp +++ /dev/null @@ -1,729 +0,0 @@ -/****************************************************************************** - * - * Project: GDAL Rasterlite driver - * Purpose: Implement GDAL Rasterlite support using OGR SQLite driver - * Author: Even Rouault, - * - ********************************************************************** - * Copyright (c) 2009-2012, Even Rouault - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "cpl_string.h" -#include "ogr_api.h" -#include "ogr_srs_api.h" -#include "memdataset.h" - -#include "rasterlitedataset.h" - -/************************************************************************/ -/* RasterliteGetTileDriverOptions () */ -/************************************************************************/ - -static char **RasterliteAddTileDriverOptionsForDriver( - CSLConstList papszOptions, char **papszTileDriverOptions, - const char *pszOptionName, const char *pszExpectedDriverName) -{ - const char *pszVal = CSLFetchNameValue(papszOptions, pszOptionName); - if (pszVal) - { - const char *pszDriverName = - CSLFetchNameValueDef(papszOptions, "DRIVER", "GTiff"); - if (EQUAL(pszDriverName, pszExpectedDriverName)) - { - papszTileDriverOptions = - CSLSetNameValue(papszTileDriverOptions, pszOptionName, pszVal); - } - else - { - CPLError(CE_Warning, CPLE_NotSupported, - "Unexpected option '%s' for driver '%s'", pszOptionName, - pszDriverName); - } - } - return papszTileDriverOptions; -} - -char **RasterliteGetTileDriverOptions(CSLConstList papszOptions) -{ - const char *pszDriverName = - CSLFetchNameValueDef(papszOptions, "DRIVER", "GTiff"); - - char **papszTileDriverOptions = nullptr; - - const char *pszQuality = CSLFetchNameValue(papszOptions, "QUALITY"); - if (pszQuality) - { - if (EQUAL(pszDriverName, "GTiff")) - { - papszTileDriverOptions = CSLSetNameValue( - papszTileDriverOptions, "JPEG_QUALITY", pszQuality); - } - else if (EQUAL(pszDriverName, "JPEG") || EQUAL(pszDriverName, "WEBP")) - { - papszTileDriverOptions = - CSLSetNameValue(papszTileDriverOptions, "QUALITY", pszQuality); - } - else - { - CPLError(CE_Warning, CPLE_NotSupported, - "Unexpected option '%s' for driver '%s'", "QUALITY", - pszDriverName); - } - } - - papszTileDriverOptions = RasterliteAddTileDriverOptionsForDriver( - papszOptions, papszTileDriverOptions, "COMPRESS", "GTiff"); - papszTileDriverOptions = RasterliteAddTileDriverOptionsForDriver( - papszOptions, papszTileDriverOptions, "PHOTOMETRIC", "GTiff"); - - return papszTileDriverOptions; -} - -/************************************************************************/ -/* RasterliteInsertSRID () */ -/************************************************************************/ - -static int RasterliteInsertSRID(GDALDatasetH hDS, const char *pszWKT) -{ - int nAuthorityCode = 0; - CPLString osAuthorityName, osProjCS, osProj4; - if (pszWKT != nullptr && strlen(pszWKT) != 0) - { - OGRSpatialReferenceH hSRS = OSRNewSpatialReference(pszWKT); - if (hSRS) - { - OSRSetAxisMappingStrategy(hSRS, OAMS_TRADITIONAL_GIS_ORDER); - - const char *pszAuthorityName = OSRGetAuthorityName(hSRS, nullptr); - if (pszAuthorityName) - osAuthorityName = pszAuthorityName; - - const char *pszProjCS = OSRGetAttrValue(hSRS, "PROJCS", 0); - if (pszProjCS) - osProjCS = pszProjCS; - - const char *pszAuthorityCode = OSRGetAuthorityCode(hSRS, nullptr); - if (pszAuthorityCode) - nAuthorityCode = atoi(pszAuthorityCode); - - char *pszProj4 = nullptr; - if (OSRExportToProj4(hSRS, &pszProj4) != OGRERR_NONE) - { - CPLFree(pszProj4); - pszProj4 = CPLStrdup(""); - } - osProj4 = pszProj4; - CPLFree(pszProj4); - } - OSRDestroySpatialReference(hSRS); - } - - CPLString osSQL; - int nSRSId = -1; - if (nAuthorityCode != 0 && !osAuthorityName.empty()) - { - osSQL.Printf("SELECT srid FROM spatial_ref_sys WHERE auth_srid = %d", - nAuthorityCode); - OGRLayerH hLyr = - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - if (hLyr == nullptr) - { - nSRSId = nAuthorityCode; - - if (!osProjCS.empty()) - osSQL.Printf( - "INSERT INTO spatial_ref_sys " - "(srid, auth_name, auth_srid, ref_sys_name, proj4text) " - "VALUES (%d, '%s', '%d', '%s', '%s')", - nSRSId, osAuthorityName.c_str(), nAuthorityCode, - osProjCS.c_str(), osProj4.c_str()); - else - osSQL.Printf("INSERT INTO spatial_ref_sys " - "(srid, auth_name, auth_srid, proj4text) " - "VALUES (%d, '%s', '%d', '%s')", - nSRSId, osAuthorityName.c_str(), nAuthorityCode, - osProj4.c_str()); - - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - } - else - { - OGRFeatureH hFeat = OGR_L_GetNextFeature(hLyr); - if (hFeat) - { - nSRSId = OGR_F_GetFieldAsInteger(hFeat, 0); - OGR_F_Destroy(hFeat); - } - GDALDatasetReleaseResultSet(hDS, hLyr); - } - } - - return nSRSId; -} - -/************************************************************************/ -/* RasterliteCreateTables () */ -/************************************************************************/ - -static GDALDatasetH RasterliteCreateTables(GDALDatasetH hDS, - const char *pszTableName, int nSRSId, - int bWipeExistingData) -{ - CPLString osSQL; - - const CPLString osDBName = GDALGetDescription(hDS); - - CPLString osRasterLayer; - osRasterLayer.Printf("%s_rasters", pszTableName); - - CPLString osMetadataLayer; - osMetadataLayer.Printf("%s_metadata", pszTableName); - - OGRLayerH hLyr; - - if (GDALDatasetGetLayerByName(hDS, osRasterLayer.c_str()) == nullptr) - { - /* -------------------------------------------------------------------- - */ - /* The table don't exist. Create them */ - /* -------------------------------------------------------------------- - */ - - /* Create _rasters table */ - osSQL.Printf("CREATE TABLE \"%s\" (" - "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," - "raster BLOB NOT NULL)", - osRasterLayer.c_str()); - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - - /* Create _metadata table */ - osSQL.Printf("CREATE TABLE \"%s\" (" - "id INTEGER NOT NULL PRIMARY KEY," - "source_name TEXT NOT NULL," - "tile_id INTEGER NOT NULL," - "width INTEGER NOT NULL," - "height INTEGER NOT NULL," - "pixel_x_size DOUBLE NOT NULL," - "pixel_y_size DOUBLE NOT NULL)", - osMetadataLayer.c_str()); - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - - /* Add geometry column to _metadata table */ - osSQL.Printf( - "SELECT AddGeometryColumn('%s', 'geometry', %d, 'POLYGON', 2)", - osMetadataLayer.c_str(), nSRSId); - if ((hLyr = GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, - nullptr)) == nullptr) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Check that the OGR SQLite driver has Spatialite support"); - GDALClose(hDS); - return nullptr; - } - GDALDatasetReleaseResultSet(hDS, hLyr); - - /* Create spatial index on _metadata table */ - osSQL.Printf("SELECT CreateSpatialIndex('%s', 'geometry')", - osMetadataLayer.c_str()); - if ((hLyr = GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, - nullptr)) == nullptr) - { - GDALClose(hDS); - return nullptr; - } - GDALDatasetReleaseResultSet(hDS, hLyr); - - /* Create statistics tables */ - osSQL.Printf("SELECT UpdateLayerStatistics()"); - CPLPushErrorHandler(CPLQuietErrorHandler); - hLyr = GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - CPLPopErrorHandler(); - GDALDatasetReleaseResultSet(hDS, hLyr); - - /* Re-open the DB to take into account the new tables*/ - GDALClose(hDS); - - hDS = RasterliteOpenSQLiteDB(osDBName.c_str(), GA_Update); - } - else - { - /* Check that the existing SRS is consistent with the one of the new */ - /* data to be inserted */ - osSQL.Printf( - "SELECT srid FROM geometry_columns WHERE f_table_name = '%s'", - osMetadataLayer.c_str()); - hLyr = GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - if (hLyr) - { - int nExistingSRID = -1; - OGRFeatureH hFeat = OGR_L_GetNextFeature(hLyr); - if (hFeat) - { - nExistingSRID = OGR_F_GetFieldAsInteger(hFeat, 0); - OGR_F_Destroy(hFeat); - } - GDALDatasetReleaseResultSet(hDS, hLyr); - - if (nExistingSRID != nSRSId) - { - if (bWipeExistingData) - { - osSQL.Printf("UPDATE geometry_columns SET srid = %d " - "WHERE f_table_name = \"%s\"", - nSRSId, osMetadataLayer.c_str()); - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - - /* Re-open the DB to take into account the change of SRS */ - GDALClose(hDS); - - hDS = RasterliteOpenSQLiteDB(osDBName.c_str(), GA_Update); - } - else - { - CPLError(CE_Failure, CPLE_NotSupported, - "New data has not the same SRS as existing data"); - GDALClose(hDS); - return nullptr; - } - } - } - - if (bWipeExistingData) - { - osSQL.Printf("DELETE FROM \"%s\"", osRasterLayer.c_str()); - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - - osSQL.Printf("DELETE FROM \"%s\"", osMetadataLayer.c_str()); - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - } - } - - return hDS; -} - -/************************************************************************/ -/* RasterliteCreateCopy () */ -/************************************************************************/ - -GDALDataset *RasterliteCreateCopy(const char *pszFilename, GDALDataset *poSrcDS, - CPL_UNUSED int bStrict, char **papszOptions, - GDALProgressFunc pfnProgress, - void *pProgressData) -{ - const int nBands = poSrcDS->GetRasterCount(); - if (nBands == 0) - { - CPLError(CE_Failure, CPLE_NotSupported, "nBands == 0"); - return nullptr; - } - - const char *pszDriverName = - CSLFetchNameValueDef(papszOptions, "DRIVER", "GTiff"); - if (EQUAL(pszDriverName, "MEM") || EQUAL(pszDriverName, "VRT")) - { - CPLError(CE_Failure, CPLE_AppDefined, - "GDAL %s driver cannot be used as underlying driver", - pszDriverName); - return nullptr; - } - - GDALDriverH hTileDriver = GDALGetDriverByName(pszDriverName); - if (hTileDriver == nullptr) - { - CPLError(CE_Failure, CPLE_AppDefined, "Cannot load GDAL %s driver", - pszDriverName); - return nullptr; - } - - GDALDriverH hMemDriver = GDALGetDriverByName("MEM"); - if (hMemDriver == nullptr) - { - CPLError(CE_Failure, CPLE_AppDefined, "Cannot load GDAL MEM driver"); - return nullptr; - } - - const int nXSize = GDALGetRasterXSize(poSrcDS); - const int nYSize = GDALGetRasterYSize(poSrcDS); - - double adfGeoTransform[6]; - if (poSrcDS->GetGeoTransform(adfGeoTransform) != CE_None) - { - adfGeoTransform[0] = 0; - adfGeoTransform[1] = 1; - adfGeoTransform[2] = 0; - adfGeoTransform[3] = 0; - adfGeoTransform[4] = 0; - adfGeoTransform[5] = -1; - } - else if (adfGeoTransform[2] != 0.0 || adfGeoTransform[4] != 0.0) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Cannot use geotransform with rotational terms"); - return nullptr; - } - - const bool bTiled = - CPLTestBool(CSLFetchNameValueDef(papszOptions, "TILED", "YES")); - int nBlockXSize, nBlockYSize; - if (bTiled) - { - nBlockXSize = - atoi(CSLFetchNameValueDef(papszOptions, "BLOCKXSIZE", "256")); - nBlockYSize = - atoi(CSLFetchNameValueDef(papszOptions, "BLOCKYSIZE", "256")); - if (nBlockXSize < 64) - nBlockXSize = 64; - else if (nBlockXSize > 4096) - nBlockXSize = 4096; - if (nBlockYSize < 64) - nBlockYSize = 64; - else if (nBlockYSize > 4096) - nBlockYSize = 4096; - } - else - { - nBlockXSize = nXSize; - nBlockYSize = nYSize; - } - - /* -------------------------------------------------------------------- */ - /* Analyze arguments */ - /* -------------------------------------------------------------------- */ - - /* Skip optional RASTERLITE: prefix */ - const char *pszFilenameWithoutPrefix = pszFilename; - if (STARTS_WITH_CI(pszFilename, "RASTERLITE:")) - pszFilenameWithoutPrefix += 11; - - char **papszTokens = - CSLTokenizeStringComplex(pszFilenameWithoutPrefix, ",", FALSE, FALSE); - const int nTokens = CSLCount(papszTokens); - CPLString osDBName; - CPLString osTableName; - if (nTokens == 0) - { - osDBName = pszFilenameWithoutPrefix; - osTableName = CPLGetBasenameSafe(pszFilenameWithoutPrefix); - } - else - { - osDBName = papszTokens[0]; - - int i; - for (i = 1; i < nTokens; i++) - { - if (STARTS_WITH_CI(papszTokens[i], "table=")) - osTableName = papszTokens[i] + 6; - else - { - CPLError(CE_Warning, CPLE_AppDefined, "Invalid option : %s", - papszTokens[i]); - } - } - } - - CSLDestroy(papszTokens); - papszTokens = nullptr; - - VSIStatBuf sBuf; - const bool bExists = (VSIStat(osDBName.c_str(), &sBuf) == 0); - - if (osTableName.empty()) - { - if (bExists) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Database already exists. Explicit table name must be " - "specified"); - return nullptr; - } - osTableName = CPLGetBasenameSafe(osDBName.c_str()); - } - - CPLString osRasterLayer; - osRasterLayer.Printf("%s_rasters", osTableName.c_str()); - - CPLString osMetadataLayer; - osMetadataLayer.Printf("%s_metadata", osTableName.c_str()); - - /* -------------------------------------------------------------------- */ - /* Create or open the SQLite DB */ - /* -------------------------------------------------------------------- */ - - GDALDriverH hSQLiteDriver = GDALGetDriverByName("SQLite"); - if (hSQLiteDriver == nullptr) - { - CPLError(CE_Failure, CPLE_AppDefined, "Cannot load OGR SQLite driver"); - return nullptr; - } - - GDALDatasetH hDS; - - if (!bExists) - { - char **papszOGROptions = CSLAddString(nullptr, "SPATIALITE=YES"); - hDS = GDALCreate(hSQLiteDriver, osDBName.c_str(), 0, 0, 0, GDT_Unknown, - papszOGROptions); - CSLDestroy(papszOGROptions); - } - else - { - hDS = RasterliteOpenSQLiteDB(osDBName.c_str(), GA_Update); - } - - if (hDS == nullptr) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Cannot load or create SQLite database"); - return nullptr; - } - - CPLString osSQL; - - /* -------------------------------------------------------------------- */ - /* Get the SRID for the SRS */ - /* -------------------------------------------------------------------- */ - int nSRSId = RasterliteInsertSRID(hDS, poSrcDS->GetProjectionRef()); - - /* -------------------------------------------------------------------- */ - /* Create or wipe existing tables */ - /* -------------------------------------------------------------------- */ - const int bWipeExistingData = - CPLTestBool(CSLFetchNameValueDef(papszOptions, "WIPE", "NO")); - - hDS = RasterliteCreateTables(hDS, osTableName.c_str(), nSRSId, - bWipeExistingData); - if (hDS == nullptr) - return nullptr; - - OGRLayerH hRasterLayer = - GDALDatasetGetLayerByName(hDS, osRasterLayer.c_str()); - OGRLayerH hMetadataLayer = - GDALDatasetGetLayerByName(hDS, osMetadataLayer.c_str()); - if (hRasterLayer == nullptr || hMetadataLayer == nullptr) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Cannot find metadata and/or raster tables"); - GDALClose(hDS); - return nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Check if there is overlapping data and warn the user */ - /* -------------------------------------------------------------------- */ - double minx = adfGeoTransform[0]; - double maxx = adfGeoTransform[0] + nXSize * adfGeoTransform[1]; - double maxy = adfGeoTransform[3]; - double miny = adfGeoTransform[3] + nYSize * adfGeoTransform[5]; - - osSQL.Printf( - "SELECT COUNT(geometry) FROM \"%s\" " - "WHERE rowid IN " - "(SELECT pkid FROM \"idx_%s_metadata_geometry\" " - "WHERE %s) AND %s", - osMetadataLayer.c_str(), osTableName.c_str(), - RasterliteGetSpatialFilterCond(minx, miny, maxx, maxy).c_str(), - RasterliteGetPixelSizeCond(adfGeoTransform[1], -adfGeoTransform[5]) - .c_str()); - - int nOverlappingGeoms = 0; - OGRLayerH hCountLyr = - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - if (hCountLyr) - { - OGRFeatureH hFeat = OGR_L_GetNextFeature(hCountLyr); - if (hFeat) - { - nOverlappingGeoms = OGR_F_GetFieldAsInteger(hFeat, 0); - OGR_F_Destroy(hFeat); - } - GDALDatasetReleaseResultSet(hDS, hCountLyr); - } - - if (nOverlappingGeoms != 0) - { - CPLError(CE_Warning, CPLE_AppDefined, - "Raster tiles already exist in the %s table within " - "the extent of the data to be inserted in", - osTableName.c_str()); - } - - /* -------------------------------------------------------------------- */ - /* Iterate over blocks to add data into raster and metadata tables */ - /* -------------------------------------------------------------------- */ - int nXBlocks = (nXSize + nBlockXSize - 1) / nBlockXSize; - int nYBlocks = (nYSize + nBlockYSize - 1) / nBlockYSize; - - GDALDataType eDataType = poSrcDS->GetRasterBand(1)->GetRasterDataType(); - int nDataTypeSize = GDALGetDataTypeSize(eDataType) / 8; - GByte *pabyMEMDSBuffer = reinterpret_cast(VSIMalloc3( - nBlockXSize, nBlockYSize, cpl::fits_on(nBands * nDataTypeSize))); - if (pabyMEMDSBuffer == nullptr) - { - GDALClose(hDS); - return nullptr; - } - - const CPLString osTempFileName( - VSIMemGenerateHiddenFilename("rasterlite_tile")); - - int nTileId = 0; - int nBlocks = 0; - int nTotalBlocks = nXBlocks * nYBlocks; - - char **papszTileDriverOptions = - RasterliteGetTileDriverOptions(papszOptions); - - GDALDatasetExecuteSQL(hDS, "BEGIN", nullptr, nullptr); - - CPLErr eErr = CE_None; - for (int nBlockYOff = 0; eErr == CE_None && nBlockYOff < nYBlocks; - nBlockYOff++) - { - for (int nBlockXOff = 0; eErr == CE_None && nBlockXOff < nXBlocks; - nBlockXOff++) - { - /* -------------------------------------------------------------------- - */ - /* Create in-memory tile */ - /* -------------------------------------------------------------------- - */ - int nReqXSize = nBlockXSize; - int nReqYSize = nBlockYSize; - if ((nBlockXOff + 1) * nBlockXSize > nXSize) - nReqXSize = nXSize - nBlockXOff * nBlockXSize; - if ((nBlockYOff + 1) * nBlockYSize > nYSize) - nReqYSize = nYSize - nBlockYOff * nBlockYSize; - - eErr = poSrcDS->RasterIO( - GF_Read, nBlockXOff * nBlockXSize, nBlockYOff * nBlockYSize, - nReqXSize, nReqYSize, pabyMEMDSBuffer, nReqXSize, nReqYSize, - eDataType, nBands, nullptr, 0, 0, 0, nullptr); - if (eErr != CE_None) - { - break; - } - - auto poMEMDS = std::unique_ptr(MEMDataset::Create( - "", nReqXSize, nReqYSize, 0, eDataType, nullptr)); - for (int iBand = 0; iBand < nBands; iBand++) - { - auto hBand = MEMCreateRasterBandEx( - poMEMDS.get(), iBand + 1, - pabyMEMDSBuffer + - iBand * nDataTypeSize * nReqXSize * nReqYSize, - eDataType, 0, 0, false); - poMEMDS->AddMEMBand(hBand); - } - - GDALDatasetH hOutDS = GDALCreateCopy( - hTileDriver, osTempFileName.c_str(), poMEMDS.get(), FALSE, - papszTileDriverOptions, nullptr, nullptr); - - if (!hOutDS) - { - eErr = CE_Failure; - break; - } - GDALClose(hOutDS); - - /* -------------------------------------------------------------------- - */ - /* Insert new entry into raster table */ - /* -------------------------------------------------------------------- - */ - vsi_l_offset nDataLength = 0; - GByte *pabyData = VSIGetMemFileBuffer(osTempFileName.c_str(), - &nDataLength, FALSE); - - OGRFeatureH hFeat = OGR_F_Create(OGR_L_GetLayerDefn(hRasterLayer)); - OGR_F_SetFieldBinary(hFeat, 0, static_cast(nDataLength), - pabyData); - - if (OGR_L_CreateFeature(hRasterLayer, hFeat) != OGRERR_NONE) - eErr = CE_Failure; - /* Query raster ID to set it as the ID of the associated metadata */ - int nRasterID = static_cast(OGR_F_GetFID(hFeat)); - - OGR_F_Destroy(hFeat); - - VSIUnlink(osTempFileName.c_str()); - if (eErr == CE_Failure) - break; - - /* -------------------------------------------------------------------- - */ - /* Insert new entry into metadata table */ - /* -------------------------------------------------------------------- - */ - - hFeat = OGR_F_Create(OGR_L_GetLayerDefn(hMetadataLayer)); - OGR_F_SetFID(hFeat, nRasterID); - OGR_F_SetFieldString(hFeat, 0, GDALGetDescription(poSrcDS)); - OGR_F_SetFieldInteger(hFeat, 1, nTileId++); - OGR_F_SetFieldInteger(hFeat, 2, nReqXSize); - OGR_F_SetFieldInteger(hFeat, 3, nReqYSize); - OGR_F_SetFieldDouble(hFeat, 4, adfGeoTransform[1]); - OGR_F_SetFieldDouble(hFeat, 5, -adfGeoTransform[5]); - - minx = adfGeoTransform[0] + - (nBlockXSize * nBlockXOff) * adfGeoTransform[1]; - maxx = adfGeoTransform[0] + - (nBlockXSize * nBlockXOff + nReqXSize) * adfGeoTransform[1]; - maxy = adfGeoTransform[3] + - (nBlockYSize * nBlockYOff) * adfGeoTransform[5]; - miny = adfGeoTransform[3] + - (nBlockYSize * nBlockYOff + nReqYSize) * adfGeoTransform[5]; - - OGRGeometryH hRectangle = OGR_G_CreateGeometry(wkbPolygon); - OGRGeometryH hLinearRing = OGR_G_CreateGeometry(wkbLinearRing); - OGR_G_AddPoint_2D(hLinearRing, minx, miny); - OGR_G_AddPoint_2D(hLinearRing, minx, maxy); - OGR_G_AddPoint_2D(hLinearRing, maxx, maxy); - OGR_G_AddPoint_2D(hLinearRing, maxx, miny); - OGR_G_AddPoint_2D(hLinearRing, minx, miny); - OGR_G_AddGeometryDirectly(hRectangle, hLinearRing); - - OGR_F_SetGeometryDirectly(hFeat, hRectangle); - - if (OGR_L_CreateFeature(hMetadataLayer, hFeat) != OGRERR_NONE) - eErr = CE_Failure; - OGR_F_Destroy(hFeat); - - nBlocks++; - if (pfnProgress && !pfnProgress(1.0 * nBlocks / nTotalBlocks, - nullptr, pProgressData)) - eErr = CE_Failure; - } - } - - VSIUnlink(osTempFileName); - VSIUnlink((osTempFileName + ".aux.xml").c_str()); - - if (eErr == CE_None) - GDALDatasetExecuteSQL(hDS, "COMMIT", nullptr, nullptr); - else - GDALDatasetExecuteSQL(hDS, "ROLLBACK", nullptr, nullptr); - - CSLDestroy(papszTileDriverOptions); - - VSIFree(pabyMEMDSBuffer); - - GDALClose(hDS); - - if (eErr == CE_Failure) - return nullptr; - - return GDALDataset::FromHandle(GDALOpen(pszFilename, GA_Update)); -} - -/************************************************************************/ -/* RasterliteDelete () */ -/************************************************************************/ - -CPLErr RasterliteDelete(CPL_UNUSED const char *pszFilename) -{ - return CE_None; -} diff --git a/frmts/rasterlite/rasterlitedataset.cpp b/frmts/rasterlite/rasterlitedataset.cpp deleted file mode 100644 index 6709c2da0cb9..000000000000 --- a/frmts/rasterlite/rasterlitedataset.cpp +++ /dev/null @@ -1,1496 +0,0 @@ -/****************************************************************************** - * - * Project: GDAL Rasterlite driver - * Purpose: Implement GDAL Rasterlite support using OGR SQLite driver - * Author: Even Rouault, - * - ********************************************************************** - * Copyright (c) 2009-2013, Even Rouault - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "cpl_string.h" -#include "gdal_frmts.h" -#include "ogr_api.h" -#include "ogr_srs_api.h" - -#include "rasterlitedataset.h" -#include "rasterlitedrivercore.h" - -#include -#include - -/************************************************************************/ -/* RasterliteOpenSQLiteDB() */ -/************************************************************************/ - -GDALDatasetH RasterliteOpenSQLiteDB(const char *pszFilename, GDALAccess eAccess) -{ - const char *const apszAllowedDrivers[] = {"SQLITE", nullptr}; - return GDALOpenEx(pszFilename, - GDAL_OF_VECTOR | - ((eAccess == GA_Update) ? GDAL_OF_UPDATE : 0), - apszAllowedDrivers, nullptr, nullptr); -} - -/************************************************************************/ -/* RasterliteGetPixelSizeCond() */ -/************************************************************************/ - -CPLString RasterliteGetPixelSizeCond(double dfPixelXSize, double dfPixelYSize, - const char *pszTablePrefixWithDot) -{ - CPLString osCond; - osCond.Printf("((%spixel_x_size >= %s AND %spixel_x_size <= %s) AND " - "(%spixel_y_size >= %s AND %spixel_y_size <= %s))", - pszTablePrefixWithDot, - CPLString().FormatC(dfPixelXSize - 1e-15, "%.15f").c_str(), - pszTablePrefixWithDot, - CPLString().FormatC(dfPixelXSize + 1e-15, "%.15f").c_str(), - pszTablePrefixWithDot, - CPLString().FormatC(dfPixelYSize - 1e-15, "%.15f").c_str(), - pszTablePrefixWithDot, - CPLString().FormatC(dfPixelYSize + 1e-15, "%.15f").c_str()); - return osCond; -} - -/************************************************************************/ -/* RasterliteGetSpatialFilterCond() */ -/************************************************************************/ - -CPLString RasterliteGetSpatialFilterCond(double minx, double miny, double maxx, - double maxy) -{ - CPLString osCond; - osCond.Printf("(xmin < %s AND xmax > %s AND ymin < %s AND ymax > %s)", - CPLString().FormatC(maxx, "%.15f").c_str(), - CPLString().FormatC(minx, "%.15f").c_str(), - CPLString().FormatC(maxy, "%.15f").c_str(), - CPLString().FormatC(miny, "%.15f").c_str()); - return osCond; -} - -/************************************************************************/ -/* RasterliteBand() */ -/************************************************************************/ - -RasterliteBand::RasterliteBand(RasterliteDataset *poDSIn, int nBandIn, - GDALDataType eDataTypeIn, int nBlockXSizeIn, - int nBlockYSizeIn) -{ - poDS = poDSIn; - nBand = nBandIn; - eDataType = eDataTypeIn; - nBlockXSize = nBlockXSizeIn; - nBlockYSize = nBlockYSizeIn; -} - -/************************************************************************/ -/* IReadBlock() */ -/************************************************************************/ - -// #define RASTERLITE_DEBUG - -CPLErr RasterliteBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage) -{ - RasterliteDataset *poGDS = reinterpret_cast(poDS); - - double minx = poGDS->adfGeoTransform[0] + - nBlockXOff * nBlockXSize * poGDS->adfGeoTransform[1]; - double maxx = poGDS->adfGeoTransform[0] + - (nBlockXOff + 1) * nBlockXSize * poGDS->adfGeoTransform[1]; - double maxy = poGDS->adfGeoTransform[3] + - nBlockYOff * nBlockYSize * poGDS->adfGeoTransform[5]; - double miny = poGDS->adfGeoTransform[3] + - (nBlockYOff + 1) * nBlockYSize * poGDS->adfGeoTransform[5]; - int nDataTypeSize = GDALGetDataTypeSize(eDataType) / 8; - -#ifdef RASTERLITE_DEBUG - if (nBand == 1) - { - printf("nBlockXOff = %d, nBlockYOff = %d, nBlockXSize = %d, " /*ok*/ - "nBlockYSize = %d\n" - "minx=%.15f miny=%.15f maxx=%.15f maxy=%.15f\n", - nBlockXOff, nBlockYOff, nBlockXSize, nBlockYSize, minx, miny, - maxx, maxy); - } -#endif - - CPLString osSQL; - osSQL.Printf("SELECT m.geometry, r.raster, m.id, m.width, m.height FROM " - "\"%s_metadata\" AS m, " - "\"%s_rasters\" AS r WHERE m.rowid IN " - "(SELECT pkid FROM \"idx_%s_metadata_geometry\" " - "WHERE %s) AND %s AND r.id = m.id", - poGDS->osTableName.c_str(), poGDS->osTableName.c_str(), - poGDS->osTableName.c_str(), - RasterliteGetSpatialFilterCond(minx, miny, maxx, maxy).c_str(), - RasterliteGetPixelSizeCond(poGDS->adfGeoTransform[1], - -poGDS->adfGeoTransform[5], "m.") - .c_str()); - - OGRLayerH hSQLLyr = - GDALDatasetExecuteSQL(poGDS->hDS, osSQL.c_str(), nullptr, nullptr); - if (hSQLLyr == nullptr) - { - memset(pImage, 0, - static_cast(nBlockXSize) * nBlockYSize * nDataTypeSize); - return CE_None; - } - - const CPLString osMemFileName( - VSIMemGenerateHiddenFilename("rasterlite_tile")); - -#ifdef RASTERLITE_DEBUG - if (nBand == 1) - { - printf("nTiles = %d\n", /*ok*/ - static_cast(OGR_L_GetFeatureCount(hSQLLyr, TRUE))); - } -#endif - - bool bHasFoundTile = false; - bool bHasMemsetTile = false; - - OGRFeatureH hFeat; - CPLErr eErr = CE_None; - while ((hFeat = OGR_L_GetNextFeature(hSQLLyr)) != nullptr && - eErr == CE_None) - { - OGRGeometryH hGeom = OGR_F_GetGeometryRef(hFeat); - if (hGeom == nullptr) - { - CPLError(CE_Failure, CPLE_AppDefined, "null geometry found"); - OGR_F_Destroy(hFeat); - GDALDatasetReleaseResultSet(poGDS->hDS, hSQLLyr); - memset(pImage, 0, - static_cast(nBlockXSize) * nBlockYSize * - nDataTypeSize); - return CE_Failure; - } - - OGREnvelope oEnvelope; - OGR_G_GetEnvelope(hGeom, &oEnvelope); - - const int nTileId = OGR_F_GetFieldAsInteger(hFeat, 1); - if (poGDS->m_nLastBadTileId == nTileId) - { - OGR_F_Destroy(hFeat); - continue; - } - const int nTileXSize = OGR_F_GetFieldAsInteger(hFeat, 2); - const int nTileYSize = OGR_F_GetFieldAsInteger(hFeat, 3); - constexpr int MAX_INT_DIV_2 = std::numeric_limits::max() / 2; - if (nTileXSize <= 0 || nTileXSize >= MAX_INT_DIV_2 || nTileYSize <= 0 || - nTileYSize >= MAX_INT_DIV_2) - { - CPLError(CE_Failure, CPLE_AppDefined, "invalid tile size"); - OGR_F_Destroy(hFeat); - GDALDatasetReleaseResultSet(poGDS->hDS, hSQLLyr); - memset(pImage, 0, - static_cast(nBlockXSize) * nBlockYSize * - nDataTypeSize); - return CE_Failure; - } - - const double dfDstXOff = - (oEnvelope.MinX - minx) / poGDS->adfGeoTransform[1]; - const double dfDstYOff = - (maxy - oEnvelope.MaxY) / (-poGDS->adfGeoTransform[5]); - constexpr int MIN_INT_DIV_2 = std::numeric_limits::min() / 2; - if (!(dfDstXOff >= MIN_INT_DIV_2 && dfDstXOff <= MAX_INT_DIV_2) || - !(dfDstYOff >= MIN_INT_DIV_2 && dfDstYOff <= MAX_INT_DIV_2)) - { - CPLError(CE_Failure, CPLE_AppDefined, "invalid geometry"); - OGR_F_Destroy(hFeat); - GDALDatasetReleaseResultSet(poGDS->hDS, hSQLLyr); - memset(pImage, 0, - static_cast(nBlockXSize) * nBlockYSize * - nDataTypeSize); - return CE_Failure; - } - int nDstXOff = static_cast(dfDstXOff + 0.5); - int nDstYOff = static_cast(dfDstYOff + 0.5); - - int nReqXSize = nTileXSize; - int nReqYSize = nTileYSize; - - int nSrcXOff, nSrcYOff; - - if (nDstXOff >= 0) - { - nSrcXOff = 0; - } - else - { - nSrcXOff = -nDstXOff; - nReqXSize += nDstXOff; - nDstXOff = 0; - } - - if (nDstYOff >= 0) - { - nSrcYOff = 0; - } - else - { - nSrcYOff = -nDstYOff; - nReqYSize += nDstYOff; - nDstYOff = 0; - } - - if (nDstXOff + nReqXSize > nBlockXSize) - nReqXSize = nBlockXSize - nDstXOff; - - if (nDstYOff + nReqYSize > nBlockYSize) - nReqYSize = nBlockYSize - nDstYOff; - -#ifdef RASTERLITE_DEBUG - if (nBand == 1) - { - printf(/*ok*/ - "id = %d, minx=%.15f miny=%.15f maxx=%.15f maxy=%.15f\n" - "nDstXOff = %d, nDstYOff = %d, nSrcXOff = %d, nSrcYOff = " - "%d, " - "nReqXSize=%d, nReqYSize=%d\n", - nTileId, oEnvelope.MinX, oEnvelope.MinY, oEnvelope.MaxX, - oEnvelope.MaxY, nDstXOff, nDstYOff, nSrcXOff, nSrcYOff, - nReqXSize, nReqYSize); - } -#endif - - if (nReqXSize > 0 && nReqYSize > 0 && nSrcXOff < nTileXSize && - nSrcYOff < nTileYSize) - { - -#ifdef RASTERLITE_DEBUG - if (nBand == 1) - { - printf("id = %d, selected !\n", nTileId); /*ok*/ - } -#endif - int nDataSize = 0; - GByte *pabyData = OGR_F_GetFieldAsBinary(hFeat, 0, &nDataSize); - - VSILFILE *fp = VSIFileFromMemBuffer(osMemFileName.c_str(), pabyData, - nDataSize, FALSE); - VSIFCloseL(fp); - - GDALDatasetH hDSTile = GDALOpenEx(osMemFileName.c_str(), - GDAL_OF_RASTER | GDAL_OF_INTERNAL, - nullptr, nullptr, nullptr); - int nTileBands = 0; - if (hDSTile && (nTileBands = GDALGetRasterCount(hDSTile)) == 0) - { - GDALClose(hDSTile); - hDSTile = nullptr; - } - if (hDSTile == nullptr) - { - poGDS->m_nLastBadTileId = nTileId; - CPLError(CE_Failure, CPLE_AppDefined, "Can't open tile %d", - nTileId); - } - - int nReqBand = 1; - if (nTileBands == poGDS->nBands) - nReqBand = nBand; - else if (eDataType == GDT_Byte && nTileBands == 1 && - poGDS->nBands == 3) - nReqBand = 1; - else - { - poGDS->m_nLastBadTileId = nTileId; - GDALClose(hDSTile); - hDSTile = nullptr; - } - - if (hDSTile) - { - if (GDALGetRasterXSize(hDSTile) != nTileXSize || - GDALGetRasterYSize(hDSTile) != nTileYSize) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Invalid dimensions for tile %d", nTileId); - poGDS->m_nLastBadTileId = nTileId; - GDALClose(hDSTile); - hDSTile = nullptr; - } - } - - if (hDSTile) - { - bHasFoundTile = true; - - bool bHasJustMemsetTileBand1 = false; - - /* If the source tile doesn't fit the entire block size, then */ - /* we memset 0 before */ - if (!(nDstXOff == 0 && nDstYOff == 0 && - nReqXSize == nBlockXSize && nReqYSize == nBlockYSize) && - !bHasMemsetTile) - { - memset(pImage, 0, - static_cast(nBlockXSize) * nBlockYSize * - nDataTypeSize); - bHasMemsetTile = true; - bHasJustMemsetTileBand1 = true; - } - - GDALColorTable *poTileCT = reinterpret_cast( - GDALGetRasterColorTable(GDALGetRasterBand(hDSTile, 1))); - unsigned char *pabyTranslationTable = nullptr; - if (poGDS->nBands == 1 && poGDS->poCT != nullptr && - poTileCT != nullptr) - { - pabyTranslationTable = reinterpret_cast( - GDALGetRasterBand(hDSTile, 1)) - ->GetIndexColorTranslationTo( - this, nullptr, nullptr); - } - - /* -------------------------------------------------------------------- - */ - /* Read tile data */ - /* -------------------------------------------------------------------- - */ - eErr = GDALRasterIO( - GDALGetRasterBand(hDSTile, nReqBand), GF_Read, nSrcXOff, - nSrcYOff, nReqXSize, nReqYSize, - reinterpret_cast(pImage) + - (nDstXOff + nDstYOff * nBlockXSize) * nDataTypeSize, - nReqXSize, nReqYSize, eDataType, nDataTypeSize, - nBlockXSize * nDataTypeSize); - - if (eDataType == GDT_Byte && pabyTranslationTable) - { - /* -------------------------------------------------------------------- - */ - /* Convert from tile CT to band CT */ - /* -------------------------------------------------------------------- - */ - for (int j = nDstYOff; j < nDstYOff + nReqYSize; j++) - { - for (int i = nDstXOff; i < nDstXOff + nReqXSize; i++) - { - GByte *pPixel = reinterpret_cast(pImage) + - i + j * nBlockXSize; - *pPixel = pabyTranslationTable[*pPixel]; - } - } - CPLFree(pabyTranslationTable); - pabyTranslationTable = nullptr; - } - else if (eDataType == GDT_Byte && nTileBands == 1 && - poGDS->nBands == 3 && poTileCT != nullptr) - { - /* -------------------------------------------------------------------- - */ - /* Expand from PCT to RGB */ - /* -------------------------------------------------------------------- - */ - GByte abyCT[256]; - const int nEntries = - std::min(256, poTileCT->GetColorEntryCount()); - for (int i = 0; i < nEntries; i++) - { - const GDALColorEntry *psEntry = - poTileCT->GetColorEntry(i); - if (nBand == 1) - abyCT[i] = static_cast(psEntry->c1); - else if (nBand == 2) - abyCT[i] = static_cast(psEntry->c2); - else - abyCT[i] = static_cast(psEntry->c3); - } - for (int i = nEntries; i < 256; i++) - abyCT[i] = 0; - - for (int j = nDstYOff; j < nDstYOff + nReqYSize; j++) - { - for (int i = nDstXOff; i < nDstXOff + nReqXSize; i++) - { - GByte *pPixel = reinterpret_cast(pImage) + - i + j * nBlockXSize; - *pPixel = abyCT[*pPixel]; - } - } - } - - /* -------------------------------------------------------------------- - */ - /* Put in the block cache the data for this block into - * other bands */ - /* while the underlying dataset is opened */ - /* -------------------------------------------------------------------- - */ - if (nBand == 1 && poGDS->nBands > 1) - { - for (int iOtherBand = 2; - iOtherBand <= poGDS->nBands && eErr == CE_None; - iOtherBand++) - { - GDALRasterBlock *poBlock = - poGDS->GetRasterBand(iOtherBand) - ->GetLockedBlockRef(nBlockXOff, nBlockYOff, - TRUE); - if (poBlock == nullptr) - break; - - GByte *pabySrcBlock = - reinterpret_cast(poBlock->GetDataRef()); - if (pabySrcBlock == nullptr) - { - poBlock->DropLock(); - break; - } - - if (nTileBands == 1) - nReqBand = 1; - else - nReqBand = iOtherBand; - - if (bHasJustMemsetTileBand1) - memset(pabySrcBlock, 0, - static_cast(nBlockXSize) * - nBlockYSize * nDataTypeSize); - - /* -------------------------------------------------------------------- - */ - /* Read tile data */ - /* -------------------------------------------------------------------- - */ - eErr = GDALRasterIO( - GDALGetRasterBand(hDSTile, nReqBand), GF_Read, - nSrcXOff, nSrcYOff, nReqXSize, nReqYSize, - reinterpret_cast(pabySrcBlock) + - (nDstXOff + nDstYOff * nBlockXSize) * - nDataTypeSize, - nReqXSize, nReqYSize, eDataType, nDataTypeSize, - nBlockXSize * nDataTypeSize); - - if (eDataType == GDT_Byte && nTileBands == 1 && - poGDS->nBands == 3 && poTileCT != nullptr) - { - /* -------------------------------------------------------------------- - */ - /* Expand from PCT to RGB */ - /* -------------------------------------------------------------------- - */ - - GByte abyCT[256]; - const int nEntries = - std::min(256, poTileCT->GetColorEntryCount()); - for (int i = 0; i < nEntries; i++) - { - const GDALColorEntry *psEntry = - poTileCT->GetColorEntry(i); - if (iOtherBand == 2) - abyCT[i] = static_cast(psEntry->c2); - else - abyCT[i] = static_cast(psEntry->c3); - } - for (int i = nEntries; i < 256; i++) - abyCT[i] = 0; - - for (int j = nDstYOff; j < nDstYOff + nReqYSize; - j++) - { - for (int i = nDstXOff; i < nDstXOff + nReqXSize; - i++) - { - GByte *pPixel = reinterpret_cast( - pabySrcBlock) + - i + j * nBlockXSize; - *pPixel = abyCT[*pPixel]; - } - } - } - - poBlock->DropLock(); - } - } - GDALClose(hDSTile); - } - - VSIUnlink(osMemFileName.c_str()); - } - else - { -#ifdef RASTERLITE_DEBUG - if (nBand == 1) - { - printf("id = %d, NOT selected !\n", nTileId); /*ok*/ - } -#endif - } - OGR_F_Destroy(hFeat); - } - - VSIUnlink(osMemFileName.c_str()); - VSIUnlink((osMemFileName + ".aux.xml").c_str()); - - if (!bHasFoundTile) - { - memset(pImage, 0, - static_cast(nBlockXSize) * nBlockYSize * nDataTypeSize); - } - - GDALDatasetReleaseResultSet(poGDS->hDS, hSQLLyr); - -#ifdef RASTERLITE_DEBUG - if (nBand == 1) - printf("\n"); /*ok*/ -#endif - - return eErr; -} - -/************************************************************************/ -/* GetOverviewCount() */ -/************************************************************************/ - -int RasterliteBand::GetOverviewCount() -{ - RasterliteDataset *poGDS = reinterpret_cast(poDS); - - if (poGDS->nLimitOvrCount >= 0) - return poGDS->nLimitOvrCount; - else if (poGDS->nResolutions > 1) - return poGDS->nResolutions - 1; - else - return GDALPamRasterBand::GetOverviewCount(); -} - -/************************************************************************/ -/* GetOverview() */ -/************************************************************************/ - -GDALRasterBand *RasterliteBand::GetOverview(int nLevel) -{ - RasterliteDataset *poGDS = reinterpret_cast(poDS); - - if (poGDS->nLimitOvrCount >= 0) - { - if (nLevel < 0 || nLevel >= poGDS->nLimitOvrCount) - return nullptr; - } - - if (poGDS->nResolutions == 1) - return GDALPamRasterBand::GetOverview(nLevel); - - if (nLevel < 0 || nLevel >= poGDS->nResolutions - 1) - return nullptr; - - GDALDataset *poOvrDS = poGDS->papoOverviews[nLevel]; - if (poOvrDS) - return poOvrDS->GetRasterBand(nBand); - - return nullptr; -} - -/************************************************************************/ -/* GetColorInterpretation() */ -/************************************************************************/ - -GDALColorInterp RasterliteBand::GetColorInterpretation() -{ - RasterliteDataset *poGDS = reinterpret_cast(poDS); - if (poGDS->nBands == 1) - { - if (poGDS->poCT != nullptr) - return GCI_PaletteIndex; - - return GCI_GrayIndex; - } - else if (poGDS->nBands == 3) - { - if (nBand == 1) - return GCI_RedBand; - else if (nBand == 2) - return GCI_GreenBand; - else if (nBand == 3) - return GCI_BlueBand; - } - - return GCI_Undefined; -} - -/************************************************************************/ -/* GetColorTable() */ -/************************************************************************/ - -GDALColorTable *RasterliteBand::GetColorTable() -{ - RasterliteDataset *poGDS = reinterpret_cast(poDS); - if (poGDS->nBands == 1) - return poGDS->poCT; - - return nullptr; -} - -/************************************************************************/ -/* RasterliteDataset() */ -/************************************************************************/ - -RasterliteDataset::RasterliteDataset() - : bMustFree(FALSE), poMainDS(nullptr), nLevel(0), papszMetadata(nullptr), - papszImageStructure(CSLAddString(nullptr, "INTERLEAVE=PIXEL")), - papszSubDatasets(nullptr), nResolutions(0), padfXResolutions(nullptr), - padfYResolutions(nullptr), papoOverviews(nullptr), nLimitOvrCount(-1), - bValidGeoTransform(FALSE), poCT(nullptr), bCheckForExistingOverview(TRUE), - hDS(nullptr) -{ - m_oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); - memset(adfGeoTransform, 0, sizeof(adfGeoTransform)); -} - -/************************************************************************/ -/* RasterliteDataset() */ -/************************************************************************/ - -RasterliteDataset::RasterliteDataset(RasterliteDataset *poMainDSIn, - int nLevelIn) - : bMustFree(FALSE), poMainDS(poMainDSIn), nLevel(nLevelIn), - papszMetadata(poMainDSIn->papszMetadata), - papszImageStructure(poMainDSIn->papszImageStructure), - papszSubDatasets(poMainDS->papszSubDatasets), - nResolutions(poMainDSIn->nResolutions - nLevelIn), - padfXResolutions(poMainDSIn->padfXResolutions + nLevelIn), - padfYResolutions(poMainDSIn->padfYResolutions + nLevelIn), - papoOverviews(poMainDSIn->papoOverviews + nLevelIn), nLimitOvrCount(-1), - bValidGeoTransform(TRUE), m_oSRS(poMainDSIn->m_oSRS), - poCT(poMainDSIn->poCT), osTableName(poMainDSIn->osTableName), - osFileName(poMainDSIn->osFileName), bCheckForExistingOverview(TRUE), - // TODO: osOvrFileName? - hDS(poMainDSIn->hDS) -{ - nRasterXSize = static_cast( - poMainDS->nRasterXSize * - (poMainDS->padfXResolutions[0] / padfXResolutions[0]) + - 0.5); - nRasterYSize = static_cast( - poMainDS->nRasterYSize * - (poMainDS->padfYResolutions[0] / padfYResolutions[0]) + - 0.5); - - memcpy(adfGeoTransform, poMainDS->adfGeoTransform, 6 * sizeof(double)); - adfGeoTransform[1] = padfXResolutions[0]; - adfGeoTransform[5] = -padfYResolutions[0]; -} - -/************************************************************************/ -/* ~RasterliteDataset() */ -/************************************************************************/ - -RasterliteDataset::~RasterliteDataset() -{ - RasterliteDataset::CloseDependentDatasets(); -} - -/************************************************************************/ -/* CloseDependentDatasets() */ -/************************************************************************/ - -int RasterliteDataset::CloseDependentDatasets() -{ - int bRet = GDALPamDataset::CloseDependentDatasets(); - - if (poMainDS == nullptr && !bMustFree) - { - CSLDestroy(papszMetadata); - papszMetadata = nullptr; - CSLDestroy(papszSubDatasets); - papszSubDatasets = nullptr; - CSLDestroy(papszImageStructure); - papszImageStructure = nullptr; - - if (papoOverviews) - { - for (int i = 1; i < nResolutions; i++) - { - if (papoOverviews[i - 1] != nullptr && - papoOverviews[i - 1]->bMustFree) - { - papoOverviews[i - 1]->poMainDS = nullptr; - } - delete papoOverviews[i - 1]; - } - CPLFree(papoOverviews); - papoOverviews = nullptr; - nResolutions = 0; - bRet = TRUE; - } - - if (hDS != nullptr) - GDALClose(hDS); - hDS = nullptr; - - CPLFree(padfXResolutions); - CPLFree(padfYResolutions); - padfXResolutions = nullptr; - padfYResolutions = nullptr; - - delete poCT; - poCT = nullptr; - } - else if (poMainDS != nullptr && bMustFree) - { - poMainDS->papoOverviews[nLevel - 1] = nullptr; - delete poMainDS; - poMainDS = nullptr; - bRet = TRUE; - } - - return bRet; -} - -/************************************************************************/ -/* AddSubDataset() */ -/************************************************************************/ - -void RasterliteDataset::AddSubDataset(const char *pszDSName) -{ - char szName[80]; - const int nCount = CSLCount(papszSubDatasets) / 2; - - snprintf(szName, sizeof(szName), "SUBDATASET_%d_NAME", nCount + 1); - papszSubDatasets = CSLSetNameValue(papszSubDatasets, szName, pszDSName); - - snprintf(szName, sizeof(szName), "SUBDATASET_%d_DESC", nCount + 1); - papszSubDatasets = CSLSetNameValue(papszSubDatasets, szName, pszDSName); -} - -/************************************************************************/ -/* GetMetadataDomainList() */ -/************************************************************************/ - -char **RasterliteDataset::GetMetadataDomainList() -{ - return BuildMetadataDomainList(GDALPamDataset::GetMetadataDomainList(), - TRUE, "SUBDATASETS", "IMAGE_STRUCTURE", - nullptr); -} - -/************************************************************************/ -/* GetMetadata() */ -/************************************************************************/ - -char **RasterliteDataset::GetMetadata(const char *pszDomain) - -{ - if (pszDomain != nullptr && EQUAL(pszDomain, "SUBDATASETS")) - return papszSubDatasets; - - if (CSLCount(papszSubDatasets) < 2 && pszDomain != nullptr && - EQUAL(pszDomain, "IMAGE_STRUCTURE")) - return papszImageStructure; - - if (pszDomain == nullptr || EQUAL(pszDomain, "")) - return papszMetadata; - - return GDALPamDataset::GetMetadata(pszDomain); -} - -/************************************************************************/ -/* GetMetadataItem() */ -/************************************************************************/ - -const char *RasterliteDataset::GetMetadataItem(const char *pszName, - const char *pszDomain) -{ - if (pszDomain != nullptr && EQUAL(pszDomain, "OVERVIEWS")) - { - if (nResolutions > 1 || CSLCount(papszSubDatasets) > 2) - return nullptr; - - osOvrFileName.Printf("%s_%s", osFileName.c_str(), osTableName.c_str()); - if (bCheckForExistingOverview == FALSE || - CPLCheckForFile(const_cast(osOvrFileName.c_str()), nullptr)) - return osOvrFileName.c_str(); - - return nullptr; - } - - return GDALPamDataset::GetMetadataItem(pszName, pszDomain); -} - -/************************************************************************/ -/* GetGeoTransform() */ -/************************************************************************/ - -CPLErr RasterliteDataset::GetGeoTransform(double *padfGeoTransform) -{ - if (bValidGeoTransform) - { - memcpy(padfGeoTransform, adfGeoTransform, 6 * sizeof(double)); - return CE_None; - } - - return CE_Failure; -} - -/************************************************************************/ -/* GetSpatialRef() */ -/************************************************************************/ - -const OGRSpatialReference *RasterliteDataset::GetSpatialRef() const -{ - return m_oSRS.IsEmpty() ? nullptr : &m_oSRS; -} - -/************************************************************************/ -/* GetFileList() */ -/************************************************************************/ - -char **RasterliteDataset::GetFileList() -{ - char **papszFileList = CSLAddString(nullptr, osFileName); - return papszFileList; -} - -/************************************************************************/ -/* GetBlockParams() */ -/************************************************************************/ - -int RasterliteDataset::GetBlockParams(OGRLayerH hRasterLyr, int nLevelIn, - int *pnBands, GDALDataType *peDataType, - int *pnBlockXSize, int *pnBlockYSize) -{ - CPLString osSQL; - osSQL.Printf("SELECT m.geometry, r.raster, m.id " - "FROM \"%s_metadata\" AS m, \"%s_rasters\" AS r " - "WHERE %s AND r.id = m.id", - osTableName.c_str(), osTableName.c_str(), - RasterliteGetPixelSizeCond(padfXResolutions[nLevelIn], - padfYResolutions[nLevelIn], "m.") - .c_str()); - - OGRLayerH hSQLLyr = - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - if (hSQLLyr == nullptr) - { - return FALSE; - } - - OGRFeatureH hFeat = OGR_L_GetNextFeature(hRasterLyr); - if (hFeat == nullptr) - { - GDALDatasetReleaseResultSet(hDS, hSQLLyr); - return FALSE; - } - - int nDataSize; - GByte *pabyData = OGR_F_GetFieldAsBinary(hFeat, 0, &nDataSize); - - if (nDataSize > 32 && - STARTS_WITH_CI(reinterpret_cast(pabyData), - "StartWaveletsImage$$")) - { - CPLError(CE_Failure, CPLE_NotSupported, - "Rasterlite driver no longer support WAVELET compressed " - "images"); - OGR_F_Destroy(hFeat); - GDALDatasetReleaseResultSet(hDS, hSQLLyr); - return FALSE; - } - - const CPLString osMemFileName( - VSIMemGenerateHiddenFilename("rasterlite_tile")); - VSILFILE *fp = - VSIFileFromMemBuffer(osMemFileName.c_str(), pabyData, nDataSize, FALSE); - VSIFCloseL(fp); - - GDALDatasetH hDSTile = GDALOpen(osMemFileName.c_str(), GA_ReadOnly); - if (hDSTile) - { - *pnBands = GDALGetRasterCount(hDSTile); - if (*pnBands == 0) - { - GDALClose(hDSTile); - hDSTile = nullptr; - } - } - else - { - CPLError(CE_Failure, CPLE_AppDefined, "Can't open tile %d", - OGR_F_GetFieldAsInteger(hFeat, 1)); - } - - if (hDSTile) - { - *peDataType = GDALGetRasterDataType(GDALGetRasterBand(hDSTile, 1)); - - for (int iBand = 2; iBand <= *pnBands; iBand++) - { - if (*peDataType != - GDALGetRasterDataType(GDALGetRasterBand(hDSTile, 1))) - { - CPLError(CE_Failure, CPLE_NotSupported, - "Band types must be identical"); - GDALClose(hDSTile); - hDSTile = nullptr; - goto end; - } - } - - *pnBlockXSize = GDALGetRasterXSize(hDSTile); - *pnBlockYSize = GDALGetRasterYSize(hDSTile); - if (CSLFindName(papszImageStructure, "COMPRESSION") == -1) - { - const char *pszCompression = - GDALGetMetadataItem(hDSTile, "COMPRESSION", "IMAGE_STRUCTURE"); - if (pszCompression != nullptr && EQUAL(pszCompression, "JPEG")) - papszImageStructure = - CSLAddString(papszImageStructure, "COMPRESSION=JPEG"); - } - - if (CSLFindName(papszMetadata, "TILE_FORMAT") == -1) - { - papszMetadata = CSLSetNameValue( - papszMetadata, "TILE_FORMAT", - GDALGetDriverShortName(GDALGetDatasetDriver(hDSTile))); - } - - if (*pnBands == 1 && this->poCT == nullptr) - { - GDALColorTable *l_poCT = reinterpret_cast( - GDALGetRasterColorTable(GDALGetRasterBand(hDSTile, 1))); - if (l_poCT) - this->poCT = l_poCT->Clone(); - } - - GDALClose(hDSTile); - } -end: - VSIUnlink(osMemFileName.c_str()); - VSIUnlink((osMemFileName + ".aux.xml").c_str()); - - OGR_F_Destroy(hFeat); - - GDALDatasetReleaseResultSet(hDS, hSQLLyr); - - return hDSTile != nullptr; -} - -/************************************************************************/ -/* Open() */ -/************************************************************************/ - -GDALDataset *RasterliteDataset::Open(GDALOpenInfo *poOpenInfo) -{ - if (RasterliteDriverIdentify(poOpenInfo) == FALSE) - return nullptr; - - CPLString osFileName; - CPLString osTableName; - int nLevel = 0; - double minx = 0.0; - double miny = 0.0; - double maxx = 0.0; - double maxy = 0.0; - int bMinXSet = FALSE; - int bMinYSet = FALSE; - int bMaxXSet = FALSE; - int bMaxYSet = FALSE; - int nReqBands = 0; - -/* -------------------------------------------------------------------- */ -/* Parse "file name" */ -/* -------------------------------------------------------------------- */ -#ifdef ENABLE_SQL_SQLITE_FORMAT - if (poOpenInfo->pabyHeader && - STARTS_WITH((const char *)poOpenInfo->pabyHeader, "-- SQL RASTERLITE")) - { - osFileName = poOpenInfo->pszFilename; - } - else -#endif - if (poOpenInfo->nHeaderBytes >= 1024 && poOpenInfo->pabyHeader && - STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, - "SQLite Format 3")) - { - osFileName = poOpenInfo->pszFilename; - } - else - { - char **papszTokens = CSLTokenizeStringComplex( - poOpenInfo->pszFilename + 11, ",", FALSE, FALSE); - int nTokens = CSLCount(papszTokens); - if (nTokens == 0) - { - CSLDestroy(papszTokens); - return nullptr; - } - - osFileName = papszTokens[0]; - - for (int i = 1; i < nTokens; i++) - { - if (STARTS_WITH_CI(papszTokens[i], "table=")) - osTableName = papszTokens[i] + 6; - else if (STARTS_WITH_CI(papszTokens[i], "level=")) - nLevel = atoi(papszTokens[i] + 6); - else if (STARTS_WITH_CI(papszTokens[i], "minx=")) - { - bMinXSet = TRUE; - minx = CPLAtof(papszTokens[i] + 5); - } - else if (STARTS_WITH_CI(papszTokens[i], "miny=")) - { - bMinYSet = TRUE; - miny = CPLAtof(papszTokens[i] + 5); - } - else if (STARTS_WITH_CI(papszTokens[i], "maxx=")) - { - bMaxXSet = TRUE; - maxx = CPLAtof(papszTokens[i] + 5); - } - else if (STARTS_WITH_CI(papszTokens[i], "maxy=")) - { - bMaxYSet = TRUE; - maxy = CPLAtof(papszTokens[i] + 5); - } - else if (STARTS_WITH_CI(papszTokens[i], "bands=")) - { - nReqBands = atoi(papszTokens[i] + 6); - } - else - { - CPLError(CE_Warning, CPLE_AppDefined, "Invalid option : %s", - papszTokens[i]); - } - } - CSLDestroy(papszTokens); - } - - /* -------------------------------------------------------------------- */ - /* Open underlying OGR DB */ - /* -------------------------------------------------------------------- */ - - GDALDatasetH hDS = - RasterliteOpenSQLiteDB(osFileName.c_str(), poOpenInfo->eAccess); - CPLDebug("RASTERLITE", "SQLite DB Open"); - - RasterliteDataset *poDS = nullptr; - - if (hDS == nullptr) - goto end; - - if (osTableName.empty()) - { - int nCountSubdataset = 0; - const int nLayers = GDALDatasetGetLayerCount(hDS); - /* -------------------------------------------------------------------- - */ - /* Add raster layers as subdatasets */ - /* -------------------------------------------------------------------- - */ - for (int i = 0; i < nLayers; i++) - { - OGRLayerH hLyr = GDALDatasetGetLayer(hDS, i); - const std::string osLayerName = OGR_L_GetName(hLyr); - const auto nPosMetadata = osLayerName.find("_metadata"); - if (nPosMetadata != std::string::npos) - { - const std::string osShortName = - osLayerName.substr(0, nPosMetadata); - - const std::string osRasterTableName = - std::string(osShortName).append("_rasters"); - - if (GDALDatasetGetLayerByName(hDS, osRasterTableName.c_str()) != - nullptr) - { - if (poDS == nullptr) - { - poDS = new RasterliteDataset(); - osTableName = osShortName; - } - - std::string osSubdatasetName; - if (!STARTS_WITH_CI(poOpenInfo->pszFilename, "RASTERLITE:")) - osSubdatasetName += "RASTERLITE:"; - osSubdatasetName += poOpenInfo->pszFilename; - osSubdatasetName += ",table="; - osSubdatasetName += osShortName; - poDS->AddSubDataset(osSubdatasetName.c_str()); - - nCountSubdataset++; - } - } - } - - if (nCountSubdataset == 0) - { - goto end; - } - else if (nCountSubdataset != 1) - { - poDS->SetDescription(poOpenInfo->pszFilename); - goto end; - } - - /* -------------------------------------------------------------------- - */ - /* If just one subdataset, then open it */ - /* -------------------------------------------------------------------- - */ - delete poDS; - poDS = nullptr; - } - - /* -------------------------------------------------------------------- */ - /* Build dataset */ - /* -------------------------------------------------------------------- */ - { - GDALDataType eDataType; - - const CPLString osMetadataTableName = osTableName + "_metadata"; - - OGRLayerH hMetadataLyr = - GDALDatasetGetLayerByName(hDS, osMetadataTableName.c_str()); - if (hMetadataLyr == nullptr) - goto end; - - const CPLString osRasterTableName = osTableName + "_rasters"; - - OGRLayerH hRasterLyr = - GDALDatasetGetLayerByName(hDS, osRasterTableName.c_str()); - if (hRasterLyr == nullptr) - goto end; - - /* -------------------------------------------------------------------- - */ - /* Fetch resolutions */ - /* -------------------------------------------------------------------- - */ - CPLString osSQL; - OGRLayerH hSQLLyr; - int nResolutions = 0; - - OGRLayerH hRasterPyramidsLyr = - GDALDatasetGetLayerByName(hDS, "raster_pyramids"); - if (hRasterPyramidsLyr) - { - osSQL.Printf("SELECT pixel_x_size, pixel_y_size " - "FROM raster_pyramids WHERE table_prefix = '%s' " - "ORDER BY pixel_x_size ASC", - osTableName.c_str()); - - hSQLLyr = - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - if (hSQLLyr != nullptr) - { - nResolutions = - static_cast(OGR_L_GetFeatureCount(hSQLLyr, TRUE)); - if (nResolutions == 0) - { - GDALDatasetReleaseResultSet(hDS, hSQLLyr); - hSQLLyr = nullptr; - } - } - } - else - hSQLLyr = nullptr; - - if (hSQLLyr == nullptr) - { - osSQL.Printf("SELECT DISTINCT(pixel_x_size), pixel_y_size " - "FROM \"%s_metadata\" WHERE pixel_x_size != 0 " - "ORDER BY pixel_x_size ASC", - osTableName.c_str()); - - hSQLLyr = - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - if (hSQLLyr == nullptr) - goto end; - - nResolutions = - static_cast(OGR_L_GetFeatureCount(hSQLLyr, TRUE)); - - if (nResolutions == 0) - { - GDALDatasetReleaseResultSet(hDS, hSQLLyr); - goto end; - } - } - - /* -------------------------------------------------------------------- - */ - /* Set dataset attributes */ - /* -------------------------------------------------------------------- - */ - - poDS = new RasterliteDataset(); - poDS->SetDescription(poOpenInfo->pszFilename); - poDS->eAccess = poOpenInfo->eAccess; - poDS->osTableName = osTableName; - poDS->osFileName = osFileName; - poDS->hDS = hDS; - - /* poDS will release it from now */ - hDS = nullptr; - - /* -------------------------------------------------------------------- - */ - /* Fetch spatial extent or use the one provided by the user */ - /* -------------------------------------------------------------------- - */ - OGREnvelope oEnvelope; - if (bMinXSet && bMinYSet && bMaxXSet && bMaxYSet) - { - oEnvelope.MinX = minx; - oEnvelope.MinY = miny; - oEnvelope.MaxX = maxx; - oEnvelope.MaxY = maxy; - } - else - { - CPLConfigOptionSetter oSetter("OGR_SQLITE_EXACT_EXTENT", "YES", - false); - OGR_L_GetExtent(hMetadataLyr, &oEnvelope, TRUE); - // printf("minx=%.15f miny=%.15f maxx=%.15f maxy=%.15f\n", - // oEnvelope.MinX, oEnvelope.MinY, oEnvelope.MaxX, - // oEnvelope.MaxY); - } - - /* -------------------------------------------------------------------- - */ - /* Store resolutions */ - /* -------------------------------------------------------------------- - */ - poDS->nResolutions = nResolutions; - poDS->padfXResolutions = reinterpret_cast( - CPLMalloc(sizeof(double) * poDS->nResolutions)); - poDS->padfYResolutions = reinterpret_cast( - CPLMalloc(sizeof(double) * poDS->nResolutions)); - - { - // Add a scope for i. - OGRFeatureH hFeat; - int i = 0; - while ((hFeat = OGR_L_GetNextFeature(hSQLLyr)) != nullptr) - { - poDS->padfXResolutions[i] = OGR_F_GetFieldAsDouble(hFeat, 0); - poDS->padfYResolutions[i] = OGR_F_GetFieldAsDouble(hFeat, 1); - - OGR_F_Destroy(hFeat); - -#ifdef RASTERLITE_DEBUG - printf("[%d] xres=%.15f yres=%.15f\n", i, /*ok*/ - poDS->padfXResolutions[i], poDS->padfYResolutions[i]); -#endif - - if (poDS->padfXResolutions[i] <= 0 || - poDS->padfYResolutions[i] <= 0) - { - CPLError(CE_Failure, CPLE_NotSupported, - "res=%d, xres=%.15f, yres=%.15f", i, - poDS->padfXResolutions[i], - poDS->padfYResolutions[i]); - GDALDatasetReleaseResultSet(poDS->hDS, hSQLLyr); - delete poDS; - poDS = nullptr; - goto end; - } - i++; - } - } - - GDALDatasetReleaseResultSet(poDS->hDS, hSQLLyr); - hSQLLyr = nullptr; - - /* -------------------------------------------------------------------- - */ - /* Compute raster size, geotransform and projection */ - /* -------------------------------------------------------------------- - */ - const double dfRasterXSize = - (oEnvelope.MaxX - oEnvelope.MinX) / poDS->padfXResolutions[0] + 0.5; - const double dfRasterYSize = - (oEnvelope.MaxY - oEnvelope.MinY) / poDS->padfYResolutions[0] + 0.5; - if (!(dfRasterXSize >= 1 && dfRasterXSize <= INT_MAX) || - !(dfRasterYSize >= 1 && dfRasterYSize <= INT_MAX)) - { - delete poDS; - poDS = nullptr; - goto end; - } - poDS->nRasterXSize = static_cast(dfRasterXSize); - poDS->nRasterYSize = static_cast(dfRasterYSize); - - poDS->bValidGeoTransform = TRUE; - poDS->adfGeoTransform[0] = oEnvelope.MinX; - poDS->adfGeoTransform[1] = poDS->padfXResolutions[0]; - poDS->adfGeoTransform[2] = 0; - poDS->adfGeoTransform[3] = oEnvelope.MaxY; - poDS->adfGeoTransform[4] = 0; - poDS->adfGeoTransform[5] = -poDS->padfYResolutions[0]; - - OGRSpatialReferenceH hSRS = OGR_L_GetSpatialRef(hMetadataLyr); - if (hSRS) - { - poDS->m_oSRS = *(OGRSpatialReference::FromHandle(hSRS)); - } - - /* -------------------------------------------------------------------- - */ - /* Get number of bands and block size */ - /* -------------------------------------------------------------------- - */ - - int nBands; - int nBlockXSize, nBlockYSize; - if (poDS->GetBlockParams(hRasterLyr, 0, &nBands, &eDataType, - &nBlockXSize, &nBlockYSize) == FALSE) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Cannot find block characteristics"); - delete poDS; - poDS = nullptr; - goto end; - } - - if (eDataType == GDT_Byte && nBands == 1 && nReqBands == 3) - nBands = 3; - else if (nReqBands != 0) - { - CPLError(CE_Warning, CPLE_NotSupported, - "Parameters bands=%d ignored", nReqBands); - } - - /* -------------------------------------------------------------------- - */ - /* Add bands */ - /* -------------------------------------------------------------------- - */ - - for (int iBand = 0; iBand < nBands; iBand++) - poDS->SetBand(iBand + 1, - new RasterliteBand(poDS, iBand + 1, eDataType, - nBlockXSize, nBlockYSize)); - - /* -------------------------------------------------------------------- - */ - /* Add overview levels as internal datasets */ - /* -------------------------------------------------------------------- - */ - if (nResolutions > 1) - { - poDS->papoOverviews = reinterpret_cast( - CPLCalloc(nResolutions - 1, sizeof(RasterliteDataset *))); - for (int nLev = 1; nLev < nResolutions; nLev++) - { - int nOvrBands; - GDALDataType eOvrDataType; - if (poDS->GetBlockParams(hRasterLyr, nLev, &nOvrBands, - &eOvrDataType, &nBlockXSize, - &nBlockYSize) == FALSE) - { - CPLError( - CE_Failure, CPLE_AppDefined, - "Cannot find block characteristics for overview %d", - nLev); - delete poDS; - poDS = nullptr; - goto end; - } - - if (eDataType == GDT_Byte && nOvrBands == 1 && nReqBands == 3) - nOvrBands = 3; - - if (nBands != nOvrBands || eDataType != eOvrDataType) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Overview %d has not the same number " - "characteristics as main band", - nLev); - delete poDS; - poDS = nullptr; - goto end; - } - - poDS->papoOverviews[nLev - 1] = - new RasterliteDataset(poDS, nLev); - - for (int iBand = 0; iBand < nBands; iBand++) - { - poDS->papoOverviews[nLev - 1]->SetBand( - iBand + 1, new RasterliteBand( - poDS->papoOverviews[nLev - 1], iBand + 1, - eDataType, nBlockXSize, nBlockYSize)); - } - } - } - - /* -------------------------------------------------------------------- - */ - /* Select an overview if the user has requested so */ - /* -------------------------------------------------------------------- - */ - if (nLevel == 0) - { - } - else if (nLevel >= 1 && nLevel <= nResolutions - 1) - { - poDS->papoOverviews[nLevel - 1]->bMustFree = TRUE; - poDS = poDS->papoOverviews[nLevel - 1]; - } - else - { - CPLError(CE_Failure, CPLE_AppDefined, - "Invalid requested level : %d. Must be >= 0 and <= %d", - nLevel, nResolutions - 1); - delete poDS; - poDS = nullptr; - } - } - - if (poDS) - { - /* -------------------------------------------------------------------- - */ - /* Setup PAM info for this subdatasets */ - /* -------------------------------------------------------------------- - */ - poDS->SetPhysicalFilename(osFileName.c_str()); - - CPLString osSubdatasetName; - osSubdatasetName.Printf("RASTERLITE:%s:table=%s", osFileName.c_str(), - osTableName.c_str()); - poDS->SetSubdatasetName(osSubdatasetName.c_str()); - poDS->TryLoadXML(); - poDS->oOvManager.Initialize(poDS, ":::VIRTUAL:::"); - } - -end: - if (hDS) - GDALClose(hDS); - - return poDS; -} - -/************************************************************************/ -/* GDALRegister_Rasterlite() */ -/************************************************************************/ - -void GDALRegister_Rasterlite() - -{ - if (!GDAL_CHECK_VERSION("Rasterlite driver")) - return; - - if (GDALGetDriverByName(DRIVER_NAME) != nullptr) - return; - - GDALDriver *poDriver = new GDALDriver(); - RasterliteDriverSetCommonMetadata(poDriver); - - poDriver->pfnOpen = RasterliteDataset::Open; - poDriver->pfnCreateCopy = RasterliteCreateCopy; - poDriver->pfnDelete = RasterliteDelete; - - GetGDALDriverManager()->RegisterDriver(poDriver); -} diff --git a/frmts/rasterlite/rasterlitedataset.h b/frmts/rasterlite/rasterlitedataset.h deleted file mode 100644 index 55a82c43df0d..000000000000 --- a/frmts/rasterlite/rasterlitedataset.h +++ /dev/null @@ -1,142 +0,0 @@ -/****************************************************************************** - * - * Project: GDAL Rasterlite driver - * Purpose: Implement GDAL Rasterlite support using OGR SQLite driver - * Author: Even Rouault, - * - ********************************************************************** - * Copyright (c) 2009-2013, Even Rouault - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#ifndef RASTERLITE_DATASET_INCLUDED -#define RASTERLITE_DATASET_INCLUDED - -#include "gdal_pam.h" -#include "ogr_api.h" - -char **RasterliteGetTileDriverOptions(CSLConstList papszOptions); - -GDALDatasetH RasterliteOpenSQLiteDB(const char *pszFilename, - GDALAccess eAccess); -CPLString RasterliteGetPixelSizeCond(double dfPixelXSize, double dfPixelYSize, - const char *pszTablePrefixWithDot = ""); -CPLString RasterliteGetSpatialFilterCond(double minx, double miny, double maxx, - double maxy); - -class RasterliteBand; - -/************************************************************************/ -/* ==================================================================== */ -/* RasterliteDataset */ -/* ==================================================================== */ -/************************************************************************/ - -class RasterliteDataset final : public GDALPamDataset -{ - friend class RasterliteBand; - - public: - RasterliteDataset(); - RasterliteDataset(RasterliteDataset *poMainDS, int nLevel); - - virtual ~RasterliteDataset(); - - virtual char **GetMetadataDomainList() override; - virtual char **GetMetadata(const char *pszDomain) override; - virtual const char *GetMetadataItem(const char *pszName, - const char *pszDomain) override; - virtual CPLErr GetGeoTransform(double *padfGeoTransform) override; - - const OGRSpatialReference *GetSpatialRef() const override; - - virtual char **GetFileList() override; - - virtual CPLErr IBuildOverviews(const char *pszResampling, int nOverviews, - const int *panOverviewList, int nBands, - const int *panBandList, - GDALProgressFunc pfnProgress, - void *pProgressData, - CSLConstList papszOptions) override; - - static GDALDataset *Open(GDALOpenInfo *); - - protected: - virtual int CloseDependentDatasets() override; - - private: - int bMustFree; - RasterliteDataset *poMainDS; - int nLevel; - - char **papszMetadata; - char **papszImageStructure; - char **papszSubDatasets; - - int nResolutions; - double *padfXResolutions; - double *padfYResolutions; - RasterliteDataset **papoOverviews; - int nLimitOvrCount; - - int bValidGeoTransform; - double adfGeoTransform[6]; - OGRSpatialReference m_oSRS{}; - - GDALColorTable *poCT; - - CPLString osTableName; - CPLString osFileName; - - int bCheckForExistingOverview; - CPLString osOvrFileName; - - GDALDatasetH hDS; - - int m_nLastBadTileId = -1; - - void AddSubDataset(const char *pszDSName); - int GetBlockParams(OGRLayerH hRasterLyr, int nLevel, int *pnBands, - GDALDataType *peDataType, int *pnBlockXSize, - int *pnBlockYSize); - CPLErr CleanOverviews(); - CPLErr CleanOverviewLevel(int nOvrFactor); - CPLErr ReloadOverviews(); - CPLErr CreateOverviewLevel(const char *pszResampling, int nOvrFactor, - CSLConstList papszOptions, - GDALProgressFunc pfnProgress, - void *pProgressData); -}; - -/************************************************************************/ -/* ==================================================================== */ -/* RasterliteBand */ -/* ==================================================================== */ -/************************************************************************/ - -class RasterliteBand final : public GDALPamRasterBand -{ - friend class RasterliteDataset; - - public: - RasterliteBand(RasterliteDataset *poDS, int nBand, GDALDataType eDataType, - int nBlockXSize, int nBlockYSize); - - virtual GDALColorInterp GetColorInterpretation() override; - virtual GDALColorTable *GetColorTable() override; - - virtual int GetOverviewCount() override; - virtual GDALRasterBand *GetOverview(int nLevel) override; - - virtual CPLErr IReadBlock(int, int, void *) override; -}; - -GDALDataset *RasterliteCreateCopy(const char *pszFilename, GDALDataset *poSrcDS, - int bStrict, char **papszOptions, - GDALProgressFunc pfnProgress, - void *pProgressData); - -CPLErr RasterliteDelete(const char *pszFilename); - -#endif // RASTERLITE_DATASET_INCLUDED diff --git a/frmts/rasterlite/rasterlitedrivercore.cpp b/frmts/rasterlite/rasterlitedrivercore.cpp deleted file mode 100644 index f3377f9fdb13..000000000000 --- a/frmts/rasterlite/rasterlitedrivercore.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/****************************************************************************** - * - * Project: GDAL Rasterlite driver - * Purpose: Implement GDAL Rasterlite support using OGR SQLite driver - * Author: Even Rouault, - * - ********************************************************************** - * Copyright (c) 2009-2013, Even Rouault - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "rasterlitedrivercore.h" - -/************************************************************************/ -/* RasterliteDriverIdentify() */ -/************************************************************************/ - -int RasterliteDriverIdentify(GDALOpenInfo *poOpenInfo) - -{ -#ifdef ENABLE_SQL_SQLITE_FORMAT - if (poOpenInfo->pabyHeader && - STARTS_WITH((const char *)poOpenInfo->pabyHeader, "-- SQL RASTERLITE")) - { - return TRUE; - } -#endif - - if (!poOpenInfo->IsExtensionEqualToCI("MBTILES") && - !poOpenInfo->IsExtensionEqualToCI("GPKG") && - poOpenInfo->nHeaderBytes >= 1024 && poOpenInfo->pabyHeader && - STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, - "SQLite Format 3") && - // Do not match direct Amazon S3 signed URLs that contains .mbtiles in - // the middle of the URL - strstr(poOpenInfo->pszFilename, ".mbtiles") == nullptr) - { - // Could be a SQLite/Spatialite file as well - return -1; - } - else if (STARTS_WITH_CI(poOpenInfo->pszFilename, "RASTERLITE:")) - { - return TRUE; - } - - return FALSE; -} - -/************************************************************************/ -/* RasterliteDriverSetCommonMetadata() */ -/************************************************************************/ - -void RasterliteDriverSetCommonMetadata(GDALDriver *poDriver) -{ - poDriver->SetDescription(DRIVER_NAME); - poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES"); - poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Rasterlite"); - poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, - "drivers/raster/rasterlite.html"); - poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "sqlite"); - poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "YES"); - poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, - "Byte UInt16 Int16 UInt32 Int32 Float32 " - "Float64 CInt16 CInt32 CFloat32 CFloat64"); - poDriver->SetMetadataItem( - GDAL_DMD_CREATIONOPTIONLIST, - "" - " " - ""); - poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); - -#ifdef ENABLE_SQL_SQLITE_FORMAT - poDriver->SetMetadataItem("ENABLE_SQL_SQLITE_FORMAT", "YES"); -#endif - - poDriver->pfnIdentify = RasterliteDriverIdentify; - poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES"); - poDriver->SetMetadataItem(GDAL_DCAP_CREATECOPY, "YES"); -} - -/************************************************************************/ -/* DeclareDeferredRasterlitePlugin() */ -/************************************************************************/ - -#ifdef PLUGIN_FILENAME -void DeclareDeferredRasterlitePlugin() -{ - if (GDALGetDriverByName(DRIVER_NAME) != nullptr) - { - return; - } - auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME); -#ifdef PLUGIN_INSTALLATION_MESSAGE - poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE, - PLUGIN_INSTALLATION_MESSAGE); -#endif - RasterliteDriverSetCommonMetadata(poDriver); - GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver); -} -#endif diff --git a/frmts/rasterlite/rasterlitedrivercore.h b/frmts/rasterlite/rasterlitedrivercore.h deleted file mode 100644 index 9433130ed389..000000000000 --- a/frmts/rasterlite/rasterlitedrivercore.h +++ /dev/null @@ -1,36 +0,0 @@ -/****************************************************************************** - * - * Project: GDAL Rasterlite driver - * Purpose: Implement GDAL Rasterlite support using OGR SQLite driver - * Author: Even Rouault, - * - ********************************************************************** - * Copyright (c) 2009-2013, Even Rouault - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#ifndef RASTERLITEDRIVERCORE_H -#define RASTERLITEDRIVERCORE_H - -#include "gdal_priv.h" - -#if defined(DEBUG) || defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) || \ - defined(ALLOW_FORMAT_DUMPS) -// Enable accepting a SQL dump (starting with a "-- SQL SQLITE" or -// "-- SQL RASTERLITE" line) as a valid -// file. This makes fuzzer life easier -#define ENABLE_SQL_SQLITE_FORMAT -#endif - -constexpr const char *DRIVER_NAME = "Rasterlite"; - -#define RasterliteDriverIdentify PLUGIN_SYMBOL_NAME(RasterliteDriverIdentify) -#define RasterliteDriverSetCommonMetadata \ - PLUGIN_SYMBOL_NAME(RasterliteDriverSetCommonMetadata) - -int RasterliteDriverIdentify(GDALOpenInfo *poOpenInfo); - -void RasterliteDriverSetCommonMetadata(GDALDriver *poDriver); - -#endif diff --git a/frmts/rasterlite/rasterliteoverviews.cpp b/frmts/rasterlite/rasterliteoverviews.cpp deleted file mode 100644 index 62707d8b1ed7..000000000000 --- a/frmts/rasterlite/rasterliteoverviews.cpp +++ /dev/null @@ -1,828 +0,0 @@ -/****************************************************************************** - * - * Project: GDAL Rasterlite driver - * Purpose: Implement GDAL Rasterlite support using OGR SQLite driver - * Author: Even Rouault, - * - ********************************************************************** - * Copyright (c) 2009-2012, Even Rouault - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "cpl_string.h" -#include "ogr_api.h" -#include "ogr_srs_api.h" -#include "memdataset.h" - -#include "rasterlitedataset.h" - -/************************************************************************/ -/* ReloadOverviews() */ -/************************************************************************/ - -CPLErr RasterliteDataset::ReloadOverviews() -{ - if (nLevel != 0) - return CE_Failure; - - /* -------------------------------------------------------------------- */ - /* Fetch resolutions */ - /* -------------------------------------------------------------------- */ - - CPLString osSQL; - OGRLayerH hRasterPyramidsLyr = - GDALDatasetGetLayerByName(hDS, "raster_pyramids"); - if (hRasterPyramidsLyr) - { - osSQL.Printf("SELECT pixel_x_size, pixel_y_size " - "FROM raster_pyramids WHERE table_prefix = '%s' " - "ORDER BY pixel_x_size ASC", - osTableName.c_str()); - } - else - { - osSQL.Printf("SELECT DISTINCT(pixel_x_size), pixel_y_size " - "FROM \"%s_metadata\" WHERE pixel_x_size != 0 " - "ORDER BY pixel_x_size ASC", - osTableName.c_str()); - } - - OGRLayerH hSQLLyr = - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - if (hSQLLyr == nullptr) - { - if (hRasterPyramidsLyr == nullptr) - return CE_Failure; - - osSQL.Printf("SELECT DISTINCT(pixel_x_size), pixel_y_size " - "FROM \"%s_metadata\" WHERE pixel_x_size != 0 " - "ORDER BY pixel_x_size ASC", - osTableName.c_str()); - - hSQLLyr = GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - if (hSQLLyr == nullptr) - return CE_Failure; - } - - /* -------------------------------------------------------------------- */ - /* Cleanup */ - /* -------------------------------------------------------------------- */ - for (int i = 1; i < nResolutions; i++) - delete papoOverviews[i - 1]; - CPLFree(papoOverviews); - papoOverviews = nullptr; - CPLFree(padfXResolutions); - padfXResolutions = nullptr; - CPLFree(padfYResolutions); - padfYResolutions = nullptr; - - /* -------------------------------------------------------------------- */ - /* Rebuild arrays */ - /* -------------------------------------------------------------------- */ - - nResolutions = static_cast(OGR_L_GetFeatureCount(hSQLLyr, TRUE)); - - padfXResolutions = - reinterpret_cast(CPLMalloc(sizeof(double) * nResolutions)); - padfYResolutions = - reinterpret_cast(CPLMalloc(sizeof(double) * nResolutions)); - - { - // Exstra scope for i. - int i = 0; - OGRFeatureH hFeat; - while ((hFeat = OGR_L_GetNextFeature(hSQLLyr)) != nullptr) - { - padfXResolutions[i] = OGR_F_GetFieldAsDouble(hFeat, 0); - padfYResolutions[i] = OGR_F_GetFieldAsDouble(hFeat, 1); - - OGR_F_Destroy(hFeat); - - i++; - } - } - - GDALDatasetReleaseResultSet(hDS, hSQLLyr); - hSQLLyr = nullptr; - - /* -------------------------------------------------------------------- */ - /* Add overview levels as internal datasets */ - /* -------------------------------------------------------------------- */ - if (nResolutions > 1) - { - CPLString osRasterTableName = osTableName; - osRasterTableName += "_rasters"; - - OGRLayerH hRasterLyr = - GDALDatasetGetLayerByName(hDS, osRasterTableName.c_str()); - - papoOverviews = reinterpret_cast( - CPLCalloc(nResolutions - 1, sizeof(RasterliteDataset *))); - for (int nLev = 1; nLev < nResolutions; nLev++) - { - int nOvrBands; - GDALDataType eOvrDataType; - int nBlockXSize, nBlockYSize; - if (GetBlockParams(hRasterLyr, nLev, &nOvrBands, &eOvrDataType, - &nBlockXSize, &nBlockYSize)) - { - if (eOvrDataType == GDT_Byte && nOvrBands == 1 && nBands == 3) - nOvrBands = 3; - - papoOverviews[nLev - 1] = new RasterliteDataset(this, nLev); - - for (int iBand = 0; iBand < nBands; iBand++) - { - papoOverviews[nLev - 1]->SetBand( - iBand + 1, new RasterliteBand( - papoOverviews[nLev - 1], iBand + 1, - eOvrDataType, nBlockXSize, nBlockYSize)); - } - } - else - { - CPLError(CE_Failure, CPLE_AppDefined, - "Cannot find block characteristics for overview %d", - nLev); - papoOverviews[nLev - 1] = nullptr; - } - } - } - - return CE_None; -} - -/************************************************************************/ -/* CleanOverviews() */ -/************************************************************************/ - -CPLErr RasterliteDataset::CleanOverviews() -{ - if (nLevel != 0) - return CE_Failure; - - CPLString osSQL("BEGIN"); - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - - const CPLString osResolutionCond = - "NOT " + - RasterliteGetPixelSizeCond(padfXResolutions[0], padfYResolutions[0]); - - osSQL.Printf("DELETE FROM \"%s_rasters\" WHERE id " - "IN(SELECT id FROM \"%s_metadata\" WHERE %s)", - osTableName.c_str(), osTableName.c_str(), - osResolutionCond.c_str()); - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - - osSQL.Printf("DELETE FROM \"%s_metadata\" WHERE %s", osTableName.c_str(), - osResolutionCond.c_str()); - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - - OGRLayerH hRasterPyramidsLyr = - GDALDatasetGetLayerByName(hDS, "raster_pyramids"); - if (hRasterPyramidsLyr) - { - osSQL.Printf( - "DELETE FROM raster_pyramids WHERE table_prefix = '%s' AND %s", - osTableName.c_str(), osResolutionCond.c_str()); - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - } - - osSQL = "COMMIT"; - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - - for (int i = 1; i < nResolutions; i++) - delete papoOverviews[i - 1]; - CPLFree(papoOverviews); - papoOverviews = nullptr; - nResolutions = 1; - - return CE_None; -} - -/************************************************************************/ -/* CleanOverviewLevel() */ -/************************************************************************/ - -CPLErr RasterliteDataset::CleanOverviewLevel(int nOvrFactor) -{ - if (nLevel != 0) - return CE_Failure; - - /* -------------------------------------------------------------------- */ - /* Find the index of the overview matching the overview factor */ - /* -------------------------------------------------------------------- */ - int iLev = 1; - for (; iLev < nResolutions; iLev++) - { - if (fabs(padfXResolutions[0] * nOvrFactor - padfXResolutions[iLev]) < - 1e-15 && - fabs(padfYResolutions[0] * nOvrFactor - padfYResolutions[iLev]) < - 1e-15) - break; - } - - if (iLev == nResolutions) - return CE_None; - - /* -------------------------------------------------------------------- */ - /* Now clean existing overviews at that resolution */ - /* -------------------------------------------------------------------- */ - - CPLString osSQL("BEGIN"); - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - - CPLString osResolutionCond = RasterliteGetPixelSizeCond( - padfXResolutions[iLev], padfYResolutions[iLev]); - - osSQL.Printf("DELETE FROM \"%s_rasters\" WHERE id " - "IN(SELECT id FROM \"%s_metadata\" WHERE %s)", - osTableName.c_str(), osTableName.c_str(), - osResolutionCond.c_str()); - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - - osSQL.Printf("DELETE FROM \"%s_metadata\" WHERE %s", osTableName.c_str(), - osResolutionCond.c_str()); - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - - OGRLayerH hRasterPyramidsLyr = - GDALDatasetGetLayerByName(hDS, "raster_pyramids"); - if (hRasterPyramidsLyr) - { - osSQL.Printf( - "DELETE FROM raster_pyramids WHERE table_prefix = '%s' AND %s", - osTableName.c_str(), osResolutionCond.c_str()); - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - } - - osSQL = "COMMIT"; - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - - return CE_None; -} - -/************************************************************************/ -/* CleanOverviewLevel() */ -/************************************************************************/ - -CPLErr RasterliteDataset::CreateOverviewLevel(const char *pszResampling, - int nOvrFactor, - CSLConstList papszOptions, - GDALProgressFunc pfnProgress, - void *pProgressData) -{ - const int nOvrXSize = nRasterXSize / nOvrFactor; - const int nOvrYSize = nRasterYSize / nOvrFactor; - - if (nOvrXSize == 0 || nOvrYSize == 0) - return CE_Failure; - - const bool bTiled = - CPLTestBool(CSLFetchNameValueDef(papszOptions, "TILED", "YES")); - int nBlockXSize, nBlockYSize; - if (bTiled) - { - nBlockXSize = - atoi(CSLFetchNameValueDef(papszOptions, "BLOCKXSIZE", "256")); - nBlockYSize = - atoi(CSLFetchNameValueDef(papszOptions, "BLOCKYSIZE", "256")); - if (nBlockXSize < 64) - nBlockXSize = 64; - else if (nBlockXSize > 4096) - nBlockXSize = 4096; - if (nBlockYSize < 64) - nBlockYSize = 64; - else if (nBlockYSize > 4096) - nBlockYSize = 4096; - } - else - { - nBlockXSize = nOvrXSize; - nBlockYSize = nOvrYSize; - } - - const char *pszDriverName = - CSLFetchNameValueDef(papszOptions, "DRIVER", "GTiff"); - if (EQUAL(pszDriverName, "MEM") || EQUAL(pszDriverName, "VRT")) - { - CPLError(CE_Failure, CPLE_AppDefined, - "GDAL %s driver cannot be used as underlying driver", - pszDriverName); - return CE_Failure; - } - GDALDriverH hTileDriver = GDALGetDriverByName(pszDriverName); - if (hTileDriver == nullptr) - { - CPLError(CE_Failure, CPLE_AppDefined, "Cannot load GDAL %s driver", - pszDriverName); - return CE_Failure; - } - - GDALDriverH hMemDriver = GDALGetDriverByName("MEM"); - if (hMemDriver == nullptr) - { - CPLError(CE_Failure, CPLE_AppDefined, "Cannot load GDAL MEM driver"); - return CE_Failure; - } - - const GDALDataType eDataType = GetRasterBand(1)->GetRasterDataType(); - int nDataTypeSize = GDALGetDataTypeSize(eDataType) / 8; - GByte *pabyMEMDSBuffer = reinterpret_cast(VSIMalloc3( - nBlockXSize, nBlockYSize, cpl::fits_on(nBands * nDataTypeSize))); - if (pabyMEMDSBuffer == nullptr) - { - return CE_Failure; - } - - const CPLString osTempFileName( - VSIMemGenerateHiddenFilename("rasterlite_tile")); - - int nTileId = 0; - int nBlocks = 0; - - const int nXBlocks = (nOvrXSize + nBlockXSize - 1) / nBlockXSize; - const int nYBlocks = (nOvrYSize + nBlockYSize - 1) / nBlockYSize; - int nTotalBlocks = nXBlocks * nYBlocks; - - CPLString osRasterLayer; - osRasterLayer.Printf("%s_rasters", osTableName.c_str()); - - CPLString osMetatadataLayer; - osMetatadataLayer.Printf("%s_metadata", osTableName.c_str()); - - OGRLayerH hRasterLayer = - GDALDatasetGetLayerByName(hDS, osRasterLayer.c_str()); - OGRLayerH hMetadataLayer = - GDALDatasetGetLayerByName(hDS, osMetatadataLayer.c_str()); - - CPLString osSourceName = "unknown"; - - const double dfXResolution = padfXResolutions[0] * nOvrFactor; - const double dfYResolution = padfXResolutions[0] * nOvrFactor; - - CPLString osSQL; - osSQL.Printf( - "SELECT source_name FROM \"%s\" WHERE " - "%s LIMIT 1", - osMetatadataLayer.c_str(), - RasterliteGetPixelSizeCond(padfXResolutions[0], padfYResolutions[0]) - .c_str()); - OGRLayerH hSQLLyr = - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - if (hSQLLyr) - { - OGRFeatureH hFeat = OGR_L_GetNextFeature(hSQLLyr); - if (hFeat) - { - const char *pszVal = OGR_F_GetFieldAsString(hFeat, 0); - if (pszVal) - osSourceName = pszVal; - OGR_F_Destroy(hFeat); - } - GDALDatasetReleaseResultSet(hDS, hSQLLyr); - } - - /* -------------------------------------------------------------------- */ - /* Compute up to which existing overview level we can use for */ - /* computing the requested overview */ - /* -------------------------------------------------------------------- */ - nLimitOvrCount = 0; - int iLev = 1; - for (; iLev < nResolutions; iLev++) - { - if (!(padfXResolutions[iLev] < dfXResolution - 1e-10 && - padfYResolutions[iLev] < dfYResolution - 1e-10)) - { - break; - } - nLimitOvrCount++; - } - /* -------------------------------------------------------------------- */ - /* Allocate buffer for tile of previous overview level */ - /* -------------------------------------------------------------------- */ - - GDALDataset *poPrevOvrLevel = - (papoOverviews != nullptr && iLev >= 2 && iLev <= nResolutions && - papoOverviews[iLev - 2]) - ? papoOverviews[iLev - 2] - : this; - const double dfRatioPrevOvr = - static_cast(poPrevOvrLevel->GetRasterBand(1)->GetXSize()) / - nOvrXSize; - const int nPrevOvrBlockXSize = - static_cast(nBlockXSize * dfRatioPrevOvr + 0.5); - const int nPrevOvrBlockYSize = - static_cast(nBlockYSize * dfRatioPrevOvr + 0.5); - GByte *pabyPrevOvrMEMDSBuffer = nullptr; - - if (!STARTS_WITH_CI(pszResampling, "NEAR")) - { - pabyPrevOvrMEMDSBuffer = reinterpret_cast( - VSIMalloc3(nPrevOvrBlockXSize, nPrevOvrBlockYSize, - cpl::fits_on(nBands * nDataTypeSize))); - if (pabyPrevOvrMEMDSBuffer == nullptr) - { - VSIFree(pabyMEMDSBuffer); - return CE_Failure; - } - } - - /* -------------------------------------------------------------------- */ - /* Iterate over blocks to add data into raster and metadata tables */ - /* -------------------------------------------------------------------- */ - - char **papszTileDriverOptions = - RasterliteGetTileDriverOptions(papszOptions); - - GDALDatasetExecuteSQL(hDS, "BEGIN", nullptr, nullptr); - - CPLErr eErr = CE_None; - for (int nBlockYOff = 0; eErr == CE_None && nBlockYOff < nYBlocks; - nBlockYOff++) - { - for (int nBlockXOff = 0; eErr == CE_None && nBlockXOff < nXBlocks; - nBlockXOff++) - { - std::unique_ptr poPrevOvrMemDS; - - /* -------------------------------------------------------------------- - */ - /* Create in-memory tile */ - /* -------------------------------------------------------------------- - */ - int nReqXSize = nBlockXSize; - int nReqYSize = nBlockYSize; - if ((nBlockXOff + 1) * nBlockXSize > nOvrXSize) - nReqXSize = nOvrXSize - nBlockXOff * nBlockXSize; - if ((nBlockYOff + 1) * nBlockYSize > nOvrYSize) - nReqYSize = nOvrYSize - nBlockYOff * nBlockYSize; - - if (pabyPrevOvrMEMDSBuffer != nullptr) - { - int nPrevOvrReqXSize = - static_cast(nReqXSize * dfRatioPrevOvr + 0.5); - int nPrevOvrReqYSize = - static_cast(nReqYSize * dfRatioPrevOvr + 0.5); - - eErr = RasterIO(GF_Read, nBlockXOff * nBlockXSize * nOvrFactor, - nBlockYOff * nBlockYSize * nOvrFactor, - nReqXSize * nOvrFactor, nReqYSize * nOvrFactor, - pabyPrevOvrMEMDSBuffer, nPrevOvrReqXSize, - nPrevOvrReqYSize, eDataType, nBands, nullptr, 0, - 0, 0, nullptr); - - if (eErr != CE_None) - { - break; - } - - poPrevOvrMemDS.reset(MEMDataset::Create("", nPrevOvrReqXSize, - nPrevOvrReqYSize, 0, - eDataType, nullptr)); - - for (int iBand = 0; iBand < nBands; iBand++) - { - auto hBand = MEMCreateRasterBandEx( - poPrevOvrMemDS.get(), iBand + 1, - pabyPrevOvrMEMDSBuffer + iBand * nDataTypeSize * - nPrevOvrReqXSize * - nPrevOvrReqYSize, - eDataType, 0, 0, false); - poPrevOvrMemDS->AddMEMBand(hBand); - } - } - else - { - eErr = RasterIO(GF_Read, nBlockXOff * nBlockXSize * nOvrFactor, - nBlockYOff * nBlockYSize * nOvrFactor, - nReqXSize * nOvrFactor, nReqYSize * nOvrFactor, - pabyMEMDSBuffer, nReqXSize, nReqYSize, - eDataType, nBands, nullptr, 0, 0, 0, nullptr); - if (eErr != CE_None) - { - break; - } - } - - auto poMemDS = std::unique_ptr(MEMDataset::Create( - "", nReqXSize, nReqYSize, 0, eDataType, nullptr)); - for (int iBand = 0; iBand < nBands; iBand++) - { - auto hBand = MEMCreateRasterBandEx( - poMemDS.get(), iBand + 1, - pabyMEMDSBuffer + - iBand * nDataTypeSize * nReqXSize * nReqYSize, - eDataType, 0, 0, false); - poMemDS->AddMEMBand(hBand); - } - - auto hMemDS = GDALDataset::ToHandle(poMemDS.get()); - if (poPrevOvrMemDS != nullptr) - { - for (int iBand = 0; iBand < nBands; iBand++) - { - GDALRasterBandH hDstOvrBand = - GDALGetRasterBand(hMemDS, iBand + 1); - - auto hPrevOvrMEMDS = - GDALDataset::ToHandle(poPrevOvrMemDS.get()); - eErr = GDALRegenerateOverviews( - GDALGetRasterBand(hPrevOvrMEMDS, iBand + 1), 1, - &hDstOvrBand, pszResampling, nullptr, nullptr); - if (eErr != CE_None) - break; - } - - poPrevOvrMemDS.reset(); - } - - GDALDatasetH hOutDS = - GDALCreateCopy(hTileDriver, osTempFileName.c_str(), hMemDS, - FALSE, papszTileDriverOptions, nullptr, nullptr); - - poMemDS.reset(); - if (!hOutDS) - { - eErr = CE_Failure; - break; - } - - GDALClose(hOutDS); - - /* -------------------------------------------------------------------- - */ - /* Insert new entry into raster table */ - /* -------------------------------------------------------------------- - */ - - vsi_l_offset nDataLength; - GByte *pabyData = VSIGetMemFileBuffer(osTempFileName.c_str(), - &nDataLength, FALSE); - - OGRFeatureH hFeat = OGR_F_Create(OGR_L_GetLayerDefn(hRasterLayer)); - OGR_F_SetFieldBinary(hFeat, 0, static_cast(nDataLength), - pabyData); - - if (OGR_L_CreateFeature(hRasterLayer, hFeat) != OGRERR_NONE) - eErr = CE_Failure; - /* Query raster ID to set it as the ID of the associated metadata */ - const int nRasterID = static_cast(OGR_F_GetFID(hFeat)); - - OGR_F_Destroy(hFeat); - - VSIUnlink(osTempFileName.c_str()); - if (eErr == CE_Failure) - break; - - /* -------------------------------------------------------------------- - */ - /* Insert new entry into metadata table */ - /* -------------------------------------------------------------------- - */ - - hFeat = OGR_F_Create(OGR_L_GetLayerDefn(hMetadataLayer)); - OGR_F_SetFID(hFeat, nRasterID); - OGR_F_SetFieldString(hFeat, 0, osSourceName); - OGR_F_SetFieldInteger(hFeat, 1, nTileId++); - OGR_F_SetFieldInteger(hFeat, 2, nReqXSize); - OGR_F_SetFieldInteger(hFeat, 3, nReqYSize); - OGR_F_SetFieldDouble(hFeat, 4, dfXResolution); - OGR_F_SetFieldDouble(hFeat, 5, dfYResolution); - - const double minx = - adfGeoTransform[0] + (nBlockXSize * nBlockXOff) * dfXResolution; - const double maxx = - adfGeoTransform[0] + - (nBlockXSize * nBlockXOff + nReqXSize) * dfXResolution; - const double maxy = adfGeoTransform[3] + - (nBlockYSize * nBlockYOff) * (-dfYResolution); - const double miny = - adfGeoTransform[3] + - (nBlockYSize * nBlockYOff + nReqYSize) * (-dfYResolution); - - OGRGeometryH hRectangle = OGR_G_CreateGeometry(wkbPolygon); - OGRGeometryH hLinearRing = OGR_G_CreateGeometry(wkbLinearRing); - OGR_G_AddPoint_2D(hLinearRing, minx, miny); - OGR_G_AddPoint_2D(hLinearRing, minx, maxy); - OGR_G_AddPoint_2D(hLinearRing, maxx, maxy); - OGR_G_AddPoint_2D(hLinearRing, maxx, miny); - OGR_G_AddPoint_2D(hLinearRing, minx, miny); - OGR_G_AddGeometryDirectly(hRectangle, hLinearRing); - - OGR_F_SetGeometryDirectly(hFeat, hRectangle); - - if (OGR_L_CreateFeature(hMetadataLayer, hFeat) != OGRERR_NONE) - eErr = CE_Failure; - OGR_F_Destroy(hFeat); - - nBlocks++; - if (pfnProgress && !pfnProgress(1.0 * nBlocks / nTotalBlocks, - nullptr, pProgressData)) - eErr = CE_Failure; - } - } - - nLimitOvrCount = -1; - - VSIUnlink(osTempFileName); - VSIUnlink((osTempFileName + ".aux.xml").c_str()); - - if (eErr == CE_None) - GDALDatasetExecuteSQL(hDS, "COMMIT", nullptr, nullptr); - else - GDALDatasetExecuteSQL(hDS, "ROLLBACK", nullptr, nullptr); - - VSIFree(pabyMEMDSBuffer); - VSIFree(pabyPrevOvrMEMDSBuffer); - - CSLDestroy(papszTileDriverOptions); - papszTileDriverOptions = nullptr; - - /* -------------------------------------------------------------------- */ - /* Update raster_pyramids table */ - /* -------------------------------------------------------------------- */ - if (eErr != CE_None) - return eErr; - - OGRLayerH hRasterPyramidsLyr = - GDALDatasetGetLayerByName(hDS, "raster_pyramids"); - if (hRasterPyramidsLyr == nullptr) - { - osSQL.Printf("CREATE TABLE raster_pyramids (" - "table_prefix TEXT NOT NULL," - "pixel_x_size DOUBLE NOT NULL," - "pixel_y_size DOUBLE NOT NULL," - "tile_count INTEGER NOT NULL)"); - GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - - /* Re-open the DB to take into account the new tables*/ - GDALClose(hDS); - - hDS = RasterliteOpenSQLiteDB(osFileName.c_str(), GA_Update); - - hRasterPyramidsLyr = GDALDatasetGetLayerByName(hDS, "raster_pyramids"); - if (hRasterPyramidsLyr == nullptr) - return CE_Failure; - } - OGRFeatureDefnH hFDefn = OGR_L_GetLayerDefn(hRasterPyramidsLyr); - - /* Insert base resolution into raster_pyramids if not already done */ - bool bHasBaseResolution = false; - osSQL.Printf( - "SELECT * FROM raster_pyramids WHERE " - "table_prefix = '%s' AND %s", - osTableName.c_str(), - RasterliteGetPixelSizeCond(padfXResolutions[0], padfYResolutions[0]) - .c_str()); - hSQLLyr = GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - if (hSQLLyr) - { - OGRFeatureH hFeat = OGR_L_GetNextFeature(hSQLLyr); - if (hFeat) - { - bHasBaseResolution = true; - OGR_F_Destroy(hFeat); - } - GDALDatasetReleaseResultSet(hDS, hSQLLyr); - } - - if (!bHasBaseResolution) - { - osSQL.Printf( - "SELECT COUNT(*) FROM \"%s\" WHERE %s", osMetatadataLayer.c_str(), - RasterliteGetPixelSizeCond(padfXResolutions[0], padfYResolutions[0]) - .c_str()); - - int nBlocksMainRes = 0; - - hSQLLyr = GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr); - if (hSQLLyr) - { - OGRFeatureH hFeat = OGR_L_GetNextFeature(hSQLLyr); - if (hFeat) - { - nBlocksMainRes = OGR_F_GetFieldAsInteger(hFeat, 0); - OGR_F_Destroy(hFeat); - } - GDALDatasetReleaseResultSet(hDS, hSQLLyr); - } - - OGRFeatureH hFeat = OGR_F_Create(hFDefn); - OGR_F_SetFieldString(hFeat, - OGR_FD_GetFieldIndex(hFDefn, "table_prefix"), - osTableName.c_str()); - OGR_F_SetFieldDouble(hFeat, - OGR_FD_GetFieldIndex(hFDefn, "pixel_x_size"), - padfXResolutions[0]); - OGR_F_SetFieldDouble(hFeat, - OGR_FD_GetFieldIndex(hFDefn, "pixel_y_size"), - padfYResolutions[0]); - OGR_F_SetFieldInteger(hFeat, OGR_FD_GetFieldIndex(hFDefn, "tile_count"), - nBlocksMainRes); - if (OGR_L_CreateFeature(hRasterPyramidsLyr, hFeat) != OGRERR_NONE) - eErr = CE_Failure; - OGR_F_Destroy(hFeat); - } - - OGRFeatureH hFeat = OGR_F_Create(hFDefn); - OGR_F_SetFieldString(hFeat, OGR_FD_GetFieldIndex(hFDefn, "table_prefix"), - osTableName.c_str()); - OGR_F_SetFieldDouble(hFeat, OGR_FD_GetFieldIndex(hFDefn, "pixel_x_size"), - dfXResolution); - OGR_F_SetFieldDouble(hFeat, OGR_FD_GetFieldIndex(hFDefn, "pixel_y_size"), - dfYResolution); - OGR_F_SetFieldInteger(hFeat, OGR_FD_GetFieldIndex(hFDefn, "tile_count"), - nTotalBlocks); - if (OGR_L_CreateFeature(hRasterPyramidsLyr, hFeat) != OGRERR_NONE) - eErr = CE_Failure; - OGR_F_Destroy(hFeat); - - return eErr; -} - -/************************************************************************/ -/* IBuildOverviews() */ -/************************************************************************/ - -CPLErr RasterliteDataset::IBuildOverviews( - const char *pszResampling, int nOverviews, const int *panOverviewList, - int nBandsIn, const int *panBandList, GDALProgressFunc pfnProgress, - void *pProgressData, CSLConstList papszOptions) -{ - if (nLevel != 0) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Overviews can only be computed on the base dataset"); - return CE_Failure; - } - - if (osTableName.empty()) - return CE_Failure; - - /* -------------------------------------------------------------------- */ - /* If we don't have read access, then create the overviews */ - /* externally. */ - /* -------------------------------------------------------------------- */ - if (GetAccess() != GA_Update) - { - CPLDebug("Rasterlite", "File open for read-only accessing, " - "creating overviews externally."); - - if (nResolutions != 1) - { - CPLError(CE_Failure, CPLE_NotSupported, - "Cannot add external overviews to a " - "dataset with internal overviews"); - return CE_Failure; - } - - bCheckForExistingOverview = FALSE; - CPLErr eErr = GDALDataset::IBuildOverviews( - pszResampling, nOverviews, panOverviewList, nBandsIn, panBandList, - pfnProgress, pProgressData, papszOptions); - bCheckForExistingOverview = TRUE; - return eErr; - } - - /* -------------------------------------------------------------------- */ - /* If zero overviews were requested, we need to clear all */ - /* existing overviews. */ - /* -------------------------------------------------------------------- */ - if (nOverviews == 0) - { - return CleanOverviews(); - } - - if (nBandsIn != GetRasterCount()) - { - CPLError(CE_Failure, CPLE_NotSupported, - "Generation of overviews in RASTERLITE only" - " supported when operating on all bands.\n" - "Operation failed.\n"); - return CE_Failure; - } - - const char *pszOvrOptions = - CPLGetConfigOption("RASTERLITE_OVR_OPTIONS", nullptr); - const CPLStringList aosCreationOptions( - pszOvrOptions ? CSLTokenizeString2(pszOvrOptions, ",", 0) : nullptr); - GDALValidateCreationOptions(GetDriver(), aosCreationOptions.List()); - - CPLErr eErr = CE_None; - for (int i = 0; i < nOverviews && eErr == CE_None; i++) - { - if (panOverviewList[i] <= 1) - continue; - - eErr = CleanOverviewLevel(panOverviewList[i]); - if (eErr == CE_None) - eErr = CreateOverviewLevel(pszResampling, panOverviewList[i], - aosCreationOptions.List(), pfnProgress, - pProgressData); - - ReloadOverviews(); - } - - return eErr; -} diff --git a/gcore/gdal_frmts.h b/gcore/gdal_frmts.h index a2df6ad6da9e..b01ea286e9cf 100644 --- a/gcore/gdal_frmts.h +++ b/gcore/gdal_frmts.h @@ -153,8 +153,6 @@ void CPL_DLL GDALRegister_GEOR(void); void DeclareDeferredGEORPlugin(void); void CPL_DLL GDALRegister_TIL(void); void CPL_DLL GDALRegister_R(void); -void CPL_DLL GDALRegister_Rasterlite(void); -void DeclareDeferredRasterlitePlugin(void); void CPL_DLL GDALRegister_PostGISRaster(void); void DeclareDeferredPostGISRasterPlugin(void); void CPL_DLL GDALRegister_NWT_GRD(void);