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