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 11523 : GDALJPEGUserData()
122 23046 : : nMaxScans(atoi(
123 11523 : CPLGetConfigOption("GDAL_JPEG_MAX_ALLOWED_SCAN_NUMBER", "100")))
124 : {
125 11523 : memset(&setjmp_buffer, 0, sizeof(setjmp_buffer));
126 11523 : }
127 : };
128 :
129 : /************************************************************************/
130 : /* ==================================================================== */
131 : /* JPGDatasetCommon */
132 : /* ==================================================================== */
133 : /************************************************************************/
134 :
135 : class JPGRasterBand;
136 : class JPGMaskBand;
137 :
138 11257 : 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 bHasReadImageStructureMetadata = false;
172 : char **papszMetadata{};
173 : int nExifOffset{-1};
174 : int nInterOffset{-1};
175 : int nGPSOffset{-1};
176 : bool bSwabflag{};
177 : int nTiffDirStart{-1};
178 : int nTIFFHEADER{-1};
179 : bool bHasDoneJpegCreateDecompress{};
180 : bool bHasDoneJpegStartDecompress{};
181 :
182 : int m_nSubdatasetCount = 0;
183 :
184 : // FLIR raw thermal image
185 : bool m_bRawThermalLittleEndian = false;
186 : int m_nRawThermalImageWidth = 0;
187 : int m_nRawThermalImageHeight = 0;
188 : std::vector<GByte> m_abyRawThermalImage{};
189 :
190 : virtual CPLErr LoadScanline(int, GByte *outBuffer = nullptr) = 0;
191 : virtual void StopDecompress() = 0;
192 : virtual CPLErr Restart() = 0;
193 :
194 : virtual int GetDataPrecision() = 0;
195 : virtual int GetOutColorSpace() = 0;
196 : virtual int GetJPEGColorSpace() = 0;
197 :
198 : bool EXIFInit(VSILFILE *);
199 : void ReadICCProfile();
200 :
201 : void CheckForMask();
202 : void DecompressMask();
203 :
204 : void LoadForMetadataDomain(const char *pszDomain);
205 :
206 : void ReadImageStructureMetadata();
207 : void ReadEXIFMetadata();
208 : void ReadXMPMetadata();
209 : void ReadFLIRMetadata();
210 : GDALDataset *OpenFLIRRawThermalImage();
211 :
212 : bool bHasCheckedForMask{};
213 : JPGMaskBand *poMaskBand{};
214 : GByte *pabyBitMask{};
215 : bool bMaskLSBOrder{true};
216 :
217 : GByte *pabyCMask{};
218 : int nCMaskSize{};
219 :
220 : // Color space exposed by GDAL. Not necessarily the in_color_space nor
221 : // the out_color_space of JPEG library.
222 : /*J_COLOR_SPACE*/ int eGDALColorSpace{JCS_UNKNOWN};
223 :
224 : bool bIsSubfile{};
225 : bool bHasTriedLoadWorldFileOrTab{};
226 : void LoadWorldFileOrTab();
227 : CPLString osWldFilename{};
228 :
229 : virtual int CloseDependentDatasets() override;
230 :
231 : virtual CPLErr IBuildOverviews(const char *, int, const int *, int,
232 : const int *, GDALProgressFunc, void *,
233 : CSLConstList papszOptions) override;
234 :
235 : CPL_DISALLOW_COPY_ASSIGN(JPGDatasetCommon)
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(GDALGeoTransform >) const 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 : {
293 : };
294 :
295 : struct jpeg_error_mgr sJErr
296 : {
297 : };
298 :
299 : struct jpeg_progress_mgr sJProgress
300 : {
301 : };
302 :
303 : virtual CPLErr LoadScanline(int, GByte *outBuffer) override;
304 : CPLErr StartDecompress();
305 : virtual void StopDecompress() override;
306 : virtual CPLErr Restart() override;
307 :
308 25652 : virtual int GetDataPrecision() override
309 : {
310 25652 : return sDInfo.data_precision;
311 : }
312 :
313 162831 : virtual int GetOutColorSpace() override
314 : {
315 162831 : return sDInfo.out_color_space;
316 : }
317 :
318 3 : virtual int GetJPEGColorSpace() override
319 : {
320 3 : return sDInfo.jpeg_color_space;
321 : }
322 :
323 : int nQLevel = 0;
324 : #if !defined(JPGDataset)
325 : void LoadDefaultTables(int);
326 : #endif
327 : void SetScaleNumAndDenom();
328 :
329 : static JPGDatasetCommon *OpenStage2(JPGDatasetOpenArgs *psArgs,
330 : JPGDataset *&poDS);
331 :
332 : public:
333 : JPGDataset();
334 : virtual ~JPGDataset();
335 :
336 : static JPGDatasetCommon *Open(JPGDatasetOpenArgs *psArgs);
337 : static GDALDataset *CreateCopy(const char *pszFilename,
338 : GDALDataset *poSrcDS, int bStrict,
339 : char **papszOptions,
340 : GDALProgressFunc pfnProgress,
341 : void *pProgressData);
342 : static GDALDataset *
343 : CreateCopyStage2(const char *pszFilename, GDALDataset *poSrcDS,
344 : char **papszOptions, GDALProgressFunc pfnProgress,
345 : void *pProgressData, VSIVirtualHandleUniquePtr fpImage,
346 : GDALDataType eDT, int nQuality, bool bAppendMask,
347 : GDALJPEGUserData &sUserData,
348 : 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 50478 : virtual ~JPGRasterBand()
377 25239 : {
378 50478 : }
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 1681 : 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)
|