LCOV - code coverage report
Current view: top level - frmts/ecw - ecwdrivercore.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 62 63 98.4 %
Date: 2024-11-21 22:18:42 Functions: 9 9 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL
       4             :  * Purpose:  ECW driver
       5             :  * Author:   Even Rouault, <even.rouault at spatialys.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2023, Even Rouault, <even.rouault at spatialys.com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : // ncsjpcbuffer.h needs the min and max macros.
      14             : #undef NOMINMAX
      15             : 
      16             : #include "ecwdrivercore.h"
      17             : 
      18             : #include "ecwsdk_headers.h"
      19             : 
      20             : constexpr unsigned char jpc_header[] = {0xff, 0x4f, 0xff,
      21             :                                         0x51};  // SOC + RSIZ markers
      22             : constexpr unsigned char jp2_header[] = {0x00, 0x00, 0x00, 0x0c, 0x6a, 0x50,
      23             :                                         0x20, 0x20, 0x0d, 0x0a, 0x87, 0x0a};
      24             : 
      25             : /* Needed for v4.3 and v5.0 */
      26             : #if !defined(NCS_ECWSDK_VERSION_STRING) && defined(NCS_ECWJP2_VERSION_STRING)
      27             : #define NCS_ECWSDK_VERSION_STRING NCS_ECWJP2_VERSION_STRING
      28             : #endif
      29             : 
      30             : /************************************************************************/
      31             : /*                           IdentifyECW()                              */
      32             : /*                                                                      */
      33             : /*      Identify method that only supports ECW files.                   */
      34             : /************************************************************************/
      35             : 
      36       53860 : int ECWDatasetIdentifyECW(GDALOpenInfo *poOpenInfo)
      37             : 
      38             : {
      39             :     /* -------------------------------------------------------------------- */
      40             :     /*      This has to either be a file on disk ending in .ecw or a        */
      41             :     /*      ecwp: protocol url.                                             */
      42             :     /* -------------------------------------------------------------------- */
      43       53860 :     if ((!EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "ecw") ||
      44         125 :          poOpenInfo->nHeaderBytes == 0) &&
      45      107769 :         !STARTS_WITH_CI(poOpenInfo->pszFilename, "ecwp:") &&
      46       53790 :         !STARTS_WITH_CI(poOpenInfo->pszFilename, "ecwps:"))
      47       53786 :         return FALSE;
      48             : 
      49          68 :     return TRUE;
      50             : }
      51             : 
      52             : /************************************************************************/
      53             : /*                    ECWDriverSetCommonMetadata()                      */
      54             : /************************************************************************/
      55             : 
      56        1306 : void ECWDriverSetCommonMetadata(GDALDriver *poDriver)
      57             : {
      58        1306 :     poDriver->SetDescription(ECW_DRIVER_NAME);
      59        1306 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
      60             : 
      61        2612 :     CPLString osLongName = "ERDAS Compressed Wavelets (SDK ";
      62             : 
      63             : #ifdef NCS_ECWSDK_VERSION_STRING
      64             :     osLongName += NCS_ECWSDK_VERSION_STRING;
      65             : #else
      66        1306 :     osLongName += "3.x";
      67             : #endif
      68        1306 :     osLongName += ")";
      69             : 
      70        1306 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, osLongName);
      71        1306 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/ecw.html");
      72        1306 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "ecw");
      73             : 
      74        1306 :     poDriver->pfnIdentify = ECWDatasetIdentifyECW;
      75        1306 :     poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
      76             : #ifdef HAVE_COMPRESS
      77             :     // The create method does not work with SDK 3.3 ( crash in
      78             :     // CNCSJP2FileView::WriteLineBIL() due to m_pFile being nullptr ).
      79             : #if ECWSDK_VERSION >= 50
      80             :     poDriver->SetMetadataItem(GDAL_DCAP_CREATE, "YES");
      81             : #endif
      82        1306 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATECOPY, "YES");
      83             : #if ECWSDK_VERSION >= 50
      84             :     poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, "Byte UInt16");
      85             : #else
      86        1306 :     poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, "Byte");
      87             : #endif
      88        1306 :     poDriver->SetMetadataItem(
      89             :         GDAL_DMD_CREATIONOPTIONLIST,
      90             :         "<CreationOptionList>"
      91             :         "   <Option name='TARGET' type='float' description='Compression "
      92             :         "Percentage' />"
      93             :         "   <Option name='PROJ' type='string' description='ECW Projection "
      94             :         "Name'/>"
      95             :         "   <Option name='DATUM' type='string' description='ECW Datum Name' />"
      96             : 
      97             : #if ECWSDK_VERSION < 40
      98             :         "   <Option name='LARGE_OK' type='boolean' description='Enable "
      99             :         "compressing 500+MB files'/>"
     100             : #else
     101             :         "   <Option name='ECW_ENCODE_KEY' type='string' description='OEM "
     102             :         "Compress Key from ERDAS.'/>"
     103             :         "   <Option name='ECW_ENCODE_COMPANY' type='string' description='OEM "
     104             :         "Company Name.'/>"
     105             : #endif
     106             : 
     107             : #if ECWSDK_VERSION >= 50
     108             :         "   <Option name='ECW_FORMAT_VERSION' type='integer' description='ECW "
     109             :         "format version (2 or 3).' default='2'/>"
     110             : #endif
     111             : 
     112        1306 :         "</CreationOptionList>");
     113             : #else
     114             :     // In read-only mode, we support VirtualIO. This is not the case
     115             :     // for ECWCreateCopyECW().
     116             :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     117             : #endif
     118        1306 : }
     119             : 
     120             : /************************************************************************/
     121             : /*                        IdentifyJPEG2000()                            */
     122             : /*                                                                      */
     123             : /*          Identify method that only supports JPEG2000 files.          */
     124             : /************************************************************************/
     125             : 
     126       59891 : int ECWDatasetIdentifyJPEG2000(GDALOpenInfo *poOpenInfo)
     127             : 
     128             : {
     129       59891 :     if (STARTS_WITH_CI(poOpenInfo->pszFilename, "J2K_SUBFILE:"))
     130           0 :         return TRUE;
     131             : 
     132       59891 :     else if (poOpenInfo->nHeaderBytes >= 16 &&
     133       10204 :              (memcmp(poOpenInfo->pabyHeader, jpc_header, sizeof(jpc_header)) ==
     134       10149 :                   0 ||
     135       10149 :               memcmp(poOpenInfo->pabyHeader, jp2_header, sizeof(jp2_header)) ==
     136             :                   0))
     137         149 :         return TRUE;
     138             : 
     139             :     else
     140       59742 :         return FALSE;
     141             : }
     142             : 
     143             : /************************************************************************/
     144             : /*                 JP2ECWDriverSetCommonMetadata()                      */
     145             : /************************************************************************/
     146             : 
     147        1306 : void JP2ECWDriverSetCommonMetadata(GDALDriver *poDriver)
     148             : {
     149        1306 :     poDriver->SetDescription(JP2ECW_DRIVER_NAME);
     150        1306 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     151        1306 :     poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
     152             : 
     153        2612 :     CPLString osLongName = "ERDAS JPEG2000 (SDK ";
     154             : 
     155             : #ifdef NCS_ECWSDK_VERSION_STRING
     156             :     osLongName += NCS_ECWSDK_VERSION_STRING;
     157             : #else
     158        1306 :     osLongName += "3.x";
     159             : #endif
     160        1306 :     osLongName += ")";
     161             : 
     162        1306 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, osLongName);
     163        1306 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/jp2ecw.html");
     164        1306 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "jp2");
     165        1306 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     166             : 
     167        1306 :     poDriver->pfnIdentify = ECWDatasetIdentifyJPEG2000;
     168        1306 :     poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
     169             : 
     170        1306 :     poDriver->SetMetadataItem(
     171             :         GDAL_DMD_OPENOPTIONLIST,
     172             :         "<OpenOptionList>"
     173             :         "   <Option name='1BIT_ALPHA_PROMOTION' type='boolean' "
     174             :         "description='Whether a 1-bit alpha channel should be promoted to "
     175             :         "8-bit' default='YES'/>"
     176             :         "   <Option name='OPEN_REMOTE_GML' type='boolean' description='Whether "
     177             :         "to load remote vector layers referenced by a link in a GMLJP2 v2 box' "
     178             :         "default='NO'/>"
     179             :         "   <Option name='GEOREF_SOURCES' type='string' description='Comma "
     180             :         "separated list made with values "
     181             :         "INTERNAL/GMLJP2/GEOJP2/WORLDFILE/PAM/NONE that describe the priority "
     182             :         "order for georeferencing' default='PAM,GEOJP2,GMLJP2,WORLDFILE'/>"
     183        1306 :         "</OpenOptionList>");
     184             : 
     185             : #ifdef HAVE_COMPRESS
     186        1306 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATE, "YES");
     187        1306 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATECOPY, "YES");
     188        1306 :     poDriver->SetMetadataItem(
     189             :         GDAL_DMD_CREATIONDATATYPES,
     190             :         "Byte UInt16 Int16 UInt32 Int32 "
     191             :         "Float32 "
     192             : #if ECWSDK_VERSION >= 40
     193             :         // Crashes for sure with 3.3. Didn't try other versions
     194             :         "Float64"
     195             : #endif
     196        1306 :     );
     197        1306 :     poDriver->SetMetadataItem(
     198             :         GDAL_DMD_CREATIONOPTIONLIST,
     199             :         "<CreationOptionList>"
     200             :         "   <Option name='TARGET' type='float' description='Compression "
     201             :         "Percentage' />"
     202             :         "   <Option name='PROJ' type='string' description='ECW Projection "
     203             :         "Name'/>"
     204             :         "   <Option name='DATUM' type='string' description='ECW Datum Name' />"
     205             :         "   <Option name='UNITS' type='string-select' description='ECW "
     206             :         "Projection Units'>"
     207             :         "       <Value>METERS</Value>"
     208             :         "       <Value>FEET</Value>"
     209             :         "   </Option>"
     210             : 
     211             : #if ECWSDK_VERSION < 40
     212             :         "   <Option name='LARGE_OK' type='boolean' description='Enable "
     213             :         "compressing 500+MB files'/>"
     214             : #else
     215             :         "   <Option name='ECW_ENCODE_KEY' type='string' description='OEM "
     216             :         "Compress Key from ERDAS.'/>"
     217             :         "   <Option name='ECW_ENCODE_COMPANY' type='string' description='OEM "
     218             :         "Company Name.'/>"
     219             : #endif
     220             : 
     221             :         "   <Option name='GeoJP2' type='boolean' description='defaults to ON'/>"
     222             :         "   <Option name='GMLJP2' type='boolean' description='defaults to ON'/>"
     223             :         "   <Option name='GMLJP2V2_DEF' type='string' description='Definition "
     224             :         "file to describe how a GMLJP2 v2 box should be generated. If set to "
     225             :         "YES, a minimal instance will be created'/>"
     226             :         "   <Option name='PROFILE' type='string-select'>"
     227             :         "       <Value>BASELINE_0</Value>"
     228             :         "       <Value>BASELINE_1</Value>"
     229             :         "       <Value>BASELINE_2</Value>"
     230             :         "       <Value>NPJE</Value>"
     231             :         "       <Value>EPJE</Value>"
     232             :         "   </Option>"
     233             :         "   <Option name='PROGRESSION' type='string-select'>"
     234             :         "       <Value>LRCP</Value>"
     235             :         "       <Value>RLCP</Value>"
     236             :         "       <Value>RPCL</Value>"
     237             :         "   </Option>"
     238             :         "   <Option name='CODESTREAM_ONLY' type='boolean' description='No JP2 "
     239             :         "wrapper'/>"
     240             :         "   <Option name='NBITS' type='int' description='Bits (precision) for "
     241             :         "sub-byte files (1-7), sub-uint16 (9-15)'/>"
     242             :         "   <Option name='LEVELS' type='int'/>"
     243             :         "   <Option name='LAYERS' type='int'/>"
     244             :         "   <Option name='PRECINCT_WIDTH' type='int'/>"
     245             :         "   <Option name='PRECINCT_HEIGHT' type='int'/>"
     246             :         "   <Option name='TILE_WIDTH' type='int'/>"
     247             :         "   <Option name='TILE_HEIGHT' type='int'/>"
     248             :         "   <Option name='INCLUDE_SOP' type='boolean'/>"
     249             :         "   <Option name='INCLUDE_EPH' type='boolean'/>"
     250             :         "   <Option name='DECOMPRESS_LAYERS' type='int'/>"
     251             :         "   <Option name='DECOMPRESS_RECONSTRUCTION_PARAMETER' type='float'/>"
     252             :         "   <Option name='WRITE_METADATA' type='boolean' description='Whether "
     253             :         "metadata should be written, in a dedicated JP2 XML box' default='NO'/>"
     254             :         "   <Option name='MAIN_MD_DOMAIN_ONLY' type='boolean' "
     255             :         "description='(Only if WRITE_METADATA=YES) Whether only metadata from "
     256             :         "the main domain should be written' default='NO'/>"
     257        1306 :         "</CreationOptionList>");
     258             : #endif
     259        1306 : }
     260             : 
     261             : /************************************************************************/
     262             : /*                    DeclareDeferredECWPlugin()                        */
     263             : /************************************************************************/
     264             : 
     265             : #ifdef PLUGIN_FILENAME
     266        1595 : void DeclareDeferredECWPlugin()
     267             : {
     268        1595 :     if (GDALGetDriverByName(ECW_DRIVER_NAME) != nullptr)
     269             :     {
     270         302 :         return;
     271             :     }
     272             :     {
     273        1293 :         auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
     274             : #ifdef PLUGIN_INSTALLATION_MESSAGE
     275             :         poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
     276             :                                   PLUGIN_INSTALLATION_MESSAGE);
     277             : #endif
     278        1293 :         ECWDriverSetCommonMetadata(poDriver);
     279        1293 :         GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
     280             :     }
     281             :     {
     282        1293 :         auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
     283             : #ifdef PLUGIN_INSTALLATION_MESSAGE
     284             :         poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
     285             :                                   PLUGIN_INSTALLATION_MESSAGE);
     286             : #endif
     287        1293 :         JP2ECWDriverSetCommonMetadata(poDriver);
     288        1293 :         GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
     289             :     }
     290             : }
     291             : #endif

Generated by: LCOV version 1.14