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 11518 : GDALJPEGUserData()
124 23037 : : nMaxScans(atoi(
125 11518 : CPLGetConfigOption("GDAL_JPEG_MAX_ALLOWED_SCAN_NUMBER", "100")))
126 : {
127 11519 : memset(&setjmp_buffer, 0, sizeof(setjmp_buffer));
128 11519 : }
129 : };
130 :
131 : /************************************************************************/
132 : /* ==================================================================== */
133 : /* JPGDatasetCommon */
134 : /* ==================================================================== */
135 : /************************************************************************/
136 :
137 : class JPGRasterBand;
138 : class JPGMaskBand;
139 :
140 11254 : 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{1};
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 : GDALGeoTransform m_gt{};
161 : std::vector<gdal::GCP> m_aoGCPs{};
162 :
163 : VSILFILE *m_fpImage{};
164 : GUIntBig nSubfileOffset{};
165 :
166 : int nLoadedScanline{-1};
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{-1};
176 : int nInterOffset{-1};
177 : int nGPSOffset{-1};
178 : bool bSwabflag{};
179 : int nTiffDirStart{-1};
180 : int nTIFFHEADER{-1};
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{true};
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{JCS_UNKNOWN};
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 : CPL_DISALLOW_COPY_ASSIGN(JPGDatasetCommon)
238 :
239 : public:
240 : JPGDatasetCommon();
241 : virtual ~JPGDatasetCommon();
242 :
243 : virtual CPLErr IRasterIO(GDALRWFlag, int, int, int, int, void *, int, int,
244 : GDALDataType, int, BANDMAP_TYPE,
245 : GSpacing nPixelSpace, GSpacing nLineSpace,
246 : GSpacing nBandSpace,
247 : GDALRasterIOExtraArg *psExtraArg) override;
248 :
249 : virtual CPLErr GetGeoTransform(GDALGeoTransform >) const override;
250 :
251 : virtual int GetGCPCount() override;
252 : const OGRSpatialReference *GetGCPSpatialRef() const override;
253 : virtual const GDAL_GCP *GetGCPs() override;
254 :
255 : const OGRSpatialReference *GetSpatialRef() const override;
256 :
257 : virtual char **GetMetadataDomainList() override;
258 : virtual char **GetMetadata(const char *pszDomain = "") override;
259 : virtual const char *GetMetadataItem(const char *pszName,
260 : const char *pszDomain = "") override;
261 :
262 : virtual char **GetFileList(void) override;
263 :
264 : virtual CPLErr FlushCache(bool bAtClosing) override;
265 :
266 : CPLStringList GetCompressionFormats(int nXOff, int nYOff, int nXSize,
267 : int nYSize, int nBandCount,
268 : const int *panBandList) override;
269 : CPLErr ReadCompressedData(const char *pszFormat, int nXOff, int nYOff,
270 : int nXSize, int nYSize, int nBandCount,
271 : const int *panBandList, void **ppBuffer,
272 : size_t *pnBufferSize,
273 : char **ppszDetailedFormat) override;
274 :
275 : static GDALDataset *Open(GDALOpenInfo *);
276 : };
277 :
278 : /************************************************************************/
279 : /* ==================================================================== */
280 : /* JPGDataset */
281 : /* ==================================================================== */
282 : /************************************************************************/
283 :
284 : class JPGDataset final : public JPGDatasetCommon
285 : {
286 : GDALJPEGUserData sUserData{};
287 :
288 : bool ErrorOutOnNonFatalError();
289 :
290 : static void EmitMessage(j_common_ptr cinfo, int msg_level);
291 : static void ProgressMonitor(j_common_ptr cinfo);
292 :
293 : struct jpeg_decompress_struct sDInfo
294 : {
295 : };
296 :
297 : struct jpeg_error_mgr sJErr
298 : {
299 : };
300 :
301 : struct jpeg_progress_mgr sJProgress
302 : {
303 : };
304 :
305 : virtual CPLErr LoadScanline(int, GByte *outBuffer) override;
306 : CPLErr StartDecompress();
307 : virtual void StopDecompress() override;
308 : virtual CPLErr Restart() override;
309 :
310 25645 : virtual int GetDataPrecision() override
311 : {
312 25645 : return sDInfo.data_precision;
313 : }
314 :
315 162829 : virtual int GetOutColorSpace() override
316 : {
317 162829 : return sDInfo.out_color_space;
318 : }
319 :
320 3 : virtual int GetJPEGColorSpace() override
321 : {
322 3 : return sDInfo.jpeg_color_space;
323 : }
324 :
325 : int nQLevel = 0;
326 : #if !defined(JPGDataset)
327 : void LoadDefaultTables(int);
328 : #endif
329 : void SetScaleNumAndDenom();
330 :
331 : static JPGDatasetCommon *OpenStage2(JPGDatasetOpenArgs *psArgs,
332 : JPGDataset *&poDS);
333 :
334 : public:
335 : JPGDataset();
336 : virtual ~JPGDataset();
337 :
338 : static JPGDatasetCommon *Open(JPGDatasetOpenArgs *psArgs);
339 : static GDALDataset *CreateCopy(const char *pszFilename,
340 : GDALDataset *poSrcDS, int bStrict,
341 : char **papszOptions,
342 : GDALProgressFunc pfnProgress,
343 : void *pProgressData);
344 : static GDALDataset *CreateCopyStage2(
345 : const char *pszFilename, GDALDataset *poSrcDS, char **papszOptions,
346 : GDALProgressFunc pfnProgress, void *pProgressData, VSILFILE *fpImage,
347 : GDALDataType eDT, int nQuality, bool bAppendMask,
348 : GDALJPEGUserData &sUserData, struct jpeg_compress_struct &sCInfo,
349 : struct jpeg_error_mgr &sJErr, GByte *&pabyScanline);
350 : static void ErrorExit(j_common_ptr cinfo);
351 : static void OutputMessage(j_common_ptr cinfo);
352 : };
353 :
354 : /************************************************************************/
355 : /* ==================================================================== */
356 : /* JPGRasterBand */
357 : /* ==================================================================== */
358 : /************************************************************************/
359 :
360 : class JPGRasterBand final : public GDALPamRasterBand
361 : {
362 : friend class JPGDatasetCommon;
363 :
364 : // We have to keep a pointer to the JPGDataset that this JPGRasterBand
365 : // belongs to. In some case, we may have this->poGDS != this->poDS
366 : // For example for a JPGRasterBand that is set to a NITFDataset.
367 : // In other words, this->poDS doesn't necessary point to a JPGDataset
368 : // See ticket #1807.
369 : JPGDatasetCommon *poGDS{};
370 :
371 : CPL_DISALLOW_COPY_ASSIGN(JPGRasterBand)
372 :
373 : public:
374 : JPGRasterBand(JPGDatasetCommon *, int);
375 :
376 50453 : virtual ~JPGRasterBand()
377 25224 : {
378 50456 : }
379 :
380 : virtual CPLErr IReadBlock(int, int, void *) override;
381 : virtual GDALColorInterp GetColorInterpretation() override;
382 :
383 : virtual GDALSuggestedBlockAccessPattern
384 18 : GetSuggestedBlockAccessPattern() const override
385 : {
386 18 : return GSBAP_TOP_TO_BOTTOM;
387 : }
388 :
389 : virtual GDALRasterBand *GetMaskBand() override;
390 : virtual int GetMaskFlags() override;
391 :
392 : virtual GDALRasterBand *GetOverview(int i) override;
393 : virtual int GetOverviewCount() override;
394 : };
395 :
396 : #if !defined(JPGDataset)
397 :
398 : /************************************************************************/
399 : /* ==================================================================== */
400 : /* JPGMaskBand */
401 : /* ==================================================================== */
402 : /************************************************************************/
403 :
404 : class JPGMaskBand final : public GDALRasterBand
405 : {
406 : protected:
407 : virtual CPLErr IReadBlock(int, int, void *) override;
408 :
409 : public:
410 : explicit JPGMaskBand(JPGDatasetCommon *poDS);
411 :
412 30 : virtual ~JPGMaskBand()
413 15 : {
414 30 : }
415 : };
416 :
417 : /************************************************************************/
418 : /* GDALRegister_JPEG() */
419 : /************************************************************************/
420 :
421 : class GDALJPGDriver final : public GDALDriver
422 : {
423 : public:
424 1653 : GDALJPGDriver() = default;
425 :
426 : char **GetMetadata(const char *pszDomain = "") override;
427 : const char *GetMetadataItem(const char *pszName,
428 : const char *pszDomain = "") override;
429 :
430 : private:
431 : std::mutex m_oMutex{};
432 : bool m_bMetadataInitialized = false;
433 : void InitializeMetadata();
434 : };
435 :
436 : #endif // !defined(JPGDataset)
|