LCOV - code coverage report
Current view: top level - frmts/jpegxl - jpegxldrivercore.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 40 40 100.0 %
Date: 2025-10-16 20:08:56 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL
       4             :  * Purpose:  JPEGXL 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             : #include "gdal_frmts.h"
      14             : #include "gdalplugindriverproxy.h"
      15             : 
      16             : #include "jpegxldrivercore.h"
      17             : 
      18             : /************************************************************************/
      19             : /*                      IsJPEGXLContainer()                             */
      20             : /************************************************************************/
      21             : 
      22        3128 : bool IsJPEGXLContainer(GDALOpenInfo *poOpenInfo)
      23             : {
      24        3128 :     constexpr const GByte abyJXLContainerSignature[] = {
      25             :         0x00, 0x00, 0x00, 0x0C, 'J', 'X', 'L', ' ', 0x0D, 0x0A, 0x87, 0x0A};
      26        3128 :     return (poOpenInfo->nHeaderBytes >=
      27        6039 :                 static_cast<int>(sizeof(abyJXLContainerSignature)) &&
      28        2911 :             memcmp(poOpenInfo->pabyHeader, abyJXLContainerSignature,
      29        3128 :                    sizeof(abyJXLContainerSignature)) == 0);
      30             : }
      31             : 
      32             : /************************************************************************/
      33             : /*                JPEGXLDatasetIdentifyPartial()                        */
      34             : /************************************************************************/
      35             : 
      36       13174 : static int JPEGXLDatasetIdentifyPartial(GDALOpenInfo *poOpenInfo)
      37             : {
      38       13174 :     if (poOpenInfo->fpL == nullptr)
      39       12093 :         return false;
      40             : 
      41        1081 :     if (poOpenInfo->IsExtensionEqualToCI("jxl"))
      42           1 :         return true;
      43             : 
      44             :     // See
      45             :     // https://github.com/libjxl/libjxl/blob/c98f133f3f5e456caaa2ba00bc920e923b713abc/lib/jxl/decode.cc#L107-L138
      46             : 
      47             :     // JPEG XL codestream
      48        1080 :     if (poOpenInfo->nHeaderBytes >= 2 && poOpenInfo->pabyHeader[0] == 0xff &&
      49          10 :         poOpenInfo->pabyHeader[1] == 0x0a)
      50             :     {
      51             :         // Two bytes is not enough to reliably identify
      52             :         // JPEGXLDataset::Identify() does a bit more work then
      53           1 :         return GDAL_IDENTIFY_UNKNOWN;
      54             :     }
      55             : 
      56        1079 :     return IsJPEGXLContainer(poOpenInfo);
      57             : }
      58             : 
      59             : /************************************************************************/
      60             : /*                   JPEGXLDriverSetCommonMetadata()                    */
      61             : /************************************************************************/
      62             : 
      63        1762 : void JPEGXLDriverSetCommonMetadata(GDALDriver *poDriver)
      64             : {
      65             :     // Set the driver details.
      66        1762 :     poDriver->SetDescription(DRIVER_NAME);
      67             : 
      68        1762 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
      69        1762 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "JPEG-XL");
      70        1762 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/jpegxl.html");
      71        1762 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "jxl");
      72        1762 :     poDriver->SetMetadataItem(GDAL_DMD_MIMETYPE, "image/jxl");
      73             : 
      74        1762 :     poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES,
      75        1762 :                               "Byte UInt16 Float32");
      76             : 
      77             : #ifdef HAVE_JXL_BOX_API
      78        1762 :     const char *pszOpenOptions =
      79             :         "<OpenOptionList>\n"
      80             :         "   <Option name='APPLY_ORIENTATION' type='boolean' "
      81             :         "description='whether to take into account EXIF Orientation to "
      82             :         "rotate/flip the image' default='NO'/>\n"
      83             :         "</OpenOptionList>\n";
      84        1762 :     poDriver->SetMetadataItem(GDAL_DMD_OPENOPTIONLIST, pszOpenOptions);
      85             : #endif
      86             : 
      87        1762 :     poDriver->SetMetadataItem(
      88             :         GDAL_DMD_CREATIONOPTIONLIST,
      89             :         "<CreationOptionList>\n"
      90             :         "   <Option name='LOSSLESS' type='boolean' description='Whether JPEGXL "
      91             :         "compression should be lossless' default='YES'/>"
      92             :         "   <Option name='LOSSLESS_COPY' type='string-select' "
      93             :         "description='Whether conversion should be lossless' default='AUTO'>"
      94             :         "     <Value>AUTO</Value>"
      95             :         "     <Value>YES</Value>"
      96             :         "     <Value>NO</Value>"
      97             :         "   </Option>"
      98             :         "   <Option name='EFFORT' type='int' description='Level of effort "
      99             :         "1(fast)-9(slow)' default='5'/>"
     100             :         "   <Option name='DISTANCE' type='float' description='Distance level "
     101             :         "for lossy compression (0=mathematically lossless, 1.0=visually "
     102             :         "lossless, usual range [0.5,3])' default='1.0' min='0.01' max='25.0'/>"
     103             : #ifdef HAVE_JxlEncoderSetExtraChannelDistance
     104             :         "  <Option name='ALPHA_DISTANCE' type='float' "
     105             :         "description='Distance level for alpha channel "
     106             :         "(-1=same as non-alpha channels, "
     107             :         "0=mathematically lossless, 1.0=visually lossless, "
     108             :         "usual range [0.5,3])' default='-1' min='-1' max='25.0'/>"
     109             : #endif
     110             :         "   <Option name='QUALITY' type='float' description='Alternative "
     111             :         "setting to DISTANCE to specify lossy compression, roughly matching "
     112             :         "libjpeg quality setting in the [0,100] range' default='90' max='100'/>"
     113             :         "   <Option name='NBITS' type='int' description='BITS for sub-byte "
     114             :         "files (1-7), sub-uint16_t (9-15)'/>"
     115             :         "   <Option name='SOURCE_ICC_PROFILE' description='ICC profile encoded "
     116             :         "in Base64' type='string'/>\n"
     117             : #ifdef HAVE_JXL_THREADS
     118             :         "   <Option name='NUM_THREADS' type='string' description='Number of "
     119             :         "worker threads for compression. Can be set to ALL_CPUS' "
     120             :         "default='ALL_CPUS'/>"
     121             : #endif
     122             : #ifdef HAVE_JXL_BOX_API
     123             :         "   <Option name='WRITE_EXIF_METADATA' type='boolean' "
     124             :         "description='Whether to write EXIF_ metadata in a Exif box' "
     125             :         "default='YES'/>"
     126             :         "   <Option name='WRITE_XMP' type='boolean' description='Whether to "
     127             :         "write xml:XMP metadata in a xml box' default='YES'/>"
     128             :         "   <Option name='WRITE_GEOJP2' type='boolean' description='Whether to "
     129             :         "write georeferencing in a jumb.uuid box' default='YES'/>"
     130             :         "   <Option name='COMPRESS_BOXES' type='boolean' description='Whether "
     131             :         "to decompress Exif/XMP/GeoJP2 boxes' default='NO'/>"
     132             : #endif
     133        1762 :         "</CreationOptionList>\n");
     134             : 
     135        1762 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     136             : 
     137             : #ifdef HAVE_JxlEncoderInitExtraChannelInfo
     138        1762 :     poDriver->SetMetadataItem("JXL_ENCODER_SUPPORT_EXTRA_CHANNELS", "YES");
     139             : #endif
     140             : 
     141        1762 :     poDriver->pfnIdentify = JPEGXLDatasetIdentifyPartial;
     142        1762 :     poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
     143        1762 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATECOPY, "YES");
     144        1762 : }
     145             : 
     146             : /************************************************************************/
     147             : /*                    DeclareDeferredJPEGXLPlugin()                     */
     148             : /************************************************************************/
     149             : 
     150             : #ifdef PLUGIN_FILENAME
     151        2033 : void DeclareDeferredJPEGXLPlugin()
     152             : {
     153        2033 :     if (GDALGetDriverByName(DRIVER_NAME) != nullptr)
     154             :     {
     155         283 :         return;
     156             :     }
     157        1750 :     auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
     158             : #ifdef PLUGIN_INSTALLATION_MESSAGE
     159             :     poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
     160             :                               PLUGIN_INSTALLATION_MESSAGE);
     161             : #endif
     162        1750 :     JPEGXLDriverSetCommonMetadata(poDriver);
     163        1750 :     GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
     164             : }
     165             : #endif

Generated by: LCOV version 1.14