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