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 12518 : GDALJPEGUserData()
134 25036 : : nMaxScans(atoi(
135 12518 : CPLGetConfigOption("GDAL_JPEG_MAX_ALLOWED_SCAN_NUMBER", "100")))
136 : {
137 12518 : memset(&setjmp_buffer, 0, sizeof(setjmp_buffer));
138 12518 : }
139 : };
140 :
141 : /************************************************************************/
142 : /* ==================================================================== */
143 : /* JPGDatasetCommon */
144 : /* ==================================================================== */
145 : /************************************************************************/
146 :
147 : class JPGRasterBand;
148 : class JPGMaskBand;
149 :
150 12255 : 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 : CPL_DISALLOW_COPY_ASSIGN(JPGDatasetCommon)
257 :
258 : public:
259 : JPGDatasetCommon();
260 : ~JPGDatasetCommon() override;
261 :
262 : CPLErr Close(GDALProgressFunc = nullptr, void * = nullptr) override;
263 :
264 : CPLErr IRasterIO(GDALRWFlag, int, int, int, int, void *, int, int,
265 : GDALDataType, int, BANDMAP_TYPE, GSpacing nPixelSpace,
266 : GSpacing nLineSpace, GSpacing nBandSpace,
267 : GDALRasterIOExtraArg *psExtraArg) override;
268 :
269 : CPLErr GetGeoTransform(GDALGeoTransform >) const override;
270 :
271 : int GetGCPCount() override;
272 : const OGRSpatialReference *GetGCPSpatialRef() const override;
273 : const GDAL_GCP *GetGCPs() override;
274 :
275 : const OGRSpatialReference *GetSpatialRef() const override;
276 :
277 : char **GetMetadataDomainList() override;
278 : CSLConstList GetMetadata(const char *pszDomain = "") override;
279 : virtual const char *GetMetadataItem(const char *pszName,
280 : const char *pszDomain = "") override;
281 :
282 : char **GetFileList(void) override;
283 :
284 : CPLErr FlushCache(bool bAtClosing) override;
285 :
286 : CPLStringList GetCompressionFormats(int nXOff, int nYOff, int nXSize,
287 : int nYSize, int nBandCount,
288 : const int *panBandList) override;
289 : CPLErr ReadCompressedData(const char *pszFormat, int nXOff, int nYOff,
290 : int nXSize, int nYSize, int nBandCount,
291 : const int *panBandList, void **ppBuffer,
292 : size_t *pnBufferSize,
293 : char **ppszDetailedFormat) override;
294 :
295 : static GDALDataset *Open(GDALOpenInfo *);
296 : };
297 :
298 : /************************************************************************/
299 : /* ==================================================================== */
300 : /* JPGDataset */
301 : /* ==================================================================== */
302 : /************************************************************************/
303 :
304 : class JPGDataset final : public JPGDatasetCommon
305 : {
306 : GDALJPEGUserData sUserData{};
307 :
308 : bool ErrorOutOnNonFatalError();
309 :
310 : static void EmitMessage(j_common_ptr cinfo, int msg_level);
311 : static void ProgressMonitor(j_common_ptr cinfo);
312 :
313 : struct jpeg_decompress_struct sDInfo
314 : {
315 : };
316 :
317 : struct jpeg_error_mgr sJErr
318 : {
319 : };
320 :
321 : struct jpeg_progress_mgr sJProgress
322 : {
323 : };
324 :
325 : CPLErr LoadScanline(int, GByte *outBuffer) override;
326 : CPLErr StartDecompress();
327 : void StopDecompress() override;
328 : CPLErr Restart() override;
329 :
330 26669 : int GetDataPrecision() override
331 : {
332 26669 : return sDInfo.data_precision;
333 : }
334 :
335 163007 : int GetOutColorSpace() override
336 : {
337 163007 : return sDInfo.out_color_space;
338 : }
339 :
340 7 : int GetJPEGColorSpace() override
341 : {
342 7 : return sDInfo.jpeg_color_space;
343 : }
344 :
345 : int nQLevel = 0;
346 : #if !defined(JPGDataset)
347 : void LoadDefaultTables(int);
348 : #endif
349 : void SetScaleNumAndDenom();
350 :
351 : static JPGDatasetCommon *OpenStage2(JPGDatasetOpenArgs *psArgs,
352 : JPGDataset *&poDS);
353 :
354 : public:
355 : JPGDataset();
356 : ~JPGDataset() override;
357 :
358 : static JPGDatasetCommon *Open(JPGDatasetOpenArgs *psArgs);
359 : static GDALDataset *CreateCopy(const char *pszFilename,
360 : GDALDataset *poSrcDS, int bStrict,
361 : CSLConstList papszOptions,
362 : GDALProgressFunc pfnProgress,
363 : void *pProgressData);
364 : static GDALDataset *
365 : CreateCopyStage2(const char *pszFilename, GDALDataset *poSrcDS,
366 : CSLConstList papszOptions, GDALProgressFunc pfnProgress,
367 : void *pProgressData, VSIVirtualHandleUniquePtr fpImage,
368 : GDALDataType eDT, int nQuality, bool bAppendMask,
369 : GDALJPEGUserData &sUserData,
370 : struct jpeg_compress_struct &sCInfo,
371 : struct jpeg_error_mgr &sJErr, GByte *&pabyScanline);
372 : static void ErrorExit(j_common_ptr cinfo);
373 : static void OutputMessage(j_common_ptr cinfo);
374 : };
375 :
376 : /************************************************************************/
377 : /* ==================================================================== */
378 : /* JPGRasterBand */
379 : /* ==================================================================== */
380 : /************************************************************************/
381 :
382 : class JPGRasterBand final : public GDALPamRasterBand
383 : {
384 : friend class JPGDatasetCommon;
385 :
386 : // We have to keep a pointer to the JPGDataset that this JPGRasterBand
387 : // belongs to. In some case, we may have this->poGDS != this->poDS
388 : // For example for a JPGRasterBand that is set to a NITFDataset.
389 : // In other words, this->poDS doesn't necessary point to a JPGDataset
390 : // See ticket #1807.
391 : JPGDatasetCommon *poGDS{};
392 :
393 : CPL_DISALLOW_COPY_ASSIGN(JPGRasterBand)
394 :
395 : public:
396 : JPGRasterBand(JPGDatasetCommon *, int);
397 :
398 : CPLErr IReadBlock(int, int, void *) override;
399 : GDALColorInterp GetColorInterpretation() override;
400 :
401 : virtual GDALSuggestedBlockAccessPattern
402 18 : GetSuggestedBlockAccessPattern() const override
403 : {
404 18 : return GSBAP_TOP_TO_BOTTOM;
405 : }
406 :
407 : GDALRasterBand *GetMaskBand() override;
408 : int GetMaskFlags() override;
409 :
410 : GDALRasterBand *GetOverview(int i) override;
411 : int GetOverviewCount() override;
412 : };
413 :
414 : #if !defined(JPGDataset)
415 :
416 : /************************************************************************/
417 : /* ==================================================================== */
418 : /* JPGMaskBand */
419 : /* ==================================================================== */
420 : /************************************************************************/
421 :
422 : class JPGMaskBand final : public GDALRasterBand
423 : {
424 : protected:
425 : CPLErr IReadBlock(int, int, void *) override;
426 :
427 : public:
428 : explicit JPGMaskBand(JPGDatasetCommon *poDS);
429 : };
430 :
431 : /************************************************************************/
432 : /* GDALRegister_JPEG() */
433 : /************************************************************************/
434 :
435 : class GDALJPGDriver final : public GDALDriver
436 : {
437 : public:
438 1776 : GDALJPGDriver() = default;
439 :
440 : CSLConstList GetMetadata(const char *pszDomain = "") override;
441 : const char *GetMetadataItem(const char *pszName,
442 : const char *pszDomain = "") override;
443 :
444 : private:
445 : std::recursive_mutex m_oMutex{};
446 : bool m_bMetadataInitialized = false;
447 : void InitializeMetadata();
448 : };
449 :
450 : #endif // !defined(JPGDataset)
|