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