LCOV - code coverage report
Current view: directory - frmts/jpeg - jpgdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 974 744 76.4 %
Date: 2011-12-18 Functions: 85 58 68.2 %

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

Generated by: LCOV version 1.7