LCOV - code coverage report
Current view: top level - frmts/jpeg - jpegdrivercore.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 51 62 82.3 %
Date: 2024-05-04 12:52:34 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             :  * Permission is hereby granted, free of charge, to any person obtaining a
      15             :  * copy of this software and associated documentation files (the "Software"),
      16             :  * to deal in the Software without restriction, including without limitation
      17             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      18             :  * and/or sell copies of the Software, and to permit persons to whom the
      19             :  * Software is furnished to do so, subject to the following conditions:
      20             :  *
      21             :  * The above copyright notice and this permission notice shall be included
      22             :  * in all copies or substantial portions of the Software.
      23             :  *
      24             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      25             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      26             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      27             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      28             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      29             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      30             :  * DEALINGS IN THE SOFTWARE.
      31             :  ****************************************************************************/
      32             : 
      33             : #include "jpegdrivercore.h"
      34             : 
      35             : // So that D_LOSSLESS_SUPPORTED is visible if defined in jmorecfg of libjpeg-turbo >= 2.2
      36             : #define JPEG_INTERNAL_OPTIONS
      37             : #include "jpeglib.h"
      38             : 
      39             : /************************************************************************/
      40             : /*                    JPEGDatasetIsJPEGLS()                             */
      41             : /************************************************************************/
      42             : 
      43        6075 : bool JPEGDatasetIsJPEGLS(GDALOpenInfo *poOpenInfo)
      44             : 
      45             : {
      46        6075 :     GByte *pabyHeader = poOpenInfo->pabyHeader;
      47        6075 :     int nHeaderBytes = poOpenInfo->nHeaderBytes;
      48             : 
      49        6075 :     if (nHeaderBytes < 10)
      50           0 :         return false;
      51             : 
      52        6075 :     if (pabyHeader[0] != 0xff || pabyHeader[1] != 0xd8)
      53           0 :         return false;
      54             : 
      55       27455 :     for (int nOffset = 2; nOffset + 4 < nHeaderBytes;)
      56             :     {
      57       23017 :         if (pabyHeader[nOffset] != 0xFF)
      58           0 :             return false;
      59             : 
      60       23017 :         int nMarker = pabyHeader[nOffset + 1];
      61       23017 :         if (nMarker == 0xDA)
      62        1637 :             return false;
      63             : 
      64       21380 :         if (nMarker == 0xF7)  // JPEG Extension 7, JPEG-LS.
      65           0 :             return true;
      66       21380 :         if (nMarker == 0xF8)  // JPEG Extension 8, JPEG-LS Extension.
      67           0 :             return true;
      68       21380 :         if (nMarker == 0xC3)  // Start of Frame 3 (Lossless Huffman)
      69           0 :             return true;
      70       21380 :         if (nMarker ==
      71             :             0xC7)  // Start of Frame 7 (Differential Lossless Huffman)
      72           0 :             return true;
      73       21380 :         if (nMarker == 0xCB)  // Start of Frame 11 (Lossless Arithmetic)
      74           0 :             return true;
      75       21380 :         if (nMarker ==
      76             :             0xCF)  // Start of Frame 15 (Differential Lossless Arithmetic)
      77           0 :             return true;
      78             : 
      79       21380 :         nOffset += 2 + pabyHeader[nOffset + 2] * 256 + pabyHeader[nOffset + 3];
      80             :     }
      81             : 
      82        4438 :     return false;
      83             : }
      84             : 
      85             : /************************************************************************/
      86             : /*                     JPEGDriverIdentify()                             */
      87             : /************************************************************************/
      88             : 
      89       55459 : int JPEGDriverIdentify(GDALOpenInfo *poOpenInfo)
      90             : 
      91             : {
      92             :     // If it is a subfile, read the JPEG header.
      93       55459 :     if (STARTS_WITH_CI(poOpenInfo->pszFilename, "JPEG_SUBFILE:"))
      94          60 :         return TRUE;
      95       55399 :     if (STARTS_WITH(poOpenInfo->pszFilename, "JPEG:"))
      96          10 :         return TRUE;
      97             : 
      98             :     // First we check to see if the file has the expected header bytes.
      99       55389 :     const int nHeaderBytes = poOpenInfo->nHeaderBytes;
     100             : 
     101       55389 :     if (nHeaderBytes < 10)
     102       45770 :         return FALSE;
     103             : 
     104        9619 :     GByte *const pabyHeader = poOpenInfo->pabyHeader;
     105        9619 :     if (pabyHeader[0] != 0xff || pabyHeader[1] != 0xd8 || pabyHeader[2] != 0xff)
     106        3544 :         return FALSE;
     107             : 
     108             :         // libjpeg-turbo >= 2.2 supports lossless mode
     109             : #if !defined(D_LOSSLESS_SUPPORTED)
     110        6075 :     if (JPEGDatasetIsJPEGLS(poOpenInfo))
     111             :     {
     112           0 :         return FALSE;
     113             :     }
     114             : #endif
     115             : 
     116             :     // Some files like
     117             :     // http://dionecanali.hd.free.fr/~mdione/mapzen/N65E039.hgt.gz could be
     118             :     // mis-identfied as JPEG
     119       12150 :     CPLString osFilenameLower = CPLString(poOpenInfo->pszFilename).tolower();
     120       12150 :     if (osFilenameLower.endsWith(".hgt") ||
     121       24300 :         osFilenameLower.endsWith(".hgt.gz") ||
     122       12150 :         osFilenameLower.endsWith(".hgt.zip"))
     123             :     {
     124           0 :         return FALSE;
     125             :     }
     126             : 
     127        6075 :     return TRUE;
     128             : }
     129             : 
     130             : /************************************************************************/
     131             : /*                     JPEGDriverSetCommonMetadata()                    */
     132             : /************************************************************************/
     133             : 
     134        1219 : void JPEGDriverSetCommonMetadata(GDALDriver *poDriver)
     135             : {
     136        1219 :     poDriver->SetDescription(DRIVER_NAME);
     137        1219 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     138        1219 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "JPEG JFIF");
     139        1219 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/jpeg.html");
     140        1219 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "jpg");
     141        1219 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSIONS, "jpg jpeg");
     142        1219 :     poDriver->SetMetadataItem(GDAL_DMD_MIMETYPE, "image/jpeg");
     143             : 
     144             : #if defined(JPEG_LIB_MK1_OR_12BIT) || defined(JPEG_DUAL_MODE_8_12)
     145        1219 :     poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, "Byte UInt16");
     146             : #else
     147             :     poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, "Byte");
     148             : #endif
     149        1219 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     150             : 
     151        1219 :     const char *pszOpenOptions =
     152             :         "<OpenOptionList>\n"
     153             :         "   <Option name='USE_INTERNAL_OVERVIEWS' type='boolean' "
     154             :         "description='whether to use implicit internal overviews' "
     155             :         "default='YES'/>\n"
     156             :         "   <Option name='APPLY_ORIENTATION' type='boolean' "
     157             :         "description='whether to take into account EXIF Orientation to "
     158             :         "rotate/flip the image' default='NO'/>\n"
     159             :         "</OpenOptionList>\n";
     160        1219 :     poDriver->SetMetadataItem(GDAL_DMD_OPENOPTIONLIST, pszOpenOptions);
     161             : 
     162             : #ifdef D_LOSSLESS_SUPPORTED
     163             :     // For autotest purposes
     164             :     poDriver->SetMetadataItem("LOSSLESS_JPEG_SUPPORTED", "YES", "JPEG");
     165             : #endif
     166             : 
     167        1219 :     poDriver->pfnIdentify = JPEGDriverIdentify;
     168        1219 :     poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
     169        1219 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATECOPY, "YES");
     170        1219 : }
     171             : 
     172             : /************************************************************************/
     173             : /*                    DeclareDeferredJPEGPlugin()                       */
     174             : /************************************************************************/
     175             : 
     176             : #ifdef PLUGIN_FILENAME
     177             : void DeclareDeferredJPEGPlugin()
     178             : {
     179             :     if (GDALGetDriverByName(DRIVER_NAME) != nullptr)
     180             :     {
     181             :         return;
     182             :     }
     183             :     auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
     184             : #ifdef PLUGIN_INSTALLATION_MESSAGE
     185             :     poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
     186             :                               PLUGIN_INSTALLATION_MESSAGE);
     187             : #endif
     188             :     JPEGDriverSetCommonMetadata(poDriver);
     189             :     GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
     190             : }
     191             : #endif

Generated by: LCOV version 1.14