LCOV - code coverage report
Current view: top level - frmts/jpeg - jpegdrivercore.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 54 64 84.4 %
Date: 2025-10-19 15:46:27 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  JPEG JFIF Driver
       4             :  * Purpose:  Implement GDAL JPEG Support based on IJG libjpeg.
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2000, Frank Warmerdam
       9             :  * Copyright (c) 2007-2014, Even Rouault <even dot rouault at spatialys.com>
      10             :  *
      11             :  * Portions Copyright (c) Her majesty the Queen in right of Canada as
      12             :  * represented by the Minister of National Defence, 2006.
      13             :  *
      14             :  * SPDX-License-Identifier: MIT
      15             :  ****************************************************************************/
      16             : 
      17             : #include "gdal_frmts.h"
      18             : #include "gdalplugindriverproxy.h"
      19             : 
      20             : #include "jpegdrivercore.h"
      21             : 
      22             : // So that D_LOSSLESS_SUPPORTED is visible if defined in jmorecfg of libjpeg-turbo >= 2.2
      23             : #define JPEG_INTERNAL_OPTIONS
      24             : #include "jpeglib.h"
      25             : 
      26             : /************************************************************************/
      27             : /*                    JPEGDatasetIsJPEGLS()                             */
      28             : /************************************************************************/
      29             : 
      30        6634 : bool JPEGDatasetIsJPEGLS(GDALOpenInfo *poOpenInfo)
      31             : 
      32             : {
      33        6634 :     GByte *pabyHeader = poOpenInfo->pabyHeader;
      34        6634 :     int nHeaderBytes = poOpenInfo->nHeaderBytes;
      35             : 
      36        6634 :     if (nHeaderBytes < 10)
      37           0 :         return false;
      38             : 
      39        6634 :     if (pabyHeader[0] != 0xff || pabyHeader[1] != 0xd8)
      40           0 :         return false;
      41             : 
      42       30456 :     for (int nOffset = 2; nOffset + 4 < nHeaderBytes;)
      43             :     {
      44       26016 :         if (pabyHeader[nOffset] != 0xFF)
      45           6 :             return false;
      46             : 
      47       26010 :         int nMarker = pabyHeader[nOffset + 1];
      48       26010 :         if (nMarker == 0xDA)
      49        2188 :             return false;
      50             : 
      51       23822 :         if (nMarker == 0xF7)  // JPEG Extension 7, JPEG-LS.
      52           0 :             return true;
      53       23822 :         if (nMarker == 0xF8)  // JPEG Extension 8, JPEG-LS Extension.
      54           0 :             return true;
      55       23822 :         if (nMarker == 0xC3)  // Start of Frame 3 (Lossless Huffman)
      56           0 :             return true;
      57       23822 :         if (nMarker ==
      58             :             0xC7)  // Start of Frame 7 (Differential Lossless Huffman)
      59           0 :             return true;
      60       23822 :         if (nMarker == 0xCB)  // Start of Frame 11 (Lossless Arithmetic)
      61           0 :             return true;
      62       23822 :         if (nMarker ==
      63             :             0xCF)  // Start of Frame 15 (Differential Lossless Arithmetic)
      64           0 :             return true;
      65             : 
      66       23822 :         nOffset += 2 + pabyHeader[nOffset + 2] * 256 + pabyHeader[nOffset + 3];
      67             :     }
      68             : 
      69        4440 :     return false;
      70             : }
      71             : 
      72             : /************************************************************************/
      73             : /*                     JPEGDriverIdentify()                             */
      74             : /************************************************************************/
      75             : 
      76       66155 : int JPEGDriverIdentify(GDALOpenInfo *poOpenInfo)
      77             : 
      78             : {
      79             :     // If it is a subfile, read the JPEG header.
      80       66155 :     if (STARTS_WITH_CI(poOpenInfo->pszFilename, "JPEG_SUBFILE:"))
      81         292 :         return TRUE;
      82       65863 :     if (STARTS_WITH(poOpenInfo->pszFilename, "JPEG:"))
      83          20 :         return TRUE;
      84             : 
      85             :     // First we check to see if the file has the expected header bytes.
      86       65843 :     const int nHeaderBytes = poOpenInfo->nHeaderBytes;
      87             : 
      88       65843 :     if (nHeaderBytes < 10)
      89       55272 :         return FALSE;
      90             : 
      91       10571 :     GByte *const pabyHeader = poOpenInfo->pabyHeader;
      92       10571 :     if (pabyHeader[0] != 0xff || pabyHeader[1] != 0xd8 || pabyHeader[2] != 0xff)
      93        3937 :         return FALSE;
      94             : 
      95             :         // libjpeg-turbo >= 2.2 supports lossless mode
      96             : #if !defined(D_LOSSLESS_SUPPORTED)
      97        6634 :     if (JPEGDatasetIsJPEGLS(poOpenInfo))
      98             :     {
      99           0 :         return FALSE;
     100             :     }
     101             : #endif
     102             : 
     103             :     // Some files like
     104             :     // http://dionecanali.hd.free.fr/~mdione/mapzen/N65E039.hgt.gz could be
     105             :     // mis-identfied as JPEG
     106       13268 :     CPLString osFilenameLower = CPLString(poOpenInfo->pszFilename).tolower();
     107       13267 :     if (osFilenameLower.endsWith(".hgt") ||
     108       26536 :         osFilenameLower.endsWith(".hgt.gz") ||
     109       13268 :         osFilenameLower.endsWith(".hgt.zip"))
     110             :     {
     111           0 :         return FALSE;
     112             :     }
     113             : 
     114        6634 :     return TRUE;
     115             : }
     116             : 
     117             : /************************************************************************/
     118             : /*                     JPEGDriverSetCommonMetadata()                    */
     119             : /************************************************************************/
     120             : 
     121        1750 : void JPEGDriverSetCommonMetadata(GDALDriver *poDriver)
     122             : {
     123        1750 :     poDriver->SetDescription(DRIVER_NAME);
     124        1750 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     125        1750 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "JPEG JFIF");
     126        1750 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/jpeg.html");
     127        1750 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "jpg");
     128        1750 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSIONS, "jpg jpeg");
     129        1750 :     poDriver->SetMetadataItem(GDAL_DMD_MIMETYPE, "image/jpeg");
     130             : 
     131             : #if defined(JPEG_LIB_MK1_OR_12BIT) || defined(JPEG_DUAL_MODE_8_12)
     132        1750 :     poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, "Byte UInt16");
     133             : #else
     134             :     poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, "Byte");
     135             : #endif
     136        1750 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     137        1750 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATE_ONLY_VISIBLE_AT_CLOSE_TIME,
     138        1750 :                               "YES");
     139             : 
     140        1750 :     const char *pszOpenOptions =
     141             :         "<OpenOptionList>\n"
     142             :         "   <Option name='USE_INTERNAL_OVERVIEWS' type='boolean' "
     143             :         "description='whether to use implicit internal overviews' "
     144             :         "default='YES'/>\n"
     145             :         "   <Option name='APPLY_ORIENTATION' type='boolean' "
     146             :         "description='whether to take into account EXIF Orientation to "
     147             :         "rotate/flip the image' default='NO'/>\n"
     148             :         "</OpenOptionList>\n";
     149        1750 :     poDriver->SetMetadataItem(GDAL_DMD_OPENOPTIONLIST, pszOpenOptions);
     150             : 
     151             : #ifdef D_LOSSLESS_SUPPORTED
     152             :     // For autotest purposes
     153             :     poDriver->SetMetadataItem("LOSSLESS_JPEG_SUPPORTED", "YES", "JPEG");
     154             : #endif
     155             : 
     156        1750 :     poDriver->pfnIdentify = JPEGDriverIdentify;
     157        1750 :     poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
     158        1750 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATECOPY, "YES");
     159        1750 : }
     160             : 
     161             : /************************************************************************/
     162             : /*                    DeclareDeferredJPEGPlugin()                       */
     163             : /************************************************************************/
     164             : 
     165             : #ifdef PLUGIN_FILENAME
     166             : void DeclareDeferredJPEGPlugin()
     167             : {
     168             :     if (GDALGetDriverByName(DRIVER_NAME) != nullptr)
     169             :     {
     170             :         return;
     171             :     }
     172             :     auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
     173             : #ifdef PLUGIN_INSTALLATION_MESSAGE
     174             :     poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
     175             :                               PLUGIN_INSTALLATION_MESSAGE);
     176             : #endif
     177             :     JPEGDriverSetCommonMetadata(poDriver);
     178             :     GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
     179             : }
     180             : #endif

Generated by: LCOV version 1.14