LCOV - code coverage report
Current view: directory - frmts/jpeg - jpgdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 872 733 84.1 %
Date: 2012-12-26 Functions: 69 51 73.9 %

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

Generated by: LCOV version 1.7