1 : /******************************************************************************
2 : * $Id: jpgdataset.cpp 25505 2013-01-14 23:32:57Z rouault $
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 : *
11 : * Portions Copyright (c) Her majesty the Queen in right of Canada as
12 : * represented by the Minister of National Defence, 2006.
13 : *
14 : * Permission is hereby granted, free of charge, to any person obtaining a
15 : * copy of this software and associated documentation files (the "Software"),
16 : * to deal in the Software without restriction, including without limitation
17 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 : * and/or sell copies of the Software, and to permit persons to whom the
19 : * Software is furnished to do so, subject to the following conditions:
20 : *
21 : * The above copyright notice and this permission notice shall be included
22 : * in all copies or substantial portions of the Software.
23 : *
24 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 : * DEALINGS IN THE SOFTWARE.
31 : ****************************************************************************/
32 :
33 : #include "gdal_pam.h"
34 : #include "cpl_string.h"
35 :
36 : #include <setjmp.h>
37 :
38 : #define TIFF_VERSION 42
39 :
40 : #define TIFF_BIGENDIAN 0x4d4d
41 : #define TIFF_LITTLEENDIAN 0x4949
42 :
43 : /*
44 : * TIFF header.
45 : */
46 : typedef struct {
47 : GUInt16 tiff_magic; /* magic number (defines byte order) */
48 : GUInt16 tiff_version; /* TIFF version number */
49 : GUInt32 tiff_diroff; /* byte offset to first directory */
50 : } TIFFHeader;
51 :
52 : CPL_CVSID("$Id: jpgdataset.cpp 25505 2013-01-14 23:32:57Z rouault $");
53 :
54 : CPL_C_START
55 : #ifdef LIBJPEG_12_PATH
56 : # include LIBJPEG_12_PATH
57 : #else
58 : # include "jpeglib.h"
59 : #endif
60 : CPL_C_END
61 :
62 : // we believe it is ok to use setjmp() in this situation.
63 : #ifdef _MSC_VER
64 : # pragma warning(disable:4611)
65 : #endif
66 :
67 : #if defined(JPEG_DUAL_MODE_8_12) && !defined(JPGDataset)
68 : GDALDataset* JPEGDataset12Open(const char* pszFilename,
69 : char** papszSiblingFiles,
70 : int nScaleFactor);
71 : GDALDataset* JPEGDataset12CreateCopy( const char * pszFilename,
72 : GDALDataset *poSrcDS,
73 : int bStrict, char ** papszOptions,
74 : GDALProgressFunc pfnProgress,
75 : void * pProgressData );
76 : #endif
77 :
78 : CPL_C_START
79 : void GDALRegister_JPEG(void);
80 : CPL_C_END
81 :
82 : #include "vsidataio.h"
83 :
84 : /*
85 : * Do we want to do special processing suitable for when JSAMPLE is a
86 : * 16bit value?
87 : */
88 : #if defined(JPEG_LIB_MK1)
89 : # define JPEG_LIB_MK1_OR_12BIT 1
90 : #elif BITS_IN_JSAMPLE == 12
91 : # define JPEG_LIB_MK1_OR_12BIT 1
92 : #endif
93 :
94 : #define Q1table GDALJPEG_Q1table
95 : #define Q2table GDALJPEG_Q2table
96 : #define Q3table GDALJPEG_Q3table
97 : #define Q4table GDALJPEG_Q4table
98 : #define Q5table GDALJPEG_Q5table
99 : #define AC_BITS GDALJPEG_AC_BITS
100 : #define AC_HUFFVAL GDALJPEG_AC_HUFFVAL
101 : #define DC_BITS GDALJPEG_DC_BITS
102 : #define DC_HUFFVAL GDALJPEG_DC_HUFFVAL
103 :
104 : extern const GByte Q1table[64];
105 : extern const GByte Q2table[64];
106 : extern const GByte Q3table[64];
107 : extern const GByte Q4table[64];
108 : extern const GByte Q5table[64];
109 : extern const GByte AC_BITS[16];
110 : extern const GByte AC_HUFFVAL[256];
111 : extern const GByte DC_BITS[16];
112 : extern const GByte DC_HUFFVAL[256];
113 :
114 : class JPGDatasetCommon;
115 : GDALRasterBand* JPGCreateBand(JPGDatasetCommon* poDS, int nBand);
116 :
117 : CPLErr JPGAppendMask( const char *pszJPGFilename, GDALRasterBand *poMask,
118 : GDALProgressFunc pfnProgress, void * pProgressData );
119 :
120 : /************************************************************************/
121 : /* ==================================================================== */
122 : /* JPGDatasetCommon */
123 : /* ==================================================================== */
124 : /************************************************************************/
125 :
126 : class JPGRasterBand;
127 : class JPGMaskBand;
128 :
129 : class JPGDatasetCommon : public GDALPamDataset
130 : {
131 : protected:
132 : friend class JPGRasterBand;
133 : friend class JPGMaskBand;
134 :
135 : jmp_buf setjmp_buffer;
136 :
137 : int nScaleFactor;
138 : int bHasInitInternalOverviews;
139 : int nInternalOverviewsCurrent;
140 : int nInternalOverviewsToFree;
141 : GDALDataset** papoInternalOverviews;
142 : void InitInternalOverviews();
143 :
144 : char *pszProjection;
145 : int bGeoTransformValid;
146 : double adfGeoTransform[6];
147 : int nGCPCount;
148 : GDAL_GCP *pasGCPList;
149 :
150 : VSILFILE *fpImage;
151 : int bOwnFPImage;
152 : GUIntBig nSubfileOffset;
153 :
154 : int nLoadedScanline;
155 : GByte *pabyScanline;
156 :
157 : int bHasReadEXIFMetadata;
158 : int bHasReadXMPMetadata;
159 : char **papszMetadata;
160 : char **papszSubDatasets;
161 : int bigendian;
162 : int nExifOffset;
163 : int nInterOffset;
164 : int nGPSOffset;
165 : int bSwabflag;
166 : int nTiffDirStart;
167 : int nTIFFHEADER;
168 : int bHasDoneJpegCreateDecompress;
169 : int bHasDoneJpegStartDecompress;
170 :
171 : virtual CPLErr LoadScanline(int) = 0;
172 : virtual void Restart() = 0;
173 :
174 : virtual int GetDataPrecision() = 0;
175 : virtual int GetOutColorSpace() = 0;
176 :
177 : int EXIFInit(VSILFILE *);
178 :
179 : int nQLevel;
180 :
181 : void CheckForMask();
182 : void DecompressMask();
183 :
184 : void ReadEXIFMetadata();
185 : void ReadXMPMetadata();
186 :
187 : int bHasCheckedForMask;
188 : JPGMaskBand *poMaskBand;
189 : GByte *pabyBitMask;
190 :
191 : GByte *pabyCMask;
192 : int nCMaskSize;
193 :
194 : J_COLOR_SPACE eGDALColorSpace; /* color space exposed by GDAL. Not necessarily the in_color_space nor */
195 : /* the out_color_space of JPEG library */
196 :
197 : int bIsSubfile;
198 : int bHasTriedLoadWorldFileOrTab;
199 : void LoadWorldFileOrTab();
200 : CPLString osWldFilename;
201 :
202 : virtual int CloseDependentDatasets();
203 :
204 : virtual CPLErr IBuildOverviews( const char *, int, int *,
205 : int, int *, GDALProgressFunc, void * );
206 :
207 : public:
208 : JPGDatasetCommon();
209 : ~JPGDatasetCommon();
210 :
211 : virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
212 : void *, int, int, GDALDataType,
213 : int, int *, int, int, int );
214 :
215 : virtual CPLErr GetGeoTransform( double * );
216 :
217 : virtual int GetGCPCount();
218 : virtual const char *GetGCPProjection();
219 : virtual const GDAL_GCP *GetGCPs();
220 :
221 : virtual char **GetMetadata( const char * pszDomain = "" );
222 : virtual const char *GetMetadataItem( const char * pszName,
223 : const char * pszDomain = "" );
224 :
225 : virtual char **GetFileList(void);
226 :
227 : static int Identify( GDALOpenInfo * );
228 : static GDALDataset *Open( GDALOpenInfo * );
229 : };
230 :
231 : /************************************************************************/
232 : /* ==================================================================== */
233 : /* JPGDataset */
234 : /* ==================================================================== */
235 : /************************************************************************/
236 :
237 : class JPGDataset : public JPGDatasetCommon
238 : {
239 : struct jpeg_decompress_struct sDInfo;
240 : struct jpeg_error_mgr sJErr;
241 :
242 : virtual CPLErr LoadScanline(int);
243 : virtual void Restart();
244 326 : virtual int GetDataPrecision() { return sDInfo.data_precision; }
245 16744 : virtual int GetOutColorSpace() { return sDInfo.out_color_space; }
246 :
247 : void LoadDefaultTables(int);
248 : void SetScaleNumAndDenom();
249 :
250 : public:
251 : JPGDataset();
252 : ~JPGDataset();
253 :
254 : static GDALDataset *Open( const char* pszFilename,
255 : char** papszSiblingFiles = NULL,
256 : int nScaleFactor = 1,
257 : VSILFILE* fpIn = NULL);
258 : static GDALDataset* CreateCopy( const char * pszFilename,
259 : GDALDataset *poSrcDS,
260 : int bStrict, char ** papszOptions,
261 : GDALProgressFunc pfnProgress,
262 : void * pProgressData );
263 :
264 : static void ErrorExit(j_common_ptr cinfo);
265 : };
266 :
267 : /************************************************************************/
268 : /* ==================================================================== */
269 : /* JPGRasterBand */
270 : /* ==================================================================== */
271 : /************************************************************************/
272 :
273 : class JPGRasterBand : public GDALPamRasterBand
274 317 : {
275 : friend class JPGDatasetCommon;
276 :
277 : /* We have to keep a pointer to the JPGDataset that this JPGRasterBand
278 : belongs to. In some case, we may have this->poGDS != this->poDS
279 : For example for a JPGRasterBand that is set to a NITFDataset...
280 : In other words, this->poDS doesn't necessary point to a JPGDataset
281 : See ticket #1807.
282 : */
283 : JPGDatasetCommon *poGDS;
284 :
285 : public:
286 :
287 : JPGRasterBand( JPGDatasetCommon *, int );
288 :
289 : virtual CPLErr IReadBlock( int, int, void * );
290 : virtual GDALColorInterp GetColorInterpretation();
291 :
292 : virtual GDALRasterBand *GetMaskBand();
293 : virtual int GetMaskFlags();
294 :
295 : virtual GDALRasterBand *GetOverview(int i);
296 : virtual int GetOverviewCount();
297 : };
298 :
299 : #if !defined(JPGDataset)
300 :
301 : /************************************************************************/
302 : /* ==================================================================== */
303 : /* JPGMaskBand */
304 : /* ==================================================================== */
305 : /************************************************************************/
306 :
307 : class JPGMaskBand : public GDALRasterBand
308 4 : {
309 : protected:
310 : virtual CPLErr IReadBlock( int, int, void * );
311 :
312 : public:
313 : JPGMaskBand( JPGDataset *poDS );
314 : };
315 :
316 : /************************************************************************/
317 : /* ReadEXIFMetadata() */
318 : /************************************************************************/
319 21 : void JPGDatasetCommon::ReadEXIFMetadata()
320 : {
321 21 : if (bHasReadEXIFMetadata)
322 0 : return;
323 :
324 21 : CPLAssert(papszMetadata == NULL);
325 :
326 : /* Save current position to avoid disturbing JPEG stream decoding */
327 21 : vsi_l_offset nCurOffset = VSIFTellL(fpImage);
328 :
329 21 : if( EXIFInit(fpImage) )
330 : {
331 : EXIFExtractMetadata(papszMetadata,
332 : fpImage, nTiffDirStart,
333 : bSwabflag, nTIFFHEADER,
334 5 : nExifOffset, nInterOffset, nGPSOffset);
335 :
336 5 : if(nExifOffset > 0){
337 : EXIFExtractMetadata(papszMetadata,
338 : fpImage, nExifOffset,
339 : bSwabflag, nTIFFHEADER,
340 5 : nExifOffset, nInterOffset, nGPSOffset);
341 : }
342 5 : if(nInterOffset > 0) {
343 : EXIFExtractMetadata(papszMetadata,
344 : fpImage, nInterOffset,
345 : bSwabflag, nTIFFHEADER,
346 0 : nExifOffset, nInterOffset, nGPSOffset);
347 : }
348 5 : if(nGPSOffset > 0) {
349 : EXIFExtractMetadata(papszMetadata,
350 : fpImage, nGPSOffset,
351 : bSwabflag, nTIFFHEADER,
352 4 : nExifOffset, nInterOffset, nGPSOffset);
353 : }
354 :
355 : /* Avoid setting the PAM dirty bit just for that */
356 5 : int nOldPamFlags = nPamFlags;
357 :
358 : /* Append metadata from PAM after EXIF metadata */
359 5 : papszMetadata = CSLMerge(papszMetadata, GDALPamDataset::GetMetadata());
360 5 : SetMetadata( papszMetadata );
361 :
362 5 : nPamFlags = nOldPamFlags;
363 : }
364 :
365 21 : VSIFSeekL( fpImage, nCurOffset, SEEK_SET );
366 :
367 21 : bHasReadEXIFMetadata = TRUE;
368 : }
369 :
370 : /************************************************************************/
371 : /* ReadXMPMetadata() */
372 : /************************************************************************/
373 :
374 : /* See ยง2.1.3 of http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/xmp/pdfs/XMPSpecificationPart3.pdf */
375 :
376 2 : void JPGDatasetCommon::ReadXMPMetadata()
377 : {
378 2 : if (bHasReadXMPMetadata)
379 0 : return;
380 :
381 : /* Save current position to avoid disturbing JPEG stream decoding */
382 2 : vsi_l_offset nCurOffset = VSIFTellL(fpImage);
383 :
384 : /* -------------------------------------------------------------------- */
385 : /* Search for APP1 chunk. */
386 : /* -------------------------------------------------------------------- */
387 : GByte abyChunkHeader[2+2+29];
388 2 : int nChunkLoc = 2;
389 2 : int bFoundXMP = FALSE;
390 :
391 2 : for( ; TRUE; )
392 : {
393 4 : if( VSIFSeekL( fpImage, nChunkLoc, SEEK_SET ) != 0 )
394 0 : break;
395 :
396 4 : if( VSIFReadL( abyChunkHeader, sizeof(abyChunkHeader), 1, fpImage ) != 1 )
397 0 : break;
398 :
399 8 : if( abyChunkHeader[0] != 0xFF
400 4 : || (abyChunkHeader[1] & 0xf0) != 0xe0 )
401 1 : break; // Not an APP chunk.
402 :
403 3 : if( abyChunkHeader[1] == 0xe1
404 : && strncmp((const char *) abyChunkHeader + 4,"http://ns.adobe.com/xap/1.0/",28) == 0 )
405 : {
406 1 : bFoundXMP = TRUE;
407 1 : break; // APP1 - XMP
408 : }
409 :
410 2 : nChunkLoc += 2 + abyChunkHeader[2] * 256 + abyChunkHeader[3];
411 : }
412 :
413 2 : if (bFoundXMP)
414 : {
415 1 : int nXMPLength = abyChunkHeader[2] * 256 + abyChunkHeader[3];
416 1 : if (nXMPLength > 2 + 29)
417 : {
418 1 : char* pszXMP = (char*)VSIMalloc(nXMPLength - 2 - 29 + 1);
419 1 : if (pszXMP)
420 : {
421 1 : if (VSIFReadL( pszXMP, nXMPLength - 2 - 29, 1, fpImage ) == 1)
422 : {
423 1 : pszXMP[nXMPLength - 2 - 29] = '\0';
424 :
425 : /* Avoid setting the PAM dirty bit just for that */
426 1 : int nOldPamFlags = nPamFlags;
427 :
428 : char *apszMDList[2];
429 1 : apszMDList[0] = pszXMP;
430 1 : apszMDList[1] = NULL;
431 1 : SetMetadata(apszMDList, "xml:XMP");
432 :
433 1 : nPamFlags = nOldPamFlags;
434 : }
435 1 : VSIFree(pszXMP);
436 : }
437 : }
438 : }
439 :
440 2 : VSIFSeekL( fpImage, nCurOffset, SEEK_SET );
441 :
442 2 : bHasReadXMPMetadata = TRUE;
443 : }
444 :
445 : /************************************************************************/
446 : /* GetMetadata() */
447 : /************************************************************************/
448 74 : char **JPGDatasetCommon::GetMetadata( const char * pszDomain )
449 : {
450 74 : if (fpImage == NULL)
451 0 : return NULL;
452 74 : if (eAccess == GA_ReadOnly && !bHasReadEXIFMetadata &&
453 : (pszDomain == NULL || EQUAL(pszDomain, "")))
454 21 : ReadEXIFMetadata();
455 74 : if (eAccess == GA_ReadOnly && !bHasReadXMPMetadata &&
456 : (pszDomain != NULL && EQUAL(pszDomain, "xml:XMP")))
457 2 : ReadXMPMetadata();
458 74 : return GDALPamDataset::GetMetadata(pszDomain);
459 : }
460 :
461 : /************************************************************************/
462 : /* GetMetadataItem() */
463 : /************************************************************************/
464 940 : const char *JPGDatasetCommon::GetMetadataItem( const char * pszName,
465 : const char * pszDomain )
466 : {
467 940 : if (fpImage == NULL)
468 1 : return NULL;
469 939 : if (eAccess == GA_ReadOnly && !bHasReadEXIFMetadata &&
470 : (pszDomain == NULL || EQUAL(pszDomain, "")) &&
471 : pszName != NULL && EQUALN(pszName, "EXIF_", 5))
472 0 : ReadEXIFMetadata();
473 939 : return GDALPamDataset::GetMetadataItem(pszName, pszDomain);
474 : }
475 :
476 : /************************************************************************/
477 : /* EXIFInit() */
478 : /* */
479 : /* Create Metadata from Information file directory APP1 */
480 : /************************************************************************/
481 21 : int JPGDatasetCommon::EXIFInit(VSILFILE *fp)
482 : {
483 21 : int one = 1;
484 : TIFFHeader hdr;
485 :
486 21 : bigendian = (*(char *)&one == 0);
487 :
488 : /* -------------------------------------------------------------------- */
489 : /* Search for APP1 chunk. */
490 : /* -------------------------------------------------------------------- */
491 : GByte abyChunkHeader[10];
492 21 : int nChunkLoc = 2;
493 :
494 24 : for( ; TRUE; )
495 : {
496 45 : if( VSIFSeekL( fp, nChunkLoc, SEEK_SET ) != 0 )
497 0 : return FALSE;
498 :
499 45 : if( VSIFReadL( abyChunkHeader, sizeof(abyChunkHeader), 1, fp ) != 1 )
500 0 : return FALSE;
501 :
502 90 : if( abyChunkHeader[0] != 0xFF
503 45 : || (abyChunkHeader[1] & 0xf0) != 0xe0 )
504 16 : return FALSE; // Not an APP chunk.
505 :
506 29 : if( abyChunkHeader[1] == 0xe1
507 : && strncmp((const char *) abyChunkHeader + 4,"Exif",4) == 0 )
508 : {
509 5 : nTIFFHEADER = nChunkLoc + 10;
510 : break; // APP1 - Exif
511 : }
512 :
513 24 : nChunkLoc += 2 + abyChunkHeader[2] * 256 + abyChunkHeader[3];
514 : }
515 :
516 : /* -------------------------------------------------------------------- */
517 : /* Read TIFF header */
518 : /* -------------------------------------------------------------------- */
519 5 : VSIFSeekL(fp, nTIFFHEADER, SEEK_SET);
520 5 : if(VSIFReadL(&hdr,1,sizeof(hdr),fp) != sizeof(hdr))
521 : CPLError( CE_Failure, CPLE_FileIO,
522 : "Failed to read %d byte from image header.",
523 0 : (int) sizeof(hdr));
524 :
525 5 : if (hdr.tiff_magic != TIFF_BIGENDIAN && hdr.tiff_magic != TIFF_LITTLEENDIAN)
526 : CPLError( CE_Failure, CPLE_AppDefined,
527 : "Not a TIFF file, bad magic number %u (%#x)",
528 0 : hdr.tiff_magic, hdr.tiff_magic);
529 :
530 5 : if (hdr.tiff_magic == TIFF_BIGENDIAN) bSwabflag = !bigendian;
531 5 : if (hdr.tiff_magic == TIFF_LITTLEENDIAN) bSwabflag = bigendian;
532 :
533 :
534 5 : if (bSwabflag) {
535 1 : CPL_SWAP16PTR(&hdr.tiff_version);
536 1 : CPL_SWAP32PTR(&hdr.tiff_diroff);
537 : }
538 :
539 :
540 5 : if (hdr.tiff_version != TIFF_VERSION)
541 : CPLError(CE_Failure, CPLE_AppDefined,
542 : "Not a TIFF file, bad version number %u (%#x)",
543 0 : hdr.tiff_version, hdr.tiff_version);
544 5 : nTiffDirStart = hdr.tiff_diroff;
545 :
546 : CPLDebug( "JPEG", "Magic: %#x <%s-endian> Version: %#x\n",
547 : hdr.tiff_magic,
548 : hdr.tiff_magic == TIFF_BIGENDIAN ? "big" : "little",
549 5 : hdr.tiff_version );
550 :
551 5 : return TRUE;
552 : }
553 :
554 : /************************************************************************/
555 : /* JPGMaskBand() */
556 : /************************************************************************/
557 :
558 4 : JPGMaskBand::JPGMaskBand( JPGDataset *poDS )
559 :
560 : {
561 4 : this->poDS = poDS;
562 4 : nBand = 0;
563 :
564 4 : nRasterXSize = poDS->GetRasterXSize();
565 4 : nRasterYSize = poDS->GetRasterYSize();
566 :
567 4 : eDataType = GDT_Byte;
568 4 : nBlockXSize = nRasterXSize;
569 4 : nBlockYSize = 1;
570 4 : }
571 :
572 : /************************************************************************/
573 : /* IReadBlock() */
574 : /************************************************************************/
575 :
576 2048 : CPLErr JPGMaskBand::IReadBlock( int nBlockX, int nBlockY, void *pImage )
577 :
578 : {
579 2048 : JPGDataset *poJDS = (JPGDataset *) poDS;
580 :
581 : /* -------------------------------------------------------------------- */
582 : /* Make sure the mask is loaded and decompressed. */
583 : /* -------------------------------------------------------------------- */
584 2048 : poJDS->DecompressMask();
585 2048 : if( poJDS->pabyBitMask == NULL )
586 0 : return CE_Failure;
587 :
588 : /* -------------------------------------------------------------------- */
589 : /* Set mask based on bitmask for this scanline. */
590 : /* -------------------------------------------------------------------- */
591 : int iX;
592 2048 : GUInt32 iBit = (GUInt32)nBlockY * (GUInt32)nBlockXSize;
593 :
594 1050624 : for( iX = 0; iX < nBlockXSize; iX++ )
595 : {
596 1048576 : if( poJDS->pabyBitMask[iBit>>3] & (0x1 << (iBit&7)) )
597 790528 : ((GByte *) pImage)[iX] = 255;
598 : else
599 258048 : ((GByte *) pImage)[iX] = 0;
600 1048576 : iBit++;
601 : }
602 :
603 2048 : return CE_None;
604 : }
605 :
606 : /************************************************************************/
607 : /* JPGRasterBand() */
608 : /************************************************************************/
609 :
610 317 : JPGRasterBand::JPGRasterBand( JPGDatasetCommon *poDS, int nBand )
611 :
612 : {
613 317 : this->poDS = poGDS = poDS;
614 :
615 317 : this->nBand = nBand;
616 317 : if( poDS->GetDataPrecision() == 12 )
617 19 : eDataType = GDT_UInt16;
618 : else
619 298 : eDataType = GDT_Byte;
620 :
621 317 : nBlockXSize = poDS->nRasterXSize;;
622 317 : nBlockYSize = 1;
623 :
624 317 : GDALMajorObject::SetMetadataItem("COMPRESSION","JPEG","IMAGE_STRUCTURE");
625 317 : }
626 :
627 : /************************************************************************/
628 : /* JPGCreateBand() */
629 : /************************************************************************/
630 :
631 317 : GDALRasterBand* JPGCreateBand(JPGDatasetCommon* poDS, int nBand)
632 : {
633 317 : return new JPGRasterBand(poDS, nBand);
634 : }
635 :
636 : /************************************************************************/
637 : /* IReadBlock() */
638 : /************************************************************************/
639 :
640 41684 : CPLErr JPGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
641 : void * pImage )
642 :
643 : {
644 : CPLErr eErr;
645 41684 : int nXSize = GetXSize();
646 41684 : int nWordSize = GDALGetDataTypeSize(eDataType) / 8;
647 :
648 41684 : CPLAssert( nBlockXOff == 0 );
649 :
650 41684 : if (poGDS->fpImage == NULL)
651 : {
652 70 : memset( pImage, 0, nXSize * nWordSize );
653 70 : return CE_None;
654 : }
655 :
656 : /* -------------------------------------------------------------------- */
657 : /* Load the desired scanline into the working buffer. */
658 : /* -------------------------------------------------------------------- */
659 41614 : eErr = poGDS->LoadScanline( nBlockYOff );
660 41614 : if( eErr != CE_None )
661 1 : return eErr;
662 :
663 : /* -------------------------------------------------------------------- */
664 : /* Transfer between the working buffer the the callers buffer. */
665 : /* -------------------------------------------------------------------- */
666 41613 : if( poGDS->GetRasterCount() == 1 )
667 : {
668 : #ifdef JPEG_LIB_MK1_OR_12BIT
669 : GDALCopyWords( poGDS->pabyScanline, GDT_UInt16, 2,
670 : pImage, eDataType, nWordSize,
671 : nXSize );
672 : #else
673 24669 : memcpy( pImage, poGDS->pabyScanline, nXSize * nWordSize );
674 : #endif
675 : }
676 : else
677 : {
678 : #ifdef JPEG_LIB_MK1_OR_12BIT
679 : GDALCopyWords( poGDS->pabyScanline + (nBand-1) * 2,
680 : GDT_UInt16, 6,
681 : pImage, eDataType, nWordSize,
682 : nXSize );
683 : #else
684 33688 : if (poGDS->eGDALColorSpace == JCS_RGB &&
685 16744 : poGDS->GetOutColorSpace() == JCS_CMYK)
686 : {
687 150 : CPLAssert(eDataType == GDT_Byte);
688 : int i;
689 150 : if (nBand == 1)
690 : {
691 2550 : for(i=0;i<nXSize;i++)
692 : {
693 2500 : int C = poGDS->pabyScanline[i * 4 + 0];
694 2500 : int K = poGDS->pabyScanline[i * 4 + 3];
695 2500 : ((GByte*)pImage)[i] = (GByte) ((C * K) / 255);
696 : }
697 : }
698 100 : else if (nBand == 2)
699 : {
700 2550 : for(i=0;i<nXSize;i++)
701 : {
702 2500 : int M = poGDS->pabyScanline[i * 4 + 1];
703 2500 : int K = poGDS->pabyScanline[i * 4 + 3];
704 2500 : ((GByte*)pImage)[i] = (GByte) ((M * K) / 255);
705 : }
706 : }
707 50 : else if (nBand == 3)
708 : {
709 2550 : for(i=0;i<nXSize;i++)
710 : {
711 2500 : int Y = poGDS->pabyScanline[i * 4 + 2];
712 2500 : int K = poGDS->pabyScanline[i * 4 + 3];
713 2500 : ((GByte*)pImage)[i] = (GByte) ((Y * K) / 255);
714 : }
715 : }
716 : }
717 : else
718 : {
719 : GDALCopyWords( poGDS->pabyScanline + (nBand-1) * nWordSize,
720 : eDataType, nWordSize * poGDS->GetRasterCount(),
721 : pImage, eDataType, nWordSize,
722 16794 : nXSize );
723 : }
724 : #endif
725 : }
726 :
727 : /* -------------------------------------------------------------------- */
728 : /* Forceably load the other bands associated with this scanline. */
729 : /* -------------------------------------------------------------------- */
730 41613 : if( nBand == 1 )
731 : {
732 : GDALRasterBlock *poBlock;
733 :
734 : int iBand;
735 40916 : for(iBand = 2; iBand <= poGDS->GetRasterCount() ; iBand++)
736 : {
737 : poBlock =
738 10848 : poGDS->GetRasterBand(iBand)->GetLockedBlockRef(nBlockXOff,nBlockYOff);
739 10848 : if( poBlock != NULL )
740 10848 : poBlock->DropLock();
741 : }
742 : }
743 :
744 :
745 41613 : return CE_None;
746 : }
747 :
748 : /************************************************************************/
749 : /* GetColorInterpretation() */
750 : /************************************************************************/
751 :
752 111 : GDALColorInterp JPGRasterBand::GetColorInterpretation()
753 :
754 : {
755 111 : if( poGDS->eGDALColorSpace == JCS_GRAYSCALE )
756 27 : return GCI_GrayIndex;
757 :
758 84 : else if( poGDS->eGDALColorSpace == JCS_RGB)
759 : {
760 80 : if ( nBand == 1 )
761 29 : return GCI_RedBand;
762 :
763 51 : else if( nBand == 2 )
764 25 : return GCI_GreenBand;
765 :
766 : else
767 26 : return GCI_BlueBand;
768 : }
769 4 : else if( poGDS->eGDALColorSpace == JCS_CMYK)
770 : {
771 4 : if ( nBand == 1 )
772 1 : return GCI_CyanBand;
773 :
774 3 : else if( nBand == 2 )
775 1 : return GCI_MagentaBand;
776 :
777 2 : else if ( nBand == 3 )
778 1 : return GCI_YellowBand;
779 :
780 : else
781 1 : return GCI_BlackBand;
782 : }
783 0 : else if( poGDS->eGDALColorSpace == JCS_YCbCr ||
784 : poGDS->eGDALColorSpace == JCS_YCCK)
785 : {
786 0 : if ( nBand == 1 )
787 0 : return GCI_YCbCr_YBand;
788 :
789 0 : else if( nBand == 2 )
790 0 : return GCI_YCbCr_CbBand;
791 :
792 0 : else if ( nBand == 3 )
793 0 : return GCI_YCbCr_CrBand;
794 :
795 : else
796 0 : return GCI_BlackBand;
797 : }
798 : else
799 : {
800 0 : CPLAssert(0);
801 0 : return GCI_Undefined;
802 : }
803 : }
804 :
805 : /************************************************************************/
806 : /* GetMaskBand() */
807 : /************************************************************************/
808 :
809 55 : GDALRasterBand *JPGRasterBand::GetMaskBand()
810 :
811 : {
812 55 : if (poGDS->nScaleFactor > 1 )
813 0 : return GDALPamRasterBand::GetMaskBand();
814 :
815 55 : if (poGDS->fpImage == NULL)
816 0 : return NULL;
817 :
818 55 : if( !poGDS->bHasCheckedForMask)
819 : {
820 18 : poGDS->CheckForMask();
821 18 : poGDS->bHasCheckedForMask = TRUE;
822 : }
823 55 : if( poGDS->pabyCMask )
824 : {
825 11 : if( poGDS->poMaskBand == NULL )
826 4 : poGDS->poMaskBand = new JPGMaskBand( (JPGDataset *) poDS );
827 :
828 11 : return poGDS->poMaskBand;
829 : }
830 : else
831 44 : return GDALPamRasterBand::GetMaskBand();
832 : }
833 :
834 : /************************************************************************/
835 : /* GetMaskFlags() */
836 : /************************************************************************/
837 :
838 50 : int JPGRasterBand::GetMaskFlags()
839 :
840 : {
841 50 : if (poGDS->nScaleFactor > 1 )
842 0 : return GDALPamRasterBand::GetMaskFlags();
843 :
844 50 : if (poGDS->fpImage == NULL)
845 0 : return 0;
846 :
847 50 : GetMaskBand();
848 50 : if( poGDS->poMaskBand != NULL )
849 7 : return GMF_PER_DATASET;
850 : else
851 43 : return GDALPamRasterBand::GetMaskFlags();
852 : }
853 :
854 : /************************************************************************/
855 : /* GetOverview() */
856 : /************************************************************************/
857 :
858 22 : GDALRasterBand* JPGRasterBand::GetOverview(int i)
859 : {
860 22 : poGDS->InitInternalOverviews();
861 :
862 22 : if( poGDS->nInternalOverviewsCurrent == 0 )
863 14 : return GDALPamRasterBand::GetOverview(i);
864 :
865 8 : if( i < 0 || i >= poGDS->nInternalOverviewsCurrent )
866 2 : return NULL;
867 : else
868 6 : return poGDS->papoInternalOverviews[i]->GetRasterBand(nBand);
869 : }
870 :
871 : /************************************************************************/
872 : /* GetOverviewCount() */
873 : /************************************************************************/
874 :
875 42 : int JPGRasterBand::GetOverviewCount()
876 : {
877 42 : poGDS->InitInternalOverviews();
878 :
879 42 : if( poGDS->nInternalOverviewsCurrent == 0 )
880 38 : return GDALPamRasterBand::GetOverviewCount();
881 :
882 4 : return poGDS->nInternalOverviewsCurrent;
883 : }
884 :
885 : /************************************************************************/
886 : /* ==================================================================== */
887 : /* JPGDataset */
888 : /* ==================================================================== */
889 : /************************************************************************/
890 :
891 204 : JPGDatasetCommon::JPGDatasetCommon()
892 :
893 : {
894 204 : fpImage = NULL;
895 204 : bOwnFPImage = FALSE;
896 :
897 204 : nScaleFactor = 1;
898 204 : bHasInitInternalOverviews = FALSE;
899 204 : nInternalOverviewsCurrent = 0;
900 204 : nInternalOverviewsToFree = 0;
901 204 : papoInternalOverviews = NULL;
902 :
903 204 : pabyScanline = NULL;
904 204 : nLoadedScanline = -1;
905 :
906 204 : bHasReadEXIFMetadata = FALSE;
907 204 : bHasReadXMPMetadata = FALSE;
908 204 : papszMetadata = NULL;
909 204 : papszSubDatasets= NULL;
910 204 : nExifOffset = -1;
911 204 : nInterOffset = -1;
912 204 : nGPSOffset = -1;
913 :
914 204 : pszProjection = NULL;
915 204 : bGeoTransformValid = FALSE;
916 204 : adfGeoTransform[0] = 0.0;
917 204 : adfGeoTransform[1] = 1.0;
918 204 : adfGeoTransform[2] = 0.0;
919 204 : adfGeoTransform[3] = 0.0;
920 204 : adfGeoTransform[4] = 0.0;
921 204 : adfGeoTransform[5] = 1.0;
922 204 : nGCPCount = 0;
923 204 : pasGCPList = NULL;
924 :
925 204 : bHasDoneJpegCreateDecompress = FALSE;
926 204 : bHasDoneJpegStartDecompress = FALSE;
927 :
928 204 : bHasCheckedForMask = FALSE;
929 204 : poMaskBand = NULL;
930 204 : pabyBitMask = NULL;
931 204 : pabyCMask = NULL;
932 204 : nCMaskSize = 0;
933 :
934 204 : eGDALColorSpace = JCS_UNKNOWN;
935 :
936 204 : bIsSubfile = FALSE;
937 204 : bHasTriedLoadWorldFileOrTab = FALSE;
938 204 : }
939 :
940 : /************************************************************************/
941 : /* ~JPGDataset() */
942 : /************************************************************************/
943 :
944 204 : JPGDatasetCommon::~JPGDatasetCommon()
945 :
946 : {
947 204 : if( bOwnFPImage && fpImage != NULL )
948 202 : VSIFCloseL( fpImage );
949 :
950 204 : if( pabyScanline != NULL )
951 103 : CPLFree( pabyScanline );
952 204 : if( papszMetadata != NULL )
953 5 : CSLDestroy( papszMetadata );
954 :
955 204 : if ( pszProjection )
956 0 : CPLFree( pszProjection );
957 :
958 204 : if ( nGCPCount > 0 )
959 : {
960 0 : GDALDeinitGCPs( nGCPCount, pasGCPList );
961 0 : CPLFree( pasGCPList );
962 : }
963 :
964 204 : CPLFree( pabyBitMask );
965 204 : CPLFree( pabyCMask );
966 204 : delete poMaskBand;
967 :
968 204 : CloseDependentDatasets();
969 204 : }
970 :
971 : /************************************************************************/
972 : /* CloseDependentDatasets() */
973 : /************************************************************************/
974 :
975 204 : int JPGDatasetCommon::CloseDependentDatasets()
976 : {
977 204 : int bRet = GDALPamDataset::CloseDependentDatasets();
978 204 : if( nInternalOverviewsToFree )
979 : {
980 5 : bRet = TRUE;
981 12 : for(int i = 0; i < nInternalOverviewsToFree; i++)
982 7 : delete papoInternalOverviews[i];
983 5 : CPLFree(papoInternalOverviews);
984 5 : papoInternalOverviews = NULL;
985 5 : nInternalOverviewsToFree = 0;
986 : }
987 204 : return bRet;
988 : }
989 :
990 : /************************************************************************/
991 : /* InitInternalOverviews() */
992 : /************************************************************************/
993 :
994 64 : void JPGDatasetCommon::InitInternalOverviews()
995 : {
996 64 : if( bHasInitInternalOverviews )
997 53 : return;
998 11 : bHasInitInternalOverviews = TRUE;
999 :
1000 : /* -------------------------------------------------------------------- */
1001 : /* Instanciate on-the-fly overviews (if no external ones). */
1002 : /* -------------------------------------------------------------------- */
1003 11 : if( nScaleFactor == 1 && GetRasterBand(1)->GetOverviewCount() == 0 )
1004 : {
1005 : /* libjpeg-6b only suppports 2, 4 and 8 scale denominators */
1006 : /* TODO: Later versions support more */
1007 :
1008 : int i;
1009 10 : int nInternalOverviews = 0;
1010 :
1011 33 : for(i = 2; i >= 0; i--)
1012 : {
1013 28 : if( nRasterXSize >= (256 << i) || nRasterYSize >= (256 << i) )
1014 : {
1015 5 : nInternalOverviews = i + 1;
1016 5 : break;
1017 : }
1018 : }
1019 :
1020 10 : if( nInternalOverviews > 0 )
1021 : {
1022 : papoInternalOverviews = (GDALDataset**)
1023 5 : CPLMalloc(nInternalOverviews * sizeof(GDALDataset*));
1024 12 : for(i = 0; i < nInternalOverviews; i++ )
1025 : {
1026 7 : papoInternalOverviews[i] =
1027 7 : JPGDataset::Open(GetDescription(), NULL, 1 << (i + 1));
1028 7 : if( papoInternalOverviews[i] == NULL )
1029 : {
1030 0 : nInternalOverviews = i;
1031 0 : break;
1032 : }
1033 : }
1034 :
1035 5 : nInternalOverviewsCurrent = nInternalOverviewsToFree = nInternalOverviews;
1036 : }
1037 : }
1038 : }
1039 :
1040 : /************************************************************************/
1041 : /* IBuildOverviews() */
1042 : /************************************************************************/
1043 :
1044 1 : CPLErr JPGDatasetCommon::IBuildOverviews( const char *pszResampling,
1045 : int nOverviewsListCount,
1046 : int *panOverviewList,
1047 : int nListBands, int *panBandList,
1048 : GDALProgressFunc pfnProgress,
1049 : void * pProgressData )
1050 : {
1051 : CPLErr eErr;
1052 :
1053 1 : bHasInitInternalOverviews = TRUE;
1054 1 : nInternalOverviewsCurrent = 0;
1055 :
1056 : eErr = GDALPamDataset::IBuildOverviews(pszResampling,
1057 : nOverviewsListCount,
1058 : panOverviewList,
1059 : nListBands, panBandList,
1060 1 : pfnProgress, pProgressData);
1061 :
1062 1 : return eErr;
1063 : }
1064 :
1065 : #endif // !defined(JPGDataset)
1066 :
1067 : /************************************************************************/
1068 : /* JPGDataset() */
1069 : /************************************************************************/
1070 :
1071 204 : JPGDataset::JPGDataset()
1072 :
1073 : {
1074 204 : sDInfo.data_precision = 8;
1075 204 : }
1076 :
1077 : /************************************************************************/
1078 : /* ~JPGDataset() */
1079 : /************************************************************************/
1080 :
1081 204 : JPGDataset::~JPGDataset()
1082 :
1083 : {
1084 204 : FlushCache();
1085 :
1086 204 : if (bHasDoneJpegStartDecompress)
1087 : {
1088 103 : jpeg_abort_decompress( &sDInfo );
1089 : }
1090 204 : if (bHasDoneJpegCreateDecompress)
1091 : {
1092 202 : jpeg_destroy_decompress( &sDInfo );
1093 : }
1094 204 : }
1095 :
1096 : /************************************************************************/
1097 : /* LoadScanline() */
1098 : /************************************************************************/
1099 :
1100 41614 : CPLErr JPGDataset::LoadScanline( int iLine )
1101 :
1102 : {
1103 41614 : if( nLoadedScanline == iLine )
1104 10667 : return CE_None;
1105 :
1106 : // setup to trap a fatal error.
1107 30947 : if (setjmp(setjmp_buffer))
1108 1 : return CE_Failure;
1109 :
1110 30947 : if (!bHasDoneJpegStartDecompress)
1111 : {
1112 104 : jpeg_start_decompress( &sDInfo );
1113 103 : bHasDoneJpegStartDecompress = TRUE;
1114 : }
1115 :
1116 30946 : if( pabyScanline == NULL )
1117 : {
1118 103 : int nJPEGBands = 0;
1119 103 : switch(sDInfo.out_color_space)
1120 : {
1121 : case JCS_GRAYSCALE:
1122 65 : nJPEGBands = 1;
1123 65 : break;
1124 : case JCS_RGB:
1125 : case JCS_YCbCr:
1126 36 : nJPEGBands = 3;
1127 36 : break;
1128 : case JCS_CMYK:
1129 : case JCS_YCCK:
1130 2 : nJPEGBands = 4;
1131 2 : break;
1132 :
1133 : default:
1134 0 : CPLAssert(0);
1135 : }
1136 :
1137 : pabyScanline = (GByte *)
1138 103 : CPLMalloc(nJPEGBands * GetRasterXSize() * 2);
1139 : }
1140 :
1141 30946 : if( iLine < nLoadedScanline )
1142 4 : Restart();
1143 :
1144 94451 : while( nLoadedScanline < iLine )
1145 : {
1146 : JSAMPLE *ppSamples;
1147 :
1148 32559 : ppSamples = (JSAMPLE *) pabyScanline;
1149 32559 : jpeg_read_scanlines( &sDInfo, &ppSamples, 1 );
1150 32559 : nLoadedScanline++;
1151 : }
1152 :
1153 30946 : return CE_None;
1154 : }
1155 :
1156 : /************************************************************************/
1157 : /* LoadDefaultTables() */
1158 : /************************************************************************/
1159 :
1160 : #if !defined(JPGDataset)
1161 :
1162 : const GByte Q1table[64] =
1163 : {
1164 : 8, 72, 72, 72, 72, 72, 72, 72, // 0 - 7
1165 : 72, 72, 78, 74, 76, 74, 78, 89, // 8 - 15
1166 : 81, 84, 84, 81, 89, 106, 93, 94, // 16 - 23
1167 : 99, 94, 93, 106, 129, 111, 108, 116, // 24 - 31
1168 : 116, 108, 111, 129, 135, 128, 136, 145, // 32 - 39
1169 : 136, 128, 135, 155, 160, 177, 177, 160, // 40 - 47
1170 : 155, 193, 213, 228, 213, 193, 255, 255, // 48 - 55
1171 : 255, 255, 255, 255, 255, 255, 255, 255 // 56 - 63
1172 : };
1173 :
1174 : const GByte Q2table[64] =
1175 : {
1176 : 8, 36, 36, 36,
1177 : 36, 36, 36, 36, 36, 36, 39, 37, 38, 37, 39, 45, 41, 42, 42, 41, 45, 53,
1178 : 47, 47, 50, 47, 47, 53, 65, 56, 54, 59, 59, 54, 56, 65, 68, 64, 69, 73,
1179 : 69, 64, 68, 78, 81, 89, 89, 81, 78, 98,108,115,108, 98,130,144,144,130,
1180 : 178,190,178,243,243,255
1181 : };
1182 :
1183 : const GByte Q3table[64] =
1184 : {
1185 : 8, 10, 10, 10,
1186 : 10, 10, 10, 10, 10, 10, 11, 10, 11, 10, 11, 13, 11, 12, 12, 11, 13, 15,
1187 : 13, 13, 14, 13, 13, 15, 18, 16, 15, 16, 16, 15, 16, 18, 19, 18, 19, 21,
1188 : 19, 18, 19, 22, 23, 25, 25, 23, 22, 27, 30, 32, 30, 27, 36, 40, 40, 36,
1189 : 50, 53, 50, 68, 68, 91
1190 : };
1191 :
1192 : const GByte Q4table[64] =
1193 : {
1194 : 8, 7, 7, 7,
1195 : 7, 7, 7, 7, 7, 7, 8, 7, 8, 7, 8, 9, 8, 8, 8, 8, 9, 11,
1196 : 9, 9, 10, 9, 9, 11, 13, 11, 11, 12, 12, 11, 11, 13, 14, 13, 14, 15,
1197 : 14, 13, 14, 16, 16, 18, 18, 16, 16, 20, 22, 23, 22, 20, 26, 29, 29, 26,
1198 : 36, 38, 36, 49, 49, 65
1199 : };
1200 :
1201 : const GByte Q5table[64] =
1202 : {
1203 : 4, 4, 4, 4,
1204 : 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6,
1205 : 5, 5, 6, 5, 5, 6, 7, 6, 6, 6, 6, 6, 6, 7, 8, 7, 8, 8,
1206 : 8, 7, 8, 9, 9, 10, 10, 9, 9, 11, 12, 13, 12, 11, 14, 16, 16, 14,
1207 : 20, 21, 20, 27, 27, 36
1208 : };
1209 :
1210 : const GByte AC_BITS[16] =
1211 : { 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 125 };
1212 :
1213 : const GByte AC_HUFFVAL[256] = {
1214 : 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
1215 : 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
1216 : 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08,
1217 : 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0,
1218 : 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16,
1219 : 0x17, 0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28,
1220 : 0x29, 0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
1221 : 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
1222 : 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
1223 : 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
1224 : 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
1225 : 0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
1226 : 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
1227 : 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
1228 : 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6,
1229 : 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5,
1230 : 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4,
1231 : 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2,
1232 : 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA,
1233 : 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
1234 : 0xF9, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1235 : 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1236 : 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1237 : 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1238 : 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1239 : 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1240 : 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1241 : 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1242 : 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1243 : 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
1244 :
1245 : const GByte DC_BITS[16] =
1246 : { 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
1247 :
1248 : const GByte DC_HUFFVAL[256] = {
1249 : 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1250 : 0x08, 0x09, 0x0A, 0x0B };
1251 :
1252 : #endif // !defined(JPGDataset)
1253 :
1254 824 : void JPGDataset::LoadDefaultTables( int n )
1255 : {
1256 824 : if( nQLevel < 1 )
1257 820 : return;
1258 :
1259 : /* -------------------------------------------------------------------- */
1260 : /* Load quantization table */
1261 : /* -------------------------------------------------------------------- */
1262 : int i;
1263 : JQUANT_TBL *quant_ptr;
1264 : const GByte *pabyQTable;
1265 :
1266 4 : if( nQLevel == 1 )
1267 4 : pabyQTable = Q1table;
1268 0 : else if( nQLevel == 2 )
1269 0 : pabyQTable = Q2table;
1270 0 : else if( nQLevel == 3 )
1271 0 : pabyQTable = Q3table;
1272 0 : else if( nQLevel == 4 )
1273 0 : pabyQTable = Q4table;
1274 0 : else if( nQLevel == 5 )
1275 0 : pabyQTable = Q5table;
1276 : else
1277 0 : return;
1278 :
1279 4 : if (sDInfo.quant_tbl_ptrs[n] == NULL)
1280 4 : sDInfo.quant_tbl_ptrs[n] =
1281 4 : jpeg_alloc_quant_table((j_common_ptr) &(sDInfo));
1282 :
1283 4 : quant_ptr = sDInfo.quant_tbl_ptrs[n]; /* quant_ptr is JQUANT_TBL* */
1284 260 : for (i = 0; i < 64; i++) {
1285 : /* Qtable[] is desired quantization table, in natural array order */
1286 256 : quant_ptr->quantval[i] = pabyQTable[i];
1287 : }
1288 :
1289 : /* -------------------------------------------------------------------- */
1290 : /* Load AC huffman table. */
1291 : /* -------------------------------------------------------------------- */
1292 : JHUFF_TBL *huff_ptr;
1293 :
1294 4 : if (sDInfo.ac_huff_tbl_ptrs[n] == NULL)
1295 4 : sDInfo.ac_huff_tbl_ptrs[n] =
1296 4 : jpeg_alloc_huff_table((j_common_ptr)&sDInfo);
1297 :
1298 4 : huff_ptr = sDInfo.ac_huff_tbl_ptrs[n]; /* huff_ptr is JHUFF_TBL* */
1299 :
1300 68 : for (i = 1; i <= 16; i++) {
1301 : /* counts[i] is number of Huffman codes of length i bits, i=1..16 */
1302 64 : huff_ptr->bits[i] = AC_BITS[i-1];
1303 : }
1304 :
1305 1028 : for (i = 0; i < 256; i++) {
1306 : /* symbols[] is the list of Huffman symbols, in code-length order */
1307 1024 : huff_ptr->huffval[i] = AC_HUFFVAL[i];
1308 : }
1309 :
1310 : /* -------------------------------------------------------------------- */
1311 : /* Load DC huffman table. */
1312 : /* -------------------------------------------------------------------- */
1313 4 : if (sDInfo.dc_huff_tbl_ptrs[n] == NULL)
1314 4 : sDInfo.dc_huff_tbl_ptrs[n] =
1315 4 : jpeg_alloc_huff_table((j_common_ptr)&sDInfo);
1316 :
1317 4 : huff_ptr = sDInfo.dc_huff_tbl_ptrs[n]; /* huff_ptr is JHUFF_TBL* */
1318 :
1319 68 : for (i = 1; i <= 16; i++) {
1320 : /* counts[i] is number of Huffman codes of length i bits, i=1..16 */
1321 64 : huff_ptr->bits[i] = DC_BITS[i-1];
1322 : }
1323 :
1324 1028 : for (i = 0; i < 256; i++) {
1325 : /* symbols[] is the list of Huffman symbols, in code-length order */
1326 1024 : huff_ptr->huffval[i] = DC_HUFFVAL[i];
1327 : }
1328 :
1329 : }
1330 :
1331 : /************************************************************************/
1332 : /* SetScaleNumAndDenom() */
1333 : /************************************************************************/
1334 :
1335 188 : void JPGDataset::SetScaleNumAndDenom()
1336 : {
1337 : #if JPEG_LIB_VERSION > 62
1338 : sDInfo.scale_num = 8 / nScaleFactor;
1339 : sDInfo.scale_denom = 8;
1340 : #else
1341 188 : sDInfo.scale_num = 1;
1342 188 : sDInfo.scale_denom = nScaleFactor;
1343 : #endif
1344 188 : }
1345 :
1346 : /************************************************************************/
1347 : /* Restart() */
1348 : /* */
1349 : /* Restart compressor at the beginning of the file. */
1350 : /************************************************************************/
1351 :
1352 4 : void JPGDataset::Restart()
1353 :
1354 : {
1355 4 : J_COLOR_SPACE colorSpace = sDInfo.out_color_space;
1356 :
1357 4 : jpeg_abort_decompress( &sDInfo );
1358 4 : jpeg_destroy_decompress( &sDInfo );
1359 4 : jpeg_create_decompress( &sDInfo );
1360 :
1361 4 : LoadDefaultTables( 0 );
1362 4 : LoadDefaultTables( 1 );
1363 4 : LoadDefaultTables( 2 );
1364 4 : LoadDefaultTables( 3 );
1365 :
1366 : /* -------------------------------------------------------------------- */
1367 : /* restart io. */
1368 : /* -------------------------------------------------------------------- */
1369 4 : VSIFSeekL( fpImage, nSubfileOffset, SEEK_SET );
1370 :
1371 4 : jpeg_vsiio_src( &sDInfo, fpImage );
1372 4 : jpeg_read_header( &sDInfo, TRUE );
1373 :
1374 4 : sDInfo.out_color_space = colorSpace;
1375 4 : nLoadedScanline = -1;
1376 4 : SetScaleNumAndDenom();
1377 4 : jpeg_start_decompress( &sDInfo );
1378 4 : bHasDoneJpegStartDecompress = TRUE;
1379 4 : }
1380 :
1381 : #if !defined(JPGDataset)
1382 :
1383 : /************************************************************************/
1384 : /* GetGeoTransform() */
1385 : /************************************************************************/
1386 :
1387 31 : CPLErr JPGDatasetCommon::GetGeoTransform( double * padfTransform )
1388 :
1389 : {
1390 31 : LoadWorldFileOrTab();
1391 :
1392 31 : if( bGeoTransformValid )
1393 : {
1394 3 : memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
1395 :
1396 3 : return CE_None;
1397 : }
1398 : else
1399 28 : return GDALPamDataset::GetGeoTransform( padfTransform );
1400 : }
1401 :
1402 : /************************************************************************/
1403 : /* GetGCPCount() */
1404 : /************************************************************************/
1405 :
1406 20 : int JPGDatasetCommon::GetGCPCount()
1407 :
1408 : {
1409 20 : LoadWorldFileOrTab();
1410 :
1411 20 : return nGCPCount;
1412 : }
1413 :
1414 : /************************************************************************/
1415 : /* GetGCPProjection() */
1416 : /************************************************************************/
1417 :
1418 0 : const char *JPGDatasetCommon::GetGCPProjection()
1419 :
1420 : {
1421 0 : LoadWorldFileOrTab();
1422 :
1423 0 : if( pszProjection && nGCPCount > 0 )
1424 0 : return pszProjection;
1425 : else
1426 0 : return "";
1427 : }
1428 :
1429 : /************************************************************************/
1430 : /* GetGCPs() */
1431 : /************************************************************************/
1432 :
1433 0 : const GDAL_GCP *JPGDatasetCommon::GetGCPs()
1434 :
1435 : {
1436 0 : LoadWorldFileOrTab();
1437 :
1438 0 : return pasGCPList;
1439 : }
1440 :
1441 : /************************************************************************/
1442 : /* IRasterIO() */
1443 : /* */
1444 : /* Checks for what might be the most common read case */
1445 : /* (reading an entire interleaved, 8bit, RGB JPEG), and */
1446 : /* optimizes for that case */
1447 : /************************************************************************/
1448 :
1449 865 : CPLErr JPGDatasetCommon::IRasterIO( GDALRWFlag eRWFlag,
1450 : int nXOff, int nYOff, int nXSize, int nYSize,
1451 : void *pData, int nBufXSize, int nBufYSize,
1452 : GDALDataType eBufType,
1453 : int nBandCount, int *panBandMap,
1454 : int nPixelSpace, int nLineSpace, int nBandSpace )
1455 :
1456 : {
1457 874 : if((eRWFlag == GF_Read) &&
1458 : (nBandCount == 3) &&
1459 : (nBands == 3) &&
1460 : (nXOff == 0) && (nXOff == 0) &&
1461 : (nXSize == nBufXSize) && (nXSize == nRasterXSize) &&
1462 : (nYSize == nBufYSize) && (nYSize == nRasterYSize) &&
1463 9 : (eBufType == GDT_Byte) && (GetDataPrecision() != 12) &&
1464 : /*(nPixelSpace >= 3)*/(nPixelSpace > 3) &&
1465 : (nLineSpace == (nPixelSpace*nXSize)) &&
1466 : (nBandSpace == 1) &&
1467 : (pData != NULL) &&
1468 : (panBandMap != NULL) &&
1469 0 : (panBandMap[0] == 1) && (panBandMap[1] == 2) && (panBandMap[2] == 3))
1470 : {
1471 0 : Restart();
1472 : int y;
1473 : CPLErr tmpError;
1474 : int x;
1475 :
1476 : // handles copy with padding case
1477 0 : for(y = 0; y < nYSize; ++y)
1478 : {
1479 0 : tmpError = LoadScanline(y);
1480 0 : if(tmpError != CE_None) return tmpError;
1481 :
1482 0 : for(x = 0; x < nXSize; ++x)
1483 : {
1484 0 : tmpError = LoadScanline(y);
1485 0 : if(tmpError != CE_None) return tmpError;
1486 : memcpy(&(((GByte*)pData)[(y*nLineSpace) + (x*nPixelSpace)]),
1487 0 : (const GByte*)&(pabyScanline[x*3]), 3);
1488 : }
1489 : }
1490 :
1491 0 : return CE_None;
1492 : }
1493 :
1494 : return GDALPamDataset::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
1495 : pData, nBufXSize, nBufYSize, eBufType,
1496 : nBandCount, panBandMap,
1497 865 : nPixelSpace, nLineSpace, nBandSpace);
1498 : }
1499 :
1500 : #if JPEG_LIB_VERSION_MAJOR < 9
1501 : /************************************************************************/
1502 : /* JPEGDatasetIsJPEGLS() */
1503 : /************************************************************************/
1504 :
1505 75 : static int JPEGDatasetIsJPEGLS( GDALOpenInfo * poOpenInfo )
1506 :
1507 : {
1508 75 : GByte *pabyHeader = poOpenInfo->pabyHeader;
1509 75 : int nHeaderBytes = poOpenInfo->nHeaderBytes;
1510 :
1511 75 : if( nHeaderBytes < 10 )
1512 0 : return FALSE;
1513 :
1514 150 : if( pabyHeader[0] != 0xff
1515 75 : || pabyHeader[1] != 0xd8 )
1516 0 : return FALSE;
1517 :
1518 75 : int nOffset = 2;
1519 684 : for (;nOffset + 4 < nHeaderBytes;)
1520 : {
1521 601 : if (pabyHeader[nOffset] != 0xFF)
1522 67 : return FALSE;
1523 :
1524 534 : int nMarker = pabyHeader[nOffset + 1];
1525 534 : if (nMarker == 0xF7 /* JPEG Extension 7, JPEG-LS */)
1526 0 : return TRUE;
1527 534 : if (nMarker == 0xF8 /* JPEG Extension 8, JPEG-LS Extension */)
1528 0 : return TRUE;
1529 534 : if (nMarker == 0xC3 /* Start of Frame 3 */)
1530 0 : return TRUE;
1531 534 : if (nMarker == 0xC7 /* Start of Frame 7 */)
1532 0 : return TRUE;
1533 534 : if (nMarker == 0xCB /* Start of Frame 11 */)
1534 0 : return TRUE;
1535 534 : if (nMarker == 0xCF /* Start of Frame 15 */)
1536 0 : return TRUE;
1537 :
1538 534 : nOffset += 2 + pabyHeader[nOffset + 2] * 256 + pabyHeader[nOffset + 3];
1539 : }
1540 :
1541 8 : return FALSE;
1542 : }
1543 : #endif
1544 :
1545 : /************************************************************************/
1546 : /* Identify() */
1547 : /************************************************************************/
1548 :
1549 14033 : int JPGDatasetCommon::Identify( GDALOpenInfo * poOpenInfo )
1550 :
1551 : {
1552 14033 : GByte *pabyHeader = NULL;
1553 14033 : int nHeaderBytes = poOpenInfo->nHeaderBytes;
1554 :
1555 : /* -------------------------------------------------------------------- */
1556 : /* If it is a subfile, read the JPEG header. */
1557 : /* -------------------------------------------------------------------- */
1558 14033 : if( EQUALN(poOpenInfo->pszFilename,"JPEG_SUBFILE:",13) )
1559 68 : return TRUE;
1560 :
1561 : /* -------------------------------------------------------------------- */
1562 : /* First we check to see if the file has the expected header */
1563 : /* bytes. */
1564 : /* -------------------------------------------------------------------- */
1565 13965 : pabyHeader = poOpenInfo->pabyHeader;
1566 :
1567 13965 : if( nHeaderBytes < 10 )
1568 11992 : return FALSE;
1569 :
1570 2170 : if( pabyHeader[0] != 0xff
1571 122 : || pabyHeader[1] != 0xd8
1572 75 : || pabyHeader[2] != 0xff )
1573 1898 : return FALSE;
1574 :
1575 : #if JPEG_LIB_VERSION_MAJOR < 9
1576 75 : if (JPEGDatasetIsJPEGLS(poOpenInfo))
1577 : {
1578 0 : return FALSE;
1579 : }
1580 : #endif
1581 :
1582 75 : return TRUE;
1583 : }
1584 :
1585 : /************************************************************************/
1586 : /* Open() */
1587 : /************************************************************************/
1588 :
1589 3790 : GDALDataset *JPGDatasetCommon::Open( GDALOpenInfo * poOpenInfo )
1590 :
1591 : {
1592 3790 : if( !Identify( poOpenInfo ) )
1593 3647 : return NULL;
1594 :
1595 143 : if( poOpenInfo->eAccess == GA_Update )
1596 : {
1597 : CPLError( CE_Failure, CPLE_NotSupported,
1598 : "The JPEG driver does not support update access to existing"
1599 0 : " datasets.\n" );
1600 0 : return NULL;
1601 : }
1602 :
1603 143 : return JPGDataset::Open(poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles);
1604 : }
1605 :
1606 : #endif // !defined(JPGDataset)
1607 :
1608 : /************************************************************************/
1609 : /* Open() */
1610 : /************************************************************************/
1611 :
1612 204 : GDALDataset *JPGDataset::Open( const char* pszFilename, char** papszSiblingFiles,
1613 : int nScaleFactor, VSILFILE* fpIn )
1614 :
1615 : {
1616 : /* -------------------------------------------------------------------- */
1617 : /* If it is a subfile, read the JPEG header. */
1618 : /* -------------------------------------------------------------------- */
1619 204 : int bIsSubfile = FALSE;
1620 204 : GUIntBig subfile_offset = 0;
1621 204 : GUIntBig subfile_size = 0;
1622 204 : const char *real_filename = pszFilename;
1623 204 : int nQLevel = -1;
1624 :
1625 204 : if( EQUALN(pszFilename,"JPEG_SUBFILE:",13) )
1626 : {
1627 : char** papszTokens;
1628 79 : int bScan = FALSE;
1629 :
1630 79 : if( EQUALN(pszFilename,"JPEG_SUBFILE:Q",14) )
1631 : {
1632 79 : papszTokens = CSLTokenizeString2(pszFilename + 14, ",", 0);
1633 79 : if (CSLCount(papszTokens) >= 3)
1634 : {
1635 79 : nQLevel = atoi(papszTokens[0]);
1636 79 : subfile_offset = CPLScanUIntBig(papszTokens[1], strlen(papszTokens[1]));
1637 79 : subfile_size = CPLScanUIntBig(papszTokens[2], strlen(papszTokens[2]));
1638 79 : bScan = TRUE;
1639 : }
1640 79 : CSLDestroy(papszTokens);
1641 : }
1642 : else
1643 : {
1644 0 : papszTokens = CSLTokenizeString2(pszFilename + 13, ",", 0);
1645 0 : if (CSLCount(papszTokens) >= 2)
1646 : {
1647 0 : subfile_offset = CPLScanUIntBig(papszTokens[0], strlen(papszTokens[0]));
1648 0 : subfile_size = CPLScanUIntBig(papszTokens[1], strlen(papszTokens[1]));
1649 0 : bScan = TRUE;
1650 : }
1651 0 : CSLDestroy(papszTokens);
1652 : }
1653 :
1654 79 : if( !bScan )
1655 : {
1656 : CPLError( CE_Failure, CPLE_OpenFailed,
1657 : "Corrupt subfile definition: %s",
1658 0 : pszFilename );
1659 0 : return NULL;
1660 : }
1661 :
1662 79 : real_filename = strstr(pszFilename,",");
1663 79 : if( real_filename != NULL )
1664 79 : real_filename = strstr(real_filename+1,",");
1665 79 : if( real_filename != NULL && nQLevel != -1 )
1666 79 : real_filename = strstr(real_filename+1,",");
1667 79 : if( real_filename != NULL )
1668 79 : real_filename++;
1669 : else
1670 : {
1671 : CPLError( CE_Failure, CPLE_OpenFailed,
1672 0 : "Could not find filename in subfile definition.");
1673 0 : return NULL;
1674 : }
1675 :
1676 : CPLDebug( "JPG",
1677 : "real_filename %s, offset=" CPL_FRMT_GUIB ", size=" CPL_FRMT_GUIB "\n",
1678 79 : real_filename, subfile_offset, subfile_size);
1679 :
1680 79 : bIsSubfile = TRUE;
1681 : }
1682 :
1683 : /* -------------------------------------------------------------------- */
1684 : /* Open the file using the large file api. */
1685 : /* -------------------------------------------------------------------- */
1686 : VSILFILE* fpImage;
1687 :
1688 204 : if( fpIn == NULL )
1689 : {
1690 204 : fpImage = VSIFOpenL( real_filename, "rb" );
1691 :
1692 204 : if( fpImage == NULL )
1693 : {
1694 : CPLError( CE_Failure, CPLE_OpenFailed,
1695 : "VSIFOpenL(%s) failed unexpectedly in jpgdataset.cpp",
1696 2 : real_filename );
1697 2 : return NULL;
1698 : }
1699 : }
1700 : else
1701 0 : fpImage = fpIn;
1702 :
1703 : /* -------------------------------------------------------------------- */
1704 : /* Create a corresponding GDALDataset. */
1705 : /* -------------------------------------------------------------------- */
1706 : JPGDataset *poDS;
1707 :
1708 202 : poDS = new JPGDataset();
1709 202 : poDS->nQLevel = nQLevel;
1710 202 : poDS->fpImage = fpImage;
1711 202 : poDS->bOwnFPImage = (fpIn == NULL);
1712 :
1713 : /* -------------------------------------------------------------------- */
1714 : /* Move to the start of jpeg data. */
1715 : /* -------------------------------------------------------------------- */
1716 202 : poDS->nSubfileOffset = subfile_offset;
1717 202 : VSIFSeekL( poDS->fpImage, poDS->nSubfileOffset, SEEK_SET );
1718 :
1719 202 : poDS->eAccess = GA_ReadOnly;
1720 :
1721 : /* Will detect mismatch between compile-time and run-time libjpeg versions */
1722 202 : if (setjmp(poDS->setjmp_buffer))
1723 : {
1724 0 : delete poDS;
1725 0 : return NULL;
1726 : }
1727 :
1728 202 : poDS->sDInfo.err = jpeg_std_error( &(poDS->sJErr) );
1729 202 : poDS->sJErr.error_exit = JPGDataset::ErrorExit;
1730 202 : poDS->sDInfo.client_data = (void *) &(poDS->setjmp_buffer);
1731 :
1732 202 : jpeg_create_decompress( &(poDS->sDInfo) );
1733 202 : poDS->bHasDoneJpegCreateDecompress = TRUE;
1734 :
1735 : /* This is to address bug related in ticket #1795 */
1736 202 : if (CPLGetConfigOption("JPEGMEM", NULL) == NULL)
1737 : {
1738 : /* If the user doesn't provide a value for JPEGMEM, we want to be sure */
1739 : /* that at least 500 MB will be used before creating the temporary file */
1740 : poDS->sDInfo.mem->max_memory_to_use =
1741 202 : MAX(poDS->sDInfo.mem->max_memory_to_use, 500 * 1024 * 1024);
1742 : }
1743 :
1744 : /* -------------------------------------------------------------------- */
1745 : /* Preload default NITF JPEG quantization tables. */
1746 : /* -------------------------------------------------------------------- */
1747 202 : poDS->LoadDefaultTables( 0 );
1748 202 : poDS->LoadDefaultTables( 1 );
1749 202 : poDS->LoadDefaultTables( 2 );
1750 202 : poDS->LoadDefaultTables( 3 );
1751 :
1752 : /* -------------------------------------------------------------------- */
1753 : /* If a fatal error occurs after this, we will return NULL */
1754 : /* -------------------------------------------------------------------- */
1755 202 : if (setjmp(poDS->setjmp_buffer))
1756 : {
1757 : #if defined(JPEG_DUAL_MODE_8_12) && !defined(JPGDataset)
1758 18 : if (poDS->sDInfo.data_precision == 12)
1759 : {
1760 17 : delete poDS;
1761 : return JPEGDataset12Open(pszFilename, papszSiblingFiles,
1762 17 : nScaleFactor);
1763 : }
1764 : #endif
1765 1 : delete poDS;
1766 1 : return NULL;
1767 : }
1768 :
1769 : /* -------------------------------------------------------------------- */
1770 : /* Read pre-image data after ensuring the file is rewound. */
1771 : /* -------------------------------------------------------------------- */
1772 202 : VSIFSeekL( poDS->fpImage, poDS->nSubfileOffset, SEEK_SET );
1773 :
1774 202 : jpeg_vsiio_src( &(poDS->sDInfo), poDS->fpImage );
1775 202 : jpeg_read_header( &(poDS->sDInfo), TRUE );
1776 :
1777 184 : if( poDS->sDInfo.data_precision != 8
1778 : && poDS->sDInfo.data_precision != 12 )
1779 : {
1780 : CPLError( CE_Failure, CPLE_NotSupported,
1781 : "GDAL JPEG Driver doesn't support files with precision of"
1782 0 : " other than 8 or 12 bits." );
1783 0 : delete poDS;
1784 0 : return NULL;
1785 : }
1786 :
1787 : /* -------------------------------------------------------------------- */
1788 : /* Capture some information from the file that is of interest. */
1789 : /* -------------------------------------------------------------------- */
1790 :
1791 184 : poDS->nScaleFactor = nScaleFactor;
1792 184 : poDS->SetScaleNumAndDenom();
1793 184 : poDS->nRasterXSize = (poDS->sDInfo.image_width + nScaleFactor - 1) / nScaleFactor;
1794 184 : poDS->nRasterYSize = (poDS->sDInfo.image_height + nScaleFactor - 1) / nScaleFactor;
1795 :
1796 184 : poDS->sDInfo.out_color_space = poDS->sDInfo.jpeg_color_space;
1797 184 : poDS->eGDALColorSpace = poDS->sDInfo.jpeg_color_space;
1798 :
1799 184 : if( poDS->sDInfo.jpeg_color_space == JCS_GRAYSCALE )
1800 : {
1801 119 : poDS->nBands = 1;
1802 : }
1803 65 : else if( poDS->sDInfo.jpeg_color_space == JCS_RGB )
1804 : {
1805 2 : poDS->nBands = 3;
1806 : }
1807 63 : else if( poDS->sDInfo.jpeg_color_space == JCS_YCbCr )
1808 : {
1809 60 : poDS->nBands = 3;
1810 60 : if (CSLTestBoolean(CPLGetConfigOption("GDAL_JPEG_TO_RGB", "YES")))
1811 : {
1812 60 : poDS->sDInfo.out_color_space = JCS_RGB;
1813 60 : poDS->eGDALColorSpace = JCS_RGB;
1814 60 : poDS->SetMetadataItem( "SOURCE_COLOR_SPACE", "YCbCr", "IMAGE_STRUCTURE" );
1815 : }
1816 : }
1817 3 : else if( poDS->sDInfo.jpeg_color_space == JCS_CMYK )
1818 : {
1819 3 : if (CSLTestBoolean(CPLGetConfigOption("GDAL_JPEG_TO_RGB", "YES")))
1820 : {
1821 2 : poDS->eGDALColorSpace = JCS_RGB;
1822 2 : poDS->nBands = 3;
1823 2 : poDS->SetMetadataItem( "SOURCE_COLOR_SPACE", "CMYK", "IMAGE_STRUCTURE" );
1824 : }
1825 : else
1826 : {
1827 1 : poDS->nBands = 4;
1828 : }
1829 : }
1830 0 : else if( poDS->sDInfo.jpeg_color_space == JCS_YCCK )
1831 : {
1832 0 : if (CSLTestBoolean(CPLGetConfigOption("GDAL_JPEG_TO_RGB", "YES")))
1833 : {
1834 0 : poDS->eGDALColorSpace = JCS_RGB;
1835 0 : poDS->nBands = 3;
1836 0 : poDS->SetMetadataItem( "SOURCE_COLOR_SPACE", "YCbCrK", "IMAGE_STRUCTURE" );
1837 : }
1838 : else
1839 : {
1840 0 : poDS->nBands = 4;
1841 : }
1842 : /* libjpeg does the translation from YCrCbK -> CMYK internally */
1843 : /* and we'll do the translation to RGB in IReadBlock() */
1844 0 : poDS->sDInfo.out_color_space = JCS_CMYK;
1845 : }
1846 : else
1847 : {
1848 : CPLError( CE_Failure, CPLE_NotSupported,
1849 : "Unrecognised jpeg_color_space value of %d.\n",
1850 0 : poDS->sDInfo.jpeg_color_space );
1851 0 : delete poDS;
1852 0 : return NULL;
1853 : }
1854 :
1855 : /* -------------------------------------------------------------------- */
1856 : /* Create band information objects. */
1857 : /* -------------------------------------------------------------------- */
1858 499 : for( int iBand = 0; iBand < poDS->nBands; iBand++ )
1859 315 : poDS->SetBand( iBand+1, JPGCreateBand( poDS, iBand+1 ) );
1860 :
1861 : /* -------------------------------------------------------------------- */
1862 : /* More metadata. */
1863 : /* -------------------------------------------------------------------- */
1864 184 : if( poDS->nBands > 1 )
1865 : {
1866 65 : poDS->SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" );
1867 65 : poDS->SetMetadataItem( "COMPRESSION", "JPEG", "IMAGE_STRUCTURE" );
1868 : }
1869 :
1870 : /* -------------------------------------------------------------------- */
1871 : /* Initialize any PAM information. */
1872 : /* -------------------------------------------------------------------- */
1873 184 : poDS->SetDescription( pszFilename );
1874 :
1875 184 : if( nScaleFactor == 1 )
1876 : {
1877 177 : if( !bIsSubfile )
1878 109 : poDS->TryLoadXML( papszSiblingFiles );
1879 : else
1880 68 : poDS->nPamFlags |= GPF_NOSAVE;
1881 :
1882 : /* -------------------------------------------------------------------- */
1883 : /* Open (external) overviews. */
1884 : /* -------------------------------------------------------------------- */
1885 177 : poDS->oOvManager.Initialize( poDS, real_filename, papszSiblingFiles );
1886 : }
1887 : else
1888 7 : poDS->nPamFlags |= GPF_NOSAVE;
1889 :
1890 184 : poDS->bIsSubfile = bIsSubfile;
1891 :
1892 184 : return poDS;
1893 : }
1894 :
1895 : #if !defined(JPGDataset)
1896 :
1897 : /************************************************************************/
1898 : /* LoadWorldFileOrTab() */
1899 : /************************************************************************/
1900 :
1901 57 : void JPGDatasetCommon::LoadWorldFileOrTab()
1902 : {
1903 57 : if (bIsSubfile)
1904 0 : return;
1905 57 : if (bHasTriedLoadWorldFileOrTab)
1906 29 : return;
1907 28 : bHasTriedLoadWorldFileOrTab = TRUE;
1908 :
1909 28 : char* pszWldFilename = NULL;
1910 :
1911 : /* TIROS3 JPEG files have a .wld extension, so don't look for .wld as */
1912 : /* as worldfile ! */
1913 28 : int bEndsWithWld = strlen(GetDescription()) > 4 &&
1914 56 : EQUAL( GetDescription() + strlen(GetDescription()) - 4, ".wld");
1915 : bGeoTransformValid =
1916 28 : GDALReadWorldFile2( GetDescription(), NULL,
1917 : adfGeoTransform,
1918 : oOvManager.GetSiblingFiles(), &pszWldFilename )
1919 28 : || GDALReadWorldFile2( GetDescription(), ".jpw",
1920 : adfGeoTransform,
1921 : oOvManager.GetSiblingFiles(), &pszWldFilename )
1922 28 : || ( !bEndsWithWld && GDALReadWorldFile2( GetDescription(), ".wld",
1923 : adfGeoTransform,
1924 112 : oOvManager.GetSiblingFiles(), &pszWldFilename ));
1925 :
1926 28 : if( !bGeoTransformValid )
1927 : {
1928 : int bTabFileOK =
1929 24 : GDALReadTabFile2( GetDescription(), adfGeoTransform,
1930 : &pszProjection,
1931 : &nGCPCount, &pasGCPList,
1932 48 : oOvManager.GetSiblingFiles(), &pszWldFilename );
1933 :
1934 24 : if( bTabFileOK && nGCPCount == 0 )
1935 0 : bGeoTransformValid = TRUE;
1936 : }
1937 :
1938 28 : if (pszWldFilename)
1939 : {
1940 4 : osWldFilename = pszWldFilename;
1941 4 : CPLFree(pszWldFilename);
1942 : }
1943 : }
1944 :
1945 : /************************************************************************/
1946 : /* GetFileList() */
1947 : /************************************************************************/
1948 :
1949 6 : char **JPGDatasetCommon::GetFileList()
1950 :
1951 : {
1952 6 : char **papszFileList = GDALPamDataset::GetFileList();
1953 :
1954 6 : LoadWorldFileOrTab();
1955 :
1956 6 : if (osWldFilename.size() != 0 &&
1957 : CSLFindString(papszFileList, osWldFilename) == -1)
1958 : {
1959 2 : papszFileList = CSLAddString( papszFileList, osWldFilename );
1960 : }
1961 :
1962 6 : return papszFileList;
1963 : }
1964 :
1965 : /************************************************************************/
1966 : /* CheckForMask() */
1967 : /************************************************************************/
1968 :
1969 18 : void JPGDatasetCommon::CheckForMask()
1970 :
1971 : {
1972 : GIntBig nFileSize;
1973 : GUInt32 nImageSize;
1974 :
1975 : /* Save current position to avoid disturbing JPEG stream decoding */
1976 18 : vsi_l_offset nCurOffset = VSIFTellL(fpImage);
1977 :
1978 : /* -------------------------------------------------------------------- */
1979 : /* Go to the end of the file, pull off four bytes, and see if */
1980 : /* it is plausibly the size of the real image data. */
1981 : /* -------------------------------------------------------------------- */
1982 18 : VSIFSeekL( fpImage, 0, SEEK_END );
1983 18 : nFileSize = VSIFTellL( fpImage );
1984 18 : VSIFSeekL( fpImage, nFileSize - 4, SEEK_SET );
1985 :
1986 18 : VSIFReadL( &nImageSize, 4, 1, fpImage );
1987 : CPL_LSBPTR32( &nImageSize );
1988 :
1989 18 : if( nImageSize < nFileSize / 2 || nImageSize > nFileSize - 4 )
1990 : goto end;
1991 :
1992 : /* -------------------------------------------------------------------- */
1993 : /* If that seems ok, seek back, and verify that just preceeding */
1994 : /* the bitmask is an apparent end-of-jpeg-data marker. */
1995 : /* -------------------------------------------------------------------- */
1996 : GByte abyEOD[2];
1997 :
1998 4 : VSIFSeekL( fpImage, nImageSize - 2, SEEK_SET );
1999 4 : VSIFReadL( abyEOD, 2, 1, fpImage );
2000 4 : if( abyEOD[0] != 0xff || abyEOD[1] != 0xd9 )
2001 : goto end;
2002 :
2003 : /* -------------------------------------------------------------------- */
2004 : /* We seem to have a mask. Read it in. */
2005 : /* -------------------------------------------------------------------- */
2006 4 : nCMaskSize = (int) (nFileSize - nImageSize - 4);
2007 4 : pabyCMask = (GByte *) VSIMalloc(nCMaskSize);
2008 4 : if (pabyCMask == NULL)
2009 : {
2010 : CPLError(CE_Failure, CPLE_OutOfMemory,
2011 : "Cannot allocate memory (%d bytes) for mask compressed buffer",
2012 0 : nCMaskSize);
2013 0 : goto end;
2014 : }
2015 4 : VSIFReadL( pabyCMask, nCMaskSize, 1, fpImage );
2016 :
2017 : CPLDebug( "JPEG", "Got %d byte compressed bitmask.",
2018 4 : nCMaskSize );
2019 :
2020 : end:
2021 18 : VSIFSeekL( fpImage, nCurOffset, SEEK_SET );
2022 18 : }
2023 :
2024 : /************************************************************************/
2025 : /* DecompressMask() */
2026 : /************************************************************************/
2027 :
2028 2048 : void JPGDatasetCommon::DecompressMask()
2029 :
2030 : {
2031 2048 : if( pabyCMask == NULL || pabyBitMask != NULL )
2032 2044 : return;
2033 :
2034 : /* -------------------------------------------------------------------- */
2035 : /* Allocate 1bit buffer - may be slightly larger than needed. */
2036 : /* -------------------------------------------------------------------- */
2037 4 : int nBufSize = nRasterYSize * ((nRasterXSize+7)/8);
2038 4 : pabyBitMask = (GByte *) VSIMalloc( nBufSize );
2039 4 : if (pabyBitMask == NULL)
2040 : {
2041 : CPLError(CE_Failure, CPLE_OutOfMemory,
2042 : "Cannot allocate memory (%d bytes) for mask uncompressed buffer",
2043 0 : nBufSize);
2044 0 : CPLFree(pabyCMask);
2045 0 : pabyCMask = NULL;
2046 0 : return;
2047 : }
2048 :
2049 : /* -------------------------------------------------------------------- */
2050 : /* Decompress */
2051 : /* -------------------------------------------------------------------- */
2052 : void* pOut = CPLZLibInflate( pabyCMask, nCMaskSize,
2053 4 : pabyBitMask, nBufSize, NULL );
2054 : /* -------------------------------------------------------------------- */
2055 : /* Cleanup if an error occurs. */
2056 : /* -------------------------------------------------------------------- */
2057 4 : if( pOut == NULL )
2058 : {
2059 : CPLError( CE_Failure, CPLE_AppDefined,
2060 0 : "Failure decoding JPEG validity bitmask." );
2061 0 : CPLFree( pabyCMask );
2062 0 : pabyCMask = NULL;
2063 :
2064 0 : CPLFree( pabyBitMask );
2065 0 : pabyBitMask = NULL;
2066 : }
2067 : }
2068 :
2069 : #endif // !defined(JPGDataset)
2070 :
2071 : /************************************************************************/
2072 : /* ErrorExit() */
2073 : /************************************************************************/
2074 :
2075 19 : void JPGDataset::ErrorExit(j_common_ptr cinfo)
2076 : {
2077 19 : jmp_buf *setjmp_buffer = (jmp_buf *) cinfo->client_data;
2078 : char buffer[JMSG_LENGTH_MAX];
2079 :
2080 : /* Create the message */
2081 19 : (*cinfo->err->format_message) (cinfo, buffer);
2082 :
2083 : /* Avoid error for a 12bit JPEG if reading from the 8bit JPEG driver and */
2084 : /* we have JPEG_DUAL_MODE_8_12 support, as we'll try again with 12bit JPEG */
2085 : /* driver */
2086 : #if defined(JPEG_DUAL_MODE_8_12) && !defined(JPGDataset)
2087 19 : if (strstr(buffer, "Unsupported JPEG data precision 12") == NULL)
2088 : #endif
2089 : CPLError( CE_Failure, CPLE_AppDefined,
2090 2 : "libjpeg: %s", buffer );
2091 :
2092 : /* Return control to the setjmp point */
2093 19 : longjmp(*setjmp_buffer, 1);
2094 : }
2095 :
2096 : #if !defined(JPGDataset)
2097 :
2098 : /************************************************************************/
2099 : /* JPGAppendMask() */
2100 : /* */
2101 : /* This function appends a zlib compressed bitmask to a JPEG */
2102 : /* file (or really any file) pulled from an existing mask band. */
2103 : /************************************************************************/
2104 :
2105 : // MSVC does not know that memset() has initialized sStream.
2106 : #ifdef _MSC_VER
2107 : # pragma warning(disable:4701)
2108 : #endif
2109 :
2110 2 : CPLErr JPGAppendMask( const char *pszJPGFilename, GDALRasterBand *poMask,
2111 : GDALProgressFunc pfnProgress, void * pProgressData )
2112 :
2113 : {
2114 2 : int nXSize = poMask->GetXSize();
2115 2 : int nYSize = poMask->GetYSize();
2116 2 : int nBitBufSize = nYSize * ((nXSize+7)/8);
2117 : int iX, iY;
2118 : GByte *pabyBitBuf, *pabyMaskLine;
2119 2 : CPLErr eErr = CE_None;
2120 :
2121 : /* -------------------------------------------------------------------- */
2122 : /* Allocate uncompressed bit buffer. */
2123 : /* -------------------------------------------------------------------- */
2124 2 : pabyBitBuf = (GByte *) VSICalloc(1,nBitBufSize);
2125 :
2126 2 : pabyMaskLine = (GByte *) VSIMalloc(nXSize);
2127 2 : if (pabyBitBuf == NULL || pabyMaskLine == NULL)
2128 : {
2129 0 : CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
2130 0 : eErr = CE_Failure;
2131 : }
2132 :
2133 : /* -------------------------------------------------------------------- */
2134 : /* Set bit buffer from mask band, scanline by scanline. */
2135 : /* -------------------------------------------------------------------- */
2136 2 : GUInt32 iBit = 0;
2137 524 : for( iY = 0; eErr == CE_None && iY < nYSize; iY++ )
2138 : {
2139 : eErr = poMask->RasterIO( GF_Read, 0, iY, nXSize, 1,
2140 522 : pabyMaskLine, nXSize, 1, GDT_Byte, 0, 0 );
2141 522 : if( eErr != CE_None )
2142 0 : break;
2143 :
2144 262766 : for( iX = 0; iX < nXSize; iX++ )
2145 : {
2146 262244 : if( pabyMaskLine[iX] != 0 )
2147 197632 : pabyBitBuf[iBit>>3] |= (0x1 << (iBit&7));
2148 :
2149 262244 : iBit++;
2150 : }
2151 :
2152 522 : if( eErr == CE_None
2153 : && !pfnProgress( (iY + 1) / (double) nYSize, NULL, pProgressData ) )
2154 : {
2155 0 : eErr = CE_Failure;
2156 : CPLError( CE_Failure, CPLE_UserInterrupt,
2157 0 : "User terminated JPGAppendMask()" );
2158 : }
2159 : }
2160 :
2161 2 : CPLFree( pabyMaskLine );
2162 :
2163 : /* -------------------------------------------------------------------- */
2164 : /* Compress */
2165 : /* -------------------------------------------------------------------- */
2166 2 : GByte *pabyCMask = NULL;
2167 :
2168 2 : if( eErr == CE_None )
2169 : {
2170 2 : pabyCMask = (GByte *) VSIMalloc(nBitBufSize + 30);
2171 2 : if (pabyCMask == NULL)
2172 : {
2173 0 : CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
2174 0 : eErr = CE_Failure;
2175 : }
2176 : }
2177 :
2178 2 : size_t nTotalOut = 0;
2179 2 : if ( eErr == CE_None )
2180 : {
2181 2 : if( CPLZLibDeflate( pabyBitBuf, nBitBufSize, 9,
2182 : pabyCMask, nBitBufSize + 30,
2183 : &nTotalOut ) == NULL )
2184 : {
2185 : CPLError( CE_Failure, CPLE_AppDefined,
2186 0 : "Deflate compression of jpeg bit mask failed." );
2187 0 : eErr = CE_Failure;
2188 : }
2189 : }
2190 :
2191 : /* -------------------------------------------------------------------- */
2192 : /* Write to disk, along with image file size. */
2193 : /* -------------------------------------------------------------------- */
2194 2 : if( eErr == CE_None )
2195 : {
2196 : VSILFILE *fpOut;
2197 : GUInt32 nImageSize;
2198 :
2199 2 : fpOut = VSIFOpenL( pszJPGFilename, "r+" );
2200 2 : if( fpOut == NULL )
2201 : {
2202 : CPLError( CE_Failure, CPLE_AppDefined,
2203 0 : "Failed to open jpeg to append bitmask." );
2204 0 : eErr = CE_Failure;
2205 : }
2206 : else
2207 : {
2208 2 : VSIFSeekL( fpOut, 0, SEEK_END );
2209 :
2210 2 : nImageSize = (GUInt32) VSIFTellL( fpOut );
2211 : CPL_LSBPTR32( &nImageSize );
2212 :
2213 2 : if( VSIFWriteL( pabyCMask, 1, nTotalOut, fpOut )
2214 : != nTotalOut )
2215 : {
2216 : CPLError( CE_Failure, CPLE_FileIO,
2217 : "Failure writing compressed bitmask.\n%s",
2218 0 : VSIStrerror( errno ) );
2219 0 : eErr = CE_Failure;
2220 : }
2221 : else
2222 2 : VSIFWriteL( &nImageSize, 4, 1, fpOut );
2223 :
2224 2 : VSIFCloseL( fpOut );
2225 : }
2226 : }
2227 :
2228 2 : CPLFree( pabyBitBuf );
2229 2 : CPLFree( pabyCMask );
2230 :
2231 2 : return eErr;
2232 : }
2233 :
2234 : #endif // !defined(JPGDataset)
2235 :
2236 : /************************************************************************/
2237 : /* CreateCopy() */
2238 : /************************************************************************/
2239 :
2240 : GDALDataset *
2241 60 : JPGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
2242 : int bStrict, char ** papszOptions,
2243 : GDALProgressFunc pfnProgress, void * pProgressData )
2244 :
2245 : {
2246 60 : int nBands = poSrcDS->GetRasterCount();
2247 60 : int nXSize = poSrcDS->GetRasterXSize();
2248 60 : int nYSize = poSrcDS->GetRasterYSize();
2249 60 : int nQuality = 75;
2250 60 : int bProgressive = FALSE;
2251 60 : int nCloneFlags = GCIF_PAM_DEFAULT;
2252 : const char* pszVal;
2253 :
2254 60 : if( !pfnProgress( 0.0, NULL, pProgressData ) )
2255 0 : return NULL;
2256 :
2257 : /* -------------------------------------------------------------------- */
2258 : /* Some some rudimentary checks */
2259 : /* -------------------------------------------------------------------- */
2260 60 : if( nBands != 1 && nBands != 3 && nBands != 4 )
2261 : {
2262 : CPLError( CE_Failure, CPLE_NotSupported,
2263 : "JPEG driver doesn't support %d bands. Must be 1 (grey), "
2264 3 : "3 (RGB) or 4 bands.\n", nBands );
2265 :
2266 3 : return NULL;
2267 : }
2268 :
2269 104 : if (nBands == 1 &&
2270 47 : poSrcDS->GetRasterBand(1)->GetColorTable() != NULL)
2271 : {
2272 : CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported,
2273 : "JPEG driver ignores color table. "
2274 : "The source raster band will be considered as grey level.\n"
2275 0 : "Consider using color table expansion (-expand option in gdal_translate)\n");
2276 0 : if (bStrict)
2277 0 : return NULL;
2278 : }
2279 :
2280 57 : GDALDataType eDT = poSrcDS->GetRasterBand(1)->GetRasterDataType();
2281 :
2282 : #if defined(JPEG_LIB_MK1_OR_12BIT) || defined(JPEG_DUAL_MODE_8_12)
2283 57 : if( eDT != GDT_Byte && eDT != GDT_UInt16 )
2284 : {
2285 : CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported,
2286 : "JPEG driver doesn't support data type %s. "
2287 : "Only eight and twelve bit bands supported (Mk1 libjpeg).\n",
2288 : GDALGetDataTypeName(
2289 9 : poSrcDS->GetRasterBand(1)->GetRasterDataType()) );
2290 :
2291 9 : if (bStrict)
2292 9 : return NULL;
2293 : }
2294 :
2295 52 : if( eDT == GDT_UInt16 || eDT == GDT_Int16 )
2296 : {
2297 : #if defined(JPEG_DUAL_MODE_8_12) && !defined(JPGDataset)
2298 : return JPEGDataset12CreateCopy(pszFilename, poSrcDS,
2299 : bStrict, papszOptions,
2300 4 : pfnProgress, pProgressData );
2301 : #else
2302 4 : eDT = GDT_UInt16;
2303 : #endif
2304 : }
2305 : else
2306 40 : eDT = GDT_Byte;
2307 :
2308 : #else
2309 : if( eDT != GDT_Byte )
2310 : {
2311 : CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported,
2312 : "JPEG driver doesn't support data type %s. "
2313 : "Only eight bit byte bands supported.\n",
2314 : GDALGetDataTypeName(
2315 : poSrcDS->GetRasterBand(1)->GetRasterDataType()) );
2316 :
2317 : if (bStrict)
2318 : return NULL;
2319 : }
2320 :
2321 : eDT = GDT_Byte; // force to 8bit.
2322 : #endif
2323 :
2324 : /* -------------------------------------------------------------------- */
2325 : /* What options has the user selected? */
2326 : /* -------------------------------------------------------------------- */
2327 44 : if( CSLFetchNameValue(papszOptions,"QUALITY") != NULL )
2328 : {
2329 3 : nQuality = atoi(CSLFetchNameValue(papszOptions,"QUALITY"));
2330 3 : if( nQuality < 10 || nQuality > 100 )
2331 : {
2332 : CPLError( CE_Failure, CPLE_IllegalArg,
2333 : "QUALITY=%s is not a legal value in the range 10-100.",
2334 0 : CSLFetchNameValue(papszOptions,"QUALITY") );
2335 0 : return NULL;
2336 : }
2337 : }
2338 :
2339 44 : bProgressive = CSLFetchBoolean( papszOptions, "PROGRESSIVE", FALSE );
2340 :
2341 : /* -------------------------------------------------------------------- */
2342 : /* Create the dataset. */
2343 : /* -------------------------------------------------------------------- */
2344 : VSILFILE *fpImage;
2345 :
2346 44 : fpImage = VSIFOpenL( pszFilename, "wb" );
2347 44 : if( fpImage == NULL )
2348 : {
2349 : CPLError( CE_Failure, CPLE_OpenFailed,
2350 : "Unable to create jpeg file %s.\n",
2351 6 : pszFilename );
2352 6 : return NULL;
2353 : }
2354 :
2355 : /* -------------------------------------------------------------------- */
2356 : /* Initialize JPG access to the file. */
2357 : /* -------------------------------------------------------------------- */
2358 : struct jpeg_compress_struct sCInfo;
2359 : struct jpeg_error_mgr sJErr;
2360 : jmp_buf setjmp_buffer;
2361 :
2362 38 : if (setjmp(setjmp_buffer))
2363 : {
2364 0 : VSIFCloseL( fpImage );
2365 0 : return NULL;
2366 : }
2367 :
2368 38 : sCInfo.err = jpeg_std_error( &sJErr );
2369 38 : sJErr.error_exit = JPGDataset::ErrorExit;
2370 38 : sCInfo.client_data = (void *) &(setjmp_buffer);
2371 :
2372 38 : jpeg_create_compress( &sCInfo );
2373 :
2374 38 : jpeg_vsiio_dest( &sCInfo, fpImage );
2375 :
2376 38 : sCInfo.image_width = nXSize;
2377 38 : sCInfo.image_height = nYSize;
2378 38 : sCInfo.input_components = nBands;
2379 :
2380 38 : if( nBands == 3 )
2381 7 : sCInfo.in_color_space = JCS_RGB;
2382 31 : else if( nBands == 1 )
2383 30 : sCInfo.in_color_space = JCS_GRAYSCALE;
2384 : else
2385 1 : sCInfo.in_color_space = JCS_UNKNOWN;
2386 :
2387 38 : jpeg_set_defaults( &sCInfo );
2388 :
2389 38 : if( eDT == GDT_UInt16 )
2390 : {
2391 3 : sCInfo.data_precision = 12;
2392 : }
2393 : else
2394 : {
2395 35 : sCInfo.data_precision = 8;
2396 : }
2397 :
2398 38 : pszVal = CSLFetchNameValue(papszOptions, "ARITHMETIC");
2399 38 : if( pszVal )
2400 0 : sCInfo.arith_code = CSLTestBoolean(pszVal);
2401 :
2402 : #if JPEG_LIB_VERSION_MAJOR >= 8 && \
2403 : (JPEG_LIB_VERSION_MAJOR > 8 || JPEG_LIB_VERSION_MINOR >= 3)
2404 : pszVal = CSLFetchNameValue(papszOptions, "BLOCK");
2405 : if( pszVal )
2406 : sCInfo.block_size = atoi(pszVal);
2407 : #endif
2408 :
2409 : #if JPEG_LIB_VERSION_MAJOR >= 9
2410 : pszVal = CSLFetchNameValue(papszOptions, "COLOR_TRANSFORM");
2411 : if( pszVal )
2412 : {
2413 : sCInfo.color_transform = EQUAL(pszVal, "RGB1") ? JCT_SUBTRACT_GREEN : JCT_NONE;
2414 : jpeg_set_colorspace(&sCInfo, JCS_RGB);
2415 : }
2416 : else
2417 : #endif
2418 :
2419 : /* Mostly for debugging purposes */
2420 38 : if( nBands == 3 && CSLTestBoolean(CPLGetConfigOption("JPEG_WRITE_RGB", "NO")) )
2421 : {
2422 0 : jpeg_set_colorspace(&sCInfo, JCS_RGB);
2423 : }
2424 :
2425 : GDALDataType eWorkDT;
2426 : #ifdef JPEG_LIB_MK1
2427 : sCInfo.bits_in_jsample = sCInfo.data_precision;
2428 : eWorkDT = GDT_UInt16; /* Always force to 16 bit for JPEG_LIB_MK1 */
2429 : #else
2430 38 : eWorkDT = eDT;
2431 : #endif
2432 :
2433 38 : jpeg_set_quality( &sCInfo, nQuality, TRUE );
2434 :
2435 38 : if( bProgressive )
2436 2 : jpeg_simple_progression( &sCInfo );
2437 :
2438 38 : jpeg_start_compress( &sCInfo, TRUE );
2439 :
2440 : /* -------------------------------------------------------------------- */
2441 : /* Does the source have a mask? If so, we will append it to the */
2442 : /* jpeg file after the imagery. */
2443 : /* -------------------------------------------------------------------- */
2444 38 : int nMaskFlags = poSrcDS->GetRasterBand(1)->GetMaskFlags();
2445 : int bAppendMask =( !(nMaskFlags & GMF_ALL_VALID)
2446 38 : && (nBands == 1 || (nMaskFlags & GMF_PER_DATASET)) );
2447 :
2448 38 : bAppendMask &= CSLFetchBoolean( papszOptions, "INTERNAL_MASK", TRUE );
2449 :
2450 : /* -------------------------------------------------------------------- */
2451 : /* Loop over image, copying image data. */
2452 : /* -------------------------------------------------------------------- */
2453 : GByte *pabyScanline;
2454 38 : CPLErr eErr = CE_None;
2455 38 : int nWorkDTSize = GDALGetDataTypeSize(eWorkDT) / 8;
2456 38 : bool bClipWarn = false;
2457 :
2458 38 : pabyScanline = (GByte *) CPLMalloc( nBands * nXSize * nWorkDTSize );
2459 :
2460 4817 : for( int iLine = 0; iLine < nYSize && eErr == CE_None; iLine++ )
2461 : {
2462 : JSAMPLE *ppSamples;
2463 :
2464 : eErr = poSrcDS->RasterIO( GF_Read, 0, iLine, nXSize, 1,
2465 : pabyScanline, nXSize, 1, eWorkDT,
2466 : nBands, NULL,
2467 : nBands*nWorkDTSize,
2468 4779 : nBands * nXSize * nWorkDTSize, nWorkDTSize );
2469 :
2470 : // clamp 16bit values to 12bit.
2471 4779 : if( nWorkDTSize == 2 )
2472 : {
2473 110 : GUInt16 *panScanline = (GUInt16 *) pabyScanline;
2474 : int iPixel;
2475 :
2476 5210 : for( iPixel = 0; iPixel < nXSize*nBands; iPixel++ )
2477 : {
2478 5100 : if( panScanline[iPixel] > 4095 )
2479 : {
2480 0 : panScanline[iPixel] = 4095;
2481 0 : if( !bClipWarn )
2482 : {
2483 0 : bClipWarn = true;
2484 : CPLError( CE_Warning, CPLE_AppDefined,
2485 0 : "One or more pixels clipped to fit 12bit domain for jpeg output." );
2486 : }
2487 : }
2488 : }
2489 : }
2490 :
2491 4779 : ppSamples = (JSAMPLE *) pabyScanline;
2492 :
2493 4779 : if( eErr == CE_None )
2494 4779 : jpeg_write_scanlines( &sCInfo, &ppSamples, 1 );
2495 :
2496 4779 : if( eErr == CE_None
2497 : && !pfnProgress( (iLine+1) / ((bAppendMask ? 2 : 1) * (double) nYSize),
2498 : NULL, pProgressData ) )
2499 : {
2500 1 : eErr = CE_Failure;
2501 : CPLError( CE_Failure, CPLE_UserInterrupt,
2502 1 : "User terminated CreateCopy()" );
2503 : }
2504 : }
2505 :
2506 : /* -------------------------------------------------------------------- */
2507 : /* Cleanup and close. */
2508 : /* -------------------------------------------------------------------- */
2509 38 : CPLFree( pabyScanline );
2510 :
2511 38 : if( eErr == CE_None )
2512 37 : jpeg_finish_compress( &sCInfo );
2513 38 : jpeg_destroy_compress( &sCInfo );
2514 :
2515 38 : VSIFCloseL( fpImage );
2516 :
2517 38 : if( eErr != CE_None )
2518 : {
2519 1 : VSIUnlink( pszFilename );
2520 1 : return NULL;
2521 : }
2522 :
2523 : /* -------------------------------------------------------------------- */
2524 : /* Append masks to the jpeg file if necessary. */
2525 : /* -------------------------------------------------------------------- */
2526 37 : if( bAppendMask )
2527 : {
2528 2 : CPLDebug( "JPEG", "Appending Mask Bitmap" );
2529 :
2530 2 : void* pScaledData = GDALCreateScaledProgress( 0.5, 1, pfnProgress, pProgressData );
2531 2 : eErr = JPGAppendMask( pszFilename, poSrcDS->GetRasterBand(1)->GetMaskBand(),
2532 4 : GDALScaledProgress, pScaledData );
2533 2 : GDALDestroyScaledProgress( pScaledData );
2534 2 : nCloneFlags &= (~GCIF_MASK);
2535 :
2536 2 : if( eErr != CE_None )
2537 : {
2538 0 : VSIUnlink( pszFilename );
2539 0 : return NULL;
2540 : }
2541 : }
2542 :
2543 : /* -------------------------------------------------------------------- */
2544 : /* Do we need a world file? */
2545 : /* -------------------------------------------------------------------- */
2546 37 : if( CSLFetchBoolean( papszOptions, "WORLDFILE", FALSE ) )
2547 : {
2548 : double adfGeoTransform[6];
2549 :
2550 1 : poSrcDS->GetGeoTransform( adfGeoTransform );
2551 1 : GDALWriteWorldFile( pszFilename, "wld", adfGeoTransform );
2552 : }
2553 :
2554 : /* -------------------------------------------------------------------- */
2555 : /* Re-open dataset, and copy any auxilary pam information. */
2556 : /* -------------------------------------------------------------------- */
2557 :
2558 : /* If outputing to stdout, we can't reopen it, so we'll return */
2559 : /* a fake dataset to make the caller happy */
2560 37 : CPLPushErrorHandler(CPLQuietErrorHandler);
2561 37 : JPGDataset *poDS = (JPGDataset*) Open( pszFilename );
2562 37 : CPLPopErrorHandler();
2563 37 : if( poDS )
2564 : {
2565 35 : poDS->CloneInfo( poSrcDS, nCloneFlags );
2566 35 : return poDS;
2567 : }
2568 :
2569 2 : CPLErrorReset();
2570 :
2571 2 : JPGDataset* poJPG_DS = new JPGDataset();
2572 2 : poJPG_DS->nRasterXSize = nXSize;
2573 2 : poJPG_DS->nRasterYSize = nYSize;
2574 4 : for(int i=0;i<nBands;i++)
2575 2 : poJPG_DS->SetBand( i+1, JPGCreateBand( poJPG_DS, i+1) );
2576 2 : return poJPG_DS;
2577 : }
2578 :
2579 : /************************************************************************/
2580 : /* GDALRegister_JPEG() */
2581 : /************************************************************************/
2582 :
2583 : #if !defined(JPGDataset)
2584 610 : void GDALRegister_JPEG()
2585 :
2586 : {
2587 : GDALDriver *poDriver;
2588 :
2589 610 : if( GDALGetDriverByName( "JPEG" ) == NULL )
2590 : {
2591 588 : poDriver = new GDALDriver();
2592 :
2593 588 : poDriver->SetDescription( "JPEG" );
2594 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
2595 588 : "JPEG JFIF" );
2596 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
2597 588 : "frmt_jpeg.html" );
2598 588 : poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "jpg" );
2599 588 : poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/jpeg" );
2600 :
2601 : #if defined(JPEG_LIB_MK1_OR_12BIT) || defined(JPEG_DUAL_MODE_8_12)
2602 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
2603 588 : "Byte UInt16" );
2604 : #else
2605 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
2606 : "Byte" );
2607 : #endif
2608 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
2609 : "<CreationOptionList>\n"
2610 : " <Option name='PROGRESSIVE' type='boolean' default='NO'/>\n"
2611 : " <Option name='QUALITY' type='int' description='good=100, bad=0, default=75'/>\n"
2612 : " <Option name='WORLDFILE' type='boolean' default='NO'/>\n"
2613 : " <Option name='INTERNAL_MASK' type='boolean' default='YES'/>\n"
2614 : " <Option name='ARITHMETIC' type='boolean' default='NO'/>\n"
2615 : #if JPEG_LIB_VERSION_MAJOR >= 8 && \
2616 : (JPEG_LIB_VERSION_MAJOR > 8 || JPEG_LIB_VERSION_MINOR >= 3)
2617 : " <Option name='BLOCK' type='int' description='between 1 and 16'/>\n"
2618 : #endif
2619 : #if JPEG_LIB_VERSION_MAJOR >= 9
2620 : " <Option name='COLOR_TRANSFORM' type='string-select'>\n"
2621 : " <Value>RGB</Value>"
2622 : " <Value>RGB1</Value>"
2623 : " </Option>"
2624 : #endif
2625 588 : "</CreationOptionList>\n" );
2626 :
2627 588 : poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
2628 :
2629 588 : poDriver->pfnIdentify = JPGDatasetCommon::Identify;
2630 588 : poDriver->pfnOpen = JPGDatasetCommon::Open;
2631 588 : poDriver->pfnCreateCopy = JPGDataset::CreateCopy;
2632 :
2633 588 : GetGDALDriverManager()->RegisterDriver( poDriver );
2634 : }
2635 610 : }
2636 : #endif
|