LCOV - code coverage report
Current view: directory - frmts/jpeg - jpgdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 873 734 84.1 %
Date: 2013-03-30 Functions: 71 53 74.6 %

       1                 : /******************************************************************************
       2                 :  * $Id: jpgdataset.cpp 25505 2013-01-14 23:32:57Z rouault $
       3                 :  *
       4                 :  * Project:  JPEG JFIF Driver
       5                 :  * Purpose:  Implement GDAL JPEG Support based on IJG libjpeg.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2000, Frank Warmerdam
      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 "gdal_pam.h"
      34                 : #include "cpl_string.h"
      35                 : 
      36                 : #include <setjmp.h>
      37                 : 
      38                 : #define TIFF_VERSION            42
      39                 : 
      40                 : #define TIFF_BIGENDIAN          0x4d4d
      41                 : #define TIFF_LITTLEENDIAN       0x4949
      42                 : 
      43                 : /*
      44                 :  * TIFF header.
      45                 :  */
      46                 : typedef struct {
      47                 :         GUInt16  tiff_magic;     /* magic number (defines byte order) */
      48                 :         GUInt16  tiff_version;   /* TIFF version number */
      49                 :         GUInt32  tiff_diroff;    /* byte offset to first directory */
      50                 : } TIFFHeader;
      51                 : 
      52                 : CPL_CVSID("$Id: jpgdataset.cpp 25505 2013-01-14 23:32:57Z rouault $");
      53                 : 
      54                 : CPL_C_START
      55                 : #ifdef LIBJPEG_12_PATH 
      56                 : #  include LIBJPEG_12_PATH
      57                 : #else
      58                 : #  include "jpeglib.h"
      59                 : #endif
      60                 : CPL_C_END
      61                 : 
      62                 : // we believe it is ok to use setjmp() in this situation.
      63                 : #ifdef _MSC_VER
      64                 : #  pragma warning(disable:4611)
      65                 : #endif
      66                 : 
      67                 : #if defined(JPEG_DUAL_MODE_8_12) && !defined(JPGDataset)
      68                 : GDALDataset* JPEGDataset12Open(const char* pszFilename,
      69                 :                                char** papszSiblingFiles,
      70                 :                                int nScaleFactor);
      71                 : GDALDataset* JPEGDataset12CreateCopy( const char * pszFilename,
      72                 :                                     GDALDataset *poSrcDS,
      73                 :                                     int bStrict, char ** papszOptions,
      74                 :                                     GDALProgressFunc pfnProgress,
      75                 :                                     void * pProgressData );
      76                 : #endif
      77                 : 
      78                 : CPL_C_START
      79                 : void  GDALRegister_JPEG(void);
      80                 : CPL_C_END
      81                 : 
      82                 : #include "vsidataio.h"
      83                 : 
      84                 : /*  
      85                 : * Do we want to do special processing suitable for when JSAMPLE is a 
      86                 : * 16bit value?   
      87                 : */ 
      88                 : #if defined(JPEG_LIB_MK1)
      89                 : #  define JPEG_LIB_MK1_OR_12BIT 1
      90                 : #elif BITS_IN_JSAMPLE == 12
      91                 : #  define JPEG_LIB_MK1_OR_12BIT 1
      92                 : #endif
      93                 : 
      94                 : #define Q1table GDALJPEG_Q1table
      95                 : #define Q2table GDALJPEG_Q2table
      96                 : #define Q3table GDALJPEG_Q3table
      97                 : #define Q4table GDALJPEG_Q4table
      98                 : #define Q5table GDALJPEG_Q5table
      99                 : #define AC_BITS GDALJPEG_AC_BITS
     100                 : #define AC_HUFFVAL GDALJPEG_AC_HUFFVAL
     101                 : #define DC_BITS GDALJPEG_DC_BITS
     102                 : #define DC_HUFFVAL GDALJPEG_DC_HUFFVAL
     103                 : 
     104                 : extern const GByte Q1table[64];
     105                 : extern const GByte Q2table[64];
     106                 : extern const GByte Q3table[64];
     107                 : extern const GByte Q4table[64];
     108                 : extern const GByte Q5table[64];
     109                 : extern const GByte AC_BITS[16];
     110                 : extern const GByte AC_HUFFVAL[256];
     111                 : extern const GByte DC_BITS[16];
     112                 : extern const GByte DC_HUFFVAL[256];
     113                 : 
     114                 : class JPGDatasetCommon;
     115                 : GDALRasterBand* JPGCreateBand(JPGDatasetCommon* poDS, int nBand);
     116                 : 
     117                 : CPLErr JPGAppendMask( const char *pszJPGFilename, GDALRasterBand *poMask,
     118                 :                       GDALProgressFunc pfnProgress, void * pProgressData );
     119                 : 
     120                 : /************************************************************************/
     121                 : /* ==================================================================== */
     122                 : /*                         JPGDatasetCommon                             */
     123                 : /* ==================================================================== */
     124                 : /************************************************************************/
     125                 : 
     126                 : class JPGRasterBand;
     127                 : class JPGMaskBand;
     128                 : 
     129                 : class JPGDatasetCommon : public GDALPamDataset
     130                 : {
     131                 : protected:
     132                 :     friend class JPGRasterBand;
     133                 :     friend class JPGMaskBand;
     134                 : 
     135                 :     jmp_buf setjmp_buffer;
     136                 : 
     137                 :     int           nScaleFactor;
     138                 :     int           bHasInitInternalOverviews;
     139                 :     int           nInternalOverviewsCurrent;
     140                 :     int           nInternalOverviewsToFree;
     141                 :     GDALDataset** papoInternalOverviews;
     142                 :     void          InitInternalOverviews();
     143                 : 
     144                 :     char   *pszProjection;
     145                 :     int    bGeoTransformValid;
     146                 :     double adfGeoTransform[6];
     147                 :     int    nGCPCount;
     148                 :     GDAL_GCP *pasGCPList;
     149                 : 
     150                 :     VSILFILE   *fpImage;
     151                 :     int         bOwnFPImage;
     152                 :     GUIntBig nSubfileOffset;
     153                 : 
     154                 :     int    nLoadedScanline;
     155                 :     GByte  *pabyScanline;
     156                 : 
     157                 :     int    bHasReadEXIFMetadata;
     158                 :     int    bHasReadXMPMetadata;
     159                 :     char   **papszMetadata;
     160                 :     char   **papszSubDatasets;
     161                 :     int    bigendian;
     162                 :     int    nExifOffset;
     163                 :     int    nInterOffset;
     164                 :     int    nGPSOffset;
     165                 :     int    bSwabflag;
     166                 :     int    nTiffDirStart;
     167                 :     int    nTIFFHEADER;
     168                 :     int    bHasDoneJpegCreateDecompress;
     169                 :     int    bHasDoneJpegStartDecompress;
     170                 : 
     171                 :     virtual CPLErr LoadScanline(int) = 0;
     172                 :     virtual void   Restart() = 0;
     173                 : 
     174                 :     virtual int GetDataPrecision() = 0;
     175                 :     virtual int GetOutColorSpace() = 0;
     176                 : 
     177                 :     int    EXIFInit(VSILFILE *);
     178                 : 
     179                 :     int    nQLevel;
     180                 : 
     181                 :     void   CheckForMask();
     182                 :     void   DecompressMask();
     183                 : 
     184                 :     void   ReadEXIFMetadata();
     185                 :     void   ReadXMPMetadata();
     186                 : 
     187                 :     int    bHasCheckedForMask;
     188                 :     JPGMaskBand *poMaskBand;
     189                 :     GByte  *pabyBitMask;
     190                 : 
     191                 :     GByte  *pabyCMask;
     192                 :     int    nCMaskSize;
     193                 : 
     194                 :     J_COLOR_SPACE eGDALColorSpace;   /* color space exposed by GDAL. Not necessarily the in_color_space nor */
     195                 :                                      /* the out_color_space of JPEG library */
     196                 : 
     197                 :     int    bIsSubfile;
     198                 :     int    bHasTriedLoadWorldFileOrTab;
     199                 :     void   LoadWorldFileOrTab();
     200                 :     CPLString osWldFilename;
     201                 : 
     202                 :     virtual int         CloseDependentDatasets();
     203                 :     
     204                 :     virtual CPLErr IBuildOverviews( const char *, int, int *,
     205                 :                                     int, int *, GDALProgressFunc, void * );
     206                 : 
     207                 :   public:
     208                 :                  JPGDatasetCommon();
     209                 :                  ~JPGDatasetCommon();
     210                 : 
     211                 :     virtual CPLErr      IRasterIO( GDALRWFlag, int, int, int, int,
     212                 :                                    void *, int, int, GDALDataType,
     213                 :                                    int, int *, int, int, int );
     214                 : 
     215                 :     virtual CPLErr GetGeoTransform( double * );
     216                 : 
     217                 :     virtual int    GetGCPCount();
     218                 :     virtual const char *GetGCPProjection();
     219                 :     virtual const GDAL_GCP *GetGCPs();
     220                 : 
     221                 :     virtual char  **GetMetadata( const char * pszDomain = "" );
     222                 :     virtual const char *GetMetadataItem( const char * pszName,
     223                 :                                          const char * pszDomain = "" );
     224                 : 
     225                 :     virtual char **GetFileList(void);
     226                 : 
     227                 :     static int          Identify( GDALOpenInfo * );
     228                 :     static GDALDataset *Open( GDALOpenInfo * );
     229                 : };
     230                 : 
     231                 : /************************************************************************/
     232                 : /* ==================================================================== */
     233                 : /*                              JPGDataset                              */
     234                 : /* ==================================================================== */
     235                 : /************************************************************************/
     236                 : 
     237                 : class JPGDataset : public JPGDatasetCommon
     238                 : {
     239                 :     struct jpeg_decompress_struct sDInfo;
     240                 :     struct jpeg_error_mgr sJErr;
     241                 : 
     242                 :     virtual CPLErr LoadScanline(int);
     243                 :     virtual void   Restart();
     244             326 :     virtual int GetDataPrecision() { return sDInfo.data_precision; }
     245           16744 :     virtual int GetOutColorSpace() { return sDInfo.out_color_space; }
     246                 : 
     247                 :     void   LoadDefaultTables(int);
     248                 :     void   SetScaleNumAndDenom();
     249                 : 
     250                 :   public:
     251                 :                  JPGDataset();
     252                 :                  ~JPGDataset();
     253                 : 
     254                 :     static GDALDataset *Open( const char* pszFilename,
     255                 :                               char** papszSiblingFiles = NULL,
     256                 :                               int nScaleFactor = 1,
     257                 :                               VSILFILE* fpIn = NULL);
     258                 :     static GDALDataset* CreateCopy( const char * pszFilename,
     259                 :                                     GDALDataset *poSrcDS,
     260                 :                                     int bStrict, char ** papszOptions,
     261                 :                                     GDALProgressFunc pfnProgress,
     262                 :                                     void * pProgressData );
     263                 : 
     264                 :     static void ErrorExit(j_common_ptr cinfo);
     265                 : };
     266                 : 
     267                 : /************************************************************************/
     268                 : /* ==================================================================== */
     269                 : /*                            JPGRasterBand                             */
     270                 : /* ==================================================================== */
     271                 : /************************************************************************/
     272                 : 
     273                 : class JPGRasterBand : public GDALPamRasterBand
     274             317 : {
     275                 :     friend class JPGDatasetCommon;
     276                 : 
     277                 :     /* We have to keep a pointer to the JPGDataset that this JPGRasterBand
     278                 :        belongs to. In some case, we may have this->poGDS != this->poDS
     279                 :        For example for a JPGRasterBand that is set to a NITFDataset...
     280                 :        In other words, this->poDS doesn't necessary point to a JPGDataset
     281                 :        See ticket #1807.
     282                 :     */
     283                 :     JPGDatasetCommon   *poGDS;
     284                 : 
     285                 :   public:
     286                 : 
     287                 :                    JPGRasterBand( JPGDatasetCommon *, int );
     288                 : 
     289                 :     virtual CPLErr IReadBlock( int, int, void * );
     290                 :     virtual GDALColorInterp GetColorInterpretation();
     291                 : 
     292                 :     virtual GDALRasterBand *GetMaskBand();
     293                 :     virtual int             GetMaskFlags();
     294                 :     
     295                 :     virtual GDALRasterBand *GetOverview(int i);
     296                 :     virtual int             GetOverviewCount();
     297                 : };
     298                 : 
     299                 : #if !defined(JPGDataset)
     300                 : 
     301                 : /************************************************************************/
     302                 : /* ==================================================================== */
     303                 : /*                             JPGMaskBand                              */
     304                 : /* ==================================================================== */
     305                 : /************************************************************************/
     306                 : 
     307                 : class JPGMaskBand : public GDALRasterBand
     308               4 : {
     309                 :   protected:
     310                 :     virtual CPLErr IReadBlock( int, int, void * );
     311                 : 
     312                 :   public:
     313                 :     JPGMaskBand( JPGDataset *poDS );
     314                 : };
     315                 : 
     316                 : /************************************************************************/
     317                 : /*                       ReadEXIFMetadata()                             */
     318                 : /************************************************************************/
     319              21 : void JPGDatasetCommon::ReadEXIFMetadata()
     320                 : {
     321              21 :     if (bHasReadEXIFMetadata)
     322               0 :         return;
     323                 : 
     324              21 :     CPLAssert(papszMetadata == NULL);
     325                 : 
     326                 :     /* Save current position to avoid disturbing JPEG stream decoding */
     327              21 :     vsi_l_offset nCurOffset = VSIFTellL(fpImage);
     328                 : 
     329              21 :     if( EXIFInit(fpImage) )
     330                 :     {
     331                 :         EXIFExtractMetadata(papszMetadata,
     332                 :                             fpImage, nTiffDirStart,
     333                 :                             bSwabflag, nTIFFHEADER,
     334               5 :                             nExifOffset, nInterOffset, nGPSOffset);
     335                 : 
     336               5 :         if(nExifOffset  > 0){
     337                 :             EXIFExtractMetadata(papszMetadata,
     338                 :                                 fpImage, nExifOffset,
     339                 :                                 bSwabflag, nTIFFHEADER,
     340               5 :                                 nExifOffset, nInterOffset, nGPSOffset);
     341                 :         }
     342               5 :         if(nInterOffset > 0) {
     343                 :             EXIFExtractMetadata(papszMetadata,
     344                 :                                 fpImage, nInterOffset,
     345                 :                                 bSwabflag, nTIFFHEADER,
     346               0 :                                 nExifOffset, nInterOffset, nGPSOffset);
     347                 :         }
     348               5 :         if(nGPSOffset > 0) {
     349                 :             EXIFExtractMetadata(papszMetadata,
     350                 :                                 fpImage, nGPSOffset,
     351                 :                                 bSwabflag, nTIFFHEADER,
     352               4 :                                 nExifOffset, nInterOffset, nGPSOffset);
     353                 :         }
     354                 : 
     355                 :         /* Avoid setting the PAM dirty bit just for that */
     356               5 :         int nOldPamFlags = nPamFlags;
     357                 : 
     358                 :         /* Append metadata from PAM after EXIF metadata */
     359               5 :         papszMetadata = CSLMerge(papszMetadata, GDALPamDataset::GetMetadata());
     360               5 :         SetMetadata( papszMetadata );
     361                 : 
     362               5 :         nPamFlags = nOldPamFlags;
     363                 :     }
     364                 : 
     365              21 :     VSIFSeekL( fpImage, nCurOffset, SEEK_SET );
     366                 : 
     367              21 :     bHasReadEXIFMetadata = TRUE;
     368                 : }
     369                 : 
     370                 : /************************************************************************/
     371                 : /*                        ReadXMPMetadata()                             */
     372                 : /************************************************************************/
     373                 : 
     374                 : /* See ยง2.1.3 of http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/xmp/pdfs/XMPSpecificationPart3.pdf */
     375                 : 
     376               2 : void JPGDatasetCommon::ReadXMPMetadata()
     377                 : {
     378               2 :     if (bHasReadXMPMetadata)
     379               0 :         return;
     380                 : 
     381                 :     /* Save current position to avoid disturbing JPEG stream decoding */
     382               2 :     vsi_l_offset nCurOffset = VSIFTellL(fpImage);
     383                 : 
     384                 : /* -------------------------------------------------------------------- */
     385                 : /*      Search for APP1 chunk.                                          */
     386                 : /* -------------------------------------------------------------------- */
     387                 :     GByte abyChunkHeader[2+2+29];
     388               2 :     int nChunkLoc = 2;
     389               2 :     int bFoundXMP = FALSE;
     390                 : 
     391               2 :     for( ; TRUE; )
     392                 :     {
     393               4 :         if( VSIFSeekL( fpImage, nChunkLoc, SEEK_SET ) != 0 )
     394               0 :             break;
     395                 : 
     396               4 :         if( VSIFReadL( abyChunkHeader, sizeof(abyChunkHeader), 1, fpImage ) != 1 )
     397               0 :             break;
     398                 : 
     399               8 :         if( abyChunkHeader[0] != 0xFF
     400               4 :             || (abyChunkHeader[1] & 0xf0) != 0xe0 )
     401               1 :             break; // Not an APP chunk.
     402                 : 
     403               3 :         if( abyChunkHeader[1] == 0xe1
     404                 :             && strncmp((const char *) abyChunkHeader + 4,"http://ns.adobe.com/xap/1.0/",28) == 0 )
     405                 :         {
     406               1 :             bFoundXMP = TRUE;
     407               1 :             break; // APP1 - XMP
     408                 :         }
     409                 : 
     410               2 :         nChunkLoc += 2 + abyChunkHeader[2] * 256 + abyChunkHeader[3];
     411                 :     }
     412                 : 
     413               2 :     if (bFoundXMP)
     414                 :     {
     415               1 :         int nXMPLength = abyChunkHeader[2] * 256 + abyChunkHeader[3];
     416               1 :         if (nXMPLength > 2 + 29)
     417                 :         {
     418               1 :             char* pszXMP = (char*)VSIMalloc(nXMPLength - 2 - 29 + 1);
     419               1 :             if (pszXMP)
     420                 :             {
     421               1 :                 if (VSIFReadL( pszXMP, nXMPLength - 2 - 29, 1, fpImage ) == 1)
     422                 :                 {
     423               1 :                     pszXMP[nXMPLength - 2 - 29] = '\0';
     424                 : 
     425                 :                     /* Avoid setting the PAM dirty bit just for that */
     426               1 :                     int nOldPamFlags = nPamFlags;
     427                 : 
     428                 :                     char *apszMDList[2];
     429               1 :                     apszMDList[0] = pszXMP;
     430               1 :                     apszMDList[1] = NULL;
     431               1 :                     SetMetadata(apszMDList, "xml:XMP");
     432                 : 
     433               1 :                     nPamFlags = nOldPamFlags;
     434                 :                 }
     435               1 :                 VSIFree(pszXMP);
     436                 :             }
     437                 :         }
     438                 :     }
     439                 : 
     440               2 :     VSIFSeekL( fpImage, nCurOffset, SEEK_SET );
     441                 : 
     442               2 :     bHasReadXMPMetadata = TRUE;
     443                 : }
     444                 : 
     445                 : /************************************************************************/
     446                 : /*                           GetMetadata()                              */
     447                 : /************************************************************************/
     448              74 : char  **JPGDatasetCommon::GetMetadata( const char * pszDomain )
     449                 : {
     450              74 :     if (fpImage == NULL)
     451               0 :         return NULL;
     452              74 :     if (eAccess == GA_ReadOnly && !bHasReadEXIFMetadata &&
     453                 :         (pszDomain == NULL || EQUAL(pszDomain, "")))
     454              21 :         ReadEXIFMetadata();
     455              74 :     if (eAccess == GA_ReadOnly && !bHasReadXMPMetadata &&
     456                 :         (pszDomain != NULL && EQUAL(pszDomain, "xml:XMP")))
     457               2 :         ReadXMPMetadata();
     458              74 :     return GDALPamDataset::GetMetadata(pszDomain);
     459                 : }
     460                 : 
     461                 : /************************************************************************/
     462                 : /*                       GetMetadataItem()                              */
     463                 : /************************************************************************/
     464             940 : const char *JPGDatasetCommon::GetMetadataItem( const char * pszName,
     465                 :                                          const char * pszDomain )
     466                 : {
     467             940 :     if (fpImage == NULL)
     468               1 :         return NULL;
     469             939 :     if (eAccess == GA_ReadOnly && !bHasReadEXIFMetadata &&
     470                 :         (pszDomain == NULL || EQUAL(pszDomain, "")) &&
     471                 :         pszName != NULL && EQUALN(pszName, "EXIF_", 5))
     472               0 :         ReadEXIFMetadata();
     473             939 :     return GDALPamDataset::GetMetadataItem(pszName, pszDomain);
     474                 : }
     475                 : 
     476                 : /************************************************************************/
     477                 : /*                        EXIFInit()                                    */
     478                 : /*                                                                      */
     479                 : /*           Create Metadata from Information file directory APP1       */
     480                 : /************************************************************************/
     481              21 : int JPGDatasetCommon::EXIFInit(VSILFILE *fp)
     482                 : {
     483              21 :     int           one = 1;
     484                 :     TIFFHeader    hdr;
     485                 :   
     486              21 :     bigendian = (*(char *)&one == 0);
     487                 : 
     488                 : /* -------------------------------------------------------------------- */
     489                 : /*      Search for APP1 chunk.                                          */
     490                 : /* -------------------------------------------------------------------- */
     491                 :     GByte abyChunkHeader[10];
     492              21 :     int nChunkLoc = 2;
     493                 : 
     494              24 :     for( ; TRUE; ) 
     495                 :     {
     496              45 :         if( VSIFSeekL( fp, nChunkLoc, SEEK_SET ) != 0 )
     497               0 :             return FALSE;
     498                 : 
     499              45 :         if( VSIFReadL( abyChunkHeader, sizeof(abyChunkHeader), 1, fp ) != 1 )
     500               0 :             return FALSE;
     501                 : 
     502              90 :         if( abyChunkHeader[0] != 0xFF 
     503              45 :             || (abyChunkHeader[1] & 0xf0) != 0xe0 )
     504              16 :             return FALSE; // Not an APP chunk.
     505                 : 
     506              29 :         if( abyChunkHeader[1] == 0xe1
     507                 :             && strncmp((const char *) abyChunkHeader + 4,"Exif",4) == 0 )
     508                 :         {
     509               5 :             nTIFFHEADER = nChunkLoc + 10;
     510                 :             break; // APP1 - Exif
     511                 :         }
     512                 : 
     513              24 :         nChunkLoc += 2 + abyChunkHeader[2] * 256 + abyChunkHeader[3];
     514                 :     }
     515                 : 
     516                 : /* -------------------------------------------------------------------- */
     517                 : /*      Read TIFF header                                                */
     518                 : /* -------------------------------------------------------------------- */
     519               5 :     VSIFSeekL(fp, nTIFFHEADER, SEEK_SET);
     520               5 :     if(VSIFReadL(&hdr,1,sizeof(hdr),fp) != sizeof(hdr)) 
     521                 :         CPLError( CE_Failure, CPLE_FileIO,
     522                 :                   "Failed to read %d byte from image header.",
     523               0 :                   (int) sizeof(hdr));
     524                 : 
     525               5 :     if (hdr.tiff_magic != TIFF_BIGENDIAN && hdr.tiff_magic != TIFF_LITTLEENDIAN)
     526                 :         CPLError( CE_Failure, CPLE_AppDefined,
     527                 :                   "Not a TIFF file, bad magic number %u (%#x)",
     528               0 :                   hdr.tiff_magic, hdr.tiff_magic);
     529                 : 
     530               5 :     if (hdr.tiff_magic == TIFF_BIGENDIAN)    bSwabflag = !bigendian;
     531               5 :     if (hdr.tiff_magic == TIFF_LITTLEENDIAN) bSwabflag = bigendian;
     532                 : 
     533                 : 
     534               5 :     if (bSwabflag) {
     535               1 :         CPL_SWAP16PTR(&hdr.tiff_version);
     536               1 :         CPL_SWAP32PTR(&hdr.tiff_diroff);
     537                 :     }
     538                 : 
     539                 : 
     540               5 :     if (hdr.tiff_version != TIFF_VERSION)
     541                 :         CPLError(CE_Failure, CPLE_AppDefined,
     542                 :                  "Not a TIFF file, bad version number %u (%#x)",
     543               0 :                  hdr.tiff_version, hdr.tiff_version); 
     544               5 :     nTiffDirStart = hdr.tiff_diroff;
     545                 : 
     546                 :     CPLDebug( "JPEG", "Magic: %#x <%s-endian> Version: %#x\n",
     547                 :               hdr.tiff_magic,
     548                 :               hdr.tiff_magic == TIFF_BIGENDIAN ? "big" : "little",
     549               5 :               hdr.tiff_version );
     550                 : 
     551               5 :     return TRUE;
     552                 : }
     553                 : 
     554                 : /************************************************************************/
     555                 : /*                            JPGMaskBand()                             */
     556                 : /************************************************************************/
     557                 : 
     558               4 : JPGMaskBand::JPGMaskBand( JPGDataset *poDS )
     559                 : 
     560                 : {
     561               4 :     this->poDS = poDS;
     562               4 :     nBand = 0;
     563                 : 
     564               4 :     nRasterXSize = poDS->GetRasterXSize();
     565               4 :     nRasterYSize = poDS->GetRasterYSize();
     566                 : 
     567               4 :     eDataType = GDT_Byte;
     568               4 :     nBlockXSize = nRasterXSize;
     569               4 :     nBlockYSize = 1;
     570               4 : }
     571                 : 
     572                 : /************************************************************************/
     573                 : /*                             IReadBlock()                             */
     574                 : /************************************************************************/
     575                 : 
     576            2048 : CPLErr JPGMaskBand::IReadBlock( int nBlockX, int nBlockY, void *pImage )
     577                 : 
     578                 : {
     579            2048 :     JPGDataset *poJDS = (JPGDataset *) poDS;
     580                 : 
     581                 : /* -------------------------------------------------------------------- */
     582                 : /*      Make sure the mask is loaded and decompressed.                  */
     583                 : /* -------------------------------------------------------------------- */
     584            2048 :     poJDS->DecompressMask();
     585            2048 :     if( poJDS->pabyBitMask == NULL )
     586               0 :         return CE_Failure;
     587                 : 
     588                 : /* -------------------------------------------------------------------- */
     589                 : /*      Set mask based on bitmask for this scanline.                    */
     590                 : /* -------------------------------------------------------------------- */
     591                 :     int iX;
     592            2048 :     GUInt32 iBit = (GUInt32)nBlockY * (GUInt32)nBlockXSize;
     593                 : 
     594         1050624 :     for( iX = 0; iX < nBlockXSize; iX++ )
     595                 :     {
     596         1048576 :         if( poJDS->pabyBitMask[iBit>>3] & (0x1 << (iBit&7)) )
     597          790528 :             ((GByte *) pImage)[iX] = 255;
     598                 :         else
     599          258048 :             ((GByte *) pImage)[iX] = 0;
     600         1048576 :         iBit++;
     601                 :     }
     602                 : 
     603            2048 :     return CE_None;
     604                 : }
     605                 : 
     606                 : /************************************************************************/
     607                 : /*                           JPGRasterBand()                            */
     608                 : /************************************************************************/
     609                 : 
     610             317 : JPGRasterBand::JPGRasterBand( JPGDatasetCommon *poDS, int nBand )
     611                 : 
     612                 : {
     613             317 :     this->poDS = poGDS = poDS;
     614                 : 
     615             317 :     this->nBand = nBand;
     616             317 :     if( poDS->GetDataPrecision() == 12 )
     617              19 :         eDataType = GDT_UInt16;
     618                 :     else
     619             298 :         eDataType = GDT_Byte;
     620                 : 
     621             317 :     nBlockXSize = poDS->nRasterXSize;;
     622             317 :     nBlockYSize = 1;
     623                 : 
     624             317 :     GDALMajorObject::SetMetadataItem("COMPRESSION","JPEG","IMAGE_STRUCTURE");
     625             317 : }
     626                 : 
     627                 : /************************************************************************/
     628                 : /*                           JPGCreateBand()                            */
     629                 : /************************************************************************/
     630                 : 
     631             317 : GDALRasterBand* JPGCreateBand(JPGDatasetCommon* poDS, int nBand)
     632                 : {
     633             317 :     return new JPGRasterBand(poDS, nBand);
     634                 : }
     635                 : 
     636                 : /************************************************************************/
     637                 : /*                             IReadBlock()                             */
     638                 : /************************************************************************/
     639                 : 
     640           41684 : CPLErr JPGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     641                 :                                   void * pImage )
     642                 : 
     643                 : {
     644                 :     CPLErr      eErr;
     645           41684 :     int         nXSize = GetXSize();
     646           41684 :     int         nWordSize = GDALGetDataTypeSize(eDataType) / 8;
     647                 :     
     648           41684 :     CPLAssert( nBlockXOff == 0 );
     649                 : 
     650           41684 :     if (poGDS->fpImage == NULL)
     651                 :     {
     652              70 :         memset( pImage, 0, nXSize * nWordSize );
     653              70 :         return CE_None;
     654                 :     }
     655                 : 
     656                 : /* -------------------------------------------------------------------- */
     657                 : /*      Load the desired scanline into the working buffer.              */
     658                 : /* -------------------------------------------------------------------- */
     659           41614 :     eErr = poGDS->LoadScanline( nBlockYOff );
     660           41614 :     if( eErr != CE_None )
     661               1 :         return eErr;
     662                 : 
     663                 : /* -------------------------------------------------------------------- */
     664                 : /*      Transfer between the working buffer the the callers buffer.     */
     665                 : /* -------------------------------------------------------------------- */
     666           41613 :     if( poGDS->GetRasterCount() == 1 )
     667                 :     {
     668                 : #ifdef JPEG_LIB_MK1_OR_12BIT
     669                 :         GDALCopyWords( poGDS->pabyScanline, GDT_UInt16, 2, 
     670                 :                        pImage, eDataType, nWordSize, 
     671                 :                        nXSize );
     672                 : #else
     673           24669 :         memcpy( pImage, poGDS->pabyScanline, nXSize * nWordSize );
     674                 : #endif
     675                 :     }
     676                 :     else
     677                 :     {
     678                 : #ifdef JPEG_LIB_MK1_OR_12BIT
     679                 :         GDALCopyWords( poGDS->pabyScanline + (nBand-1) * 2, 
     680                 :                        GDT_UInt16, 6, 
     681                 :                        pImage, eDataType, nWordSize, 
     682                 :                        nXSize );
     683                 : #else
     684           33688 :         if (poGDS->eGDALColorSpace == JCS_RGB &&
     685           16744 :             poGDS->GetOutColorSpace() == JCS_CMYK)
     686                 :         {
     687             150 :             CPLAssert(eDataType == GDT_Byte);
     688                 :             int i;
     689             150 :             if (nBand == 1)
     690                 :             {
     691            2550 :                 for(i=0;i<nXSize;i++)
     692                 :                 {
     693            2500 :                     int C = poGDS->pabyScanline[i * 4 + 0];
     694            2500 :                     int K = poGDS->pabyScanline[i * 4 + 3];
     695            2500 :                     ((GByte*)pImage)[i] = (GByte) ((C * K) / 255);
     696                 :                 }
     697                 :             }
     698             100 :             else  if (nBand == 2)
     699                 :             {
     700            2550 :                 for(i=0;i<nXSize;i++)
     701                 :                 {
     702            2500 :                     int M = poGDS->pabyScanline[i * 4 + 1];
     703            2500 :                     int K = poGDS->pabyScanline[i * 4 + 3];
     704            2500 :                     ((GByte*)pImage)[i] = (GByte) ((M * K) / 255);
     705                 :                 }
     706                 :             }
     707              50 :             else if (nBand == 3)
     708                 :             {
     709            2550 :                 for(i=0;i<nXSize;i++)
     710                 :                 {
     711            2500 :                     int Y = poGDS->pabyScanline[i * 4 + 2];
     712            2500 :                     int K = poGDS->pabyScanline[i * 4 + 3];
     713            2500 :                     ((GByte*)pImage)[i] = (GByte) ((Y * K) / 255);
     714                 :                 }
     715                 :             }
     716                 :         }
     717                 :         else
     718                 :         {
     719                 :             GDALCopyWords( poGDS->pabyScanline + (nBand-1) * nWordSize, 
     720                 :                         eDataType, nWordSize * poGDS->GetRasterCount(), 
     721                 :                         pImage, eDataType, nWordSize, 
     722           16794 :                         nXSize );
     723                 :         }
     724                 : #endif
     725                 :     }
     726                 : 
     727                 : /* -------------------------------------------------------------------- */
     728                 : /*      Forceably load the other bands associated with this scanline.   */
     729                 : /* -------------------------------------------------------------------- */
     730           41613 :     if( nBand == 1 )
     731                 :     {
     732                 :         GDALRasterBlock *poBlock;
     733                 : 
     734                 :         int iBand;
     735           40916 :         for(iBand = 2; iBand <= poGDS->GetRasterCount() ; iBand++)
     736                 :         {
     737                 :             poBlock = 
     738           10848 :                 poGDS->GetRasterBand(iBand)->GetLockedBlockRef(nBlockXOff,nBlockYOff);
     739           10848 :             if( poBlock != NULL )
     740           10848 :                 poBlock->DropLock();
     741                 :         }
     742                 :     }
     743                 : 
     744                 : 
     745           41613 :     return CE_None;
     746                 : }
     747                 : 
     748                 : /************************************************************************/
     749                 : /*                       GetColorInterpretation()                       */
     750                 : /************************************************************************/
     751                 : 
     752             111 : GDALColorInterp JPGRasterBand::GetColorInterpretation()
     753                 : 
     754                 : {
     755             111 :     if( poGDS->eGDALColorSpace == JCS_GRAYSCALE )
     756              27 :         return GCI_GrayIndex;
     757                 : 
     758              84 :     else if( poGDS->eGDALColorSpace == JCS_RGB)
     759                 :     {
     760              80 :         if ( nBand == 1 )
     761              29 :             return GCI_RedBand;
     762                 : 
     763              51 :         else if( nBand == 2 )
     764              25 :             return GCI_GreenBand;
     765                 : 
     766                 :         else 
     767              26 :             return GCI_BlueBand;
     768                 :     }
     769               4 :     else if( poGDS->eGDALColorSpace == JCS_CMYK)
     770                 :     {
     771               4 :         if ( nBand == 1 )
     772               1 :             return GCI_CyanBand;
     773                 : 
     774               3 :         else if( nBand == 2 )
     775               1 :             return GCI_MagentaBand;
     776                 : 
     777               2 :         else if ( nBand == 3 )
     778               1 :             return GCI_YellowBand;
     779                 : 
     780                 :         else
     781               1 :             return GCI_BlackBand;
     782                 :     }
     783               0 :     else if( poGDS->eGDALColorSpace == JCS_YCbCr ||
     784                 :              poGDS->eGDALColorSpace == JCS_YCCK)
     785                 :     {
     786               0 :         if ( nBand == 1 )
     787               0 :             return GCI_YCbCr_YBand;
     788                 : 
     789               0 :         else if( nBand == 2 )
     790               0 :             return GCI_YCbCr_CbBand;
     791                 : 
     792               0 :         else if ( nBand == 3 )
     793               0 :             return GCI_YCbCr_CrBand;
     794                 : 
     795                 :         else
     796               0 :             return GCI_BlackBand;
     797                 :     }
     798                 :     else
     799                 :     {
     800               0 :         CPLAssert(0);
     801               0 :         return GCI_Undefined;
     802                 :     }
     803                 : }
     804                 : 
     805                 : /************************************************************************/
     806                 : /*                            GetMaskBand()                             */
     807                 : /************************************************************************/
     808                 : 
     809              55 : GDALRasterBand *JPGRasterBand::GetMaskBand()
     810                 : 
     811                 : {
     812              55 :     if (poGDS->nScaleFactor > 1 )
     813               0 :         return GDALPamRasterBand::GetMaskBand();
     814                 : 
     815              55 :     if (poGDS->fpImage == NULL)
     816               0 :         return NULL;
     817                 : 
     818              55 :     if( !poGDS->bHasCheckedForMask)
     819                 :     {
     820              18 :         poGDS->CheckForMask();
     821              18 :         poGDS->bHasCheckedForMask = TRUE;
     822                 :     }
     823              55 :     if( poGDS->pabyCMask )
     824                 :     {
     825              11 :         if( poGDS->poMaskBand == NULL )
     826               4 :             poGDS->poMaskBand = new JPGMaskBand( (JPGDataset *) poDS );
     827                 : 
     828              11 :         return poGDS->poMaskBand;
     829                 :     }
     830                 :     else
     831              44 :         return GDALPamRasterBand::GetMaskBand();
     832                 : }
     833                 : 
     834                 : /************************************************************************/
     835                 : /*                            GetMaskFlags()                            */
     836                 : /************************************************************************/
     837                 : 
     838              50 : int JPGRasterBand::GetMaskFlags()
     839                 : 
     840                 : {
     841              50 :     if (poGDS->nScaleFactor > 1 )
     842               0 :         return GDALPamRasterBand::GetMaskFlags();
     843                 : 
     844              50 :     if (poGDS->fpImage == NULL)
     845               0 :         return 0;
     846                 : 
     847              50 :     GetMaskBand();
     848              50 :     if( poGDS->poMaskBand != NULL )
     849               7 :         return GMF_PER_DATASET;
     850                 :     else
     851              43 :         return GDALPamRasterBand::GetMaskFlags();
     852                 : }
     853                 : 
     854                 : /************************************************************************/
     855                 : /*                            GetOverview()                             */
     856                 : /************************************************************************/
     857                 : 
     858              22 : GDALRasterBand* JPGRasterBand::GetOverview(int i)
     859                 : {
     860              22 :     poGDS->InitInternalOverviews();
     861                 : 
     862              22 :     if( poGDS->nInternalOverviewsCurrent == 0 )
     863              14 :         return GDALPamRasterBand::GetOverview(i);
     864                 : 
     865               8 :     if( i < 0 || i >= poGDS->nInternalOverviewsCurrent )
     866               2 :         return NULL;
     867                 :     else
     868               6 :         return poGDS->papoInternalOverviews[i]->GetRasterBand(nBand);
     869                 : }
     870                 : 
     871                 : /************************************************************************/
     872                 : /*                         GetOverviewCount()                           */
     873                 : /************************************************************************/
     874                 : 
     875              42 : int JPGRasterBand::GetOverviewCount()
     876                 : {
     877              42 :     poGDS->InitInternalOverviews();
     878                 : 
     879              42 :     if( poGDS->nInternalOverviewsCurrent == 0 )
     880              38 :         return GDALPamRasterBand::GetOverviewCount();
     881                 : 
     882               4 :     return poGDS->nInternalOverviewsCurrent;
     883                 : }
     884                 : 
     885                 : /************************************************************************/
     886                 : /* ==================================================================== */
     887                 : /*                             JPGDataset                               */
     888                 : /* ==================================================================== */
     889                 : /************************************************************************/
     890                 : 
     891             204 : JPGDatasetCommon::JPGDatasetCommon()
     892                 : 
     893                 : {
     894             204 :     fpImage = NULL;
     895             204 :     bOwnFPImage = FALSE;
     896                 : 
     897             204 :     nScaleFactor = 1;
     898             204 :     bHasInitInternalOverviews = FALSE;
     899             204 :     nInternalOverviewsCurrent = 0;
     900             204 :     nInternalOverviewsToFree = 0;
     901             204 :     papoInternalOverviews = NULL;
     902                 : 
     903             204 :     pabyScanline = NULL;
     904             204 :     nLoadedScanline = -1;
     905                 : 
     906             204 :     bHasReadEXIFMetadata = FALSE;
     907             204 :     bHasReadXMPMetadata = FALSE;
     908             204 :     papszMetadata   = NULL;
     909             204 :     papszSubDatasets= NULL;
     910             204 :     nExifOffset     = -1;
     911             204 :     nInterOffset    = -1;
     912             204 :     nGPSOffset      = -1;
     913                 : 
     914             204 :     pszProjection = NULL;
     915             204 :     bGeoTransformValid = FALSE;
     916             204 :     adfGeoTransform[0] = 0.0;
     917             204 :     adfGeoTransform[1] = 1.0;
     918             204 :     adfGeoTransform[2] = 0.0;
     919             204 :     adfGeoTransform[3] = 0.0;
     920             204 :     adfGeoTransform[4] = 0.0;
     921             204 :     adfGeoTransform[5] = 1.0;
     922             204 :     nGCPCount = 0;
     923             204 :     pasGCPList = NULL;
     924                 : 
     925             204 :     bHasDoneJpegCreateDecompress = FALSE;
     926             204 :     bHasDoneJpegStartDecompress = FALSE;
     927                 : 
     928             204 :     bHasCheckedForMask = FALSE;
     929             204 :     poMaskBand = NULL;
     930             204 :     pabyBitMask = NULL;
     931             204 :     pabyCMask = NULL;
     932             204 :     nCMaskSize = 0;
     933                 : 
     934             204 :     eGDALColorSpace = JCS_UNKNOWN;
     935                 : 
     936             204 :     bIsSubfile = FALSE;
     937             204 :     bHasTriedLoadWorldFileOrTab = FALSE;
     938             204 : }
     939                 : 
     940                 : /************************************************************************/
     941                 : /*                           ~JPGDataset()                              */
     942                 : /************************************************************************/
     943                 : 
     944             204 : JPGDatasetCommon::~JPGDatasetCommon()
     945                 : 
     946                 : {
     947             204 :     if( bOwnFPImage && fpImage != NULL )
     948             202 :         VSIFCloseL( fpImage );
     949                 : 
     950             204 :     if( pabyScanline != NULL )
     951             103 :         CPLFree( pabyScanline );
     952             204 :     if( papszMetadata != NULL )
     953               5 :       CSLDestroy( papszMetadata );
     954                 : 
     955             204 :     if ( pszProjection )
     956               0 :         CPLFree( pszProjection );
     957                 : 
     958             204 :     if ( nGCPCount > 0 )
     959                 :     {
     960               0 :         GDALDeinitGCPs( nGCPCount, pasGCPList );
     961               0 :         CPLFree( pasGCPList );
     962                 :     }
     963                 : 
     964             204 :     CPLFree( pabyBitMask );
     965             204 :     CPLFree( pabyCMask );
     966             204 :     delete poMaskBand;
     967                 : 
     968             204 :     CloseDependentDatasets();
     969             204 : }
     970                 : 
     971                 : /************************************************************************/
     972                 : /*                       CloseDependentDatasets()                       */
     973                 : /************************************************************************/
     974                 : 
     975             204 : int JPGDatasetCommon::CloseDependentDatasets()
     976                 : {
     977             204 :     int bRet = GDALPamDataset::CloseDependentDatasets();
     978             204 :     if( nInternalOverviewsToFree )
     979                 :     {
     980               5 :         bRet = TRUE;
     981              12 :         for(int i = 0; i < nInternalOverviewsToFree; i++)
     982               7 :             delete papoInternalOverviews[i];
     983               5 :         CPLFree(papoInternalOverviews);
     984               5 :         papoInternalOverviews = NULL;
     985               5 :         nInternalOverviewsToFree = 0;
     986                 :     }
     987             204 :     return bRet;
     988                 : }
     989                 : 
     990                 : /************************************************************************/
     991                 : /*                       InitInternalOverviews()                        */
     992                 : /************************************************************************/
     993                 : 
     994              64 : void JPGDatasetCommon::InitInternalOverviews()
     995                 : {
     996              64 :     if( bHasInitInternalOverviews )
     997              53 :         return;
     998              11 :     bHasInitInternalOverviews = TRUE;
     999                 : 
    1000                 : /* -------------------------------------------------------------------- */
    1001                 : /*      Instanciate on-the-fly overviews (if no external ones).         */
    1002                 : /* -------------------------------------------------------------------- */
    1003              11 :     if( nScaleFactor == 1 && GetRasterBand(1)->GetOverviewCount() == 0 )
    1004                 :     {
    1005                 :         /* libjpeg-6b only suppports 2, 4 and 8 scale denominators */
    1006                 :         /* TODO: Later versions support more */
    1007                 : 
    1008                 :         int i;
    1009              10 :         int nInternalOverviews = 0;
    1010                 : 
    1011              33 :         for(i = 2; i >= 0; i--)
    1012                 :         {
    1013              28 :             if( nRasterXSize >= (256 << i) || nRasterYSize >= (256 << i) )
    1014                 :             {
    1015               5 :                 nInternalOverviews = i + 1;
    1016               5 :                 break;
    1017                 :             }
    1018                 :         }
    1019                 : 
    1020              10 :         if( nInternalOverviews > 0 )
    1021                 :         {
    1022                 :             papoInternalOverviews = (GDALDataset**)
    1023               5 :                     CPLMalloc(nInternalOverviews * sizeof(GDALDataset*));
    1024              12 :             for(i = 0; i < nInternalOverviews; i++ )
    1025                 :             {
    1026               7 :                 papoInternalOverviews[i] =
    1027               7 :                     JPGDataset::Open(GetDescription(), NULL, 1 << (i + 1));
    1028               7 :                 if( papoInternalOverviews[i] == NULL )
    1029                 :                 {
    1030               0 :                     nInternalOverviews = i;
    1031               0 :                     break;
    1032                 :                 }
    1033                 :             }
    1034                 : 
    1035               5 :             nInternalOverviewsCurrent = nInternalOverviewsToFree = nInternalOverviews;
    1036                 :         }
    1037                 :     }
    1038                 : }
    1039                 : 
    1040                 : /************************************************************************/
    1041                 : /*                          IBuildOverviews()                           */
    1042                 : /************************************************************************/
    1043                 : 
    1044               1 : CPLErr JPGDatasetCommon::IBuildOverviews( const char *pszResampling, 
    1045                 :                                           int nOverviewsListCount,
    1046                 :                                           int *panOverviewList, 
    1047                 :                                           int nListBands, int *panBandList,
    1048                 :                                           GDALProgressFunc pfnProgress, 
    1049                 :                                           void * pProgressData )
    1050                 : {
    1051                 :     CPLErr eErr;
    1052                 : 
    1053               1 :     bHasInitInternalOverviews = TRUE;
    1054               1 :     nInternalOverviewsCurrent = 0;
    1055                 : 
    1056                 :     eErr = GDALPamDataset::IBuildOverviews(pszResampling,
    1057                 :                                            nOverviewsListCount,
    1058                 :                                            panOverviewList,
    1059                 :                                            nListBands, panBandList,
    1060               1 :                                            pfnProgress, pProgressData);
    1061                 : 
    1062               1 :     return eErr;
    1063                 : }
    1064                 : 
    1065                 : #endif // !defined(JPGDataset)
    1066                 : 
    1067                 : /************************************************************************/
    1068                 : /*                            JPGDataset()                              */
    1069                 : /************************************************************************/
    1070                 : 
    1071             204 : JPGDataset::JPGDataset()
    1072                 : 
    1073                 : {
    1074             204 :     sDInfo.data_precision = 8;
    1075             204 : }
    1076                 : 
    1077                 : /************************************************************************/
    1078                 : /*                           ~JPGDataset()                            */
    1079                 : /************************************************************************/
    1080                 : 
    1081             204 : JPGDataset::~JPGDataset()
    1082                 : 
    1083                 : {
    1084             204 :     FlushCache();
    1085                 : 
    1086             204 :     if (bHasDoneJpegStartDecompress)
    1087                 :     {
    1088             103 :         jpeg_abort_decompress( &sDInfo );
    1089                 :     }
    1090             204 :     if (bHasDoneJpegCreateDecompress)
    1091                 :     {
    1092             202 :         jpeg_destroy_decompress( &sDInfo );
    1093                 :     }
    1094             204 : }
    1095                 : 
    1096                 : /************************************************************************/
    1097                 : /*                            LoadScanline()                            */
    1098                 : /************************************************************************/
    1099                 : 
    1100           41614 : CPLErr JPGDataset::LoadScanline( int iLine )
    1101                 : 
    1102                 : {
    1103           41614 :     if( nLoadedScanline == iLine )
    1104           10667 :         return CE_None;
    1105                 : 
    1106                 :     // setup to trap a fatal error.
    1107           30947 :     if (setjmp(setjmp_buffer)) 
    1108               1 :         return CE_Failure;
    1109                 : 
    1110           30947 :     if (!bHasDoneJpegStartDecompress)
    1111                 :     {
    1112             104 :         jpeg_start_decompress( &sDInfo );
    1113             103 :         bHasDoneJpegStartDecompress = TRUE;
    1114                 :     }
    1115                 : 
    1116           30946 :     if( pabyScanline == NULL )
    1117                 :     {
    1118             103 :         int nJPEGBands = 0;
    1119             103 :         switch(sDInfo.out_color_space)
    1120                 :         {
    1121                 :             case JCS_GRAYSCALE:
    1122              65 :                 nJPEGBands = 1;
    1123              65 :                 break;
    1124                 :             case JCS_RGB:
    1125                 :             case JCS_YCbCr:
    1126              36 :                 nJPEGBands = 3;
    1127              36 :                 break;
    1128                 :             case JCS_CMYK:
    1129                 :             case JCS_YCCK:
    1130               2 :                 nJPEGBands = 4;
    1131               2 :                 break;
    1132                 : 
    1133                 :             default:
    1134               0 :                 CPLAssert(0);
    1135                 :         }
    1136                 : 
    1137                 :         pabyScanline = (GByte *)
    1138             103 :             CPLMalloc(nJPEGBands * GetRasterXSize() * 2);
    1139                 :     }
    1140                 : 
    1141           30946 :     if( iLine < nLoadedScanline )
    1142               4 :         Restart();
    1143                 :         
    1144           94451 :     while( nLoadedScanline < iLine )
    1145                 :     {
    1146                 :         JSAMPLE *ppSamples;
    1147                 :             
    1148           32559 :         ppSamples = (JSAMPLE *) pabyScanline;
    1149           32559 :         jpeg_read_scanlines( &sDInfo, &ppSamples, 1 );
    1150           32559 :         nLoadedScanline++;
    1151                 :     }
    1152                 : 
    1153           30946 :     return CE_None;
    1154                 : }
    1155                 : 
    1156                 : /************************************************************************/
    1157                 : /*                         LoadDefaultTables()                          */
    1158                 : /************************************************************************/
    1159                 : 
    1160                 : #if !defined(JPGDataset)
    1161                 : 
    1162                 : const GByte Q1table[64] =
    1163                 : {
    1164                 :    8,    72,  72,  72,  72,  72,  72,  72, // 0 - 7
    1165                 :     72,   72,  78,  74,  76,  74,  78,  89, // 8 - 15
    1166                 :     81,   84,  84,  81,  89, 106,  93,  94, // 16 - 23
    1167                 :     99,   94,  93, 106, 129, 111, 108, 116, // 24 - 31
    1168                 :     116, 108, 111, 129, 135, 128, 136, 145, // 32 - 39
    1169                 :     136, 128, 135, 155, 160, 177, 177, 160, // 40 - 47
    1170                 :     155, 193, 213, 228, 213, 193, 255, 255, // 48 - 55
    1171                 :     255, 255, 255, 255, 255, 255, 255, 255  // 56 - 63
    1172                 : };
    1173                 : 
    1174                 : const GByte Q2table[64] =
    1175                 : {
    1176                 :     8, 36, 36, 36,
    1177                 :     36, 36, 36, 36, 36, 36, 39, 37, 38, 37, 39, 45, 41, 42, 42, 41, 45, 53,
    1178                 :     47, 47, 50, 47, 47, 53, 65, 56, 54, 59, 59, 54, 56, 65, 68, 64, 69, 73,
    1179                 :     69, 64, 68, 78, 81, 89, 89, 81, 78, 98,108,115,108, 98,130,144,144,130,
    1180                 :     178,190,178,243,243,255
    1181                 : };
    1182                 : 
    1183                 : const GByte Q3table[64] =
    1184                 : {
    1185                 :      8, 10, 10, 10,
    1186                 :     10, 10, 10, 10, 10, 10, 11, 10, 11, 10, 11, 13, 11, 12, 12, 11, 13, 15, 
    1187                 :     13, 13, 14, 13, 13, 15, 18, 16, 15, 16, 16, 15, 16, 18, 19, 18, 19, 21, 
    1188                 :     19, 18, 19, 22, 23, 25, 25, 23, 22, 27, 30, 32, 30, 27, 36, 40, 40, 36, 
    1189                 :     50, 53, 50, 68, 68, 91 
    1190                 : }; 
    1191                 : 
    1192                 : const GByte Q4table[64] =
    1193                 : {
    1194                 :     8, 7, 7, 7,
    1195                 :     7, 7, 7, 7, 7, 7, 8, 7, 8, 7, 8, 9, 8, 8, 8, 8, 9, 11, 
    1196                 :     9, 9, 10, 9, 9, 11, 13, 11, 11, 12, 12, 11, 11, 13, 14, 13, 14, 15, 
    1197                 :     14, 13, 14, 16, 16, 18, 18, 16, 16, 20, 22, 23, 22, 20, 26, 29, 29, 26, 
    1198                 :     36, 38, 36, 49, 49, 65
    1199                 : };
    1200                 : 
    1201                 : const GByte Q5table[64] =
    1202                 : {
    1203                 :     4, 4, 4, 4, 
    1204                 :     4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6,
    1205                 :     5, 5, 6, 5, 5, 6, 7, 6, 6, 6, 6, 6, 6, 7, 8, 7, 8, 8, 
    1206                 :     8, 7, 8, 9, 9, 10, 10, 9, 9, 11, 12, 13, 12, 11, 14, 16, 16, 14, 
    1207                 :     20, 21, 20, 27, 27, 36
    1208                 : };
    1209                 : 
    1210                 : const GByte AC_BITS[16] =
    1211                 : { 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 125 };
    1212                 : 
    1213                 : const GByte AC_HUFFVAL[256] = {
    1214                 :     0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,          
    1215                 :     0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
    1216                 :     0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08,
    1217                 :     0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0,
    1218                 :     0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16,
    1219                 :     0x17, 0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28,
    1220                 :     0x29, 0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
    1221                 :     0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
    1222                 :     0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
    1223                 :     0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
    1224                 :     0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
    1225                 :     0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
    1226                 :     0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
    1227                 :     0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
    1228                 :     0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6,
    1229                 :     0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5,
    1230                 :     0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4,
    1231                 :     0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2,
    1232                 :     0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA,
    1233                 :     0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
    1234                 :     0xF9, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    1235                 :     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    1236                 :     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    1237                 :     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    1238                 :     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    1239                 :     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    1240                 :     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    1241                 :     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    1242                 :     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    1243                 :     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
    1244                 : 
    1245                 : const GByte DC_BITS[16] =
    1246                 : { 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
    1247                 : 
    1248                 : const GByte DC_HUFFVAL[256] = {
    1249                 :     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
    1250                 :     0x08, 0x09, 0x0A, 0x0B };
    1251                 : 
    1252                 : #endif // !defined(JPGDataset)
    1253                 : 
    1254             824 : void JPGDataset::LoadDefaultTables( int n )
    1255                 : {
    1256             824 :     if( nQLevel < 1 )
    1257             820 :         return;
    1258                 : 
    1259                 : /* -------------------------------------------------------------------- */
    1260                 : /*      Load quantization table           */
    1261                 : /* -------------------------------------------------------------------- */
    1262                 :     int i;
    1263                 :     JQUANT_TBL  *quant_ptr;
    1264                 :     const GByte *pabyQTable;
    1265                 : 
    1266               4 :     if( nQLevel == 1 )
    1267               4 :         pabyQTable = Q1table;
    1268               0 :     else if( nQLevel == 2 )
    1269               0 :         pabyQTable = Q2table;
    1270               0 :     else if( nQLevel == 3 )
    1271               0 :         pabyQTable = Q3table;
    1272               0 :     else if( nQLevel == 4 )
    1273               0 :         pabyQTable = Q4table;
    1274               0 :     else if( nQLevel == 5 )
    1275               0 :         pabyQTable = Q5table;
    1276                 :     else
    1277               0 :         return;
    1278                 : 
    1279               4 :     if (sDInfo.quant_tbl_ptrs[n] == NULL)
    1280               4 :         sDInfo.quant_tbl_ptrs[n] = 
    1281               4 :             jpeg_alloc_quant_table((j_common_ptr) &(sDInfo));
    1282                 :     
    1283               4 :     quant_ptr = sDInfo.quant_tbl_ptrs[n]; /* quant_ptr is JQUANT_TBL* */
    1284             260 :     for (i = 0; i < 64; i++) {
    1285                 :         /* Qtable[] is desired quantization table, in natural array order */
    1286             256 :         quant_ptr->quantval[i] = pabyQTable[i];
    1287                 :     }
    1288                 : 
    1289                 : /* -------------------------------------------------------------------- */
    1290                 : /*      Load AC huffman table.                                          */
    1291                 : /* -------------------------------------------------------------------- */
    1292                 :     JHUFF_TBL  *huff_ptr;
    1293                 : 
    1294               4 :     if (sDInfo.ac_huff_tbl_ptrs[n] == NULL)
    1295               4 :         sDInfo.ac_huff_tbl_ptrs[n] =
    1296               4 :             jpeg_alloc_huff_table((j_common_ptr)&sDInfo);
    1297                 : 
    1298               4 :     huff_ptr = sDInfo.ac_huff_tbl_ptrs[n];  /* huff_ptr is JHUFF_TBL* */
    1299                 : 
    1300              68 :     for (i = 1; i <= 16; i++) {
    1301                 :         /* counts[i] is number of Huffman codes of length i bits, i=1..16 */
    1302              64 :         huff_ptr->bits[i] = AC_BITS[i-1];
    1303                 :     }
    1304                 : 
    1305            1028 :     for (i = 0; i < 256; i++) {
    1306                 :         /* symbols[] is the list of Huffman symbols, in code-length order */
    1307            1024 :         huff_ptr->huffval[i] = AC_HUFFVAL[i];
    1308                 :     }
    1309                 : 
    1310                 : /* -------------------------------------------------------------------- */
    1311                 : /*      Load DC huffman table.                                          */
    1312                 : /* -------------------------------------------------------------------- */
    1313               4 :     if (sDInfo.dc_huff_tbl_ptrs[n] == NULL)
    1314               4 :         sDInfo.dc_huff_tbl_ptrs[n] =
    1315               4 :             jpeg_alloc_huff_table((j_common_ptr)&sDInfo);
    1316                 : 
    1317               4 :     huff_ptr = sDInfo.dc_huff_tbl_ptrs[n];  /* huff_ptr is JHUFF_TBL* */
    1318                 : 
    1319              68 :     for (i = 1; i <= 16; i++) {
    1320                 :         /* counts[i] is number of Huffman codes of length i bits, i=1..16 */
    1321              64 :         huff_ptr->bits[i] = DC_BITS[i-1];
    1322                 :     }
    1323                 : 
    1324            1028 :     for (i = 0; i < 256; i++) {
    1325                 :         /* symbols[] is the list of Huffman symbols, in code-length order */
    1326            1024 :         huff_ptr->huffval[i] = DC_HUFFVAL[i];
    1327                 :     }
    1328                 : 
    1329                 : }
    1330                 : 
    1331                 : /************************************************************************/
    1332                 : /*                       SetScaleNumAndDenom()                          */
    1333                 : /************************************************************************/
    1334                 : 
    1335             188 : void JPGDataset::SetScaleNumAndDenom()
    1336                 : {
    1337                 : #if JPEG_LIB_VERSION > 62
    1338                 :     sDInfo.scale_num = 8 / nScaleFactor;
    1339                 :     sDInfo.scale_denom = 8;
    1340                 : #else
    1341             188 :     sDInfo.scale_num = 1;
    1342             188 :     sDInfo.scale_denom = nScaleFactor;
    1343                 : #endif
    1344             188 : }
    1345                 : 
    1346                 : /************************************************************************/
    1347                 : /*                              Restart()                               */
    1348                 : /*                                                                      */
    1349                 : /*      Restart compressor at the beginning of the file.                */
    1350                 : /************************************************************************/
    1351                 : 
    1352               4 : void JPGDataset::Restart()
    1353                 : 
    1354                 : {
    1355               4 :     J_COLOR_SPACE colorSpace = sDInfo.out_color_space;
    1356                 : 
    1357               4 :     jpeg_abort_decompress( &sDInfo );
    1358               4 :     jpeg_destroy_decompress( &sDInfo );
    1359               4 :     jpeg_create_decompress( &sDInfo );
    1360                 : 
    1361               4 :     LoadDefaultTables( 0 );
    1362               4 :     LoadDefaultTables( 1 );
    1363               4 :     LoadDefaultTables( 2 );
    1364               4 :     LoadDefaultTables( 3 );
    1365                 : 
    1366                 : /* -------------------------------------------------------------------- */
    1367                 : /*      restart io.                                                     */
    1368                 : /* -------------------------------------------------------------------- */
    1369               4 :     VSIFSeekL( fpImage, nSubfileOffset, SEEK_SET );
    1370                 : 
    1371               4 :     jpeg_vsiio_src( &sDInfo, fpImage );
    1372               4 :     jpeg_read_header( &sDInfo, TRUE );
    1373                 : 
    1374               4 :     sDInfo.out_color_space = colorSpace;
    1375               4 :     nLoadedScanline = -1;
    1376               4 :     SetScaleNumAndDenom();
    1377               4 :     jpeg_start_decompress( &sDInfo );
    1378               4 :     bHasDoneJpegStartDecompress = TRUE;
    1379               4 : }
    1380                 : 
    1381                 : #if !defined(JPGDataset)
    1382                 : 
    1383                 : /************************************************************************/
    1384                 : /*                          GetGeoTransform()                           */
    1385                 : /************************************************************************/
    1386                 : 
    1387              31 : CPLErr JPGDatasetCommon::GetGeoTransform( double * padfTransform )
    1388                 : 
    1389                 : {
    1390              31 :     LoadWorldFileOrTab();
    1391                 : 
    1392              31 :     if( bGeoTransformValid )
    1393                 :     {
    1394               3 :         memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
    1395                 :         
    1396               3 :         return CE_None;
    1397                 :     }
    1398                 :     else 
    1399              28 :         return GDALPamDataset::GetGeoTransform( padfTransform );
    1400                 : }
    1401                 : 
    1402                 : /************************************************************************/
    1403                 : /*                            GetGCPCount()                             */
    1404                 : /************************************************************************/
    1405                 : 
    1406              20 : int JPGDatasetCommon::GetGCPCount()
    1407                 : 
    1408                 : {
    1409              20 :     LoadWorldFileOrTab();
    1410                 : 
    1411              20 :     return nGCPCount;
    1412                 : }
    1413                 : 
    1414                 : /************************************************************************/
    1415                 : /*                          GetGCPProjection()                          */
    1416                 : /************************************************************************/
    1417                 : 
    1418               0 : const char *JPGDatasetCommon::GetGCPProjection()
    1419                 : 
    1420                 : {
    1421               0 :     LoadWorldFileOrTab();
    1422                 : 
    1423               0 :     if( pszProjection && nGCPCount > 0 )
    1424               0 :         return pszProjection;
    1425                 :     else
    1426               0 :         return "";
    1427                 : }
    1428                 : 
    1429                 : /************************************************************************/
    1430                 : /*                               GetGCPs()                              */
    1431                 : /************************************************************************/
    1432                 : 
    1433               0 : const GDAL_GCP *JPGDatasetCommon::GetGCPs()
    1434                 : 
    1435                 : {
    1436               0 :     LoadWorldFileOrTab();
    1437                 : 
    1438               0 :     return pasGCPList;
    1439                 : }
    1440                 : 
    1441                 : /************************************************************************/
    1442                 : /*                             IRasterIO()                              */
    1443                 : /*                                                                      */
    1444                 : /*      Checks for what might be the most common read case              */
    1445                 : /*      (reading an entire interleaved, 8bit, RGB JPEG), and            */
    1446                 : /*      optimizes for that case                                         */
    1447                 : /************************************************************************/
    1448                 : 
    1449             865 : CPLErr JPGDatasetCommon::IRasterIO( GDALRWFlag eRWFlag,
    1450                 :                               int nXOff, int nYOff, int nXSize, int nYSize,
    1451                 :                               void *pData, int nBufXSize, int nBufYSize, 
    1452                 :                               GDALDataType eBufType,
    1453                 :                               int nBandCount, int *panBandMap, 
    1454                 :                               int nPixelSpace, int nLineSpace, int nBandSpace )
    1455                 : 
    1456                 : {
    1457             874 :     if((eRWFlag == GF_Read) &&
    1458                 :        (nBandCount == 3) &&
    1459                 :        (nBands == 3) &&
    1460                 :        (nXOff == 0) && (nXOff == 0) &&
    1461                 :        (nXSize == nBufXSize) && (nXSize == nRasterXSize) &&
    1462                 :        (nYSize == nBufYSize) && (nYSize == nRasterYSize) &&
    1463               9 :        (eBufType == GDT_Byte) && (GetDataPrecision() != 12) &&
    1464                 :        /*(nPixelSpace >= 3)*/(nPixelSpace > 3) &&
    1465                 :        (nLineSpace == (nPixelSpace*nXSize)) &&
    1466                 :        (nBandSpace == 1) &&
    1467                 :        (pData != NULL) &&
    1468                 :        (panBandMap != NULL) &&
    1469               0 :        (panBandMap[0] == 1) && (panBandMap[1] == 2) && (panBandMap[2] == 3))
    1470                 :     {
    1471               0 :         Restart();
    1472                 :         int y;
    1473                 :         CPLErr tmpError;
    1474                 :         int x;
    1475                 : 
    1476                 :         // handles copy with padding case
    1477               0 :         for(y = 0; y < nYSize; ++y)
    1478                 :         {
    1479               0 :             tmpError = LoadScanline(y);
    1480               0 :             if(tmpError != CE_None) return tmpError;
    1481                 : 
    1482               0 :             for(x = 0; x < nXSize; ++x)
    1483                 :             {
    1484               0 :                 tmpError = LoadScanline(y);
    1485               0 :                 if(tmpError != CE_None) return tmpError;
    1486                 :                 memcpy(&(((GByte*)pData)[(y*nLineSpace) + (x*nPixelSpace)]), 
    1487               0 :                        (const GByte*)&(pabyScanline[x*3]), 3);
    1488                 :             }
    1489                 :         }
    1490                 : 
    1491               0 :         return CE_None;
    1492                 :     }
    1493                 : 
    1494                 :     return GDALPamDataset::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
    1495                 :                                      pData, nBufXSize, nBufYSize, eBufType, 
    1496                 :                                      nBandCount, panBandMap, 
    1497             865 :                                      nPixelSpace, nLineSpace, nBandSpace);
    1498                 : }
    1499                 : 
    1500                 : #if JPEG_LIB_VERSION_MAJOR < 9
    1501                 : /************************************************************************/
    1502                 : /*                    JPEGDatasetIsJPEGLS()                             */
    1503                 : /************************************************************************/
    1504                 : 
    1505              75 : static int JPEGDatasetIsJPEGLS( GDALOpenInfo * poOpenInfo )
    1506                 : 
    1507                 : {
    1508              75 :     GByte  *pabyHeader = poOpenInfo->pabyHeader;
    1509              75 :     int    nHeaderBytes = poOpenInfo->nHeaderBytes;
    1510                 : 
    1511              75 :     if( nHeaderBytes < 10 )
    1512               0 :         return FALSE;
    1513                 : 
    1514             150 :     if( pabyHeader[0] != 0xff
    1515              75 :         || pabyHeader[1] != 0xd8 )
    1516               0 :         return FALSE;
    1517                 : 
    1518              75 :     int nOffset = 2;
    1519             684 :     for (;nOffset + 4 < nHeaderBytes;)
    1520                 :     {
    1521             601 :         if (pabyHeader[nOffset] != 0xFF)
    1522              67 :             return FALSE;
    1523                 : 
    1524             534 :         int nMarker = pabyHeader[nOffset + 1];
    1525             534 :         if (nMarker == 0xF7 /* JPEG Extension 7, JPEG-LS */)
    1526               0 :             return TRUE;
    1527             534 :         if (nMarker == 0xF8 /* JPEG Extension 8, JPEG-LS Extension */)
    1528               0 :             return TRUE;
    1529             534 :         if (nMarker == 0xC3 /* Start of Frame 3 */)
    1530               0 :             return TRUE;
    1531             534 :         if (nMarker == 0xC7 /* Start of Frame 7 */)
    1532               0 :             return TRUE;
    1533             534 :         if (nMarker == 0xCB /* Start of Frame 11 */)
    1534               0 :             return TRUE;
    1535             534 :         if (nMarker == 0xCF /* Start of Frame 15 */)
    1536               0 :             return TRUE;
    1537                 : 
    1538             534 :         nOffset += 2 + pabyHeader[nOffset + 2] * 256 + pabyHeader[nOffset + 3];
    1539                 :     }
    1540                 : 
    1541               8 :     return FALSE;
    1542                 : }
    1543                 : #endif
    1544                 : 
    1545                 : /************************************************************************/
    1546                 : /*                              Identify()                              */
    1547                 : /************************************************************************/
    1548                 : 
    1549           14033 : int JPGDatasetCommon::Identify( GDALOpenInfo * poOpenInfo )
    1550                 : 
    1551                 : {
    1552           14033 :     GByte  *pabyHeader = NULL;
    1553           14033 :     int    nHeaderBytes = poOpenInfo->nHeaderBytes;
    1554                 : 
    1555                 : /* -------------------------------------------------------------------- */
    1556                 : /*      If it is a subfile, read the JPEG header.                       */
    1557                 : /* -------------------------------------------------------------------- */
    1558           14033 :     if( EQUALN(poOpenInfo->pszFilename,"JPEG_SUBFILE:",13) )
    1559              68 :         return TRUE;
    1560                 : 
    1561                 : /* -------------------------------------------------------------------- */
    1562                 : /*  First we check to see if the file has the expected header */
    1563                 : /*  bytes.                */    
    1564                 : /* -------------------------------------------------------------------- */
    1565           13965 :     pabyHeader = poOpenInfo->pabyHeader;
    1566                 : 
    1567           13965 :     if( nHeaderBytes < 10 )
    1568           11992 :         return FALSE;
    1569                 : 
    1570            2170 :     if( pabyHeader[0] != 0xff
    1571             122 :         || pabyHeader[1] != 0xd8
    1572              75 :         || pabyHeader[2] != 0xff )
    1573            1898 :         return FALSE;
    1574                 : 
    1575                 : #if JPEG_LIB_VERSION_MAJOR < 9
    1576              75 :     if (JPEGDatasetIsJPEGLS(poOpenInfo))
    1577                 :     {
    1578               0 :         return FALSE;
    1579                 :     }
    1580                 : #endif
    1581                 : 
    1582              75 :     return TRUE;
    1583                 : }
    1584                 : 
    1585                 : /************************************************************************/
    1586                 : /*                                Open()                                */
    1587                 : /************************************************************************/
    1588                 : 
    1589            3790 : GDALDataset *JPGDatasetCommon::Open( GDALOpenInfo * poOpenInfo )
    1590                 : 
    1591                 : {
    1592            3790 :     if( !Identify( poOpenInfo ) )
    1593            3647 :         return NULL;
    1594                 : 
    1595             143 :     if( poOpenInfo->eAccess == GA_Update )
    1596                 :     {
    1597                 :         CPLError( CE_Failure, CPLE_NotSupported, 
    1598                 :                   "The JPEG driver does not support update access to existing"
    1599               0 :                   " datasets.\n" );
    1600               0 :         return NULL;
    1601                 :     }
    1602                 : 
    1603             143 :     return JPGDataset::Open(poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles);
    1604                 : }
    1605                 : 
    1606                 : #endif // !defined(JPGDataset)
    1607                 : 
    1608                 : /************************************************************************/
    1609                 : /*                                Open()                                */
    1610                 : /************************************************************************/
    1611                 : 
    1612             204 : GDALDataset *JPGDataset::Open( const char* pszFilename, char** papszSiblingFiles,
    1613                 :                                int nScaleFactor, VSILFILE* fpIn )
    1614                 : 
    1615                 : {
    1616                 : /* -------------------------------------------------------------------- */
    1617                 : /*      If it is a subfile, read the JPEG header.                       */
    1618                 : /* -------------------------------------------------------------------- */
    1619             204 :     int bIsSubfile = FALSE;
    1620             204 :     GUIntBig subfile_offset = 0;
    1621             204 :     GUIntBig subfile_size = 0;
    1622             204 :     const char *real_filename = pszFilename;
    1623             204 :     int nQLevel = -1;
    1624                 : 
    1625             204 :     if( EQUALN(pszFilename,"JPEG_SUBFILE:",13) )
    1626                 :     {
    1627                 :         char** papszTokens;
    1628              79 :         int bScan = FALSE;
    1629                 : 
    1630              79 :         if( EQUALN(pszFilename,"JPEG_SUBFILE:Q",14) )
    1631                 :         {
    1632              79 :             papszTokens = CSLTokenizeString2(pszFilename + 14, ",", 0);
    1633              79 :             if (CSLCount(papszTokens) >= 3)
    1634                 :             {
    1635              79 :                 nQLevel = atoi(papszTokens[0]);
    1636              79 :                 subfile_offset = CPLScanUIntBig(papszTokens[1], strlen(papszTokens[1]));
    1637              79 :                 subfile_size = CPLScanUIntBig(papszTokens[2], strlen(papszTokens[2]));
    1638              79 :                 bScan = TRUE;
    1639                 :             }
    1640              79 :             CSLDestroy(papszTokens);
    1641                 :         }
    1642                 :         else
    1643                 :         {
    1644               0 :             papszTokens = CSLTokenizeString2(pszFilename + 13, ",", 0);
    1645               0 :             if (CSLCount(papszTokens) >= 2)
    1646                 :             {
    1647               0 :                 subfile_offset = CPLScanUIntBig(papszTokens[0], strlen(papszTokens[0]));
    1648               0 :                 subfile_size = CPLScanUIntBig(papszTokens[1], strlen(papszTokens[1]));
    1649               0 :                 bScan = TRUE;
    1650                 :             }
    1651               0 :             CSLDestroy(papszTokens);
    1652                 :         }
    1653                 : 
    1654              79 :         if( !bScan ) 
    1655                 :         {
    1656                 :             CPLError( CE_Failure, CPLE_OpenFailed, 
    1657                 :                       "Corrupt subfile definition: %s", 
    1658               0 :                       pszFilename );
    1659               0 :             return NULL;
    1660                 :         }
    1661                 : 
    1662              79 :         real_filename = strstr(pszFilename,",");
    1663              79 :         if( real_filename != NULL )
    1664              79 :             real_filename = strstr(real_filename+1,",");
    1665              79 :         if( real_filename != NULL && nQLevel != -1 )
    1666              79 :             real_filename = strstr(real_filename+1,",");
    1667              79 :         if( real_filename != NULL )
    1668              79 :             real_filename++;
    1669                 :         else
    1670                 :         {
    1671                 :             CPLError( CE_Failure, CPLE_OpenFailed, 
    1672               0 :                       "Could not find filename in subfile definition.");
    1673               0 :             return NULL;
    1674                 :         }
    1675                 : 
    1676                 :         CPLDebug( "JPG",
    1677                 :                   "real_filename %s, offset=" CPL_FRMT_GUIB ", size=" CPL_FRMT_GUIB "\n", 
    1678              79 :                   real_filename, subfile_offset, subfile_size);
    1679                 : 
    1680              79 :         bIsSubfile = TRUE;
    1681                 :     }
    1682                 : 
    1683                 : /* -------------------------------------------------------------------- */
    1684                 : /*      Open the file using the large file api.                         */
    1685                 : /* -------------------------------------------------------------------- */
    1686                 :     VSILFILE* fpImage;
    1687                 : 
    1688             204 :     if( fpIn == NULL )
    1689                 :     {
    1690             204 :         fpImage = VSIFOpenL( real_filename, "rb" );
    1691                 : 
    1692             204 :         if( fpImage == NULL )
    1693                 :         {
    1694                 :             CPLError( CE_Failure, CPLE_OpenFailed,
    1695                 :                     "VSIFOpenL(%s) failed unexpectedly in jpgdataset.cpp",
    1696               2 :                     real_filename );
    1697               2 :             return NULL;
    1698                 :         }
    1699                 :     }
    1700                 :     else
    1701               0 :         fpImage = fpIn;
    1702                 : 
    1703                 : /* -------------------------------------------------------------------- */
    1704                 : /*      Create a corresponding GDALDataset.                             */
    1705                 : /* -------------------------------------------------------------------- */
    1706                 :     JPGDataset  *poDS;
    1707                 : 
    1708             202 :     poDS = new JPGDataset();
    1709             202 :     poDS->nQLevel = nQLevel;
    1710             202 :     poDS->fpImage = fpImage;
    1711             202 :     poDS->bOwnFPImage = (fpIn == NULL);
    1712                 : 
    1713                 : /* -------------------------------------------------------------------- */
    1714                 : /*      Move to the start of jpeg data.                                 */
    1715                 : /* -------------------------------------------------------------------- */
    1716             202 :     poDS->nSubfileOffset = subfile_offset;
    1717             202 :     VSIFSeekL( poDS->fpImage, poDS->nSubfileOffset, SEEK_SET );
    1718                 : 
    1719             202 :     poDS->eAccess = GA_ReadOnly;
    1720                 : 
    1721                 :     /* Will detect mismatch between compile-time and run-time libjpeg versions */
    1722             202 :     if (setjmp(poDS->setjmp_buffer)) 
    1723                 :     {
    1724               0 :         delete poDS;
    1725               0 :         return NULL;
    1726                 :     }
    1727                 : 
    1728             202 :     poDS->sDInfo.err = jpeg_std_error( &(poDS->sJErr) );
    1729             202 :     poDS->sJErr.error_exit = JPGDataset::ErrorExit;
    1730             202 :     poDS->sDInfo.client_data = (void *) &(poDS->setjmp_buffer);
    1731                 : 
    1732             202 :     jpeg_create_decompress( &(poDS->sDInfo) );
    1733             202 :     poDS->bHasDoneJpegCreateDecompress = TRUE;
    1734                 : 
    1735                 :     /* This is to address bug related in ticket #1795 */
    1736             202 :     if (CPLGetConfigOption("JPEGMEM", NULL) == NULL)
    1737                 :     {
    1738                 :         /* If the user doesn't provide a value for JPEGMEM, we want to be sure */
    1739                 :         /* that at least 500 MB will be used before creating the temporary file */
    1740                 :         poDS->sDInfo.mem->max_memory_to_use =
    1741             202 :                 MAX(poDS->sDInfo.mem->max_memory_to_use, 500 * 1024 * 1024);
    1742                 :     }
    1743                 : 
    1744                 : /* -------------------------------------------------------------------- */
    1745                 : /*      Preload default NITF JPEG quantization tables.                  */
    1746                 : /* -------------------------------------------------------------------- */
    1747             202 :     poDS->LoadDefaultTables( 0 );
    1748             202 :     poDS->LoadDefaultTables( 1 );
    1749             202 :     poDS->LoadDefaultTables( 2 );
    1750             202 :     poDS->LoadDefaultTables( 3 );
    1751                 : 
    1752                 : /* -------------------------------------------------------------------- */
    1753                 : /*      If a fatal error occurs after this, we will return NULL         */
    1754                 : /* -------------------------------------------------------------------- */
    1755             202 :     if (setjmp(poDS->setjmp_buffer)) 
    1756                 :     {
    1757                 : #if defined(JPEG_DUAL_MODE_8_12) && !defined(JPGDataset)
    1758              18 :         if (poDS->sDInfo.data_precision == 12)
    1759                 :         {
    1760              17 :             delete poDS;
    1761                 :             return JPEGDataset12Open(pszFilename, papszSiblingFiles,
    1762              17 :                                      nScaleFactor);
    1763                 :         }
    1764                 : #endif
    1765               1 :         delete poDS;
    1766               1 :         return NULL;
    1767                 :     }
    1768                 : 
    1769                 : /* -------------------------------------------------------------------- */
    1770                 : /*  Read pre-image data after ensuring the file is rewound.         */
    1771                 : /* -------------------------------------------------------------------- */
    1772             202 :     VSIFSeekL( poDS->fpImage, poDS->nSubfileOffset, SEEK_SET );
    1773                 : 
    1774             202 :     jpeg_vsiio_src( &(poDS->sDInfo), poDS->fpImage );
    1775             202 :     jpeg_read_header( &(poDS->sDInfo), TRUE );
    1776                 : 
    1777             184 :     if( poDS->sDInfo.data_precision != 8
    1778                 :         && poDS->sDInfo.data_precision != 12 )
    1779                 :     {
    1780                 :         CPLError( CE_Failure, CPLE_NotSupported, 
    1781                 :                   "GDAL JPEG Driver doesn't support files with precision of"
    1782               0 :                   " other than 8 or 12 bits." );
    1783               0 :         delete poDS;
    1784               0 :         return NULL;
    1785                 :     }
    1786                 : 
    1787                 : /* -------------------------------------------------------------------- */
    1788                 : /*      Capture some information from the file that is of interest.     */
    1789                 : /* -------------------------------------------------------------------- */
    1790                 : 
    1791             184 :     poDS->nScaleFactor = nScaleFactor;
    1792             184 :     poDS->SetScaleNumAndDenom();
    1793             184 :     poDS->nRasterXSize = (poDS->sDInfo.image_width + nScaleFactor - 1) / nScaleFactor;
    1794             184 :     poDS->nRasterYSize = (poDS->sDInfo.image_height + nScaleFactor - 1) / nScaleFactor;
    1795                 : 
    1796             184 :     poDS->sDInfo.out_color_space = poDS->sDInfo.jpeg_color_space;
    1797             184 :     poDS->eGDALColorSpace = poDS->sDInfo.jpeg_color_space;
    1798                 : 
    1799             184 :     if( poDS->sDInfo.jpeg_color_space == JCS_GRAYSCALE )
    1800                 :     {
    1801             119 :         poDS->nBands = 1;
    1802                 :     }
    1803              65 :     else if( poDS->sDInfo.jpeg_color_space == JCS_RGB )
    1804                 :     {
    1805               2 :         poDS->nBands = 3;
    1806                 :     }
    1807              63 :     else if( poDS->sDInfo.jpeg_color_space == JCS_YCbCr )
    1808                 :     {
    1809              60 :         poDS->nBands = 3;
    1810              60 :         if (CSLTestBoolean(CPLGetConfigOption("GDAL_JPEG_TO_RGB", "YES")))
    1811                 :         {
    1812              60 :             poDS->sDInfo.out_color_space = JCS_RGB;
    1813              60 :             poDS->eGDALColorSpace = JCS_RGB;
    1814              60 :             poDS->SetMetadataItem( "SOURCE_COLOR_SPACE", "YCbCr", "IMAGE_STRUCTURE" );
    1815                 :         }
    1816                 :     }
    1817               3 :     else if( poDS->sDInfo.jpeg_color_space == JCS_CMYK )
    1818                 :     {
    1819               3 :         if (CSLTestBoolean(CPLGetConfigOption("GDAL_JPEG_TO_RGB", "YES")))
    1820                 :         {
    1821               2 :             poDS->eGDALColorSpace = JCS_RGB;
    1822               2 :             poDS->nBands = 3;
    1823               2 :             poDS->SetMetadataItem( "SOURCE_COLOR_SPACE", "CMYK", "IMAGE_STRUCTURE" );
    1824                 :         }
    1825                 :         else
    1826                 :         {
    1827               1 :             poDS->nBands = 4;
    1828                 :         }
    1829                 :     }
    1830               0 :     else if( poDS->sDInfo.jpeg_color_space == JCS_YCCK )
    1831                 :     {
    1832               0 :         if (CSLTestBoolean(CPLGetConfigOption("GDAL_JPEG_TO_RGB", "YES")))
    1833                 :         {
    1834               0 :             poDS->eGDALColorSpace = JCS_RGB;
    1835               0 :             poDS->nBands = 3;
    1836               0 :             poDS->SetMetadataItem( "SOURCE_COLOR_SPACE", "YCbCrK", "IMAGE_STRUCTURE" );
    1837                 :         }
    1838                 :         else
    1839                 :         {
    1840               0 :             poDS->nBands = 4;
    1841                 :         }
    1842                 :         /* libjpeg does the translation from YCrCbK -> CMYK internally */
    1843                 :         /* and we'll do the translation to RGB in IReadBlock() */
    1844               0 :         poDS->sDInfo.out_color_space = JCS_CMYK;
    1845                 :     }
    1846                 :     else
    1847                 :     {
    1848                 :         CPLError( CE_Failure, CPLE_NotSupported, 
    1849                 :                   "Unrecognised jpeg_color_space value of %d.\n", 
    1850               0 :                   poDS->sDInfo.jpeg_color_space );
    1851               0 :         delete poDS;
    1852               0 :         return NULL;
    1853                 :     }
    1854                 : 
    1855                 : /* -------------------------------------------------------------------- */
    1856                 : /*      Create band information objects.                                */
    1857                 : /* -------------------------------------------------------------------- */
    1858             499 :     for( int iBand = 0; iBand < poDS->nBands; iBand++ )
    1859             315 :         poDS->SetBand( iBand+1, JPGCreateBand( poDS, iBand+1 ) );
    1860                 : 
    1861                 : /* -------------------------------------------------------------------- */
    1862                 : /*      More metadata.                                                  */
    1863                 : /* -------------------------------------------------------------------- */
    1864             184 :     if( poDS->nBands > 1 )
    1865                 :     {
    1866              65 :         poDS->SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" );
    1867              65 :         poDS->SetMetadataItem( "COMPRESSION", "JPEG", "IMAGE_STRUCTURE" );
    1868                 :     }
    1869                 : 
    1870                 : /* -------------------------------------------------------------------- */
    1871                 : /*      Initialize any PAM information.                                 */
    1872                 : /* -------------------------------------------------------------------- */
    1873             184 :     poDS->SetDescription( pszFilename );
    1874                 : 
    1875             184 :     if( nScaleFactor == 1 )
    1876                 :     {
    1877             177 :         if( !bIsSubfile )
    1878             109 :             poDS->TryLoadXML( papszSiblingFiles );
    1879                 :         else
    1880              68 :             poDS->nPamFlags |= GPF_NOSAVE;
    1881                 : 
    1882                 : /* -------------------------------------------------------------------- */
    1883                 : /*      Open (external) overviews.                                      */
    1884                 : /* -------------------------------------------------------------------- */
    1885             177 :         poDS->oOvManager.Initialize( poDS, real_filename, papszSiblingFiles );
    1886                 :     }
    1887                 :     else
    1888               7 :         poDS->nPamFlags |= GPF_NOSAVE;
    1889                 : 
    1890             184 :     poDS->bIsSubfile = bIsSubfile;
    1891                 : 
    1892             184 :     return poDS;
    1893                 : }
    1894                 : 
    1895                 : #if !defined(JPGDataset)
    1896                 : 
    1897                 : /************************************************************************/
    1898                 : /*                       LoadWorldFileOrTab()                           */
    1899                 : /************************************************************************/
    1900                 : 
    1901              57 : void JPGDatasetCommon::LoadWorldFileOrTab()
    1902                 : {
    1903              57 :     if (bIsSubfile)
    1904               0 :         return;
    1905              57 :     if (bHasTriedLoadWorldFileOrTab)
    1906              29 :         return;
    1907              28 :     bHasTriedLoadWorldFileOrTab = TRUE;
    1908                 : 
    1909              28 :     char* pszWldFilename = NULL;
    1910                 : 
    1911                 :     /* TIROS3 JPEG files have a .wld extension, so don't look for .wld as */
    1912                 :     /* as worldfile ! */
    1913              28 :     int bEndsWithWld = strlen(GetDescription()) > 4 &&
    1914              56 :                         EQUAL( GetDescription() + strlen(GetDescription()) - 4, ".wld");
    1915                 :     bGeoTransformValid =
    1916              28 :         GDALReadWorldFile2( GetDescription(), NULL,
    1917                 :                             adfGeoTransform,
    1918                 :                             oOvManager.GetSiblingFiles(), &pszWldFilename )
    1919              28 :         || GDALReadWorldFile2( GetDescription(), ".jpw",
    1920                 :                                 adfGeoTransform,
    1921                 :                                oOvManager.GetSiblingFiles(), &pszWldFilename )
    1922              28 :         || ( !bEndsWithWld && GDALReadWorldFile2( GetDescription(), ".wld",
    1923                 :                                 adfGeoTransform,
    1924             112 :                                 oOvManager.GetSiblingFiles(), &pszWldFilename ));
    1925                 : 
    1926              28 :     if( !bGeoTransformValid )
    1927                 :     {
    1928                 :         int bTabFileOK =
    1929              24 :             GDALReadTabFile2( GetDescription(), adfGeoTransform,
    1930                 :                               &pszProjection,
    1931                 :                               &nGCPCount, &pasGCPList,
    1932              48 :                               oOvManager.GetSiblingFiles(), &pszWldFilename );
    1933                 : 
    1934              24 :         if( bTabFileOK && nGCPCount == 0 )
    1935               0 :             bGeoTransformValid = TRUE;
    1936                 :     }
    1937                 : 
    1938              28 :     if (pszWldFilename)
    1939                 :     {
    1940               4 :         osWldFilename = pszWldFilename;
    1941               4 :         CPLFree(pszWldFilename);
    1942                 :     }
    1943                 : }
    1944                 : 
    1945                 : /************************************************************************/
    1946                 : /*                            GetFileList()                             */
    1947                 : /************************************************************************/
    1948                 : 
    1949               6 : char **JPGDatasetCommon::GetFileList()
    1950                 : 
    1951                 : {
    1952               6 :     char **papszFileList = GDALPamDataset::GetFileList();
    1953                 : 
    1954               6 :     LoadWorldFileOrTab();
    1955                 : 
    1956               6 :     if (osWldFilename.size() != 0 &&
    1957                 :         CSLFindString(papszFileList, osWldFilename) == -1)
    1958                 :     {
    1959               2 :         papszFileList = CSLAddString( papszFileList, osWldFilename );
    1960                 :     }
    1961                 : 
    1962               6 :     return papszFileList;
    1963                 : }
    1964                 : 
    1965                 : /************************************************************************/
    1966                 : /*                            CheckForMask()                            */
    1967                 : /************************************************************************/
    1968                 : 
    1969              18 : void JPGDatasetCommon::CheckForMask()
    1970                 : 
    1971                 : {
    1972                 :     GIntBig nFileSize;
    1973                 :     GUInt32 nImageSize;
    1974                 : 
    1975                 :     /* Save current position to avoid disturbing JPEG stream decoding */
    1976              18 :     vsi_l_offset nCurOffset = VSIFTellL(fpImage);
    1977                 : 
    1978                 : /* -------------------------------------------------------------------- */
    1979                 : /*      Go to the end of the file, pull off four bytes, and see if      */
    1980                 : /*      it is plausibly the size of the real image data.                */
    1981                 : /* -------------------------------------------------------------------- */
    1982              18 :     VSIFSeekL( fpImage, 0, SEEK_END );
    1983              18 :     nFileSize = VSIFTellL( fpImage );
    1984              18 :     VSIFSeekL( fpImage, nFileSize - 4, SEEK_SET );
    1985                 :     
    1986              18 :     VSIFReadL( &nImageSize, 4, 1, fpImage );
    1987                 :     CPL_LSBPTR32( &nImageSize );
    1988                 : 
    1989              18 :     if( nImageSize < nFileSize / 2 || nImageSize > nFileSize - 4 )
    1990                 :         goto end;
    1991                 : 
    1992                 : /* -------------------------------------------------------------------- */
    1993                 : /*      If that seems ok, seek back, and verify that just preceeding    */
    1994                 : /*      the bitmask is an apparent end-of-jpeg-data marker.             */
    1995                 : /* -------------------------------------------------------------------- */
    1996                 :     GByte abyEOD[2];
    1997                 : 
    1998               4 :     VSIFSeekL( fpImage, nImageSize - 2, SEEK_SET );
    1999               4 :     VSIFReadL( abyEOD, 2, 1, fpImage );
    2000               4 :     if( abyEOD[0] != 0xff || abyEOD[1] != 0xd9 )
    2001                 :         goto end;
    2002                 : 
    2003                 : /* -------------------------------------------------------------------- */
    2004                 : /*      We seem to have a mask.  Read it in.                            */
    2005                 : /* -------------------------------------------------------------------- */
    2006               4 :     nCMaskSize = (int) (nFileSize - nImageSize - 4);
    2007               4 :     pabyCMask = (GByte *) VSIMalloc(nCMaskSize);
    2008               4 :     if (pabyCMask == NULL)
    2009                 :     {
    2010                 :         CPLError(CE_Failure, CPLE_OutOfMemory,
    2011                 :                  "Cannot allocate memory (%d bytes) for mask compressed buffer",
    2012               0 :                  nCMaskSize);
    2013               0 :         goto end;
    2014                 :     }
    2015               4 :     VSIFReadL( pabyCMask, nCMaskSize, 1, fpImage );
    2016                 : 
    2017                 :     CPLDebug( "JPEG", "Got %d byte compressed bitmask.",
    2018               4 :               nCMaskSize );
    2019                 : 
    2020                 : end:
    2021              18 :     VSIFSeekL( fpImage, nCurOffset, SEEK_SET );
    2022              18 : }
    2023                 : 
    2024                 : /************************************************************************/
    2025                 : /*                           DecompressMask()                           */
    2026                 : /************************************************************************/
    2027                 : 
    2028            2048 : void JPGDatasetCommon::DecompressMask()
    2029                 : 
    2030                 : {
    2031            2048 :     if( pabyCMask == NULL || pabyBitMask != NULL )
    2032            2044 :         return;
    2033                 : 
    2034                 : /* -------------------------------------------------------------------- */
    2035                 : /*      Allocate 1bit buffer - may be slightly larger than needed.      */
    2036                 : /* -------------------------------------------------------------------- */
    2037               4 :     int nBufSize = nRasterYSize * ((nRasterXSize+7)/8);
    2038               4 :     pabyBitMask = (GByte *) VSIMalloc( nBufSize );
    2039               4 :     if (pabyBitMask == NULL)
    2040                 :     {
    2041                 :         CPLError(CE_Failure, CPLE_OutOfMemory,
    2042                 :                  "Cannot allocate memory (%d bytes) for mask uncompressed buffer",
    2043               0 :                  nBufSize);
    2044               0 :         CPLFree(pabyCMask);
    2045               0 :         pabyCMask = NULL;
    2046               0 :         return;
    2047                 :     }
    2048                 :     
    2049                 : /* -------------------------------------------------------------------- */
    2050                 : /*      Decompress                                                      */
    2051                 : /* -------------------------------------------------------------------- */
    2052                 :     void* pOut = CPLZLibInflate( pabyCMask, nCMaskSize,
    2053               4 :                                  pabyBitMask, nBufSize, NULL );
    2054                 : /* -------------------------------------------------------------------- */
    2055                 : /*      Cleanup if an error occurs.                                     */
    2056                 : /* -------------------------------------------------------------------- */
    2057               4 :     if( pOut == NULL )
    2058                 :     {
    2059                 :         CPLError( CE_Failure, CPLE_AppDefined,
    2060               0 :                   "Failure decoding JPEG validity bitmask." );
    2061               0 :         CPLFree( pabyCMask );
    2062               0 :         pabyCMask = NULL;
    2063                 : 
    2064               0 :         CPLFree( pabyBitMask );
    2065               0 :         pabyBitMask = NULL;
    2066                 :     }
    2067                 : }
    2068                 : 
    2069                 : #endif // !defined(JPGDataset)
    2070                 : 
    2071                 : /************************************************************************/
    2072                 : /*                             ErrorExit()                              */
    2073                 : /************************************************************************/
    2074                 : 
    2075              19 : void JPGDataset::ErrorExit(j_common_ptr cinfo)
    2076                 : {
    2077              19 :     jmp_buf *setjmp_buffer = (jmp_buf *) cinfo->client_data;
    2078                 :     char buffer[JMSG_LENGTH_MAX];
    2079                 : 
    2080                 :     /* Create the message */
    2081              19 :     (*cinfo->err->format_message) (cinfo, buffer);
    2082                 : 
    2083                 : /* Avoid error for a 12bit JPEG if reading from the 8bit JPEG driver and */
    2084                 : /* we have JPEG_DUAL_MODE_8_12 support, as we'll try again with 12bit JPEG */
    2085                 : /* driver */
    2086                 : #if defined(JPEG_DUAL_MODE_8_12) && !defined(JPGDataset)
    2087              19 :     if (strstr(buffer, "Unsupported JPEG data precision 12") == NULL)
    2088                 : #endif
    2089                 :     CPLError( CE_Failure, CPLE_AppDefined,
    2090               2 :               "libjpeg: %s", buffer );
    2091                 : 
    2092                 :     /* Return control to the setjmp point */
    2093              19 :     longjmp(*setjmp_buffer, 1);
    2094                 : }
    2095                 : 
    2096                 : #if !defined(JPGDataset)
    2097                 : 
    2098                 : /************************************************************************/
    2099                 : /*                           JPGAppendMask()                            */
    2100                 : /*                                                                      */
    2101                 : /*      This function appends a zlib compressed bitmask to a JPEG       */
    2102                 : /*      file (or really any file) pulled from an existing mask band.    */
    2103                 : /************************************************************************/
    2104                 : 
    2105                 : // MSVC does not know that memset() has initialized sStream.
    2106                 : #ifdef _MSC_VER
    2107                 : #  pragma warning(disable:4701)
    2108                 : #endif
    2109                 : 
    2110               2 : CPLErr JPGAppendMask( const char *pszJPGFilename, GDALRasterBand *poMask,
    2111                 :                       GDALProgressFunc pfnProgress, void * pProgressData )
    2112                 : 
    2113                 : {
    2114               2 :     int nXSize = poMask->GetXSize();
    2115               2 :     int nYSize = poMask->GetYSize();
    2116               2 :     int nBitBufSize = nYSize * ((nXSize+7)/8);
    2117                 :     int iX, iY;
    2118                 :     GByte *pabyBitBuf, *pabyMaskLine;
    2119               2 :     CPLErr eErr = CE_None;
    2120                 : 
    2121                 : /* -------------------------------------------------------------------- */
    2122                 : /*      Allocate uncompressed bit buffer.                               */
    2123                 : /* -------------------------------------------------------------------- */
    2124               2 :     pabyBitBuf = (GByte *) VSICalloc(1,nBitBufSize);
    2125                 : 
    2126               2 :     pabyMaskLine = (GByte *) VSIMalloc(nXSize);
    2127               2 :     if (pabyBitBuf == NULL || pabyMaskLine == NULL)
    2128                 :     {
    2129               0 :         CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
    2130               0 :         eErr = CE_Failure;
    2131                 :     }
    2132                 : 
    2133                 : /* -------------------------------------------------------------------- */
    2134                 : /*      Set bit buffer from mask band, scanline by scanline.            */
    2135                 : /* -------------------------------------------------------------------- */
    2136               2 :     GUInt32 iBit = 0;
    2137             524 :     for( iY = 0; eErr == CE_None && iY < nYSize; iY++ )
    2138                 :     {
    2139                 :         eErr = poMask->RasterIO( GF_Read, 0, iY, nXSize, 1,
    2140             522 :                                  pabyMaskLine, nXSize, 1, GDT_Byte, 0, 0 );
    2141             522 :         if( eErr != CE_None )
    2142               0 :             break;
    2143                 : 
    2144          262766 :         for( iX = 0; iX < nXSize; iX++ )
    2145                 :         {
    2146          262244 :             if( pabyMaskLine[iX] != 0 )
    2147          197632 :                 pabyBitBuf[iBit>>3] |= (0x1 << (iBit&7));
    2148                 : 
    2149          262244 :             iBit++;
    2150                 :         }
    2151                 : 
    2152             522 :         if( eErr == CE_None
    2153                 :             && !pfnProgress( (iY + 1) / (double) nYSize, NULL, pProgressData ) )
    2154                 :         {
    2155               0 :             eErr = CE_Failure;
    2156                 :             CPLError( CE_Failure, CPLE_UserInterrupt,
    2157               0 :                       "User terminated JPGAppendMask()" );
    2158                 :         }
    2159                 :     }
    2160                 :     
    2161               2 :     CPLFree( pabyMaskLine );
    2162                 : 
    2163                 : /* -------------------------------------------------------------------- */
    2164                 : /*      Compress                                                        */
    2165                 : /* -------------------------------------------------------------------- */
    2166               2 :     GByte *pabyCMask = NULL;
    2167                 : 
    2168               2 :     if( eErr == CE_None )
    2169                 :     {
    2170               2 :         pabyCMask = (GByte *) VSIMalloc(nBitBufSize + 30);
    2171               2 :         if (pabyCMask == NULL)
    2172                 :         {
    2173               0 :             CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
    2174               0 :             eErr = CE_Failure;
    2175                 :         }
    2176                 :     }
    2177                 : 
    2178               2 :     size_t nTotalOut = 0;
    2179               2 :     if ( eErr == CE_None )
    2180                 :     {
    2181               2 :         if( CPLZLibDeflate( pabyBitBuf, nBitBufSize, 9,
    2182                 :                             pabyCMask, nBitBufSize + 30,
    2183                 :                             &nTotalOut ) == NULL )
    2184                 :         {
    2185                 :             CPLError( CE_Failure, CPLE_AppDefined, 
    2186               0 :                       "Deflate compression of jpeg bit mask failed." );
    2187               0 :             eErr = CE_Failure;
    2188                 :         }
    2189                 :     }
    2190                 : 
    2191                 : /* -------------------------------------------------------------------- */
    2192                 : /*      Write to disk, along with image file size.                      */
    2193                 : /* -------------------------------------------------------------------- */
    2194               2 :     if( eErr == CE_None )
    2195                 :     {
    2196                 :         VSILFILE *fpOut;
    2197                 :         GUInt32 nImageSize;
    2198                 : 
    2199               2 :         fpOut = VSIFOpenL( pszJPGFilename, "r+" );
    2200               2 :         if( fpOut == NULL )
    2201                 :         {
    2202                 :             CPLError( CE_Failure, CPLE_AppDefined, 
    2203               0 :                       "Failed to open jpeg to append bitmask." );
    2204               0 :             eErr = CE_Failure;
    2205                 :         }
    2206                 :         else
    2207                 :         {
    2208               2 :             VSIFSeekL( fpOut, 0, SEEK_END );
    2209                 : 
    2210               2 :             nImageSize = (GUInt32) VSIFTellL( fpOut );
    2211                 :             CPL_LSBPTR32( &nImageSize );
    2212                 : 
    2213               2 :             if( VSIFWriteL( pabyCMask, 1, nTotalOut, fpOut ) 
    2214                 :                 != nTotalOut )
    2215                 :             {
    2216                 :                 CPLError( CE_Failure, CPLE_FileIO,
    2217                 :                           "Failure writing compressed bitmask.\n%s",
    2218               0 :                           VSIStrerror( errno ) );
    2219               0 :                 eErr = CE_Failure;
    2220                 :             }
    2221                 :             else
    2222               2 :                 VSIFWriteL( &nImageSize, 4, 1, fpOut );
    2223                 : 
    2224               2 :             VSIFCloseL( fpOut );
    2225                 :         }
    2226                 :     }
    2227                 : 
    2228               2 :     CPLFree( pabyBitBuf );
    2229               2 :     CPLFree( pabyCMask );
    2230                 : 
    2231               2 :     return eErr;
    2232                 : }
    2233                 : 
    2234                 : #endif // !defined(JPGDataset)
    2235                 : 
    2236                 : /************************************************************************/
    2237                 : /*                              CreateCopy()                            */
    2238                 : /************************************************************************/
    2239                 : 
    2240                 : GDALDataset *
    2241              60 : JPGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
    2242                 :                         int bStrict, char ** papszOptions,
    2243                 :                         GDALProgressFunc pfnProgress, void * pProgressData )
    2244                 : 
    2245                 : {
    2246              60 :     int  nBands = poSrcDS->GetRasterCount();
    2247              60 :     int  nXSize = poSrcDS->GetRasterXSize();
    2248              60 :     int  nYSize = poSrcDS->GetRasterYSize();
    2249              60 :     int  nQuality = 75;
    2250              60 :     int  bProgressive = FALSE;
    2251              60 :     int  nCloneFlags = GCIF_PAM_DEFAULT;
    2252                 :     const char* pszVal;
    2253                 : 
    2254              60 :     if( !pfnProgress( 0.0, NULL, pProgressData ) )
    2255               0 :         return NULL;
    2256                 : 
    2257                 : /* -------------------------------------------------------------------- */
    2258                 : /*      Some some rudimentary checks                                    */
    2259                 : /* -------------------------------------------------------------------- */
    2260              60 :     if( nBands != 1 && nBands != 3 && nBands != 4 )
    2261                 :     {
    2262                 :         CPLError( CE_Failure, CPLE_NotSupported, 
    2263                 :                   "JPEG driver doesn't support %d bands.  Must be 1 (grey), "
    2264               3 :                   "3 (RGB) or 4 bands.\n", nBands );
    2265                 : 
    2266               3 :         return NULL;
    2267                 :     }
    2268                 : 
    2269             104 :     if (nBands == 1 &&
    2270              47 :         poSrcDS->GetRasterBand(1)->GetColorTable() != NULL)
    2271                 :     {
    2272                 :         CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported, 
    2273                 :                   "JPEG driver ignores color table. "
    2274                 :                   "The source raster band will be considered as grey level.\n"
    2275               0 :                   "Consider using color table expansion (-expand option in gdal_translate)\n");
    2276               0 :         if (bStrict)
    2277               0 :             return NULL;
    2278                 :     }
    2279                 : 
    2280              57 :     GDALDataType eDT = poSrcDS->GetRasterBand(1)->GetRasterDataType();
    2281                 : 
    2282                 : #if defined(JPEG_LIB_MK1_OR_12BIT) || defined(JPEG_DUAL_MODE_8_12)
    2283              57 :     if( eDT != GDT_Byte && eDT != GDT_UInt16 )
    2284                 :     {
    2285                 :         CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported, 
    2286                 :                   "JPEG driver doesn't support data type %s. "
    2287                 :                   "Only eight and twelve bit bands supported (Mk1 libjpeg).\n",
    2288                 :                   GDALGetDataTypeName( 
    2289               9 :                       poSrcDS->GetRasterBand(1)->GetRasterDataType()) );
    2290                 : 
    2291               9 :         if (bStrict)
    2292               9 :             return NULL;
    2293                 :     }
    2294                 : 
    2295              52 :     if( eDT == GDT_UInt16 || eDT == GDT_Int16 )
    2296                 :     {
    2297                 : #if defined(JPEG_DUAL_MODE_8_12) && !defined(JPGDataset)
    2298                 :         return JPEGDataset12CreateCopy(pszFilename, poSrcDS,
    2299                 :                                 bStrict, papszOptions, 
    2300               4 :                                 pfnProgress, pProgressData );
    2301                 : #else
    2302               4 :         eDT = GDT_UInt16;
    2303                 : #endif
    2304                 :     }
    2305                 :     else
    2306              40 :         eDT = GDT_Byte;
    2307                 : 
    2308                 : #else
    2309                 :     if( eDT != GDT_Byte )
    2310                 :     {
    2311                 :         CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported, 
    2312                 :                   "JPEG driver doesn't support data type %s. "
    2313                 :                   "Only eight bit byte bands supported.\n", 
    2314                 :                   GDALGetDataTypeName( 
    2315                 :                       poSrcDS->GetRasterBand(1)->GetRasterDataType()) );
    2316                 : 
    2317                 :         if (bStrict)
    2318                 :             return NULL;
    2319                 :     }
    2320                 :     
    2321                 :     eDT = GDT_Byte; // force to 8bit. 
    2322                 : #endif
    2323                 : 
    2324                 : /* -------------------------------------------------------------------- */
    2325                 : /*      What options has the user selected?                             */
    2326                 : /* -------------------------------------------------------------------- */
    2327              44 :     if( CSLFetchNameValue(papszOptions,"QUALITY") != NULL )
    2328                 :     {
    2329               3 :         nQuality = atoi(CSLFetchNameValue(papszOptions,"QUALITY"));
    2330               3 :         if( nQuality < 10 || nQuality > 100 )
    2331                 :         {
    2332                 :             CPLError( CE_Failure, CPLE_IllegalArg,
    2333                 :                       "QUALITY=%s is not a legal value in the range 10-100.",
    2334               0 :                       CSLFetchNameValue(papszOptions,"QUALITY") );
    2335               0 :             return NULL;
    2336                 :         }
    2337                 :     }
    2338                 : 
    2339              44 :     bProgressive = CSLFetchBoolean( papszOptions, "PROGRESSIVE", FALSE );
    2340                 : 
    2341                 : /* -------------------------------------------------------------------- */
    2342                 : /*      Create the dataset.                                             */
    2343                 : /* -------------------------------------------------------------------- */
    2344                 :     VSILFILE  *fpImage;
    2345                 : 
    2346              44 :     fpImage = VSIFOpenL( pszFilename, "wb" );
    2347              44 :     if( fpImage == NULL )
    2348                 :     {
    2349                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
    2350                 :                   "Unable to create jpeg file %s.\n", 
    2351               6 :                   pszFilename );
    2352               6 :         return NULL;
    2353                 :     }
    2354                 : 
    2355                 : /* -------------------------------------------------------------------- */
    2356                 : /*      Initialize JPG access to the file.                              */
    2357                 : /* -------------------------------------------------------------------- */
    2358                 :     struct jpeg_compress_struct sCInfo;
    2359                 :     struct jpeg_error_mgr sJErr;
    2360                 :     jmp_buf setjmp_buffer;
    2361                 :     
    2362              38 :     if (setjmp(setjmp_buffer)) 
    2363                 :     {
    2364               0 :         VSIFCloseL( fpImage );
    2365               0 :         return NULL;
    2366                 :     }
    2367                 : 
    2368              38 :     sCInfo.err = jpeg_std_error( &sJErr );
    2369              38 :     sJErr.error_exit = JPGDataset::ErrorExit;
    2370              38 :     sCInfo.client_data = (void *) &(setjmp_buffer);
    2371                 : 
    2372              38 :     jpeg_create_compress( &sCInfo );
    2373                 :     
    2374              38 :     jpeg_vsiio_dest( &sCInfo, fpImage );
    2375                 :     
    2376              38 :     sCInfo.image_width = nXSize;
    2377              38 :     sCInfo.image_height = nYSize;
    2378              38 :     sCInfo.input_components = nBands;
    2379                 : 
    2380              38 :     if( nBands == 3 )
    2381               7 :         sCInfo.in_color_space = JCS_RGB;
    2382              31 :     else if( nBands == 1 )
    2383              30 :         sCInfo.in_color_space = JCS_GRAYSCALE;
    2384                 :     else
    2385               1 :         sCInfo.in_color_space = JCS_UNKNOWN;
    2386                 : 
    2387              38 :     jpeg_set_defaults( &sCInfo );
    2388                 :     
    2389              38 :     if( eDT == GDT_UInt16 )
    2390                 :     {
    2391               3 :         sCInfo.data_precision = 12;
    2392                 :     }
    2393                 :     else
    2394                 :     {
    2395              35 :         sCInfo.data_precision = 8;
    2396                 :     }
    2397                 : 
    2398              38 :     pszVal = CSLFetchNameValue(papszOptions, "ARITHMETIC");
    2399              38 :     if( pszVal )
    2400               0 :         sCInfo.arith_code = CSLTestBoolean(pszVal);
    2401                 : 
    2402                 : #if JPEG_LIB_VERSION_MAJOR >= 8 && \
    2403                 :       (JPEG_LIB_VERSION_MAJOR > 8 || JPEG_LIB_VERSION_MINOR >= 3)
    2404                 :     pszVal = CSLFetchNameValue(papszOptions, "BLOCK");
    2405                 :     if( pszVal )
    2406                 :         sCInfo.block_size = atoi(pszVal);
    2407                 : #endif
    2408                 : 
    2409                 : #if JPEG_LIB_VERSION_MAJOR >= 9
    2410                 :     pszVal = CSLFetchNameValue(papszOptions, "COLOR_TRANSFORM");
    2411                 :     if( pszVal )
    2412                 :     {
    2413                 :         sCInfo.color_transform = EQUAL(pszVal, "RGB1") ? JCT_SUBTRACT_GREEN : JCT_NONE;
    2414                 :         jpeg_set_colorspace(&sCInfo, JCS_RGB);
    2415                 :     }
    2416                 :     else
    2417                 : #endif
    2418                 : 
    2419                 :     /* Mostly for debugging purposes */
    2420              38 :     if( nBands == 3 && CSLTestBoolean(CPLGetConfigOption("JPEG_WRITE_RGB", "NO")) )
    2421                 :     {
    2422               0 :         jpeg_set_colorspace(&sCInfo, JCS_RGB);
    2423                 :     }
    2424                 : 
    2425                 :     GDALDataType eWorkDT;
    2426                 : #ifdef JPEG_LIB_MK1
    2427                 :     sCInfo.bits_in_jsample = sCInfo.data_precision;
    2428                 :     eWorkDT = GDT_UInt16; /* Always force to 16 bit for JPEG_LIB_MK1 */
    2429                 : #else
    2430              38 :     eWorkDT = eDT;
    2431                 : #endif
    2432                 : 
    2433              38 :     jpeg_set_quality( &sCInfo, nQuality, TRUE );
    2434                 : 
    2435              38 :     if( bProgressive )
    2436               2 :         jpeg_simple_progression( &sCInfo );
    2437                 : 
    2438              38 :     jpeg_start_compress( &sCInfo, TRUE );
    2439                 : 
    2440                 : /* -------------------------------------------------------------------- */
    2441                 : /*      Does the source have a mask?  If so, we will append it to the   */
    2442                 : /*      jpeg file after the imagery.                                    */
    2443                 : /* -------------------------------------------------------------------- */
    2444              38 :     int nMaskFlags = poSrcDS->GetRasterBand(1)->GetMaskFlags();
    2445                 :     int bAppendMask =( !(nMaskFlags & GMF_ALL_VALID)
    2446              38 :         && (nBands == 1 || (nMaskFlags & GMF_PER_DATASET)) );
    2447                 : 
    2448              38 :     bAppendMask &= CSLFetchBoolean( papszOptions, "INTERNAL_MASK", TRUE );
    2449                 : 
    2450                 : /* -------------------------------------------------------------------- */
    2451                 : /*      Loop over image, copying image data.                            */
    2452                 : /* -------------------------------------------------------------------- */
    2453                 :     GByte   *pabyScanline;
    2454              38 :     CPLErr      eErr = CE_None;
    2455              38 :     int         nWorkDTSize = GDALGetDataTypeSize(eWorkDT) / 8;
    2456              38 :     bool        bClipWarn = false;
    2457                 : 
    2458              38 :     pabyScanline = (GByte *) CPLMalloc( nBands * nXSize * nWorkDTSize );
    2459                 : 
    2460            4817 :     for( int iLine = 0; iLine < nYSize && eErr == CE_None; iLine++ )
    2461                 :     {
    2462                 :         JSAMPLE      *ppSamples;
    2463                 : 
    2464                 :         eErr = poSrcDS->RasterIO( GF_Read, 0, iLine, nXSize, 1, 
    2465                 :                                   pabyScanline, nXSize, 1, eWorkDT,
    2466                 :                                   nBands, NULL,
    2467                 :                                   nBands*nWorkDTSize, 
    2468            4779 :                                   nBands * nXSize * nWorkDTSize, nWorkDTSize );
    2469                 : 
    2470                 :         // clamp 16bit values to 12bit.
    2471            4779 :         if( nWorkDTSize == 2 )
    2472                 :         {
    2473             110 :             GUInt16 *panScanline = (GUInt16 *) pabyScanline;
    2474                 :             int iPixel;
    2475                 : 
    2476            5210 :             for( iPixel = 0; iPixel < nXSize*nBands; iPixel++ )
    2477                 :             {
    2478            5100 :                 if( panScanline[iPixel] > 4095 )
    2479                 :                 {
    2480               0 :                     panScanline[iPixel] = 4095;
    2481               0 :                     if( !bClipWarn )
    2482                 :                     {
    2483               0 :                         bClipWarn = true;
    2484                 :                         CPLError( CE_Warning, CPLE_AppDefined,
    2485               0 :                                   "One or more pixels clipped to fit 12bit domain for jpeg output." );
    2486                 :                     }
    2487                 :                 }
    2488                 :             }
    2489                 :         }
    2490                 : 
    2491            4779 :         ppSamples = (JSAMPLE *) pabyScanline;
    2492                 : 
    2493            4779 :         if( eErr == CE_None )
    2494            4779 :             jpeg_write_scanlines( &sCInfo, &ppSamples, 1 );
    2495                 : 
    2496            4779 :         if( eErr == CE_None 
    2497                 :             && !pfnProgress( (iLine+1) / ((bAppendMask ? 2 : 1) * (double) nYSize),
    2498                 :                              NULL, pProgressData ) )
    2499                 :         {
    2500               1 :             eErr = CE_Failure;
    2501                 :             CPLError( CE_Failure, CPLE_UserInterrupt, 
    2502               1 :                       "User terminated CreateCopy()" );
    2503                 :         }
    2504                 :     }
    2505                 : 
    2506                 : /* -------------------------------------------------------------------- */
    2507                 : /*      Cleanup and close.                                              */
    2508                 : /* -------------------------------------------------------------------- */
    2509              38 :     CPLFree( pabyScanline );
    2510                 : 
    2511              38 :     if( eErr == CE_None )
    2512              37 :         jpeg_finish_compress( &sCInfo );
    2513              38 :     jpeg_destroy_compress( &sCInfo );
    2514                 : 
    2515              38 :     VSIFCloseL( fpImage );
    2516                 : 
    2517              38 :     if( eErr != CE_None )
    2518                 :     {
    2519               1 :         VSIUnlink( pszFilename );
    2520               1 :         return NULL;
    2521                 :     }
    2522                 : 
    2523                 : /* -------------------------------------------------------------------- */
    2524                 : /*      Append masks to the jpeg file if necessary.                     */
    2525                 : /* -------------------------------------------------------------------- */
    2526              37 :     if( bAppendMask )
    2527                 :     {
    2528               2 :         CPLDebug( "JPEG", "Appending Mask Bitmap" );
    2529                 : 
    2530               2 :         void* pScaledData = GDALCreateScaledProgress( 0.5, 1, pfnProgress, pProgressData );
    2531               2 :         eErr = JPGAppendMask( pszFilename, poSrcDS->GetRasterBand(1)->GetMaskBand(),
    2532               4 :                               GDALScaledProgress, pScaledData );
    2533               2 :         GDALDestroyScaledProgress( pScaledData );
    2534               2 :         nCloneFlags &= (~GCIF_MASK);
    2535                 : 
    2536               2 :         if( eErr != CE_None )
    2537                 :         {
    2538               0 :             VSIUnlink( pszFilename );
    2539               0 :             return NULL;
    2540                 :         }
    2541                 :     }
    2542                 : 
    2543                 : /* -------------------------------------------------------------------- */
    2544                 : /*      Do we need a world file?                                        */
    2545                 : /* -------------------------------------------------------------------- */
    2546              37 :     if( CSLFetchBoolean( papszOptions, "WORLDFILE", FALSE ) )
    2547                 :     {
    2548                 :   double      adfGeoTransform[6];
    2549                 :   
    2550               1 :   poSrcDS->GetGeoTransform( adfGeoTransform );
    2551               1 :   GDALWriteWorldFile( pszFilename, "wld", adfGeoTransform );
    2552                 :     }
    2553                 : 
    2554                 : /* -------------------------------------------------------------------- */
    2555                 : /*      Re-open dataset, and copy any auxilary pam information.         */
    2556                 : /* -------------------------------------------------------------------- */
    2557                 : 
    2558                 :     /* If outputing to stdout, we can't reopen it, so we'll return */
    2559                 :     /* a fake dataset to make the caller happy */
    2560              37 :     CPLPushErrorHandler(CPLQuietErrorHandler);
    2561              37 :     JPGDataset *poDS = (JPGDataset*) Open( pszFilename );
    2562              37 :     CPLPopErrorHandler();
    2563              37 :     if( poDS )
    2564                 :     {
    2565              35 :         poDS->CloneInfo( poSrcDS, nCloneFlags );
    2566              35 :         return poDS;
    2567                 :     }
    2568                 : 
    2569               2 :     CPLErrorReset();
    2570                 : 
    2571               2 :     JPGDataset* poJPG_DS = new JPGDataset();
    2572               2 :     poJPG_DS->nRasterXSize = nXSize;
    2573               2 :     poJPG_DS->nRasterYSize = nYSize;
    2574               4 :     for(int i=0;i<nBands;i++)
    2575               2 :         poJPG_DS->SetBand( i+1, JPGCreateBand( poJPG_DS, i+1) );
    2576               2 :     return poJPG_DS;
    2577                 : }
    2578                 : 
    2579                 : /************************************************************************/
    2580                 : /*                         GDALRegister_JPEG()                          */
    2581                 : /************************************************************************/
    2582                 : 
    2583                 : #if !defined(JPGDataset)
    2584             610 : void GDALRegister_JPEG()
    2585                 : 
    2586                 : {
    2587                 :     GDALDriver  *poDriver;
    2588                 : 
    2589             610 :     if( GDALGetDriverByName( "JPEG" ) == NULL )
    2590                 :     {
    2591             588 :         poDriver = new GDALDriver();
    2592                 :         
    2593             588 :         poDriver->SetDescription( "JPEG" );
    2594                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
    2595             588 :                                    "JPEG JFIF" );
    2596                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
    2597             588 :                                    "frmt_jpeg.html" );
    2598             588 :         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "jpg" );
    2599             588 :         poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/jpeg" );
    2600                 : 
    2601                 : #if defined(JPEG_LIB_MK1_OR_12BIT) || defined(JPEG_DUAL_MODE_8_12)
    2602                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
    2603             588 :                                    "Byte UInt16" );
    2604                 : #else
    2605                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
    2606                 :                                    "Byte" );
    2607                 : #endif
    2608                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, 
    2609                 : "<CreationOptionList>\n"
    2610                 : "   <Option name='PROGRESSIVE' type='boolean' default='NO'/>\n"
    2611                 : "   <Option name='QUALITY' type='int' description='good=100, bad=0, default=75'/>\n"
    2612                 : "   <Option name='WORLDFILE' type='boolean' default='NO'/>\n"
    2613                 : "   <Option name='INTERNAL_MASK' type='boolean' default='YES'/>\n"
    2614                 : "   <Option name='ARITHMETIC' type='boolean' default='NO'/>\n"
    2615                 : #if JPEG_LIB_VERSION_MAJOR >= 8 && \
    2616                 :       (JPEG_LIB_VERSION_MAJOR > 8 || JPEG_LIB_VERSION_MINOR >= 3)
    2617                 : "   <Option name='BLOCK' type='int' description='between 1 and 16'/>\n"
    2618                 : #endif
    2619                 : #if JPEG_LIB_VERSION_MAJOR >= 9
    2620                 : "   <Option name='COLOR_TRANSFORM' type='string-select'>\n"
    2621                 : "       <Value>RGB</Value>"
    2622                 : "       <Value>RGB1</Value>"
    2623                 : "   </Option>"
    2624                 : #endif
    2625             588 : "</CreationOptionList>\n" );
    2626                 : 
    2627             588 :         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
    2628                 : 
    2629             588 :         poDriver->pfnIdentify = JPGDatasetCommon::Identify;
    2630             588 :         poDriver->pfnOpen = JPGDatasetCommon::Open;
    2631             588 :         poDriver->pfnCreateCopy = JPGDataset::CreateCopy;
    2632                 : 
    2633             588 :         GetGDALDriverManager()->RegisterDriver( poDriver );
    2634                 :     }
    2635             610 : }
    2636                 : #endif

Generated by: LCOV version 1.7