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