1 /****************************************************************************** 2 * $Id: jpgdataset.cpp 37340 2017-02-11 18:28:02Z goatbar 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 * Copyright (c) 2007-2014, Even Rouault <even dot rouault at spatialys.com> 11 * 12 * Portions Copyright (c) Her majesty the Queen in right of Canada as 13 * represented by the Minister of National Defence, 2006. 14 * 15 * Permission is hereby granted, free of charge, to any person obtaining a 16 * copy of this software and associated documentation files (the "Software"), 17 * to deal in the Software without restriction, including without limitation 18 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 19 * and/or sell copies of the Software, and to permit persons to whom the 20 * Software is furnished to do so, subject to the following conditions: 21 * 22 * The above copyright notice and this permission notice shall be included 23 * in all copies or substantial portions of the Software. 24 * 25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 26 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 28 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 30 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 31 * DEALINGS IN THE SOFTWARE. 32 ****************************************************************************/ 33 34 #include "cpl_port.h" 35 36 // TODO(schwehr): Run IWYU. 37 #include <cerrno> 38 #include <climits> 39 #include <cstddef> 40 #include <cstdio> 41 #include <cstdlib> 42 #include <cstring> 43 #if HAVE_FCNTL_H 44 # include <fcntl.h> 45 #endif 46 #include <setjmp.h> 47 48 #include <algorithm> 49 #include <string> 50 51 #include "cpl_conv.h" 52 #include "cpl_error.h" 53 #include "cpl_progress.h" 54 #include "cpl_string.h" 55 #include "cpl_vsi.h" 56 #include "gdal.h" 57 #include "gdal_frmts.h" 58 #include "gdal_pam.h" 59 #include "gdal_priv.h" 60 CPL_C_START 61 #ifdef LIBJPEG_12_PATH 62 # include LIBJPEG_12_PATH 63 #else 64 # include "jpeglib.h" 65 #endif 66 CPL_C_END 67 #include "memdataset.h" 68 #include "vsidataio.h" 69 70 // TIFF header. 71 typedef struct 72 { 73 GUInt16 tiff_magic; // Magic number (defines byte order). 74 GUInt16 tiff_version; // TIFF version number. 75 GUInt32 tiff_diroff; // byte offset to first directory. 76 } TIFFHeader; 77 78 // Ok to use setjmp(). 79 #ifdef _MSC_VER 80 # pragma warning(disable:4611) 81 #endif 82 83 typedef struct 84 { 85 const char *pszFilename; 86 VSILFILE *fpLin; 87 char **papszSiblingFiles; 88 int nScaleFactor; 89 bool bDoPAMInitialize; 90 bool bUseInternalOverviews; 91 } JPGDatasetOpenArgs; 92 93 class JPGDatasetCommon; 94 95 #if defined(JPEG_DUAL_MODE_8_12) && !defined(JPGDataset) 96 JPGDatasetCommon *JPEGDataset12Open(JPGDatasetOpenArgs *psArgs); 97 GDALDataset *JPEGDataset12CreateCopy( const char *pszFilename, 98 GDALDataset *poSrcDS, 99 int bStrict, char **papszOptions, 100 GDALProgressFunc pfnProgress, 101 void *pProgressData ); 102 #endif 103 104 // Do we want to do special processing suitable for when JSAMPLE is a 105 // 16bit value? 106 #if defined(JPEG_LIB_MK1) 107 # define JPEG_LIB_MK1_OR_12BIT 1 108 #elif BITS_IN_JSAMPLE == 12 109 # define JPEG_LIB_MK1_OR_12BIT 1 110 #endif 111 112 GDALRasterBand *JPGCreateBand(JPGDatasetCommon *poDS, int nBand); 113 114 typedef void (*my_jpeg_write_m_header)(void *cinfo, int marker, 115 unsigned int datalen); 116 typedef void (*my_jpeg_write_m_byte)(void *cinfo, int val); 117 118 CPLErr JPGAppendMask( const char *pszJPGFilename, GDALRasterBand *poMask, 119 GDALProgressFunc pfnProgress, void *pProgressData ); 120 void JPGAddEXIF ( GDALDataType eWorkDT, 121 GDALDataset *poSrcDS, char** papszOptions, 122 void *cinfo, 123 my_jpeg_write_m_header p_jpeg_write_m_header, 124 my_jpeg_write_m_byte p_jpeg_write_m_byte, 125 GDALDataset *(pCreateCopy)( 126 const char *, GDALDataset *, 127 int, char **, 128 GDALProgressFunc pfnProgress, 129 void *pProgressData ) ); 130 void JPGAddICCProfile( void *pInfo, 131 const char *pszICCProfile, 132 my_jpeg_write_m_header p_jpeg_write_m_header, 133 my_jpeg_write_m_byte p_jpeg_write_m_byte); 134 135 class GDALJPEGUserData 136 { 137 public: 138 jmp_buf setjmp_buffer; 139 bool bNonFatalErrorEncountered = false; 140 void (*p_previous_emit_message)(j_common_ptr cinfo, int msg_level) = nullptr; 141 int nMaxScans; 142 GDALJPEGUserData()143 GDALJPEGUserData() : 144 nMaxScans(atoi( 145 CPLGetConfigOption("GDAL_JPEG_MAX_ALLOWED_SCAN_NUMBER", "100"))) 146 { 147 memset(&setjmp_buffer, 0, sizeof(setjmp_buffer)); 148 } 149 }; 150 151 /************************************************************************/ 152 /* ==================================================================== */ 153 /* JPGDatasetCommon */ 154 /* ==================================================================== */ 155 /************************************************************************/ 156 157 class JPGRasterBand; 158 class JPGMaskBand; 159 160 class JPGDatasetCommon CPL_NON_FINAL: public GDALPamDataset 161 { 162 protected: 163 friend class JPGDataset; 164 friend class JPGRasterBand; 165 friend class JPGMaskBand; 166 167 int nScaleFactor; 168 bool bHasInitInternalOverviews; 169 int nInternalOverviewsCurrent; 170 int nInternalOverviewsToFree; 171 GDALDataset **papoInternalOverviews; 172 JPGDatasetCommon* poActiveDS = nullptr; /* only valid in parent DS */ 173 JPGDatasetCommon** ppoActiveDS = nullptr; /* &poActiveDS of poActiveDS from parentDS */ 174 void InitInternalOverviews(); 175 GDALDataset *InitEXIFOverview(); 176 177 char *pszProjection; 178 bool bGeoTransformValid; 179 double adfGeoTransform[6]; 180 int nGCPCount; 181 GDAL_GCP *pasGCPList; 182 183 VSILFILE *fpImage; 184 GUIntBig nSubfileOffset; 185 186 int nLoadedScanline; 187 GByte *pabyScanline; 188 189 bool bHasReadEXIFMetadata; 190 bool bHasReadXMPMetadata; 191 bool bHasReadICCMetadata; 192 bool bHasReadFLIRMetadata = false; 193 char **papszMetadata; 194 int nExifOffset; 195 int nInterOffset; 196 int nGPSOffset; 197 bool bSwabflag; 198 int nTiffDirStart; 199 int nTIFFHEADER; 200 bool bHasDoneJpegCreateDecompress; 201 bool bHasDoneJpegStartDecompress; 202 203 int m_nSubdatasetCount = 0; 204 205 // FLIR raw thermal image 206 bool m_bRawThermalLittleEndian = false; 207 int m_nRawThermalImageWidth = 0; 208 int m_nRawThermalImageHeight = 0; 209 std::vector<GByte> m_abyRawThermalImage{}; 210 211 virtual CPLErr LoadScanline(int, GByte* outBuffer = nullptr) = 0; 212 virtual void StopDecompress() = 0; 213 virtual CPLErr Restart() = 0; 214 215 virtual int GetDataPrecision() = 0; 216 virtual int GetOutColorSpace() = 0; 217 218 bool EXIFInit(VSILFILE *); 219 void ReadICCProfile(); 220 221 void CheckForMask(); 222 void DecompressMask(); 223 224 void LoadForMetadataDomain( const char *pszDomain ); 225 226 void ReadEXIFMetadata(); 227 void ReadXMPMetadata(); 228 void ReadFLIRMetadata(); 229 GDALDataset* OpenFLIRRawThermalImage(); 230 231 bool bHasCheckedForMask; 232 JPGMaskBand *poMaskBand; 233 GByte *pabyBitMask; 234 bool bMaskLSBOrder; 235 236 GByte *pabyCMask; 237 int nCMaskSize; 238 239 // Color space exposed by GDAL. Not necessarily the in_color_space nor 240 // the out_color_space of JPEG library. 241 /*J_COLOR_SPACE*/ int eGDALColorSpace; 242 243 bool bIsSubfile; 244 bool bHasTriedLoadWorldFileOrTab; 245 void LoadWorldFileOrTab(); 246 CPLString osWldFilename; 247 248 virtual int CloseDependentDatasets() override; 249 250 virtual CPLErr IBuildOverviews( const char *, int, int *, int, int *, 251 GDALProgressFunc, void * ) override; 252 253 public: 254 JPGDatasetCommon(); 255 virtual ~JPGDatasetCommon(); 256 257 virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int, 258 void *, int, int, GDALDataType, 259 int, int *, 260 GSpacing nPixelSpace, GSpacing nLineSpace, 261 GSpacing nBandSpace, 262 GDALRasterIOExtraArg* psExtraArg ) override; 263 264 virtual CPLErr GetGeoTransform( double * ) override; 265 266 virtual int GetGCPCount() override; 267 virtual const char *_GetGCPProjection() override; GetGCPSpatialRef()268 const OGRSpatialReference* GetGCPSpatialRef() const override { 269 return GetGCPSpatialRefFromOldGetGCPProjection(); 270 } 271 virtual const GDAL_GCP *GetGCPs() override; 272 273 virtual char **GetMetadataDomainList() override; 274 virtual char **GetMetadata( const char *pszDomain = "" ) override; 275 virtual const char *GetMetadataItem( const char *pszName, 276 const char *pszDomain = "" ) override; 277 278 virtual char **GetFileList(void) override; 279 280 virtual void FlushCache(void) override; 281 282 static int Identify( GDALOpenInfo * ); 283 static GDALDataset *Open( GDALOpenInfo * ); 284 }; 285 286 /************************************************************************/ 287 /* ==================================================================== */ 288 /* JPGDataset */ 289 /* ==================================================================== */ 290 /************************************************************************/ 291 292 class JPGDataset final: public JPGDatasetCommon 293 { 294 GDALJPEGUserData sUserData; 295 296 bool ErrorOutOnNonFatalError(); 297 298 static void EmitMessage(j_common_ptr cinfo, int msg_level); 299 static void ProgressMonitor (j_common_ptr cinfo ); 300 301 struct jpeg_decompress_struct sDInfo; 302 struct jpeg_error_mgr sJErr; 303 struct jpeg_progress_mgr sJProgress; 304 305 virtual CPLErr LoadScanline(int, GByte* outBuffer) override; 306 virtual void StopDecompress() override; 307 virtual CPLErr Restart() override; GetDataPrecision()308 virtual int GetDataPrecision() override { return sDInfo.data_precision; } GetOutColorSpace()309 virtual int GetOutColorSpace() override { return sDInfo.out_color_space; } 310 311 int nQLevel; 312 #if !defined(JPGDataset) 313 void LoadDefaultTables(int); 314 #endif 315 void SetScaleNumAndDenom(); 316 317 static JPGDatasetCommon *OpenStage2( JPGDatasetOpenArgs *psArgs, 318 JPGDataset *&poDS ); 319 320 public: 321 JPGDataset(); 322 virtual ~JPGDataset(); 323 324 static JPGDatasetCommon *Open( JPGDatasetOpenArgs *psArgs ); 325 static GDALDataset *CreateCopy( const char *pszFilename, 326 GDALDataset *poSrcDS, 327 int bStrict, char ** papszOptions, 328 GDALProgressFunc pfnProgress, 329 void *pProgressData ); 330 static GDALDataset *CreateCopyStage2( 331 const char *pszFilename, GDALDataset *poSrcDS, char **papszOptions, 332 GDALProgressFunc pfnProgress, void *pProgressData, VSILFILE *fpImage, 333 GDALDataType eDT, int nQuality, bool bAppendMask, 334 GDALJPEGUserData &sUserData, struct jpeg_compress_struct &sCInfo, 335 struct jpeg_error_mgr &sJErr, GByte *&pabyScanline); 336 static void ErrorExit(j_common_ptr cinfo); 337 }; 338 339 /************************************************************************/ 340 /* ==================================================================== */ 341 /* JPGRasterBand */ 342 /* ==================================================================== */ 343 /************************************************************************/ 344 345 class JPGRasterBand final: public GDALPamRasterBand 346 { 347 friend class JPGDatasetCommon; 348 349 // We have to keep a pointer to the JPGDataset that this JPGRasterBand 350 // belongs to. In some case, we may have this->poGDS != this->poDS 351 // For example for a JPGRasterBand that is set to a NITFDataset. 352 // In other words, this->poDS doesn't necessary point to a JPGDataset 353 // See ticket #1807. 354 JPGDatasetCommon *poGDS; 355 356 public: 357 JPGRasterBand(JPGDatasetCommon *, int); ~JPGRasterBand()358 virtual ~JPGRasterBand() {} 359 360 virtual CPLErr IReadBlock( int, int, void * ) override; 361 virtual GDALColorInterp GetColorInterpretation() override; 362 363 virtual GDALRasterBand *GetMaskBand() override; 364 virtual int GetMaskFlags() override; 365 366 virtual GDALRasterBand *GetOverview(int i) override; 367 virtual int GetOverviewCount() override; 368 }; 369 370 #if !defined(JPGDataset) 371 372 /************************************************************************/ 373 /* ==================================================================== */ 374 /* JPGMaskBand */ 375 /* ==================================================================== */ 376 /************************************************************************/ 377 378 class JPGMaskBand final: public GDALRasterBand 379 { 380 protected: 381 virtual CPLErr IReadBlock( int, int, void * ) override; 382 383 public: 384 explicit JPGMaskBand( JPGDatasetCommon *poDS ); ~JPGMaskBand()385 virtual ~JPGMaskBand() {} 386 }; 387 388 /************************************************************************/ 389 /* GDALRegister_JPEG() */ 390 /************************************************************************/ 391 392 class GDALJPGDriver final: public GDALDriver 393 { 394 public: GDALJPGDriver()395 GDALJPGDriver() {} 396 397 char **GetMetadata( const char *pszDomain = "" ) override; 398 const char *GetMetadataItem( const char *pszName, 399 const char *pszDomain = "" ) override; 400 }; 401 402 #endif // !defined(JPGDataset) 403