From a9b8346e5e8f4ae010bc7d57a97519642ec11884 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Fri, 17 Jan 2025 18:31:01 +0100 Subject: [PATCH] Remove OZI OZF2/OZFX3 raster driver --- .../expected_gdalinfo_formats.txt | 1 - ...indows_conda_expected_gdalinfo_formats.txt | 1 - autotest/gdrivers/ozi.py | 82 --- doc/source/drivers/raster/index.rst | 1 - doc/source/drivers/raster/ozi.rst | 27 - frmts/CMakeLists.txt | 1 - frmts/drivers.ini | 1 - frmts/gdalallregister.cpp | 4 - frmts/ozi/CMakeLists.txt | 12 - frmts/ozi/ozidataset.cpp | 671 ------------------ gcore/gdal_frmts.h | 1 - 11 files changed, 802 deletions(-) delete mode 100755 autotest/gdrivers/ozi.py delete mode 100644 doc/source/drivers/raster/ozi.rst delete mode 100644 frmts/ozi/CMakeLists.txt delete mode 100644 frmts/ozi/ozidataset.cpp diff --git a/.github/workflows/ubuntu_24.04/expected_gdalinfo_formats.txt b/.github/workflows/ubuntu_24.04/expected_gdalinfo_formats.txt index db8d5841a8e3..54759dcf3534 100644 --- a/.github/workflows/ubuntu_24.04/expected_gdalinfo_formats.txt +++ b/.github/workflows/ubuntu_24.04/expected_gdalinfo_formats.txt @@ -127,7 +127,6 @@ Supported Formats: (ro:read-only, rw:read-write, +:update, v:virtual-I/O s:subda SAGA -raster- (rw+v): SAGA GIS Binary Grid (.sdat, .sg-grd-z) (*.sdat, *.sg-grd-z) XYZ -raster- (rwv): ASCII Gridded XYZ (*.xyz) HF2 -raster- (rwv): HF2/HFZ heightfield raster (*.hf2) - OZI -raster- (rov): OziExplorer Image File CTG -raster- (rov): USGS LULC Composite Theme Grid ZMap -raster- (rwv): ZMap Plus Grid (*.dat) NGSGEOID -raster- (rov): NOAA NGS Geoid Height Grids (*.bin) diff --git a/.github/workflows/windows_conda_expected_gdalinfo_formats.txt b/.github/workflows/windows_conda_expected_gdalinfo_formats.txt index 5b0cb5089e3d..2077516a871d 100644 --- a/.github/workflows/windows_conda_expected_gdalinfo_formats.txt +++ b/.github/workflows/windows_conda_expected_gdalinfo_formats.txt @@ -128,7 +128,6 @@ Supported Formats: (ro:read-only, rw:read-write, +:update, v:virtual-I/O s:subda SAGA -raster- (rw+v): SAGA GIS Binary Grid (.sdat, .sg-grd-z) (*.sdat, *.sg-grd-z) XYZ -raster- (rwv): ASCII Gridded XYZ (*.xyz) HF2 -raster- (rwv): HF2/HFZ heightfield raster (*.hf2) - OZI -raster- (rov): OziExplorer Image File CTG -raster- (rov): USGS LULC Composite Theme Grid ZMap -raster- (rwv): ZMap Plus Grid (*.dat) NGSGEOID -raster- (rov): NOAA NGS Geoid Height Grids (*.bin) diff --git a/autotest/gdrivers/ozi.py b/autotest/gdrivers/ozi.py deleted file mode 100755 index fbf5034d7634..000000000000 --- a/autotest/gdrivers/ozi.py +++ /dev/null @@ -1,82 +0,0 @@ -#!/usr/bin/env pytest -############################################################################### -# -# Project: GDAL/OGR Test Suite -# Purpose: OZI Testing. -# Author: Even Rouault -# -############################################################################### -# Copyright (c) 2011, Even Rouault -# -# SPDX-License-Identifier: MIT -############################################################################### - -import os - -import gdaltest -import pytest - -from osgeo import gdal - -pytestmark = pytest.mark.require_driver("OZI") - -############################################################################### -# Test reading OZF2 file - - -def test_ozi_online_1(): - - gdaltest.download_or_skip( - "http://www.oziexplorer2.com/maps/Europe2001_setup.exe", "Europe2001_setup.exe" - ) - - try: - os.stat("tmp/cache/Europe 2001_OZF.map") - except OSError: - try: - gdaltest.unzip("tmp/cache", "tmp/cache/Europe2001_setup.exe") - try: - os.stat("tmp/cache/Europe 2001_OZF.map") - except OSError: - pytest.skip() - except Exception: - pytest.skip() - - ds = gdal.Open("tmp/cache/Europe 2001_OZF.map") - assert ds is not None - - if False: # pylint: disable=using-constant-test - gt = ds.GetGeoTransform() - wkt = ds.GetProjectionRef() - - expected_gt = ( - -1841870.2731215316, - 3310.9550245520159, - -13.025246304875619, - 8375316.4662204208, - -16.912440131236657, - -3264.1162527118681, - ) - for i in range(6): - assert gt[i] == pytest.approx(expected_gt[i], abs=1e-7), "bad geotransform" - - else: - gcps = ds.GetGCPs() - - assert len(gcps) == 4, "did not get expected gcp count." - - gcp0 = gcps[0] - assert ( - gcp0.GCPPixel == 61 - and gcp0.GCPLine == 436 - and gcp0.GCPX == pytest.approx(-1653990.4525324, abs=0.001) - and gcp0.GCPY == pytest.approx(6950885.0402214, abs=0.001) - ), "did not get expected gcp." - - wkt = ds.GetGCPProjection() - - expected_wkt = 'PROJCS["unnamed",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.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]],PROJECTION["Lambert_Conformal_Conic_2SP"],PARAMETER["latitude_of_origin",4],PARAMETER["central_meridian",10],PARAMETER["standard_parallel_1",40],PARAMETER["standard_parallel_2",56],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["Meter",1],AXIS["Easting",EAST],AXIS["Northing",NORTH]]' - assert wkt == expected_wkt, wkt - - cs = ds.GetRasterBand(1).Checksum() - assert cs == 16025, "bad checksum" diff --git a/doc/source/drivers/raster/index.rst b/doc/source/drivers/raster/index.rst index 7231e3208a3e..f35fede51cda 100644 --- a/doc/source/drivers/raster/index.rst +++ b/doc/source/drivers/raster/index.rst @@ -131,7 +131,6 @@ Raster drivers nwtgrd ogcapi openfilegdb - ozi palsar paux pcidsk diff --git a/doc/source/drivers/raster/ozi.rst b/doc/source/drivers/raster/ozi.rst deleted file mode 100644 index 498d590b7768..000000000000 --- a/doc/source/drivers/raster/ozi.rst +++ /dev/null @@ -1,27 +0,0 @@ -.. _raster.ozi: - -================================================================================ -OZI -- OZF2/OZFX3 raster -================================================================================ - -.. shortname:: OZI - -.. built_in_by_default:: - -GDAL supports reading OZF2/OZFX3 raster datasets. - -Either the image file or the .map file can be passed to GDAL. To -retrieve georeferencing, you need to specify the .map file. - -Driver capabilities -------------------- - -.. supports_georeferencing:: - -.. supports_virtualio:: - -See also --------- - -- `Specification of OZF2/OZFX3 - format `__ diff --git a/frmts/CMakeLists.txt b/frmts/CMakeLists.txt index a484587b6d55..950eba3d1f14 100644 --- a/frmts/CMakeLists.txt +++ b/frmts/CMakeLists.txt @@ -147,7 +147,6 @@ gdal_optional_format(bsb "Maptech/NOAA BSB Nautical Chart Format") gdal_dependent_format(aigrid "Arc/Info Binary Grid Format" "OGR_ENABLE_DRIVER_AVC") gdal_optional_format(usgsdem "USGS ASCII DEM (and CDED)") gdal_optional_format(airsar "AirSAR Polarimetric Format") -gdal_optional_format(ozi "OZF2/OZFX3 raster") gdal_optional_format(pcidsk "PCI Geomatics Database File") gdal_optional_format(sigdem "Scaled Integer Gridded DEM .sigdem Driver") gdal_dependent_format(msg "Meteosat Second Generation" "GDAL_USE_PUBLICDECOMPWT") diff --git a/frmts/drivers.ini b/frmts/drivers.ini index c28e48407382..fb64b007f928 100644 --- a/frmts/drivers.ini +++ b/frmts/drivers.ini @@ -152,7 +152,6 @@ PostGISRaster SAGA XYZ HF2 -OZI CTG ZMap NGSGEOID diff --git a/frmts/gdalallregister.cpp b/frmts/gdalallregister.cpp index a8f073396e17..c569711ba288 100644 --- a/frmts/gdalallregister.cpp +++ b/frmts/gdalallregister.cpp @@ -716,10 +716,6 @@ void CPL_STDCALL GDALAllRegister() GDALRegister_HF2(); #endif -#ifdef FRMT_ozi - GDALRegister_OZI(); -#endif - #ifdef FRMT_ctg GDALRegister_CTG(); #endif diff --git a/frmts/ozi/CMakeLists.txt b/frmts/ozi/CMakeLists.txt deleted file mode 100644 index a31ed5da5a8c..000000000000 --- a/frmts/ozi/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -add_gdal_driver(TARGET gdal_OZI SOURCES ozidataset.cpp PLUGIN_CAPABLE_IF "NOT GDAL_USE_ZLIB_INTERNAL" NO_DEPS) -gdal_standard_includes(gdal_OZI) -target_compile_definitions(gdal_OZI PRIVATE -DHAVE_LIBZ -DZIP_SUPPORT) -if (GDAL_USE_ZLIB_INTERNAL) - gdal_add_vendored_lib(gdal_OZI libz) -else () - target_compile_definitions(gdal_OZI PRIVATE -DHAVE_ZLIB_H -DHAVE_ZLIB) - gdal_target_link_libraries(gdal_OZI PRIVATE ZLIB::ZLIB) - if (MSVC AND NOT ZLIB_IS_STATIC) - target_compile_definitions(gdal_OZI PRIVATE -DZLIB_DLL) - endif () -endif () diff --git a/frmts/ozi/ozidataset.cpp b/frmts/ozi/ozidataset.cpp deleted file mode 100644 index b617677965a1..000000000000 --- a/frmts/ozi/ozidataset.cpp +++ /dev/null @@ -1,671 +0,0 @@ -/****************************************************************************** - * - * Project: OZF2 and OZFx3 binary files driver - * Purpose: GDALDataset driver for OZF2 and OZFx3 binary files. - * Author: Even Rouault, - * - ****************************************************************************** - * Copyright (c) 2010-2012, Even Rouault - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "gdal_frmts.h" -#include "gdal_pam.h" -#include "zlib.h" - -/* g++ -fPIC -g -Wall frmts/ozi/ozidataset.cpp -shared -o gdal_OZI.so -Iport - * -Igcore -Iogr -L. -lgdal */ - -/************************************************************************/ -/* ==================================================================== */ -/* OZIDataset */ -/* ==================================================================== */ -/************************************************************************/ - -class OZIRasterBand; - -class OZIDataset final : public GDALPamDataset -{ - friend class OZIRasterBand; - - VSILFILE *fp; - int nZoomLevelCount; - int *panZoomLevelOffsets; - OZIRasterBand **papoOvrBands; - vsi_l_offset nFileSize; - - int bOzi3; - GByte nKeyInit; - - public: - OZIDataset(); - virtual ~OZIDataset(); - - static GDALDataset *Open(GDALOpenInfo *); - static int Identify(GDALOpenInfo *); -}; - -/************************************************************************/ -/* ==================================================================== */ -/* OZIRasterBand */ -/* ==================================================================== */ -/************************************************************************/ - -class OZIRasterBand final : public GDALPamRasterBand -{ - friend class OZIDataset; - - int nXBlocks; - int nZoomLevel; - std::unique_ptr poColorTable{}; - GByte *pabyTranslationTable; - - public: - OZIRasterBand(OZIDataset *, int nZoomLevel, int nRasterXSize, - int nRasterYSize, int nXBlocks, - std::unique_ptr &&poColorTableIn); - virtual ~OZIRasterBand(); - - virtual CPLErr IReadBlock(int, int, void *) override; - virtual GDALColorInterp GetColorInterpretation() override; - virtual GDALColorTable *GetColorTable() override; - - virtual int GetOverviewCount() override; - virtual GDALRasterBand *GetOverview(int nLevel) override; -}; - -/************************************************************************/ -/* I/O functions */ -/************************************************************************/ - -constexpr GByte abyKey[] = {0x2D, 0x4A, 0x43, 0xF1, 0x27, 0x9B, 0x69, - 0x4F, 0x36, 0x52, 0x87, 0xEC, 0x5F, 0x42, - 0x53, 0x22, 0x9E, 0x8B, 0x2D, 0x83, 0x3D, - 0xD2, 0x84, 0xBA, 0xD8, 0x5B}; - -static void OZIDecrypt(void *pabyVal, int n, GByte nKeyInit) -{ - for (int i = 0; i < n; i++) - { - reinterpret_cast(pabyVal)[i] ^= - abyKey[i % sizeof(abyKey)] + nKeyInit; - } -} - -static int ReadInt(GByte **pptr) -{ - int nVal; - memcpy(&nVal, *pptr, 4); - *pptr += 4; - CPL_LSBPTR32(&nVal); - return nVal; -} - -static short ReadShort(GByte **pptr) -{ - short nVal; - memcpy(&nVal, *pptr, 2); - *pptr += 2; - CPL_LSBPTR16(&nVal); - return nVal; -} - -static int ReadInt(VSILFILE *fp, int bOzi3 = FALSE, int nKeyInit = 0) -{ - int nVal; - VSIFReadL(&nVal, 1, 4, fp); - if (bOzi3) - { - GByte abyVal[4]; - memcpy(&abyVal[0], &nVal, 4); - OZIDecrypt(&abyVal[0], 4, static_cast(nKeyInit)); - memcpy(&nVal, &abyVal[0], 4); - } - CPL_LSBPTR32(&nVal); - return nVal; -} - -static short ReadShort(VSILFILE *fp, int bOzi3 = FALSE, int nKeyInit = 0) -{ - short nVal; - VSIFReadL(&nVal, 1, 2, fp); - if (bOzi3) - { - GByte abyVal[2]; - memcpy(&abyVal[0], &nVal, 2); - OZIDecrypt(&abyVal[0], 2, static_cast(nKeyInit)); - memcpy(&nVal, &abyVal[0], 2); - } - CPL_LSBPTR16(&nVal); - return nVal; -} - -/************************************************************************/ -/* OZIRasterBand() */ -/************************************************************************/ - -OZIRasterBand::OZIRasterBand(OZIDataset *poDSIn, int nZoomLevelIn, - int nRasterXSizeIn, int nRasterYSizeIn, - int nXBlocksIn, - std::unique_ptr &&poColorTableIn) - : nXBlocks(nXBlocksIn), nZoomLevel(nZoomLevelIn), - poColorTable(std::move(poColorTableIn)), pabyTranslationTable(nullptr) -{ - poDS = poDSIn; - nBand = 1; - - eDataType = GDT_Byte; - - nBlockXSize = 64; - nBlockYSize = 64; - - nRasterXSize = nRasterXSizeIn; - nRasterYSize = nRasterYSizeIn; -} - -/************************************************************************/ -/* ~OZIRasterBand() */ -/************************************************************************/ - -OZIRasterBand::~OZIRasterBand() -{ - CPLFree(pabyTranslationTable); -} - -/************************************************************************/ -/* GetColorInterpretation() */ -/************************************************************************/ - -GDALColorInterp OZIRasterBand::GetColorInterpretation() -{ - return GCI_PaletteIndex; -} - -/************************************************************************/ -/* GetColorTable() */ -/************************************************************************/ - -GDALColorTable *OZIRasterBand::GetColorTable() -{ - return poColorTable.get(); -} - -/************************************************************************/ -/* IReadBlock() */ -/************************************************************************/ - -CPLErr OZIRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage) - -{ - OZIDataset *poGDS = reinterpret_cast(poDS); - - const int nBlock = nBlockYOff * nXBlocks + nBlockXOff; - - VSIFSeekL(poGDS->fp, - poGDS->panZoomLevelOffsets[nZoomLevel] + 12 + 1024 + 4 * nBlock, - SEEK_SET); - const int nPointer = ReadInt(poGDS->fp, poGDS->bOzi3, poGDS->nKeyInit); - if (nPointer < 0 || (vsi_l_offset)nPointer >= poGDS->nFileSize) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Invalid offset for block (%d, %d) : %d", nBlockXOff, - nBlockYOff, nPointer); - return CE_Failure; - } - int nNextPointer = ReadInt(poGDS->fp, poGDS->bOzi3, poGDS->nKeyInit); - if (nNextPointer <= nPointer + 16 || - (vsi_l_offset)nNextPointer >= poGDS->nFileSize || - nNextPointer - nPointer > 10 * 64 * 64) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Invalid next offset for block (%d, %d) : %d", nBlockXOff, - nBlockYOff, nNextPointer); - return CE_Failure; - } - - VSIFSeekL(poGDS->fp, nPointer, SEEK_SET); - - const int nToRead = nNextPointer - nPointer; - GByte *pabyZlibBuffer = reinterpret_cast(CPLMalloc(nToRead)); - if (VSIFReadL(pabyZlibBuffer, nToRead, 1, poGDS->fp) != 1) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Not enough byte read for block (%d, %d)", nBlockXOff, - nBlockYOff); - CPLFree(pabyZlibBuffer); - return CE_Failure; - } - - if (poGDS->bOzi3) - OZIDecrypt(pabyZlibBuffer, 16, poGDS->nKeyInit); - - if (pabyZlibBuffer[0] != 0x78 || pabyZlibBuffer[1] != 0xDA) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Bad ZLIB signature for block (%d, %d) : 0x%02X 0x%02X", - nBlockXOff, nBlockYOff, pabyZlibBuffer[0], pabyZlibBuffer[1]); - CPLFree(pabyZlibBuffer); - return CE_Failure; - } - - z_stream stream; - memset(&stream, 0, sizeof(stream)); - stream.zalloc = (alloc_func) nullptr; - stream.zfree = (free_func) nullptr; - stream.opaque = (voidpf) nullptr; - stream.next_in = pabyZlibBuffer + 2; - stream.avail_in = nToRead - 2; - - int err = inflateInit2(&(stream), -MAX_WBITS); - - for (int i = 0; i < 64 && err == Z_OK; i++) - { - stream.next_out = reinterpret_cast(pImage) + (63 - i) * 64; - stream.avail_out = 64; - err = inflate(&(stream), Z_NO_FLUSH); - if (err != Z_OK && err != Z_STREAM_END) - break; - - if (pabyTranslationTable) - { - GByte *ptr = reinterpret_cast(pImage) + (63 - i) * 64; - for (int j = 0; j < 64; j++) - { - *ptr = pabyTranslationTable[*ptr]; - ptr++; - } - } - } - - inflateEnd(&stream); - - CPLFree(pabyZlibBuffer); - - return (err == Z_OK || err == Z_STREAM_END) ? CE_None : CE_Failure; -} - -/************************************************************************/ -/* GetOverviewCount() */ -/************************************************************************/ - -int OZIRasterBand::GetOverviewCount() -{ - if (nZoomLevel != 0) - return 0; - - OZIDataset *poGDS = reinterpret_cast(poDS); - return poGDS->nZoomLevelCount - 1; -} - -/************************************************************************/ -/* GetOverview() */ -/************************************************************************/ - -GDALRasterBand *OZIRasterBand::GetOverview(int nLevel) -{ - if (nZoomLevel != 0) - return nullptr; - - OZIDataset *poGDS = reinterpret_cast(poDS); - if (nLevel < 0 || nLevel >= poGDS->nZoomLevelCount - 1) - return nullptr; - - return poGDS->papoOvrBands[nLevel + 1]; -} - -/************************************************************************/ -/* ~OZIDataset() */ -/************************************************************************/ - -OZIDataset::OZIDataset() - : fp(nullptr), nZoomLevelCount(0), panZoomLevelOffsets(nullptr), - papoOvrBands(nullptr), nFileSize(0), bOzi3(FALSE), nKeyInit(0) -{ -} - -/************************************************************************/ -/* ~OZIDataset() */ -/************************************************************************/ - -OZIDataset::~OZIDataset() -{ - if (fp) - VSIFCloseL(fp); - if (papoOvrBands != nullptr) - { - /* start at 1: do not destroy the base band ! */ - for (int i = 1; i < nZoomLevelCount; i++) - delete papoOvrBands[i]; - CPLFree(papoOvrBands); - } - CPLFree(panZoomLevelOffsets); -} - -/************************************************************************/ -/* Identify() */ -/************************************************************************/ - -int OZIDataset::Identify(GDALOpenInfo *poOpenInfo) -{ - if (poOpenInfo->nHeaderBytes < 14) - return FALSE; - - if (poOpenInfo->pabyHeader[0] == 0x80 && poOpenInfo->pabyHeader[1] == 0x77) - return TRUE; - - return poOpenInfo->pabyHeader[0] == 0x78 && - poOpenInfo->pabyHeader[1] == 0x77 && - poOpenInfo->pabyHeader[6] == 0x40 && - poOpenInfo->pabyHeader[7] == 0x00 && - poOpenInfo->pabyHeader[8] == 0x01 && - poOpenInfo->pabyHeader[9] == 0x00 && - poOpenInfo->pabyHeader[10] == 0x36 && - poOpenInfo->pabyHeader[11] == 0x04 && - poOpenInfo->pabyHeader[12] == 0x00 && - poOpenInfo->pabyHeader[13] == 0x00; -} - -/************************************************************************/ -/* Open() */ -/************************************************************************/ - -GDALDataset *OZIDataset::Open(GDALOpenInfo *poOpenInfo) - -{ - if (!Identify(poOpenInfo)) - return nullptr; - - GByte abyHeader[14]; - memcpy(abyHeader, poOpenInfo->pabyHeader, 14); - - int bOzi3 = (abyHeader[0] == 0x80 && abyHeader[1] == 0x77); - - const CPLString osImgFilename = poOpenInfo->pszFilename; - VSILFILE *fp = VSIFOpenL(osImgFilename.c_str(), "rb"); - if (fp == nullptr) - return nullptr; - - OZIDataset *poDS = new OZIDataset(); - poDS->fp = fp; - - GByte nKeyInit = 0; - if (bOzi3) - { - VSIFSeekL(fp, 14, SEEK_SET); - - GByte nRandomNumber = 0; - VSIFReadL(&nRandomNumber, 1, 1, fp); - // printf("nRandomNumber = %d\n", nRandomNumber); - if (nRandomNumber < 0x94) - { - delete poDS; - return nullptr; - } - VSIFSeekL(fp, 0x93, SEEK_CUR); - VSIFReadL(&nKeyInit, 1, 1, fp); - - VSIFSeekL(fp, 0, SEEK_SET); - VSIFReadL(abyHeader, 1, 14, fp); - OZIDecrypt(abyHeader, 14, nKeyInit); - if (!(abyHeader[6] == 0x40 && abyHeader[7] == 0x00 && - abyHeader[8] == 0x01 && abyHeader[9] == 0x00 && - abyHeader[10] == 0x36 && abyHeader[11] == 0x04 && - abyHeader[12] == 0x00 && abyHeader[13] == 0x00)) - { - delete poDS; - return nullptr; - } - - VSIFSeekL(fp, 14 + 1 + nRandomNumber, SEEK_SET); - const int nMagic = ReadInt(fp, bOzi3, nKeyInit); - CPLDebug("OZI", "OZI version code : 0x%08X", nMagic); - - poDS->bOzi3 = bOzi3; - } - else - { - VSIFSeekL(fp, 14, SEEK_SET); - } - - GByte abyHeader2[40], abyHeader2_Backup[40]; - VSIFReadL(abyHeader2, 40, 1, fp); - memcpy(abyHeader2_Backup, abyHeader2, 40); - - /* There's apparently a relationship between the nMagic number */ - /* and the nKeyInit, but I'm too lazy to add switch/cases that might */ - /* be not exhaustive, so let's try the 'brute force' attack !!! */ - /* It is much so funny to be able to run one in a few microseconds :-) */ - for (int i = 0; i < 256; i++) - { - nKeyInit = static_cast(i); - GByte *pabyHeader2 = abyHeader2; - if (bOzi3) - OZIDecrypt(abyHeader2, 40, nKeyInit); - - const int nHeaderSize = ReadInt(&pabyHeader2); /* should be 40 */ - poDS->nRasterXSize = ReadInt(&pabyHeader2); - poDS->nRasterYSize = ReadInt(&pabyHeader2); - const int nDepth = ReadShort(&pabyHeader2); /* should be 1 */ - const int nBPP = ReadShort(&pabyHeader2); /* should be 8 */ - ReadInt(&pabyHeader2); /* reserved */ - ReadInt(&pabyHeader2); /* pixel number (height * width) : unused */ - ReadInt(&pabyHeader2); /* reserved */ - ReadInt(&pabyHeader2); /* reserved */ - ReadInt(&pabyHeader2); /* ?? 0x100 */ - ReadInt(&pabyHeader2); /* ?? 0x100 */ - - if (nHeaderSize != 40 || nDepth != 1 || nBPP != 8) - { - if (bOzi3) - { - if (nKeyInit != 255) - { - memcpy(abyHeader2, abyHeader2_Backup, 40); - continue; - } - else - { - CPLDebug("OZI", "Cannot decipher 2nd header. Sorry..."); - delete poDS; - return nullptr; - } - } - else - { - CPLDebug("OZI", "nHeaderSize = %d, nDepth = %d, nBPP = %d", - nHeaderSize, nDepth, nBPP); - delete poDS; - return nullptr; - } - } - else - break; - } - poDS->nKeyInit = nKeyInit; - - int nSeparator = ReadInt(fp); - if (!bOzi3 && nSeparator != 0x77777777) - { - CPLDebug("OZI", "didn't get end of header2 marker"); - delete poDS; - return nullptr; - } - - poDS->nZoomLevelCount = ReadShort(fp); - -#ifdef DEBUG_VERBOSE - CPLDebug("OZI", "nZoomLevelCount = %d", poDS->nZoomLevelCount); -#endif - - if (poDS->nZoomLevelCount < 0 || poDS->nZoomLevelCount >= 256) - { - CPLDebug("OZI", "nZoomLevelCount = %d", poDS->nZoomLevelCount); - delete poDS; - return nullptr; - } - - /* Skip array of zoom level percentage. We don't need it for GDAL */ - VSIFSeekL(fp, sizeof(float) * poDS->nZoomLevelCount, SEEK_CUR); - - nSeparator = ReadInt(fp); - if (!bOzi3 && nSeparator != 0x77777777) - { - /* Some files have 8 extra bytes before the marker. I'm not sure */ - /* what they are used for. So just skip them and hope that */ - /* we'll find the marker */ - CPL_IGNORE_RET_VAL(ReadInt(fp)); - nSeparator = ReadInt(fp); - if (nSeparator != 0x77777777) - { - CPLDebug("OZI", "didn't get end of zoom levels marker"); - delete poDS; - return nullptr; - } - } - - VSIFSeekL(fp, 0, SEEK_END); - const vsi_l_offset nFileSize = VSIFTellL(fp); - poDS->nFileSize = nFileSize; - VSIFSeekL(fp, nFileSize - 4, SEEK_SET); - const int nZoomLevelTableOffset = ReadInt(fp, bOzi3, nKeyInit); - if (nZoomLevelTableOffset < 0 || - (vsi_l_offset)nZoomLevelTableOffset >= nFileSize) - { - CPLDebug("OZI", "nZoomLevelTableOffset = %d", nZoomLevelTableOffset); - delete poDS; - return nullptr; - } - - VSIFSeekL(fp, nZoomLevelTableOffset, SEEK_SET); - - poDS->panZoomLevelOffsets = - reinterpret_cast(CPLMalloc(sizeof(int) * poDS->nZoomLevelCount)); - - for (int i = 0; i < poDS->nZoomLevelCount; i++) - { - poDS->panZoomLevelOffsets[i] = ReadInt(fp, bOzi3, nKeyInit); - if (poDS->panZoomLevelOffsets[i] < 0 || - (vsi_l_offset)poDS->panZoomLevelOffsets[i] >= nFileSize) - { - CPLDebug("OZI", "panZoomLevelOffsets[%d] = %d", i, - poDS->panZoomLevelOffsets[i]); - delete poDS; - return nullptr; - } - } - - poDS->papoOvrBands = reinterpret_cast( - CPLCalloc(sizeof(OZIRasterBand *), poDS->nZoomLevelCount)); - - for (int i = 0; i < poDS->nZoomLevelCount; i++) - { - VSIFSeekL(fp, poDS->panZoomLevelOffsets[i], SEEK_SET); - const int nW = ReadInt(fp, bOzi3, nKeyInit); - const int nH = ReadInt(fp, bOzi3, nKeyInit); - const short nTileX = ReadShort(fp, bOzi3, nKeyInit); - const short nTileY = ReadShort(fp, bOzi3, nKeyInit); - if (i == 0 && (nW != poDS->nRasterXSize || nH != poDS->nRasterYSize)) - { - CPLDebug("OZI", - "zoom[%d] inconsistent dimensions for zoom level 0 " - ": nW=%d, nH=%d, nTileX=%d, nTileY=%d, nRasterXSize=%d, " - "nRasterYSize=%d", - i, nW, nH, nTileX, nTileY, poDS->nRasterXSize, - poDS->nRasterYSize); - delete poDS; - return nullptr; - } - /* Note (#3895): some files such as world.ozf2 provided with OziExplorer - */ - /* expose nTileY=33, but have nH=2048, so only require 32 tiles in - * vertical dimension. */ - /* So there's apparently one extra and useless tile that will be ignored - */ - /* without causing apparent issues */ - /* Some other files have more tile in horizontal direction than needed, - * so let's */ - /* accept that. But in that case we really need to keep the nTileX value - * for IReadBlock() */ - /* to work properly */ - if ((nW + 63) / 64 > nTileX || (nH + 63) / 64 > nTileY) - { - CPLDebug("OZI", - "zoom[%d] unexpected number of tiles : nW=%d, " - "nH=%d, nTileX=%d, nTileY=%d", - i, nW, nH, nTileX, nTileY); - delete poDS; - return nullptr; - } - - auto poColorTable = std::make_unique(); - GByte abyColorTable[256 * 4]; - VSIFReadL(abyColorTable, 1, 1024, fp); - if (bOzi3) - OZIDecrypt(abyColorTable, 1024, nKeyInit); - for (int j = 0; j < 256; j++) - { - GDALColorEntry sEntry; - sEntry.c1 = abyColorTable[4 * j + 2]; - sEntry.c2 = abyColorTable[4 * j + 1]; - sEntry.c3 = abyColorTable[4 * j + 0]; - sEntry.c4 = 255; - poColorTable->SetColorEntry(j, &sEntry); - } - - poDS->papoOvrBands[i] = - new OZIRasterBand(poDS, i, nW, nH, nTileX, std::move(poColorTable)); - - if (i > 0) - { - GByte *pabyTranslationTable = - poDS->papoOvrBands[i]->GetIndexColorTranslationTo( - poDS->papoOvrBands[0], nullptr, nullptr); - - poDS->papoOvrBands[i]->poColorTable.reset( - poDS->papoOvrBands[0]->poColorTable->Clone()); - poDS->papoOvrBands[i]->pabyTranslationTable = pabyTranslationTable; - } - } - - poDS->SetBand(1, poDS->papoOvrBands[0]); - - /* -------------------------------------------------------------------- */ - /* Initialize any PAM information. */ - /* -------------------------------------------------------------------- */ - poDS->SetDescription(poOpenInfo->pszFilename); - poDS->TryLoadXML(); - - /* -------------------------------------------------------------------- */ - /* Support overviews. */ - /* -------------------------------------------------------------------- */ - poDS->oOvManager.Initialize(poDS, poOpenInfo->pszFilename); - return poDS; -} - -/************************************************************************/ -/* GDALRegister_OZI() */ -/************************************************************************/ - -void GDALRegister_OZI() - -{ - if (!GDAL_CHECK_VERSION("OZI driver")) - return; - - if (GDALGetDriverByName("OZI") != nullptr) - return; - - GDALDriver *poDriver = new GDALDriver(); - - poDriver->SetDescription("OZI"); - poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES"); - poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "OziExplorer Image File"); - poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/ozi.html"); - poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); - - poDriver->pfnOpen = OZIDataset::Open; - poDriver->pfnIdentify = OZIDataset::Identify; - - GetGDALDriverManager()->RegisterDriver(poDriver); -} diff --git a/gcore/gdal_frmts.h b/gcore/gdal_frmts.h index e957afc14719..a2df6ad6da9e 100644 --- a/gcore/gdal_frmts.h +++ b/gcore/gdal_frmts.h @@ -172,7 +172,6 @@ void CPL_DLL GDALRegister_HF2(void); void CPL_DLL GDALRegister_PDF(void); void DeclareDeferredPDFPlugin(void); void CPL_DLL GDALRegister_MAP(void); -void CPL_DLL GDALRegister_OZI(void); void CPL_DLL GDALRegister_ACE2(void); void CPL_DLL GDALRegister_CTG(void); void CPL_DLL GDALRegister_SNODAS(void);