LCOV - code coverage report
Current view: directory - frmts/jpeg - jpgdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 987 753 76.3 %
Date: 2012-04-28 Functions: 85 58 68.2 %

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

Generated by: LCOV version 1.7