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: 2024-05-13 13:33:37 Functions: 4 4 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             :  * Permission is hereby granted, free of charge, to any person obtaining a
      11             :  * copy of this software and associated documentation files (the "Software"),
      12             :  * to deal in the Software without restriction, including without limitation
      13             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      14             :  * and/or sell copies of the Software, and to permit persons to whom the
      15             :  * Software is furnished to do so, subject to the following conditions:
      16             :  *
      17             :  * The above copyright notice and this permission notice shall be included
      18             :  * in all copies or substantial portions of the Software.
      19             :  *
      20             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      21             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      22             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      23             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      24             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      25             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      26             :  * DEALINGS IN THE SOFTWARE.
      27             :  ****************************************************************************/
      28             : 
      29             : #include "jpegxldrivercore.h"
      30             : 
      31             : /************************************************************************/
      32             : /*                      IsJPEGXLContainer()                             */
      33             : /************************************************************************/
      34             : 
      35        2606 : bool IsJPEGXLContainer(GDALOpenInfo *poOpenInfo)
      36             : {
      37        2606 :     constexpr const GByte abyJXLContainerSignature[] = {
      38             :         0x00, 0x00, 0x00, 0x0C, 'J', 'X', 'L', ' ', 0x0D, 0x0A, 0x87, 0x0A};
      39        2606 :     return (poOpenInfo->nHeaderBytes >=
      40        5028 :                 static_cast<int>(sizeof(abyJXLContainerSignature)) &&
      41        2422 :             memcmp(poOpenInfo->pabyHeader, abyJXLContainerSignature,
      42        2606 :                    sizeof(abyJXLContainerSignature)) == 0);
      43             : }
      44             : 
      45             : /************************************************************************/
      46             : /*                JPEGXLDatasetIdentifyPartial()                        */
      47             : /************************************************************************/
      48             : 
      49       18257 : static int JPEGXLDatasetIdentifyPartial(GDALOpenInfo *poOpenInfo)
      50             : {
      51       18257 :     if (poOpenInfo->fpL == nullptr)
      52       17296 :         return false;
      53             : 
      54         961 :     if (EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "jxl"))
      55           1 :         return true;
      56             : 
      57             :     // See
      58             :     // https://github.com/libjxl/libjxl/blob/c98f133f3f5e456caaa2ba00bc920e923b713abc/lib/jxl/decode.cc#L107-L138
      59             : 
      60             :     // JPEG XL codestream
      61         960 :     if (poOpenInfo->nHeaderBytes >= 2 && poOpenInfo->pabyHeader[0] == 0xff &&
      62           9 :         poOpenInfo->pabyHeader[1] == 0x0a)
      63             :     {
      64             :         // Two bytes is not enough to reliably identify
      65             :         // JPEGXLDataset::Identify() does a bit more work then
      66           1 :         return GDAL_IDENTIFY_UNKNOWN;
      67             :     }
      68             : 
      69         959 :     return IsJPEGXLContainer(poOpenInfo);
      70             : }
      71             : 
      72             : /************************************************************************/
      73             : /*                   JPEGXLDriverSetCommonMetadata()                    */
      74             : /************************************************************************/
      75             : 
      76        1230 : void JPEGXLDriverSetCommonMetadata(GDALDriver *poDriver)
      77             : {
      78             :     // Set the driver details.
      79        1230 :     poDriver->SetDescription(DRIVER_NAME);
      80             : 
      81        1230 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
      82        1230 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "JPEG-XL");
      83        1230 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/jpegxl.html");
      84        1230 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "jxl");
      85        1230 :     poDriver->SetMetadataItem(GDAL_DMD_MIMETYPE, "image/jxl");
      86             : 
      87        1230 :     poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES,
      88        1230 :                               "Byte UInt16 Float32");
      89             : 
      90             : #ifdef HAVE_JXL_BOX_API
      91        1230 :     const char *pszOpenOptions =
      92             :         "<OpenOptionList>\n"
      93             :         "   <Option name='APPLY_ORIENTATION' type='boolean' "
      94             :         "description='whether to take into account EXIF Orientation to "
      95             :         "rotate/flip the image' default='NO'/>\n"
      96             :         "</OpenOptionList>\n";
      97        1230 :     poDriver->SetMetadataItem(GDAL_DMD_OPENOPTIONLIST, pszOpenOptions);
      98             : #endif
      99             : 
     100        1230 :     poDriver->SetMetadataItem(
     101             :         GDAL_DMD_CREATIONOPTIONLIST,
     102             :         "<CreationOptionList>\n"
     103             :         "   <Option name='LOSSLESS' type='boolean' description='Whether JPEGXL "
     104             :         "compression should be lossless' default='YES'/>"
     105             :         "   <Option name='LOSSLESS_COPY' type='string-select' "
     106             :         "description='Whether conversion should be lossless' default='AUTO'>"
     107             :         "     <Value>AUTO</Value>"
     108             :         "     <Value>YES</Value>"
     109             :         "     <Value>NO</Value>"
     110             :         "   </Option>"
     111             :         "   <Option name='EFFORT' type='int' description='Level of effort "
     112             :         "1(fast)-9(slow)' default='5'/>"
     113             :         "   <Option name='DISTANCE' type='float' description='Distance level "
     114             :         "for lossy compression (0=mathematically lossless, 1.0=visually "
     115             :         "lossless, usual range [0.5,3])' default='1.0' min='0.1' max='15.0'/>"
     116             : #ifdef HAVE_JxlEncoderSetExtraChannelDistance
     117             :         "  <Option name='ALPHA_DISTANCE' type='float' "
     118             :         "description='Distance level for alpha channel "
     119             :         "(-1=same as non-alpha channels, "
     120             :         "0=mathematically lossless, 1.0=visually lossless, "
     121             :         "usual range [0.5,3])' default='-1' min='-1' max='15.0'/>"
     122             : #endif
     123             :         "   <Option name='QUALITY' type='float' description='Alternative "
     124             :         "setting to DISTANCE to specify lossy compression, roughly matching "
     125             :         "libjpeg quality setting in the [0,100] range' default='90' max='100'/>"
     126             :         "   <Option name='NBITS' type='int' description='BITS for sub-byte "
     127             :         "files (1-7), sub-uint16_t (9-15)'/>"
     128             :         "   <Option name='SOURCE_ICC_PROFILE' description='ICC profile encoded "
     129             :         "in Base64' type='string'/>\n"
     130             : #ifdef HAVE_JXL_THREADS
     131             :         "   <Option name='NUM_THREADS' type='string' description='Number of "
     132             :         "worker threads for compression. Can be set to ALL_CPUS' "
     133             :         "default='ALL_CPUS'/>"
     134             : #endif
     135             : #ifdef HAVE_JXL_BOX_API
     136             :         "   <Option name='WRITE_EXIF_METADATA' type='boolean' "
     137             :         "description='Whether to write EXIF_ metadata in a Exif box' "
     138             :         "default='YES'/>"
     139             :         "   <Option name='WRITE_XMP' type='boolean' description='Whether to "
     140             :         "write xml:XMP metadata in a xml box' default='YES'/>"
     141             :         "   <Option name='WRITE_GEOJP2' type='boolean' description='Whether to "
     142             :         "write georeferencing in a jumb.uuid box' default='YES'/>"
     143             :         "   <Option name='COMPRESS_BOXES' type='boolean' description='Whether "
     144             :         "to decompress Exif/XMP/GeoJP2 boxes' default='NO'/>"
     145             : #endif
     146        1230 :         "</CreationOptionList>\n");
     147             : 
     148        1230 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     149             : 
     150             : #ifdef HAVE_JxlEncoderInitExtraChannelInfo
     151        1230 :     poDriver->SetMetadataItem("JXL_ENCODER_SUPPORT_EXTRA_CHANNELS", "YES");
     152             : #endif
     153             : 
     154        1230 :     poDriver->pfnIdentify = JPEGXLDatasetIdentifyPartial;
     155        1230 :     poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
     156        1230 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATECOPY, "YES");
     157        1230 : }
     158             : 
     159             : /************************************************************************/
     160             : /*                    DeclareDeferredJPEGXLPlugin()                     */
     161             : /************************************************************************/
     162             : 
     163             : #ifdef PLUGIN_FILENAME
     164        1522 : void DeclareDeferredJPEGXLPlugin()
     165             : {
     166        1522 :     if (GDALGetDriverByName(DRIVER_NAME) != nullptr)
     167             :     {
     168         301 :         return;
     169             :     }
     170        1221 :     auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
     171             : #ifdef PLUGIN_INSTALLATION_MESSAGE
     172             :     poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
     173             :                               PLUGIN_INSTALLATION_MESSAGE);
     174             : #endif
     175        1221 :     JPEGXLDriverSetCommonMetadata(poDriver);
     176        1221 :     GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
     177             : }
     178             : #endif

Generated by: LCOV version 1.14