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 : class JPGVSIFileMultiplexerHandler;
72 :
73 : struct JPGVSIFileMultiplexerCommon
74 : {
75 : std::shared_ptr<VSIVirtualHandle> m_poUnderlyingHandle{};
76 : JPGVSIFileMultiplexerHandler *m_poCurrentOwner = nullptr;
77 : int m_nSubscribers = 0;
78 : };
79 :
80 : struct JPGDatasetOpenArgs
81 : {
82 : const char *pszFilename = nullptr;
83 : std::shared_ptr<JPGVSIFileMultiplexerCommon> poCommon{};
84 : VSIVirtualHandleUniquePtr fp{};
85 : CSLConstList papszSiblingFiles = nullptr;
86 : int nScaleFactor = 1;
87 : bool bDoPAMInitialize = false;
88 : bool bUseInternalOverviews = false;
89 : bool bIsLossless = false;
90 : CSLConstList papszOpenOptions = nullptr;
91 : };
92 :
93 : class JPGDatasetCommon;
94 :
95 : #if defined(JPEG_DUAL_MODE_8_12) && !defined(JPGDataset)
96 : JPGDatasetCommon *JPEGDataset12Open(JPGDatasetOpenArgs *psArgs);
97 : GDALDataset *JPEGDataset12CreateCopy(const char *pszFilename,
98 : GDALDataset *poSrcDS, int bStrict,
99 : CSLConstList papszOptions,
100 : GDALProgressFunc pfnProgress,
101 : void *pProgressData);
102 : #endif
103 :
104 : GDALRasterBand *JPGCreateBand(JPGDatasetCommon *poDS, int nBand);
105 :
106 : typedef void (*my_jpeg_write_m_header)(void *cinfo, int marker,
107 : unsigned int datalen);
108 : typedef void (*my_jpeg_write_m_byte)(void *cinfo, int val);
109 :
110 : CPLErr JPGAppendMask(const char *pszJPGFilename, GDALRasterBand *poMask,
111 : GDALProgressFunc pfnProgress, void *pProgressData);
112 : void JPGAddEXIF(GDALDataType eWorkDT, GDALDataset *poSrcDS,
113 : CSLConstList papszOptions, void *cinfo,
114 : my_jpeg_write_m_header p_jpeg_write_m_header,
115 : my_jpeg_write_m_byte p_jpeg_write_m_byte,
116 : GDALDataset *(pCreateCopy)(const char *, GDALDataset *, int,
117 : CSLConstList,
118 : GDALProgressFunc pfnProgress,
119 : void *pProgressData));
120 : void JPGAddICCProfile(void *pInfo, const char *pszICCProfile,
121 : my_jpeg_write_m_header p_jpeg_write_m_header,
122 : my_jpeg_write_m_byte p_jpeg_write_m_byte);
123 :
124 : class GDALJPEGUserData
125 : {
126 : public:
127 : jmp_buf setjmp_buffer;
128 : bool bNonFatalErrorEncountered = false;
129 : void (*p_previous_emit_message)(j_common_ptr cinfo,
130 : int msg_level) = nullptr;
131 : int nMaxScans;
132 :
133 12520 : GDALJPEGUserData()
134 25040 : : nMaxScans(atoi(
135 12520 : CPLGetConfigOption("GDAL_JPEG_MAX_ALLOWED_SCAN_NUMBER", "100")))
136 : {
137 12520 : memset(&setjmp_buffer, 0, sizeof(setjmp_buffer));
138 12520 : }
139 : };
140 :
141 : /************************************************************************/
142 : /* ==================================================================== */
143 : /* JPGDatasetCommon */
144 : /* ==================================================================== */
145 : /************************************************************************/
146 :
147 : class JPGRasterBand;
148 : class JPGMaskBand;
149 :
150 12257 : class JPGDatasetCommon CPL_NON_FINAL : public GDALPamDataset
151 : {
152 : protected:
153 : friend class JPGDataset;
154 : friend class JPGRasterBand;
155 : friend class JPGMaskBand;
156 :
157 : int nScaleFactor{1};
158 : bool bHasInitInternalOverviews{};
159 : int nInternalOverviewsCurrent{};
160 : int nInternalOverviewsToFree{};
161 : GDALDataset **papoInternalOverviews{};
162 : JPGDatasetCommon *poActiveDS = nullptr; /* only valid in parent DS */
163 : JPGDatasetCommon **ppoActiveDS =
164 : nullptr; /* &poActiveDS of poActiveDS from parentDS */
165 : void InitInternalOverviews();
166 : GDALDataset *InitEXIFOverview();
167 :
168 : mutable OGRSpatialReference m_oSRS{};
169 : bool bGeoTransformValid{};
170 : GDALGeoTransform m_gt{};
171 : std::vector<gdal::GCP> m_aoGCPs{};
172 :
173 : std::shared_ptr<JPGVSIFileMultiplexerCommon> m_poCommon{};
174 : VSIVirtualHandleUniquePtr m_fpImage{};
175 : GUIntBig nSubfileOffset{};
176 :
177 : int nLoadedScanline{-1};
178 : GByte *m_pabyScanline{};
179 :
180 : bool bHasReadEXIFMetadata{};
181 : bool bHasReadXMPMetadata{};
182 : bool bHasReadICCMetadata{};
183 : bool bHasReadFLIRMetadata = false;
184 : bool bHasReadDJIMetadata = false;
185 : bool bHasReadImageStructureMetadata = false;
186 : char **papszMetadata{};
187 : uint32_t nExifOffset{0};
188 : uint32_t nInterOffset{0};
189 : uint32_t nGPSOffset{0};
190 : bool bSwabflag{};
191 : bool m_bTiffDirStartInit = false;
192 : uint32_t nTiffDirStart{0};
193 : vsi_l_offset nTIFFHEADER{0};
194 : bool bHasDoneJpegCreateDecompress{};
195 : bool bHasDoneJpegStartDecompress{};
196 :
197 : int m_nSubdatasetCount = 0;
198 :
199 : // FLIR or DJI raw thermal image
200 : bool m_bRawThermalLittleEndian = false;
201 : int m_nRawThermalImageWidth = 0;
202 : int m_nRawThermalImageHeight = 0;
203 : std::vector<GByte> m_abyRawThermalImage{};
204 :
205 : // FLIR embedded image (RGB next to raw thermal)
206 : std::vector<GByte> m_abyEmbeddedImage{};
207 :
208 : virtual CPLErr LoadScanline(int, GByte *outBuffer = nullptr) = 0;
209 : virtual void StopDecompress() = 0;
210 : virtual CPLErr Restart() = 0;
211 :
212 : virtual int GetDataPrecision() = 0;
213 : virtual int GetOutColorSpace() = 0;
214 : virtual int GetJPEGColorSpace() = 0;
215 :
216 : bool EXIFInit(VSILFILE *);
217 : void ReadICCProfile();
218 :
219 : void CheckForMask();
220 : void DecompressMask();
221 :
222 : void LoadForMetadataDomain(const char *pszDomain);
223 :
224 : void ReadImageStructureMetadata();
225 : void ReadEXIFMetadata();
226 : void ReadXMPMetadata();
227 : void ReadThermalMetadata();
228 : void ReadFLIRMetadata();
229 : void ReadDJIMetadata();
230 : GDALDataset *OpenRawThermalImage(const char *pszConnectionString);
231 : GDALDataset *OpenEmbeddedImage(const char *pszConnectionString);
232 :
233 : bool bHasCheckedForMask{};
234 : JPGMaskBand *poMaskBand{};
235 : GByte *pabyBitMask{};
236 : bool bMaskLSBOrder{true};
237 :
238 : GByte *pabyCMask{};
239 : int nCMaskSize{};
240 :
241 : // Color space exposed by GDAL. Not necessarily the in_color_space nor
242 : // the out_color_space of JPEG library.
243 : /*J_COLOR_SPACE*/ int eGDALColorSpace{JCS_UNKNOWN};
244 :
245 : bool bIsSubfile{};
246 : bool bHasTriedLoadWorldFileOrTab{};
247 : void LoadWorldFileOrTab();
248 : CPLString osWldFilename{};
249 :
250 : int CloseDependentDatasets() override;
251 :
252 : CPLErr IBuildOverviews(const char *, int, const int *, int, const int *,
253 : GDALProgressFunc, void *,
254 : CSLConstList papszOptions) override;
255 :
256 : void ArtemisIIEasterEgg();
257 :
258 : CPL_DISALLOW_COPY_ASSIGN(JPGDatasetCommon)
259 :
260 : public:
261 : JPGDatasetCommon();
262 : ~JPGDatasetCommon() override;
263 :
264 : CPLErr Close(GDALProgressFunc = nullptr, void * = nullptr) override;
265 :
266 : CPLErr IRasterIO(GDALRWFlag, int, int, int, int, void *, int, int,
267 : GDALDataType, int, BANDMAP_TYPE, GSpacing nPixelSpace,
268 : GSpacing nLineSpace, GSpacing nBandSpace,
269 : GDALRasterIOExtraArg *psExtraArg) override;
270 :
271 : CPLErr GetGeoTransform(GDALGeoTransform >) const override;
272 :
273 : int GetGCPCount() override;
274 : const OGRSpatialReference *GetGCPSpatialRef() const override;
275 : const GDAL_GCP *GetGCPs() override;
276 :
277 : const OGRSpatialReference *GetSpatialRef() const override;
278 :
279 : char **GetMetadataDomainList() override;
280 : CSLConstList GetMetadata(const char *pszDomain = "") override;
281 : virtual const char *GetMetadataItem(const char *pszName,
282 : const char *pszDomain = "") override;
283 :
284 : char **GetFileList(void) override;
285 :
286 : CPLErr FlushCache(bool bAtClosing) override;
287 :
288 : CPLStringList GetCompressionFormats(int nXOff, int nYOff, int nXSize,
289 : int nYSize, int nBandCount,
290 : const int *panBandList) override;
291 : CPLErr ReadCompressedData(const char *pszFormat, int nXOff, int nYOff,
292 : int nXSize, int nYSize, int nBandCount,
293 : const int *panBandList, void **ppBuffer,
294 : size_t *pnBufferSize,
295 : char **ppszDetailedFormat) override;
296 :
297 : static GDALDataset *Open(GDALOpenInfo *);
298 : };
299 :
300 : /************************************************************************/
301 : /* ==================================================================== */
302 : /* JPGDataset */
303 : /* ==================================================================== */
304 : /************************************************************************/
305 :
306 : class JPGDataset final : public JPGDatasetCommon
307 : {
308 : GDALJPEGUserData sUserData{};
309 :
310 : bool ErrorOutOnNonFatalError();
311 :
312 : static void EmitMessage(j_common_ptr cinfo, int msg_level);
313 : static void ProgressMonitor(j_common_ptr cinfo);
314 :
315 : struct jpeg_decompress_struct sDInfo{};
316 :
317 : struct jpeg_error_mgr sJErr{};
318 :
319 : struct jpeg_progress_mgr sJProgress{};
320 :
321 : CPLErr LoadScanline(int, GByte *outBuffer) override;
322 : CPLErr StartDecompress();
323 : void StopDecompress() override;
324 : CPLErr Restart() override;
325 :
326 26673 : int GetDataPrecision() override
327 : {
328 26673 : return sDInfo.data_precision;
329 : }
330 :
331 166075 : int GetOutColorSpace() override
332 : {
333 166075 : return sDInfo.out_color_space;
334 : }
335 :
336 7 : int GetJPEGColorSpace() override
337 : {
338 7 : return sDInfo.jpeg_color_space;
339 : }
340 :
341 : int nQLevel = 0;
342 : #if !defined(JPGDataset)
343 : void LoadDefaultTables(int);
344 : #endif
345 : void SetScaleNumAndDenom();
346 :
347 : static JPGDatasetCommon *OpenStage2(JPGDatasetOpenArgs *psArgs,
348 : JPGDataset *&poDS);
349 :
350 : public:
351 : JPGDataset();
352 : ~JPGDataset() override;
353 :
354 : static JPGDatasetCommon *Open(JPGDatasetOpenArgs *psArgs);
355 : static GDALDataset *CreateCopy(const char *pszFilename,
356 : GDALDataset *poSrcDS, int bStrict,
357 : CSLConstList papszOptions,
358 : GDALProgressFunc pfnProgress,
359 : void *pProgressData);
360 : static GDALDataset *
361 : CreateCopyStage2(const char *pszFilename, GDALDataset *poSrcDS,
362 : CSLConstList papszOptions, GDALProgressFunc pfnProgress,
363 : void *pProgressData, VSIVirtualHandleUniquePtr fpImage,
364 : GDALDataType eDT, int nQuality, bool bAppendMask,
365 : GDALJPEGUserData &sUserData,
366 : struct jpeg_compress_struct &sCInfo,
367 : struct jpeg_error_mgr &sJErr, GByte *&pabyScanline);
368 : static void ErrorExit(j_common_ptr cinfo);
369 : static void OutputMessage(j_common_ptr cinfo);
370 : };
371 :
372 : /************************************************************************/
373 : /* ==================================================================== */
374 : /* JPGRasterBand */
375 : /* ==================================================================== */
376 : /************************************************************************/
377 :
378 : class JPGRasterBand final : public GDALPamRasterBand
379 : {
380 : friend class JPGDatasetCommon;
381 :
382 : // We have to keep a pointer to the JPGDataset that this JPGRasterBand
383 : // belongs to. In some case, we may have this->poGDS != this->poDS
384 : // For example for a JPGRasterBand that is set to a NITFDataset.
385 : // In other words, this->poDS doesn't necessary point to a JPGDataset
386 : // See ticket #1807.
387 : JPGDatasetCommon *poGDS{};
388 :
389 : CPL_DISALLOW_COPY_ASSIGN(JPGRasterBand)
390 :
391 : public:
392 : JPGRasterBand(JPGDatasetCommon *, int);
393 :
394 : CPLErr IReadBlock(int, int, void *) override;
395 : GDALColorInterp GetColorInterpretation() override;
396 :
397 : virtual GDALSuggestedBlockAccessPattern
398 12 : GetSuggestedBlockAccessPattern() const override
399 : {
400 12 : return GSBAP_TOP_TO_BOTTOM;
401 : }
402 :
403 : GDALRasterBand *GetMaskBand() override;
404 : int GetMaskFlags() override;
405 :
406 : GDALRasterBand *GetOverview(int i) override;
407 : int GetOverviewCount() override;
408 : };
409 :
410 : #if !defined(JPGDataset)
411 :
412 : /************************************************************************/
413 : /* ==================================================================== */
414 : /* JPGMaskBand */
415 : /* ==================================================================== */
416 : /************************************************************************/
417 :
418 : class JPGMaskBand final : public GDALRasterBand
419 : {
420 : protected:
421 : CPLErr IReadBlock(int, int, void *) override;
422 :
423 : public:
424 : explicit JPGMaskBand(JPGDatasetCommon *poDS);
425 : };
426 :
427 : /************************************************************************/
428 : /* GDALRegister_JPEG() */
429 : /************************************************************************/
430 :
431 : class GDALJPGDriver final : public GDALDriver
432 : {
433 : public:
434 1803 : GDALJPGDriver() = default;
435 :
436 : CSLConstList GetMetadata(const char *pszDomain = "") override;
437 : const char *GetMetadataItem(const char *pszName,
438 : const char *pszDomain = "") override;
439 :
440 : private:
441 : std::recursive_mutex m_oMutex{};
442 : bool m_bMetadataInitialized = false;
443 : void InitializeMetadata();
444 : };
445 :
446 : #endif // !defined(JPGDataset)
|