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 : #include <setjmp.h>
28 :
29 : #include <algorithm>
30 : #include <mutex>
31 : #include <string>
32 :
33 : #include "cpl_conv.h"
34 : #include "cpl_error.h"
35 : #include "cpl_progress.h"
36 : #include "cpl_string.h"
37 : #include "cpl_vsi.h"
38 : #include "cpl_vsi_virtual.h"
39 : #include "gdal.h"
40 : #include "gdal_frmts.h"
41 : #include "gdal_pam.h"
42 : #include "gdal_priv.h"
43 :
44 : CPL_C_START
45 :
46 : // So that D_LOSSLESS_SUPPORTED is visible if defined in jmorecfg of libjpeg-turbo >= 2.2
47 : #define JPEG_INTERNAL_OPTIONS
48 :
49 : #ifdef LIBJPEG_12_PATH
50 : #include LIBJPEG_12_PATH
51 : #else
52 : #include "jpeglib.h"
53 : #endif
54 : CPL_C_END
55 : #include "memdataset.h"
56 : #include "vsidataio.h"
57 :
58 : // TIFF header.
59 : typedef struct
60 : {
61 : GUInt16 tiff_magic; // Magic number (defines byte order).
62 : GUInt16 tiff_version; // TIFF version number.
63 : GUInt32 tiff_diroff; // byte offset to first directory.
64 : } TIFFHeader;
65 :
66 : // Ok to use setjmp().
67 : #ifdef _MSC_VER
68 : #pragma warning(disable : 4611)
69 : #endif
70 :
71 : struct JPGDatasetOpenArgs
72 : {
73 : const char *pszFilename = nullptr;
74 : VSILFILE *fpLin = nullptr;
75 : CSLConstList papszSiblingFiles = nullptr;
76 : int nScaleFactor = 1;
77 : bool bDoPAMInitialize = false;
78 : bool bUseInternalOverviews = false;
79 : bool bIsLossless = false;
80 : };
81 :
82 : class JPGDatasetCommon;
83 :
84 : #if defined(JPEG_DUAL_MODE_8_12) && !defined(JPGDataset)
85 : JPGDatasetCommon *JPEGDataset12Open(JPGDatasetOpenArgs *psArgs);
86 : GDALDataset *JPEGDataset12CreateCopy(const char *pszFilename,
87 : GDALDataset *poSrcDS, int bStrict,
88 : char **papszOptions,
89 : GDALProgressFunc pfnProgress,
90 : void *pProgressData);
91 : #endif
92 :
93 : GDALRasterBand *JPGCreateBand(JPGDatasetCommon *poDS, int nBand);
94 :
95 : typedef void (*my_jpeg_write_m_header)(void *cinfo, int marker,
96 : unsigned int datalen);
97 : typedef void (*my_jpeg_write_m_byte)(void *cinfo, int val);
98 :
99 : CPLErr JPGAppendMask(const char *pszJPGFilename, GDALRasterBand *poMask,
100 : GDALProgressFunc pfnProgress, void *pProgressData);
101 : void JPGAddEXIF(GDALDataType eWorkDT, GDALDataset *poSrcDS, char **papszOptions,
102 : void *cinfo, my_jpeg_write_m_header p_jpeg_write_m_header,
103 : my_jpeg_write_m_byte p_jpeg_write_m_byte,
104 : GDALDataset *(pCreateCopy)(const char *, GDALDataset *, int,
105 : char **,
106 : GDALProgressFunc pfnProgress,
107 : void *pProgressData));
108 : void JPGAddICCProfile(void *pInfo, const char *pszICCProfile,
109 : my_jpeg_write_m_header p_jpeg_write_m_header,
110 : my_jpeg_write_m_byte p_jpeg_write_m_byte);
111 :
112 : class GDALJPEGUserData
113 : {
114 : public:
115 : jmp_buf setjmp_buffer;
116 : bool bNonFatalErrorEncountered = false;
117 : void (*p_previous_emit_message)(j_common_ptr cinfo,
118 : int msg_level) = nullptr;
119 : int nMaxScans;
120 :
121 11518 : GDALJPEGUserData()
122 23037 : : nMaxScans(atoi(
123 11518 : CPLGetConfigOption("GDAL_JPEG_MAX_ALLOWED_SCAN_NUMBER", "100")))
124 : {
125 11519 : memset(&setjmp_buffer, 0, sizeof(setjmp_buffer));
126 11519 : }
127 : };
128 :
129 : /************************************************************************/
130 : /* ==================================================================== */
131 : /* JPGDatasetCommon */
132 : /* ==================================================================== */
133 : /************************************************************************/
134 :
135 : class JPGRasterBand;
136 : class JPGMaskBand;
137 :
138 11256 : class JPGDatasetCommon CPL_NON_FINAL : public GDALPamDataset
139 : {
140 : protected:
141 : friend class JPGDataset;
142 : friend class JPGRasterBand;
143 : friend class JPGMaskBand;
144 :
145 : int nScaleFactor{1};
146 : bool bHasInitInternalOverviews{};
147 : int nInternalOverviewsCurrent{};
148 : int nInternalOverviewsToFree{};
149 : GDALDataset **papoInternalOverviews{};
150 : JPGDatasetCommon *poActiveDS = nullptr; /* only valid in parent DS */
151 : JPGDatasetCommon **ppoActiveDS =
152 : nullptr; /* &poActiveDS of poActiveDS from parentDS */
153 : void InitInternalOverviews();
154 : GDALDataset *InitEXIFOverview();
155 :
156 : mutable OGRSpatialReference m_oSRS{};
157 : bool bGeoTransformValid{};
158 : GDALGeoTransform m_gt{};
159 : std::vector<gdal::GCP> m_aoGCPs{};
160 :
161 : VSILFILE *m_fpImage{};
162 : GUIntBig nSubfileOffset{};
163 :
164 : int nLoadedScanline{-1};
165 : GByte *m_pabyScanline{};
166 :
167 : bool bHasReadEXIFMetadata{};
168 : bool bHasReadXMPMetadata{};
169 : bool bHasReadICCMetadata{};
170 : bool bHasReadFLIRMetadata = false;
171 : bool bHasReadDJIMetadata = false;
172 : bool bHasReadImageStructureMetadata = false;
173 : char **papszMetadata{};
174 : int nExifOffset{-1};
175 : int nInterOffset{-1};
176 : int nGPSOffset{-1};
177 : bool bSwabflag{};
178 : int nTiffDirStart{-1};
179 : int nTIFFHEADER{-1};
180 : bool bHasDoneJpegCreateDecompress{};
181 : bool bHasDoneJpegStartDecompress{};
182 :
183 : int m_nSubdatasetCount = 0;
184 :
185 : // FLIR or DJI 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 ReadThermalMetadata();
211 : void ReadFLIRMetadata();
212 : void ReadDJIMetadata();
213 : GDALDataset *OpenRawThermalImage();
214 :
215 : bool bHasCheckedForMask{};
216 : JPGMaskBand *poMaskBand{};
217 : GByte *pabyBitMask{};
218 : bool bMaskLSBOrder{true};
219 :
220 : GByte *pabyCMask{};
221 : int nCMaskSize{};
222 :
223 : // Color space exposed by GDAL. Not necessarily the in_color_space nor
224 : // the out_color_space of JPEG library.
225 : /*J_COLOR_SPACE*/ int eGDALColorSpace{JCS_UNKNOWN};
226 :
227 : bool bIsSubfile{};
228 : bool bHasTriedLoadWorldFileOrTab{};
229 : void LoadWorldFileOrTab();
230 : CPLString osWldFilename{};
231 :
232 : int CloseDependentDatasets() override;
233 :
234 : CPLErr IBuildOverviews(const char *, int, const int *, int, const int *,
235 : GDALProgressFunc, void *,
236 : CSLConstList papszOptions) override;
237 :
238 : CPL_DISALLOW_COPY_ASSIGN(JPGDatasetCommon)
239 :
240 : public:
241 : JPGDatasetCommon();
242 : ~JPGDatasetCommon() override;
243 :
244 : CPLErr IRasterIO(GDALRWFlag, int, int, int, int, void *, int, int,
245 : GDALDataType, int, BANDMAP_TYPE, GSpacing nPixelSpace,
246 : GSpacing nLineSpace, GSpacing nBandSpace,
247 : GDALRasterIOExtraArg *psExtraArg) override;
248 :
249 : CPLErr GetGeoTransform(GDALGeoTransform >) const override;
250 :
251 : int GetGCPCount() override;
252 : const OGRSpatialReference *GetGCPSpatialRef() const override;
253 : const GDAL_GCP *GetGCPs() override;
254 :
255 : const OGRSpatialReference *GetSpatialRef() const override;
256 :
257 : char **GetMetadataDomainList() override;
258 : char **GetMetadata(const char *pszDomain = "") override;
259 : virtual const char *GetMetadataItem(const char *pszName,
260 : const char *pszDomain = "") override;
261 :
262 : char **GetFileList(void) override;
263 :
264 : 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 : CPLErr LoadScanline(int, GByte *outBuffer) override;
306 : CPLErr StartDecompress();
307 : void StopDecompress() override;
308 : CPLErr Restart() override;
309 :
310 25651 : int GetDataPrecision() override
311 : {
312 25651 : return sDInfo.data_precision;
313 : }
314 :
315 162833 : int GetOutColorSpace() override
316 : {
317 162833 : return sDInfo.out_color_space;
318 : }
319 :
320 3 : 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 : ~JPGDataset() override;
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 *
345 : CreateCopyStage2(const char *pszFilename, GDALDataset *poSrcDS,
346 : char **papszOptions, GDALProgressFunc pfnProgress,
347 : void *pProgressData, VSIVirtualHandleUniquePtr fpImage,
348 : GDALDataType eDT, int nQuality, bool bAppendMask,
349 : GDALJPEGUserData &sUserData,
350 : struct jpeg_compress_struct &sCInfo,
351 : struct jpeg_error_mgr &sJErr, GByte *&pabyScanline);
352 : static void ErrorExit(j_common_ptr cinfo);
353 : static void OutputMessage(j_common_ptr cinfo);
354 : };
355 :
356 : /************************************************************************/
357 : /* ==================================================================== */
358 : /* JPGRasterBand */
359 : /* ==================================================================== */
360 : /************************************************************************/
361 :
362 : class JPGRasterBand final : public GDALPamRasterBand
363 : {
364 : friend class JPGDatasetCommon;
365 :
366 : // We have to keep a pointer to the JPGDataset that this JPGRasterBand
367 : // belongs to. In some case, we may have this->poGDS != this->poDS
368 : // For example for a JPGRasterBand that is set to a NITFDataset.
369 : // In other words, this->poDS doesn't necessary point to a JPGDataset
370 : // See ticket #1807.
371 : JPGDatasetCommon *poGDS{};
372 :
373 : CPL_DISALLOW_COPY_ASSIGN(JPGRasterBand)
374 :
375 : public:
376 : JPGRasterBand(JPGDatasetCommon *, int);
377 :
378 : CPLErr IReadBlock(int, int, void *) override;
379 : GDALColorInterp GetColorInterpretation() override;
380 :
381 : virtual GDALSuggestedBlockAccessPattern
382 18 : GetSuggestedBlockAccessPattern() const override
383 : {
384 18 : return GSBAP_TOP_TO_BOTTOM;
385 : }
386 :
387 : GDALRasterBand *GetMaskBand() override;
388 : int GetMaskFlags() override;
389 :
390 : GDALRasterBand *GetOverview(int i) override;
391 : int GetOverviewCount() override;
392 : };
393 :
394 : #if !defined(JPGDataset)
395 :
396 : /************************************************************************/
397 : /* ==================================================================== */
398 : /* JPGMaskBand */
399 : /* ==================================================================== */
400 : /************************************************************************/
401 :
402 : class JPGMaskBand final : public GDALRasterBand
403 : {
404 : protected:
405 : CPLErr IReadBlock(int, int, void *) override;
406 :
407 : public:
408 : explicit JPGMaskBand(JPGDatasetCommon *poDS);
409 : };
410 :
411 : /************************************************************************/
412 : /* GDALRegister_JPEG() */
413 : /************************************************************************/
414 :
415 : class GDALJPGDriver final : public GDALDriver
416 : {
417 : public:
418 1741 : GDALJPGDriver() = default;
419 :
420 : char **GetMetadata(const char *pszDomain = "") override;
421 : const char *GetMetadataItem(const char *pszName,
422 : const char *pszDomain = "") override;
423 :
424 : private:
425 : std::recursive_mutex m_oMutex{};
426 : bool m_bMetadataInitialized = false;
427 : void InitializeMetadata();
428 : };
429 :
430 : #endif // !defined(JPGDataset)
|