Line data Source code
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 : * SPDX-License-Identifier: MIT
16 : ****************************************************************************/
17 :
18 : #include "cpl_port.h"
19 :
20 : // TODO(schwehr): Run IWYU.
21 : #include <cerrno>
22 : #include <climits>
23 : #include <cstddef>
24 : #include <cstdio>
25 : #include <cstdlib>
26 : #include <cstring>
27 : #if HAVE_FCNTL_H
28 : #include <fcntl.h>
29 : #endif
30 : #include <setjmp.h>
31 :
32 : #include <algorithm>
33 : #include <mutex>
34 : #include <string>
35 :
36 : #include "cpl_conv.h"
37 : #include "cpl_error.h"
38 : #include "cpl_progress.h"
39 : #include "cpl_string.h"
40 : #include "cpl_vsi.h"
41 : #include "gdal.h"
42 : #include "gdal_frmts.h"
43 : #include "gdal_pam.h"
44 : #include "gdal_priv.h"
45 :
46 : CPL_C_START
47 :
48 : // So that D_LOSSLESS_SUPPORTED is visible if defined in jmorecfg of libjpeg-turbo >= 2.2
49 : #define JPEG_INTERNAL_OPTIONS
50 :
51 : #ifdef LIBJPEG_12_PATH
52 : #include LIBJPEG_12_PATH
53 : #else
54 : #include "jpeglib.h"
55 : #endif
56 : CPL_C_END
57 : #include "memdataset.h"
58 : #include "vsidataio.h"
59 :
60 : // TIFF header.
61 : typedef struct
62 : {
63 : GUInt16 tiff_magic; // Magic number (defines byte order).
64 : GUInt16 tiff_version; // TIFF version number.
65 : GUInt32 tiff_diroff; // byte offset to first directory.
66 : } TIFFHeader;
67 :
68 : // Ok to use setjmp().
69 : #ifdef _MSC_VER
70 : #pragma warning(disable : 4611)
71 : #endif
72 :
73 : struct JPGDatasetOpenArgs
74 : {
75 : const char *pszFilename = nullptr;
76 : VSILFILE *fpLin = nullptr;
77 : CSLConstList papszSiblingFiles = nullptr;
78 : int nScaleFactor = 1;
79 : bool bDoPAMInitialize = false;
80 : bool bUseInternalOverviews = false;
81 : bool bIsLossless = false;
82 : };
83 :
84 : class JPGDatasetCommon;
85 :
86 : #if defined(JPEG_DUAL_MODE_8_12) && !defined(JPGDataset)
87 : JPGDatasetCommon *JPEGDataset12Open(JPGDatasetOpenArgs *psArgs);
88 : GDALDataset *JPEGDataset12CreateCopy(const char *pszFilename,
89 : GDALDataset *poSrcDS, int bStrict,
90 : char **papszOptions,
91 : GDALProgressFunc pfnProgress,
92 : void *pProgressData);
93 : #endif
94 :
95 : GDALRasterBand *JPGCreateBand(JPGDatasetCommon *poDS, int nBand);
96 :
97 : typedef void (*my_jpeg_write_m_header)(void *cinfo, int marker,
98 : unsigned int datalen);
99 : typedef void (*my_jpeg_write_m_byte)(void *cinfo, int val);
100 :
101 : CPLErr JPGAppendMask(const char *pszJPGFilename, GDALRasterBand *poMask,
102 : GDALProgressFunc pfnProgress, void *pProgressData);
103 : void JPGAddEXIF(GDALDataType eWorkDT, GDALDataset *poSrcDS, char **papszOptions,
104 : void *cinfo, my_jpeg_write_m_header p_jpeg_write_m_header,
105 : my_jpeg_write_m_byte p_jpeg_write_m_byte,
106 : GDALDataset *(pCreateCopy)(const char *, GDALDataset *, int,
107 : char **,
108 : GDALProgressFunc pfnProgress,
109 : void *pProgressData));
110 : void JPGAddICCProfile(void *pInfo, const char *pszICCProfile,
111 : my_jpeg_write_m_header p_jpeg_write_m_header,
112 : my_jpeg_write_m_byte p_jpeg_write_m_byte);
113 :
114 : class GDALJPEGUserData
115 : {
116 : public:
117 : jmp_buf setjmp_buffer;
118 : bool bNonFatalErrorEncountered = false;
119 : void (*p_previous_emit_message)(j_common_ptr cinfo,
120 : int msg_level) = nullptr;
121 : int nMaxScans;
122 :
123 11517 : GDALJPEGUserData()
124 23034 : : nMaxScans(atoi(
125 11517 : CPLGetConfigOption("GDAL_JPEG_MAX_ALLOWED_SCAN_NUMBER", "100")))
126 : {
127 11517 : memset(&setjmp_buffer, 0, sizeof(setjmp_buffer));
128 11517 : }
129 : };
130 :
131 : /************************************************************************/
132 : /* ==================================================================== */
133 : /* JPGDatasetCommon */
134 : /* ==================================================================== */
135 : /************************************************************************/
136 :
137 : class JPGRasterBand;
138 : class JPGMaskBand;
139 :
140 : class JPGDatasetCommon CPL_NON_FINAL : public GDALPamDataset
141 : {
142 : protected:
143 : friend class JPGDataset;
144 : friend class JPGRasterBand;
145 : friend class JPGMaskBand;
146 :
147 : int nScaleFactor;
148 : bool bHasInitInternalOverviews;
149 : int nInternalOverviewsCurrent;
150 : int nInternalOverviewsToFree;
151 : GDALDataset **papoInternalOverviews;
152 : JPGDatasetCommon *poActiveDS = nullptr; /* only valid in parent DS */
153 : JPGDatasetCommon **ppoActiveDS =
154 : nullptr; /* &poActiveDS of poActiveDS from parentDS */
155 : void InitInternalOverviews();
156 : GDALDataset *InitEXIFOverview();
157 :
158 : mutable OGRSpatialReference m_oSRS{};
159 : bool bGeoTransformValid;
160 : double adfGeoTransform[6];
161 : std::vector<gdal::GCP> m_aoGCPs{};
162 :
163 : VSILFILE *m_fpImage;
164 : GUIntBig nSubfileOffset;
165 :
166 : int nLoadedScanline;
167 : GByte *m_pabyScanline;
168 :
169 : bool bHasReadEXIFMetadata;
170 : bool bHasReadXMPMetadata;
171 : bool bHasReadICCMetadata;
172 : bool bHasReadFLIRMetadata = false;
173 : bool bHasReadImageStructureMetadata = false;
174 : char **papszMetadata;
175 : int nExifOffset;
176 : int nInterOffset;
177 : int nGPSOffset;
178 : bool bSwabflag;
179 : int nTiffDirStart;
180 : int nTIFFHEADER;
181 : bool bHasDoneJpegCreateDecompress;
182 : bool bHasDoneJpegStartDecompress;
183 :
184 : int m_nSubdatasetCount = 0;
185 :
186 : // FLIR raw thermal image
187 : bool m_bRawThermalLittleEndian = false;
188 : int m_nRawThermalImageWidth = 0;
189 : int m_nRawThermalImageHeight = 0;
190 : std::vector<GByte> m_abyRawThermalImage{};
191 :
192 : virtual CPLErr LoadScanline(int, GByte *outBuffer = nullptr) = 0;
193 : virtual void StopDecompress() = 0;
194 : virtual CPLErr Restart() = 0;
195 :
196 : virtual int GetDataPrecision() = 0;
197 : virtual int GetOutColorSpace() = 0;
198 : virtual int GetJPEGColorSpace() = 0;
199 :
200 : bool EXIFInit(VSILFILE *);
201 : void ReadICCProfile();
202 :
203 : void CheckForMask();
204 : void DecompressMask();
205 :
206 : void LoadForMetadataDomain(const char *pszDomain);
207 :
208 : void ReadImageStructureMetadata();
209 : void ReadEXIFMetadata();
210 : void ReadXMPMetadata();
211 : void ReadFLIRMetadata();
212 : GDALDataset *OpenFLIRRawThermalImage();
213 :
214 : bool bHasCheckedForMask;
215 : JPGMaskBand *poMaskBand;
216 : GByte *pabyBitMask;
217 : bool bMaskLSBOrder;
218 :
219 : GByte *pabyCMask;
220 : int nCMaskSize;
221 :
222 : // Color space exposed by GDAL. Not necessarily the in_color_space nor
223 : // the out_color_space of JPEG library.
224 : /*J_COLOR_SPACE*/ int eGDALColorSpace;
225 :
226 : bool bIsSubfile;
227 : bool bHasTriedLoadWorldFileOrTab;
228 : void LoadWorldFileOrTab();
229 : CPLString osWldFilename;
230 :
231 : virtual int CloseDependentDatasets() override;
232 :
233 : virtual CPLErr IBuildOverviews(const char *, int, const int *, int,
234 : const int *, GDALProgressFunc, void *,
235 : CSLConstList papszOptions) override;
236 :
237 : public:
238 : JPGDatasetCommon();
239 : virtual ~JPGDatasetCommon();
240 :
241 : virtual CPLErr IRasterIO(GDALRWFlag, int, int, int, int, void *, int, int,
242 : GDALDataType, int, BANDMAP_TYPE,
243 : GSpacing nPixelSpace, GSpacing nLineSpace,
244 : GSpacing nBandSpace,
245 : GDALRasterIOExtraArg *psExtraArg) override;
246 :
247 : virtual CPLErr GetGeoTransform(double *) override;
248 :
249 : virtual int GetGCPCount() override;
250 : const OGRSpatialReference *GetGCPSpatialRef() const override;
251 : virtual const GDAL_GCP *GetGCPs() override;
252 :
253 : const OGRSpatialReference *GetSpatialRef() const override;
254 :
255 : virtual char **GetMetadataDomainList() override;
256 : virtual char **GetMetadata(const char *pszDomain = "") override;
257 : virtual const char *GetMetadataItem(const char *pszName,
258 : const char *pszDomain = "") override;
259 :
260 : virtual char **GetFileList(void) override;
261 :
262 : virtual CPLErr FlushCache(bool bAtClosing) override;
263 :
264 : CPLStringList GetCompressionFormats(int nXOff, int nYOff, int nXSize,
265 : int nYSize, int nBandCount,
266 : const int *panBandList) override;
267 : CPLErr ReadCompressedData(const char *pszFormat, int nXOff, int nYOff,
268 : int nXSize, int nYSize, int nBandCount,
269 : const int *panBandList, void **ppBuffer,
270 : size_t *pnBufferSize,
271 : char **ppszDetailedFormat) override;
272 :
273 : static GDALDataset *Open(GDALOpenInfo *);
274 : };
275 :
276 : /************************************************************************/
277 : /* ==================================================================== */
278 : /* JPGDataset */
279 : /* ==================================================================== */
280 : /************************************************************************/
281 :
282 : class JPGDataset final : public JPGDatasetCommon
283 : {
284 : GDALJPEGUserData sUserData;
285 :
286 : bool ErrorOutOnNonFatalError();
287 :
288 : static void EmitMessage(j_common_ptr cinfo, int msg_level);
289 : static void ProgressMonitor(j_common_ptr cinfo);
290 :
291 : struct jpeg_decompress_struct sDInfo;
292 : struct jpeg_error_mgr sJErr;
293 : struct jpeg_progress_mgr sJProgress;
294 :
295 : virtual CPLErr LoadScanline(int, GByte *outBuffer) override;
296 : CPLErr StartDecompress();
297 : virtual void StopDecompress() override;
298 : virtual CPLErr Restart() override;
299 :
300 25639 : virtual int GetDataPrecision() override
301 : {
302 25639 : return sDInfo.data_precision;
303 : }
304 :
305 162827 : virtual int GetOutColorSpace() override
306 : {
307 162827 : return sDInfo.out_color_space;
308 : }
309 :
310 3 : virtual int GetJPEGColorSpace() override
311 : {
312 3 : return sDInfo.jpeg_color_space;
313 : }
314 :
315 : int nQLevel;
316 : #if !defined(JPGDataset)
317 : void LoadDefaultTables(int);
318 : #endif
319 : void SetScaleNumAndDenom();
320 :
321 : static JPGDatasetCommon *OpenStage2(JPGDatasetOpenArgs *psArgs,
322 : JPGDataset *&poDS);
323 :
324 : public:
325 : JPGDataset();
326 : virtual ~JPGDataset();
327 :
328 : static JPGDatasetCommon *Open(JPGDatasetOpenArgs *psArgs);
329 : static GDALDataset *CreateCopy(const char *pszFilename,
330 : GDALDataset *poSrcDS, int bStrict,
331 : char **papszOptions,
332 : GDALProgressFunc pfnProgress,
333 : void *pProgressData);
334 : static GDALDataset *CreateCopyStage2(
335 : const char *pszFilename, GDALDataset *poSrcDS, char **papszOptions,
336 : GDALProgressFunc pfnProgress, void *pProgressData, VSILFILE *fpImage,
337 : GDALDataType eDT, int nQuality, bool bAppendMask,
338 : GDALJPEGUserData &sUserData, struct jpeg_compress_struct &sCInfo,
339 : struct jpeg_error_mgr &sJErr, GByte *&pabyScanline);
340 : static void ErrorExit(j_common_ptr cinfo);
341 : static void OutputMessage(j_common_ptr cinfo);
342 : };
343 :
344 : /************************************************************************/
345 : /* ==================================================================== */
346 : /* JPGRasterBand */
347 : /* ==================================================================== */
348 : /************************************************************************/
349 :
350 : class JPGRasterBand final : public GDALPamRasterBand
351 : {
352 : friend class JPGDatasetCommon;
353 :
354 : // We have to keep a pointer to the JPGDataset that this JPGRasterBand
355 : // belongs to. In some case, we may have this->poGDS != this->poDS
356 : // For example for a JPGRasterBand that is set to a NITFDataset.
357 : // In other words, this->poDS doesn't necessary point to a JPGDataset
358 : // See ticket #1807.
359 : JPGDatasetCommon *poGDS;
360 :
361 : public:
362 : JPGRasterBand(JPGDatasetCommon *, int);
363 :
364 50456 : virtual ~JPGRasterBand()
365 25228 : {
366 50456 : }
367 :
368 : virtual CPLErr IReadBlock(int, int, void *) override;
369 : virtual GDALColorInterp GetColorInterpretation() override;
370 :
371 : virtual GDALSuggestedBlockAccessPattern
372 18 : GetSuggestedBlockAccessPattern() const override
373 : {
374 18 : return GSBAP_TOP_TO_BOTTOM;
375 : }
376 :
377 : virtual GDALRasterBand *GetMaskBand() override;
378 : virtual int GetMaskFlags() override;
379 :
380 : virtual GDALRasterBand *GetOverview(int i) override;
381 : virtual int GetOverviewCount() override;
382 : };
383 :
384 : #if !defined(JPGDataset)
385 :
386 : /************************************************************************/
387 : /* ==================================================================== */
388 : /* JPGMaskBand */
389 : /* ==================================================================== */
390 : /************************************************************************/
391 :
392 : class JPGMaskBand final : public GDALRasterBand
393 : {
394 : protected:
395 : virtual CPLErr IReadBlock(int, int, void *) override;
396 :
397 : public:
398 : explicit JPGMaskBand(JPGDatasetCommon *poDS);
399 :
400 30 : virtual ~JPGMaskBand()
401 15 : {
402 30 : }
403 : };
404 :
405 : /************************************************************************/
406 : /* GDALRegister_JPEG() */
407 : /************************************************************************/
408 :
409 : class GDALJPGDriver final : public GDALDriver
410 : {
411 : public:
412 1607 : GDALJPGDriver() = default;
413 :
414 : char **GetMetadata(const char *pszDomain = "") override;
415 : const char *GetMetadataItem(const char *pszName,
416 : const char *pszDomain = "") override;
417 :
418 : private:
419 : std::mutex m_oMutex{};
420 : bool m_bMetadataInitialized = false;
421 : void InitializeMetadata();
422 : };
423 :
424 : #endif // !defined(JPGDataset)
|