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