LCOV - code coverage report
Current view: directory - frmts/jpeg - jpgdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 835 625 74.9 %
Date: 2010-01-09 Functions: 70 57 81.4 %

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

Generated by: LCOV version 1.7