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