1 : /******************************************************************************
2 : * $Id: geotiff.cpp 25273 2012-12-01 10:36:01Z rouault $
3 : *
4 : * Project: GeoTIFF Driver
5 : * Purpose: GDAL GeoTIFF support.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 1998, 2002, Frank Warmerdam <warmerdam@pobox.com>
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : /* If we use sunpro compiler on linux. Weird idea indeed ! */
31 : #if defined(__SUNPRO_CC) && defined(__linux__)
32 : #define _GNU_SOURCE
33 : #elif defined(__GNUC__) && !defined(_GNU_SOURCE)
34 : /* Required to use RTLD_DEFAULT of dlfcn.h */
35 : #define _GNU_SOURCE
36 : #endif
37 :
38 : #include "gdal_pam.h"
39 : #define CPL_SERV_H_INCLUDED
40 :
41 : #include "xtiffio.h"
42 : #include "geovalues.h"
43 : #include "cpl_string.h"
44 : #include "cpl_csv.h"
45 : #include "cpl_minixml.h"
46 : #include "gt_overview.h"
47 : #include "ogr_spatialref.h"
48 : #include "tif_float.h"
49 : #include "gtiff.h"
50 : #include "gdal_csv.h"
51 : #include "gt_wkt_srs.h"
52 : #include "tifvsi.h"
53 : #include "cpl_multiproc.h"
54 : #include "cplkeywordparser.h"
55 : #include "gt_jpeg_copy.h"
56 :
57 : CPL_CVSID("$Id: geotiff.cpp 25273 2012-12-01 10:36:01Z rouault $");
58 :
59 : /************************************************************************/
60 : /* ==================================================================== */
61 : /* GDALOverviewDS */
62 : /* ==================================================================== */
63 : /************************************************************************/
64 :
65 : /* GDALOverviewDS is not specific to GTiff and could probably be moved */
66 : /* in gcore. It is currently used to generate a fake */
67 : /* dataset from the overview levels of the source dataset that is taken */
68 : /* by CreateCopy() */
69 :
70 : #include "gdal_proxy.h"
71 :
72 : class GDALOverviewBand;
73 :
74 : class GDALOverviewDS : public GDALDataset
75 : {
76 : private:
77 :
78 : friend class GDALOverviewBand;
79 :
80 : GDALDataset* poDS;
81 : GDALDataset* poOvrDS;
82 : int nOvrLevel;
83 :
84 : public:
85 : GDALOverviewDS(GDALDataset* poDS, int nOvrLevel);
86 : virtual ~GDALOverviewDS();
87 :
88 : virtual char **GetMetadata( const char * pszDomain = "" );
89 : virtual const char *GetMetadataItem( const char * pszName,
90 : const char * pszDomain = "" );
91 : };
92 :
93 : class GDALOverviewBand : public GDALProxyRasterBand
94 : {
95 : protected:
96 : GDALRasterBand* poUnderlyingBand;
97 : virtual GDALRasterBand* RefUnderlyingRasterBand();
98 :
99 : public:
100 : GDALOverviewBand(GDALOverviewDS* poDS, int nBand);
101 : virtual ~GDALOverviewBand();
102 : };
103 :
104 12 : GDALOverviewDS::GDALOverviewDS(GDALDataset* poDS, int nOvrLevel)
105 : {
106 12 : this->poDS = poDS;
107 12 : this->nOvrLevel = nOvrLevel;
108 12 : eAccess = poDS->GetAccess();
109 12 : nRasterXSize = poDS->GetRasterBand(1)->GetOverview(nOvrLevel)->GetXSize();
110 12 : nRasterYSize = poDS->GetRasterBand(1)->GetOverview(nOvrLevel)->GetYSize();
111 12 : poOvrDS = poDS->GetRasterBand(1)->GetOverview(nOvrLevel)->GetDataset();
112 12 : nBands = poDS->GetRasterCount();
113 : int i;
114 26 : for(i=0;i<nBands;i++)
115 14 : SetBand(i+1, new GDALOverviewBand(this, i+1));
116 12 : }
117 :
118 12 : GDALOverviewDS::~GDALOverviewDS()
119 : {
120 12 : FlushCache();
121 12 : }
122 :
123 0 : char **GDALOverviewDS::GetMetadata( const char * pszDomain )
124 : {
125 0 : if (poOvrDS != NULL)
126 0 : return poOvrDS->GetMetadata(pszDomain);
127 :
128 0 : return poDS->GetMetadata(pszDomain);
129 : }
130 :
131 30 : const char *GDALOverviewDS::GetMetadataItem( const char * pszName, const char * pszDomain )
132 : {
133 30 : if (poOvrDS != NULL)
134 30 : return poOvrDS->GetMetadataItem(pszName, pszDomain);
135 :
136 0 : return poDS->GetMetadataItem(pszName, pszDomain);
137 : }
138 :
139 14 : GDALOverviewBand::GDALOverviewBand(GDALOverviewDS* poDS, int nBand)
140 : {
141 14 : this->poDS = poDS;
142 14 : this->nBand = nBand;
143 14 : poUnderlyingBand = poDS->poDS->GetRasterBand(nBand)->GetOverview(poDS->nOvrLevel);
144 14 : nRasterXSize = poDS->nRasterXSize;
145 14 : nRasterYSize = poDS->nRasterYSize;
146 14 : eDataType = poUnderlyingBand->GetRasterDataType();
147 14 : poUnderlyingBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
148 14 : }
149 :
150 14 : GDALOverviewBand::~GDALOverviewBand()
151 : {
152 14 : FlushCache();
153 14 : }
154 :
155 50 : GDALRasterBand* GDALOverviewBand::RefUnderlyingRasterBand()
156 : {
157 50 : return poUnderlyingBand;
158 : }
159 :
160 : /************************************************************************/
161 : /* IsPowerOfTwo() */
162 : /************************************************************************/
163 :
164 162 : static int IsPowerOfTwo(unsigned int i)
165 : {
166 162 : int nBitSet = 0;
167 1624 : while(i != 0)
168 : {
169 1300 : if ((i & 1))
170 162 : nBitSet ++;
171 1300 : i >>= 1;
172 : }
173 162 : return nBitSet == 1;
174 : }
175 :
176 : /************************************************************************/
177 : /* GTIFFGetOverviewBlockSize() */
178 : /************************************************************************/
179 :
180 162 : void GTIFFGetOverviewBlockSize(int* pnBlockXSize, int* pnBlockYSize)
181 : {
182 : static int bHasWarned = FALSE;
183 162 : const char* pszVal = CPLGetConfigOption("GDAL_TIFF_OVR_BLOCKSIZE", "128");
184 162 : int nOvrBlockSize = atoi(pszVal);
185 162 : if (nOvrBlockSize < 64 || nOvrBlockSize > 4096 ||
186 : !IsPowerOfTwo(nOvrBlockSize))
187 : {
188 0 : if (!bHasWarned)
189 : {
190 : CPLError(CE_Warning, CPLE_NotSupported,
191 : "Wrong value for GDAL_TIFF_OVR_BLOCKSIZE : %s. "
192 : "Should be a power of 2 between 64 and 4096. Defaulting to 128",
193 0 : pszVal);
194 0 : bHasWarned = TRUE;
195 : }
196 0 : nOvrBlockSize = 128;
197 : }
198 :
199 162 : *pnBlockXSize = nOvrBlockSize;
200 162 : *pnBlockYSize = nOvrBlockSize;
201 162 : }
202 :
203 : enum
204 : {
205 : ENDIANNESS_NATIVE,
206 : ENDIANNESS_LITTLE,
207 : ENDIANNESS_BIG
208 : };
209 :
210 : /************************************************************************/
211 : /* ==================================================================== */
212 : /* GTiffDataset */
213 : /* ==================================================================== */
214 : /************************************************************************/
215 :
216 : class GTiffRasterBand;
217 : class GTiffRGBABand;
218 : class GTiffBitmapBand;
219 :
220 : class GTiffDataset : public GDALPamDataset
221 : {
222 : friend class GTiffRasterBand;
223 : friend class GTiffSplitBand;
224 : friend class GTiffRGBABand;
225 : friend class GTiffBitmapBand;
226 : friend class GTiffSplitBitmapBand;
227 : friend class GTiffOddBitsBand;
228 :
229 : friend void GTIFFSetJpegQuality(GDALDatasetH hGTIFFDS, int nJpegQuality);
230 :
231 : TIFF *hTIFF;
232 : GTiffDataset **ppoActiveDSRef;
233 : GTiffDataset *poActiveDS; /* only used in actual base */
234 :
235 : int bScanDeferred;
236 : void ScanDirectories();
237 :
238 : toff_t nDirOffset;
239 : int bBase;
240 : int bCloseTIFFHandle; /* usefull for closing TIFF handle opened by GTIFF_DIR: */
241 :
242 : uint16 nPlanarConfig;
243 : uint16 nSamplesPerPixel;
244 : uint16 nBitsPerSample;
245 : uint32 nRowsPerStrip;
246 : uint16 nPhotometric;
247 : uint16 nSampleFormat;
248 : uint16 nCompression;
249 :
250 : int nBlocksPerBand;
251 :
252 : uint32 nBlockXSize;
253 : uint32 nBlockYSize;
254 :
255 : int nLoadedBlock; /* or tile */
256 : int bLoadedBlockDirty;
257 : GByte *pabyBlockBuf;
258 :
259 : CPLErr LoadBlockBuf( int nBlockId, int bReadFromDisk = TRUE );
260 : CPLErr FlushBlockBuf();
261 : int bWriteErrorInFlushBlockBuf;
262 :
263 : char *pszProjection;
264 : int bLookedForProjection;
265 : int bLookedForMDAreaOrPoint;
266 :
267 : void LoadMDAreaOrPoint();
268 : void LookForProjection();
269 : #ifdef ESRI_BUILD
270 : void AdjustLinearUnit( short UOMLength );
271 : #endif
272 :
273 : double adfGeoTransform[6];
274 : int bGeoTransformValid;
275 :
276 : int bTreatAsRGBA;
277 : int bCrystalized;
278 :
279 : void Crystalize();
280 :
281 : GDALColorTable *poColorTable;
282 :
283 : void WriteGeoTIFFInfo();
284 : int SetDirectory( toff_t nDirOffset = 0 );
285 :
286 : int nOverviewCount;
287 : GTiffDataset **papoOverviewDS;
288 :
289 : int nGCPCount;
290 : GDAL_GCP *pasGCPList;
291 :
292 : int IsBlockAvailable( int nBlockId );
293 :
294 : int bGeoTIFFInfoChanged;
295 : int bNoDataSet;
296 : double dfNoDataValue;
297 :
298 : int bMetadataChanged;
299 :
300 : int bNeedsRewrite;
301 :
302 : void ApplyPamInfo();
303 : void PushMetadataToPam();
304 :
305 : GDALMultiDomainMetadata oGTiffMDMD;
306 :
307 : CPLString osProfile;
308 : char **papszCreationOptions;
309 :
310 : int bLoadingOtherBands;
311 :
312 : static void WriteRPCTag( TIFF *, char ** );
313 : void ReadRPCTag();
314 :
315 : void* pabyTempWriteBuffer;
316 : int nTempWriteBufferSize;
317 : int WriteEncodedTile(uint32 tile, GByte* pabyData, int bPreserveDataBuffer);
318 : int WriteEncodedStrip(uint32 strip, GByte* pabyData, int bPreserveDataBuffer);
319 :
320 : GTiffDataset* poMaskDS;
321 : GTiffDataset* poBaseDS;
322 :
323 : CPLString osFilename;
324 :
325 : int bFillEmptyTiles;
326 : void FillEmptyTiles(void);
327 :
328 : void FlushDirectory();
329 : CPLErr CleanOverviews();
330 :
331 : /* Used for the all-in-on-strip case */
332 : int nLastLineRead;
333 : int nLastBandRead;
334 : int bTreatAsSplit;
335 : int bTreatAsSplitBitmap;
336 :
337 : int bClipWarn;
338 :
339 : CPLString osRPBFile;
340 : int FindRPBFile();
341 : CPLString osRPCFile;
342 : int FindRPCFile();
343 : CPLString osIMDFile;
344 : int FindIMDFile();
345 : CPLString osPVLFile;
346 : int FindPVLFile();
347 : int bHasSearchedRPC;
348 : void LoadRPCRPB();
349 : int bHasSearchedIMD;
350 : int bHasSearchedPVL;
351 : void LoadIMDPVL();
352 :
353 : int bEXIFMetadataLoaded;
354 : void LoadEXIFMetadata();
355 :
356 : int bHasWarnedDisableAggressiveBandCaching;
357 :
358 : int bDontReloadFirstBlock; /* Hack for libtiff 3.X and #3633 */
359 :
360 : int nZLevel;
361 : int nLZMAPreset;
362 : int nJpegQuality;
363 :
364 : int bPromoteTo8Bits;
365 :
366 : int bDebugDontWriteBlocks;
367 :
368 : CPLErr RegisterNewOverviewDataset(toff_t nOverviewOffset);
369 : CPLErr CreateOverviewsFromSrcOverviews(GDALDataset* poSrcDS);
370 : CPLErr CreateInternalMaskOverviews(int nOvrBlockXSize,
371 : int nOvrBlockYSize);
372 :
373 : int bIsFinalized;
374 : int Finalize();
375 :
376 : int bIgnoreReadErrors;
377 :
378 : CPLString osWldFilename;
379 :
380 : int bDirectIO;
381 :
382 : protected:
383 : virtual int CloseDependentDatasets();
384 :
385 : public:
386 : GTiffDataset();
387 : ~GTiffDataset();
388 :
389 : virtual const char *GetProjectionRef(void);
390 : virtual CPLErr SetProjection( const char * );
391 : virtual CPLErr GetGeoTransform( double * );
392 : virtual CPLErr SetGeoTransform( double * );
393 :
394 : virtual int GetGCPCount();
395 : virtual const char *GetGCPProjection();
396 : virtual const GDAL_GCP *GetGCPs();
397 : CPLErr SetGCPs( int, const GDAL_GCP *, const char * );
398 :
399 : virtual char **GetFileList(void);
400 :
401 : virtual CPLErr IBuildOverviews( const char *, int, int *, int, int *,
402 : GDALProgressFunc, void * );
403 :
404 : CPLErr OpenOffset( TIFF *, GTiffDataset **ppoActiveDSRef,
405 : toff_t nDirOffset, int bBaseIn, GDALAccess,
406 : int bAllowRGBAInterface = TRUE, int bReadGeoTransform = FALSE,
407 : char** papszSiblingFiles = NULL);
408 :
409 : static GDALDataset *OpenDir( GDALOpenInfo * );
410 : static GDALDataset *Open( GDALOpenInfo * );
411 : static int Identify( GDALOpenInfo * );
412 : static GDALDataset *Create( const char * pszFilename,
413 : int nXSize, int nYSize, int nBands,
414 : GDALDataType eType, char ** papszParmList );
415 : static GDALDataset *CreateCopy( const char * pszFilename,
416 : GDALDataset *poSrcDS,
417 : int bStrict, char ** papszOptions,
418 : GDALProgressFunc pfnProgress,
419 : void * pProgressData );
420 : virtual void FlushCache( void );
421 :
422 : virtual CPLErr SetMetadata( char **, const char * = "" );
423 : virtual char **GetMetadata( const char * pszDomain = "" );
424 : virtual CPLErr SetMetadataItem( const char*, const char*,
425 : const char* = "" );
426 : virtual const char *GetMetadataItem( const char * pszName,
427 : const char * pszDomain = "" );
428 : virtual void *GetInternalHandle( const char * );
429 :
430 : virtual CPLErr CreateMaskBand( int nFlags );
431 :
432 : // only needed by createcopy and close code.
433 : static int WriteMetadata( GDALDataset *, TIFF *, int, const char *,
434 : const char *, char **, int bExcludeRPBandIMGFileWriting = FALSE );
435 : static void WriteNoDataValue( TIFF *, double );
436 :
437 : static TIFF * CreateLL( const char * pszFilename,
438 : int nXSize, int nYSize, int nBands,
439 : GDALDataType eType,
440 : double dfExtraSpaceForOverviews,
441 : char **papszParmList );
442 :
443 : CPLErr WriteEncodedTileOrStrip(uint32 tile_or_strip, void* data, int bPreserveDataBuffer);
444 : };
445 :
446 : /************************************************************************/
447 : /* GTIFFSetJpegQuality() */
448 : /* Called by GTIFFBuildOverviews() to set the jpeg quality on the IFD */
449 : /* of the .ovr file */
450 : /************************************************************************/
451 :
452 4 : void GTIFFSetJpegQuality(GDALDatasetH hGTIFFDS, int nJpegQuality)
453 : {
454 4 : CPLAssert(EQUAL(GDALGetDriverShortName(GDALGetDatasetDriver(hGTIFFDS)), "GTIFF"));
455 :
456 4 : GTiffDataset* poDS = (GTiffDataset*)hGTIFFDS;
457 4 : poDS->nJpegQuality = nJpegQuality;
458 :
459 4 : poDS->ScanDirectories();
460 :
461 : int i;
462 7 : for(i=0;i<poDS->nOverviewCount;i++)
463 3 : poDS->papoOverviewDS[i]->nJpegQuality = nJpegQuality;
464 4 : }
465 :
466 : /************************************************************************/
467 : /* ==================================================================== */
468 : /* GTiffRasterBand */
469 : /* ==================================================================== */
470 : /************************************************************************/
471 :
472 : class GTiffRasterBand : public GDALPamRasterBand
473 400095 : {
474 : friend class GTiffDataset;
475 :
476 : GDALColorInterp eBandInterp;
477 :
478 : int bHaveOffsetScale;
479 : double dfOffset;
480 : double dfScale;
481 : CPLString osUnitType;
482 : CPLString osDescription;
483 :
484 : CPLErr DirectIO( GDALRWFlag eRWFlag,
485 : int nXOff, int nYOff, int nXSize, int nYSize,
486 : void * pData, int nBufXSize, int nBufYSize,
487 : GDALDataType eBufType,
488 : int nPixelSpace, int nLineSpace );
489 :
490 : protected:
491 : GTiffDataset *poGDS;
492 : GDALMultiDomainMetadata oGTiffMDMD;
493 :
494 : int bNoDataSet;
495 : double dfNoDataValue;
496 :
497 : void NullBlock( void *pData );
498 : CPLErr FillCacheForOtherBands( int nBlockXOff, int nBlockYOff );
499 :
500 : public:
501 : GTiffRasterBand( GTiffDataset *, int );
502 :
503 : virtual CPLErr IReadBlock( int, int, void * );
504 : virtual CPLErr IWriteBlock( int, int, void * );
505 :
506 : virtual CPLErr IRasterIO( GDALRWFlag eRWFlag,
507 : int nXOff, int nYOff, int nXSize, int nYSize,
508 : void * pData, int nBufXSize, int nBufYSize,
509 : GDALDataType eBufType,
510 : int nPixelSpace, int nLineSpace );
511 :
512 : virtual const char *GetDescription() const;
513 : virtual void SetDescription( const char * );
514 :
515 : virtual GDALColorInterp GetColorInterpretation();
516 : virtual GDALColorTable *GetColorTable();
517 : virtual CPLErr SetColorTable( GDALColorTable * );
518 : virtual double GetNoDataValue( int * );
519 : virtual CPLErr SetNoDataValue( double );
520 :
521 : virtual double GetOffset( int *pbSuccess = NULL );
522 : virtual CPLErr SetOffset( double dfNewValue );
523 : virtual double GetScale( int *pbSuccess = NULL );
524 : virtual CPLErr SetScale( double dfNewValue );
525 : virtual const char* GetUnitType();
526 : virtual CPLErr SetUnitType( const char *pszNewValue );
527 : virtual CPLErr SetColorInterpretation( GDALColorInterp );
528 :
529 : virtual CPLErr SetMetadata( char **, const char * = "" );
530 : virtual char **GetMetadata( const char * pszDomain = "" );
531 : virtual CPLErr SetMetadataItem( const char*, const char*,
532 : const char* = "" );
533 : virtual const char *GetMetadataItem( const char * pszName,
534 : const char * pszDomain = "" );
535 : virtual int GetOverviewCount();
536 : virtual GDALRasterBand *GetOverview( int );
537 :
538 : virtual GDALRasterBand *GetMaskBand();
539 : virtual int GetMaskFlags();
540 : virtual CPLErr CreateMaskBand( int nFlags );
541 : };
542 :
543 : /************************************************************************/
544 : /* GTiffRasterBand() */
545 : /************************************************************************/
546 :
547 400095 : GTiffRasterBand::GTiffRasterBand( GTiffDataset *poDS, int nBand )
548 :
549 : {
550 400095 : poGDS = poDS;
551 :
552 400095 : this->poDS = poDS;
553 400095 : this->nBand = nBand;
554 :
555 400095 : bHaveOffsetScale = FALSE;
556 400095 : dfOffset = 0.0;
557 400095 : dfScale = 1.0;
558 :
559 : /* -------------------------------------------------------------------- */
560 : /* Get the GDAL data type. */
561 : /* -------------------------------------------------------------------- */
562 400095 : uint16 nSampleFormat = poDS->nSampleFormat;
563 :
564 400095 : eDataType = GDT_Unknown;
565 :
566 400095 : if( poDS->nBitsPerSample <= 8 )
567 : {
568 397347 : eDataType = GDT_Byte;
569 397347 : if( nSampleFormat == SAMPLEFORMAT_INT )
570 9 : SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE", "IMAGE_STRUCTURE" );
571 :
572 : }
573 2748 : else if( poDS->nBitsPerSample <= 16 )
574 : {
575 645 : if( nSampleFormat == SAMPLEFORMAT_INT )
576 272 : eDataType = GDT_Int16;
577 : else
578 373 : eDataType = GDT_UInt16;
579 : }
580 2103 : else if( poDS->nBitsPerSample == 32 )
581 : {
582 1156 : if( nSampleFormat == SAMPLEFORMAT_COMPLEXINT )
583 190 : eDataType = GDT_CInt16;
584 966 : else if( nSampleFormat == SAMPLEFORMAT_IEEEFP )
585 503 : eDataType = GDT_Float32;
586 463 : else if( nSampleFormat == SAMPLEFORMAT_INT )
587 232 : eDataType = GDT_Int32;
588 : else
589 231 : eDataType = GDT_UInt32;
590 : }
591 947 : else if( poDS->nBitsPerSample == 64 )
592 : {
593 674 : if( nSampleFormat == SAMPLEFORMAT_IEEEFP )
594 282 : eDataType = GDT_Float64;
595 392 : else if( nSampleFormat == SAMPLEFORMAT_COMPLEXIEEEFP )
596 203 : eDataType = GDT_CFloat32;
597 189 : else if( nSampleFormat == SAMPLEFORMAT_COMPLEXINT )
598 189 : eDataType = GDT_CInt32;
599 : }
600 273 : else if( poDS->nBitsPerSample == 128 )
601 : {
602 205 : if( nSampleFormat == SAMPLEFORMAT_COMPLEXIEEEFP )
603 205 : eDataType = GDT_CFloat64;
604 : }
605 :
606 : /* -------------------------------------------------------------------- */
607 : /* Try to work out band color interpretation. */
608 : /* -------------------------------------------------------------------- */
609 400095 : int bLookForExtraSamples = FALSE;
610 :
611 400183 : if( poDS->poColorTable != NULL && nBand == 1 )
612 88 : eBandInterp = GCI_PaletteIndex;
613 400007 : else if( poDS->nPhotometric == PHOTOMETRIC_RGB
614 : || (poDS->nPhotometric == PHOTOMETRIC_YCBCR
615 : && poDS->nCompression == COMPRESSION_JPEG
616 : && CSLTestBoolean( CPLGetConfigOption("CONVERT_YCBCR_TO_RGB",
617 : "YES") )) )
618 : {
619 1766 : if( nBand == 1 )
620 553 : eBandInterp = GCI_RedBand;
621 1213 : else if( nBand == 2 )
622 553 : eBandInterp = GCI_GreenBand;
623 660 : else if( nBand == 3 )
624 553 : eBandInterp = GCI_BlueBand;
625 : else
626 107 : bLookForExtraSamples = TRUE;
627 : }
628 398241 : else if( poDS->nPhotometric == PHOTOMETRIC_YCBCR )
629 : {
630 4 : if( nBand == 1 )
631 1 : eBandInterp = GCI_YCbCr_YBand;
632 3 : else if( nBand == 2 )
633 1 : eBandInterp = GCI_YCbCr_CbBand;
634 2 : else if( nBand == 3 )
635 1 : eBandInterp = GCI_YCbCr_CrBand;
636 : else
637 1 : bLookForExtraSamples = TRUE;
638 : }
639 398237 : else if( poDS->nPhotometric == PHOTOMETRIC_SEPARATED )
640 : {
641 40 : if( nBand == 1 )
642 10 : eBandInterp = GCI_CyanBand;
643 30 : else if( nBand == 2 )
644 10 : eBandInterp = GCI_MagentaBand;
645 20 : else if( nBand == 3 )
646 10 : eBandInterp = GCI_YellowBand;
647 10 : else if( nBand == 4 )
648 10 : eBandInterp = GCI_BlackBand;
649 : else
650 0 : bLookForExtraSamples = TRUE;
651 : }
652 402681 : else if( poDS->nPhotometric == PHOTOMETRIC_MINISBLACK && nBand == 1 )
653 4484 : eBandInterp = GCI_GrayIndex;
654 : else
655 393713 : bLookForExtraSamples = TRUE;
656 :
657 400095 : if( bLookForExtraSamples )
658 : {
659 : uint16 *v;
660 393821 : uint16 count = 0;
661 :
662 393821 : if( TIFFGetField( poDS->hTIFF, TIFFTAG_EXTRASAMPLES, &count, &v ) )
663 : {
664 : int nBaseSamples;
665 393651 : nBaseSamples = poDS->nSamplesPerPixel - count;
666 :
667 1181052 : if( nBand > nBaseSamples
668 393651 : && (v[nBand-nBaseSamples-1] == EXTRASAMPLE_ASSOCALPHA
669 393646 : || v[nBand-nBaseSamples-1] == EXTRASAMPLE_UNASSALPHA) )
670 104 : eBandInterp = GCI_AlphaBand;
671 : else
672 393547 : eBandInterp = GCI_Undefined;
673 : }
674 : else
675 170 : eBandInterp = GCI_Undefined;
676 : }
677 :
678 : /* -------------------------------------------------------------------- */
679 : /* Establish block size for strip or tiles. */
680 : /* -------------------------------------------------------------------- */
681 400095 : nBlockXSize = poDS->nBlockXSize;
682 400095 : nBlockYSize = poDS->nBlockYSize;
683 :
684 400095 : bNoDataSet = FALSE;
685 400095 : dfNoDataValue = -9999.0;
686 400095 : }
687 :
688 : /************************************************************************/
689 : /* DirectIO() */
690 : /************************************************************************/
691 :
692 : /* Reads directly bytes from the file using ReadMultiRange(), and by-pass */
693 : /* block reading. Restricted to simple TIFF configurations (un-tiled, */
694 : /* uncompressed data, standard data types). Particularly usefull to extract */
695 : /* sub-windows of data on a large /vsicurl dataset). */
696 :
697 1 : CPLErr GTiffRasterBand::DirectIO( GDALRWFlag eRWFlag,
698 : int nXOff, int nYOff, int nXSize, int nYSize,
699 : void * pData, int nBufXSize, int nBufYSize,
700 : GDALDataType eBufType,
701 : int nPixelSpace, int nLineSpace )
702 : {
703 1 : if( !(eRWFlag == GF_Read &&
704 : poGDS->nCompression == COMPRESSION_NONE &&
705 : (poGDS->nPhotometric == PHOTOMETRIC_MINISBLACK ||
706 : poGDS->nPhotometric == PHOTOMETRIC_RGB ||
707 : poGDS->nPhotometric == PHOTOMETRIC_PALETTE) &&
708 : (poGDS->nBitsPerSample == 8 || (poGDS->nBitsPerSample == 16) ||
709 : poGDS->nBitsPerSample == 32 || poGDS->nBitsPerSample == 64) &&
710 : poGDS->nBitsPerSample == GDALGetDataTypeSize(eDataType) &&
711 : !TIFFIsTiled( poGDS->hTIFF )) )
712 : {
713 0 : return CE_Failure;
714 : }
715 :
716 : /*CPLDebug("GTiff", "DirectIO(%d,%d,%d,%d -> %dx%d)",
717 : nXOff, nYOff, nXSize, nYSize,
718 : nBufXSize, nBufYSize);*/
719 :
720 : /* ==================================================================== */
721 : /* Do we have overviews that would be appropriate to satisfy */
722 : /* this request? */
723 : /* ==================================================================== */
724 2 : if( (nBufXSize < nXSize || nBufYSize < nYSize)
725 1 : && GetOverviewCount() > 0 && eRWFlag == GF_Read )
726 : {
727 : int nOverview;
728 :
729 : nOverview =
730 : GDALBandGetBestOverviewLevel(this, nXOff, nYOff, nXSize, nYSize,
731 0 : nBufXSize, nBufYSize);
732 0 : if (nOverview >= 0)
733 : {
734 0 : GDALRasterBand* poOverviewBand = GetOverview(nOverview);
735 0 : if (poOverviewBand == NULL)
736 0 : return CE_Failure;
737 :
738 : return poOverviewBand->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
739 : pData, nBufXSize, nBufYSize, eBufType,
740 0 : nPixelSpace, nLineSpace );
741 : }
742 : }
743 :
744 : /* Make sure that TIFFTAG_STRIPOFFSETS is up-to-date */
745 1 : if (poGDS->GetAccess() == GA_Update)
746 0 : poGDS->FlushCache();
747 :
748 : /* Get strip offsets */
749 1 : toff_t *panTIFFOffsets = NULL;
750 1 : if ( !TIFFGetField( poGDS->hTIFF, TIFFTAG_STRIPOFFSETS, &panTIFFOffsets ) ||
751 : panTIFFOffsets == NULL )
752 : {
753 0 : return CE_Failure;
754 : }
755 :
756 : int iLine;
757 1 : int nReqXSize = nXSize; /* sub-sampling or over-sampling can only be done at last stage */
758 1 : int nReqYSize = MIN(nBufYSize, nYSize); /* we can do sub-sampling at the extraction stage */
759 1 : void** ppData = (void**) VSIMalloc(nReqYSize * sizeof(void*));
760 : vsi_l_offset* panOffsets = (vsi_l_offset*)
761 1 : VSIMalloc(nReqYSize * sizeof(vsi_l_offset));
762 1 : size_t* panSizes = (size_t*) VSIMalloc(nReqYSize * sizeof(size_t));
763 1 : int eDTSize = GDALGetDataTypeSize(eDataType) / 8;
764 1 : void* pTmpBuffer = NULL;
765 1 : CPLErr eErr = CE_None;
766 1 : int nContigBands = ((poGDS->nPlanarConfig == PLANARCONFIG_CONTIG) ? poGDS->nBands : 1);
767 1 : int ePixelSize = eDTSize * nContigBands;
768 :
769 1 : if (ppData == NULL || panOffsets == NULL || panSizes == NULL)
770 0 : eErr = CE_Failure;
771 1 : else if (nXSize != nBufXSize || nYSize != nBufYSize ||
772 : eBufType != eDataType ||
773 : nPixelSpace != GDALGetDataTypeSize(eBufType) / 8 ||
774 : nContigBands > 1)
775 : {
776 : /* We need a temporary buffer for over-sampling/sub-sampling */
777 : /* and/or data type conversion */
778 1 : pTmpBuffer = VSIMalloc(nReqXSize * nReqYSize * ePixelSize);
779 1 : if (pTmpBuffer == NULL)
780 0 : eErr = CE_Failure;
781 : }
782 :
783 : /* Prepare data extraction */
784 129 : for(iLine=0;eErr == CE_None && iLine<nReqYSize;iLine++)
785 : {
786 128 : if (pTmpBuffer == NULL)
787 0 : ppData[iLine] = ((GByte*)pData) + iLine * nLineSpace;
788 : else
789 128 : ppData[iLine] = ((GByte*)pTmpBuffer) + iLine * nReqXSize * ePixelSize;
790 : int nSrcLine;
791 128 : if (nBufYSize < nYSize) /* Sub-sampling in y */
792 128 : nSrcLine = nYOff + (int)((iLine + 0.5) * nYSize / nBufYSize);
793 : else
794 0 : nSrcLine = nYOff + iLine;
795 :
796 128 : int nBlockXOff = 0;
797 128 : int nBlockYOff = nSrcLine / nBlockYSize;
798 128 : int nYOffsetInBlock = nSrcLine % nBlockYSize;
799 128 : int nBlocksPerRow = DIV_ROUND_UP(nRasterXSize, nBlockXSize);
800 128 : int nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
801 128 : if( poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE )
802 : {
803 0 : nBlockId += (nBand-1) * poGDS->nBlocksPerBand;
804 : }
805 :
806 128 : panOffsets[iLine] = panTIFFOffsets[nBlockId];
807 128 : if (panOffsets[iLine] == 0) /* We don't support sparse files */
808 0 : eErr = CE_Failure;
809 :
810 128 : panOffsets[iLine] += (nXOff + nYOffsetInBlock * nBlockXSize) * ePixelSize;
811 128 : panSizes[iLine] = nReqXSize * ePixelSize;
812 : }
813 :
814 : /* Extract data from the file */
815 1 : if (eErr == CE_None)
816 : {
817 1 : VSILFILE* fp = (VSILFILE*) TIFFClientdata( poGDS->hTIFF );
818 1 : int nRet = VSIFReadMultiRangeL(nReqYSize, ppData, panOffsets, panSizes, fp);
819 1 : if (nRet != 0)
820 0 : eErr = CE_Failure;
821 : }
822 :
823 : /* Byte-swap if necessary */
824 1 : if (eErr == CE_None && TIFFIsByteSwapped(poGDS->hTIFF))
825 : {
826 0 : for(iLine=0;iLine<nReqYSize;iLine++)
827 : {
828 0 : GDALSwapWords( ppData[iLine], eDTSize, nReqXSize * nContigBands, eDTSize);
829 : }
830 : }
831 :
832 : /* Over-sampling/sub-sampling and/or data type conversion */
833 1 : if (eErr == CE_None && pTmpBuffer != NULL)
834 : {
835 129 : for(int iY=0;iY<nBufYSize;iY++)
836 : {
837 : int iSrcY = (nBufYSize <= nYSize) ? iY :
838 128 : (int)((iY + 0.5) * nYSize / nBufYSize);
839 128 : if (nBufXSize == nXSize && nContigBands == 1)
840 : {
841 : GDALCopyWords( ppData[iSrcY], eDataType, eDTSize,
842 : ((GByte*)pData) + iY * nLineSpace,
843 : eBufType, nPixelSpace,
844 0 : nReqXSize);
845 : }
846 : else
847 : {
848 128 : GByte* pabySrcData = ((GByte*)ppData[iSrcY]) +
849 128 : ((nContigBands > 1) ? (nBand-1) : 0) * eDTSize;
850 128 : GByte* pabyDstData = ((GByte*)pData) + iY * nLineSpace;
851 16512 : for(int iX=0;iX<nBufXSize;iX++)
852 : {
853 : int iSrcX = (nBufXSize == nXSize) ? iX :
854 16384 : (int)((iX+0.5) * nXSize / nBufXSize);
855 : GDALCopyWords( pabySrcData + iSrcX * ePixelSize,
856 : eDataType, 0,
857 : pabyDstData + iX * nPixelSpace,
858 16384 : eBufType, 0, 1);
859 : }
860 : }
861 : }
862 : }
863 :
864 : /* Cleanup */
865 1 : CPLFree(pTmpBuffer);
866 1 : CPLFree(ppData);
867 1 : CPLFree(panOffsets);
868 1 : CPLFree(panSizes);
869 :
870 1 : return eErr;
871 : }
872 :
873 : /************************************************************************/
874 : /* IRasterIO() */
875 : /************************************************************************/
876 :
877 732380 : CPLErr GTiffRasterBand::IRasterIO( GDALRWFlag eRWFlag,
878 : int nXOff, int nYOff, int nXSize, int nYSize,
879 : void * pData, int nBufXSize, int nBufYSize,
880 : GDALDataType eBufType,
881 : int nPixelSpace, int nLineSpace )
882 : {
883 : CPLErr eErr;
884 :
885 : //CPLDebug("GTiff", "RasterIO(%d, %d, %d, %d, %d, %d)",
886 : // nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize);
887 :
888 732380 : if (poGDS->bDirectIO)
889 : {
890 : eErr = DirectIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
891 : pData, nBufXSize, nBufYSize, eBufType,
892 1 : nPixelSpace, nLineSpace);
893 :
894 1 : if (eErr == CE_None)
895 1 : return eErr;
896 : }
897 :
898 732379 : if (poGDS->nBands != 1 &&
899 : poGDS->nPlanarConfig == PLANARCONFIG_CONTIG &&
900 : eRWFlag == GF_Read &&
901 : nXSize == nBufXSize && nYSize == nBufYSize)
902 : {
903 167436 : int nBlockX1 = nXOff / nBlockXSize;
904 167436 : int nBlockY1 = nYOff / nBlockYSize;
905 167436 : int nBlockX2 = (nXOff + nXSize - 1) / nBlockXSize;
906 167436 : int nBlockY2 = (nYOff + nYSize - 1) / nBlockYSize;
907 167436 : int nXBlocks = nBlockX2 - nBlockX1 + 1;
908 167436 : int nYBlocks = nBlockY2 - nBlockY1 + 1;
909 : GIntBig nRequiredMem = (GIntBig)poGDS->nBands * nXBlocks * nYBlocks *
910 : nBlockXSize * nBlockYSize *
911 167436 : (GDALGetDataTypeSize(eDataType) / 8);
912 167436 : if (nRequiredMem > GDALGetCacheMax64())
913 : {
914 21 : if (!poGDS->bHasWarnedDisableAggressiveBandCaching)
915 : {
916 : CPLDebug("GTiff", "Disable aggressive band caching. Cache not big enough. "
917 1 : "At least " CPL_FRMT_GIB " bytes necessary", nRequiredMem);
918 1 : poGDS->bHasWarnedDisableAggressiveBandCaching = TRUE;
919 : }
920 21 : poGDS->bLoadingOtherBands = TRUE;
921 : }
922 : }
923 :
924 : eErr = GDALPamRasterBand::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
925 : pData, nBufXSize, nBufYSize, eBufType,
926 732379 : nPixelSpace, nLineSpace);
927 :
928 732379 : poGDS->bLoadingOtherBands = FALSE;
929 :
930 732379 : return eErr;
931 : }
932 :
933 : /************************************************************************/
934 : /* IReadBlock() */
935 : /************************************************************************/
936 :
937 98800 : CPLErr GTiffRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
938 : void * pImage )
939 :
940 : {
941 : int nBlockBufSize, nBlockId, nBlockIdBand0;
942 98800 : CPLErr eErr = CE_None;
943 :
944 98800 : if (!poGDS->SetDirectory())
945 0 : return CE_Failure;
946 :
947 98800 : if( TIFFIsTiled(poGDS->hTIFF) )
948 13700 : nBlockBufSize = TIFFTileSize( poGDS->hTIFF );
949 : else
950 : {
951 85100 : CPLAssert( nBlockXOff == 0 );
952 85100 : nBlockBufSize = TIFFStripSize( poGDS->hTIFF );
953 : }
954 :
955 98800 : CPLAssert(nBlocksPerRow != 0);
956 98800 : nBlockIdBand0 = nBlockXOff + nBlockYOff * nBlocksPerRow;
957 98800 : if( poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE )
958 1235 : nBlockId = nBlockIdBand0 + (nBand-1) * poGDS->nBlocksPerBand;
959 : else
960 97565 : nBlockId = nBlockIdBand0;
961 :
962 : /* -------------------------------------------------------------------- */
963 : /* The bottom most partial tiles and strips are sometimes only */
964 : /* partially encoded. This code reduces the requested data so */
965 : /* an error won't be reported in this case. (#1179) */
966 : /* -------------------------------------------------------------------- */
967 98800 : int nBlockReqSize = nBlockBufSize;
968 :
969 98800 : if( (nBlockYOff+1) * nBlockYSize > nRasterYSize )
970 : {
971 : nBlockReqSize = (nBlockBufSize / nBlockYSize)
972 1680 : * (nBlockYSize - (((nBlockYOff+1) * nBlockYSize) % nRasterYSize));
973 : }
974 :
975 : /* -------------------------------------------------------------------- */
976 : /* Handle the case of a strip or tile that doesn't exist yet. */
977 : /* Just set to zeros and return. */
978 : /* -------------------------------------------------------------------- */
979 98800 : if( !poGDS->IsBlockAvailable(nBlockId) )
980 : {
981 12723 : NullBlock( pImage );
982 12723 : return CE_None;
983 : }
984 :
985 : /* -------------------------------------------------------------------- */
986 : /* Handle simple case (separate, onesampleperpixel) */
987 : /* -------------------------------------------------------------------- */
988 86077 : if( poGDS->nBands == 1
989 : || poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE )
990 : {
991 13736 : if( nBlockReqSize < nBlockBufSize )
992 435 : memset( pImage, 0, nBlockBufSize );
993 :
994 13736 : if( TIFFIsTiled( poGDS->hTIFF ) )
995 : {
996 8576 : if( TIFFReadEncodedTile( poGDS->hTIFF, nBlockId, pImage,
997 : nBlockReqSize ) == -1
998 : && !poGDS->bIgnoreReadErrors )
999 : {
1000 1 : memset( pImage, 0, nBlockBufSize );
1001 : CPLError( CE_Failure, CPLE_AppDefined,
1002 1 : "TIFFReadEncodedTile() failed.\n" );
1003 :
1004 1 : eErr = CE_Failure;
1005 : }
1006 : }
1007 : else
1008 : {
1009 5160 : if( TIFFReadEncodedStrip( poGDS->hTIFF, nBlockId, pImage,
1010 : nBlockReqSize ) == -1
1011 : && !poGDS->bIgnoreReadErrors )
1012 : {
1013 1 : memset( pImage, 0, nBlockBufSize );
1014 : CPLError( CE_Failure, CPLE_AppDefined,
1015 1 : "TIFFReadEncodedStrip() failed.\n" );
1016 :
1017 1 : eErr = CE_Failure;
1018 : }
1019 : }
1020 :
1021 13736 : return eErr;
1022 : }
1023 :
1024 : /* -------------------------------------------------------------------- */
1025 : /* Load desired block */
1026 : /* -------------------------------------------------------------------- */
1027 72341 : eErr = poGDS->LoadBlockBuf( nBlockId );
1028 72341 : if( eErr != CE_None )
1029 : {
1030 : memset( pImage, 0,
1031 : nBlockXSize * nBlockYSize
1032 0 : * (GDALGetDataTypeSize(eDataType) / 8) );
1033 0 : return eErr;
1034 : }
1035 :
1036 : /* -------------------------------------------------------------------- */
1037 : /* Special case for YCbCr subsampled data. */
1038 : /* -------------------------------------------------------------------- */
1039 : #ifdef notdef
1040 : if( (eBandInterp == GCI_YCbCr_YBand
1041 : || eBandInterp == GCI_YCbCr_CbBand
1042 : || eBandInterp == GCI_YCbCr_CrBand)
1043 : && poGDS->nBitsPerSample == 8 )
1044 : {
1045 : uint16 hs, vs;
1046 : int iX, iY;
1047 :
1048 : TIFFGetFieldDefaulted( poGDS->hTIFF, TIFFTAG_YCBCRSUBSAMPLING,
1049 : &hs, &vs);
1050 :
1051 : for( iY = 0; iY < nBlockYSize; iY++ )
1052 : {
1053 : for( iX = 0; iX < nBlockXSize; iX++ )
1054 : {
1055 : int iBlock = (iY / vs) * (nBlockXSize/hs) + (iX / hs);
1056 : GByte *pabySrcBlock = poGDS->pabyBlockBuf +
1057 : (vs * hs + 2) * iBlock;
1058 :
1059 : if( eBandInterp == GCI_YCbCr_YBand )
1060 : ((GByte *)pImage)[iY*nBlockXSize + iX] =
1061 : pabySrcBlock[(iX % hs) + (iY % vs) * hs];
1062 : else if( eBandInterp == GCI_YCbCr_CbBand )
1063 : ((GByte *)pImage)[iY*nBlockXSize + iX] =
1064 : pabySrcBlock[vs * hs + 0];
1065 : else if( eBandInterp == GCI_YCbCr_CrBand )
1066 : ((GByte *)pImage)[iY*nBlockXSize + iX] =
1067 : pabySrcBlock[vs * hs + 1];
1068 : }
1069 : }
1070 :
1071 : return CE_None;
1072 : }
1073 : #endif
1074 :
1075 : /* -------------------------------------------------------------------- */
1076 : /* Handle simple case of eight bit data, and pixel interleaving. */
1077 : /* -------------------------------------------------------------------- */
1078 72341 : if( poGDS->nBitsPerSample == 8 )
1079 : {
1080 : int i, nBlockPixels;
1081 : GByte *pabyImage;
1082 72247 : GByte *pabyImageDest = (GByte*)pImage;
1083 72247 : int nBands = poGDS->nBands;
1084 :
1085 72247 : pabyImage = poGDS->pabyBlockBuf + nBand - 1;
1086 :
1087 72247 : nBlockPixels = nBlockXSize * nBlockYSize;
1088 :
1089 : /* ==================================================================== */
1090 : /* Optimization for high number of words to transfer and some */
1091 : /* typical band numbers : we unroll the loop. */
1092 : /* ==================================================================== */
1093 : #define COPY_TO_DST_BUFFER(nBands) \
1094 : if (nBlockPixels > 100) \
1095 : { \
1096 : for ( i = nBlockPixels / 16; i != 0; i -- ) \
1097 : { \
1098 : pabyImageDest[0] = pabyImage[0*nBands]; \
1099 : pabyImageDest[1] = pabyImage[1*nBands]; \
1100 : pabyImageDest[2] = pabyImage[2*nBands]; \
1101 : pabyImageDest[3] = pabyImage[3*nBands]; \
1102 : pabyImageDest[4] = pabyImage[4*nBands]; \
1103 : pabyImageDest[5] = pabyImage[5*nBands]; \
1104 : pabyImageDest[6] = pabyImage[6*nBands]; \
1105 : pabyImageDest[7] = pabyImage[7*nBands]; \
1106 : pabyImageDest[8] = pabyImage[8*nBands]; \
1107 : pabyImageDest[9] = pabyImage[9*nBands]; \
1108 : pabyImageDest[10] = pabyImage[10*nBands]; \
1109 : pabyImageDest[11] = pabyImage[11*nBands]; \
1110 : pabyImageDest[12] = pabyImage[12*nBands]; \
1111 : pabyImageDest[13] = pabyImage[13*nBands]; \
1112 : pabyImageDest[14] = pabyImage[14*nBands]; \
1113 : pabyImageDest[15] = pabyImage[15*nBands]; \
1114 : pabyImageDest += 16; \
1115 : pabyImage += 16*nBands; \
1116 : } \
1117 : nBlockPixels = nBlockPixels % 16; \
1118 : } \
1119 : for( i = 0; i < nBlockPixels; i++ ) \
1120 : { \
1121 : pabyImageDest[i] = *pabyImage; \
1122 : pabyImage += nBands; \
1123 : }
1124 :
1125 72247 : switch (nBands)
1126 : {
1127 4663 : case 3: COPY_TO_DST_BUFFER(3); break;
1128 1976 : case 4: COPY_TO_DST_BUFFER(4); break;
1129 : default:
1130 : {
1131 770081 : for( i = 0; i < nBlockPixels; i++ )
1132 : {
1133 704473 : pabyImageDest[i] = *pabyImage;
1134 704473 : pabyImage += nBands;
1135 : }
1136 : }
1137 : }
1138 : #undef COPY_TO_DST_BUFFER
1139 : }
1140 :
1141 : else
1142 : {
1143 : int i, nBlockPixels, nWordBytes;
1144 : GByte *pabyImage;
1145 :
1146 94 : nWordBytes = poGDS->nBitsPerSample / 8;
1147 94 : pabyImage = poGDS->pabyBlockBuf + (nBand - 1) * nWordBytes;
1148 :
1149 94 : nBlockPixels = nBlockXSize * nBlockYSize;
1150 551822 : for( i = 0; i < nBlockPixels; i++ )
1151 : {
1152 2755440 : for( int j = 0; j < nWordBytes; j++ )
1153 : {
1154 2203712 : ((GByte *) pImage)[i*nWordBytes + j] = pabyImage[j];
1155 : }
1156 551728 : pabyImage += poGDS->nBands * nWordBytes;
1157 : }
1158 : }
1159 :
1160 72341 : if (eErr == CE_None)
1161 72341 : eErr = FillCacheForOtherBands(nBlockXOff, nBlockYOff);
1162 :
1163 72341 : return eErr;
1164 : }
1165 :
1166 :
1167 : /************************************************************************/
1168 : /* FillCacheForOtherBands() */
1169 : /************************************************************************/
1170 :
1171 72357 : CPLErr GTiffRasterBand::FillCacheForOtherBands( int nBlockXOff, int nBlockYOff )
1172 :
1173 : {
1174 72357 : CPLErr eErr = CE_None;
1175 : /* -------------------------------------------------------------------- */
1176 : /* In the fairly common case of pixel interleaved 8bit data */
1177 : /* that is multi-band, lets push the rest of the data into the */
1178 : /* block cache too, to avoid (hopefully) having to redecode it. */
1179 : /* */
1180 : /* Our following logic actually depends on the fact that the */
1181 : /* this block is already loaded, so subsequent calls will end */
1182 : /* up back in this method and pull from the loaded block. */
1183 : /* */
1184 : /* Be careful not entering this portion of code from */
1185 : /* the other bands, otherwise we'll get very deep nested calls */
1186 : /* and O(nBands^2) performance ! */
1187 : /* */
1188 : /* If there are many bands and the block cache size is not big */
1189 : /* enough to accomodate the size of all the blocks, don't enter */
1190 : /* -------------------------------------------------------------------- */
1191 72357 : if( poGDS->nBands != 1 && !poGDS->bLoadingOtherBands &&
1192 : nBlockXSize * nBlockYSize * (GDALGetDataTypeSize(eDataType) / 8) < GDALGetCacheMax64() / poGDS->nBands)
1193 : {
1194 : int iOtherBand;
1195 :
1196 2120 : poGDS->bLoadingOtherBands = TRUE;
1197 :
1198 74474 : for( iOtherBand = 1; iOtherBand <= poGDS->nBands; iOtherBand++ )
1199 : {
1200 72354 : if( iOtherBand == nBand )
1201 2120 : continue;
1202 :
1203 : GDALRasterBlock *poBlock;
1204 :
1205 : poBlock = poGDS->GetRasterBand(iOtherBand)->
1206 70234 : GetLockedBlockRef(nBlockXOff,nBlockYOff);
1207 70234 : if (poBlock == NULL)
1208 : {
1209 0 : eErr = CE_Failure;
1210 0 : break;
1211 : }
1212 70234 : poBlock->DropLock();
1213 : }
1214 :
1215 2120 : poGDS->bLoadingOtherBands = FALSE;
1216 : }
1217 :
1218 72357 : return eErr;
1219 : }
1220 :
1221 : /************************************************************************/
1222 : /* IWriteBlock() */
1223 : /************************************************************************/
1224 :
1225 25455 : CPLErr GTiffRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
1226 : void * pImage )
1227 :
1228 : {
1229 : int nBlockId;
1230 25455 : CPLErr eErr = CE_None;
1231 :
1232 25455 : if (poGDS->bDebugDontWriteBlocks)
1233 7024 : return CE_None;
1234 :
1235 18431 : if (poGDS->bWriteErrorInFlushBlockBuf)
1236 : {
1237 : /* Report as an error if a previously loaded block couldn't be */
1238 : /* written correctly */
1239 0 : poGDS->bWriteErrorInFlushBlockBuf = FALSE;
1240 0 : return CE_Failure;
1241 : }
1242 :
1243 18431 : if (!poGDS->SetDirectory())
1244 0 : return CE_Failure;
1245 :
1246 : CPLAssert( poGDS != NULL
1247 : && nBlockXOff >= 0
1248 : && nBlockYOff >= 0
1249 18431 : && pImage != NULL );
1250 18431 : CPLAssert(nBlocksPerRow != 0);
1251 :
1252 : /* -------------------------------------------------------------------- */
1253 : /* Handle case of "separate" images */
1254 : /* -------------------------------------------------------------------- */
1255 18431 : if( poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE
1256 : || poGDS->nBands == 1 )
1257 : {
1258 : nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow
1259 15819 : + (nBand-1) * poGDS->nBlocksPerBand;
1260 :
1261 15819 : eErr = poGDS->WriteEncodedTileOrStrip(nBlockId, pImage, TRUE);
1262 :
1263 15819 : return eErr;
1264 : }
1265 :
1266 : /* -------------------------------------------------------------------- */
1267 : /* Handle case of pixel interleaved (PLANARCONFIG_CONTIG) images. */
1268 : /* -------------------------------------------------------------------- */
1269 2612 : nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
1270 :
1271 2612 : eErr = poGDS->LoadBlockBuf( nBlockId );
1272 2612 : if( eErr != CE_None )
1273 0 : return eErr;
1274 :
1275 : /* -------------------------------------------------------------------- */
1276 : /* On write of pixel interleaved data, we might as well flush */
1277 : /* out any other bands that are dirty in our cache. This is */
1278 : /* especially helpful when writing compressed blocks. */
1279 : /* -------------------------------------------------------------------- */
1280 : int iBand;
1281 2612 : int nWordBytes = poGDS->nBitsPerSample / 8;
1282 2612 : int nBands = poGDS->nBands;
1283 :
1284 10722 : for( iBand = 0; iBand < nBands; iBand++ )
1285 : {
1286 8110 : const GByte *pabyThisImage = NULL;
1287 8110 : GDALRasterBlock *poBlock = NULL;
1288 :
1289 8110 : if( iBand+1 == nBand )
1290 2612 : pabyThisImage = (GByte *) pImage;
1291 : else
1292 : {
1293 : poBlock = ((GTiffRasterBand *)poGDS->GetRasterBand( iBand+1 ))
1294 5498 : ->TryGetLockedBlockRef( nBlockXOff, nBlockYOff );
1295 :
1296 5498 : if( poBlock == NULL )
1297 226 : continue;
1298 :
1299 5272 : if( !poBlock->GetDirty() )
1300 : {
1301 199 : poBlock->DropLock();
1302 199 : continue;
1303 : }
1304 :
1305 5073 : pabyThisImage = (GByte *) poBlock->GetDataRef();
1306 : }
1307 :
1308 7685 : int i, nBlockPixels = nBlockXSize * nBlockYSize;
1309 7685 : GByte *pabyOut = poGDS->pabyBlockBuf + iBand*nWordBytes;
1310 :
1311 7685 : if (nWordBytes == 1)
1312 : {
1313 :
1314 : /* ==================================================================== */
1315 : /* Optimization for high number of words to transfer and some */
1316 : /* typical band numbers : we unroll the loop. */
1317 : /* ==================================================================== */
1318 : #define COPY_TO_DST_BUFFER(nBands) \
1319 : if (nBlockPixels > 100) \
1320 : { \
1321 : for ( i = nBlockPixels / 16; i != 0; i -- ) \
1322 : { \
1323 : pabyOut[0*nBands] = pabyThisImage[0]; \
1324 : pabyOut[1*nBands] = pabyThisImage[1]; \
1325 : pabyOut[2*nBands] = pabyThisImage[2]; \
1326 : pabyOut[3*nBands] = pabyThisImage[3]; \
1327 : pabyOut[4*nBands] = pabyThisImage[4]; \
1328 : pabyOut[5*nBands] = pabyThisImage[5]; \
1329 : pabyOut[6*nBands] = pabyThisImage[6]; \
1330 : pabyOut[7*nBands] = pabyThisImage[7]; \
1331 : pabyOut[8*nBands] = pabyThisImage[8]; \
1332 : pabyOut[9*nBands] = pabyThisImage[9]; \
1333 : pabyOut[10*nBands] = pabyThisImage[10]; \
1334 : pabyOut[11*nBands] = pabyThisImage[11]; \
1335 : pabyOut[12*nBands] = pabyThisImage[12]; \
1336 : pabyOut[13*nBands] = pabyThisImage[13]; \
1337 : pabyOut[14*nBands] = pabyThisImage[14]; \
1338 : pabyOut[15*nBands] = pabyThisImage[15]; \
1339 : pabyThisImage += 16; \
1340 : pabyOut += 16*nBands; \
1341 : } \
1342 : nBlockPixels = nBlockPixels % 16; \
1343 : } \
1344 : for( i = 0; i < nBlockPixels; i++ ) \
1345 : { \
1346 : *pabyOut = pabyThisImage[i]; \
1347 : pabyOut += nBands; \
1348 : }
1349 :
1350 7621 : switch (nBands)
1351 : {
1352 6476 : case 3: COPY_TO_DST_BUFFER(3); break;
1353 1029 : case 4: COPY_TO_DST_BUFFER(4); break;
1354 : default:
1355 : {
1356 446514 : for( i = 0; i < nBlockPixels; i++ )
1357 : {
1358 446398 : *pabyOut = pabyThisImage[i];
1359 446398 : pabyOut += nBands;
1360 : }
1361 : }
1362 : }
1363 : #undef COPY_TO_DST_BUFFER
1364 : }
1365 : else
1366 : {
1367 205496 : for( i = 0; i < nBlockPixels; i++ )
1368 : {
1369 205432 : memcpy( pabyOut, pabyThisImage, nWordBytes );
1370 :
1371 205432 : pabyOut += nWordBytes * nBands;
1372 205432 : pabyThisImage += nWordBytes;
1373 : }
1374 : }
1375 :
1376 7685 : if( poBlock != NULL )
1377 : {
1378 5073 : poBlock->MarkClean();
1379 5073 : poBlock->DropLock();
1380 : }
1381 : }
1382 :
1383 2612 : poGDS->bLoadedBlockDirty = TRUE;
1384 :
1385 2612 : return CE_None;
1386 : }
1387 :
1388 : /************************************************************************/
1389 : /* SetDescription() */
1390 : /************************************************************************/
1391 :
1392 7 : void GTiffRasterBand::SetDescription( const char *pszDescription )
1393 :
1394 : {
1395 7 : if( pszDescription == NULL )
1396 0 : pszDescription = "";
1397 :
1398 7 : osDescription = pszDescription;
1399 7 : }
1400 :
1401 : /************************************************************************/
1402 : /* GetDescription() */
1403 : /************************************************************************/
1404 :
1405 134245 : const char *GTiffRasterBand::GetDescription() const
1406 : {
1407 134245 : return osDescription;
1408 : }
1409 :
1410 : /************************************************************************/
1411 : /* GetOffset() */
1412 : /************************************************************************/
1413 :
1414 134113 : double GTiffRasterBand::GetOffset( int *pbSuccess )
1415 :
1416 : {
1417 134113 : if( pbSuccess )
1418 1080 : *pbSuccess = bHaveOffsetScale;
1419 134113 : return dfOffset;
1420 : }
1421 :
1422 : /************************************************************************/
1423 : /* SetOffset() */
1424 : /************************************************************************/
1425 :
1426 10 : CPLErr GTiffRasterBand::SetOffset( double dfNewValue )
1427 :
1428 : {
1429 10 : if( !bHaveOffsetScale || dfNewValue != dfOffset )
1430 10 : poGDS->bMetadataChanged = TRUE;
1431 :
1432 10 : bHaveOffsetScale = TRUE;
1433 10 : dfOffset = dfNewValue;
1434 10 : return CE_None;
1435 : }
1436 :
1437 : /************************************************************************/
1438 : /* GetScale() */
1439 : /************************************************************************/
1440 :
1441 134113 : double GTiffRasterBand::GetScale( int *pbSuccess )
1442 :
1443 : {
1444 134113 : if( pbSuccess )
1445 1080 : *pbSuccess = bHaveOffsetScale;
1446 134113 : return dfScale;
1447 : }
1448 :
1449 : /************************************************************************/
1450 : /* SetScale() */
1451 : /************************************************************************/
1452 :
1453 10 : CPLErr GTiffRasterBand::SetScale( double dfNewValue )
1454 :
1455 : {
1456 10 : if( !bHaveOffsetScale || dfNewValue != dfScale )
1457 10 : poGDS->bMetadataChanged = TRUE;
1458 :
1459 10 : bHaveOffsetScale = TRUE;
1460 10 : dfScale = dfNewValue;
1461 10 : return CE_None;
1462 : }
1463 :
1464 : /************************************************************************/
1465 : /* GetUnitType() */
1466 : /************************************************************************/
1467 :
1468 133694 : const char* GTiffRasterBand::GetUnitType()
1469 :
1470 : {
1471 133694 : return osUnitType.c_str();
1472 : }
1473 :
1474 : /************************************************************************/
1475 : /* SetUnitType() */
1476 : /************************************************************************/
1477 :
1478 18 : CPLErr GTiffRasterBand::SetUnitType( const char* pszNewValue )
1479 :
1480 : {
1481 18 : CPLString osNewValue(pszNewValue ? pszNewValue : "");
1482 18 : if( osNewValue.compare(osUnitType) != 0 )
1483 17 : poGDS->bMetadataChanged = TRUE;
1484 :
1485 18 : osUnitType = osNewValue;
1486 18 : return CE_None;
1487 : }
1488 :
1489 : /************************************************************************/
1490 : /* GetMetadata() */
1491 : /************************************************************************/
1492 :
1493 2642 : char **GTiffRasterBand::GetMetadata( const char * pszDomain )
1494 :
1495 : {
1496 2642 : return oGTiffMDMD.GetMetadata( pszDomain );
1497 : }
1498 :
1499 : /************************************************************************/
1500 : /* SetMetadata() */
1501 : /************************************************************************/
1502 :
1503 367 : CPLErr GTiffRasterBand::SetMetadata( char ** papszMD, const char *pszDomain )
1504 :
1505 : {
1506 367 : if( pszDomain == NULL || !EQUAL(pszDomain,"_temporary_") )
1507 : {
1508 367 : if( papszMD != NULL )
1509 34 : poGDS->bMetadataChanged = TRUE;
1510 : }
1511 :
1512 367 : return oGTiffMDMD.SetMetadata( papszMD, pszDomain );
1513 : }
1514 :
1515 : /************************************************************************/
1516 : /* GetMetadataItem() */
1517 : /************************************************************************/
1518 :
1519 5412 : const char *GTiffRasterBand::GetMetadataItem( const char * pszName,
1520 : const char * pszDomain )
1521 :
1522 : {
1523 5412 : return oGTiffMDMD.GetMetadataItem( pszName, pszDomain );
1524 : }
1525 :
1526 : /************************************************************************/
1527 : /* SetMetadataItem() */
1528 : /************************************************************************/
1529 :
1530 671 : CPLErr GTiffRasterBand::SetMetadataItem( const char *pszName,
1531 : const char *pszValue,
1532 : const char *pszDomain )
1533 :
1534 : {
1535 671 : if( pszDomain == NULL || !EQUAL(pszDomain,"_temporary_") )
1536 671 : poGDS->bMetadataChanged = TRUE;
1537 :
1538 671 : return oGTiffMDMD.SetMetadataItem( pszName, pszValue, pszDomain );
1539 : }
1540 :
1541 : /************************************************************************/
1542 : /* GetColorInterpretation() */
1543 : /************************************************************************/
1544 :
1545 3724 : GDALColorInterp GTiffRasterBand::GetColorInterpretation()
1546 :
1547 : {
1548 3724 : return eBandInterp;
1549 : }
1550 :
1551 : /************************************************************************/
1552 : /* GTiffGetAlphaValue() */
1553 : /************************************************************************/
1554 :
1555 : /* Note: was EXTRASAMPLE_ASSOCALPHA in GDAL < 1.10 */
1556 : #define DEFAULT_ALPHA_TYPE EXTRASAMPLE_UNASSALPHA
1557 :
1558 102 : static int GTiffGetAlphaValue(const char* pszValue, int nDefault)
1559 : {
1560 102 : if (pszValue == NULL)
1561 101 : return nDefault;
1562 1 : else if (EQUAL(pszValue, "YES"))
1563 1 : return DEFAULT_ALPHA_TYPE;
1564 0 : else if (EQUAL(pszValue, "PREMULTIPLIED"))
1565 0 : return EXTRASAMPLE_ASSOCALPHA;
1566 0 : else if (EQUAL(pszValue, "NON-PREMULTIPLIED"))
1567 0 : return EXTRASAMPLE_UNASSALPHA;
1568 0 : else if (EQUAL(pszValue, "NO") ||
1569 : EQUAL(pszValue, "UNSPECIFIED"))
1570 0 : return EXTRASAMPLE_UNSPECIFIED;
1571 : else
1572 0 : return nDefault;
1573 : }
1574 :
1575 : /************************************************************************/
1576 : /* SetColorInterpretation() */
1577 : /************************************************************************/
1578 :
1579 20 : CPLErr GTiffRasterBand::SetColorInterpretation( GDALColorInterp eInterp )
1580 :
1581 : {
1582 20 : if( eInterp == eBandInterp )
1583 12 : return CE_None;
1584 :
1585 8 : if( poGDS->bCrystalized )
1586 0 : return GDALPamRasterBand::SetColorInterpretation( eInterp );
1587 :
1588 : /* greyscale + alpha */
1589 8 : else if( eInterp == GCI_AlphaBand
1590 : && nBand == 2
1591 : && poGDS->nSamplesPerPixel == 2
1592 : && poGDS->nPhotometric == PHOTOMETRIC_MINISBLACK )
1593 : {
1594 : uint16 v[1];
1595 : v[0] = GTiffGetAlphaValue(CPLGetConfigOption("GTIFF_ALPHA", NULL),
1596 1 : DEFAULT_ALPHA_TYPE);
1597 :
1598 1 : TIFFSetField(poGDS->hTIFF, TIFFTAG_EXTRASAMPLES, 1, v);
1599 1 : eBandInterp = eInterp;
1600 1 : return CE_None;
1601 : }
1602 :
1603 : /* RGB + alpha */
1604 7 : else if( eInterp == GCI_AlphaBand
1605 : && nBand == 4
1606 : && poGDS->nSamplesPerPixel == 4
1607 : && poGDS->nPhotometric == PHOTOMETRIC_RGB )
1608 : {
1609 : uint16 v[1];
1610 : v[0] = GTiffGetAlphaValue(CPLGetConfigOption("GTIFF_ALPHA", NULL),
1611 1 : DEFAULT_ALPHA_TYPE);
1612 :
1613 1 : TIFFSetField(poGDS->hTIFF, TIFFTAG_EXTRASAMPLES, 1, v);
1614 1 : eBandInterp = eInterp;
1615 1 : return CE_None;
1616 : }
1617 :
1618 : else
1619 6 : return GDALPamRasterBand::SetColorInterpretation( eInterp );
1620 : }
1621 :
1622 : /************************************************************************/
1623 : /* GetColorTable() */
1624 : /************************************************************************/
1625 :
1626 2460 : GDALColorTable *GTiffRasterBand::GetColorTable()
1627 :
1628 : {
1629 2460 : if( nBand == 1 )
1630 2019 : return poGDS->poColorTable;
1631 : else
1632 441 : return NULL;
1633 : }
1634 :
1635 : /************************************************************************/
1636 : /* SetColorTable() */
1637 : /************************************************************************/
1638 :
1639 15 : CPLErr GTiffRasterBand::SetColorTable( GDALColorTable * poCT )
1640 :
1641 : {
1642 : /* -------------------------------------------------------------------- */
1643 : /* Check if this is even a candidate for applying a PCT. */
1644 : /* -------------------------------------------------------------------- */
1645 15 : if( nBand != 1)
1646 : {
1647 : CPLError( CE_Failure, CPLE_NotSupported,
1648 0 : "SetColorTable() can only be called on band 1." );
1649 0 : return CE_Failure;
1650 : }
1651 :
1652 15 : if( poGDS->nSamplesPerPixel != 1 && poGDS->nSamplesPerPixel != 2)
1653 : {
1654 : CPLError( CE_Failure, CPLE_NotSupported,
1655 0 : "SetColorTable() not supported for multi-sample TIFF files." );
1656 0 : return CE_Failure;
1657 : }
1658 :
1659 15 : if( eDataType != GDT_Byte && eDataType != GDT_UInt16 )
1660 : {
1661 : CPLError( CE_Failure, CPLE_NotSupported,
1662 0 : "SetColorTable() only supported for Byte or UInt16 bands in TIFF format." );
1663 0 : return CE_Failure;
1664 : }
1665 :
1666 : /* -------------------------------------------------------------------- */
1667 : /* We are careful about calling SetDirectory() to avoid */
1668 : /* prematurely crystalizing the directory. (#2820) */
1669 : /* -------------------------------------------------------------------- */
1670 15 : if( poGDS->bCrystalized )
1671 : {
1672 4 : if (!poGDS->SetDirectory())
1673 0 : return CE_Failure;
1674 : }
1675 :
1676 : /* -------------------------------------------------------------------- */
1677 : /* Is this really a request to clear the color table? */
1678 : /* -------------------------------------------------------------------- */
1679 15 : if( poCT == NULL || poCT->GetColorEntryCount() == 0 )
1680 : {
1681 : TIFFSetField( poGDS->hTIFF, TIFFTAG_PHOTOMETRIC,
1682 1 : PHOTOMETRIC_MINISBLACK );
1683 :
1684 : #ifdef HAVE_UNSETFIELD
1685 1 : TIFFUnsetField( poGDS->hTIFF, TIFFTAG_COLORMAP );
1686 : #else
1687 : CPLDebug( "GTiff",
1688 : "TIFFUnsetField() not supported, colormap may not be cleared." );
1689 : #endif
1690 :
1691 1 : if( poGDS->poColorTable )
1692 : {
1693 1 : delete poGDS->poColorTable;
1694 1 : poGDS->poColorTable = NULL;
1695 : }
1696 :
1697 1 : return CE_None;
1698 : }
1699 :
1700 : /* -------------------------------------------------------------------- */
1701 : /* Write out the colortable, and update the configuration. */
1702 : /* -------------------------------------------------------------------- */
1703 : int nColors;
1704 :
1705 14 : if( eDataType == GDT_Byte )
1706 13 : nColors = 256;
1707 : else
1708 1 : nColors = 65536;
1709 :
1710 : unsigned short *panTRed, *panTGreen, *panTBlue;
1711 :
1712 14 : panTRed = (unsigned short *) CPLMalloc(sizeof(unsigned short)*nColors);
1713 14 : panTGreen = (unsigned short *) CPLMalloc(sizeof(unsigned short)*nColors);
1714 14 : panTBlue = (unsigned short *) CPLMalloc(sizeof(unsigned short)*nColors);
1715 :
1716 68878 : for( int iColor = 0; iColor < nColors; iColor++ )
1717 : {
1718 68864 : if( iColor < poCT->GetColorEntryCount() )
1719 : {
1720 : GDALColorEntry sRGB;
1721 :
1722 824 : poCT->GetColorEntryAsRGB( iColor, &sRGB );
1723 :
1724 824 : panTRed[iColor] = (unsigned short) (257 * sRGB.c1);
1725 824 : panTGreen[iColor] = (unsigned short) (257 * sRGB.c2);
1726 824 : panTBlue[iColor] = (unsigned short) (257 * sRGB.c3);
1727 : }
1728 : else
1729 : {
1730 68040 : panTRed[iColor] = panTGreen[iColor] = panTBlue[iColor] = 0;
1731 : }
1732 : }
1733 :
1734 14 : TIFFSetField( poGDS->hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE );
1735 : TIFFSetField( poGDS->hTIFF, TIFFTAG_COLORMAP,
1736 14 : panTRed, panTGreen, panTBlue );
1737 :
1738 14 : CPLFree( panTRed );
1739 14 : CPLFree( panTGreen );
1740 14 : CPLFree( panTBlue );
1741 :
1742 14 : if( poGDS->poColorTable )
1743 3 : delete poGDS->poColorTable;
1744 :
1745 : /* libtiff 3.X needs setting this in all cases (creation or update) */
1746 : /* whereas libtiff 4.X would just need it if there */
1747 : /* was no color table before */
1748 : #if 0
1749 : else
1750 : #endif
1751 14 : poGDS->bNeedsRewrite = TRUE;
1752 :
1753 14 : poGDS->poColorTable = poCT->Clone();
1754 14 : eBandInterp = GCI_PaletteIndex;
1755 :
1756 14 : return CE_None;
1757 : }
1758 :
1759 : /************************************************************************/
1760 : /* GetNoDataValue() */
1761 : /************************************************************************/
1762 :
1763 20357 : double GTiffRasterBand::GetNoDataValue( int * pbSuccess )
1764 :
1765 : {
1766 20357 : if( bNoDataSet )
1767 : {
1768 99 : if( pbSuccess )
1769 90 : *pbSuccess = TRUE;
1770 :
1771 99 : return dfNoDataValue;
1772 : }
1773 :
1774 20258 : if( poGDS->bNoDataSet )
1775 : {
1776 263 : if( pbSuccess )
1777 244 : *pbSuccess = TRUE;
1778 :
1779 263 : return poGDS->dfNoDataValue;
1780 : }
1781 :
1782 19995 : return GDALPamRasterBand::GetNoDataValue( pbSuccess );
1783 : }
1784 :
1785 : /************************************************************************/
1786 : /* SetNoDataValue() */
1787 : /************************************************************************/
1788 :
1789 70 : CPLErr GTiffRasterBand::SetNoDataValue( double dfNoData )
1790 :
1791 : {
1792 70 : if( poGDS->bNoDataSet && poGDS->dfNoDataValue == dfNoData )
1793 21 : return CE_None;
1794 :
1795 49 : if (!poGDS->SetDirectory()) // needed to call TIFFSetField().
1796 0 : return CE_Failure;
1797 :
1798 49 : poGDS->bNoDataSet = TRUE;
1799 49 : poGDS->dfNoDataValue = dfNoData;
1800 :
1801 49 : poGDS->WriteNoDataValue( poGDS->hTIFF, dfNoData );
1802 49 : poGDS->bNeedsRewrite = TRUE;
1803 :
1804 49 : bNoDataSet = TRUE;
1805 49 : dfNoDataValue = dfNoData;
1806 49 : return CE_None;
1807 : }
1808 :
1809 : /************************************************************************/
1810 : /* NullBlock() */
1811 : /* */
1812 : /* Set the block data to the null value if it is set, or zero */
1813 : /* if there is no null data value. */
1814 : /************************************************************************/
1815 :
1816 13289 : void GTiffRasterBand::NullBlock( void *pData )
1817 :
1818 : {
1819 13289 : int nWords = nBlockXSize * nBlockYSize;
1820 13289 : int nChunkSize = MAX(1,GDALGetDataTypeSize(eDataType)/8);
1821 :
1822 : int bNoDataSet;
1823 13289 : double dfNoData = GetNoDataValue( &bNoDataSet );
1824 13289 : if( !bNoDataSet )
1825 : {
1826 : #ifdef ESRI_BUILD
1827 : if ( poGDS->nBitsPerSample >= 2 )
1828 : memset( pData, 0, nWords*nChunkSize );
1829 : else
1830 : memset( pData, 1, nWords*nChunkSize );
1831 : #else
1832 13198 : memset( pData, 0, nWords*nChunkSize );
1833 : #endif
1834 : }
1835 : else
1836 : {
1837 : /* Will convert nodata value to the right type and copy efficiently */
1838 : GDALCopyWords( &dfNoData, GDT_Float64, 0,
1839 91 : pData, eDataType, nChunkSize, nWords);
1840 : }
1841 13289 : }
1842 :
1843 : /************************************************************************/
1844 : /* GetOverviewCount() */
1845 : /************************************************************************/
1846 :
1847 301307 : int GTiffRasterBand::GetOverviewCount()
1848 :
1849 : {
1850 301307 : poGDS->ScanDirectories();
1851 :
1852 301307 : if( poGDS->nOverviewCount > 0 )
1853 1016 : return poGDS->nOverviewCount;
1854 : else
1855 300291 : return GDALRasterBand::GetOverviewCount();
1856 : }
1857 :
1858 : /************************************************************************/
1859 : /* GetOverview() */
1860 : /************************************************************************/
1861 :
1862 1126 : GDALRasterBand *GTiffRasterBand::GetOverview( int i )
1863 :
1864 : {
1865 1126 : poGDS->ScanDirectories();
1866 :
1867 1126 : if( poGDS->nOverviewCount > 0 )
1868 : {
1869 842 : if( i < 0 || i >= poGDS->nOverviewCount )
1870 0 : return NULL;
1871 : else
1872 842 : return poGDS->papoOverviewDS[i]->GetRasterBand(nBand);
1873 : }
1874 : else
1875 284 : return GDALRasterBand::GetOverview( i );
1876 : }
1877 :
1878 : /************************************************************************/
1879 : /* GetMaskFlags() */
1880 : /************************************************************************/
1881 :
1882 3385 : int GTiffRasterBand::GetMaskFlags()
1883 : {
1884 3385 : poGDS->ScanDirectories();
1885 :
1886 3385 : if( poGDS->poMaskDS != NULL )
1887 : {
1888 51 : if( poGDS->poMaskDS->GetRasterCount() == 1)
1889 : {
1890 45 : return GMF_PER_DATASET;
1891 : }
1892 : else
1893 : {
1894 6 : return 0;
1895 : }
1896 : }
1897 : else
1898 3334 : return GDALPamRasterBand::GetMaskFlags();
1899 : }
1900 :
1901 : /************************************************************************/
1902 : /* GetMaskBand() */
1903 : /************************************************************************/
1904 :
1905 2491 : GDALRasterBand *GTiffRasterBand::GetMaskBand()
1906 : {
1907 2491 : poGDS->ScanDirectories();
1908 :
1909 2491 : if( poGDS->poMaskDS != NULL )
1910 : {
1911 1419 : if( poGDS->poMaskDS->GetRasterCount() == 1)
1912 1413 : return poGDS->poMaskDS->GetRasterBand(1);
1913 : else
1914 6 : return poGDS->poMaskDS->GetRasterBand(nBand);
1915 : }
1916 : else
1917 1072 : return GDALPamRasterBand::GetMaskBand();
1918 : }
1919 :
1920 : /************************************************************************/
1921 : /* ==================================================================== */
1922 : /* GTiffSplitBand */
1923 : /* ==================================================================== */
1924 : /************************************************************************/
1925 :
1926 : class GTiffSplitBand : public GTiffRasterBand
1927 : {
1928 : friend class GTiffDataset;
1929 :
1930 : public:
1931 :
1932 : GTiffSplitBand( GTiffDataset *, int );
1933 : virtual ~GTiffSplitBand();
1934 :
1935 : virtual CPLErr IReadBlock( int, int, void * );
1936 : virtual CPLErr IWriteBlock( int, int, void * );
1937 : };
1938 :
1939 : /************************************************************************/
1940 : /* GTiffSplitBand() */
1941 : /************************************************************************/
1942 :
1943 28 : GTiffSplitBand::GTiffSplitBand( GTiffDataset *poDS, int nBand )
1944 28 : : GTiffRasterBand( poDS, nBand )
1945 :
1946 : {
1947 28 : nBlockXSize = poDS->GetRasterXSize();
1948 28 : nBlockYSize = 1;
1949 28 : }
1950 :
1951 : /************************************************************************/
1952 : /* ~GTiffSplitBand() */
1953 : /************************************************************************/
1954 :
1955 28 : GTiffSplitBand::~GTiffSplitBand()
1956 : {
1957 28 : }
1958 :
1959 : /************************************************************************/
1960 : /* IReadBlock() */
1961 : /************************************************************************/
1962 :
1963 69856 : CPLErr GTiffSplitBand::IReadBlock( int nBlockXOff, int nBlockYOff,
1964 : void * pImage )
1965 :
1966 : {
1967 : (void) nBlockXOff;
1968 :
1969 : /* Optimization when reading the same line in a contig multi-band TIFF */
1970 69856 : if( poGDS->nPlanarConfig == PLANARCONFIG_CONTIG && poGDS->nBands > 1 &&
1971 : poGDS->nLastLineRead == nBlockYOff )
1972 : {
1973 9 : goto extract_band_data;
1974 : }
1975 :
1976 69847 : if (!poGDS->SetDirectory())
1977 0 : return CE_Failure;
1978 :
1979 109694 : if (poGDS->nPlanarConfig == PLANARCONFIG_CONTIG &&
1980 : poGDS->nBands > 1)
1981 : {
1982 39847 : if (poGDS->pabyBlockBuf == NULL)
1983 4 : poGDS->pabyBlockBuf = (GByte *) CPLMalloc(TIFFScanlineSize(poGDS->hTIFF));
1984 : }
1985 : else
1986 : {
1987 30000 : CPLAssert(TIFFScanlineSize(poGDS->hTIFF) == nBlockXSize);
1988 : }
1989 :
1990 : /* -------------------------------------------------------------------- */
1991 : /* Read through to target scanline. */
1992 : /* -------------------------------------------------------------------- */
1993 69847 : if( poGDS->nLastLineRead >= nBlockYOff )
1994 31 : poGDS->nLastLineRead = -1;
1995 :
1996 69847 : if( poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE && poGDS->nBands > 1 )
1997 : {
1998 : /* If we change of band, we must start reading the */
1999 : /* new strip from its beginning */
2000 30000 : if ( poGDS->nLastBandRead != nBand )
2001 20 : poGDS->nLastLineRead = -1;
2002 30000 : poGDS->nLastBandRead = nBand;
2003 : }
2004 :
2005 258854 : while( poGDS->nLastLineRead < nBlockYOff )
2006 : {
2007 119160 : if( TIFFReadScanline( poGDS->hTIFF,
2008 : poGDS->pabyBlockBuf ? poGDS->pabyBlockBuf : pImage,
2009 : ++poGDS->nLastLineRead,
2010 : (poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE) ? (uint16) (nBand-1) : 0 ) == -1
2011 : && !poGDS->bIgnoreReadErrors )
2012 : {
2013 : CPLError( CE_Failure, CPLE_AppDefined,
2014 0 : "TIFFReadScanline() failed." );
2015 0 : return CE_Failure;
2016 : }
2017 : }
2018 :
2019 : extract_band_data:
2020 : /* -------------------------------------------------------------------- */
2021 : /* Extract band data from contig buffer. */
2022 : /* -------------------------------------------------------------------- */
2023 69856 : if ( poGDS->pabyBlockBuf != NULL )
2024 : {
2025 39856 : int iPixel, iSrcOffset= nBand - 1, iDstOffset=0;
2026 :
2027 13947104 : for( iPixel = 0; iPixel < nBlockXSize; iPixel++, iSrcOffset+=poGDS->nBands, iDstOffset++ )
2028 : {
2029 13907248 : ((GByte *) pImage)[iDstOffset] = poGDS->pabyBlockBuf[iSrcOffset];
2030 : }
2031 : }
2032 :
2033 69856 : return CE_None;
2034 : }
2035 :
2036 : /************************************************************************/
2037 : /* IWriteBlock() */
2038 : /************************************************************************/
2039 :
2040 0 : CPLErr GTiffSplitBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
2041 : void * pImage )
2042 :
2043 : {
2044 : (void) nBlockXOff;
2045 : (void) nBlockYOff;
2046 : (void) pImage;
2047 :
2048 : CPLError( CE_Failure, CPLE_AppDefined,
2049 0 : "Split bands are read-only." );
2050 0 : return CE_Failure;
2051 : }
2052 :
2053 : /************************************************************************/
2054 : /* ==================================================================== */
2055 : /* GTiffRGBABand */
2056 : /* ==================================================================== */
2057 : /************************************************************************/
2058 :
2059 : class GTiffRGBABand : public GTiffRasterBand
2060 20 : {
2061 : friend class GTiffDataset;
2062 :
2063 : public:
2064 :
2065 : GTiffRGBABand( GTiffDataset *, int );
2066 :
2067 : virtual CPLErr IReadBlock( int, int, void * );
2068 : virtual CPLErr IWriteBlock( int, int, void * );
2069 :
2070 : virtual GDALColorInterp GetColorInterpretation();
2071 : };
2072 :
2073 :
2074 : /************************************************************************/
2075 : /* GTiffRGBABand() */
2076 : /************************************************************************/
2077 :
2078 20 : GTiffRGBABand::GTiffRGBABand( GTiffDataset *poDS, int nBand )
2079 20 : : GTiffRasterBand( poDS, nBand )
2080 :
2081 : {
2082 20 : eDataType = GDT_Byte;
2083 20 : }
2084 :
2085 : /************************************************************************/
2086 : /* IWriteBlock() */
2087 : /************************************************************************/
2088 :
2089 0 : CPLErr GTiffRGBABand::IWriteBlock( int, int, void * )
2090 :
2091 : {
2092 : CPLError( CE_Failure, CPLE_AppDefined,
2093 0 : "RGBA interpreted raster bands are read-only." );
2094 0 : return CE_Failure;
2095 : }
2096 :
2097 : /************************************************************************/
2098 : /* IReadBlock() */
2099 : /************************************************************************/
2100 :
2101 16 : CPLErr GTiffRGBABand::IReadBlock( int nBlockXOff, int nBlockYOff,
2102 : void * pImage )
2103 :
2104 : {
2105 : int nBlockBufSize, nBlockId;
2106 16 : CPLErr eErr = CE_None;
2107 :
2108 16 : if (!poGDS->SetDirectory())
2109 0 : return CE_Failure;
2110 :
2111 16 : CPLAssert(nBlocksPerRow != 0);
2112 16 : nBlockBufSize = 4 * nBlockXSize * nBlockYSize;
2113 16 : nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
2114 :
2115 : /* -------------------------------------------------------------------- */
2116 : /* Allocate a temporary buffer for this strip. */
2117 : /* -------------------------------------------------------------------- */
2118 16 : if( poGDS->pabyBlockBuf == NULL )
2119 : {
2120 3 : poGDS->pabyBlockBuf = (GByte *) VSIMalloc3( 4, nBlockXSize, nBlockYSize );
2121 3 : if( poGDS->pabyBlockBuf == NULL )
2122 0 : return( CE_Failure );
2123 : }
2124 :
2125 : /* -------------------------------------------------------------------- */
2126 : /* Read the strip */
2127 : /* -------------------------------------------------------------------- */
2128 16 : if( poGDS->nLoadedBlock != nBlockId )
2129 : {
2130 4 : if( TIFFIsTiled( poGDS->hTIFF ) )
2131 : {
2132 1 : if( TIFFReadRGBATile(poGDS->hTIFF,
2133 : nBlockXOff * nBlockXSize,
2134 : nBlockYOff * nBlockYSize,
2135 : (uint32 *) poGDS->pabyBlockBuf) == -1
2136 : && !poGDS->bIgnoreReadErrors )
2137 : {
2138 : /* Once TIFFError() is properly hooked, this can go away */
2139 : CPLError( CE_Failure, CPLE_AppDefined,
2140 0 : "TIFFReadRGBATile() failed." );
2141 :
2142 0 : memset( poGDS->pabyBlockBuf, 0, nBlockBufSize );
2143 :
2144 0 : eErr = CE_Failure;
2145 : }
2146 : }
2147 : else
2148 : {
2149 3 : if( TIFFReadRGBAStrip(poGDS->hTIFF,
2150 : nBlockId * nBlockYSize,
2151 : (uint32 *) poGDS->pabyBlockBuf) == -1
2152 : && !poGDS->bIgnoreReadErrors )
2153 : {
2154 : /* Once TIFFError() is properly hooked, this can go away */
2155 : CPLError( CE_Failure, CPLE_AppDefined,
2156 0 : "TIFFReadRGBAStrip() failed." );
2157 :
2158 0 : memset( poGDS->pabyBlockBuf, 0, nBlockBufSize );
2159 :
2160 0 : eErr = CE_Failure;
2161 : }
2162 : }
2163 : }
2164 :
2165 16 : poGDS->nLoadedBlock = nBlockId;
2166 :
2167 : /* -------------------------------------------------------------------- */
2168 : /* Handle simple case of eight bit data, and pixel interleaving. */
2169 : /* -------------------------------------------------------------------- */
2170 : int iDestLine, nBO;
2171 : int nThisBlockYSize;
2172 :
2173 16 : if( (nBlockYOff+1) * nBlockYSize > GetYSize()
2174 : && !TIFFIsTiled( poGDS->hTIFF ) )
2175 4 : nThisBlockYSize = GetYSize() - nBlockYOff * nBlockYSize;
2176 : else
2177 12 : nThisBlockYSize = nBlockYSize;
2178 :
2179 : #ifdef CPL_LSB
2180 16 : nBO = nBand - 1;
2181 : #else
2182 : nBO = 4 - nBand;
2183 : #endif
2184 :
2185 1116 : for( iDestLine = 0; iDestLine < nThisBlockYSize; iDestLine++ )
2186 : {
2187 : int nSrcOffset;
2188 :
2189 1100 : nSrcOffset = (nThisBlockYSize - iDestLine - 1) * nBlockXSize * 4;
2190 :
2191 : GDALCopyWords( poGDS->pabyBlockBuf + nBO + nSrcOffset, GDT_Byte, 4,
2192 : ((GByte *) pImage)+iDestLine*nBlockXSize, GDT_Byte, 1,
2193 1100 : nBlockXSize );
2194 : }
2195 :
2196 16 : if (eErr == CE_None)
2197 16 : eErr = FillCacheForOtherBands(nBlockXOff, nBlockYOff);
2198 :
2199 16 : return eErr;
2200 : }
2201 :
2202 : /************************************************************************/
2203 : /* GetColorInterpretation() */
2204 : /************************************************************************/
2205 :
2206 6 : GDALColorInterp GTiffRGBABand::GetColorInterpretation()
2207 :
2208 : {
2209 6 : if( nBand == 1 )
2210 2 : return GCI_RedBand;
2211 4 : else if( nBand == 2 )
2212 1 : return GCI_GreenBand;
2213 3 : else if( nBand == 3 )
2214 1 : return GCI_BlueBand;
2215 : else
2216 2 : return GCI_AlphaBand;
2217 : }
2218 :
2219 : /************************************************************************/
2220 : /* ==================================================================== */
2221 : /* GTiffOddBitsBand */
2222 : /* ==================================================================== */
2223 : /************************************************************************/
2224 :
2225 : class GTiffOddBitsBand : public GTiffRasterBand
2226 : {
2227 : friend class GTiffDataset;
2228 : public:
2229 :
2230 : GTiffOddBitsBand( GTiffDataset *, int );
2231 : virtual ~GTiffOddBitsBand();
2232 :
2233 : virtual CPLErr IReadBlock( int, int, void * );
2234 : virtual CPLErr IWriteBlock( int, int, void * );
2235 : };
2236 :
2237 :
2238 : /************************************************************************/
2239 : /* GTiffOddBitsBand() */
2240 : /************************************************************************/
2241 :
2242 383 : GTiffOddBitsBand::GTiffOddBitsBand( GTiffDataset *poGDS, int nBand )
2243 383 : : GTiffRasterBand( poGDS, nBand )
2244 :
2245 : {
2246 383 : eDataType = GDT_Byte;
2247 383 : if( poGDS->nSampleFormat == SAMPLEFORMAT_IEEEFP )
2248 2 : eDataType = GDT_Float32;
2249 478 : else if( poGDS->nBitsPerSample > 8 && poGDS->nBitsPerSample < 16 )
2250 97 : eDataType = GDT_UInt16;
2251 284 : else if( poGDS->nBitsPerSample > 16 )
2252 67 : eDataType = GDT_UInt32;
2253 383 : }
2254 :
2255 : /************************************************************************/
2256 : /* ~GTiffOddBitsBand() */
2257 : /************************************************************************/
2258 :
2259 383 : GTiffOddBitsBand::~GTiffOddBitsBand()
2260 :
2261 : {
2262 383 : }
2263 :
2264 : /************************************************************************/
2265 : /* IWriteBlock() */
2266 : /************************************************************************/
2267 :
2268 441 : CPLErr GTiffOddBitsBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
2269 : void *pImage )
2270 :
2271 : {
2272 : int nBlockId;
2273 441 : CPLErr eErr = CE_None;
2274 :
2275 441 : if (poGDS->bWriteErrorInFlushBlockBuf)
2276 : {
2277 : /* Report as an error if a previously loaded block couldn't be */
2278 : /* written correctly */
2279 0 : poGDS->bWriteErrorInFlushBlockBuf = FALSE;
2280 0 : return CE_Failure;
2281 : }
2282 :
2283 441 : if (!poGDS->SetDirectory())
2284 0 : return CE_Failure;
2285 :
2286 : CPLAssert( poGDS != NULL
2287 : && nBlockXOff >= 0
2288 : && nBlockYOff >= 0
2289 441 : && pImage != NULL );
2290 :
2291 441 : if( eDataType == GDT_Float32 && poGDS->nBitsPerSample < 32 )
2292 : {
2293 : CPLError(CE_Failure, CPLE_NotSupported,
2294 0 : "Writing float data with nBitsPerSample < 32 is unsupported");
2295 0 : return CE_Failure;
2296 : }
2297 :
2298 : /* -------------------------------------------------------------------- */
2299 : /* Load the block buffer. */
2300 : /* -------------------------------------------------------------------- */
2301 441 : CPLAssert(nBlocksPerRow != 0);
2302 441 : nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
2303 :
2304 441 : if( poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE )
2305 18 : nBlockId += (nBand-1) * poGDS->nBlocksPerBand;
2306 :
2307 : /* Only read content from disk in the CONTIG case */
2308 : eErr = poGDS->LoadBlockBuf( nBlockId,
2309 441 : poGDS->nPlanarConfig == PLANARCONFIG_CONTIG && poGDS->nBands > 1 );
2310 441 : if( eErr != CE_None )
2311 0 : return eErr;
2312 :
2313 441 : GUInt32 nMaxVal = (1 << poGDS->nBitsPerSample) - 1;
2314 :
2315 : /* -------------------------------------------------------------------- */
2316 : /* Handle case of "separate" images or single band images where */
2317 : /* no interleaving with other data is required. */
2318 : /* -------------------------------------------------------------------- */
2319 441 : if( poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE
2320 : || poGDS->nBands == 1 )
2321 : {
2322 425 : int iBit, iPixel, iBitOffset = 0;
2323 : int iX, iY, nBitsPerLine;
2324 :
2325 : // bits per line rounds up to next byte boundary.
2326 425 : nBitsPerLine = nBlockXSize * poGDS->nBitsPerSample;
2327 425 : if( (nBitsPerLine & 7) != 0 )
2328 35 : nBitsPerLine = (nBitsPerLine + 7) & (~7);
2329 :
2330 : /* Initialize to zero as we set the buffer with binary or operations */
2331 425 : if (poGDS->nBitsPerSample != 24)
2332 420 : memset(poGDS->pabyBlockBuf, 0, (nBitsPerLine / 8) * nBlockYSize);
2333 :
2334 425 : iPixel = 0;
2335 40759 : for( iY = 0; iY < nBlockYSize; iY++ )
2336 : {
2337 40334 : iBitOffset = iY * nBitsPerLine;
2338 :
2339 : /* Small optimization in 1 bit case */
2340 40334 : if (poGDS->nBitsPerSample == 1)
2341 : {
2342 18178763 : for( iX = 0; iX < nBlockXSize; iX++ )
2343 : {
2344 18139027 : if (((GByte *) pImage)[iPixel++])
2345 10262134 : poGDS->pabyBlockBuf[iBitOffset>>3] |= (0x80 >>(iBitOffset & 7));
2346 18139027 : iBitOffset++;
2347 : }
2348 :
2349 39736 : continue;
2350 : }
2351 :
2352 39368 : for( iX = 0; iX < nBlockXSize; iX++ )
2353 : {
2354 38770 : GUInt32 nInWord = 0;
2355 38770 : if( eDataType == GDT_Byte )
2356 400 : nInWord = ((GByte *) pImage)[iPixel++];
2357 38370 : else if( eDataType == GDT_UInt16 )
2358 35569 : nInWord = ((GUInt16 *) pImage)[iPixel++];
2359 2801 : else if( eDataType == GDT_UInt32 )
2360 2801 : nInWord = ((GUInt32 *) pImage)[iPixel++];
2361 : else
2362 0 : CPLAssert(0);
2363 :
2364 38770 : if (nInWord > nMaxVal)
2365 : {
2366 400 : nInWord = nMaxVal;
2367 400 : if( !poGDS->bClipWarn )
2368 : {
2369 1 : poGDS->bClipWarn = TRUE;
2370 : CPLError( CE_Warning, CPLE_AppDefined,
2371 1 : "One or more pixels clipped to fit %d bit domain.", poGDS->nBitsPerSample );
2372 : }
2373 : }
2374 :
2375 38770 : if (poGDS->nBitsPerSample == 24)
2376 : {
2377 : /* -------------------------------------------------------------------- */
2378 : /* Special case for 24bit data which is pre-byteswapped since */
2379 : /* the size falls on a byte boundary ... ugg (#2361). */
2380 : /* -------------------------------------------------------------------- */
2381 : #ifdef CPL_MSB
2382 : poGDS->pabyBlockBuf[(iBitOffset>>3) + 0] =
2383 : (GByte) nInWord;
2384 : poGDS->pabyBlockBuf[(iBitOffset>>3) + 1] =
2385 : (GByte) (nInWord >> 8);
2386 : poGDS->pabyBlockBuf[(iBitOffset>>3) + 2] =
2387 : (GByte) (nInWord >> 16);
2388 : #else
2389 1400 : poGDS->pabyBlockBuf[(iBitOffset>>3) + 0] =
2390 1400 : (GByte) (nInWord >> 16);
2391 1400 : poGDS->pabyBlockBuf[(iBitOffset>>3) + 1] =
2392 1400 : (GByte) (nInWord >> 8);
2393 1400 : poGDS->pabyBlockBuf[(iBitOffset>>3) + 2] =
2394 1400 : (GByte) nInWord;
2395 : #endif
2396 1400 : iBitOffset += 24;
2397 : }
2398 : else
2399 : {
2400 485812 : for( iBit = 0; iBit < poGDS->nBitsPerSample; iBit++ )
2401 : {
2402 448442 : if (nInWord & (1 << (poGDS->nBitsPerSample - 1 - iBit)))
2403 18485 : poGDS->pabyBlockBuf[iBitOffset>>3] |= (0x80 >>(iBitOffset & 7));
2404 448442 : iBitOffset++;
2405 : }
2406 : }
2407 : }
2408 : }
2409 :
2410 425 : poGDS->bLoadedBlockDirty = TRUE;
2411 :
2412 425 : return eErr;
2413 : }
2414 :
2415 : /* -------------------------------------------------------------------- */
2416 : /* Handle case of pixel interleaved (PLANARCONFIG_CONTIG) images. */
2417 : /* -------------------------------------------------------------------- */
2418 :
2419 : /* -------------------------------------------------------------------- */
2420 : /* On write of pixel interleaved data, we might as well flush */
2421 : /* out any other bands that are dirty in our cache. This is */
2422 : /* especially helpful when writing compressed blocks. */
2423 : /* -------------------------------------------------------------------- */
2424 : int iBand;
2425 :
2426 54 : for( iBand = 0; iBand < poGDS->nBands; iBand++ )
2427 : {
2428 38 : const GByte *pabyThisImage = NULL;
2429 38 : GDALRasterBlock *poBlock = NULL;
2430 38 : int iBit, iPixel, iBitOffset = 0;
2431 : int iPixelBitSkip, iBandBitOffset, iX, iY, nBitsPerLine;
2432 :
2433 38 : if( iBand+1 == nBand )
2434 16 : pabyThisImage = (GByte *) pImage;
2435 : else
2436 : {
2437 : poBlock = ((GTiffOddBitsBand *)poGDS->GetRasterBand( iBand+1 ))
2438 22 : ->TryGetLockedBlockRef( nBlockXOff, nBlockYOff );
2439 :
2440 22 : if( poBlock == NULL )
2441 10 : continue;
2442 :
2443 12 : if( !poBlock->GetDirty() )
2444 : {
2445 0 : poBlock->DropLock();
2446 0 : continue;
2447 : }
2448 :
2449 12 : pabyThisImage = (GByte *) poBlock->GetDataRef();
2450 : }
2451 :
2452 28 : iPixelBitSkip = poGDS->nBitsPerSample * poGDS->nBands;
2453 28 : iBandBitOffset = iBand * poGDS->nBitsPerSample;
2454 :
2455 : // bits per line rounds up to next byte boundary.
2456 28 : nBitsPerLine = nBlockXSize * iPixelBitSkip;
2457 28 : if( (nBitsPerLine & 7) != 0 )
2458 15 : nBitsPerLine = (nBitsPerLine + 7) & (~7);
2459 :
2460 28 : iPixel = 0;
2461 671 : for( iY = 0; iY < nBlockYSize; iY++ )
2462 : {
2463 643 : iBitOffset = iBandBitOffset + iY * nBitsPerLine;
2464 :
2465 22616 : for( iX = 0; iX < nBlockXSize; iX++ )
2466 : {
2467 21973 : GUInt32 nInWord = 0;
2468 21973 : if( eDataType == GDT_Byte )
2469 4085 : nInWord = ((GByte *) pabyThisImage)[iPixel++];
2470 17888 : else if( eDataType == GDT_UInt16 )
2471 15088 : nInWord = ((GUInt16 *) pabyThisImage)[iPixel++];
2472 2800 : else if( eDataType == GDT_UInt32 )
2473 2800 : nInWord = ((GUInt32 *) pabyThisImage)[iPixel++];
2474 : else
2475 0 : CPLAssert(0);
2476 :
2477 21973 : if (nInWord > nMaxVal)
2478 : {
2479 0 : nInWord = nMaxVal;
2480 0 : if( !poGDS->bClipWarn )
2481 : {
2482 0 : poGDS->bClipWarn = TRUE;
2483 : CPLError( CE_Warning, CPLE_AppDefined,
2484 0 : "One or more pixels clipped to fit %d bit domain.", poGDS->nBitsPerSample );
2485 : }
2486 : }
2487 :
2488 21973 : if (poGDS->nBitsPerSample == 24)
2489 : {
2490 : /* -------------------------------------------------------------------- */
2491 : /* Special case for 24bit data which is pre-byteswapped since */
2492 : /* the size falls on a byte boundary ... ugg (#2361). */
2493 : /* -------------------------------------------------------------------- */
2494 : #ifdef CPL_MSB
2495 : poGDS->pabyBlockBuf[(iBitOffset>>3) + 0] =
2496 : (GByte) nInWord;
2497 : poGDS->pabyBlockBuf[(iBitOffset>>3) + 1] =
2498 : (GByte) (nInWord >> 8);
2499 : poGDS->pabyBlockBuf[(iBitOffset>>3) + 2] =
2500 : (GByte) (nInWord >> 16);
2501 : #else
2502 1400 : poGDS->pabyBlockBuf[(iBitOffset>>3) + 0] =
2503 1400 : (GByte) (nInWord >> 16);
2504 1400 : poGDS->pabyBlockBuf[(iBitOffset>>3) + 1] =
2505 1400 : (GByte) (nInWord >> 8);
2506 1400 : poGDS->pabyBlockBuf[(iBitOffset>>3) + 2] =
2507 1400 : (GByte) nInWord;
2508 : #endif
2509 1400 : iBitOffset += 24;
2510 : }
2511 : else
2512 : {
2513 248624 : for( iBit = 0; iBit < poGDS->nBitsPerSample; iBit++ )
2514 : {
2515 228051 : if (nInWord & (1 << (poGDS->nBitsPerSample - 1 - iBit)))
2516 101895 : poGDS->pabyBlockBuf[iBitOffset>>3] |= (0x80 >>(iBitOffset & 7));
2517 : else
2518 : {
2519 : /* We must explictly unset the bit as we may update an existing block */
2520 126156 : poGDS->pabyBlockBuf[iBitOffset>>3] &= ~(0x80 >>(iBitOffset & 7));
2521 : }
2522 :
2523 228051 : iBitOffset++;
2524 : }
2525 : }
2526 :
2527 21973 : iBitOffset= iBitOffset + iPixelBitSkip - poGDS->nBitsPerSample;
2528 : }
2529 : }
2530 :
2531 28 : if( poBlock != NULL )
2532 : {
2533 12 : poBlock->MarkClean();
2534 12 : poBlock->DropLock();
2535 : }
2536 : }
2537 :
2538 16 : poGDS->bLoadedBlockDirty = TRUE;
2539 :
2540 16 : return CE_None;
2541 : }
2542 :
2543 : /************************************************************************/
2544 : /* IReadBlock() */
2545 : /************************************************************************/
2546 :
2547 815 : CPLErr GTiffOddBitsBand::IReadBlock( int nBlockXOff, int nBlockYOff,
2548 : void * pImage )
2549 :
2550 : {
2551 : int nBlockId;
2552 815 : CPLErr eErr = CE_None;
2553 :
2554 815 : if (!poGDS->SetDirectory())
2555 0 : return CE_Failure;
2556 :
2557 815 : CPLAssert(nBlocksPerRow != 0);
2558 815 : nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
2559 :
2560 815 : if( poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE )
2561 20 : nBlockId += (nBand-1) * poGDS->nBlocksPerBand;
2562 :
2563 : /* -------------------------------------------------------------------- */
2564 : /* Handle the case of a strip in a writable file that doesn't */
2565 : /* exist yet, but that we want to read. Just set to zeros and */
2566 : /* return. */
2567 : /* -------------------------------------------------------------------- */
2568 815 : if( !poGDS->IsBlockAvailable(nBlockId) )
2569 : {
2570 566 : NullBlock( pImage );
2571 566 : return CE_None;
2572 : }
2573 :
2574 : /* -------------------------------------------------------------------- */
2575 : /* Load the block buffer. */
2576 : /* -------------------------------------------------------------------- */
2577 249 : eErr = poGDS->LoadBlockBuf( nBlockId );
2578 249 : if( eErr != CE_None )
2579 0 : return eErr;
2580 :
2581 416 : if ( poGDS->nBitsPerSample == 1 && (poGDS->nBands == 1 || poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE ) )
2582 : {
2583 : /* -------------------------------------------------------------------- */
2584 : /* Translate 1bit data to eight bit. */
2585 : /* -------------------------------------------------------------------- */
2586 167 : int iDstOffset=0, iLine;
2587 167 : register GByte *pabyBlockBuf = poGDS->pabyBlockBuf;
2588 :
2589 17841 : for( iLine = 0; iLine < nBlockYSize; iLine++ )
2590 : {
2591 : int iSrcOffset, iPixel;
2592 :
2593 17674 : iSrcOffset = ((nBlockXSize+7) >> 3) * 8 * iLine;
2594 :
2595 17674 : GByte bSetVal = (poGDS->bPromoteTo8Bits) ? 255 : 1;
2596 :
2597 4724882 : for( iPixel = 0; iPixel < nBlockXSize; iPixel++, iSrcOffset++ )
2598 : {
2599 4707208 : if( pabyBlockBuf[iSrcOffset >>3] & (0x80 >> (iSrcOffset & 0x7)) )
2600 1534422 : ((GByte *) pImage)[iDstOffset++] = bSetVal;
2601 : else
2602 3172786 : ((GByte *) pImage)[iDstOffset++] = 0;
2603 : }
2604 : }
2605 : }
2606 : /* -------------------------------------------------------------------- */
2607 : /* Handle the case of 16- and 24-bit floating point data as per */
2608 : /* TIFF Technical Note 3. */
2609 : /* -------------------------------------------------------------------- */
2610 84 : else if( eDataType == GDT_Float32 && poGDS->nBitsPerSample < 32 )
2611 : {
2612 : int i, nBlockPixels, nWordBytes, iSkipBytes;
2613 : GByte *pabyImage;
2614 :
2615 2 : nWordBytes = poGDS->nBitsPerSample / 8;
2616 2 : pabyImage = poGDS->pabyBlockBuf + (nBand - 1) * nWordBytes;
2617 : iSkipBytes = ( poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE ) ?
2618 2 : nWordBytes : poGDS->nBands * nWordBytes;
2619 :
2620 2 : nBlockPixels = nBlockXSize * nBlockYSize;
2621 2 : if ( poGDS->nBitsPerSample == 16 )
2622 : {
2623 401 : for( i = 0; i < nBlockPixels; i++ )
2624 : {
2625 400 : ((GUInt32 *) pImage)[i] =
2626 400 : HalfToFloat( *((GUInt16 *)pabyImage) );
2627 400 : pabyImage += iSkipBytes;
2628 : }
2629 : }
2630 1 : else if ( poGDS->nBitsPerSample == 24 )
2631 : {
2632 401 : for( i = 0; i < nBlockPixels; i++ )
2633 : {
2634 : #ifdef CPL_MSB
2635 : ((GUInt32 *) pImage)[i] =
2636 : TripleToFloat( ((GUInt32)*(pabyImage + 0) << 16)
2637 : | ((GUInt32)*(pabyImage + 1) << 8)
2638 : | (GUInt32)*(pabyImage + 2) );
2639 : #else
2640 400 : ((GUInt32 *) pImage)[i] =
2641 : TripleToFloat( ((GUInt32)*(pabyImage + 2) << 16)
2642 : | ((GUInt32)*(pabyImage + 1) << 8)
2643 400 : | (GUInt32)*pabyImage );
2644 : #endif
2645 400 : pabyImage += iSkipBytes;
2646 : }
2647 : }
2648 : }
2649 :
2650 : /* -------------------------------------------------------------------- */
2651 : /* Special case for moving 12bit data somewhat more efficiently. */
2652 : /* -------------------------------------------------------------------- */
2653 80 : else if( poGDS->nBitsPerSample == 12 )
2654 : {
2655 20 : int iPixel, iBitOffset = 0;
2656 : int iPixelBitSkip, iBandBitOffset, iX, iY, nBitsPerLine;
2657 :
2658 20 : if( poGDS->nPlanarConfig == PLANARCONFIG_CONTIG )
2659 : {
2660 17 : iPixelBitSkip = poGDS->nBands * poGDS->nBitsPerSample;
2661 17 : iBandBitOffset = (nBand-1) * poGDS->nBitsPerSample;
2662 : }
2663 : else
2664 : {
2665 3 : iPixelBitSkip = poGDS->nBitsPerSample;
2666 3 : iBandBitOffset = 0;
2667 : }
2668 :
2669 : // bits per line rounds up to next byte boundary.
2670 20 : nBitsPerLine = nBlockXSize * iPixelBitSkip;
2671 20 : if( (nBitsPerLine & 7) != 0 )
2672 0 : nBitsPerLine = (nBitsPerLine + 7) & (~7);
2673 :
2674 20 : iPixel = 0;
2675 904 : for( iY = 0; iY < nBlockYSize; iY++ )
2676 : {
2677 884 : iBitOffset = iBandBitOffset + iY * nBitsPerLine;
2678 :
2679 65524 : for( iX = 0; iX < nBlockXSize; iX++ )
2680 : {
2681 64640 : int iByte = iBitOffset>>3;
2682 :
2683 64640 : if( (iBitOffset & 0x7) == 0 )
2684 : {
2685 : /* starting on byte boundary */
2686 :
2687 64840 : ((GUInt16 *) pImage)[iPixel++] =
2688 32420 : (poGDS->pabyBlockBuf[iByte] << 4)
2689 32420 : | (poGDS->pabyBlockBuf[iByte+1] >> 4);
2690 : }
2691 : else
2692 : {
2693 : /* starting off byte boundary */
2694 :
2695 64440 : ((GUInt16 *) pImage)[iPixel++] =
2696 32220 : ((poGDS->pabyBlockBuf[iByte] & 0xf) << 8)
2697 32220 : | (poGDS->pabyBlockBuf[iByte+1]);
2698 : }
2699 64640 : iBitOffset += iPixelBitSkip;
2700 : }
2701 : }
2702 : }
2703 :
2704 : /* -------------------------------------------------------------------- */
2705 : /* Special case for 24bit data which is pre-byteswapped since */
2706 : /* the size falls on a byte boundary ... ugg (#2361). */
2707 : /* -------------------------------------------------------------------- */
2708 60 : else if( poGDS->nBitsPerSample == 24 )
2709 : {
2710 : int iPixel;
2711 : int iPixelByteSkip, iBandByteOffset, iX, iY, nBytesPerLine;
2712 :
2713 11 : if( poGDS->nPlanarConfig == PLANARCONFIG_CONTIG )
2714 : {
2715 8 : iPixelByteSkip = (poGDS->nBands * poGDS->nBitsPerSample) / 8;
2716 8 : iBandByteOffset = ((nBand-1) * poGDS->nBitsPerSample) / 8;
2717 : }
2718 : else
2719 : {
2720 3 : iPixelByteSkip = poGDS->nBitsPerSample / 8;
2721 3 : iBandByteOffset = 0;
2722 : }
2723 :
2724 11 : nBytesPerLine = nBlockXSize * iPixelByteSkip;
2725 :
2726 11 : iPixel = 0;
2727 191 : for( iY = 0; iY < nBlockYSize; iY++ )
2728 : {
2729 : GByte *pabyImage =
2730 180 : poGDS->pabyBlockBuf + iBandByteOffset + iY * nBytesPerLine;
2731 :
2732 3380 : for( iX = 0; iX < nBlockXSize; iX++ )
2733 : {
2734 : #ifdef CPL_MSB
2735 : ((GUInt32 *) pImage)[iPixel++] =
2736 : ((GUInt32)*(pabyImage + 2) << 16)
2737 : | ((GUInt32)*(pabyImage + 1) << 8)
2738 : | (GUInt32)*(pabyImage + 0);
2739 : #else
2740 6400 : ((GUInt32 *) pImage)[iPixel++] =
2741 : ((GUInt32)*(pabyImage + 0) << 16)
2742 : | ((GUInt32)*(pabyImage + 1) << 8)
2743 3200 : | (GUInt32)*(pabyImage + 2);
2744 : #endif
2745 3200 : pabyImage += iPixelByteSkip;
2746 : }
2747 : }
2748 : }
2749 :
2750 : /* -------------------------------------------------------------------- */
2751 : /* Handle 1-32 bit integer data. */
2752 : /* -------------------------------------------------------------------- */
2753 : else
2754 : {
2755 49 : int iBit, iPixel, iBitOffset = 0;
2756 : int iPixelBitSkip, iBandBitOffset, iX, iY, nBitsPerLine;
2757 :
2758 49 : if( poGDS->nPlanarConfig == PLANARCONFIG_CONTIG )
2759 : {
2760 43 : iPixelBitSkip = poGDS->nBands * poGDS->nBitsPerSample;
2761 43 : iBandBitOffset = (nBand-1) * poGDS->nBitsPerSample;
2762 : }
2763 : else
2764 : {
2765 6 : iPixelBitSkip = poGDS->nBitsPerSample;
2766 6 : iBandBitOffset = 0;
2767 : }
2768 :
2769 : // bits per line rounds up to next byte boundary.
2770 49 : nBitsPerLine = nBlockXSize * iPixelBitSkip;
2771 49 : if( (nBitsPerLine & 7) != 0 )
2772 48 : nBitsPerLine = (nBitsPerLine + 7) & (~7);
2773 :
2774 49 : register GByte *pabyBlockBuf = poGDS->pabyBlockBuf;
2775 49 : iPixel = 0;
2776 :
2777 2285 : for( iY = 0; iY < nBlockYSize; iY++ )
2778 : {
2779 2236 : iBitOffset = iBandBitOffset + iY * nBitsPerLine;
2780 :
2781 180540 : for( iX = 0; iX < nBlockXSize; iX++ )
2782 : {
2783 178304 : int nOutWord = 0;
2784 :
2785 452342 : for( iBit = 0; iBit < poGDS->nBitsPerSample; iBit++ )
2786 : {
2787 274038 : if( pabyBlockBuf[iBitOffset>>3]
2788 : & (0x80 >>(iBitOffset & 7)) )
2789 137696 : nOutWord |= (1 << (poGDS->nBitsPerSample - 1 - iBit));
2790 274038 : iBitOffset++;
2791 : }
2792 :
2793 178304 : iBitOffset= iBitOffset + iPixelBitSkip - poGDS->nBitsPerSample;
2794 :
2795 178304 : if( eDataType == GDT_Byte )
2796 172302 : ((GByte *) pImage)[iPixel++] = (GByte) nOutWord;
2797 6002 : else if( eDataType == GDT_UInt16 )
2798 3201 : ((GUInt16 *) pImage)[iPixel++] = (GUInt16) nOutWord;
2799 2801 : else if( eDataType == GDT_UInt32 )
2800 2801 : ((GUInt32 *) pImage)[iPixel++] = nOutWord;
2801 : else
2802 0 : CPLAssert(0);
2803 : }
2804 : }
2805 : }
2806 :
2807 249 : return CE_None;
2808 : }
2809 :
2810 :
2811 : /************************************************************************/
2812 : /* ==================================================================== */
2813 : /* GTiffBitmapBand */
2814 : /* ==================================================================== */
2815 : /************************************************************************/
2816 :
2817 : class GTiffBitmapBand : public GTiffOddBitsBand
2818 : {
2819 : friend class GTiffDataset;
2820 :
2821 : GDALColorTable *poColorTable;
2822 :
2823 : public:
2824 :
2825 : GTiffBitmapBand( GTiffDataset *, int );
2826 : virtual ~GTiffBitmapBand();
2827 :
2828 : virtual GDALColorInterp GetColorInterpretation();
2829 : virtual GDALColorTable *GetColorTable();
2830 : };
2831 :
2832 :
2833 : /************************************************************************/
2834 : /* GTiffBitmapBand() */
2835 : /************************************************************************/
2836 :
2837 129 : GTiffBitmapBand::GTiffBitmapBand( GTiffDataset *poDS, int nBand )
2838 129 : : GTiffOddBitsBand( poDS, nBand )
2839 :
2840 : {
2841 129 : eDataType = GDT_Byte;
2842 :
2843 129 : if( poDS->poColorTable != NULL )
2844 17 : poColorTable = poDS->poColorTable->Clone();
2845 : else
2846 : {
2847 : #ifdef ESRI_BUILD
2848 : poColorTable = NULL;
2849 : #else
2850 : GDALColorEntry oWhite, oBlack;
2851 :
2852 112 : oWhite.c1 = 255;
2853 112 : oWhite.c2 = 255;
2854 112 : oWhite.c3 = 255;
2855 112 : oWhite.c4 = 255;
2856 :
2857 112 : oBlack.c1 = 0;
2858 112 : oBlack.c2 = 0;
2859 112 : oBlack.c3 = 0;
2860 112 : oBlack.c4 = 255;
2861 :
2862 112 : poColorTable = new GDALColorTable();
2863 :
2864 112 : if( poDS->nPhotometric == PHOTOMETRIC_MINISWHITE )
2865 : {
2866 0 : poColorTable->SetColorEntry( 0, &oWhite );
2867 0 : poColorTable->SetColorEntry( 1, &oBlack );
2868 : }
2869 : else
2870 : {
2871 112 : poColorTable->SetColorEntry( 0, &oBlack );
2872 112 : poColorTable->SetColorEntry( 1, &oWhite );
2873 : }
2874 : #endif /* not defined ESRI_BUILD */
2875 : }
2876 129 : }
2877 :
2878 : /************************************************************************/
2879 : /* ~GTiffBitmapBand() */
2880 : /************************************************************************/
2881 :
2882 129 : GTiffBitmapBand::~GTiffBitmapBand()
2883 :
2884 : {
2885 129 : delete poColorTable;
2886 129 : }
2887 :
2888 : /************************************************************************/
2889 : /* GetColorInterpretation() */
2890 : /************************************************************************/
2891 :
2892 21 : GDALColorInterp GTiffBitmapBand::GetColorInterpretation()
2893 :
2894 : {
2895 21 : if (poGDS->bPromoteTo8Bits)
2896 13 : return GCI_Undefined;
2897 : else
2898 8 : return GCI_PaletteIndex;
2899 : }
2900 :
2901 : /************************************************************************/
2902 : /* GetColorTable() */
2903 : /************************************************************************/
2904 :
2905 12 : GDALColorTable *GTiffBitmapBand::GetColorTable()
2906 :
2907 : {
2908 12 : if (poGDS->bPromoteTo8Bits)
2909 0 : return NULL;
2910 : else
2911 12 : return poColorTable;
2912 : }
2913 :
2914 : /************************************************************************/
2915 : /* ==================================================================== */
2916 : /* GTiffSplitBitmapBand */
2917 : /* ==================================================================== */
2918 : /************************************************************************/
2919 :
2920 : class GTiffSplitBitmapBand : public GTiffBitmapBand
2921 : {
2922 : friend class GTiffDataset;
2923 :
2924 : public:
2925 :
2926 : GTiffSplitBitmapBand( GTiffDataset *, int );
2927 : virtual ~GTiffSplitBitmapBand();
2928 :
2929 : virtual CPLErr IReadBlock( int, int, void * );
2930 : virtual CPLErr IWriteBlock( int, int, void * );
2931 : };
2932 :
2933 :
2934 : /************************************************************************/
2935 : /* GTiffSplitBitmapBand() */
2936 : /************************************************************************/
2937 :
2938 4 : GTiffSplitBitmapBand::GTiffSplitBitmapBand( GTiffDataset *poDS, int nBand )
2939 4 : : GTiffBitmapBand( poDS, nBand )
2940 :
2941 : {
2942 4 : nBlockXSize = poDS->GetRasterXSize();
2943 4 : nBlockYSize = 1;
2944 4 : }
2945 :
2946 : /************************************************************************/
2947 : /* ~GTiffSplitBitmapBand() */
2948 : /************************************************************************/
2949 :
2950 4 : GTiffSplitBitmapBand::~GTiffSplitBitmapBand()
2951 :
2952 : {
2953 4 : }
2954 :
2955 :
2956 : /************************************************************************/
2957 : /* IReadBlock() */
2958 : /************************************************************************/
2959 :
2960 21600 : CPLErr GTiffSplitBitmapBand::IReadBlock( int nBlockXOff, int nBlockYOff,
2961 : void * pImage )
2962 :
2963 : {
2964 : (void) nBlockXOff;
2965 :
2966 21600 : if (!poGDS->SetDirectory())
2967 0 : return CE_Failure;
2968 :
2969 21600 : if (poGDS->pabyBlockBuf == NULL)
2970 3 : poGDS->pabyBlockBuf = (GByte *) CPLMalloc(TIFFScanlineSize(poGDS->hTIFF));
2971 :
2972 : /* -------------------------------------------------------------------- */
2973 : /* Read through to target scanline. */
2974 : /* -------------------------------------------------------------------- */
2975 21600 : if( poGDS->nLastLineRead >= nBlockYOff )
2976 0 : poGDS->nLastLineRead = -1;
2977 :
2978 64800 : while( poGDS->nLastLineRead < nBlockYOff )
2979 : {
2980 21600 : if( TIFFReadScanline( poGDS->hTIFF, poGDS->pabyBlockBuf, ++poGDS->nLastLineRead, 0 ) == -1
2981 : && !poGDS->bIgnoreReadErrors )
2982 : {
2983 : CPLError( CE_Failure, CPLE_AppDefined,
2984 0 : "TIFFReadScanline() failed." );
2985 0 : return CE_Failure;
2986 : }
2987 : }
2988 :
2989 : /* -------------------------------------------------------------------- */
2990 : /* Translate 1bit data to eight bit. */
2991 : /* -------------------------------------------------------------------- */
2992 21600 : int iPixel, iSrcOffset=0, iDstOffset=0;
2993 :
2994 21621600 : for( iPixel = 0; iPixel < nBlockXSize; iPixel++, iSrcOffset++ )
2995 : {
2996 21600000 : if( poGDS->pabyBlockBuf[iSrcOffset >>3] & (0x80 >> (iSrcOffset & 0x7)) )
2997 21243630 : ((GByte *) pImage)[iDstOffset++] = 1;
2998 : else
2999 356370 : ((GByte *) pImage)[iDstOffset++] = 0;
3000 : }
3001 :
3002 21600 : return CE_None;
3003 : }
3004 :
3005 : /************************************************************************/
3006 : /* IWriteBlock() */
3007 : /************************************************************************/
3008 :
3009 0 : CPLErr GTiffSplitBitmapBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
3010 : void * pImage )
3011 :
3012 : {
3013 : (void) nBlockXOff;
3014 : (void) nBlockYOff;
3015 : (void) pImage;
3016 :
3017 : CPLError( CE_Failure, CPLE_AppDefined,
3018 0 : "Split bitmap bands are read-only." );
3019 0 : return CE_Failure;
3020 : }
3021 :
3022 : /************************************************************************/
3023 : /* ==================================================================== */
3024 : /* GTiffDataset */
3025 : /* ==================================================================== */
3026 : /************************************************************************/
3027 :
3028 :
3029 : /************************************************************************/
3030 : /* GTiffDataset() */
3031 : /************************************************************************/
3032 :
3033 5247 : GTiffDataset::GTiffDataset()
3034 :
3035 : {
3036 5247 : nLoadedBlock = -1;
3037 5247 : bLoadedBlockDirty = FALSE;
3038 5247 : pabyBlockBuf = NULL;
3039 5247 : bWriteErrorInFlushBlockBuf = FALSE;
3040 5247 : hTIFF = NULL;
3041 5247 : bNeedsRewrite = FALSE;
3042 5247 : bMetadataChanged = FALSE;
3043 5247 : bGeoTIFFInfoChanged = FALSE;
3044 5247 : bCrystalized = TRUE;
3045 5247 : poColorTable = NULL;
3046 5247 : bNoDataSet = FALSE;
3047 5247 : dfNoDataValue = -9999.0;
3048 5247 : pszProjection = CPLStrdup("");
3049 5247 : bLookedForProjection = FALSE;
3050 5247 : bLookedForMDAreaOrPoint = FALSE;
3051 5247 : bBase = TRUE;
3052 5247 : bCloseTIFFHandle = FALSE;
3053 5247 : bTreatAsRGBA = FALSE;
3054 5247 : nOverviewCount = 0;
3055 5247 : papoOverviewDS = NULL;
3056 5247 : nDirOffset = 0;
3057 5247 : poActiveDS = NULL;
3058 5247 : ppoActiveDSRef = NULL;
3059 :
3060 5247 : bGeoTransformValid = FALSE;
3061 5247 : adfGeoTransform[0] = 0.0;
3062 5247 : adfGeoTransform[1] = 1.0;
3063 5247 : adfGeoTransform[2] = 0.0;
3064 5247 : adfGeoTransform[3] = 0.0;
3065 5247 : adfGeoTransform[4] = 0.0;
3066 5247 : adfGeoTransform[5] = 1.0;
3067 :
3068 5247 : nGCPCount = 0;
3069 5247 : pasGCPList = NULL;
3070 :
3071 5247 : osProfile = "GDALGeoTIFF";
3072 :
3073 5247 : papszCreationOptions = NULL;
3074 :
3075 5247 : nTempWriteBufferSize = 0;
3076 5247 : pabyTempWriteBuffer = NULL;
3077 :
3078 5247 : poMaskDS = NULL;
3079 5247 : poBaseDS = NULL;
3080 :
3081 5247 : bFillEmptyTiles = FALSE;
3082 5247 : bLoadingOtherBands = FALSE;
3083 5247 : nLastLineRead = -1;
3084 5247 : nLastBandRead = -1;
3085 5247 : bTreatAsSplit = FALSE;
3086 5247 : bTreatAsSplitBitmap = FALSE;
3087 5247 : bClipWarn = FALSE;
3088 5247 : bHasWarnedDisableAggressiveBandCaching = FALSE;
3089 5247 : bDontReloadFirstBlock = FALSE;
3090 :
3091 5247 : nZLevel = -1;
3092 5247 : nLZMAPreset = -1;
3093 5247 : nJpegQuality = -1;
3094 :
3095 5247 : bPromoteTo8Bits = FALSE;
3096 :
3097 5247 : bDebugDontWriteBlocks = CSLTestBoolean(CPLGetConfigOption("GTIFF_DONT_WRITE_BLOCKS", "NO"));
3098 :
3099 5247 : bIsFinalized = FALSE;
3100 5247 : bIgnoreReadErrors = CSLTestBoolean(CPLGetConfigOption("GTIFF_IGNORE_READ_ERRORS", "NO"));
3101 :
3102 5247 : bHasSearchedRPC = FALSE;
3103 5247 : bHasSearchedIMD = FALSE;
3104 5247 : bHasSearchedPVL = FALSE;
3105 5247 : bEXIFMetadataLoaded = FALSE;
3106 :
3107 5247 : bScanDeferred = TRUE;
3108 :
3109 5247 : bDirectIO = CSLTestBoolean(CPLGetConfigOption("GTIFF_DIRECT_IO", "NO"));
3110 5247 : }
3111 :
3112 : /************************************************************************/
3113 : /* ~GTiffDataset() */
3114 : /************************************************************************/
3115 :
3116 5247 : GTiffDataset::~GTiffDataset()
3117 :
3118 : {
3119 5247 : Finalize();
3120 5247 : }
3121 :
3122 : /************************************************************************/
3123 : /* Finalize() */
3124 : /************************************************************************/
3125 :
3126 5251 : int GTiffDataset::Finalize()
3127 : {
3128 5251 : if (bIsFinalized)
3129 4 : return FALSE;
3130 :
3131 5247 : int bHasDroppedRef = FALSE;
3132 :
3133 5247 : Crystalize();
3134 :
3135 : /* -------------------------------------------------------------------- */
3136 : /* Handle forcing xml:ESRI data to be written to PAM. */
3137 : /* -------------------------------------------------------------------- */
3138 5247 : if( CSLTestBoolean(CPLGetConfigOption( "ESRI_XML_PAM", "NO" )) )
3139 : {
3140 7 : char **papszESRIMD = GetMetadata("xml:ESRI");
3141 7 : if( papszESRIMD )
3142 : {
3143 5 : GDALPamDataset::SetMetadata( papszESRIMD, "xml:ESRI");
3144 : }
3145 : }
3146 :
3147 : /* -------------------------------------------------------------------- */
3148 : /* Ensure any blocks write cached by GDAL gets pushed through libtiff.*/
3149 : /* -------------------------------------------------------------------- */
3150 5247 : GDALPamDataset::FlushCache();
3151 :
3152 : /* -------------------------------------------------------------------- */
3153 : /* Fill in missing blocks with empty data. */
3154 : /* -------------------------------------------------------------------- */
3155 5247 : if( bFillEmptyTiles )
3156 : {
3157 952 : FillEmptyTiles();
3158 952 : bFillEmptyTiles = FALSE;
3159 : }
3160 :
3161 : /* -------------------------------------------------------------------- */
3162 : /* Force a complete flush, including either rewriting(moving) */
3163 : /* of writing in place the current directory. */
3164 : /* -------------------------------------------------------------------- */
3165 5247 : FlushCache();
3166 :
3167 : /* -------------------------------------------------------------------- */
3168 : /* If there is still changed metadata, then presumably we want */
3169 : /* to push it into PAM. */
3170 : /* -------------------------------------------------------------------- */
3171 5247 : if( bMetadataChanged )
3172 : {
3173 31 : PushMetadataToPam();
3174 31 : bMetadataChanged = FALSE;
3175 31 : GDALPamDataset::FlushCache();
3176 : }
3177 :
3178 : /* -------------------------------------------------------------------- */
3179 : /* Cleanup overviews. */
3180 : /* -------------------------------------------------------------------- */
3181 5247 : if( bBase )
3182 : {
3183 5131 : for( int i = 0; i < nOverviewCount; i++ )
3184 : {
3185 274 : delete papoOverviewDS[i];
3186 274 : bHasDroppedRef = TRUE;
3187 : }
3188 4857 : nOverviewCount = 0;
3189 : }
3190 :
3191 : /* If we are a mask dataset, we can have overviews, but we don't */
3192 : /* own them. We can only free the array, not the overviews themselves */
3193 5247 : CPLFree( papoOverviewDS );
3194 5247 : papoOverviewDS = NULL;
3195 :
3196 : /* poMaskDS is owned by the main image and the overviews */
3197 : /* so because of the latter case, we can delete it even if */
3198 : /* we are not the base image */
3199 5247 : if (poMaskDS)
3200 : {
3201 108 : delete poMaskDS;
3202 108 : poMaskDS = NULL;
3203 108 : bHasDroppedRef = TRUE;
3204 : }
3205 :
3206 5247 : if( poColorTable != NULL )
3207 98 : delete poColorTable;
3208 5247 : poColorTable = NULL;
3209 :
3210 5247 : if( bBase || bCloseTIFFHandle )
3211 : {
3212 4863 : XTIFFClose( hTIFF );
3213 4863 : hTIFF = NULL;
3214 : }
3215 :
3216 5247 : if( nGCPCount > 0 )
3217 : {
3218 29 : GDALDeinitGCPs( nGCPCount, pasGCPList );
3219 29 : CPLFree( pasGCPList );
3220 29 : pasGCPList = NULL;
3221 29 : nGCPCount = 0;
3222 : }
3223 :
3224 5247 : CPLFree( pszProjection );
3225 5247 : pszProjection = NULL;
3226 :
3227 5247 : CSLDestroy( papszCreationOptions );
3228 5247 : papszCreationOptions = NULL;
3229 :
3230 5247 : CPLFree(pabyTempWriteBuffer);
3231 5247 : pabyTempWriteBuffer = NULL;
3232 :
3233 5247 : if( *ppoActiveDSRef == this )
3234 4975 : *ppoActiveDSRef = NULL;
3235 5247 : ppoActiveDSRef = NULL;
3236 :
3237 5247 : bIsFinalized = TRUE;
3238 :
3239 5247 : return bHasDroppedRef;
3240 : }
3241 :
3242 : /************************************************************************/
3243 : /* CloseDependentDatasets() */
3244 : /************************************************************************/
3245 :
3246 4 : int GTiffDataset::CloseDependentDatasets()
3247 : {
3248 4 : if (!bBase)
3249 0 : return FALSE;
3250 :
3251 4 : int bHasDroppedRef = GDALPamDataset::CloseDependentDatasets();
3252 :
3253 4 : bHasDroppedRef |= Finalize();
3254 :
3255 4 : return bHasDroppedRef;
3256 : }
3257 :
3258 : /************************************************************************/
3259 : /* FillEmptyTiles() */
3260 : /************************************************************************/
3261 :
3262 952 : void GTiffDataset::FillEmptyTiles()
3263 :
3264 : {
3265 952 : toff_t *panByteCounts = NULL;
3266 : int nBlockCount, iBlock;
3267 :
3268 952 : if (!SetDirectory())
3269 0 : return;
3270 :
3271 : /* -------------------------------------------------------------------- */
3272 : /* How many blocks are there in this file? */
3273 : /* -------------------------------------------------------------------- */
3274 952 : if( nPlanarConfig == PLANARCONFIG_SEPARATE )
3275 7 : nBlockCount = nBlocksPerBand * nBands;
3276 : else
3277 945 : nBlockCount = nBlocksPerBand;
3278 :
3279 : /* -------------------------------------------------------------------- */
3280 : /* Fetch block maps. */
3281 : /* -------------------------------------------------------------------- */
3282 952 : if( TIFFIsTiled( hTIFF ) )
3283 19 : TIFFGetField( hTIFF, TIFFTAG_TILEBYTECOUNTS, &panByteCounts );
3284 : else
3285 933 : TIFFGetField( hTIFF, TIFFTAG_STRIPBYTECOUNTS, &panByteCounts );
3286 :
3287 952 : if (panByteCounts == NULL)
3288 : {
3289 : /* Got here with libtiff 3.9.3 and tiff_write_8 test */
3290 0 : CPLError(CE_Failure, CPLE_AppDefined, "FillEmptyTiles() failed because panByteCounts == NULL");
3291 0 : return;
3292 : }
3293 :
3294 : /* -------------------------------------------------------------------- */
3295 : /* Prepare a blank data buffer to write for uninitialized blocks. */
3296 : /* -------------------------------------------------------------------- */
3297 : int nBlockBytes;
3298 :
3299 952 : if( TIFFIsTiled( hTIFF ) )
3300 19 : nBlockBytes = TIFFTileSize(hTIFF);
3301 : else
3302 933 : nBlockBytes = TIFFStripSize(hTIFF);
3303 :
3304 952 : GByte *pabyData = (GByte *) VSICalloc(nBlockBytes,1);
3305 952 : if (pabyData == NULL)
3306 : {
3307 : CPLError(CE_Failure, CPLE_OutOfMemory,
3308 0 : "Cannot allocate %d bytes", nBlockBytes);
3309 0 : return;
3310 : }
3311 :
3312 : /* -------------------------------------------------------------------- */
3313 : /* Check all blocks, writing out data for uninitialized blocks. */
3314 : /* -------------------------------------------------------------------- */
3315 100583 : for( iBlock = 0; iBlock < nBlockCount; iBlock++ )
3316 : {
3317 99631 : if( panByteCounts[iBlock] == 0 )
3318 : {
3319 88350 : if( WriteEncodedTileOrStrip( iBlock, pabyData, FALSE ) != CE_None )
3320 0 : break;
3321 : }
3322 : }
3323 :
3324 952 : CPLFree( pabyData );
3325 : }
3326 :
3327 : /************************************************************************/
3328 : /* WriteEncodedTile() */
3329 : /************************************************************************/
3330 :
3331 9797 : int GTiffDataset::WriteEncodedTile(uint32 tile, GByte *pabyData,
3332 : int bPreserveDataBuffer)
3333 : {
3334 9797 : int cc = TIFFTileSize( hTIFF );
3335 9797 : int bNeedTileFill = FALSE;
3336 9797 : int iRow=0, iColumn=0;
3337 9797 : int nBlocksPerRow=1, nBlocksPerColumn=1;
3338 :
3339 : /*
3340 : ** Do we need to spread edge values right or down for a partial
3341 : ** JPEG encoded tile? We do this to avoid edge artifacts.
3342 : */
3343 9797 : if( nCompression == COMPRESSION_JPEG )
3344 : {
3345 350 : nBlocksPerRow = DIV_ROUND_UP(nRasterXSize, nBlockXSize);
3346 350 : nBlocksPerColumn = DIV_ROUND_UP(nRasterYSize, nBlockYSize);
3347 :
3348 350 : iColumn = (tile % nBlocksPerBand) % nBlocksPerRow;
3349 350 : iRow = (tile % nBlocksPerBand) / nBlocksPerRow;
3350 :
3351 : // Is this a partial right edge tile?
3352 350 : if( iRow == nBlocksPerRow - 1
3353 : && nRasterXSize % nBlockXSize != 0 )
3354 27 : bNeedTileFill = TRUE;
3355 :
3356 : // Is this a partial bottom edge tile?
3357 350 : if( iColumn == nBlocksPerColumn - 1
3358 : && nRasterYSize % nBlockYSize != 0 )
3359 37 : bNeedTileFill = TRUE;
3360 : }
3361 :
3362 : /*
3363 : ** If we need to fill out the tile, or if we want to prevent
3364 : ** TIFFWriteEncodedTile from altering the buffer as part of
3365 : ** byte swapping the data on write then we will need a temporary
3366 : ** working buffer. If not, we can just do a direct write.
3367 : */
3368 9797 : if (bPreserveDataBuffer
3369 : && (TIFFIsByteSwapped(hTIFF) || bNeedTileFill) )
3370 : {
3371 130 : if (cc != nTempWriteBufferSize)
3372 : {
3373 33 : pabyTempWriteBuffer = CPLRealloc(pabyTempWriteBuffer, cc);
3374 33 : nTempWriteBufferSize = cc;
3375 : }
3376 130 : memcpy(pabyTempWriteBuffer, pabyData, cc);
3377 :
3378 130 : pabyData = (GByte *) pabyTempWriteBuffer;
3379 : }
3380 :
3381 : /*
3382 : ** Perform tile fill if needed.
3383 : */
3384 9797 : if( bNeedTileFill )
3385 : {
3386 37 : int nRightPixelsToFill = 0;
3387 37 : int nBottomPixelsToFill = 0;
3388 37 : int nPixelSize = cc / (nBlockXSize * nBlockYSize);
3389 : unsigned int iX, iY, iSrcX, iSrcY;
3390 :
3391 37 : CPLDebug( "GTiff", "Filling out jpeg edge tile on write." );
3392 :
3393 37 : if( iColumn == nBlocksPerRow - 1 )
3394 27 : nRightPixelsToFill = nBlockXSize * (iColumn+1) - nRasterXSize;
3395 37 : if( iRow == nBlocksPerColumn - 1 )
3396 29 : nBottomPixelsToFill = nBlockYSize * (iRow+1) - nRasterYSize;
3397 :
3398 : // Fill out to the right.
3399 37 : iSrcX = nBlockXSize - nRightPixelsToFill - 1;
3400 :
3401 2033 : for( iX = iSrcX+1; iX < nBlockXSize; iX++ )
3402 : {
3403 257484 : for( iY = 0; iY < nBlockYSize; iY++ )
3404 : {
3405 : memcpy( pabyData + (nBlockXSize * iY + iX) * nPixelSize,
3406 : pabyData + (nBlockXSize * iY + iSrcX) * nPixelSize,
3407 255488 : nPixelSize );
3408 : }
3409 : }
3410 :
3411 : // now fill out the bottom.
3412 37 : iSrcY = nBlockYSize - nBottomPixelsToFill - 1;
3413 2173 : for( iY = iSrcY+1; iY < nBlockYSize; iY++ )
3414 : {
3415 : memcpy( pabyData + nBlockXSize * nPixelSize * iY,
3416 : pabyData + nBlockXSize * nPixelSize * iSrcY,
3417 2136 : nPixelSize * nBlockXSize );
3418 : }
3419 : }
3420 :
3421 9797 : return TIFFWriteEncodedTile(hTIFF, tile, pabyData, cc);
3422 : }
3423 :
3424 : /************************************************************************/
3425 : /* WriteEncodedStrip() */
3426 : /************************************************************************/
3427 :
3428 97425 : int GTiffDataset::WriteEncodedStrip(uint32 strip, GByte* pabyData,
3429 : int bPreserveDataBuffer)
3430 : {
3431 97425 : int cc = TIFFStripSize( hTIFF );
3432 :
3433 : /* -------------------------------------------------------------------- */
3434 : /* If this is the last strip in the image, and is partial, then */
3435 : /* we need to trim the number of scanlines written to the */
3436 : /* amount of valid data we have. (#2748) */
3437 : /* -------------------------------------------------------------------- */
3438 97425 : int nStripWithinBand = strip % nBlocksPerBand;
3439 :
3440 97425 : if( (int) ((nStripWithinBand+1) * nRowsPerStrip) > GetRasterYSize() )
3441 : {
3442 : cc = (cc / nRowsPerStrip)
3443 172 : * (GetRasterYSize() - nStripWithinBand * nRowsPerStrip);
3444 : CPLDebug( "GTiff", "Adjusted bytes to write from %d to %d.",
3445 172 : (int) TIFFStripSize(hTIFF), cc );
3446 : }
3447 :
3448 : /* -------------------------------------------------------------------- */
3449 : /* TIFFWriteEncodedStrip can alter the passed buffer if */
3450 : /* byte-swapping is necessary so we use a temporary buffer */
3451 : /* before calling it. */
3452 : /* -------------------------------------------------------------------- */
3453 97425 : if (bPreserveDataBuffer && TIFFIsByteSwapped(hTIFF))
3454 : {
3455 211 : if (cc != nTempWriteBufferSize)
3456 : {
3457 23 : pabyTempWriteBuffer = CPLRealloc(pabyTempWriteBuffer, cc);
3458 23 : nTempWriteBufferSize = cc;
3459 : }
3460 211 : memcpy(pabyTempWriteBuffer, pabyData, cc);
3461 211 : return TIFFWriteEncodedStrip(hTIFF, strip, pabyTempWriteBuffer, cc);
3462 : }
3463 : else
3464 97214 : return TIFFWriteEncodedStrip(hTIFF, strip, pabyData, cc);
3465 : }
3466 :
3467 : /************************************************************************/
3468 : /* WriteEncodedTileOrStrip() */
3469 : /************************************************************************/
3470 :
3471 107222 : CPLErr GTiffDataset::WriteEncodedTileOrStrip(uint32 tile_or_strip, void* data,
3472 : int bPreserveDataBuffer)
3473 : {
3474 107222 : CPLErr eErr = CE_None;
3475 :
3476 107222 : if( TIFFIsTiled( hTIFF ) )
3477 : {
3478 9797 : if( WriteEncodedTile(tile_or_strip, (GByte*) data,
3479 : bPreserveDataBuffer) == -1 )
3480 : {
3481 0 : eErr = CE_Failure;
3482 : }
3483 : }
3484 : else
3485 : {
3486 97425 : if( WriteEncodedStrip(tile_or_strip, (GByte *) data,
3487 : bPreserveDataBuffer) == -1 )
3488 : {
3489 0 : eErr = CE_Failure;
3490 : }
3491 : }
3492 :
3493 107222 : return eErr;
3494 : }
3495 :
3496 : /************************************************************************/
3497 : /* FlushBlockBuf() */
3498 : /************************************************************************/
3499 :
3500 225742 : CPLErr GTiffDataset::FlushBlockBuf()
3501 :
3502 : {
3503 225742 : CPLErr eErr = CE_None;
3504 :
3505 225742 : if( nLoadedBlock < 0 || !bLoadedBlockDirty )
3506 222689 : return CE_None;
3507 :
3508 3053 : bLoadedBlockDirty = FALSE;
3509 :
3510 3053 : if (!SetDirectory())
3511 0 : return CE_Failure;
3512 :
3513 3053 : eErr = WriteEncodedTileOrStrip(nLoadedBlock, pabyBlockBuf, TRUE);
3514 3053 : if (eErr != CE_None)
3515 : {
3516 : CPLError( CE_Failure, CPLE_AppDefined,
3517 0 : "WriteEncodedTile/Strip() failed." );
3518 0 : bWriteErrorInFlushBlockBuf = TRUE;
3519 : }
3520 :
3521 3053 : return eErr;
3522 : }
3523 :
3524 : /************************************************************************/
3525 : /* LoadBlockBuf() */
3526 : /* */
3527 : /* Load working block buffer with request block (tile/strip). */
3528 : /************************************************************************/
3529 :
3530 75643 : CPLErr GTiffDataset::LoadBlockBuf( int nBlockId, int bReadFromDisk )
3531 :
3532 : {
3533 : int nBlockBufSize;
3534 75643 : CPLErr eErr = CE_None;
3535 :
3536 75643 : if( nLoadedBlock == nBlockId )
3537 70332 : return CE_None;
3538 :
3539 : /* -------------------------------------------------------------------- */
3540 : /* If we have a dirty loaded block, flush it out first. */
3541 : /* -------------------------------------------------------------------- */
3542 5311 : if( nLoadedBlock != -1 && bLoadedBlockDirty )
3543 : {
3544 0 : eErr = FlushBlockBuf();
3545 0 : if( eErr != CE_None )
3546 0 : return eErr;
3547 : }
3548 :
3549 : /* -------------------------------------------------------------------- */
3550 : /* Get block size. */
3551 : /* -------------------------------------------------------------------- */
3552 5311 : if( TIFFIsTiled(hTIFF) )
3553 991 : nBlockBufSize = TIFFTileSize( hTIFF );
3554 : else
3555 4320 : nBlockBufSize = TIFFStripSize( hTIFF );
3556 :
3557 5311 : if ( !nBlockBufSize )
3558 : {
3559 : CPLError( CE_Failure, CPLE_AppDefined,
3560 0 : "Bogus block size; unable to allocate a buffer.");
3561 0 : return CE_Failure;
3562 : }
3563 :
3564 : /* -------------------------------------------------------------------- */
3565 : /* Allocate a temporary buffer for this strip. */
3566 : /* -------------------------------------------------------------------- */
3567 5311 : if( pabyBlockBuf == NULL )
3568 : {
3569 533 : pabyBlockBuf = (GByte *) VSICalloc( 1, nBlockBufSize );
3570 533 : if( pabyBlockBuf == NULL )
3571 : {
3572 : CPLError( CE_Failure, CPLE_OutOfMemory,
3573 : "Unable to allocate %d bytes for a temporary strip "
3574 : "buffer in GTIFF driver.",
3575 0 : nBlockBufSize );
3576 :
3577 0 : return( CE_Failure );
3578 : }
3579 : }
3580 :
3581 : /* -------------------------------------------------------------------- */
3582 : /* When called from ::IWriteBlock in separate cases (or in single band */
3583 : /* geotiffs), the ::IWriteBlock will override the content of the buffer*/
3584 : /* with pImage, so we don't need to read data from disk */
3585 : /* -------------------------------------------------------------------- */
3586 5311 : if( !bReadFromDisk )
3587 : {
3588 419 : nLoadedBlock = nBlockId;
3589 419 : return CE_None;
3590 : }
3591 :
3592 : /* libtiff 3.X doesn't like mixing read&write of JPEG compressed blocks */
3593 : /* The below hack is necessary due to another hack that consist in */
3594 : /* writing zero block to force creation of JPEG tables */
3595 4892 : if( nBlockId == 0 && bDontReloadFirstBlock )
3596 : {
3597 0 : bDontReloadFirstBlock = FALSE;
3598 0 : memset( pabyBlockBuf, 0, nBlockBufSize );
3599 0 : nLoadedBlock = nBlockId;
3600 0 : return CE_None;
3601 : }
3602 :
3603 : /* -------------------------------------------------------------------- */
3604 : /* The bottom most partial tiles and strips are sometimes only */
3605 : /* partially encoded. This code reduces the requested data so */
3606 : /* an error won't be reported in this case. (#1179) */
3607 : /* -------------------------------------------------------------------- */
3608 4892 : int nBlockReqSize = nBlockBufSize;
3609 4892 : int nBlocksPerRow = DIV_ROUND_UP(nRasterXSize, nBlockXSize);
3610 4892 : int nBlockYOff = (nBlockId % nBlocksPerBand) / nBlocksPerRow;
3611 :
3612 4892 : if( (int)((nBlockYOff+1) * nBlockYSize) > nRasterYSize )
3613 : {
3614 : nBlockReqSize = (nBlockBufSize / nBlockYSize)
3615 285 : * (nBlockYSize - (((nBlockYOff+1) * nBlockYSize) % nRasterYSize));
3616 285 : memset( pabyBlockBuf, 0, nBlockBufSize );
3617 : }
3618 :
3619 : /* -------------------------------------------------------------------- */
3620 : /* If we don't have this block already loaded, and we know it */
3621 : /* doesn't yet exist on disk, just zero the memory buffer and */
3622 : /* pretend we loaded it. */
3623 : /* -------------------------------------------------------------------- */
3624 4892 : if( !IsBlockAvailable( nBlockId ) )
3625 : {
3626 2493 : memset( pabyBlockBuf, 0, nBlockBufSize );
3627 2493 : nLoadedBlock = nBlockId;
3628 2493 : return CE_None;
3629 : }
3630 :
3631 : /* -------------------------------------------------------------------- */
3632 : /* Load the block, if it isn't our current block. */
3633 : /* -------------------------------------------------------------------- */
3634 2399 : if( TIFFIsTiled( hTIFF ) )
3635 : {
3636 457 : if( TIFFReadEncodedTile(hTIFF, nBlockId, pabyBlockBuf,
3637 : nBlockReqSize) == -1
3638 : && !bIgnoreReadErrors )
3639 : {
3640 : /* Once TIFFError() is properly hooked, this can go away */
3641 : CPLError( CE_Failure, CPLE_AppDefined,
3642 0 : "TIFFReadEncodedTile() failed." );
3643 :
3644 0 : memset( pabyBlockBuf, 0, nBlockBufSize );
3645 :
3646 0 : eErr = CE_Failure;
3647 : }
3648 : }
3649 : else
3650 : {
3651 1942 : if( TIFFReadEncodedStrip(hTIFF, nBlockId, pabyBlockBuf,
3652 : nBlockReqSize) == -1
3653 : && !bIgnoreReadErrors )
3654 : {
3655 : /* Once TIFFError() is properly hooked, this can go away */
3656 : CPLError( CE_Failure, CPLE_AppDefined,
3657 0 : "TIFFReadEncodedStrip() failed." );
3658 :
3659 0 : memset( pabyBlockBuf, 0, nBlockBufSize );
3660 :
3661 0 : eErr = CE_Failure;
3662 : }
3663 : }
3664 :
3665 2399 : nLoadedBlock = nBlockId;
3666 2399 : bLoadedBlockDirty = FALSE;
3667 :
3668 2399 : return eErr;
3669 : }
3670 :
3671 :
3672 : /************************************************************************/
3673 : /* Crystalize() */
3674 : /* */
3675 : /* Make sure that the directory information is written out for */
3676 : /* a new file, require before writing any imagery data. */
3677 : /************************************************************************/
3678 :
3679 230833 : void GTiffDataset::Crystalize()
3680 :
3681 : {
3682 230833 : if( !bCrystalized )
3683 : {
3684 : WriteMetadata( this, hTIFF, TRUE, osProfile, osFilename,
3685 970 : papszCreationOptions );
3686 970 : WriteGeoTIFFInfo();
3687 :
3688 970 : bMetadataChanged = FALSE;
3689 970 : bGeoTIFFInfoChanged = FALSE;
3690 970 : bNeedsRewrite = FALSE;
3691 :
3692 970 : bCrystalized = TRUE;
3693 :
3694 970 : TIFFWriteCheck( hTIFF, TIFFIsTiled(hTIFF), "GTiffDataset::Crystalize");
3695 :
3696 : // Keep zip and tiff quality, and jpegcolormode which get reset when we call
3697 : // TIFFWriteDirectory
3698 970 : int jquality = -1, zquality = -1, nColorMode = -1;
3699 970 : TIFFGetField(hTIFF, TIFFTAG_JPEGQUALITY, &jquality);
3700 970 : TIFFGetField(hTIFF, TIFFTAG_ZIPQUALITY, &zquality);
3701 970 : TIFFGetField( hTIFF, TIFFTAG_JPEGCOLORMODE, &nColorMode );
3702 :
3703 970 : TIFFWriteDirectory( hTIFF );
3704 970 : TIFFSetDirectory( hTIFF, 0 );
3705 :
3706 :
3707 : // Now, reset zip and tiff quality and jpegcolormode.
3708 970 : if(jquality > 0)
3709 14 : TIFFSetField(hTIFF, TIFFTAG_JPEGQUALITY, jquality);
3710 970 : if(zquality > 0)
3711 0 : TIFFSetField(hTIFF, TIFFTAG_ZIPQUALITY, zquality);
3712 970 : if (nColorMode >= 0)
3713 14 : TIFFSetField(hTIFF, TIFFTAG_JPEGCOLORMODE, nColorMode);
3714 :
3715 970 : nDirOffset = TIFFCurrentDirOffset( hTIFF );
3716 : }
3717 230833 : }
3718 :
3719 :
3720 : /************************************************************************/
3721 : /* IsBlockAvailable() */
3722 : /* */
3723 : /* Return TRUE if the indicated strip/tile is available. We */
3724 : /* establish this by testing if the stripbytecount is zero. If */
3725 : /* zero then the block has never been committed to disk. */
3726 : /************************************************************************/
3727 :
3728 104507 : int GTiffDataset::IsBlockAvailable( int nBlockId )
3729 :
3730 : {
3731 104507 : toff_t *panByteCounts = NULL;
3732 :
3733 104507 : if( ( TIFFIsTiled( hTIFF )
3734 : && TIFFGetField( hTIFF, TIFFTAG_TILEBYTECOUNTS, &panByteCounts ) )
3735 : || ( !TIFFIsTiled( hTIFF )
3736 : && TIFFGetField( hTIFF, TIFFTAG_STRIPBYTECOUNTS, &panByteCounts ) ) )
3737 : {
3738 104507 : if( panByteCounts == NULL )
3739 0 : return FALSE;
3740 : else
3741 104507 : return panByteCounts[nBlockId] != 0;
3742 : }
3743 : else
3744 0 : return FALSE;
3745 : }
3746 :
3747 : /************************************************************************/
3748 : /* FlushCache() */
3749 : /* */
3750 : /* We override this so we can also flush out local tiff strip */
3751 : /* cache if need be. */
3752 : /************************************************************************/
3753 :
3754 5864 : void GTiffDataset::FlushCache()
3755 :
3756 : {
3757 5864 : if (bIsFinalized)
3758 0 : return;
3759 :
3760 5864 : GDALPamDataset::FlushCache();
3761 :
3762 5864 : if( bLoadedBlockDirty && nLoadedBlock != -1 )
3763 156 : FlushBlockBuf();
3764 :
3765 5864 : CPLFree( pabyBlockBuf );
3766 5864 : pabyBlockBuf = NULL;
3767 5864 : nLoadedBlock = -1;
3768 5864 : bLoadedBlockDirty = FALSE;
3769 :
3770 5864 : if (!SetDirectory())
3771 0 : return;
3772 5864 : FlushDirectory();
3773 : }
3774 :
3775 : /************************************************************************/
3776 : /* FlushDirectory() */
3777 : /************************************************************************/
3778 :
3779 7260 : void GTiffDataset::FlushDirectory()
3780 :
3781 : {
3782 7260 : if( GetAccess() == GA_Update )
3783 : {
3784 3490 : if( bMetadataChanged )
3785 : {
3786 17 : if (!SetDirectory())
3787 0 : return;
3788 : bNeedsRewrite =
3789 : WriteMetadata( this, hTIFF, TRUE, osProfile, osFilename,
3790 17 : papszCreationOptions );
3791 17 : bMetadataChanged = FALSE;
3792 : }
3793 :
3794 3490 : if( bGeoTIFFInfoChanged )
3795 : {
3796 16 : if (!SetDirectory())
3797 0 : return;
3798 16 : WriteGeoTIFFInfo();
3799 : }
3800 :
3801 3490 : if( bNeedsRewrite )
3802 : {
3803 : #if defined(TIFFLIB_VERSION)
3804 : #if defined(HAVE_TIFFGETSIZEPROC)
3805 75 : if (!SetDirectory())
3806 0 : return;
3807 :
3808 75 : TIFFSizeProc pfnSizeProc = TIFFGetSizeProc( hTIFF );
3809 :
3810 75 : nDirOffset = pfnSizeProc( TIFFClientdata( hTIFF ) );
3811 75 : if( (nDirOffset % 2) == 1 )
3812 15 : nDirOffset++;
3813 :
3814 75 : TIFFRewriteDirectory( hTIFF );
3815 :
3816 75 : TIFFSetSubDirectory( hTIFF, nDirOffset );
3817 : #elif TIFFLIB_VERSION > 20010925 && TIFFLIB_VERSION != 20011807
3818 : if (!SetDirectory())
3819 : return;
3820 :
3821 : TIFFRewriteDirectory( hTIFF );
3822 : #endif
3823 : #endif
3824 75 : bNeedsRewrite = FALSE;
3825 : }
3826 : }
3827 :
3828 : // there are some circumstances in which we can reach this point
3829 : // without having made this our directory (SetDirectory()) in which
3830 : // case we should not risk a flush.
3831 7260 : if( GetAccess() == GA_Update && TIFFCurrentDirOffset(hTIFF) == nDirOffset )
3832 : {
3833 : #if defined(BIGTIFF_SUPPORT)
3834 3472 : TIFFSizeProc pfnSizeProc = TIFFGetSizeProc( hTIFF );
3835 :
3836 3472 : toff_t nNewDirOffset = pfnSizeProc( TIFFClientdata( hTIFF ) );
3837 3472 : if( (nNewDirOffset % 2) == 1 )
3838 433 : nNewDirOffset++;
3839 :
3840 3472 : TIFFFlush( hTIFF );
3841 :
3842 3472 : if( nDirOffset != TIFFCurrentDirOffset( hTIFF ) )
3843 : {
3844 54 : nDirOffset = nNewDirOffset;
3845 : CPLDebug( "GTiff",
3846 54 : "directory moved during flush in FlushDirectory()" );
3847 : }
3848 : #else
3849 : /* For libtiff 3.X, the above causes regressions and crashes in */
3850 : /* tiff_write.py and tiff_ovr.py */
3851 : TIFFFlush( hTIFF );
3852 : #endif
3853 : }
3854 : }
3855 :
3856 : /************************************************************************/
3857 : /* TIFF_OvLevelAdjust() */
3858 : /* */
3859 : /* Some overview levels cannot be achieved closely enough to be */
3860 : /* recognised as the desired overview level. This function */
3861 : /* will adjust an overview level to one that is achievable on */
3862 : /* the given raster size. */
3863 : /* */
3864 : /* For instance a 1200x1200 image on which a 256 level overview */
3865 : /* is request will end up generating a 5x5 overview. However, */
3866 : /* this will appear to the system be a level 240 overview. */
3867 : /* This function will adjust 256 to 240 based on knowledge of */
3868 : /* the image size. */
3869 : /* */
3870 : /* This is a copy of the GDALOvLevelAdjust() function in */
3871 : /* gdaldefaultoverviews.cpp. */
3872 : /************************************************************************/
3873 :
3874 199 : static int TIFF_OvLevelAdjust( int nOvLevel, int nXSize )
3875 :
3876 : {
3877 199 : int nOXSize = (nXSize + nOvLevel - 1) / nOvLevel;
3878 :
3879 199 : return (int) (0.5 + nXSize / (double) nOXSize);
3880 : }
3881 :
3882 : /************************************************************************/
3883 : /* CleanOverviews() */
3884 : /************************************************************************/
3885 :
3886 2 : CPLErr GTiffDataset::CleanOverviews()
3887 :
3888 : {
3889 2 : CPLAssert( bBase );
3890 :
3891 2 : ScanDirectories();
3892 :
3893 2 : FlushDirectory();
3894 2 : *ppoActiveDSRef = NULL;
3895 :
3896 : /* -------------------------------------------------------------------- */
3897 : /* Cleanup overviews objects, and get offsets to all overview */
3898 : /* directories. */
3899 : /* -------------------------------------------------------------------- */
3900 2 : std::vector<toff_t> anOvDirOffsets;
3901 : int i;
3902 :
3903 4 : for( i = 0; i < nOverviewCount; i++ )
3904 : {
3905 2 : anOvDirOffsets.push_back( papoOverviewDS[i]->nDirOffset );
3906 2 : delete papoOverviewDS[i];
3907 : }
3908 :
3909 : /* -------------------------------------------------------------------- */
3910 : /* Loop through all the directories, translating the offsets */
3911 : /* into indexes we can use with TIFFUnlinkDirectory(). */
3912 : /* -------------------------------------------------------------------- */
3913 2 : std::vector<uint16> anOvDirIndexes;
3914 2 : int iThisOffset = 1;
3915 :
3916 2 : TIFFSetDirectory( hTIFF, 0 );
3917 :
3918 2 : for( ; TRUE; )
3919 : {
3920 8 : for( i = 0; i < nOverviewCount; i++ )
3921 : {
3922 4 : if( anOvDirOffsets[i] == TIFFCurrentDirOffset( hTIFF ) )
3923 : {
3924 : CPLDebug( "GTiff", "%d -> %d",
3925 2 : (int) anOvDirOffsets[i], iThisOffset );
3926 2 : anOvDirIndexes.push_back( (uint16) iThisOffset );
3927 : }
3928 : }
3929 :
3930 4 : if( TIFFLastDirectory( hTIFF ) )
3931 : break;
3932 :
3933 2 : TIFFReadDirectory( hTIFF );
3934 2 : iThisOffset++;
3935 : }
3936 :
3937 : /* -------------------------------------------------------------------- */
3938 : /* Actually unlink the target directories. Note that we do */
3939 : /* this from last to first so as to avoid renumbering any of */
3940 : /* the earlier directories we need to remove. */
3941 : /* -------------------------------------------------------------------- */
3942 6 : while( !anOvDirIndexes.empty() )
3943 : {
3944 2 : TIFFUnlinkDirectory( hTIFF, anOvDirIndexes.back() );
3945 2 : anOvDirIndexes.pop_back();
3946 : }
3947 :
3948 2 : CPLFree( papoOverviewDS );
3949 :
3950 2 : nOverviewCount = 0;
3951 2 : papoOverviewDS = NULL;
3952 :
3953 2 : if (!SetDirectory())
3954 0 : return CE_Failure;
3955 :
3956 2 : return CE_None;
3957 : }
3958 :
3959 :
3960 : /************************************************************************/
3961 : /* RegisterNewOverviewDataset() */
3962 : /************************************************************************/
3963 :
3964 131 : CPLErr GTiffDataset::RegisterNewOverviewDataset(toff_t nOverviewOffset)
3965 : {
3966 131 : GTiffDataset* poODS = new GTiffDataset();
3967 131 : poODS->nJpegQuality = nJpegQuality;
3968 131 : poODS->nZLevel = nZLevel;
3969 131 : poODS->nLZMAPreset = nLZMAPreset;
3970 :
3971 131 : if( nCompression == COMPRESSION_JPEG )
3972 : {
3973 18 : if ( CPLGetConfigOption( "JPEG_QUALITY_OVERVIEW", NULL ) != NULL )
3974 : {
3975 8 : poODS->nJpegQuality = atoi(CPLGetConfigOption("JPEG_QUALITY_OVERVIEW","75"));
3976 : }
3977 : TIFFSetField( hTIFF, TIFFTAG_JPEGQUALITY,
3978 18 : poODS->nJpegQuality );
3979 : }
3980 :
3981 131 : if( poODS->OpenOffset( hTIFF, ppoActiveDSRef, nOverviewOffset, FALSE,
3982 : GA_Update ) != CE_None )
3983 : {
3984 0 : delete poODS;
3985 0 : return CE_Failure;
3986 : }
3987 : else
3988 : {
3989 131 : nOverviewCount++;
3990 : papoOverviewDS = (GTiffDataset **)
3991 : CPLRealloc(papoOverviewDS,
3992 131 : nOverviewCount * (sizeof(void*)));
3993 131 : papoOverviewDS[nOverviewCount-1] = poODS;
3994 131 : poODS->poBaseDS = this;
3995 131 : return CE_None;
3996 : }
3997 : }
3998 :
3999 : /************************************************************************/
4000 : /* CreateOverviewsFromSrcOverviews() */
4001 : /************************************************************************/
4002 :
4003 5 : CPLErr GTiffDataset::CreateOverviewsFromSrcOverviews(GDALDataset* poSrcDS)
4004 : {
4005 5 : CPLAssert(poSrcDS->GetRasterCount() != 0);
4006 5 : CPLAssert(nOverviewCount == 0);
4007 :
4008 5 : ScanDirectories();
4009 :
4010 : /* -------------------------------------------------------------------- */
4011 : /* Move to the directory for this dataset. */
4012 : /* -------------------------------------------------------------------- */
4013 5 : if (!SetDirectory())
4014 0 : return CE_Failure;
4015 5 : FlushDirectory();
4016 :
4017 5 : int nOvBitsPerSample = nBitsPerSample;
4018 :
4019 : /* -------------------------------------------------------------------- */
4020 : /* Do we have a palette? If so, create a TIFF compatible version. */
4021 : /* -------------------------------------------------------------------- */
4022 5 : std::vector<unsigned short> anTRed, anTGreen, anTBlue;
4023 5 : unsigned short *panRed=NULL, *panGreen=NULL, *panBlue=NULL;
4024 :
4025 5 : if( nPhotometric == PHOTOMETRIC_PALETTE && poColorTable != NULL )
4026 : {
4027 : int nColors;
4028 :
4029 0 : if( nOvBitsPerSample == 8 )
4030 0 : nColors = 256;
4031 0 : else if( nOvBitsPerSample < 8 )
4032 0 : nColors = 1 << nOvBitsPerSample;
4033 : else
4034 0 : nColors = 65536;
4035 :
4036 0 : anTRed.resize(nColors,0);
4037 0 : anTGreen.resize(nColors,0);
4038 0 : anTBlue.resize(nColors,0);
4039 :
4040 0 : for( int iColor = 0; iColor < nColors; iColor++ )
4041 : {
4042 0 : if( iColor < poColorTable->GetColorEntryCount() )
4043 : {
4044 : GDALColorEntry sRGB;
4045 :
4046 0 : poColorTable->GetColorEntryAsRGB( iColor, &sRGB );
4047 :
4048 0 : anTRed[iColor] = (unsigned short) (256 * sRGB.c1);
4049 0 : anTGreen[iColor] = (unsigned short) (256 * sRGB.c2);
4050 0 : anTBlue[iColor] = (unsigned short) (256 * sRGB.c3);
4051 : }
4052 : else
4053 : {
4054 0 : anTRed[iColor] = anTGreen[iColor] = anTBlue[iColor] = 0;
4055 : }
4056 : }
4057 :
4058 0 : panRed = &(anTRed[0]);
4059 0 : panGreen = &(anTGreen[0]);
4060 0 : panBlue = &(anTBlue[0]);
4061 : }
4062 :
4063 : /* -------------------------------------------------------------------- */
4064 : /* Do we need some metadata for the overviews? */
4065 : /* -------------------------------------------------------------------- */
4066 5 : CPLString osMetadata;
4067 :
4068 5 : GTIFFBuildOverviewMetadata( "NONE", this, osMetadata );
4069 :
4070 : /* -------------------------------------------------------------------- */
4071 : /* Fetch extra sample tag */
4072 : /* -------------------------------------------------------------------- */
4073 5 : uint16 *panExtraSampleValues = NULL;
4074 5 : uint16 nExtraSamples = 0;
4075 :
4076 5 : if( TIFFGetField( hTIFF, TIFFTAG_EXTRASAMPLES, &nExtraSamples, &panExtraSampleValues) )
4077 : {
4078 0 : uint16* panExtraSampleValuesNew = (uint16*) CPLMalloc(nExtraSamples * sizeof(uint16));
4079 0 : memcpy(panExtraSampleValuesNew, panExtraSampleValues, nExtraSamples * sizeof(uint16));
4080 0 : panExtraSampleValues = panExtraSampleValuesNew;
4081 : }
4082 : else
4083 : {
4084 5 : panExtraSampleValues = NULL;
4085 5 : nExtraSamples = 0;
4086 : }
4087 :
4088 : /* -------------------------------------------------------------------- */
4089 : /* Fetch predictor tag */
4090 : /* -------------------------------------------------------------------- */
4091 5 : uint16 nPredictor = PREDICTOR_NONE;
4092 5 : if ( nCompression == COMPRESSION_LZW ||
4093 : nCompression == COMPRESSION_ADOBE_DEFLATE )
4094 0 : TIFFGetField( hTIFF, TIFFTAG_PREDICTOR, &nPredictor );
4095 : int nOvrBlockXSize, nOvrBlockYSize;
4096 5 : GTIFFGetOverviewBlockSize(&nOvrBlockXSize, &nOvrBlockYSize);
4097 :
4098 5 : int nSrcOverviews = poSrcDS->GetRasterBand(1)->GetOverviewCount();
4099 : int i;
4100 5 : CPLErr eErr = CE_None;
4101 :
4102 18 : for(i=0;i<nSrcOverviews && eErr == CE_None;i++)
4103 : {
4104 13 : GDALRasterBand* poOvrBand = poSrcDS->GetRasterBand(1)->GetOverview(i);
4105 :
4106 13 : int nOXSize = poOvrBand->GetXSize(), nOYSize = poOvrBand->GetYSize();
4107 :
4108 : toff_t nOverviewOffset =
4109 : GTIFFWriteDirectory(hTIFF, FILETYPE_REDUCEDIMAGE,
4110 : nOXSize, nOYSize,
4111 : nOvBitsPerSample, nPlanarConfig,
4112 : nSamplesPerPixel, nOvrBlockXSize, nOvrBlockYSize, TRUE,
4113 : nCompression, nPhotometric, nSampleFormat,
4114 : nPredictor,
4115 : panRed, panGreen, panBlue,
4116 : nExtraSamples, panExtraSampleValues,
4117 13 : osMetadata );
4118 :
4119 13 : if( nOverviewOffset == 0 )
4120 0 : eErr = CE_Failure;
4121 : else
4122 13 : eErr = RegisterNewOverviewDataset(nOverviewOffset);
4123 : }
4124 :
4125 5 : CPLFree(panExtraSampleValues);
4126 5 : panExtraSampleValues = NULL;
4127 :
4128 : /* -------------------------------------------------------------------- */
4129 : /* Create overviews for the mask. */
4130 : /* -------------------------------------------------------------------- */
4131 5 : if (eErr == CE_None)
4132 5 : eErr = CreateInternalMaskOverviews(nOvrBlockXSize, nOvrBlockYSize);
4133 :
4134 5 : return eErr;
4135 : }
4136 :
4137 :
4138 : /************************************************************************/
4139 : /* CreateInternalMaskOverviews() */
4140 : /************************************************************************/
4141 :
4142 86 : CPLErr GTiffDataset::CreateInternalMaskOverviews(int nOvrBlockXSize,
4143 : int nOvrBlockYSize)
4144 : {
4145 : GTiffDataset *poODS;
4146 :
4147 86 : ScanDirectories();
4148 :
4149 : /* -------------------------------------------------------------------- */
4150 : /* Create overviews for the mask. */
4151 : /* -------------------------------------------------------------------- */
4152 86 : CPLErr eErr = CE_None;
4153 :
4154 86 : const char* pszInternalMask = CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK", NULL);
4155 86 : if (poMaskDS != NULL &&
4156 : poMaskDS->GetRasterCount() == 1 &&
4157 : (pszInternalMask == NULL || CSLTestBoolean(pszInternalMask)))
4158 : {
4159 : int nMaskOvrCompression;
4160 4 : if( strstr(GDALGetMetadataItem(GDALGetDriverByName( "GTiff" ),
4161 : GDAL_DMD_CREATIONOPTIONLIST, NULL ),
4162 : "<Value>DEFLATE</Value>") != NULL )
4163 4 : nMaskOvrCompression = COMPRESSION_ADOBE_DEFLATE;
4164 : else
4165 0 : nMaskOvrCompression = COMPRESSION_PACKBITS;
4166 :
4167 : int i;
4168 12 : for( i = 0; i < nOverviewCount; i++ )
4169 : {
4170 8 : if (papoOverviewDS[i]->poMaskDS == NULL)
4171 : {
4172 : toff_t nOverviewOffset;
4173 :
4174 : nOverviewOffset =
4175 : GTIFFWriteDirectory(hTIFF, FILETYPE_REDUCEDIMAGE | FILETYPE_MASK,
4176 16 : papoOverviewDS[i]->nRasterXSize, papoOverviewDS[i]->nRasterYSize,
4177 : 1, PLANARCONFIG_CONTIG,
4178 : 1, nOvrBlockXSize, nOvrBlockYSize, TRUE,
4179 : nMaskOvrCompression, PHOTOMETRIC_MASK, SAMPLEFORMAT_UINT, PREDICTOR_NONE,
4180 : NULL, NULL, NULL, 0, NULL,
4181 24 : "" );
4182 :
4183 8 : if( nOverviewOffset == 0 )
4184 : {
4185 0 : eErr = CE_Failure;
4186 0 : continue;
4187 : }
4188 :
4189 8 : poODS = new GTiffDataset();
4190 8 : if( poODS->OpenOffset( hTIFF, ppoActiveDSRef,
4191 : nOverviewOffset, FALSE,
4192 : GA_Update ) != CE_None )
4193 : {
4194 0 : delete poODS;
4195 0 : eErr = CE_Failure;
4196 : }
4197 : else
4198 : {
4199 8 : poODS->bPromoteTo8Bits = CSLTestBoolean(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK_TO_8BIT", "YES"));
4200 8 : poODS->poBaseDS = this;
4201 8 : papoOverviewDS[i]->poMaskDS = poODS;
4202 8 : poMaskDS->nOverviewCount++;
4203 : poMaskDS->papoOverviewDS = (GTiffDataset **)
4204 : CPLRealloc(poMaskDS->papoOverviewDS,
4205 8 : poMaskDS->nOverviewCount * (sizeof(void*)));
4206 8 : poMaskDS->papoOverviewDS[poMaskDS->nOverviewCount-1] = poODS;
4207 : }
4208 : }
4209 : }
4210 : }
4211 :
4212 86 : return eErr;
4213 : }
4214 :
4215 : /************************************************************************/
4216 : /* IBuildOverviews() */
4217 : /************************************************************************/
4218 :
4219 149 : CPLErr GTiffDataset::IBuildOverviews(
4220 : const char * pszResampling,
4221 : int nOverviews, int * panOverviewList,
4222 : int nBands, int * panBandList,
4223 : GDALProgressFunc pfnProgress, void * pProgressData )
4224 :
4225 : {
4226 149 : CPLErr eErr = CE_None;
4227 : int i;
4228 : GTiffDataset *poODS;
4229 149 : int bUseGenericHandling = FALSE;
4230 :
4231 149 : ScanDirectories();
4232 :
4233 : /* -------------------------------------------------------------------- */
4234 : /* If RRD or external OVR overviews requested, then invoke */
4235 : /* generic handling. */
4236 : /* -------------------------------------------------------------------- */
4237 149 : if( CSLTestBoolean(CPLGetConfigOption( "USE_RRD", "NO" ))
4238 : || CSLTestBoolean(CPLGetConfigOption( "TIFF_USE_OVR", "NO" )) )
4239 : {
4240 2 : bUseGenericHandling = TRUE;
4241 : }
4242 :
4243 : /* -------------------------------------------------------------------- */
4244 : /* If we don't have read access, then create the overviews */
4245 : /* externally. */
4246 : /* -------------------------------------------------------------------- */
4247 149 : if( GetAccess() != GA_Update )
4248 : {
4249 : CPLDebug( "GTiff",
4250 : "File open for read-only accessing, "
4251 63 : "creating overviews externally." );
4252 :
4253 63 : bUseGenericHandling = TRUE;
4254 : }
4255 :
4256 149 : if( bUseGenericHandling )
4257 : {
4258 65 : if (nOverviewCount != 0)
4259 : {
4260 : CPLError(CE_Failure, CPLE_NotSupported,
4261 0 : "Cannot add external overviews when there are already internal overviews");
4262 0 : return CE_Failure;
4263 : }
4264 :
4265 : return GDALDataset::IBuildOverviews(
4266 : pszResampling, nOverviews, panOverviewList,
4267 65 : nBands, panBandList, pfnProgress, pProgressData );
4268 : }
4269 :
4270 : /* -------------------------------------------------------------------- */
4271 : /* Our TIFF overview support currently only works safely if all */
4272 : /* bands are handled at the same time. */
4273 : /* -------------------------------------------------------------------- */
4274 84 : if( nBands != GetRasterCount() )
4275 : {
4276 : CPLError( CE_Failure, CPLE_NotSupported,
4277 : "Generation of overviews in TIFF currently only"
4278 : " supported when operating on all bands.\n"
4279 0 : "Operation failed.\n" );
4280 0 : return CE_Failure;
4281 : }
4282 :
4283 : /* -------------------------------------------------------------------- */
4284 : /* If zero overviews were requested, we need to clear all */
4285 : /* existing overviews. */
4286 : /* -------------------------------------------------------------------- */
4287 84 : if( nOverviews == 0 )
4288 : {
4289 3 : if( nOverviewCount == 0 )
4290 : return GDALDataset::IBuildOverviews(
4291 : pszResampling, nOverviews, panOverviewList,
4292 1 : nBands, panBandList, pfnProgress, pProgressData );
4293 : else
4294 2 : return CleanOverviews();
4295 : }
4296 :
4297 : /* -------------------------------------------------------------------- */
4298 : /* libtiff 3.X has issues when generating interleaved overviews. */
4299 : /* so generate them one after another one. */
4300 : /* -------------------------------------------------------------------- */
4301 : #ifndef BIGTIFF_SUPPORT
4302 : if( nOverviews > 1 )
4303 : {
4304 : double* padfOvrRasterFactor = (double*) CPLMalloc(sizeof(double) * nOverviews);
4305 : double dfTotal = 0;
4306 : for( i = 0; i < nOverviews; i++ )
4307 : {
4308 : if( panOverviewList[i] <= 0 )
4309 : {
4310 : CPLError(CE_Failure, CPLE_AppDefined,
4311 : "Invalid overview factor : %d", panOverviewList[i]);
4312 : eErr = CE_Failure;
4313 : break;
4314 : }
4315 : padfOvrRasterFactor[i] = 1.0 / (panOverviewList[i] * panOverviewList[i]);
4316 : dfTotal += padfOvrRasterFactor[i];
4317 : }
4318 :
4319 : double dfAcc = 0.0;
4320 : for( i = 0; i < nOverviews && eErr == CE_None; i++ )
4321 : {
4322 : void *pScaledProgressData;
4323 : pScaledProgressData =
4324 : GDALCreateScaledProgress( dfAcc / dfTotal,
4325 : (dfAcc + padfOvrRasterFactor[i]) / dfTotal,
4326 : pfnProgress, pProgressData );
4327 : dfAcc += padfOvrRasterFactor[i];
4328 :
4329 : eErr = IBuildOverviews(
4330 : pszResampling, 1, &panOverviewList[i],
4331 : nBands, panBandList, GDALScaledProgress, pScaledProgressData );
4332 :
4333 : GDALDestroyScaledProgress(pScaledProgressData);
4334 : }
4335 :
4336 : CPLFree(padfOvrRasterFactor);
4337 :
4338 : return eErr;
4339 : }
4340 : #endif
4341 :
4342 : /* -------------------------------------------------------------------- */
4343 : /* Initialize progress counter. */
4344 : /* -------------------------------------------------------------------- */
4345 81 : if( !pfnProgress( 0.0, NULL, pProgressData ) )
4346 : {
4347 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
4348 0 : return CE_Failure;
4349 : }
4350 :
4351 : /* -------------------------------------------------------------------- */
4352 : /* Move to the directory for this dataset. */
4353 : /* -------------------------------------------------------------------- */
4354 81 : if (!SetDirectory())
4355 0 : return CE_Failure;
4356 81 : FlushDirectory();
4357 :
4358 : /* -------------------------------------------------------------------- */
4359 : /* If we are averaging bit data to grayscale we need to create */
4360 : /* 8bit overviews. */
4361 : /* -------------------------------------------------------------------- */
4362 81 : int nOvBitsPerSample = nBitsPerSample;
4363 :
4364 81 : if( EQUALN(pszResampling,"AVERAGE_BIT2",12) )
4365 2 : nOvBitsPerSample = 8;
4366 :
4367 : /* -------------------------------------------------------------------- */
4368 : /* Do we have a palette? If so, create a TIFF compatible version. */
4369 : /* -------------------------------------------------------------------- */
4370 81 : std::vector<unsigned short> anTRed, anTGreen, anTBlue;
4371 81 : unsigned short *panRed=NULL, *panGreen=NULL, *panBlue=NULL;
4372 :
4373 81 : if( nPhotometric == PHOTOMETRIC_PALETTE && poColorTable != NULL )
4374 : {
4375 : int nColors;
4376 :
4377 9 : if( nOvBitsPerSample == 8 )
4378 9 : nColors = 256;
4379 0 : else if( nOvBitsPerSample < 8 )
4380 0 : nColors = 1 << nOvBitsPerSample;
4381 : else
4382 0 : nColors = 65536;
4383 :
4384 9 : anTRed.resize(nColors,0);
4385 9 : anTGreen.resize(nColors,0);
4386 9 : anTBlue.resize(nColors,0);
4387 :
4388 2313 : for( int iColor = 0; iColor < nColors; iColor++ )
4389 : {
4390 2304 : if( iColor < poColorTable->GetColorEntryCount() )
4391 : {
4392 : GDALColorEntry sRGB;
4393 :
4394 2304 : poColorTable->GetColorEntryAsRGB( iColor, &sRGB );
4395 :
4396 2304 : anTRed[iColor] = (unsigned short) (256 * sRGB.c1);
4397 2304 : anTGreen[iColor] = (unsigned short) (256 * sRGB.c2);
4398 2304 : anTBlue[iColor] = (unsigned short) (256 * sRGB.c3);
4399 : }
4400 : else
4401 : {
4402 0 : anTRed[iColor] = anTGreen[iColor] = anTBlue[iColor] = 0;
4403 : }
4404 : }
4405 :
4406 9 : panRed = &(anTRed[0]);
4407 9 : panGreen = &(anTGreen[0]);
4408 9 : panBlue = &(anTBlue[0]);
4409 : }
4410 :
4411 : /* -------------------------------------------------------------------- */
4412 : /* Do we need some metadata for the overviews? */
4413 : /* -------------------------------------------------------------------- */
4414 81 : CPLString osMetadata;
4415 :
4416 81 : GTIFFBuildOverviewMetadata( pszResampling, this, osMetadata );
4417 :
4418 : /* -------------------------------------------------------------------- */
4419 : /* Fetch extra sample tag */
4420 : /* -------------------------------------------------------------------- */
4421 81 : uint16 *panExtraSampleValues = NULL;
4422 81 : uint16 nExtraSamples = 0;
4423 :
4424 81 : if( TIFFGetField( hTIFF, TIFFTAG_EXTRASAMPLES, &nExtraSamples, &panExtraSampleValues) )
4425 : {
4426 8 : uint16* panExtraSampleValuesNew = (uint16*) CPLMalloc(nExtraSamples * sizeof(uint16));
4427 8 : memcpy(panExtraSampleValuesNew, panExtraSampleValues, nExtraSamples * sizeof(uint16));
4428 8 : panExtraSampleValues = panExtraSampleValuesNew;
4429 : }
4430 : else
4431 : {
4432 73 : panExtraSampleValues = NULL;
4433 73 : nExtraSamples = 0;
4434 : }
4435 :
4436 : /* -------------------------------------------------------------------- */
4437 : /* Fetch predictor tag */
4438 : /* -------------------------------------------------------------------- */
4439 81 : uint16 nPredictor = PREDICTOR_NONE;
4440 81 : if ( nCompression == COMPRESSION_LZW ||
4441 : nCompression == COMPRESSION_ADOBE_DEFLATE )
4442 7 : TIFFGetField( hTIFF, TIFFTAG_PREDICTOR, &nPredictor );
4443 :
4444 : /* -------------------------------------------------------------------- */
4445 : /* Establish which of the overview levels we already have, and */
4446 : /* which are new. We assume that band 1 of the file is */
4447 : /* representative. */
4448 : /* -------------------------------------------------------------------- */
4449 : int nOvrBlockXSize, nOvrBlockYSize;
4450 81 : GTIFFGetOverviewBlockSize(&nOvrBlockXSize, &nOvrBlockYSize);
4451 213 : for( i = 0; i < nOverviews && eErr == CE_None; i++ )
4452 : {
4453 : int j;
4454 :
4455 219 : for( j = 0; j < nOverviewCount && eErr == CE_None; j++ )
4456 : {
4457 : int nOvFactor;
4458 :
4459 87 : poODS = papoOverviewDS[j];
4460 :
4461 : nOvFactor = (int)
4462 87 : (0.5 + GetRasterXSize() / (double) poODS->GetRasterXSize());
4463 :
4464 87 : if( nOvFactor == panOverviewList[i]
4465 : || nOvFactor == TIFF_OvLevelAdjust( panOverviewList[i],
4466 : GetRasterXSize() ) )
4467 14 : panOverviewList[i] *= -1;
4468 : }
4469 :
4470 132 : if( panOverviewList[i] > 0 )
4471 : {
4472 : toff_t nOverviewOffset;
4473 : int nOXSize, nOYSize;
4474 :
4475 118 : nOXSize = (GetRasterXSize() + panOverviewList[i] - 1)
4476 236 : / panOverviewList[i];
4477 118 : nOYSize = (GetRasterYSize() + panOverviewList[i] - 1)
4478 236 : / panOverviewList[i];
4479 :
4480 : nOverviewOffset =
4481 : GTIFFWriteDirectory(hTIFF, FILETYPE_REDUCEDIMAGE,
4482 : nOXSize, nOYSize,
4483 : nOvBitsPerSample, nPlanarConfig,
4484 : nSamplesPerPixel, nOvrBlockXSize, nOvrBlockYSize, TRUE,
4485 : nCompression, nPhotometric, nSampleFormat,
4486 : nPredictor,
4487 : panRed, panGreen, panBlue,
4488 : nExtraSamples, panExtraSampleValues,
4489 118 : osMetadata );
4490 :
4491 :
4492 118 : if( nOverviewOffset == 0 )
4493 0 : eErr = CE_Failure;
4494 : else
4495 118 : eErr = RegisterNewOverviewDataset(nOverviewOffset);
4496 : }
4497 : else
4498 14 : panOverviewList[i] *= -1;
4499 : }
4500 :
4501 81 : CPLFree(panExtraSampleValues);
4502 81 : panExtraSampleValues = NULL;
4503 :
4504 : /* -------------------------------------------------------------------- */
4505 : /* Create overviews for the mask. */
4506 : /* -------------------------------------------------------------------- */
4507 81 : if (eErr == CE_None)
4508 81 : eErr = CreateInternalMaskOverviews(nOvrBlockXSize, nOvrBlockYSize);
4509 : else
4510 0 : return eErr;
4511 :
4512 : /* -------------------------------------------------------------------- */
4513 : /* Refresh overviews for the mask */
4514 : /* -------------------------------------------------------------------- */
4515 92 : if (poMaskDS != NULL &&
4516 : poMaskDS->GetRasterCount() == 1)
4517 : {
4518 : GDALRasterBand **papoOverviewBands;
4519 11 : int nMaskOverviews = 0;
4520 :
4521 11 : papoOverviewBands = (GDALRasterBand **) CPLCalloc(sizeof(void*),nOverviewCount);
4522 33 : for( i = 0; i < nOverviewCount; i++ )
4523 : {
4524 22 : if (papoOverviewDS[i]->poMaskDS != NULL)
4525 : {
4526 36 : papoOverviewBands[nMaskOverviews ++] =
4527 18 : papoOverviewDS[i]->poMaskDS->GetRasterBand(1);
4528 : }
4529 : }
4530 : eErr = GDALRegenerateOverviews( (GDALRasterBandH)
4531 : poMaskDS->GetRasterBand(1),
4532 : nMaskOverviews,
4533 : (GDALRasterBandH *) papoOverviewBands,
4534 11 : pszResampling, GDALDummyProgress, NULL);
4535 11 : CPLFree(papoOverviewBands);
4536 : }
4537 :
4538 :
4539 : /* -------------------------------------------------------------------- */
4540 : /* Refresh old overviews that were listed. */
4541 : /* -------------------------------------------------------------------- */
4542 97 : if (nCompression != COMPRESSION_NONE &&
4543 : nPlanarConfig == PLANARCONFIG_CONTIG &&
4544 : GDALDataTypeIsComplex(GetRasterBand( panBandList[0] )->GetRasterDataType()) == FALSE &&
4545 16 : GetRasterBand( panBandList[0] )->GetColorTable() == NULL &&
4546 : (EQUALN(pszResampling, "NEAR", 4) || EQUAL(pszResampling, "AVERAGE") || EQUAL(pszResampling, "GAUSS")))
4547 : {
4548 : /* In the case of pixel interleaved compressed overviews, we want to generate */
4549 : /* the overviews for all the bands block by block, and not band after band, */
4550 : /* in order to write the block once and not loose space in the TIFF file */
4551 :
4552 : GDALRasterBand ***papapoOverviewBands;
4553 : GDALRasterBand **papoBandList;
4554 :
4555 16 : int nNewOverviews = 0;
4556 : int iBand;
4557 :
4558 16 : papapoOverviewBands = (GDALRasterBand ***) CPLCalloc(sizeof(void*),nBands);
4559 16 : papoBandList = (GDALRasterBand **) CPLCalloc(sizeof(void*),nBands);
4560 60 : for( iBand = 0; iBand < nBands; iBand++ )
4561 : {
4562 44 : GDALRasterBand* poBand = GetRasterBand( panBandList[iBand] );
4563 :
4564 44 : papoBandList[iBand] = poBand;
4565 44 : papapoOverviewBands[iBand] = (GDALRasterBand **) CPLCalloc(sizeof(void*), poBand->GetOverviewCount());
4566 :
4567 44 : int iCurOverview = 0;
4568 114 : for( i = 0; i < nOverviews; i++ )
4569 : {
4570 : int j;
4571 :
4572 96 : for( j = 0; j < poBand->GetOverviewCount(); j++ )
4573 : {
4574 : int nOvFactor;
4575 96 : GDALRasterBand * poOverview = poBand->GetOverview( j );
4576 :
4577 : nOvFactor = (int)
4578 96 : (0.5 + poBand->GetXSize() / (double) poOverview->GetXSize());
4579 :
4580 : int bHasNoData;
4581 96 : double noDataValue = poBand->GetNoDataValue(&bHasNoData);
4582 :
4583 96 : if (bHasNoData)
4584 18 : poOverview->SetNoDataValue(noDataValue);
4585 :
4586 96 : if( nOvFactor == panOverviewList[i]
4587 : || nOvFactor == TIFF_OvLevelAdjust( panOverviewList[i],
4588 : poBand->GetXSize() ) )
4589 : {
4590 70 : papapoOverviewBands[iBand][iCurOverview] = poOverview;
4591 70 : iCurOverview++ ;
4592 70 : break;
4593 : }
4594 : }
4595 : }
4596 :
4597 44 : if (nNewOverviews == 0)
4598 16 : nNewOverviews = iCurOverview;
4599 28 : else if (nNewOverviews != iCurOverview)
4600 : {
4601 0 : CPLAssert(0);
4602 0 : return CE_Failure;
4603 : }
4604 : }
4605 :
4606 : GDALRegenerateOverviewsMultiBand(nBands, papoBandList,
4607 : nNewOverviews, papapoOverviewBands,
4608 16 : pszResampling, pfnProgress, pProgressData );
4609 :
4610 60 : for( iBand = 0; iBand < nBands; iBand++ )
4611 : {
4612 44 : CPLFree(papapoOverviewBands[iBand]);
4613 : }
4614 16 : CPLFree(papapoOverviewBands);
4615 16 : CPLFree(papoBandList);
4616 : }
4617 : else
4618 : {
4619 : GDALRasterBand **papoOverviewBands;
4620 :
4621 : papoOverviewBands = (GDALRasterBand **)
4622 65 : CPLCalloc(sizeof(void*),nOverviews);
4623 :
4624 156 : for( int iBand = 0; iBand < nBands && eErr == CE_None; iBand++ )
4625 : {
4626 : GDALRasterBand *poBand;
4627 : int nNewOverviews;
4628 :
4629 91 : poBand = GetRasterBand( panBandList[iBand] );
4630 :
4631 91 : nNewOverviews = 0;
4632 253 : for( i = 0; i < nOverviews && poBand != NULL; i++ )
4633 : {
4634 : int j;
4635 :
4636 261 : for( j = 0; j < poBand->GetOverviewCount(); j++ )
4637 : {
4638 : int nOvFactor;
4639 261 : GDALRasterBand * poOverview = poBand->GetOverview( j );
4640 :
4641 : int bHasNoData;
4642 261 : double noDataValue = poBand->GetNoDataValue(&bHasNoData);
4643 :
4644 261 : if (bHasNoData)
4645 7 : poOverview->SetNoDataValue(noDataValue);
4646 :
4647 : nOvFactor = (int)
4648 261 : (0.5 + poBand->GetXSize() / (double) poOverview->GetXSize());
4649 :
4650 261 : if( nOvFactor == panOverviewList[i]
4651 : || nOvFactor == TIFF_OvLevelAdjust( panOverviewList[i],
4652 : poBand->GetXSize() ) )
4653 : {
4654 162 : papoOverviewBands[nNewOverviews++] = poOverview;
4655 162 : break;
4656 : }
4657 : }
4658 : }
4659 :
4660 : void *pScaledProgressData;
4661 :
4662 : pScaledProgressData =
4663 : GDALCreateScaledProgress( iBand / (double) nBands,
4664 : (iBand+1) / (double) nBands,
4665 91 : pfnProgress, pProgressData );
4666 :
4667 : eErr = GDALRegenerateOverviews( (GDALRasterBandH) poBand,
4668 : nNewOverviews,
4669 : (GDALRasterBandH *) papoOverviewBands,
4670 : pszResampling,
4671 : GDALScaledProgress,
4672 91 : pScaledProgressData);
4673 :
4674 91 : GDALDestroyScaledProgress( pScaledProgressData );
4675 : }
4676 :
4677 : /* -------------------------------------------------------------------- */
4678 : /* Cleanup */
4679 : /* -------------------------------------------------------------------- */
4680 65 : CPLFree( papoOverviewBands );
4681 : }
4682 :
4683 :
4684 81 : pfnProgress( 1.0, NULL, pProgressData );
4685 :
4686 81 : return eErr;
4687 : }
4688 :
4689 :
4690 : /************************************************************************/
4691 : /* WriteGeoTIFFInfo() */
4692 : /************************************************************************/
4693 :
4694 986 : void GTiffDataset::WriteGeoTIFFInfo()
4695 :
4696 : {
4697 986 : bool bPixelIsPoint = false;
4698 986 : int bPointGeoIgnore = FALSE;
4699 :
4700 1264 : if( GetMetadataItem( GDALMD_AREA_OR_POINT )
4701 278 : && EQUAL(GetMetadataItem(GDALMD_AREA_OR_POINT),
4702 : GDALMD_AOP_POINT) )
4703 : {
4704 4 : bPixelIsPoint = true;
4705 : bPointGeoIgnore =
4706 : CSLTestBoolean( CPLGetConfigOption("GTIFF_POINT_GEO_IGNORE",
4707 4 : "FALSE") );
4708 : }
4709 :
4710 : /* -------------------------------------------------------------------- */
4711 : /* If the geotransform is the default, don't bother writing it. */
4712 : /* -------------------------------------------------------------------- */
4713 3110 : if( adfGeoTransform[0] != 0.0 || adfGeoTransform[1] != 1.0
4714 576 : || adfGeoTransform[2] != 0.0 || adfGeoTransform[3] != 0.0
4715 843 : || adfGeoTransform[4] != 0.0 || ABS(adfGeoTransform[5]) != 1.0 )
4716 : {
4717 705 : bNeedsRewrite = TRUE;
4718 :
4719 : /* -------------------------------------------------------------------- */
4720 : /* Clear old tags to ensure we don't end up with conflicting */
4721 : /* information. (#2625) */
4722 : /* -------------------------------------------------------------------- */
4723 : #ifdef HAVE_UNSETFIELD
4724 705 : TIFFUnsetField( hTIFF, TIFFTAG_GEOPIXELSCALE );
4725 705 : TIFFUnsetField( hTIFF, TIFFTAG_GEOTIEPOINTS );
4726 705 : TIFFUnsetField( hTIFF, TIFFTAG_GEOTRANSMATRIX );
4727 : #endif
4728 :
4729 : /* -------------------------------------------------------------------- */
4730 : /* Write the transform. If we have a normal north-up image we */
4731 : /* use the tiepoint plus pixelscale otherwise we use a matrix. */
4732 : /* -------------------------------------------------------------------- */
4733 2110 : if( adfGeoTransform[2] == 0.0 && adfGeoTransform[4] == 0.0
4734 703 : && adfGeoTransform[5] < 0.0 )
4735 : {
4736 : double adfPixelScale[3], adfTiePoints[6];
4737 :
4738 702 : adfPixelScale[0] = adfGeoTransform[1];
4739 702 : adfPixelScale[1] = fabs(adfGeoTransform[5]);
4740 702 : adfPixelScale[2] = 0.0;
4741 :
4742 702 : if( !EQUAL(osProfile,"BASELINE") )
4743 697 : TIFFSetField( hTIFF, TIFFTAG_GEOPIXELSCALE, 3, adfPixelScale );
4744 :
4745 702 : adfTiePoints[0] = 0.0;
4746 702 : adfTiePoints[1] = 0.0;
4747 702 : adfTiePoints[2] = 0.0;
4748 702 : adfTiePoints[3] = adfGeoTransform[0];
4749 702 : adfTiePoints[4] = adfGeoTransform[3];
4750 702 : adfTiePoints[5] = 0.0;
4751 :
4752 702 : if( bPixelIsPoint && !bPointGeoIgnore )
4753 : {
4754 0 : adfTiePoints[3] += adfGeoTransform[1] * 0.5 + adfGeoTransform[2] * 0.5;
4755 0 : adfTiePoints[4] += adfGeoTransform[4] * 0.5 + adfGeoTransform[5] * 0.5;
4756 : }
4757 :
4758 702 : if( !EQUAL(osProfile,"BASELINE") )
4759 697 : TIFFSetField( hTIFF, TIFFTAG_GEOTIEPOINTS, 6, adfTiePoints );
4760 : }
4761 : else
4762 : {
4763 : double adfMatrix[16];
4764 :
4765 3 : memset(adfMatrix,0,sizeof(double) * 16);
4766 :
4767 3 : adfMatrix[0] = adfGeoTransform[1];
4768 3 : adfMatrix[1] = adfGeoTransform[2];
4769 3 : adfMatrix[3] = adfGeoTransform[0];
4770 3 : adfMatrix[4] = adfGeoTransform[4];
4771 3 : adfMatrix[5] = adfGeoTransform[5];
4772 3 : adfMatrix[7] = adfGeoTransform[3];
4773 3 : adfMatrix[15] = 1.0;
4774 :
4775 3 : if( bPixelIsPoint && !bPointGeoIgnore )
4776 : {
4777 0 : adfMatrix[3] += adfGeoTransform[1] * 0.5 + adfGeoTransform[2] * 0.5;
4778 0 : adfMatrix[7] += adfGeoTransform[4] * 0.5 + adfGeoTransform[5] * 0.5;
4779 : }
4780 :
4781 3 : if( !EQUAL(osProfile,"BASELINE") )
4782 3 : TIFFSetField( hTIFF, TIFFTAG_GEOTRANSMATRIX, 16, adfMatrix );
4783 : }
4784 :
4785 : // Do we need a world file?
4786 705 : if( CSLFetchBoolean( papszCreationOptions, "TFW", FALSE ) )
4787 2 : GDALWriteWorldFile( osFilename, "tfw", adfGeoTransform );
4788 703 : else if( CSLFetchBoolean( papszCreationOptions, "WORLDFILE", FALSE ) )
4789 2 : GDALWriteWorldFile( osFilename, "wld", adfGeoTransform );
4790 : }
4791 281 : else if( GetGCPCount() > 0 )
4792 : {
4793 : double *padfTiePoints;
4794 : int iGCP;
4795 :
4796 2 : bNeedsRewrite = TRUE;
4797 :
4798 : padfTiePoints = (double *)
4799 2 : CPLMalloc( 6 * sizeof(double) * GetGCPCount() );
4800 :
4801 14 : for( iGCP = 0; iGCP < GetGCPCount(); iGCP++ )
4802 : {
4803 :
4804 12 : padfTiePoints[iGCP*6+0] = pasGCPList[iGCP].dfGCPPixel;
4805 12 : padfTiePoints[iGCP*6+1] = pasGCPList[iGCP].dfGCPLine;
4806 12 : padfTiePoints[iGCP*6+2] = 0;
4807 12 : padfTiePoints[iGCP*6+3] = pasGCPList[iGCP].dfGCPX;
4808 12 : padfTiePoints[iGCP*6+4] = pasGCPList[iGCP].dfGCPY;
4809 12 : padfTiePoints[iGCP*6+5] = pasGCPList[iGCP].dfGCPZ;
4810 :
4811 12 : if( bPixelIsPoint && !bPointGeoIgnore )
4812 : {
4813 0 : padfTiePoints[iGCP*6+0] += 0.5;
4814 0 : padfTiePoints[iGCP*6+1] += 0.5;
4815 : }
4816 : }
4817 :
4818 2 : if( !EQUAL(osProfile,"BASELINE") )
4819 : TIFFSetField( hTIFF, TIFFTAG_GEOTIEPOINTS,
4820 2 : 6 * GetGCPCount(), padfTiePoints );
4821 2 : CPLFree( padfTiePoints );
4822 : }
4823 :
4824 : /* -------------------------------------------------------------------- */
4825 : /* Write out projection definition. */
4826 : /* -------------------------------------------------------------------- */
4827 986 : if( pszProjection != NULL && !EQUAL( pszProjection, "" )
4828 : && !EQUAL(osProfile,"BASELINE") )
4829 : {
4830 : GTIF *psGTIF;
4831 :
4832 748 : bNeedsRewrite = TRUE;
4833 :
4834 : // If we have existing geokeys, try to wipe them
4835 : // by writing a dummy goekey directory. (#2546)
4836 748 : uint16 *panVI = NULL;
4837 : uint16 nKeyCount;
4838 :
4839 748 : if( TIFFGetField( hTIFF, TIFFTAG_GEOKEYDIRECTORY,
4840 : &nKeyCount, &panVI ) )
4841 : {
4842 9 : GUInt16 anGKVersionInfo[4] = { 1, 1, 0, 0 };
4843 9 : double adfDummyDoubleParams[1] = { 0.0 };
4844 : TIFFSetField( hTIFF, TIFFTAG_GEOKEYDIRECTORY,
4845 9 : 4, anGKVersionInfo );
4846 : TIFFSetField( hTIFF, TIFFTAG_GEODOUBLEPARAMS,
4847 9 : 1, adfDummyDoubleParams );
4848 9 : TIFFSetField( hTIFF, TIFFTAG_GEOASCIIPARAMS, "" );
4849 : }
4850 :
4851 748 : psGTIF = GTIFNew( hTIFF );
4852 :
4853 : // set according to coordinate system.
4854 748 : GTIFSetFromOGISDefn( psGTIF, pszProjection );
4855 :
4856 748 : if( bPixelIsPoint )
4857 : {
4858 : GTIFKeySet(psGTIF, GTRasterTypeGeoKey, TYPE_SHORT, 1,
4859 4 : RasterPixelIsPoint);
4860 : }
4861 :
4862 748 : GTIFWriteKeys( psGTIF );
4863 748 : GTIFFree( psGTIF );
4864 : }
4865 986 : }
4866 :
4867 : /************************************************************************/
4868 : /* AppendMetadataItem() */
4869 : /************************************************************************/
4870 :
4871 269 : static void AppendMetadataItem( CPLXMLNode **ppsRoot, CPLXMLNode **ppsTail,
4872 : const char *pszKey, const char *pszValue,
4873 : int nBand, const char *pszRole,
4874 : const char *pszDomain )
4875 :
4876 : {
4877 : char szBandId[32];
4878 : CPLXMLNode *psItem;
4879 :
4880 : /* -------------------------------------------------------------------- */
4881 : /* Create the Item element, and subcomponents. */
4882 : /* -------------------------------------------------------------------- */
4883 269 : psItem = CPLCreateXMLNode( NULL, CXT_Element, "Item" );
4884 : CPLCreateXMLNode( CPLCreateXMLNode( psItem, CXT_Attribute, "name"),
4885 269 : CXT_Text, pszKey );
4886 :
4887 269 : if( nBand > 0 )
4888 : {
4889 52 : sprintf( szBandId, "%d", nBand - 1 );
4890 : CPLCreateXMLNode( CPLCreateXMLNode( psItem,CXT_Attribute,"sample"),
4891 52 : CXT_Text, szBandId );
4892 : }
4893 :
4894 269 : if( pszRole != NULL )
4895 : CPLCreateXMLNode( CPLCreateXMLNode( psItem,CXT_Attribute,"role"),
4896 10 : CXT_Text, pszRole );
4897 :
4898 269 : if( pszDomain != NULL && strlen(pszDomain) > 0 )
4899 : CPLCreateXMLNode( CPLCreateXMLNode( psItem,CXT_Attribute,"domain"),
4900 3 : CXT_Text, pszDomain );
4901 :
4902 269 : char *pszEscapedItemValue = CPLEscapeString(pszValue,-1,CPLES_XML);
4903 269 : CPLCreateXMLNode( psItem, CXT_Text, pszEscapedItemValue );
4904 269 : CPLFree( pszEscapedItemValue );
4905 :
4906 : /* -------------------------------------------------------------------- */
4907 : /* Create root, if missing. */
4908 : /* -------------------------------------------------------------------- */
4909 269 : if( *ppsRoot == NULL )
4910 75 : *ppsRoot = CPLCreateXMLNode( NULL, CXT_Element, "GDALMetadata" );
4911 :
4912 : /* -------------------------------------------------------------------- */
4913 : /* Append item to tail. We keep track of the tail to avoid */
4914 : /* O(nsquared) time as the list gets longer. */
4915 : /* -------------------------------------------------------------------- */
4916 269 : if( *ppsTail == NULL )
4917 75 : CPLAddXMLChild( *ppsRoot, psItem );
4918 : else
4919 194 : CPLAddXMLSibling( *ppsTail, psItem );
4920 :
4921 269 : *ppsTail = psItem;
4922 269 : }
4923 :
4924 : /************************************************************************/
4925 : /* WriteMDMDMetadata() */
4926 : /************************************************************************/
4927 :
4928 133465 : static void WriteMDMetadata( GDALMultiDomainMetadata *poMDMD, TIFF *hTIFF,
4929 : CPLXMLNode **ppsRoot, CPLXMLNode **ppsTail,
4930 : int nBand, const char *pszProfile )
4931 :
4932 : {
4933 : int iDomain;
4934 : char **papszDomainList;
4935 :
4936 : (void) pszProfile;
4937 :
4938 : /* ==================================================================== */
4939 : /* Process each domain. */
4940 : /* ==================================================================== */
4941 133465 : papszDomainList = poMDMD->GetDomainList();
4942 134021 : for( iDomain = 0; papszDomainList && papszDomainList[iDomain]; iDomain++ )
4943 : {
4944 556 : char **papszMD = poMDMD->GetMetadata( papszDomainList[iDomain] );
4945 : int iItem;
4946 556 : int bIsXML = FALSE;
4947 :
4948 556 : if( EQUAL(papszDomainList[iDomain], "IMAGE_STRUCTURE") )
4949 57 : continue; // ignored
4950 499 : if( EQUAL(papszDomainList[iDomain], "RPC") )
4951 0 : continue; // handled elsewhere
4952 499 : if( EQUAL(papszDomainList[iDomain], "xml:ESRI")
4953 : && CSLTestBoolean(CPLGetConfigOption( "ESRI_XML_PAM", "NO" )) )
4954 1 : continue; // handled elsewhere
4955 :
4956 498 : if( EQUALN(papszDomainList[iDomain], "xml:",4 ) )
4957 2 : bIsXML = TRUE;
4958 :
4959 : /* -------------------------------------------------------------------- */
4960 : /* Process each item in this domain. */
4961 : /* -------------------------------------------------------------------- */
4962 1185 : for( iItem = 0; papszMD && papszMD[iItem]; iItem++ )
4963 : {
4964 : const char *pszItemValue;
4965 687 : char *pszItemName = NULL;
4966 :
4967 687 : if( bIsXML )
4968 : {
4969 2 : pszItemName = CPLStrdup("doc");
4970 2 : pszItemValue = papszMD[iItem];
4971 : }
4972 : else
4973 : {
4974 685 : pszItemValue = CPLParseNameValue( papszMD[iItem], &pszItemName);
4975 685 : if( pszItemName == NULL )
4976 : {
4977 1 : CPLDebug("GTiff", "Invalid metadata item : %s", papszMD[iItem]);
4978 1 : continue;
4979 : }
4980 : }
4981 :
4982 : /* -------------------------------------------------------------------- */
4983 : /* Convert into XML item or handle as a special TIFF tag. */
4984 : /* -------------------------------------------------------------------- */
4985 715 : if( strlen(papszDomainList[iDomain]) == 0
4986 : && nBand == 0 && EQUALN(pszItemName,"TIFFTAG_",8) )
4987 : {
4988 29 : if( EQUAL(pszItemName,"TIFFTAG_DOCUMENTNAME") )
4989 4 : TIFFSetField( hTIFF, TIFFTAG_DOCUMENTNAME, pszItemValue );
4990 25 : else if( EQUAL(pszItemName,"TIFFTAG_IMAGEDESCRIPTION") )
4991 1 : TIFFSetField( hTIFF, TIFFTAG_IMAGEDESCRIPTION, pszItemValue );
4992 24 : else if( EQUAL(pszItemName,"TIFFTAG_SOFTWARE") )
4993 2 : TIFFSetField( hTIFF, TIFFTAG_SOFTWARE, pszItemValue );
4994 22 : else if( EQUAL(pszItemName,"TIFFTAG_DATETIME") )
4995 1 : TIFFSetField( hTIFF, TIFFTAG_DATETIME, pszItemValue );
4996 21 : else if( EQUAL(pszItemName,"TIFFTAG_ARTIST") )
4997 1 : TIFFSetField( hTIFF, TIFFTAG_ARTIST, pszItemValue );
4998 20 : else if( EQUAL(pszItemName,"TIFFTAG_HOSTCOMPUTER") )
4999 1 : TIFFSetField( hTIFF, TIFFTAG_HOSTCOMPUTER, pszItemValue );
5000 19 : else if( EQUAL(pszItemName,"TIFFTAG_COPYRIGHT") )
5001 1 : TIFFSetField( hTIFF, TIFFTAG_COPYRIGHT, pszItemValue );
5002 18 : else if( EQUAL(pszItemName,"TIFFTAG_XRESOLUTION") )
5003 6 : TIFFSetField( hTIFF, TIFFTAG_XRESOLUTION, CPLAtof(pszItemValue) );
5004 12 : else if( EQUAL(pszItemName,"TIFFTAG_YRESOLUTION") )
5005 6 : TIFFSetField( hTIFF, TIFFTAG_YRESOLUTION, CPLAtof(pszItemValue) );
5006 6 : else if( EQUAL(pszItemName,"TIFFTAG_RESOLUTIONUNIT") )
5007 6 : TIFFSetField( hTIFF, TIFFTAG_RESOLUTIONUNIT, atoi(pszItemValue) );
5008 0 : else if( EQUAL(pszItemName,"TIFFTAG_MINSAMPLEVALUE") )
5009 0 : TIFFSetField( hTIFF, TIFFTAG_MINSAMPLEVALUE, atoi(pszItemValue) );
5010 0 : else if( EQUAL(pszItemName,"TIFFTAG_MAXSAMPLEVALUE") )
5011 0 : TIFFSetField( hTIFF, TIFFTAG_MAXSAMPLEVALUE, atoi(pszItemValue) );
5012 : else
5013 : CPLError(CE_Warning, CPLE_NotSupported,
5014 : "%s metadata item is unhandled and will not be written",
5015 0 : pszItemName);
5016 : }
5017 657 : else if( nBand == 0 && EQUAL(pszItemName,GDALMD_AREA_OR_POINT) )
5018 : /* do nothing, handled elsewhere */;
5019 : else
5020 : AppendMetadataItem( ppsRoot, ppsTail,
5021 : pszItemName, pszItemValue,
5022 259 : nBand, NULL, papszDomainList[iDomain] );
5023 :
5024 686 : CPLFree( pszItemName );
5025 : }
5026 : }
5027 133465 : }
5028 :
5029 : /************************************************************************/
5030 : /* WriteMetadata() */
5031 : /************************************************************************/
5032 :
5033 1220 : int GTiffDataset::WriteMetadata( GDALDataset *poSrcDS, TIFF *hTIFF,
5034 : int bSrcIsGeoTIFF,
5035 : const char *pszProfile,
5036 : const char *pszTIFFFilename,
5037 : char **papszCreationOptions,
5038 : int bExcludeRPBandIMGFileWriting)
5039 :
5040 : {
5041 : /* -------------------------------------------------------------------- */
5042 : /* Convert all the remaining metadata into a simple XML */
5043 : /* format. */
5044 : /* -------------------------------------------------------------------- */
5045 1220 : CPLXMLNode *psRoot = NULL, *psTail = NULL;
5046 :
5047 1220 : if( bSrcIsGeoTIFF )
5048 : {
5049 : WriteMDMetadata( &(((GTiffDataset *)poSrcDS)->oGTiffMDMD),
5050 991 : hTIFF, &psRoot, &psTail, 0, pszProfile );
5051 : }
5052 : else
5053 : {
5054 229 : char **papszMD = poSrcDS->GetMetadata();
5055 :
5056 229 : if( CSLCount(papszMD) > 0 )
5057 : {
5058 153 : GDALMultiDomainMetadata oMDMD;
5059 153 : oMDMD.SetMetadata( papszMD );
5060 :
5061 153 : WriteMDMetadata( &oMDMD, hTIFF, &psRoot, &psTail, 0, pszProfile );
5062 : }
5063 : }
5064 :
5065 : /* -------------------------------------------------------------------- */
5066 : /* Handle RPC data written to an RPB file. */
5067 : /* -------------------------------------------------------------------- */
5068 1220 : char **papszRPCMD = poSrcDS->GetMetadata("RPC");
5069 1220 : if( papszRPCMD != NULL && !bExcludeRPBandIMGFileWriting )
5070 : {
5071 4 : if( EQUAL(pszProfile,"GDALGeoTIFF") )
5072 2 : WriteRPCTag( hTIFF, papszRPCMD );
5073 :
5074 4 : if( !EQUAL(pszProfile,"GDALGeoTIFF")
5075 : || CSLFetchBoolean( papszCreationOptions, "RPB", FALSE ) )
5076 : {
5077 2 : GDALWriteRPBFile( pszTIFFFilename, papszRPCMD );
5078 : }
5079 : }
5080 :
5081 : /* -------------------------------------------------------------------- */
5082 : /* Handle metadata data written to an IMD file. */
5083 : /* -------------------------------------------------------------------- */
5084 1220 : char **papszIMDMD = poSrcDS->GetMetadata("IMD");
5085 1220 : if( papszIMDMD != NULL && !bExcludeRPBandIMGFileWriting)
5086 : {
5087 4 : GDALWriteIMDFile( pszTIFFFilename, papszIMDMD );
5088 : }
5089 :
5090 : /* -------------------------------------------------------------------- */
5091 : /* We also need to address band specific metadata, and special */
5092 : /* "role" metadata. */
5093 : /* -------------------------------------------------------------------- */
5094 : int nBand;
5095 133874 : for( nBand = 1; nBand <= poSrcDS->GetRasterCount(); nBand++ )
5096 : {
5097 132654 : GDALRasterBand *poBand = poSrcDS->GetRasterBand( nBand );
5098 :
5099 132654 : if( bSrcIsGeoTIFF )
5100 : {
5101 : WriteMDMetadata( &(((GTiffRasterBand *)poBand)->oGTiffMDMD),
5102 132294 : hTIFF, &psRoot, &psTail, nBand, pszProfile );
5103 : }
5104 : else
5105 : {
5106 360 : char **papszMD = poBand->GetMetadata();
5107 :
5108 360 : if( CSLCount(papszMD) > 0 )
5109 : {
5110 27 : GDALMultiDomainMetadata oMDMD;
5111 27 : oMDMD.SetMetadata( papszMD );
5112 :
5113 : WriteMDMetadata( &oMDMD, hTIFF, &psRoot, &psTail, nBand,
5114 27 : pszProfile );
5115 : }
5116 : }
5117 :
5118 132654 : double dfOffset = poBand->GetOffset();
5119 132654 : double dfScale = poBand->GetScale();
5120 :
5121 132654 : if( dfOffset != 0.0 || dfScale != 1.0 )
5122 : {
5123 : char szValue[128];
5124 :
5125 2 : sprintf( szValue, "%.18g", dfOffset );
5126 : AppendMetadataItem( &psRoot, &psTail, "OFFSET", szValue, nBand,
5127 2 : "offset", "" );
5128 2 : sprintf( szValue, "%.18g", dfScale );
5129 : AppendMetadataItem( &psRoot, &psTail, "SCALE", szValue, nBand,
5130 2 : "scale", "" );
5131 : }
5132 :
5133 132654 : const char* pszUnitType = poBand->GetUnitType();
5134 132654 : if (pszUnitType != NULL && pszUnitType[0] != '\0')
5135 : AppendMetadataItem( &psRoot, &psTail, "UNITTYPE", pszUnitType, nBand,
5136 5 : "unittype", "" );
5137 :
5138 :
5139 132654 : if (strlen(poBand->GetDescription()) > 0)
5140 : {
5141 : AppendMetadataItem( &psRoot, &psTail, "DESCRIPTION",
5142 1 : poBand->GetDescription(), nBand,
5143 2 : "description", "" );
5144 : }
5145 : }
5146 :
5147 : /* -------------------------------------------------------------------- */
5148 : /* Write out the generic XML metadata if there is any. */
5149 : /* -------------------------------------------------------------------- */
5150 1220 : if( psRoot != NULL )
5151 : {
5152 75 : int bRet = TRUE;
5153 :
5154 75 : if( EQUAL(pszProfile,"GDALGeoTIFF") )
5155 : {
5156 65 : char *pszXML_MD = CPLSerializeXMLTree( psRoot );
5157 65 : if( strlen(pszXML_MD) > 32000 )
5158 : {
5159 1 : if( bSrcIsGeoTIFF )
5160 1 : ((GTiffDataset *) poSrcDS)->PushMetadataToPam();
5161 : else
5162 0 : bRet = FALSE;
5163 : CPLError( CE_Warning, CPLE_AppDefined,
5164 1 : "Lost metadata writing to GeoTIFF ... too large to fit in tag." );
5165 : }
5166 : else
5167 : {
5168 64 : TIFFSetField( hTIFF, TIFFTAG_GDAL_METADATA, pszXML_MD );
5169 : }
5170 65 : CPLFree( pszXML_MD );
5171 : }
5172 : else
5173 : {
5174 10 : if( bSrcIsGeoTIFF )
5175 6 : ((GTiffDataset *) poSrcDS)->PushMetadataToPam();
5176 : else
5177 4 : bRet = FALSE;
5178 : }
5179 :
5180 75 : CPLDestroyXMLNode( psRoot );
5181 :
5182 75 : return bRet;
5183 : }
5184 : else
5185 : {
5186 : /* If we have no more metadata but it existed before, remove the GDAL_METADATA tag */
5187 1145 : if( EQUAL(pszProfile,"GDALGeoTIFF") )
5188 : {
5189 1139 : char* pszText = NULL;
5190 1139 : if( TIFFGetField( hTIFF, TIFFTAG_GDAL_METADATA, &pszText ) )
5191 : {
5192 : #ifdef HAVE_UNSETFIELD
5193 2 : TIFFUnsetField( hTIFF, TIFFTAG_GDAL_METADATA );
5194 : #else
5195 : TIFFSetField( hTIFF, TIFFTAG_GDAL_METADATA, "" );
5196 : #endif
5197 : }
5198 : }
5199 : }
5200 :
5201 1145 : return TRUE;
5202 : }
5203 :
5204 : /************************************************************************/
5205 : /* PushMetadataToPam() */
5206 : /* */
5207 : /* When producing a strict profile TIFF or if our aggregate */
5208 : /* metadata is too big for a single tiff tag we may end up */
5209 : /* needing to write it via the PAM mechanisms. This method */
5210 : /* copies all the appropriate metadata into the PAM level */
5211 : /* metadata object but with special care to avoid copying */
5212 : /* metadata handled in other ways in TIFF format. */
5213 : /************************************************************************/
5214 :
5215 38 : void GTiffDataset::PushMetadataToPam()
5216 :
5217 : {
5218 : int nBand;
5219 126 : for( nBand = 0; nBand <= GetRasterCount(); nBand++ )
5220 : {
5221 : GDALMultiDomainMetadata *poSrcMDMD;
5222 88 : GTiffRasterBand *poBand = NULL;
5223 :
5224 88 : if( nBand == 0 )
5225 38 : poSrcMDMD = &(this->oGTiffMDMD);
5226 : else
5227 : {
5228 50 : poBand = (GTiffRasterBand *) GetRasterBand(nBand);
5229 50 : poSrcMDMD = &(poBand->oGTiffMDMD);
5230 : }
5231 :
5232 : /* -------------------------------------------------------------------- */
5233 : /* Loop over the available domains. */
5234 : /* -------------------------------------------------------------------- */
5235 : int iDomain, i;
5236 : char **papszDomainList;
5237 :
5238 88 : papszDomainList = poSrcMDMD->GetDomainList();
5239 379 : for( iDomain = 0;
5240 185 : papszDomainList && papszDomainList[iDomain];
5241 : iDomain++ )
5242 : {
5243 106 : char **papszMD = poSrcMDMD->GetMetadata( papszDomainList[iDomain] );
5244 :
5245 424 : if( EQUAL(papszDomainList[iDomain],"RPC")
5246 106 : || EQUAL(papszDomainList[iDomain],"IMD")
5247 106 : || EQUAL(papszDomainList[iDomain],"_temporary_")
5248 106 : || EQUAL(papszDomainList[iDomain],"IMAGE_STRUCTURE") )
5249 41 : continue;
5250 :
5251 65 : papszMD = CSLDuplicate(papszMD);
5252 :
5253 228 : for( i = CSLCount(papszMD)-1; i >= 0; i-- )
5254 : {
5255 320 : if( EQUALN(papszMD[i],"TIFFTAG_",8)
5256 157 : || EQUALN(papszMD[i],GDALMD_AREA_OR_POINT,
5257 : strlen(GDALMD_AREA_OR_POINT)) )
5258 27 : papszMD = CSLRemoveStrings( papszMD, i, 1, NULL );
5259 : }
5260 :
5261 65 : if( nBand == 0 )
5262 28 : GDALPamDataset::SetMetadata( papszMD, papszDomainList[iDomain]);
5263 : else
5264 37 : poBand->GDALPamRasterBand::SetMetadata( papszMD, papszDomainList[iDomain]);
5265 :
5266 65 : CSLDestroy( papszMD );
5267 : }
5268 :
5269 : /* -------------------------------------------------------------------- */
5270 : /* Handle some "special domain" stuff. */
5271 : /* -------------------------------------------------------------------- */
5272 88 : if( poBand != NULL )
5273 : {
5274 50 : poBand->GDALPamRasterBand::SetOffset( poBand->GetOffset() );
5275 50 : poBand->GDALPamRasterBand::SetScale( poBand->GetScale() );
5276 50 : poBand->GDALPamRasterBand::SetUnitType( poBand->GetUnitType() );
5277 50 : poBand->GDALPamRasterBand::SetDescription( poBand->GetDescription() );
5278 : }
5279 : }
5280 38 : }
5281 :
5282 : /************************************************************************/
5283 : /* WriteRPCTag() */
5284 : /* */
5285 : /* Format a TAG according to: */
5286 : /* */
5287 : /* http://geotiff.maptools.org/rpc_prop.html */
5288 : /************************************************************************/
5289 :
5290 : /* static */
5291 2 : void GTiffDataset::WriteRPCTag( TIFF *hTIFF, char **papszRPCMD )
5292 :
5293 : {
5294 : double adfRPCTag[92];
5295 : GDALRPCInfo sRPC;
5296 :
5297 2 : if( !GDALExtractRPCInfo( papszRPCMD, &sRPC ) )
5298 0 : return;
5299 :
5300 2 : adfRPCTag[0] = -1.0; // Error Bias
5301 2 : adfRPCTag[1] = -1.0; // Error Random
5302 :
5303 2 : adfRPCTag[2] = sRPC.dfLINE_OFF;
5304 2 : adfRPCTag[3] = sRPC.dfSAMP_OFF;
5305 2 : adfRPCTag[4] = sRPC.dfLAT_OFF;
5306 2 : adfRPCTag[5] = sRPC.dfLONG_OFF;
5307 2 : adfRPCTag[6] = sRPC.dfHEIGHT_OFF;
5308 2 : adfRPCTag[7] = sRPC.dfLINE_SCALE;
5309 2 : adfRPCTag[8] = sRPC.dfSAMP_SCALE;
5310 2 : adfRPCTag[9] = sRPC.dfLAT_SCALE;
5311 2 : adfRPCTag[10] = sRPC.dfLONG_SCALE;
5312 2 : adfRPCTag[11] = sRPC.dfHEIGHT_SCALE;
5313 :
5314 2 : memcpy( adfRPCTag + 12, sRPC.adfLINE_NUM_COEFF, sizeof(double) * 20 );
5315 2 : memcpy( adfRPCTag + 32, sRPC.adfLINE_DEN_COEFF, sizeof(double) * 20 );
5316 2 : memcpy( adfRPCTag + 52, sRPC.adfSAMP_NUM_COEFF, sizeof(double) * 20 );
5317 2 : memcpy( adfRPCTag + 72, sRPC.adfSAMP_DEN_COEFF, sizeof(double) * 20 );
5318 :
5319 2 : TIFFSetField( hTIFF, TIFFTAG_RPCCOEFFICIENT, 92, adfRPCTag );
5320 : }
5321 :
5322 : /************************************************************************/
5323 : /* ReadRPCTag() */
5324 : /* */
5325 : /* Format a TAG according to: */
5326 : /* */
5327 : /* http://geotiff.maptools.org/rpc_prop.html */
5328 : /************************************************************************/
5329 :
5330 2238 : void GTiffDataset::ReadRPCTag()
5331 :
5332 : {
5333 : double *padfRPCTag;
5334 2238 : char **papszMD = NULL;
5335 2238 : CPLString osField;
5336 2238 : CPLString osMultiField;
5337 : int i;
5338 : uint16 nCount;
5339 :
5340 2238 : if( !TIFFGetField( hTIFF, TIFFTAG_RPCCOEFFICIENT, &nCount, &padfRPCTag )
5341 : || nCount != 92 )
5342 : return;
5343 :
5344 6 : osField.Printf( "%.15g", padfRPCTag[2] );
5345 6 : papszMD = CSLSetNameValue( papszMD, "LINE_OFF", osField );
5346 :
5347 6 : osField.Printf( "%.15g", padfRPCTag[3] );
5348 6 : papszMD = CSLSetNameValue( papszMD, "SAMP_OFF", osField );
5349 :
5350 6 : osField.Printf( "%.15g", padfRPCTag[4] );
5351 6 : papszMD = CSLSetNameValue( papszMD, "LAT_OFF", osField );
5352 :
5353 6 : osField.Printf( "%.15g", padfRPCTag[5] );
5354 6 : papszMD = CSLSetNameValue( papszMD, "LONG_OFF", osField );
5355 :
5356 6 : osField.Printf( "%.15g", padfRPCTag[6] );
5357 6 : papszMD = CSLSetNameValue( papszMD, "HEIGHT_OFF", osField );
5358 :
5359 6 : osField.Printf( "%.15g", padfRPCTag[7] );
5360 6 : papszMD = CSLSetNameValue( papszMD, "LINE_SCALE", osField );
5361 :
5362 6 : osField.Printf( "%.15g", padfRPCTag[8] );
5363 6 : papszMD = CSLSetNameValue( papszMD, "SAMP_SCALE", osField );
5364 :
5365 6 : osField.Printf( "%.15g", padfRPCTag[9] );
5366 6 : papszMD = CSLSetNameValue( papszMD, "LAT_SCALE", osField );
5367 :
5368 6 : osField.Printf( "%.15g", padfRPCTag[10] );
5369 6 : papszMD = CSLSetNameValue( papszMD, "LONG_SCALE", osField );
5370 :
5371 6 : osField.Printf( "%.15g", padfRPCTag[11] );
5372 6 : papszMD = CSLSetNameValue( papszMD, "HEIGHT_SCALE", osField );
5373 :
5374 126 : for( i = 0; i < 20; i++ )
5375 : {
5376 120 : osField.Printf( "%.15g", padfRPCTag[12+i] );
5377 120 : if( i > 0 )
5378 114 : osMultiField += " ";
5379 : else
5380 6 : osMultiField = "";
5381 120 : osMultiField += osField;
5382 : }
5383 6 : papszMD = CSLSetNameValue( papszMD, "LINE_NUM_COEFF", osMultiField );
5384 :
5385 126 : for( i = 0; i < 20; i++ )
5386 : {
5387 120 : osField.Printf( "%.15g", padfRPCTag[32+i] );
5388 120 : if( i > 0 )
5389 114 : osMultiField += " ";
5390 : else
5391 6 : osMultiField = "";
5392 120 : osMultiField += osField;
5393 : }
5394 6 : papszMD = CSLSetNameValue( papszMD, "LINE_DEN_COEFF", osMultiField );
5395 :
5396 126 : for( i = 0; i < 20; i++ )
5397 : {
5398 120 : osField.Printf( "%.15g", padfRPCTag[52+i] );
5399 120 : if( i > 0 )
5400 114 : osMultiField += " ";
5401 : else
5402 6 : osMultiField = "";
5403 120 : osMultiField += osField;
5404 : }
5405 6 : papszMD = CSLSetNameValue( papszMD, "SAMP_NUM_COEFF", osMultiField );
5406 :
5407 126 : for( i = 0; i < 20; i++ )
5408 : {
5409 120 : osField.Printf( "%.15g", padfRPCTag[72+i] );
5410 120 : if( i > 0 )
5411 114 : osMultiField += " ";
5412 : else
5413 6 : osMultiField = "";
5414 120 : osMultiField += osField;
5415 : }
5416 6 : papszMD = CSLSetNameValue( papszMD, "SAMP_DEN_COEFF", osMultiField );
5417 :
5418 6 : oGTiffMDMD.SetMetadata( papszMD, "RPC" );
5419 6 : CSLDestroy( papszMD );
5420 : }
5421 :
5422 : /************************************************************************/
5423 : /* WriteNoDataValue() */
5424 : /************************************************************************/
5425 :
5426 78 : void GTiffDataset::WriteNoDataValue( TIFF *hTIFF, double dfNoData )
5427 :
5428 : {
5429 : char szVal[400];
5430 78 : if (CPLIsNan(dfNoData))
5431 3 : strcpy(szVal, "nan");
5432 : else
5433 75 : snprintf(szVal, sizeof(szVal), "%.18g", dfNoData);
5434 78 : TIFFSetField( hTIFF, TIFFTAG_GDAL_NODATA, szVal );
5435 78 : }
5436 :
5437 : /************************************************************************/
5438 : /* SetDirectory() */
5439 : /************************************************************************/
5440 :
5441 225586 : int GTiffDataset::SetDirectory( toff_t nNewOffset )
5442 :
5443 : {
5444 225586 : Crystalize();
5445 :
5446 225586 : FlushBlockBuf();
5447 :
5448 225586 : if( nNewOffset == 0 )
5449 221309 : nNewOffset = nDirOffset;
5450 :
5451 225586 : if( TIFFCurrentDirOffset(hTIFF) == nNewOffset )
5452 : {
5453 224021 : CPLAssert( *ppoActiveDSRef == this || *ppoActiveDSRef == NULL );
5454 224021 : *ppoActiveDSRef = this;
5455 224021 : return TRUE;
5456 : }
5457 :
5458 1565 : if( GetAccess() == GA_Update )
5459 : {
5460 1267 : if( *ppoActiveDSRef != NULL )
5461 1141 : (*ppoActiveDSRef)->FlushDirectory();
5462 : }
5463 :
5464 1565 : if( nNewOffset == 0)
5465 0 : return TRUE;
5466 :
5467 1565 : (*ppoActiveDSRef) = this;
5468 :
5469 1565 : int nSetDirResult = TIFFSetSubDirectory( hTIFF, nNewOffset );
5470 1565 : if (!nSetDirResult)
5471 0 : return nSetDirResult;
5472 :
5473 : /* -------------------------------------------------------------------- */
5474 : /* YCbCr JPEG compressed images should be translated on the fly */
5475 : /* to RGB by libtiff/libjpeg unless specifically requested */
5476 : /* otherwise. */
5477 : /* -------------------------------------------------------------------- */
5478 1565 : if( !TIFFGetField( hTIFF, TIFFTAG_COMPRESSION, &(nCompression) ) )
5479 0 : nCompression = COMPRESSION_NONE;
5480 :
5481 1565 : if( !TIFFGetField( hTIFF, TIFFTAG_PHOTOMETRIC, &(nPhotometric) ) )
5482 0 : nPhotometric = PHOTOMETRIC_MINISBLACK;
5483 :
5484 1565 : if( nCompression == COMPRESSION_JPEG
5485 : && nPhotometric == PHOTOMETRIC_YCBCR
5486 : && CSLTestBoolean( CPLGetConfigOption("CONVERT_YCBCR_TO_RGB",
5487 : "YES") ) )
5488 : {
5489 : int nColorMode;
5490 :
5491 216 : TIFFGetField( hTIFF, TIFFTAG_JPEGCOLORMODE, &nColorMode );
5492 216 : if( nColorMode != JPEGCOLORMODE_RGB )
5493 216 : TIFFSetField(hTIFF, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
5494 : }
5495 :
5496 : /* -------------------------------------------------------------------- */
5497 : /* Propogate any quality settings. */
5498 : /* -------------------------------------------------------------------- */
5499 1565 : if( GetAccess() == GA_Update )
5500 : {
5501 : // Now, reset zip and jpeg quality.
5502 1267 : if(nJpegQuality > 0 && nCompression == COMPRESSION_JPEG)
5503 : {
5504 : CPLDebug( "GTiff", "Propgate JPEG_QUALITY(%d) in SetDirectory()",
5505 134 : nJpegQuality );
5506 134 : TIFFSetField(hTIFF, TIFFTAG_JPEGQUALITY, nJpegQuality);
5507 : }
5508 1267 : if(nZLevel > 0 && nCompression == COMPRESSION_ADOBE_DEFLATE)
5509 0 : TIFFSetField(hTIFF, TIFFTAG_ZIPQUALITY, nZLevel);
5510 1267 : if(nLZMAPreset > 0 && nCompression == COMPRESSION_LZMA)
5511 0 : TIFFSetField(hTIFF, TIFFTAG_LZMAPRESET, nLZMAPreset);
5512 : }
5513 :
5514 1565 : return nSetDirResult;
5515 : }
5516 :
5517 : /************************************************************************/
5518 : /* Identify() */
5519 : /************************************************************************/
5520 :
5521 19339 : int GTiffDataset::Identify( GDALOpenInfo * poOpenInfo )
5522 :
5523 : {
5524 19339 : const char *pszFilename = poOpenInfo->pszFilename;
5525 19339 : if( EQUALN(pszFilename,"GTIFF_RAW:", strlen("GTIFF_RAW:")) )
5526 : {
5527 235 : pszFilename += strlen("GTIFF_RAW:");
5528 235 : GDALOpenInfo oOpenInfo( pszFilename, poOpenInfo->eAccess );
5529 235 : return Identify(&oOpenInfo);
5530 : }
5531 :
5532 : /* -------------------------------------------------------------------- */
5533 : /* We have a special hook for handling opening a specific */
5534 : /* directory of a TIFF file. */
5535 : /* -------------------------------------------------------------------- */
5536 19104 : if( EQUALN(pszFilename,"GTIFF_DIR:",strlen("GTIFF_DIR:")) )
5537 6 : return TRUE;
5538 :
5539 : /* -------------------------------------------------------------------- */
5540 : /* First we check to see if the file has the expected header */
5541 : /* bytes. */
5542 : /* -------------------------------------------------------------------- */
5543 19098 : if( poOpenInfo->nHeaderBytes < 2 )
5544 11824 : return FALSE;
5545 :
5546 10777 : if( (poOpenInfo->pabyHeader[0] != 'I' || poOpenInfo->pabyHeader[1] != 'I')
5547 3503 : && (poOpenInfo->pabyHeader[0] != 'M' || poOpenInfo->pabyHeader[1] != 'M'))
5548 3348 : return FALSE;
5549 :
5550 : #ifndef BIGTIFF_SUPPORT
5551 : if( (poOpenInfo->pabyHeader[2] == 0x2B && poOpenInfo->pabyHeader[3] == 0) ||
5552 : (poOpenInfo->pabyHeader[2] == 0 && poOpenInfo->pabyHeader[3] == 0x2B) )
5553 : {
5554 : CPLError( CE_Failure, CPLE_OpenFailed,
5555 : "This is a BigTIFF file. BigTIFF is not supported by this\n"
5556 : "version of GDAL and libtiff." );
5557 : return FALSE;
5558 : }
5559 : #endif
5560 :
5561 4201 : if( (poOpenInfo->pabyHeader[2] != 0x2A || poOpenInfo->pabyHeader[3] != 0)
5562 181 : && (poOpenInfo->pabyHeader[3] != 0x2A || poOpenInfo->pabyHeader[2] != 0)
5563 78 : && (poOpenInfo->pabyHeader[2] != 0x2B || poOpenInfo->pabyHeader[3] != 0)
5564 16 : && (poOpenInfo->pabyHeader[3] != 0x2B || poOpenInfo->pabyHeader[2] != 0))
5565 0 : return FALSE;
5566 :
5567 3926 : return TRUE;
5568 : }
5569 :
5570 : /************************************************************************/
5571 : /* Open() */
5572 : /************************************************************************/
5573 :
5574 8781 : GDALDataset *GTiffDataset::Open( GDALOpenInfo * poOpenInfo )
5575 :
5576 : {
5577 : TIFF *hTIFF;
5578 8781 : int bAllowRGBAInterface = TRUE;
5579 8781 : const char *pszFilename = poOpenInfo->pszFilename;
5580 :
5581 : /* -------------------------------------------------------------------- */
5582 : /* Check if it looks like a TIFF file. */
5583 : /* -------------------------------------------------------------------- */
5584 8781 : if (!Identify(poOpenInfo))
5585 4888 : return NULL;
5586 :
5587 3893 : if( EQUALN(pszFilename,"GTIFF_RAW:", strlen("GTIFF_RAW:")) )
5588 : {
5589 235 : bAllowRGBAInterface = FALSE;
5590 235 : pszFilename += strlen("GTIFF_RAW:");
5591 : }
5592 :
5593 : /* -------------------------------------------------------------------- */
5594 : /* We have a special hook for handling opening a specific */
5595 : /* directory of a TIFF file. */
5596 : /* -------------------------------------------------------------------- */
5597 3893 : if( EQUALN(pszFilename,"GTIFF_DIR:",strlen("GTIFF_DIR:")) )
5598 6 : return OpenDir( poOpenInfo );
5599 :
5600 3887 : if (!GTiffOneTimeInit())
5601 0 : return NULL;
5602 :
5603 : /* -------------------------------------------------------------------- */
5604 : /* Try opening the dataset. */
5605 : /* -------------------------------------------------------------------- */
5606 :
5607 : /* Disable strip chop for now */
5608 3887 : hTIFF = VSI_TIFFOpen( pszFilename, ( poOpenInfo->eAccess == GA_ReadOnly ) ? "rc" : "r+c" );
5609 3887 : if( hTIFF == NULL )
5610 0 : return( NULL );
5611 :
5612 : uint32 nXSize, nYSize;
5613 : uint16 nPlanarConfig;
5614 : uint32 nRowsPerStrip;
5615 : uint16 nCompression;
5616 :
5617 3887 : TIFFGetField( hTIFF, TIFFTAG_IMAGEWIDTH, &nXSize );
5618 3887 : TIFFGetField( hTIFF, TIFFTAG_IMAGELENGTH, &nYSize );
5619 :
5620 3887 : if( nXSize > INT_MAX || nYSize > INT_MAX )
5621 : {
5622 : /* GDAL only supports signed 32bit dimensions */
5623 0 : XTIFFClose( hTIFF );
5624 0 : return( NULL );
5625 : }
5626 :
5627 3887 : if( !TIFFGetField( hTIFF, TIFFTAG_PLANARCONFIG, &(nPlanarConfig) ) )
5628 0 : nPlanarConfig = PLANARCONFIG_CONTIG;
5629 :
5630 3887 : if( !TIFFGetField( hTIFF, TIFFTAG_COMPRESSION, &(nCompression) ) )
5631 0 : nCompression = COMPRESSION_NONE;
5632 :
5633 3887 : if( !TIFFGetField( hTIFF, TIFFTAG_ROWSPERSTRIP, &(nRowsPerStrip) ) )
5634 371 : nRowsPerStrip = nYSize;
5635 :
5636 3887 : if (!TIFFIsTiled( hTIFF ) &&
5637 : nCompression == COMPRESSION_NONE &&
5638 : nRowsPerStrip >= nYSize &&
5639 : nPlanarConfig == PLANARCONFIG_CONTIG)
5640 : {
5641 2973 : int bReopenWithStripChop = TRUE;
5642 2973 : if ( nYSize > 128 * 1024 * 1024 )
5643 : {
5644 : uint16 nSamplesPerPixel;
5645 : uint16 nBitsPerSample;
5646 :
5647 1 : if( !TIFFGetField(hTIFF, TIFFTAG_SAMPLESPERPIXEL, &nSamplesPerPixel ) )
5648 0 : nSamplesPerPixel = 1;
5649 :
5650 1 : if( !TIFFGetField(hTIFF, TIFFTAG_BITSPERSAMPLE, &(nBitsPerSample)) )
5651 0 : nBitsPerSample = 1;
5652 :
5653 1 : vsi_l_offset nLineSize = (nSamplesPerPixel * (vsi_l_offset)nXSize * nBitsPerSample + 7) / 8;
5654 1 : int nDefaultStripHeight = (int)(8192 / nLineSize);
5655 1 : if (nDefaultStripHeight == 0) nDefaultStripHeight = 1;
5656 1 : vsi_l_offset nStrips = nYSize / nDefaultStripHeight;
5657 :
5658 : /* There is a risk of DoS due to huge amount of memory allocated in ChopUpSingleUncompressedStrip() */
5659 : /* in libtiff */
5660 1 : if (nStrips > 128 * 1024 * 1024 &&
5661 : !CSLTestBoolean(CPLGetConfigOption("GTIFF_FORCE_STRIP_CHOP", "NO")))
5662 : {
5663 : CPLError(CE_Warning, CPLE_AppDefined,
5664 : "Potential denial of service detected. Avoid using strip chop. "
5665 1 : "Set the GTIFF_FORCE_STRIP_CHOP configuration open to go over this test.");
5666 1 : bReopenWithStripChop = FALSE;
5667 : }
5668 : }
5669 :
5670 2973 : if (bReopenWithStripChop)
5671 : {
5672 2972 : CPLDebug("GTiff", "Reopen with strip chop enabled");
5673 2972 : XTIFFClose(hTIFF);
5674 2972 : hTIFF = VSI_TIFFOpen( pszFilename, ( poOpenInfo->eAccess == GA_ReadOnly ) ? "r" : "r+" );
5675 2972 : if( hTIFF == NULL )
5676 0 : return( NULL );
5677 : }
5678 : }
5679 :
5680 : /* -------------------------------------------------------------------- */
5681 : /* Create a corresponding GDALDataset. */
5682 : /* -------------------------------------------------------------------- */
5683 : GTiffDataset *poDS;
5684 :
5685 3887 : poDS = new GTiffDataset();
5686 3887 : poDS->SetDescription( pszFilename );
5687 7774 : poDS->osFilename = pszFilename;
5688 3887 : poDS->poActiveDS = poDS;
5689 :
5690 3887 : if( poDS->OpenOffset( hTIFF, &(poDS->poActiveDS),
5691 : TIFFCurrentDirOffset(hTIFF), TRUE,
5692 : poOpenInfo->eAccess,
5693 : bAllowRGBAInterface, TRUE,
5694 : poOpenInfo->papszSiblingFiles) != CE_None )
5695 : {
5696 0 : delete poDS;
5697 0 : return NULL;
5698 : }
5699 :
5700 : /* -------------------------------------------------------------------- */
5701 : /* Initialize any PAM information. */
5702 : /* -------------------------------------------------------------------- */
5703 3887 : poDS->TryLoadXML( poOpenInfo->papszSiblingFiles);
5704 3887 : poDS->ApplyPamInfo();
5705 :
5706 : int i;
5707 271080 : for(i=1;i<=poDS->nBands;i++)
5708 : {
5709 267193 : GTiffRasterBand* poBand = (GTiffRasterBand*) poDS->GetRasterBand(i);
5710 :
5711 : /* Load scale, offset and unittype from PAM if available */
5712 267193 : if (!poBand->bHaveOffsetScale)
5713 : {
5714 267187 : poBand->dfScale = poBand->GDALPamRasterBand::GetScale(&poBand->bHaveOffsetScale);
5715 267187 : poBand->dfOffset = poBand->GDALPamRasterBand::GetOffset();
5716 : }
5717 267193 : if (poBand->osUnitType.size() == 0)
5718 : {
5719 267180 : const char* pszUnitType = poBand->GDALPamRasterBand::GetUnitType();
5720 267180 : if (pszUnitType)
5721 267180 : poBand->osUnitType = pszUnitType;
5722 : }
5723 : }
5724 :
5725 3887 : poDS->bMetadataChanged = FALSE;
5726 3887 : poDS->bGeoTIFFInfoChanged = FALSE;
5727 :
5728 : /* -------------------------------------------------------------------- */
5729 : /* Check for external overviews. */
5730 : /* -------------------------------------------------------------------- */
5731 3887 : poDS->oOvManager.Initialize( poDS, pszFilename, poOpenInfo->papszSiblingFiles );
5732 :
5733 3887 : return poDS;
5734 : }
5735 :
5736 : /************************************************************************/
5737 : /* LoadMDAreaOrPoint() */
5738 : /************************************************************************/
5739 :
5740 : /* This is a light version of LookForProjection(), which saves the */
5741 : /* potential costly cost of GTIFGetOGISDefn(), since we just need to */
5742 : /* access to a raw GeoTIFF key, and not build the full projection object. */
5743 :
5744 4651 : void GTiffDataset::LoadMDAreaOrPoint()
5745 : {
5746 4651 : if( bLookedForProjection || bLookedForMDAreaOrPoint ||
5747 : oGTiffMDMD.GetMetadataItem( GDALMD_AREA_OR_POINT ) != NULL )
5748 4456 : return;
5749 :
5750 195 : bLookedForMDAreaOrPoint = TRUE;
5751 :
5752 195 : if (!SetDirectory())
5753 0 : return;
5754 :
5755 195 : GTIF* hGTIF = GTIFNew(hTIFF);
5756 :
5757 195 : if ( !hGTIF )
5758 : {
5759 : CPLError( CE_Warning, CPLE_AppDefined,
5760 0 : "GeoTIFF tags apparently corrupt, they are being ignored." );
5761 : }
5762 : else
5763 : {
5764 : // Is this a pixel-is-point dataset?
5765 : short nRasterType;
5766 :
5767 195 : if( GTIFKeyGet(hGTIF, GTRasterTypeGeoKey, &nRasterType,
5768 : 0, 1 ) == 1 )
5769 : {
5770 85 : if( nRasterType == (short) RasterPixelIsPoint )
5771 8 : oGTiffMDMD.SetMetadataItem( GDALMD_AREA_OR_POINT, GDALMD_AOP_POINT );
5772 : else
5773 77 : oGTiffMDMD.SetMetadataItem( GDALMD_AREA_OR_POINT, GDALMD_AOP_AREA );
5774 : }
5775 :
5776 195 : GTIFFree( hGTIF );
5777 : }
5778 : }
5779 :
5780 : /************************************************************************/
5781 : /* LookForProjection() */
5782 : /************************************************************************/
5783 :
5784 4628 : void GTiffDataset::LookForProjection()
5785 :
5786 : {
5787 4628 : if( bLookedForProjection )
5788 3626 : return;
5789 :
5790 1002 : bLookedForProjection = TRUE;
5791 1002 : if (!SetDirectory())
5792 0 : return;
5793 :
5794 : /* -------------------------------------------------------------------- */
5795 : /* Capture the GeoTIFF projection, if available. */
5796 : /* -------------------------------------------------------------------- */
5797 : GTIF *hGTIF;
5798 :
5799 1002 : CPLFree( pszProjection );
5800 1002 : pszProjection = NULL;
5801 :
5802 1002 : hGTIF = GTIFNew(hTIFF);
5803 :
5804 1002 : if ( !hGTIF )
5805 : {
5806 : CPLError( CE_Warning, CPLE_AppDefined,
5807 0 : "GeoTIFF tags apparently corrupt, they are being ignored." );
5808 : }
5809 : else
5810 : {
5811 : GTIFDefn *psGTIFDefn;
5812 :
5813 : #if LIBGEOTIFF_VERSION >= 1410
5814 : psGTIFDefn = GTIFAllocDefn();
5815 : #else
5816 1002 : psGTIFDefn = (GTIFDefn *) CPLCalloc(1,sizeof(GTIFDefn));
5817 : #endif
5818 :
5819 1002 : if( GTIFGetDefn( hGTIF, psGTIFDefn ) )
5820 : {
5821 955 : pszProjection = GTIFGetOGISDefn( hGTIF, psGTIFDefn );
5822 :
5823 : // Should we simplify away vertical CS stuff?
5824 955 : if( EQUALN(pszProjection,"COMPD_CS",8)
5825 : && !CSLTestBoolean( CPLGetConfigOption("GTIFF_REPORT_COMPD_CS",
5826 : "NO") ) )
5827 : {
5828 1 : OGRSpatialReference oSRS;
5829 :
5830 1 : CPLDebug( "GTiff", "Got COMPD_CS, but stripping it." );
5831 1 : char *pszWKT = pszProjection;
5832 1 : oSRS.importFromWkt( &pszWKT );
5833 1 : CPLFree( pszProjection );
5834 :
5835 1 : oSRS.StripVertical();
5836 1 : oSRS.exportToWkt( &pszProjection );
5837 : }
5838 : }
5839 :
5840 : // Is this a pixel-is-point dataset?
5841 : short nRasterType;
5842 :
5843 : // check the tif linear unit and the CS linear unit
5844 : #ifdef ESRI_BUILD
5845 : AdjustLinearUnit(psGTIFDefn.UOMLength);
5846 : #endif
5847 :
5848 : #if LIBGEOTIFF_VERSION >= 1410
5849 : GTIFFreeDefn(psGTIFDefn);
5850 : #else
5851 1002 : CPLFree(psGTIFDefn);
5852 : #endif
5853 :
5854 1002 : if( GTIFKeyGet(hGTIF, GTRasterTypeGeoKey, &nRasterType,
5855 : 0, 1 ) == 1 )
5856 : {
5857 954 : if( nRasterType == (short) RasterPixelIsPoint )
5858 17 : oGTiffMDMD.SetMetadataItem( GDALMD_AREA_OR_POINT, GDALMD_AOP_POINT );
5859 : else
5860 937 : oGTiffMDMD.SetMetadataItem( GDALMD_AREA_OR_POINT, GDALMD_AOP_AREA );
5861 : }
5862 :
5863 1002 : GTIFFree( hGTIF );
5864 : }
5865 :
5866 1002 : if( pszProjection == NULL )
5867 : {
5868 47 : pszProjection = CPLStrdup( "" );
5869 : }
5870 :
5871 1002 : bGeoTIFFInfoChanged = FALSE;
5872 : }
5873 :
5874 : /************************************************************************/
5875 : /* AdjustLinearUnit() */
5876 : /* */
5877 : /* The following code is only used in ESRI Builds and there is */
5878 : /* outstanding discussion on whether it is even appropriate */
5879 : /* then. */
5880 : /************************************************************************/
5881 : #ifdef ESRI_BUILD
5882 :
5883 : void GTiffDataset::AdjustLinearUnit(short UOMLength)
5884 : {
5885 : if (!pszProjection || strlen(pszProjection) == 0)
5886 : return;
5887 : if( UOMLength == 9001)
5888 : {
5889 : char* pstr = strstr(pszProjection, "PARAMETER");
5890 : if (!pstr)
5891 : return;
5892 : pstr = strstr(pstr, "UNIT[");
5893 : if (!pstr)
5894 : return;
5895 : pstr = strchr(pstr, ',') + 1;
5896 : if (!pstr)
5897 : return;
5898 : char* pstr1 = strchr(pstr, ']');
5899 : if (!pstr1 || pstr1 - pstr >= 128)
5900 : return;
5901 : char csUnitStr[128];
5902 : strncpy(csUnitStr, pstr, pstr1-pstr);
5903 : csUnitStr[pstr1-pstr] = '\0';
5904 : double csUnit = CPLAtof(csUnitStr);
5905 : if(fabs(csUnit - 1.0) > 0.000001)
5906 : {
5907 : for(long i=0; i<6; i++)
5908 : adfGeoTransform[i] /= csUnit;
5909 : }
5910 : }
5911 : }
5912 :
5913 : #endif /* def ESRI_BUILD */
5914 :
5915 : /************************************************************************/
5916 : /* ApplyPamInfo() */
5917 : /* */
5918 : /* PAM Information, if available, overrides the GeoTIFF */
5919 : /* geotransform and projection definition. Check for them */
5920 : /* now. */
5921 : /************************************************************************/
5922 :
5923 3887 : void GTiffDataset::ApplyPamInfo()
5924 :
5925 : {
5926 : double adfPamGeoTransform[6];
5927 :
5928 3887 : if( GDALPamDataset::GetGeoTransform( adfPamGeoTransform ) == CE_None
5929 0 : && (adfPamGeoTransform[0] != 0.0 || adfPamGeoTransform[1] != 1.0
5930 0 : || adfPamGeoTransform[2] != 0.0 || adfPamGeoTransform[3] != 0.0
5931 0 : || adfPamGeoTransform[4] != 0.0 || adfPamGeoTransform[5] != 1.0 ))
5932 : {
5933 0 : memcpy( adfGeoTransform, adfPamGeoTransform, sizeof(double)*6 );
5934 0 : bGeoTransformValid = TRUE;
5935 : }
5936 :
5937 3887 : const char *pszPamSRS = GDALPamDataset::GetProjectionRef();
5938 :
5939 3887 : if( pszPamSRS != NULL && strlen(pszPamSRS) > 0 )
5940 : {
5941 2 : CPLFree( pszProjection );
5942 2 : pszProjection = CPLStrdup( pszPamSRS );
5943 2 : bLookedForProjection = TRUE;
5944 : }
5945 :
5946 3887 : int nPamGCPCount = GDALPamDataset::GetGCPCount();
5947 3887 : if( nPamGCPCount > 0 )
5948 : {
5949 2 : if( nGCPCount > 0 )
5950 : {
5951 0 : GDALDeinitGCPs( nGCPCount, pasGCPList );
5952 0 : CPLFree( pasGCPList );
5953 0 : pasGCPList = NULL;
5954 : }
5955 :
5956 2 : nGCPCount = nPamGCPCount;
5957 2 : pasGCPList = GDALDuplicateGCPs(nGCPCount, GDALPamDataset::GetGCPs());
5958 :
5959 2 : CPLFree( pszProjection );
5960 2 : pszProjection = NULL;
5961 :
5962 2 : const char *pszPamGCPProjection = GDALPamDataset::GetGCPProjection();
5963 2 : if( pszPamGCPProjection != NULL && strlen(pszPamGCPProjection) > 0 )
5964 2 : pszProjection = CPLStrdup(pszPamGCPProjection);
5965 :
5966 2 : bLookedForProjection = TRUE;
5967 : }
5968 :
5969 : /* -------------------------------------------------------------------- */
5970 : /* Copy any PAM metadata into our GeoTIFF context, and with */
5971 : /* the PAM info overriding the GeoTIFF context. */
5972 : /* -------------------------------------------------------------------- */
5973 3887 : char **papszPamDomains = oMDMD.GetDomainList();
5974 :
5975 3903 : for( int iDomain = 0; papszPamDomains && papszPamDomains[iDomain] != NULL; iDomain++ )
5976 : {
5977 16 : const char *pszDomain = papszPamDomains[iDomain];
5978 16 : char **papszGT_MD = CSLDuplicate(oGTiffMDMD.GetMetadata( pszDomain ));
5979 16 : char **papszPAM_MD = oMDMD.GetMetadata( pszDomain );
5980 :
5981 16 : papszGT_MD = CSLMerge( papszGT_MD, papszPAM_MD );
5982 :
5983 16 : oGTiffMDMD.SetMetadata( papszGT_MD, pszDomain );
5984 16 : CSLDestroy( papszGT_MD );
5985 : }
5986 :
5987 271080 : for( int i = 1; i <= GetRasterCount(); i++)
5988 : {
5989 267193 : GTiffRasterBand* poBand = (GTiffRasterBand *)GetRasterBand(i);
5990 267193 : papszPamDomains = poBand->oMDMD.GetDomainList();
5991 :
5992 267233 : for( int iDomain = 0; papszPamDomains && papszPamDomains[iDomain] != NULL; iDomain++ )
5993 : {
5994 40 : const char *pszDomain = papszPamDomains[iDomain];
5995 40 : char **papszGT_MD = CSLDuplicate(poBand->oGTiffMDMD.GetMetadata( pszDomain ));
5996 40 : char **papszPAM_MD = poBand->oMDMD.GetMetadata( pszDomain );
5997 :
5998 40 : papszGT_MD = CSLMerge( papszGT_MD, papszPAM_MD );
5999 :
6000 40 : poBand->oGTiffMDMD.SetMetadata( papszGT_MD, pszDomain );
6001 40 : CSLDestroy( papszGT_MD );
6002 : }
6003 : }
6004 3887 : }
6005 :
6006 : /************************************************************************/
6007 : /* OpenDir() */
6008 : /* */
6009 : /* Open a specific directory as encoded into a filename. */
6010 : /************************************************************************/
6011 :
6012 6 : GDALDataset *GTiffDataset::OpenDir( GDALOpenInfo * poOpenInfo )
6013 :
6014 : {
6015 6 : int bAllowRGBAInterface = TRUE;
6016 6 : const char* pszFilename = poOpenInfo->pszFilename;
6017 6 : if( EQUALN(pszFilename,"GTIFF_RAW:", strlen("GTIFF_RAW:")) )
6018 : {
6019 0 : bAllowRGBAInterface = FALSE;
6020 0 : pszFilename += strlen("GTIFF_RAW:");
6021 : }
6022 :
6023 6 : if( !EQUALN(pszFilename,"GTIFF_DIR:",strlen("GTIFF_DIR:")) )
6024 0 : return NULL;
6025 :
6026 : /* -------------------------------------------------------------------- */
6027 : /* Split out filename, and dir#/offset. */
6028 : /* -------------------------------------------------------------------- */
6029 6 : pszFilename += strlen("GTIFF_DIR:");
6030 6 : int bAbsolute = FALSE;
6031 : toff_t nOffset;
6032 :
6033 6 : if( EQUALN(pszFilename,"off:",4) )
6034 : {
6035 1 : bAbsolute = TRUE;
6036 1 : pszFilename += 4;
6037 : }
6038 :
6039 6 : nOffset = atol(pszFilename);
6040 6 : pszFilename += 1;
6041 :
6042 20 : while( *pszFilename != '\0' && pszFilename[-1] != ':' )
6043 8 : pszFilename++;
6044 :
6045 6 : if( *pszFilename == '\0' || nOffset == 0 )
6046 : {
6047 : CPLError( CE_Failure, CPLE_OpenFailed,
6048 : "Unable to extract offset or filename, should take the form\n"
6049 0 : "GTIFF_DIR:<dir>:filename or GTIFF_DIR:off:<dir_offset>:filename" );
6050 0 : return NULL;
6051 : }
6052 :
6053 : /* -------------------------------------------------------------------- */
6054 : /* Try opening the dataset. */
6055 : /* -------------------------------------------------------------------- */
6056 : TIFF *hTIFF;
6057 :
6058 6 : if (!GTiffOneTimeInit())
6059 0 : return NULL;
6060 :
6061 6 : hTIFF = VSI_TIFFOpen( pszFilename, "r" );
6062 6 : if( hTIFF == NULL )
6063 0 : return( NULL );
6064 :
6065 : /* -------------------------------------------------------------------- */
6066 : /* If a directory was requested by index, advance to it now. */
6067 : /* -------------------------------------------------------------------- */
6068 6 : if( !bAbsolute )
6069 : {
6070 12 : while( nOffset > 1 )
6071 : {
6072 2 : if( TIFFReadDirectory( hTIFF ) == 0 )
6073 : {
6074 0 : XTIFFClose( hTIFF );
6075 : CPLError( CE_Failure, CPLE_OpenFailed,
6076 0 : "Requested directory %lu not found.", (long unsigned int)nOffset );
6077 0 : return NULL;
6078 : }
6079 2 : nOffset--;
6080 : }
6081 :
6082 5 : nOffset = TIFFCurrentDirOffset( hTIFF );
6083 : }
6084 :
6085 : /* -------------------------------------------------------------------- */
6086 : /* Create a corresponding GDALDataset. */
6087 : /* -------------------------------------------------------------------- */
6088 : GTiffDataset *poDS;
6089 :
6090 6 : poDS = new GTiffDataset();
6091 6 : poDS->SetDescription( poOpenInfo->pszFilename );
6092 12 : poDS->osFilename = poOpenInfo->pszFilename;
6093 6 : poDS->poActiveDS = poDS;
6094 :
6095 12 : if( !EQUAL(pszFilename,poOpenInfo->pszFilename)
6096 : && !EQUALN(poOpenInfo->pszFilename,"GTIFF_RAW:",10) )
6097 : {
6098 6 : poDS->SetPhysicalFilename( pszFilename );
6099 6 : poDS->SetSubdatasetName( poOpenInfo->pszFilename );
6100 6 : poDS->osFilename = pszFilename;
6101 : }
6102 :
6103 6 : if (poOpenInfo->eAccess == GA_Update)
6104 : {
6105 : CPLError( CE_Warning, CPLE_AppDefined,
6106 0 : "Opening a specific TIFF directory is not supported in update mode. Switching to read-only" );
6107 : }
6108 :
6109 6 : if( poDS->OpenOffset( hTIFF, &(poDS->poActiveDS),
6110 : nOffset, FALSE, GA_ReadOnly,
6111 : bAllowRGBAInterface, TRUE,
6112 : poOpenInfo->papszSiblingFiles ) != CE_None )
6113 : {
6114 0 : delete poDS;
6115 0 : return NULL;
6116 : }
6117 : else
6118 : {
6119 6 : poDS->bCloseTIFFHandle = TRUE;
6120 6 : return poDS;
6121 : }
6122 : }
6123 :
6124 : /************************************************************************/
6125 : /* OpenOffset() */
6126 : /* */
6127 : /* Initialize the GTiffDataset based on a passed in file */
6128 : /* handle, and directory offset to utilize. This is called for */
6129 : /* full res, and overview pages. */
6130 : /************************************************************************/
6131 :
6132 4277 : CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
6133 : GTiffDataset **ppoActiveDSRef,
6134 : toff_t nDirOffsetIn,
6135 : int bBaseIn, GDALAccess eAccess,
6136 : int bAllowRGBAInterface,
6137 : int bReadGeoTransform,
6138 : char** papszSiblingFiles )
6139 :
6140 : {
6141 : uint32 nXSize, nYSize;
6142 4277 : int bTreatAsBitmap = FALSE;
6143 4277 : int bTreatAsOdd = FALSE;
6144 :
6145 4277 : this->eAccess = eAccess;
6146 :
6147 4277 : hTIFF = hTIFFIn;
6148 4277 : this->ppoActiveDSRef = ppoActiveDSRef;
6149 :
6150 4277 : nDirOffset = nDirOffsetIn;
6151 :
6152 4277 : if (!SetDirectory( nDirOffsetIn ))
6153 0 : return CE_Failure;
6154 :
6155 4277 : bBase = bBaseIn;
6156 :
6157 4277 : this->eAccess = eAccess;
6158 :
6159 : /* -------------------------------------------------------------------- */
6160 : /* Capture some information from the file that is of interest. */
6161 : /* -------------------------------------------------------------------- */
6162 4277 : TIFFGetField( hTIFF, TIFFTAG_IMAGEWIDTH, &nXSize );
6163 4277 : TIFFGetField( hTIFF, TIFFTAG_IMAGELENGTH, &nYSize );
6164 4277 : nRasterXSize = nXSize;
6165 4277 : nRasterYSize = nYSize;
6166 :
6167 4277 : if( !TIFFGetField(hTIFF, TIFFTAG_SAMPLESPERPIXEL, &nSamplesPerPixel ) )
6168 1 : nBands = 1;
6169 : else
6170 4276 : nBands = nSamplesPerPixel;
6171 :
6172 4277 : if( !TIFFGetField(hTIFF, TIFFTAG_BITSPERSAMPLE, &(nBitsPerSample)) )
6173 1 : nBitsPerSample = 1;
6174 :
6175 4277 : if( !TIFFGetField( hTIFF, TIFFTAG_PLANARCONFIG, &(nPlanarConfig) ) )
6176 0 : nPlanarConfig = PLANARCONFIG_CONTIG;
6177 :
6178 4277 : if( !TIFFGetField( hTIFF, TIFFTAG_PHOTOMETRIC, &(nPhotometric) ) )
6179 1 : nPhotometric = PHOTOMETRIC_MINISBLACK;
6180 :
6181 4277 : if( !TIFFGetField( hTIFF, TIFFTAG_SAMPLEFORMAT, &(nSampleFormat) ) )
6182 44 : nSampleFormat = SAMPLEFORMAT_UINT;
6183 :
6184 4277 : if( !TIFFGetField( hTIFF, TIFFTAG_COMPRESSION, &(nCompression) ) )
6185 0 : nCompression = COMPRESSION_NONE;
6186 :
6187 : #if defined(TIFFLIB_VERSION) && TIFFLIB_VERSION > 20031007 /* 3.6.0 */
6188 4277 : if (nCompression != COMPRESSION_NONE &&
6189 : !TIFFIsCODECConfigured(nCompression))
6190 : {
6191 : CPLError( CE_Failure, CPLE_AppDefined,
6192 0 : "Cannot open TIFF file due to missing codec." );
6193 0 : return CE_Failure;
6194 : }
6195 : #endif
6196 :
6197 : /* -------------------------------------------------------------------- */
6198 : /* YCbCr JPEG compressed images should be translated on the fly */
6199 : /* to RGB by libtiff/libjpeg unless specifically requested */
6200 : /* otherwise. */
6201 : /* -------------------------------------------------------------------- */
6202 4277 : if( nCompression == COMPRESSION_JPEG
6203 : && nPhotometric == PHOTOMETRIC_YCBCR
6204 : && CSLTestBoolean( CPLGetConfigOption("CONVERT_YCBCR_TO_RGB",
6205 : "YES") ) )
6206 : {
6207 : int nColorMode;
6208 :
6209 118 : SetMetadataItem( "SOURCE_COLOR_SPACE", "YCbCr", "IMAGE_STRUCTURE" );
6210 118 : if ( !TIFFGetField( hTIFF, TIFFTAG_JPEGCOLORMODE, &nColorMode ) ||
6211 : nColorMode != JPEGCOLORMODE_RGB )
6212 100 : TIFFSetField(hTIFF, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
6213 : }
6214 :
6215 : /* -------------------------------------------------------------------- */
6216 : /* Get strip/tile layout. */
6217 : /* -------------------------------------------------------------------- */
6218 4277 : if( TIFFIsTiled(hTIFF) )
6219 : {
6220 707 : TIFFGetField( hTIFF, TIFFTAG_TILEWIDTH, &(nBlockXSize) );
6221 707 : TIFFGetField( hTIFF, TIFFTAG_TILELENGTH, &(nBlockYSize) );
6222 : }
6223 : else
6224 : {
6225 3570 : if( !TIFFGetField( hTIFF, TIFFTAG_ROWSPERSTRIP,
6226 : &(nRowsPerStrip) ) )
6227 : {
6228 : CPLError( CE_Warning, CPLE_AppDefined,
6229 0 : "RowsPerStrip not defined ... assuming all one strip." );
6230 0 : nRowsPerStrip = nYSize; /* dummy value */
6231 : }
6232 :
6233 : // If the rows per strip is larger than the file we will get
6234 : // confused. libtiff internally will treat the rowsperstrip as
6235 : // the image height and it is best if we do too. (#4468)
6236 3570 : if (nRowsPerStrip > (uint32)nRasterYSize)
6237 12 : nRowsPerStrip = nRasterYSize;
6238 :
6239 3570 : nBlockXSize = nRasterXSize;
6240 3570 : nBlockYSize = nRowsPerStrip;
6241 : }
6242 :
6243 : nBlocksPerBand =
6244 4277 : DIV_ROUND_UP(nYSize, nBlockYSize) * DIV_ROUND_UP(nXSize, nBlockXSize);
6245 :
6246 : /* -------------------------------------------------------------------- */
6247 : /* Should we handle this using the GTiffBitmapBand? */
6248 : /* -------------------------------------------------------------------- */
6249 4277 : if( nBitsPerSample == 1 && nBands == 1 )
6250 : {
6251 129 : bTreatAsBitmap = TRUE;
6252 :
6253 : // Lets treat large "one row" bitmaps using the scanline api.
6254 129 : if( !TIFFIsTiled(hTIFF)
6255 : && nBlockYSize == nYSize
6256 : && nYSize > 2000
6257 : && bAllowRGBAInterface )
6258 4 : bTreatAsSplitBitmap = TRUE;
6259 : }
6260 :
6261 : /* -------------------------------------------------------------------- */
6262 : /* Should we treat this via the RGBA interface? */
6263 : /* -------------------------------------------------------------------- */
6264 4277 : if( bAllowRGBAInterface &&
6265 : !bTreatAsBitmap && !(nBitsPerSample > 8)
6266 : && (nPhotometric == PHOTOMETRIC_CIELAB ||
6267 : nPhotometric == PHOTOMETRIC_LOGL ||
6268 : nPhotometric == PHOTOMETRIC_LOGLUV ||
6269 : nPhotometric == PHOTOMETRIC_SEPARATED ||
6270 : ( nPhotometric == PHOTOMETRIC_YCBCR
6271 : && nCompression != COMPRESSION_JPEG )) )
6272 : {
6273 : char szMessage[1024];
6274 :
6275 5 : if( TIFFRGBAImageOK( hTIFF, szMessage ) == 1 )
6276 : {
6277 5 : const char* pszSourceColorSpace = NULL;
6278 5 : switch (nPhotometric)
6279 : {
6280 : case PHOTOMETRIC_CIELAB:
6281 1 : pszSourceColorSpace = "CIELAB";
6282 1 : break;
6283 : case PHOTOMETRIC_LOGL:
6284 0 : pszSourceColorSpace = "LOGL";
6285 0 : break;
6286 : case PHOTOMETRIC_LOGLUV:
6287 0 : pszSourceColorSpace = "LOGLUV";
6288 0 : break;
6289 : case PHOTOMETRIC_SEPARATED:
6290 3 : pszSourceColorSpace = "CMYK";
6291 3 : break;
6292 : case PHOTOMETRIC_YCBCR:
6293 1 : pszSourceColorSpace = "YCbCr";
6294 : break;
6295 : }
6296 5 : if (pszSourceColorSpace)
6297 5 : SetMetadataItem( "SOURCE_COLOR_SPACE", pszSourceColorSpace, "IMAGE_STRUCTURE" );
6298 5 : bTreatAsRGBA = TRUE;
6299 5 : nBands = 4;
6300 : }
6301 : else
6302 : {
6303 0 : CPLDebug( "GTiff", "TIFFRGBAImageOK says:\n%s", szMessage );
6304 : }
6305 : }
6306 :
6307 : /* -------------------------------------------------------------------- */
6308 : /* Should we treat this via the split interface? */
6309 : /* -------------------------------------------------------------------- */
6310 4277 : if( !TIFFIsTiled(hTIFF)
6311 : && nBitsPerSample == 8
6312 : && nBlockYSize == nYSize
6313 : && nYSize > 2000
6314 : && !bTreatAsRGBA
6315 : && CSLTestBoolean(CPLGetConfigOption("GDAL_ENABLE_TIFF_SPLIT", "YES")))
6316 : {
6317 : /* libtiff 3.9.2 (20091104) and older, libtiff 4.0.0beta5 (also 20091104) */
6318 : /* and older will crash when trying to open a all-in-one-strip */
6319 : /* YCbCr JPEG compressed TIFF (see #3259). */
6320 : #if (TIFFLIB_VERSION <= 20091104 && !defined(BIGTIFF_SUPPORT)) || \
6321 : (TIFFLIB_VERSION <= 20091104 && defined(BIGTIFF_SUPPORT))
6322 : if (nPhotometric == PHOTOMETRIC_YCBCR &&
6323 : nCompression == COMPRESSION_JPEG)
6324 : {
6325 : CPLDebug("GTiff", "Avoid using split band to open all-in-one-strip "
6326 : "YCbCr JPEG compressed TIFF because of older libtiff");
6327 : }
6328 : else
6329 : #endif
6330 10 : bTreatAsSplit = TRUE;
6331 : }
6332 :
6333 : /* -------------------------------------------------------------------- */
6334 : /* Should we treat this via the odd bits interface? */
6335 : /* -------------------------------------------------------------------- */
6336 4277 : if ( nSampleFormat == SAMPLEFORMAT_IEEEFP )
6337 : {
6338 500 : if ( nBitsPerSample == 16 || nBitsPerSample == 24 )
6339 2 : bTreatAsOdd = TRUE;
6340 : }
6341 3777 : else if ( !bTreatAsRGBA && !bTreatAsBitmap
6342 : && nBitsPerSample != 8
6343 : && nBitsPerSample != 16
6344 : && nBitsPerSample != 32
6345 : && nBitsPerSample != 64
6346 : && nBitsPerSample != 128 )
6347 115 : bTreatAsOdd = TRUE;
6348 :
6349 4277 : int bMinIsWhite = nPhotometric == PHOTOMETRIC_MINISWHITE;
6350 :
6351 : /* -------------------------------------------------------------------- */
6352 : /* Capture the color table if there is one. */
6353 : /* -------------------------------------------------------------------- */
6354 : unsigned short *panRed, *panGreen, *panBlue;
6355 :
6356 4277 : if( bTreatAsRGBA
6357 : || TIFFGetField( hTIFF, TIFFTAG_COLORMAP,
6358 : &panRed, &panGreen, &panBlue) == 0 )
6359 : {
6360 : // Build inverted palette if we have inverted photometric.
6361 : // Pixel values remains unchanged. Avoid doing this for *deep*
6362 : // data types (per #1882)
6363 4206 : if( nBitsPerSample <= 16 && nPhotometric == PHOTOMETRIC_MINISWHITE )
6364 : {
6365 : GDALColorEntry oEntry;
6366 : int iColor, nColorCount;
6367 :
6368 7 : poColorTable = new GDALColorTable();
6369 7 : nColorCount = 1 << nBitsPerSample;
6370 :
6371 21 : for ( iColor = 0; iColor < nColorCount; iColor++ )
6372 : {
6373 : oEntry.c1 = oEntry.c2 = oEntry.c3 = (short)
6374 14 : ((255 * (nColorCount - 1 - iColor)) / (nColorCount-1));
6375 14 : oEntry.c4 = 255;
6376 14 : poColorTable->SetColorEntry( iColor, &oEntry );
6377 : }
6378 :
6379 7 : nPhotometric = PHOTOMETRIC_PALETTE;
6380 : }
6381 : else
6382 4192 : poColorTable = NULL;
6383 : }
6384 : else
6385 : {
6386 78 : int nColorCount, nMaxColor = 0;
6387 : GDALColorEntry oEntry;
6388 :
6389 78 : poColorTable = new GDALColorTable();
6390 :
6391 78 : nColorCount = 1 << nBitsPerSample;
6392 :
6393 343906 : for( int iColor = nColorCount - 1; iColor >= 0; iColor-- )
6394 : {
6395 343828 : oEntry.c1 = panRed[iColor] / 256;
6396 343828 : oEntry.c2 = panGreen[iColor] / 256;
6397 343828 : oEntry.c3 = panBlue[iColor] / 256;
6398 343828 : oEntry.c4 = 255;
6399 :
6400 343828 : poColorTable->SetColorEntry( iColor, &oEntry );
6401 :
6402 343828 : nMaxColor = MAX(nMaxColor,panRed[iColor]);
6403 343828 : nMaxColor = MAX(nMaxColor,panGreen[iColor]);
6404 343828 : nMaxColor = MAX(nMaxColor,panBlue[iColor]);
6405 : }
6406 :
6407 : // Bug 1384 - Some TIFF files are generated with color map entry
6408 : // values in range 0-255 instead of 0-65535 - try to handle these
6409 : // gracefully.
6410 78 : if( nMaxColor > 0 && nMaxColor < 256 )
6411 : {
6412 0 : CPLDebug( "GTiff", "TIFF ColorTable seems to be improperly scaled, fixing up." );
6413 :
6414 0 : for( int iColor = nColorCount - 1; iColor >= 0; iColor-- )
6415 : {
6416 0 : oEntry.c1 = panRed[iColor];
6417 0 : oEntry.c2 = panGreen[iColor];
6418 0 : oEntry.c3 = panBlue[iColor];
6419 0 : oEntry.c4 = 255;
6420 :
6421 0 : poColorTable->SetColorEntry( iColor, &oEntry );
6422 : }
6423 : }
6424 : }
6425 :
6426 : /* -------------------------------------------------------------------- */
6427 : /* Create band information objects. */
6428 : /* -------------------------------------------------------------------- */
6429 272101 : for( int iBand = 0; iBand < nBands; iBand++ )
6430 : {
6431 267824 : if( bTreatAsRGBA )
6432 20 : SetBand( iBand+1, new GTiffRGBABand( this, iBand+1 ) );
6433 267804 : else if( bTreatAsSplitBitmap )
6434 4 : SetBand( iBand+1, new GTiffSplitBitmapBand( this, iBand+1 ) );
6435 267800 : else if( bTreatAsSplit )
6436 28 : SetBand( iBand+1, new GTiffSplitBand( this, iBand+1 ) );
6437 267772 : else if( bTreatAsBitmap )
6438 125 : SetBand( iBand+1, new GTiffBitmapBand( this, iBand+1 ) );
6439 267647 : else if( bTreatAsOdd )
6440 231 : SetBand( iBand+1, new GTiffOddBitsBand( this, iBand+1 ) );
6441 : else
6442 267416 : SetBand( iBand+1, new GTiffRasterBand( this, iBand+1 ) );
6443 : }
6444 :
6445 4277 : if( GetRasterBand(1)->GetRasterDataType() == GDT_Unknown )
6446 : {
6447 : CPLError( CE_Failure, CPLE_NotSupported,
6448 0 : "Unsupported TIFF configuration." );
6449 0 : return CE_Failure;
6450 : }
6451 :
6452 : /* -------------------------------------------------------------------- */
6453 : /* Get the transform or gcps from the GeoTIFF file. */
6454 : /* -------------------------------------------------------------------- */
6455 4277 : if( bReadGeoTransform )
6456 : {
6457 3893 : char *pszTabWKT = NULL;
6458 : double *padfTiePoints, *padfScale, *padfMatrix;
6459 : uint16 nCount;
6460 3893 : bool bPixelIsPoint = false;
6461 : short nRasterType;
6462 : GTIF *psGTIF;
6463 3893 : int bPointGeoIgnore = FALSE;
6464 :
6465 3893 : psGTIF = GTIFNew( hTIFF ); // I wonder how expensive this is?
6466 :
6467 3893 : if( psGTIF )
6468 : {
6469 3892 : if( GTIFKeyGet(psGTIF, GTRasterTypeGeoKey, &nRasterType,
6470 : 0, 1 ) == 1
6471 : && nRasterType == (short) RasterPixelIsPoint )
6472 : {
6473 31 : bPixelIsPoint = true;
6474 : bPointGeoIgnore =
6475 : CSLTestBoolean( CPLGetConfigOption("GTIFF_POINT_GEO_IGNORE",
6476 31 : "FALSE") );
6477 : }
6478 :
6479 3892 : GTIFFree( psGTIF );
6480 : }
6481 :
6482 3893 : adfGeoTransform[0] = 0.0;
6483 3893 : adfGeoTransform[1] = 1.0;
6484 3893 : adfGeoTransform[2] = 0.0;
6485 3893 : adfGeoTransform[3] = 0.0;
6486 3893 : adfGeoTransform[4] = 0.0;
6487 3893 : adfGeoTransform[5] = 1.0;
6488 :
6489 9413 : if( TIFFGetField(hTIFF,TIFFTAG_GEOPIXELSCALE,&nCount,&padfScale )
6490 : && nCount >= 2
6491 5520 : && padfScale[0] != 0.0 && padfScale[1] != 0.0 )
6492 : {
6493 2760 : adfGeoTransform[1] = padfScale[0];
6494 2760 : adfGeoTransform[5] = - ABS(padfScale[1]);
6495 :
6496 2760 : if( TIFFGetField(hTIFF,TIFFTAG_GEOTIEPOINTS,&nCount,&padfTiePoints )
6497 : && nCount >= 6 )
6498 : {
6499 : adfGeoTransform[0] =
6500 2760 : padfTiePoints[3] - padfTiePoints[0] * adfGeoTransform[1];
6501 : adfGeoTransform[3] =
6502 2760 : padfTiePoints[4] - padfTiePoints[1] * adfGeoTransform[5];
6503 :
6504 2760 : if( bPixelIsPoint && !bPointGeoIgnore )
6505 : {
6506 15 : adfGeoTransform[0] -= (adfGeoTransform[1] * 0.5 + adfGeoTransform[2] * 0.5);
6507 15 : adfGeoTransform[3] -= (adfGeoTransform[4] * 0.5 + adfGeoTransform[5] * 0.5);
6508 : }
6509 :
6510 2760 : bGeoTransformValid = TRUE;
6511 : }
6512 : }
6513 :
6514 1133 : else if( TIFFGetField(hTIFF,TIFFTAG_GEOTRANSMATRIX,&nCount,&padfMatrix )
6515 : && nCount == 16 )
6516 : {
6517 14 : adfGeoTransform[0] = padfMatrix[3];
6518 14 : adfGeoTransform[1] = padfMatrix[0];
6519 14 : adfGeoTransform[2] = padfMatrix[1];
6520 14 : adfGeoTransform[3] = padfMatrix[7];
6521 14 : adfGeoTransform[4] = padfMatrix[4];
6522 14 : adfGeoTransform[5] = padfMatrix[5];
6523 :
6524 14 : if( bPixelIsPoint && !bPointGeoIgnore )
6525 : {
6526 4 : adfGeoTransform[0] -= (adfGeoTransform[1] * 0.5 + adfGeoTransform[2] * 0.5);
6527 4 : adfGeoTransform[3] -= (adfGeoTransform[4] * 0.5 + adfGeoTransform[5] * 0.5);
6528 : }
6529 :
6530 14 : bGeoTransformValid = TRUE;
6531 : }
6532 :
6533 : /* -------------------------------------------------------------------- */
6534 : /* Otherwise try looking for a .tfw, .tifw or .wld file. */
6535 : /* -------------------------------------------------------------------- */
6536 : else
6537 : {
6538 1119 : char* pszWldFilename = NULL;
6539 :
6540 : bGeoTransformValid =
6541 : GDALReadWorldFile2( osFilename, NULL, adfGeoTransform,
6542 1119 : papszSiblingFiles, &pszWldFilename);
6543 :
6544 1119 : if( !bGeoTransformValid )
6545 : {
6546 : bGeoTransformValid =
6547 : GDALReadWorldFile2( osFilename, "wld", adfGeoTransform,
6548 1114 : papszSiblingFiles, &pszWldFilename);
6549 : }
6550 :
6551 1119 : if( !bGeoTransformValid )
6552 : {
6553 : int bTabFileOK =
6554 : GDALReadTabFile2( osFilename, adfGeoTransform,
6555 : &pszTabWKT, &nGCPCount, &pasGCPList,
6556 1109 : papszSiblingFiles, &pszWldFilename );
6557 :
6558 1109 : if( bTabFileOK && nGCPCount == 0 )
6559 2 : bGeoTransformValid = TRUE;
6560 : }
6561 :
6562 1119 : if (pszWldFilename)
6563 : {
6564 12 : osWldFilename = pszWldFilename;
6565 12 : CPLFree(pszWldFilename);
6566 : }
6567 : }
6568 :
6569 : /* -------------------------------------------------------------------- */
6570 : /* Check for GCPs. Note, we will allow there to be GCPs and a */
6571 : /* transform in some circumstances. */
6572 : /* -------------------------------------------------------------------- */
6573 3893 : if( TIFFGetField(hTIFF,TIFFTAG_GEOTIEPOINTS,&nCount,&padfTiePoints )
6574 : && !bGeoTransformValid )
6575 : {
6576 25 : nGCPCount = nCount / 6;
6577 25 : pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),nGCPCount);
6578 :
6579 129 : for( int iGCP = 0; iGCP < nGCPCount; iGCP++ )
6580 : {
6581 : char szID[32];
6582 :
6583 104 : sprintf( szID, "%d", iGCP+1 );
6584 104 : pasGCPList[iGCP].pszId = CPLStrdup( szID );
6585 104 : pasGCPList[iGCP].pszInfo = CPLStrdup("");
6586 104 : pasGCPList[iGCP].dfGCPPixel = padfTiePoints[iGCP*6+0];
6587 104 : pasGCPList[iGCP].dfGCPLine = padfTiePoints[iGCP*6+1];
6588 104 : pasGCPList[iGCP].dfGCPX = padfTiePoints[iGCP*6+3];
6589 104 : pasGCPList[iGCP].dfGCPY = padfTiePoints[iGCP*6+4];
6590 104 : pasGCPList[iGCP].dfGCPZ = padfTiePoints[iGCP*6+5];
6591 :
6592 104 : if( bPixelIsPoint && !bPointGeoIgnore )
6593 : {
6594 0 : pasGCPList[iGCP].dfGCPPixel -= 0.5;
6595 0 : pasGCPList[iGCP].dfGCPLine -= 0.5;
6596 : }
6597 : }
6598 : }
6599 :
6600 : /* -------------------------------------------------------------------- */
6601 : /* Did we find a tab file? If so we will use it's coordinate */
6602 : /* system and give it precidence. */
6603 : /* -------------------------------------------------------------------- */
6604 3895 : if( pszTabWKT != NULL
6605 2 : && (pszProjection == NULL || pszProjection[0] == '\0') )
6606 : {
6607 2 : CPLFree( pszProjection );
6608 2 : pszProjection = pszTabWKT;
6609 2 : pszTabWKT = NULL;
6610 2 : bLookedForProjection = TRUE;
6611 : }
6612 :
6613 3893 : CPLFree( pszTabWKT );
6614 3893 : bGeoTIFFInfoChanged = FALSE;
6615 : }
6616 :
6617 : /* -------------------------------------------------------------------- */
6618 : /* Capture some other potentially interesting information. */
6619 : /* -------------------------------------------------------------------- */
6620 : char *pszText, szWorkMDI[200];
6621 : float fResolution;
6622 : uint16 nShort;
6623 :
6624 4277 : if( TIFFGetField( hTIFF, TIFFTAG_DOCUMENTNAME, &pszText ) )
6625 21 : SetMetadataItem( "TIFFTAG_DOCUMENTNAME", pszText );
6626 :
6627 4277 : if( TIFFGetField( hTIFF, TIFFTAG_IMAGEDESCRIPTION, &pszText ) )
6628 6 : SetMetadataItem( "TIFFTAG_IMAGEDESCRIPTION", pszText );
6629 :
6630 4277 : if( TIFFGetField( hTIFF, TIFFTAG_SOFTWARE, &pszText ) )
6631 10 : SetMetadataItem( "TIFFTAG_SOFTWARE", pszText );
6632 :
6633 4277 : if( TIFFGetField( hTIFF, TIFFTAG_DATETIME, &pszText ) )
6634 5 : SetMetadataItem( "TIFFTAG_DATETIME", pszText );
6635 :
6636 4277 : if( TIFFGetField( hTIFF, TIFFTAG_ARTIST, &pszText ) )
6637 2 : SetMetadataItem( "TIFFTAG_ARTIST", pszText );
6638 :
6639 4277 : if( TIFFGetField( hTIFF, TIFFTAG_HOSTCOMPUTER, &pszText ) )
6640 2 : SetMetadataItem( "TIFFTAG_HOSTCOMPUTER", pszText );
6641 :
6642 4277 : if( TIFFGetField( hTIFF, TIFFTAG_COPYRIGHT, &pszText ) )
6643 2 : SetMetadataItem( "TIFFTAG_COPYRIGHT", pszText );
6644 :
6645 4277 : if( TIFFGetField( hTIFF, TIFFTAG_XRESOLUTION, &fResolution ) )
6646 : {
6647 46 : sprintf( szWorkMDI, "%.8g", fResolution );
6648 46 : SetMetadataItem( "TIFFTAG_XRESOLUTION", szWorkMDI );
6649 : }
6650 :
6651 4277 : if( TIFFGetField( hTIFF, TIFFTAG_YRESOLUTION, &fResolution ) )
6652 : {
6653 46 : sprintf( szWorkMDI, "%.8g", fResolution );
6654 46 : SetMetadataItem( "TIFFTAG_YRESOLUTION", szWorkMDI );
6655 : }
6656 :
6657 4277 : if( TIFFGetField( hTIFF, TIFFTAG_MINSAMPLEVALUE, &nShort ) )
6658 : {
6659 0 : sprintf( szWorkMDI, "%d", nShort );
6660 0 : SetMetadataItem( "TIFFTAG_MINSAMPLEVALUE", szWorkMDI );
6661 : }
6662 :
6663 4277 : if( TIFFGetField( hTIFF, TIFFTAG_MAXSAMPLEVALUE, &nShort ) )
6664 : {
6665 0 : sprintf( szWorkMDI, "%d", nShort );
6666 0 : SetMetadataItem( "TIFFTAG_MAXSAMPLEVALUE", szWorkMDI );
6667 : }
6668 :
6669 4277 : if( TIFFGetField( hTIFF, TIFFTAG_RESOLUTIONUNIT, &nShort ) )
6670 : {
6671 46 : if( nShort == RESUNIT_NONE )
6672 16 : sprintf( szWorkMDI, "%d (unitless)", nShort );
6673 30 : else if( nShort == RESUNIT_INCH )
6674 30 : sprintf( szWorkMDI, "%d (pixels/inch)", nShort );
6675 0 : else if( nShort == RESUNIT_CENTIMETER )
6676 0 : sprintf( szWorkMDI, "%d (pixels/cm)", nShort );
6677 : else
6678 0 : sprintf( szWorkMDI, "%d", nShort );
6679 46 : SetMetadataItem( "TIFFTAG_RESOLUTIONUNIT", szWorkMDI );
6680 : }
6681 :
6682 : int nTagSize;
6683 : void* pData;
6684 4277 : if( TIFFGetField( hTIFF, TIFFTAG_XMLPACKET, &nTagSize, &pData ) )
6685 : {
6686 2 : char* pszXMP = (char*)VSIMalloc(nTagSize + 1);
6687 2 : if (pszXMP)
6688 : {
6689 2 : memcpy(pszXMP, pData, nTagSize);
6690 2 : pszXMP[nTagSize] = '\0';
6691 :
6692 : char *apszMDList[2];
6693 2 : apszMDList[0] = pszXMP;
6694 2 : apszMDList[1] = NULL;
6695 2 : SetMetadata(apszMDList, "xml:XMP");
6696 :
6697 2 : CPLFree(pszXMP);
6698 : }
6699 : }
6700 :
6701 4277 : if( nCompression == COMPRESSION_NONE )
6702 : /* no compression tag */;
6703 432 : else if( nCompression == COMPRESSION_CCITTRLE )
6704 0 : SetMetadataItem( "COMPRESSION", "CCITTRLE", "IMAGE_STRUCTURE" );
6705 432 : else if( nCompression == COMPRESSION_CCITTFAX3 )
6706 0 : SetMetadataItem( "COMPRESSION", "CCITTFAX3", "IMAGE_STRUCTURE" );
6707 432 : else if( nCompression == COMPRESSION_CCITTFAX4 )
6708 9 : SetMetadataItem( "COMPRESSION", "CCITTFAX4", "IMAGE_STRUCTURE" );
6709 423 : else if( nCompression == COMPRESSION_LZW )
6710 42 : SetMetadataItem( "COMPRESSION", "LZW", "IMAGE_STRUCTURE" );
6711 381 : else if( nCompression == COMPRESSION_OJPEG )
6712 1 : SetMetadataItem( "COMPRESSION", "OJPEG", "IMAGE_STRUCTURE" );
6713 380 : else if( nCompression == COMPRESSION_JPEG )
6714 : {
6715 155 : if ( nPhotometric == PHOTOMETRIC_YCBCR )
6716 118 : SetMetadataItem( "COMPRESSION", "YCbCr JPEG", "IMAGE_STRUCTURE" );
6717 : else
6718 37 : SetMetadataItem( "COMPRESSION", "JPEG", "IMAGE_STRUCTURE" );
6719 : }
6720 225 : else if( nCompression == COMPRESSION_NEXT )
6721 0 : SetMetadataItem( "COMPRESSION", "NEXT", "IMAGE_STRUCTURE" );
6722 225 : else if( nCompression == COMPRESSION_CCITTRLEW )
6723 0 : SetMetadataItem( "COMPRESSION", "CCITTRLEW", "IMAGE_STRUCTURE" );
6724 225 : else if( nCompression == COMPRESSION_PACKBITS )
6725 10 : SetMetadataItem( "COMPRESSION", "PACKBITS", "IMAGE_STRUCTURE" );
6726 215 : else if( nCompression == COMPRESSION_THUNDERSCAN )
6727 0 : SetMetadataItem( "COMPRESSION", "THUNDERSCAN", "IMAGE_STRUCTURE" );
6728 215 : else if( nCompression == COMPRESSION_PIXARFILM )
6729 0 : SetMetadataItem( "COMPRESSION", "PIXARFILM", "IMAGE_STRUCTURE" );
6730 215 : else if( nCompression == COMPRESSION_PIXARLOG )
6731 0 : SetMetadataItem( "COMPRESSION", "PIXARLOG", "IMAGE_STRUCTURE" );
6732 215 : else if( nCompression == COMPRESSION_DEFLATE )
6733 71 : SetMetadataItem( "COMPRESSION", "DEFLATE", "IMAGE_STRUCTURE" );
6734 144 : else if( nCompression == COMPRESSION_ADOBE_DEFLATE )
6735 144 : SetMetadataItem( "COMPRESSION", "DEFLATE", "IMAGE_STRUCTURE" );
6736 0 : else if( nCompression == COMPRESSION_DCS )
6737 0 : SetMetadataItem( "COMPRESSION", "DCS", "IMAGE_STRUCTURE" );
6738 0 : else if( nCompression == COMPRESSION_JBIG )
6739 0 : SetMetadataItem( "COMPRESSION", "JBIG", "IMAGE_STRUCTURE" );
6740 0 : else if( nCompression == COMPRESSION_SGILOG )
6741 0 : SetMetadataItem( "COMPRESSION", "SGILOG", "IMAGE_STRUCTURE" );
6742 0 : else if( nCompression == COMPRESSION_SGILOG24 )
6743 0 : SetMetadataItem( "COMPRESSION", "SGILOG24", "IMAGE_STRUCTURE" );
6744 0 : else if( nCompression == COMPRESSION_JP2000 )
6745 0 : SetMetadataItem( "COMPRESSION", "JP2000", "IMAGE_STRUCTURE" );
6746 0 : else if( nCompression == COMPRESSION_LZMA )
6747 0 : SetMetadataItem( "COMPRESSION", "LZMA", "IMAGE_STRUCTURE" );
6748 :
6749 : else
6750 : {
6751 0 : CPLString oComp;
6752 : SetMetadataItem( "COMPRESSION",
6753 0 : (const char *) oComp.Printf( "%d", nCompression));
6754 : }
6755 :
6756 4799 : if( nPlanarConfig == PLANARCONFIG_CONTIG && nBands != 1 )
6757 522 : SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" );
6758 : else
6759 3755 : SetMetadataItem( "INTERLEAVE", "BAND", "IMAGE_STRUCTURE" );
6760 :
6761 4277 : if( (GetRasterBand(1)->GetRasterDataType() == GDT_Byte && nBitsPerSample != 8 ) ||
6762 : (GetRasterBand(1)->GetRasterDataType() == GDT_UInt16 && nBitsPerSample != 16) ||
6763 : (GetRasterBand(1)->GetRasterDataType() == GDT_UInt32 && nBitsPerSample != 32) )
6764 : {
6765 1204 : for (int i = 0; i < nBands; ++i)
6766 : GetRasterBand(i+1)->SetMetadataItem( "NBITS",
6767 : CPLString().Printf( "%d", (int)nBitsPerSample ),
6768 358 : "IMAGE_STRUCTURE" );
6769 : }
6770 :
6771 4277 : if( bMinIsWhite )
6772 8 : SetMetadataItem( "MINISWHITE", "YES", "IMAGE_STRUCTURE" );
6773 :
6774 4277 : if( TIFFGetField( hTIFF, TIFFTAG_GDAL_METADATA, &pszText ) )
6775 : {
6776 211 : CPLXMLNode *psRoot = CPLParseXMLString( pszText );
6777 211 : CPLXMLNode *psItem = NULL;
6778 :
6779 211 : if( psRoot != NULL && psRoot->eType == CXT_Element
6780 : && EQUAL(psRoot->pszValue,"GDALMetadata") )
6781 211 : psItem = psRoot->psChild;
6782 :
6783 1073 : for( ; psItem != NULL; psItem = psItem->psNext )
6784 : {
6785 : const char *pszKey, *pszValue, *pszRole, *pszDomain;
6786 : char *pszUnescapedValue;
6787 862 : int nBand, bIsXML = FALSE;
6788 :
6789 862 : if( psItem->eType != CXT_Element
6790 : || !EQUAL(psItem->pszValue,"Item") )
6791 0 : continue;
6792 :
6793 862 : pszKey = CPLGetXMLValue( psItem, "name", NULL );
6794 862 : pszValue = CPLGetXMLValue( psItem, NULL, NULL );
6795 862 : nBand = atoi(CPLGetXMLValue( psItem, "sample", "-1" )) + 1;
6796 862 : pszRole = CPLGetXMLValue( psItem, "role", "" );
6797 862 : pszDomain = CPLGetXMLValue( psItem, "domain", "" );
6798 :
6799 862 : if( pszKey == NULL || pszValue == NULL )
6800 37 : continue;
6801 :
6802 825 : if( EQUALN(pszDomain,"xml:",4) )
6803 3 : bIsXML = TRUE;
6804 :
6805 : pszUnescapedValue = CPLUnescapeString( pszValue, NULL,
6806 825 : CPLES_XML );
6807 825 : if( nBand == 0 )
6808 : {
6809 649 : if( bIsXML )
6810 : {
6811 3 : char *apszMD[2] = { pszUnescapedValue, NULL };
6812 3 : SetMetadata( apszMD, pszDomain );
6813 : }
6814 : else
6815 646 : SetMetadataItem( pszKey, pszUnescapedValue, pszDomain );
6816 : }
6817 : else
6818 : {
6819 176 : GDALRasterBand *poBand = GetRasterBand(nBand);
6820 176 : if( poBand != NULL )
6821 : {
6822 176 : if( EQUAL(pszRole,"scale") )
6823 6 : poBand->SetScale( CPLAtofM(pszUnescapedValue) );
6824 170 : else if( EQUAL(pszRole,"offset") )
6825 6 : poBand->SetOffset( CPLAtofM(pszUnescapedValue) );
6826 164 : else if( EQUAL(pszRole,"unittype") )
6827 13 : poBand->SetUnitType( pszUnescapedValue );
6828 151 : else if( EQUAL(pszRole,"description") )
6829 2 : poBand->SetDescription( pszUnescapedValue );
6830 : else
6831 : {
6832 149 : if( bIsXML )
6833 : {
6834 0 : char *apszMD[2] = { pszUnescapedValue, NULL };
6835 0 : poBand->SetMetadata( apszMD, pszDomain );
6836 : }
6837 : else
6838 : poBand->SetMetadataItem(pszKey,pszUnescapedValue,
6839 149 : pszDomain );
6840 : }
6841 : }
6842 : }
6843 825 : CPLFree( pszUnescapedValue );
6844 : }
6845 :
6846 211 : CPLDestroyXMLNode( psRoot );
6847 : }
6848 :
6849 4277 : bMetadataChanged = FALSE;
6850 :
6851 : /* -------------------------------------------------------------------- */
6852 : /* Check for NODATA */
6853 : /* -------------------------------------------------------------------- */
6854 4277 : if( TIFFGetField( hTIFF, TIFFTAG_GDAL_NODATA, &pszText ) )
6855 : {
6856 182 : bNoDataSet = TRUE;
6857 182 : dfNoDataValue = CPLAtofM( pszText );
6858 : }
6859 :
6860 : /* -------------------------------------------------------------------- */
6861 : /* If this is a "base" raster, we should scan for any */
6862 : /* associated overviews, internal mask bands and subdatasets. */
6863 : /* -------------------------------------------------------------------- */
6864 4277 : if( bBase )
6865 : {
6866 : //ScanDirectories();
6867 : }
6868 :
6869 4277 : return( CE_None );
6870 : }
6871 :
6872 : /************************************************************************/
6873 : /* ScanDirectories() */
6874 : /* */
6875 : /* Scan through all the directories finding overviews, masks */
6876 : /* and subdatasets. */
6877 : /************************************************************************/
6878 :
6879 308776 : void GTiffDataset::ScanDirectories()
6880 :
6881 : {
6882 : /* -------------------------------------------------------------------- */
6883 : /* We only scan once. We do not scan for non-base datasets. */
6884 : /* -------------------------------------------------------------------- */
6885 308776 : if( !bScanDeferred )
6886 307444 : return;
6887 :
6888 1332 : bScanDeferred = FALSE;
6889 :
6890 1332 : if( !bBase )
6891 57 : return;
6892 :
6893 1275 : if( TIFFLastDirectory( hTIFF ) )
6894 1137 : return;
6895 :
6896 138 : CPLDebug( "GTiff", "ScanDirectories()" );
6897 :
6898 : /* ==================================================================== */
6899 : /* Scan all directories. */
6900 : /* ==================================================================== */
6901 138 : char **papszSubdatasets = NULL;
6902 138 : int iDirIndex = 0;
6903 :
6904 138 : FlushDirectory();
6905 631 : while( !TIFFLastDirectory( hTIFF )
6906 : && (iDirIndex == 0 || TIFFReadDirectory( hTIFF ) != 0) )
6907 : {
6908 355 : toff_t nThisDir = TIFFCurrentDirOffset(hTIFF);
6909 355 : uint32 nSubType = 0;
6910 :
6911 355 : *ppoActiveDSRef = NULL; // our directory no longer matches this ds
6912 :
6913 355 : iDirIndex++;
6914 :
6915 355 : if( !TIFFGetField(hTIFF, TIFFTAG_SUBFILETYPE, &nSubType) )
6916 75 : nSubType = 0;
6917 :
6918 : /* Embedded overview of the main image */
6919 500 : if ((nSubType & FILETYPE_REDUCEDIMAGE) != 0 &&
6920 : (nSubType & FILETYPE_MASK) == 0 &&
6921 : iDirIndex != 1 )
6922 : {
6923 : GTiffDataset *poODS;
6924 :
6925 145 : poODS = new GTiffDataset();
6926 290 : if( poODS->OpenOffset( hTIFF, ppoActiveDSRef, nThisDir, FALSE,
6927 : eAccess ) != CE_None
6928 : || poODS->GetRasterCount() != GetRasterCount() )
6929 : {
6930 0 : delete poODS;
6931 : }
6932 : else
6933 : {
6934 : CPLDebug( "GTiff", "Opened %dx%d overview.\n",
6935 145 : poODS->GetRasterXSize(), poODS->GetRasterYSize());
6936 145 : nOverviewCount++;
6937 : papoOverviewDS = (GTiffDataset **)
6938 : CPLRealloc(papoOverviewDS,
6939 145 : nOverviewCount * (sizeof(void*)));
6940 145 : papoOverviewDS[nOverviewCount-1] = poODS;
6941 145 : poODS->poBaseDS = this;
6942 : }
6943 : }
6944 :
6945 : /* Embedded mask of the main image */
6946 249 : else if ((nSubType & FILETYPE_MASK) != 0 &&
6947 : (nSubType & FILETYPE_REDUCEDIMAGE) == 0 &&
6948 : poMaskDS == NULL )
6949 : {
6950 39 : poMaskDS = new GTiffDataset();
6951 :
6952 : /* The TIFF6 specification - page 37 - only allows 1 SamplesPerPixel and 1 BitsPerSample
6953 : Here we support either 1 or 8 bit per sample
6954 : and we support either 1 sample per pixel or as many samples as in the main image
6955 : We don't check the value of the PhotometricInterpretation tag, which should be
6956 : set to "Transparency mask" (4) according to the specification (page 36)
6957 : ... But the TIFF6 specification allows image masks to have a higher resolution than
6958 : the main image, what we don't support here
6959 : */
6960 :
6961 78 : if( poMaskDS->OpenOffset( hTIFF, ppoActiveDSRef, nThisDir,
6962 : FALSE, eAccess ) != CE_None
6963 : || poMaskDS->GetRasterCount() == 0
6964 : || !(poMaskDS->GetRasterCount() == 1 || poMaskDS->GetRasterCount() == GetRasterCount())
6965 : || poMaskDS->GetRasterXSize() != GetRasterXSize()
6966 : || poMaskDS->GetRasterYSize() != GetRasterYSize()
6967 : || poMaskDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte)
6968 : {
6969 0 : delete poMaskDS;
6970 0 : poMaskDS = NULL;
6971 : }
6972 : else
6973 : {
6974 39 : CPLDebug( "GTiff", "Opened band mask.\n");
6975 39 : poMaskDS->poBaseDS = this;
6976 :
6977 39 : poMaskDS->bPromoteTo8Bits = CSLTestBoolean(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK_TO_8BIT", "YES"));
6978 : }
6979 : }
6980 :
6981 : /* Embedded mask of an overview */
6982 : /* The TIFF6 specification allows the combination of the FILETYPE_xxxx masks */
6983 203 : else if ((nSubType & FILETYPE_REDUCEDIMAGE) != 0 &&
6984 : (nSubType & FILETYPE_MASK) != 0)
6985 : {
6986 32 : GTiffDataset* poDS = new GTiffDataset();
6987 64 : if( poDS->OpenOffset( hTIFF, ppoActiveDSRef, nThisDir, FALSE,
6988 : eAccess ) != CE_None
6989 : || poDS->GetRasterCount() == 0
6990 : || poDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte)
6991 : {
6992 0 : delete poDS;
6993 : }
6994 : else
6995 : {
6996 : int i;
6997 47 : for(i=0;i<nOverviewCount;i++)
6998 : {
6999 111 : if (((GTiffDataset*)papoOverviewDS[i])->poMaskDS == NULL &&
7000 32 : poDS->GetRasterXSize() == papoOverviewDS[i]->GetRasterXSize() &&
7001 32 : poDS->GetRasterYSize() == papoOverviewDS[i]->GetRasterYSize() &&
7002 : (poDS->GetRasterCount() == 1 || poDS->GetRasterCount() == GetRasterCount()))
7003 : {
7004 : CPLDebug( "GTiff", "Opened band mask for %dx%d overview.\n",
7005 32 : poDS->GetRasterXSize(), poDS->GetRasterYSize());
7006 32 : ((GTiffDataset*)papoOverviewDS[i])->poMaskDS = poDS;
7007 32 : poDS->bPromoteTo8Bits = CSLTestBoolean(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK_TO_8BIT", "YES"));
7008 32 : poDS->poBaseDS = this;
7009 32 : break;
7010 : }
7011 : }
7012 32 : if (i == nOverviewCount)
7013 : {
7014 0 : delete poDS;
7015 : }
7016 : }
7017 : }
7018 139 : else if( nSubType == 0 || nSubType == FILETYPE_PAGE ) {
7019 75 : CPLString osName, osDesc;
7020 : uint32 nXSize, nYSize;
7021 : uint16 nSPP;
7022 :
7023 75 : TIFFGetField( hTIFF, TIFFTAG_IMAGEWIDTH, &nXSize );
7024 75 : TIFFGetField( hTIFF, TIFFTAG_IMAGELENGTH, &nYSize );
7025 75 : if( !TIFFGetField(hTIFF, TIFFTAG_SAMPLESPERPIXEL, &nSPP ) )
7026 0 : nSPP = 1;
7027 :
7028 : osName.Printf( "SUBDATASET_%d_NAME=GTIFF_DIR:%d:%s",
7029 75 : iDirIndex, iDirIndex, osFilename.c_str() );
7030 : osDesc.Printf( "SUBDATASET_%d_DESC=Page %d (%dP x %dL x %dB)",
7031 : iDirIndex, iDirIndex,
7032 75 : (int)nXSize, (int)nYSize, nSPP );
7033 :
7034 : papszSubdatasets =
7035 75 : CSLAddString( papszSubdatasets, osName );
7036 : papszSubdatasets =
7037 75 : CSLAddString( papszSubdatasets, osDesc );
7038 : }
7039 :
7040 : // Make sure we are stepping from the expected directory regardless
7041 : // of churn done processing the above.
7042 355 : if( TIFFCurrentDirOffset(hTIFF) != nThisDir )
7043 0 : TIFFSetSubDirectory( hTIFF, nThisDir );
7044 355 : *ppoActiveDSRef = NULL;
7045 : }
7046 :
7047 : /* If we have a mask for the main image, loop over the overviews, and if they */
7048 : /* have a mask, let's set this mask as an overview of the main mask... */
7049 138 : if (poMaskDS != NULL)
7050 : {
7051 : int i;
7052 71 : for(i=0;i<nOverviewCount;i++)
7053 : {
7054 32 : if (((GTiffDataset*)papoOverviewDS[i])->poMaskDS != NULL)
7055 : {
7056 32 : poMaskDS->nOverviewCount++;
7057 : poMaskDS->papoOverviewDS = (GTiffDataset **)
7058 : CPLRealloc(poMaskDS->papoOverviewDS,
7059 32 : poMaskDS->nOverviewCount * (sizeof(void*)));
7060 32 : poMaskDS->papoOverviewDS[poMaskDS->nOverviewCount-1] =
7061 32 : ((GTiffDataset*)papoOverviewDS[i])->poMaskDS;
7062 : }
7063 : }
7064 : }
7065 :
7066 : /* -------------------------------------------------------------------- */
7067 : /* Only keep track of subdatasets if we have more than one */
7068 : /* subdataset (pair). */
7069 : /* -------------------------------------------------------------------- */
7070 138 : if( CSLCount(papszSubdatasets) > 2 )
7071 : {
7072 1 : oGTiffMDMD.SetMetadata( papszSubdatasets, "SUBDATASETS" );
7073 : }
7074 138 : CSLDestroy( papszSubdatasets );
7075 :
7076 : }
7077 :
7078 :
7079 2416 : static int GTiffGetLZMAPreset(char** papszOptions)
7080 : {
7081 2416 : int nLZMAPreset = -1;
7082 2416 : const char* pszValue = CSLFetchNameValue( papszOptions, "LZMA_PRESET" );
7083 2416 : if( pszValue != NULL )
7084 : {
7085 0 : nLZMAPreset = atoi( pszValue );
7086 0 : if (!(nLZMAPreset >= 0 && nLZMAPreset <= 9))
7087 : {
7088 : CPLError( CE_Warning, CPLE_IllegalArg,
7089 : "LZMA_PRESET=%s value not recognised, ignoring.",
7090 0 : pszValue );
7091 0 : nLZMAPreset = -1;
7092 : }
7093 : }
7094 2416 : return nLZMAPreset;
7095 : }
7096 :
7097 :
7098 2416 : static int GTiffGetZLevel(char** papszOptions)
7099 : {
7100 2416 : int nZLevel = -1;
7101 2416 : const char* pszValue = CSLFetchNameValue( papszOptions, "ZLEVEL" );
7102 2416 : if( pszValue != NULL )
7103 : {
7104 0 : nZLevel = atoi( pszValue );
7105 0 : if (!(nZLevel >= 1 && nZLevel <= 9))
7106 : {
7107 : CPLError( CE_Warning, CPLE_IllegalArg,
7108 : "ZLEVEL=%s value not recognised, ignoring.",
7109 0 : pszValue );
7110 0 : nZLevel = -1;
7111 : }
7112 : }
7113 2416 : return nZLevel;
7114 : }
7115 :
7116 2416 : static int GTiffGetJpegQuality(char** papszOptions)
7117 : {
7118 2416 : int nJpegQuality = -1;
7119 2416 : const char* pszValue = CSLFetchNameValue( papszOptions, "JPEG_QUALITY" );
7120 2416 : if( pszValue != NULL )
7121 : {
7122 28 : nJpegQuality = atoi( pszValue );
7123 28 : if (!(nJpegQuality >= 1 && nJpegQuality <= 100))
7124 : {
7125 : CPLError( CE_Warning, CPLE_IllegalArg,
7126 : "JPEG_QUALITY=%s value not recognised, ignoring.",
7127 0 : pszValue );
7128 0 : nJpegQuality = -1;
7129 : }
7130 : }
7131 2416 : return nJpegQuality;
7132 : }
7133 :
7134 : /************************************************************************/
7135 : /* GTiffCreate() */
7136 : /* */
7137 : /* Shared functionality between GTiffDataset::Create() and */
7138 : /* GTiffCreateCopy() for creating TIFF file based on a set of */
7139 : /* options and a configuration. */
7140 : /************************************************************************/
7141 :
7142 1218 : TIFF *GTiffDataset::CreateLL( const char * pszFilename,
7143 : int nXSize, int nYSize, int nBands,
7144 : GDALDataType eType,
7145 : double dfExtraSpaceForOverviews,
7146 : char **papszParmList )
7147 :
7148 : {
7149 : TIFF *hTIFF;
7150 1218 : int nBlockXSize = 0, nBlockYSize = 0;
7151 1218 : int bTiled = FALSE;
7152 1218 : int nCompression = COMPRESSION_NONE;
7153 1218 : int nPredictor = PREDICTOR_NONE, nJpegQuality = -1, nZLevel = -1,
7154 1218 : nLZMAPreset = -1;
7155 : uint16 nSampleFormat;
7156 : int nPlanar;
7157 : const char *pszValue;
7158 : const char *pszProfile;
7159 1218 : int bCreateBigTIFF = FALSE;
7160 :
7161 1218 : if (!GTiffOneTimeInit())
7162 0 : return NULL;
7163 :
7164 : /* -------------------------------------------------------------------- */
7165 : /* Blow on a few errors. */
7166 : /* -------------------------------------------------------------------- */
7167 1218 : if( nXSize < 1 || nYSize < 1 || nBands < 1 )
7168 : {
7169 : CPLError( CE_Failure, CPLE_AppDefined,
7170 : "Attempt to create %dx%dx%d TIFF file, but width, height and bands\n"
7171 : "must be positive.",
7172 1 : nXSize, nYSize, nBands );
7173 :
7174 1 : return NULL;
7175 : }
7176 :
7177 1217 : if (nBands > 65535)
7178 : {
7179 : CPLError( CE_Failure, CPLE_AppDefined,
7180 : "Attempt to create %dx%dx%d TIFF file, but bands\n"
7181 : "must be lesser or equal to 65535.",
7182 0 : nXSize, nYSize, nBands );
7183 :
7184 0 : return NULL;
7185 : }
7186 :
7187 : /* -------------------------------------------------------------------- */
7188 : /* Setup values based on options. */
7189 : /* -------------------------------------------------------------------- */
7190 1217 : pszProfile = CSLFetchNameValue(papszParmList,"PROFILE");
7191 1217 : if( pszProfile == NULL )
7192 1204 : pszProfile = "GDALGeoTIFF";
7193 :
7194 1217 : if( CSLFetchBoolean( papszParmList, "TILED", FALSE ) )
7195 28 : bTiled = TRUE;
7196 :
7197 1217 : pszValue = CSLFetchNameValue(papszParmList,"BLOCKXSIZE");
7198 1217 : if( pszValue != NULL )
7199 14 : nBlockXSize = atoi( pszValue );
7200 :
7201 1217 : pszValue = CSLFetchNameValue(papszParmList,"BLOCKYSIZE");
7202 1217 : if( pszValue != NULL )
7203 22 : nBlockYSize = atoi( pszValue );
7204 :
7205 1217 : pszValue = CSLFetchNameValue(papszParmList,"INTERLEAVE");
7206 1217 : if( pszValue != NULL )
7207 : {
7208 26 : if( EQUAL( pszValue, "PIXEL" ) )
7209 13 : nPlanar = PLANARCONFIG_CONTIG;
7210 13 : else if( EQUAL( pszValue, "BAND" ) )
7211 13 : nPlanar = PLANARCONFIG_SEPARATE;
7212 : else
7213 : {
7214 : CPLError( CE_Failure, CPLE_AppDefined,
7215 : "INTERLEAVE=%s unsupported, value must be PIXEL or BAND.",
7216 0 : pszValue );
7217 0 : return NULL;
7218 : }
7219 : }
7220 : else
7221 : {
7222 1191 : nPlanar = PLANARCONFIG_CONTIG;
7223 : }
7224 :
7225 1217 : pszValue = CSLFetchNameValue( papszParmList, "COMPRESS" );
7226 1217 : if( pszValue != NULL )
7227 : {
7228 65 : nCompression = GTIFFGetCompressionMethod(pszValue, "COMPRESS");
7229 65 : if (nCompression < 0)
7230 0 : return NULL;
7231 : }
7232 :
7233 1217 : pszValue = CSLFetchNameValue( papszParmList, "PREDICTOR" );
7234 1217 : if( pszValue != NULL )
7235 4 : nPredictor = atoi( pszValue );
7236 :
7237 1217 : nZLevel = GTiffGetZLevel(papszParmList);
7238 1217 : nLZMAPreset = GTiffGetLZMAPreset(papszParmList);
7239 1217 : nJpegQuality = GTiffGetJpegQuality(papszParmList);
7240 :
7241 : /* -------------------------------------------------------------------- */
7242 : /* Compute the uncompressed size. */
7243 : /* -------------------------------------------------------------------- */
7244 : double dfUncompressedImageSize;
7245 :
7246 : dfUncompressedImageSize =
7247 1217 : nXSize * ((double)nYSize) * nBands * (GDALGetDataTypeSize(eType)/8);
7248 1217 : dfUncompressedImageSize += dfExtraSpaceForOverviews;
7249 :
7250 1217 : if( nCompression == COMPRESSION_NONE
7251 : && dfUncompressedImageSize > 4200000000.0 )
7252 : {
7253 : #ifndef BIGTIFF_SUPPORT
7254 : CPLError( CE_Failure, CPLE_NotSupported,
7255 : "A %d pixels x %d lines x %d bands %s image would be larger than 4GB\n"
7256 : "but this is the largest size a TIFF can be, and BigTIFF is unavailable.\n"
7257 : "Creation failed.",
7258 : nXSize, nYSize, nBands, GDALGetDataTypeName(eType) );
7259 : return NULL;
7260 : #endif
7261 : }
7262 :
7263 : /* -------------------------------------------------------------------- */
7264 : /* Should the file be created as a bigtiff file? */
7265 : /* -------------------------------------------------------------------- */
7266 1217 : const char *pszBIGTIFF = CSLFetchNameValue(papszParmList, "BIGTIFF");
7267 :
7268 1217 : if( pszBIGTIFF == NULL )
7269 1210 : pszBIGTIFF = "IF_NEEDED";
7270 :
7271 1217 : if( EQUAL(pszBIGTIFF,"IF_NEEDED") )
7272 : {
7273 1211 : if( nCompression == COMPRESSION_NONE
7274 : && dfUncompressedImageSize > 4200000000.0 )
7275 10 : bCreateBigTIFF = TRUE;
7276 : }
7277 6 : else if( EQUAL(pszBIGTIFF,"IF_SAFER") )
7278 : {
7279 4 : if( dfUncompressedImageSize > 2000000000.0 )
7280 1 : bCreateBigTIFF = TRUE;
7281 : }
7282 :
7283 : else
7284 : {
7285 2 : bCreateBigTIFF = CSLTestBoolean( pszBIGTIFF );
7286 2 : if (!bCreateBigTIFF && nCompression == COMPRESSION_NONE &&
7287 : dfUncompressedImageSize > 4200000000.0 )
7288 : {
7289 : CPLError( CE_Failure, CPLE_NotSupported,
7290 : "The TIFF file will be larger than 4GB, so BigTIFF is necessary.\n"
7291 1 : "Creation failed.");
7292 1 : return NULL;
7293 : }
7294 : }
7295 :
7296 : #ifndef BIGTIFF_SUPPORT
7297 : if( bCreateBigTIFF )
7298 : {
7299 : CPLError( CE_Warning, CPLE_NotSupported,
7300 : "BigTIFF requested, but GDAL built without BigTIFF\n"
7301 : "enabled libtiff, request ignored." );
7302 : bCreateBigTIFF = FALSE;
7303 : }
7304 : #endif
7305 :
7306 1216 : if( bCreateBigTIFF )
7307 12 : CPLDebug( "GTiff", "File being created as a BigTIFF." );
7308 :
7309 : /* -------------------------------------------------------------------- */
7310 : /* Check if the user wishes a particular endianness */
7311 : /* -------------------------------------------------------------------- */
7312 :
7313 1216 : int eEndianness = ENDIANNESS_NATIVE;
7314 1216 : pszValue = CSLFetchNameValue(papszParmList, "ENDIANNESS");
7315 1216 : if ( pszValue == NULL )
7316 1210 : pszValue = CPLGetConfigOption( "GDAL_TIFF_ENDIANNESS", NULL );
7317 1216 : if ( pszValue != NULL )
7318 : {
7319 814 : if (EQUAL(pszValue, "LITTLE"))
7320 6 : eEndianness = ENDIANNESS_LITTLE;
7321 808 : else if (EQUAL(pszValue, "BIG"))
7322 0 : eEndianness = ENDIANNESS_BIG;
7323 808 : else if (EQUAL(pszValue, "INVERTED"))
7324 : {
7325 : #ifdef CPL_LSB
7326 27 : eEndianness = ENDIANNESS_BIG;
7327 : #else
7328 : eEndianness = ENDIANNESS_LITTLE;
7329 : #endif
7330 : }
7331 781 : else if (!EQUAL(pszValue, "NATIVE"))
7332 : {
7333 : CPLError( CE_Warning, CPLE_NotSupported,
7334 0 : "ENDIANNESS=%s not supported. Defaulting to NATIVE", pszValue );
7335 : }
7336 : }
7337 :
7338 : /* -------------------------------------------------------------------- */
7339 : /* Try opening the dataset. */
7340 : /* -------------------------------------------------------------------- */
7341 :
7342 : char szOpeningFlag[5];
7343 1216 : strcpy(szOpeningFlag, "w+");
7344 1216 : if (bCreateBigTIFF)
7345 12 : strcat(szOpeningFlag, "8");
7346 1216 : if (eEndianness == ENDIANNESS_BIG)
7347 27 : strcat(szOpeningFlag, "b");
7348 1189 : else if (eEndianness == ENDIANNESS_LITTLE)
7349 6 : strcat(szOpeningFlag, "l");
7350 1216 : hTIFF = VSI_TIFFOpen( pszFilename, szOpeningFlag );
7351 1216 : if( hTIFF == NULL )
7352 : {
7353 17 : if( CPLGetLastErrorNo() == 0 )
7354 : CPLError( CE_Failure, CPLE_OpenFailed,
7355 : "Attempt to create new tiff file `%s'\n"
7356 : "failed in XTIFFOpen().\n",
7357 0 : pszFilename );
7358 17 : return NULL;
7359 : }
7360 :
7361 : /* -------------------------------------------------------------------- */
7362 : /* How many bits per sample? We have a special case if NBITS */
7363 : /* specified for GDT_Byte, GDT_UInt16, GDT_UInt32. */
7364 : /* -------------------------------------------------------------------- */
7365 1199 : int nBitsPerSample = GDALGetDataTypeSize(eType);
7366 1199 : if (CSLFetchNameValue(papszParmList, "NBITS") != NULL)
7367 : {
7368 38 : int nMinBits = 0, nMaxBits = 0;
7369 38 : nBitsPerSample = atoi(CSLFetchNameValue(papszParmList, "NBITS"));
7370 38 : if( eType == GDT_Byte )
7371 : {
7372 13 : nMinBits = 1;
7373 13 : nMaxBits = 8;
7374 : }
7375 25 : else if( eType == GDT_UInt16 )
7376 : {
7377 13 : nMinBits = 9;
7378 13 : nMaxBits = 16;
7379 : }
7380 12 : else if( eType == GDT_UInt32 )
7381 : {
7382 12 : nMinBits = 17;
7383 12 : nMaxBits = 32;
7384 : }
7385 : else
7386 : {
7387 : CPLError(CE_Warning, CPLE_NotSupported,
7388 : "NBITS is not supported for data type %s",
7389 0 : GDALGetDataTypeName(eType));
7390 0 : nBitsPerSample = GDALGetDataTypeSize(eType);
7391 : }
7392 :
7393 38 : if (nMinBits != 0)
7394 : {
7395 38 : if (nBitsPerSample < nMinBits)
7396 : {
7397 : CPLError(CE_Warning, CPLE_AppDefined,
7398 : "NBITS=%d is invalid for data type %s. Using NBITS=%d",
7399 0 : nBitsPerSample, GDALGetDataTypeName(eType), nMinBits);
7400 0 : nBitsPerSample = nMinBits;
7401 : }
7402 38 : else if (nBitsPerSample > nMaxBits)
7403 : {
7404 : CPLError(CE_Warning, CPLE_AppDefined,
7405 : "NBITS=%d is invalid for data type %s. Using NBITS=%d",
7406 0 : nBitsPerSample, GDALGetDataTypeName(eType), nMaxBits);
7407 0 : nBitsPerSample = nMaxBits;
7408 : }
7409 : }
7410 : }
7411 :
7412 : /* -------------------------------------------------------------------- */
7413 : /* Do we have a custom pixel type (just used for signed byte now). */
7414 : /* -------------------------------------------------------------------- */
7415 1199 : const char *pszPixelType = CSLFetchNameValue( papszParmList, "PIXELTYPE" );
7416 1199 : if( pszPixelType == NULL )
7417 1197 : pszPixelType = "";
7418 :
7419 : /* -------------------------------------------------------------------- */
7420 : /* Setup some standard flags. */
7421 : /* -------------------------------------------------------------------- */
7422 1199 : TIFFSetField( hTIFF, TIFFTAG_IMAGEWIDTH, nXSize );
7423 1199 : TIFFSetField( hTIFF, TIFFTAG_IMAGELENGTH, nYSize );
7424 1199 : TIFFSetField( hTIFF, TIFFTAG_BITSPERSAMPLE, nBitsPerSample );
7425 :
7426 1324 : if( (eType == GDT_Byte && EQUAL(pszPixelType,"SIGNEDBYTE"))
7427 : || eType == GDT_Int16 || eType == GDT_Int32 )
7428 125 : nSampleFormat = SAMPLEFORMAT_INT;
7429 1176 : else if( eType == GDT_CInt16 || eType == GDT_CInt32 )
7430 102 : nSampleFormat = SAMPLEFORMAT_COMPLEXINT;
7431 1111 : else if( eType == GDT_Float32 || eType == GDT_Float64 )
7432 139 : nSampleFormat = SAMPLEFORMAT_IEEEFP;
7433 941 : else if( eType == GDT_CFloat32 || eType == GDT_CFloat64 )
7434 108 : nSampleFormat = SAMPLEFORMAT_COMPLEXIEEEFP;
7435 : else
7436 725 : nSampleFormat = SAMPLEFORMAT_UINT;
7437 :
7438 1199 : TIFFSetField( hTIFF, TIFFTAG_SAMPLEFORMAT, nSampleFormat );
7439 1199 : TIFFSetField( hTIFF, TIFFTAG_SAMPLESPERPIXEL, nBands );
7440 1199 : TIFFSetField( hTIFF, TIFFTAG_PLANARCONFIG, nPlanar );
7441 :
7442 : /* -------------------------------------------------------------------- */
7443 : /* Setup Photometric Interpretation. Take this value from the user */
7444 : /* passed option or guess correct value otherwise. */
7445 : /* -------------------------------------------------------------------- */
7446 1199 : int nSamplesAccountedFor = 1;
7447 1199 : int bForceColorTable = FALSE;
7448 :
7449 1199 : pszValue = CSLFetchNameValue(papszParmList,"PHOTOMETRIC");
7450 1199 : if( pszValue != NULL )
7451 : {
7452 31 : if( EQUAL( pszValue, "MINISBLACK" ) )
7453 0 : TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK );
7454 31 : else if( EQUAL( pszValue, "MINISWHITE" ) )
7455 2 : TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE );
7456 29 : else if( EQUAL( pszValue, "PALETTE" ))
7457 : {
7458 3 : TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE );
7459 3 : nSamplesAccountedFor = 1;
7460 3 : bForceColorTable = TRUE;
7461 : }
7462 26 : else if( EQUAL( pszValue, "RGB" ))
7463 : {
7464 2 : TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB );
7465 2 : nSamplesAccountedFor = 3;
7466 : }
7467 24 : else if( EQUAL( pszValue, "CMYK" ))
7468 : {
7469 2 : TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_SEPARATED );
7470 2 : nSamplesAccountedFor = 4;
7471 : }
7472 22 : else if( EQUAL( pszValue, "YCBCR" ))
7473 : {
7474 : /* Because of subsampling, setting YCBCR without JPEG compression leads */
7475 : /* to a crash currently. Would need to make GTiffRasterBand::IWriteBlock() */
7476 : /* aware of subsampling so that it doesn't overrun buffer size returned */
7477 : /* by libtiff */
7478 22 : if ( nCompression != COMPRESSION_JPEG )
7479 : {
7480 : CPLError(CE_Failure, CPLE_NotSupported,
7481 0 : "Currently, PHOTOMETRIC=YCBCR requires COMPRESS=JPEG");
7482 0 : XTIFFClose(hTIFF);
7483 0 : return NULL;
7484 : }
7485 :
7486 22 : if ( nPlanar == PLANARCONFIG_SEPARATE )
7487 : {
7488 : CPLError(CE_Failure, CPLE_NotSupported,
7489 0 : "PHOTOMETRIC=YCBCR requires INTERLEAVE=PIXEL");
7490 0 : XTIFFClose(hTIFF);
7491 0 : return NULL;
7492 : }
7493 :
7494 : /* YCBCR strictly requires 3 bands. Not less, not more */
7495 : /* Issue an explicit error message as libtiff one is a bit cryptic : */
7496 : /* TIFFVStripSize64:Invalid td_samplesperpixel value */
7497 22 : if ( nBands != 3 )
7498 : {
7499 : CPLError(CE_Failure, CPLE_NotSupported,
7500 0 : "PHOTOMETRIC=YCBCR requires a source raster with only 3 bands (RGB)");
7501 0 : XTIFFClose(hTIFF);
7502 0 : return NULL;
7503 : }
7504 :
7505 22 : TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_YCBCR );
7506 22 : nSamplesAccountedFor = 3;
7507 : }
7508 0 : else if( EQUAL( pszValue, "CIELAB" ))
7509 : {
7510 0 : TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_CIELAB );
7511 0 : nSamplesAccountedFor = 3;
7512 : }
7513 0 : else if( EQUAL( pszValue, "ICCLAB" ))
7514 : {
7515 0 : TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_ICCLAB );
7516 0 : nSamplesAccountedFor = 3;
7517 : }
7518 0 : else if( EQUAL( pszValue, "ITULAB" ))
7519 : {
7520 0 : TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_ITULAB );
7521 0 : nSamplesAccountedFor = 3;
7522 : }
7523 : else
7524 : {
7525 : CPLError( CE_Warning, CPLE_IllegalArg,
7526 : "PHOTOMETRIC=%s value not recognised, ignoring.\n"
7527 : "Set the Photometric Interpretation as MINISBLACK.",
7528 0 : pszValue );
7529 0 : TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK );
7530 : }
7531 :
7532 31 : if ( nBands < nSamplesAccountedFor )
7533 : {
7534 : CPLError( CE_Warning, CPLE_IllegalArg,
7535 : "PHOTOMETRIC=%s value does not correspond to number "
7536 : "of bands (%d), ignoring.\n"
7537 : "Set the Photometric Interpretation as MINISBLACK.",
7538 0 : pszValue, nBands );
7539 0 : TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK );
7540 : }
7541 : }
7542 : else
7543 : {
7544 : /*
7545 : * If image contains 3 or 4 bands and datatype is Byte then we will
7546 : * assume it is RGB. In all other cases assume it is MINISBLACK.
7547 : */
7548 1223 : if( nBands == 3 && eType == GDT_Byte )
7549 : {
7550 55 : TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB );
7551 55 : nSamplesAccountedFor = 3;
7552 : }
7553 1142 : else if( nBands == 4 && eType == GDT_Byte )
7554 : {
7555 : uint16 v[1];
7556 :
7557 : v[0] = GTiffGetAlphaValue(CSLFetchNameValue(papszParmList,"ALPHA"),
7558 29 : DEFAULT_ALPHA_TYPE);
7559 :
7560 29 : TIFFSetField(hTIFF, TIFFTAG_EXTRASAMPLES, 1, v);
7561 29 : TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB );
7562 29 : nSamplesAccountedFor = 4;
7563 : }
7564 : else
7565 : {
7566 1084 : TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK );
7567 1084 : nSamplesAccountedFor = 1;
7568 : }
7569 : }
7570 :
7571 : /* -------------------------------------------------------------------- */
7572 : /* If there are extra samples, we need to mark them with an */
7573 : /* appropriate extrasamples definition here. */
7574 : /* -------------------------------------------------------------------- */
7575 1199 : if( nBands > nSamplesAccountedFor )
7576 : {
7577 : uint16 *v;
7578 : int i;
7579 66 : int nExtraSamples = nBands - nSamplesAccountedFor;
7580 :
7581 66 : v = (uint16 *) CPLMalloc( sizeof(uint16) * nExtraSamples );
7582 :
7583 : v[0] = GTiffGetAlphaValue(CSLFetchNameValue(papszParmList, "ALPHA"),
7584 66 : EXTRASAMPLE_UNSPECIFIED);
7585 :
7586 131181 : for( i = 1; i < nExtraSamples; i++ )
7587 131115 : v[i] = EXTRASAMPLE_UNSPECIFIED;
7588 :
7589 66 : TIFFSetField(hTIFF, TIFFTAG_EXTRASAMPLES, nExtraSamples, v );
7590 :
7591 66 : CPLFree(v);
7592 : }
7593 :
7594 : /* Set the compression method before asking the default strip size */
7595 : /* This is usefull when translating to a JPEG-In-TIFF file where */
7596 : /* the default strip size is 8 or 16 depending on the photometric value */
7597 1199 : TIFFSetField( hTIFF, TIFFTAG_COMPRESSION, nCompression );
7598 :
7599 : /* -------------------------------------------------------------------- */
7600 : /* Setup tiling/stripping flags. */
7601 : /* -------------------------------------------------------------------- */
7602 1199 : if( bTiled )
7603 : {
7604 28 : if( nBlockXSize == 0 )
7605 15 : nBlockXSize = 256;
7606 :
7607 28 : if( nBlockYSize == 0 )
7608 15 : nBlockYSize = 256;
7609 :
7610 28 : if (!TIFFSetField( hTIFF, TIFFTAG_TILEWIDTH, nBlockXSize ) ||
7611 : !TIFFSetField( hTIFF, TIFFTAG_TILELENGTH, nBlockYSize ))
7612 : {
7613 0 : XTIFFClose(hTIFF);
7614 0 : return NULL;
7615 : }
7616 : }
7617 : else
7618 : {
7619 : uint32 nRowsPerStrip;
7620 :
7621 1171 : if( nBlockYSize == 0 )
7622 1162 : nRowsPerStrip = MIN(nYSize, (int)TIFFDefaultStripSize(hTIFF,0));
7623 : else
7624 9 : nRowsPerStrip = nBlockYSize;
7625 :
7626 1171 : TIFFSetField( hTIFF, TIFFTAG_ROWSPERSTRIP, nRowsPerStrip );
7627 : }
7628 :
7629 : /* -------------------------------------------------------------------- */
7630 : /* Set compression related tags. */
7631 : /* -------------------------------------------------------------------- */
7632 1199 : if ( nCompression == COMPRESSION_LZW ||
7633 : nCompression == COMPRESSION_ADOBE_DEFLATE )
7634 27 : TIFFSetField( hTIFF, TIFFTAG_PREDICTOR, nPredictor );
7635 1199 : if (nCompression == COMPRESSION_ADOBE_DEFLATE
7636 : && nZLevel != -1)
7637 0 : TIFFSetField( hTIFF, TIFFTAG_ZIPQUALITY, nZLevel );
7638 1213 : else if( nCompression == COMPRESSION_JPEG
7639 : && nJpegQuality != -1 )
7640 14 : TIFFSetField( hTIFF, TIFFTAG_JPEGQUALITY, nJpegQuality );
7641 1185 : else if( nCompression == COMPRESSION_LZMA && nLZMAPreset != -1)
7642 0 : TIFFSetField( hTIFF, TIFFTAG_LZMAPRESET, nLZMAPreset );
7643 :
7644 : /* -------------------------------------------------------------------- */
7645 : /* If we forced production of a file with photometric=palette, */
7646 : /* we need to push out a default color table. */
7647 : /* -------------------------------------------------------------------- */
7648 1199 : if( bForceColorTable )
7649 : {
7650 : int nColors;
7651 :
7652 3 : if( eType == GDT_Byte )
7653 3 : nColors = 256;
7654 : else
7655 0 : nColors = 65536;
7656 :
7657 : unsigned short *panTRed, *panTGreen, *panTBlue;
7658 :
7659 3 : panTRed = (unsigned short *) CPLMalloc(sizeof(unsigned short)*nColors);
7660 3 : panTGreen = (unsigned short *) CPLMalloc(sizeof(unsigned short)*nColors);
7661 3 : panTBlue = (unsigned short *) CPLMalloc(sizeof(unsigned short)*nColors);
7662 :
7663 771 : for( int iColor = 0; iColor < nColors; iColor++ )
7664 : {
7665 768 : if( eType == GDT_Byte )
7666 : {
7667 768 : panTRed[iColor] = (unsigned short) (257 * iColor);
7668 768 : panTGreen[iColor] = (unsigned short) (257 * iColor);
7669 768 : panTBlue[iColor] = (unsigned short) (257 * iColor);
7670 : }
7671 : else
7672 : {
7673 0 : panTRed[iColor] = (unsigned short) iColor;
7674 0 : panTGreen[iColor] = (unsigned short) iColor;
7675 0 : panTBlue[iColor] = (unsigned short) iColor;
7676 : }
7677 : }
7678 :
7679 : TIFFSetField( hTIFF, TIFFTAG_COLORMAP,
7680 3 : panTRed, panTGreen, panTBlue );
7681 :
7682 3 : CPLFree( panTRed );
7683 3 : CPLFree( panTGreen );
7684 3 : CPLFree( panTBlue );
7685 : }
7686 :
7687 1199 : return( hTIFF );
7688 : }
7689 :
7690 : /************************************************************************/
7691 : /* Create() */
7692 : /* */
7693 : /* Create a new GeoTIFF or TIFF file. */
7694 : /************************************************************************/
7695 :
7696 972 : GDALDataset *GTiffDataset::Create( const char * pszFilename,
7697 : int nXSize, int nYSize, int nBands,
7698 : GDALDataType eType,
7699 : char **papszParmList )
7700 :
7701 : {
7702 : GTiffDataset * poDS;
7703 : TIFF *hTIFF;
7704 :
7705 : /* -------------------------------------------------------------------- */
7706 : /* Create the underlying TIFF file. */
7707 : /* -------------------------------------------------------------------- */
7708 : hTIFF = CreateLL( pszFilename, nXSize, nYSize, nBands,
7709 972 : eType, 0, papszParmList );
7710 :
7711 972 : if( hTIFF == NULL )
7712 2 : return NULL;
7713 :
7714 : /* -------------------------------------------------------------------- */
7715 : /* Create the new GTiffDataset object. */
7716 : /* -------------------------------------------------------------------- */
7717 970 : poDS = new GTiffDataset();
7718 970 : poDS->hTIFF = hTIFF;
7719 970 : poDS->poActiveDS = poDS;
7720 970 : poDS->ppoActiveDSRef = &(poDS->poActiveDS);
7721 :
7722 970 : poDS->nRasterXSize = nXSize;
7723 970 : poDS->nRasterYSize = nYSize;
7724 970 : poDS->eAccess = GA_Update;
7725 970 : poDS->bCrystalized = FALSE;
7726 970 : poDS->nSamplesPerPixel = (uint16) nBands;
7727 1940 : poDS->osFilename = pszFilename;
7728 :
7729 : /* Avoid premature crystalization that will cause directory re-writting */
7730 : /* if GetProjectionRef() or GetGeoTransform() are called on the newly created GeoTIFF */
7731 970 : poDS->bLookedForProjection = TRUE;
7732 :
7733 970 : TIFFGetField( hTIFF, TIFFTAG_SAMPLEFORMAT, &(poDS->nSampleFormat) );
7734 970 : TIFFGetField( hTIFF, TIFFTAG_PLANARCONFIG, &(poDS->nPlanarConfig) );
7735 970 : TIFFGetField( hTIFF, TIFFTAG_PHOTOMETRIC, &(poDS->nPhotometric) );
7736 970 : TIFFGetField( hTIFF, TIFFTAG_BITSPERSAMPLE, &(poDS->nBitsPerSample) );
7737 970 : TIFFGetField( hTIFF, TIFFTAG_COMPRESSION, &(poDS->nCompression) );
7738 :
7739 970 : if( TIFFIsTiled(hTIFF) )
7740 : {
7741 21 : TIFFGetField( hTIFF, TIFFTAG_TILEWIDTH, &(poDS->nBlockXSize) );
7742 21 : TIFFGetField( hTIFF, TIFFTAG_TILELENGTH, &(poDS->nBlockYSize) );
7743 : }
7744 : else
7745 : {
7746 949 : if( !TIFFGetField( hTIFF, TIFFTAG_ROWSPERSTRIP,
7747 : &(poDS->nRowsPerStrip) ) )
7748 0 : poDS->nRowsPerStrip = 1; /* dummy value */
7749 :
7750 949 : poDS->nBlockXSize = nXSize;
7751 949 : poDS->nBlockYSize = MIN((int)poDS->nRowsPerStrip,nYSize);
7752 : }
7753 :
7754 : poDS->nBlocksPerBand =
7755 : DIV_ROUND_UP(nYSize, poDS->nBlockYSize)
7756 970 : * DIV_ROUND_UP(nXSize, poDS->nBlockXSize);
7757 :
7758 970 : if( CSLFetchNameValue( papszParmList, "PROFILE" ) != NULL )
7759 4 : poDS->osProfile = CSLFetchNameValue( papszParmList, "PROFILE" );
7760 :
7761 : /* -------------------------------------------------------------------- */
7762 : /* YCbCr JPEG compressed images should be translated on the fly */
7763 : /* to RGB by libtiff/libjpeg unless specifically requested */
7764 : /* otherwise. */
7765 : /* -------------------------------------------------------------------- */
7766 970 : if( poDS->nCompression == COMPRESSION_JPEG
7767 : && poDS->nPhotometric == PHOTOMETRIC_YCBCR
7768 : && CSLTestBoolean( CPLGetConfigOption("CONVERT_YCBCR_TO_RGB",
7769 : "YES") ) )
7770 : {
7771 : int nColorMode;
7772 :
7773 13 : poDS->SetMetadataItem( "SOURCE_COLOR_SPACE", "YCbCr", "IMAGE_STRUCTURE" );
7774 13 : if ( !TIFFGetField( hTIFF, TIFFTAG_JPEGCOLORMODE, &nColorMode ) ||
7775 : nColorMode != JPEGCOLORMODE_RGB )
7776 13 : TIFFSetField(hTIFF, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
7777 : }
7778 :
7779 : /* -------------------------------------------------------------------- */
7780 : /* Read palette back as a color table if it has one. */
7781 : /* -------------------------------------------------------------------- */
7782 : unsigned short *panRed, *panGreen, *panBlue;
7783 :
7784 970 : if( poDS->nPhotometric == PHOTOMETRIC_PALETTE
7785 : && TIFFGetField( hTIFF, TIFFTAG_COLORMAP,
7786 : &panRed, &panGreen, &panBlue) )
7787 : {
7788 : int nColorCount;
7789 : GDALColorEntry oEntry;
7790 :
7791 3 : poDS->poColorTable = new GDALColorTable();
7792 :
7793 3 : nColorCount = 1 << poDS->nBitsPerSample;
7794 :
7795 771 : for( int iColor = nColorCount - 1; iColor >= 0; iColor-- )
7796 : {
7797 768 : oEntry.c1 = panRed[iColor] / 256;
7798 768 : oEntry.c2 = panGreen[iColor] / 256;
7799 768 : oEntry.c3 = panBlue[iColor] / 256;
7800 768 : oEntry.c4 = 255;
7801 :
7802 768 : poDS->poColorTable->SetColorEntry( iColor, &oEntry );
7803 : }
7804 : }
7805 :
7806 : /* -------------------------------------------------------------------- */
7807 : /* Do we want to ensure all blocks get written out on close to */
7808 : /* avoid sparse files? */
7809 : /* -------------------------------------------------------------------- */
7810 970 : if( !CSLFetchBoolean( papszParmList, "SPARSE_OK", FALSE ) )
7811 952 : poDS->bFillEmptyTiles = TRUE;
7812 :
7813 : /* -------------------------------------------------------------------- */
7814 : /* Preserve creation options for consulting later (for instance */
7815 : /* to decide if a TFW file should be written). */
7816 : /* -------------------------------------------------------------------- */
7817 970 : poDS->papszCreationOptions = CSLDuplicate( papszParmList );
7818 :
7819 970 : poDS->nZLevel = GTiffGetZLevel(papszParmList);
7820 970 : poDS->nLZMAPreset = GTiffGetLZMAPreset(papszParmList);
7821 970 : poDS->nJpegQuality = GTiffGetJpegQuality(papszParmList);
7822 :
7823 : #if !defined(BIGTIFF_SUPPORT)
7824 : /* -------------------------------------------------------------------- */
7825 : /* If we are writing jpeg compression we need to write some */
7826 : /* imagery to force the jpegtables to get created. This is, */
7827 : /* likely only needed with libtiff >= 3.9.3 (#3633) */
7828 : /* -------------------------------------------------------------------- */
7829 : if( poDS->nCompression == COMPRESSION_JPEG
7830 : && strstr(TIFFLIB_VERSION_STR, "Version 3.9") != NULL )
7831 : {
7832 : CPLDebug( "GDAL",
7833 : "Writing zero block to force creation of JPEG tables." );
7834 : if( TIFFIsTiled( hTIFF ) )
7835 : {
7836 : int cc = TIFFTileSize( hTIFF );
7837 : unsigned char *pabyZeros = (unsigned char *) CPLCalloc(cc,1);
7838 : TIFFWriteEncodedTile(hTIFF, 0, pabyZeros, cc);
7839 : CPLFree( pabyZeros );
7840 : }
7841 : else
7842 : {
7843 : int cc = TIFFStripSize( hTIFF );
7844 : unsigned char *pabyZeros = (unsigned char *) CPLCalloc(cc,1);
7845 : TIFFWriteEncodedStrip(hTIFF, 0, pabyZeros, cc);
7846 : CPLFree( pabyZeros );
7847 : }
7848 : poDS->bDontReloadFirstBlock = TRUE;
7849 : }
7850 : #endif
7851 :
7852 : /* -------------------------------------------------------------------- */
7853 : /* Create band information objects. */
7854 : /* -------------------------------------------------------------------- */
7855 : int iBand;
7856 :
7857 133241 : for( iBand = 0; iBand < nBands; iBand++ )
7858 : {
7859 264519 : if( poDS->nBitsPerSample == 8 ||
7860 : poDS->nBitsPerSample == 16 ||
7861 : poDS->nBitsPerSample == 32 ||
7862 : poDS->nBitsPerSample == 64 ||
7863 : poDS->nBitsPerSample == 128)
7864 132248 : poDS->SetBand( iBand+1, new GTiffRasterBand( poDS, iBand+1 ) );
7865 : else
7866 : {
7867 23 : poDS->SetBand( iBand+1, new GTiffOddBitsBand( poDS, iBand+1 ) );
7868 : poDS->GetRasterBand( iBand+1 )->
7869 : SetMetadataItem( "NBITS",
7870 : CPLString().Printf("%d",poDS->nBitsPerSample),
7871 46 : "IMAGE_STRUCTURE" );
7872 : }
7873 : }
7874 :
7875 970 : poDS->oOvManager.Initialize( poDS, pszFilename );
7876 :
7877 970 : return( poDS );
7878 : }
7879 :
7880 : /************************************************************************/
7881 : /* CreateCopy() */
7882 : /************************************************************************/
7883 :
7884 : GDALDataset *
7885 247 : GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
7886 : int bStrict, char ** papszOptions,
7887 : GDALProgressFunc pfnProgress, void * pProgressData )
7888 :
7889 : {
7890 : TIFF *hTIFF;
7891 247 : int nXSize = poSrcDS->GetRasterXSize();
7892 247 : int nYSize = poSrcDS->GetRasterYSize();
7893 247 : int nBands = poSrcDS->GetRasterCount();
7894 : int iBand;
7895 247 : CPLErr eErr = CE_None;
7896 : uint16 nPlanarConfig;
7897 : uint16 nBitsPerSample;
7898 : GDALRasterBand *poPBand;
7899 :
7900 247 : if( poSrcDS->GetRasterCount() == 0 )
7901 : {
7902 : CPLError( CE_Failure, CPLE_AppDefined,
7903 1 : "Unable to export GeoTIFF files with zero bands." );
7904 1 : return NULL;
7905 : }
7906 :
7907 246 : poPBand = poSrcDS->GetRasterBand(1);
7908 246 : GDALDataType eType = poPBand->GetRasterDataType();
7909 :
7910 : /* -------------------------------------------------------------------- */
7911 : /* Check, whether all bands in input dataset has the same type. */
7912 : /* -------------------------------------------------------------------- */
7913 387 : for ( iBand = 2; iBand <= nBands; iBand++ )
7914 : {
7915 141 : if ( eType != poSrcDS->GetRasterBand(iBand)->GetRasterDataType() )
7916 : {
7917 0 : if ( bStrict )
7918 : {
7919 : CPLError( CE_Failure, CPLE_AppDefined,
7920 : "Unable to export GeoTIFF file with different datatypes per\n"
7921 0 : "different bands. All bands should have the same types in TIFF." );
7922 0 : return NULL;
7923 : }
7924 : else
7925 : {
7926 : CPLError( CE_Warning, CPLE_AppDefined,
7927 : "Unable to export GeoTIFF file with different datatypes per\n"
7928 0 : "different bands. All bands should have the same types in TIFF." );
7929 : }
7930 : }
7931 : }
7932 :
7933 246 : if( !pfnProgress( 0.0, NULL, pProgressData ) )
7934 0 : return NULL;
7935 :
7936 : /* -------------------------------------------------------------------- */
7937 : /* Capture the profile. */
7938 : /* -------------------------------------------------------------------- */
7939 : const char *pszProfile;
7940 : int bGeoTIFF;
7941 :
7942 246 : pszProfile = CSLFetchNameValue(papszOptions,"PROFILE");
7943 246 : if( pszProfile == NULL )
7944 237 : pszProfile = "GDALGeoTIFF";
7945 :
7946 246 : if( !EQUAL(pszProfile,"BASELINE")
7947 : && !EQUAL(pszProfile,"GeoTIFF")
7948 : && !EQUAL(pszProfile,"GDALGeoTIFF") )
7949 : {
7950 : CPLError( CE_Failure, CPLE_AppDefined,
7951 : "PROFILE=%s not supported in GTIFF driver.",
7952 0 : pszProfile );
7953 0 : return NULL;
7954 : }
7955 :
7956 246 : if( EQUAL(pszProfile,"BASELINE") )
7957 6 : bGeoTIFF = FALSE;
7958 : else
7959 240 : bGeoTIFF = TRUE;
7960 :
7961 : /* -------------------------------------------------------------------- */
7962 : /* Special handling for NBITS. Copy from band metadata if found. */
7963 : /* -------------------------------------------------------------------- */
7964 246 : char **papszCreateOptions = CSLDuplicate( papszOptions );
7965 :
7966 251 : if( poPBand->GetMetadataItem( "NBITS", "IMAGE_STRUCTURE" ) != NULL
7967 5 : && atoi(poPBand->GetMetadataItem( "NBITS", "IMAGE_STRUCTURE" )) > 0
7968 : && CSLFetchNameValue( papszCreateOptions, "NBITS") == NULL )
7969 : {
7970 : papszCreateOptions =
7971 : CSLSetNameValue( papszCreateOptions, "NBITS",
7972 : poPBand->GetMetadataItem( "NBITS",
7973 3 : "IMAGE_STRUCTURE" ) );
7974 : }
7975 :
7976 401 : if( CSLFetchNameValue( papszOptions, "PIXELTYPE" ) == NULL
7977 : && eType == GDT_Byte
7978 155 : && poPBand->GetMetadataItem( "PIXELTYPE", "IMAGE_STRUCTURE" ) )
7979 : {
7980 : papszCreateOptions =
7981 : CSLSetNameValue( papszCreateOptions, "PIXELTYPE",
7982 : poPBand->GetMetadataItem(
7983 0 : "PIXELTYPE", "IMAGE_STRUCTURE" ) );
7984 : }
7985 :
7986 246 : int nSrcOverviews = poSrcDS->GetRasterBand(1)->GetOverviewCount();
7987 246 : double dfExtraSpaceForOverviews = 0;
7988 246 : if (nSrcOverviews != 0 &&
7989 : CSLFetchBoolean(papszOptions, "COPY_SRC_OVERVIEWS", FALSE))
7990 : {
7991 : int i;
7992 18 : for(i=0;i<nSrcOverviews;i++)
7993 : {
7994 13 : dfExtraSpaceForOverviews += ((double)poSrcDS->GetRasterBand(1)->GetOverview(i)->GetXSize()) *
7995 26 : poSrcDS->GetRasterBand(1)->GetOverview(i)->GetYSize();
7996 : }
7997 5 : dfExtraSpaceForOverviews *= nBands * (GDALGetDataTypeSize(eType) / 8);
7998 : }
7999 :
8000 : /* -------------------------------------------------------------------- */
8001 : /* Should we use optimized way of copying from an input JPEG */
8002 : /* dataset ? */
8003 : /* -------------------------------------------------------------------- */
8004 246 : int bCopyFromJPEG = FALSE;
8005 246 : int bDirectCopyFromJPEG = FALSE;
8006 :
8007 : /* Note: JPEG_DIRECT_COPY is not defined by default, because it is mainly */
8008 : /* usefull for debugging purposes */
8009 : #ifdef JPEG_DIRECT_COPY
8010 : if (CSLFetchBoolean(papszCreateOptions, "JPEG_DIRECT_COPY", FALSE) &&
8011 : GTIFF_CanDirectCopyFromJPEG(poSrcDS, papszCreateOptions))
8012 : {
8013 : CPLDebug("GTiff", "Using special direct copy mode from a JPEG dataset");
8014 :
8015 : bDirectCopyFromJPEG = TRUE;
8016 : }
8017 : #endif
8018 :
8019 : #ifdef HAVE_LIBJPEG
8020 : /* when CreateCopy'ing() from a JPEG dataset, and asking for COMPRESS=JPEG, */
8021 : /* use DCT coefficients (unless other options are incompatible, like strip/tile dimensions, */
8022 : /* specifying JPEG_QUALITY option, incompatible PHOTOMETRIC with the source colorspace, etc...) */
8023 : /* to avoid the lossy steps involved by uncompression/recompression */
8024 246 : if (!bDirectCopyFromJPEG && GTIFF_CanCopyFromJPEG(poSrcDS, papszCreateOptions))
8025 : {
8026 8 : CPLDebug("GTiff", "Using special copy mode from a JPEG dataset");
8027 :
8028 8 : bCopyFromJPEG = TRUE;
8029 : }
8030 : #endif
8031 :
8032 : /* -------------------------------------------------------------------- */
8033 : /* Create the file. */
8034 : /* -------------------------------------------------------------------- */
8035 : hTIFF = CreateLL( pszFilename, nXSize, nYSize, nBands,
8036 246 : eType, dfExtraSpaceForOverviews, papszCreateOptions );
8037 :
8038 246 : CSLDestroy( papszCreateOptions );
8039 :
8040 246 : if( hTIFF == NULL )
8041 17 : return NULL;
8042 :
8043 229 : TIFFGetField( hTIFF, TIFFTAG_PLANARCONFIG, &nPlanarConfig );
8044 229 : TIFFGetField(hTIFF, TIFFTAG_BITSPERSAMPLE, &nBitsPerSample );
8045 :
8046 : /* -------------------------------------------------------------------- */
8047 : /* Are we really producing an RGBA image? If so, set the */
8048 : /* associated alpha information. */
8049 : /* -------------------------------------------------------------------- */
8050 : int bForcePhotometric =
8051 229 : CSLFetchNameValue(papszOptions,"PHOTOMETRIC") != NULL;
8052 :
8053 236 : if( nBands == 4 && !bForcePhotometric
8054 7 : && poSrcDS->GetRasterBand(4)->GetColorInterpretation()==GCI_AlphaBand)
8055 : {
8056 : uint16 v[1];
8057 :
8058 : v[0] = GTiffGetAlphaValue(CSLFetchNameValue(papszOptions, "ALPHA"),
8059 5 : DEFAULT_ALPHA_TYPE);
8060 :
8061 5 : TIFFSetField(hTIFF, TIFFTAG_EXTRASAMPLES, 1, v);
8062 5 : TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB );
8063 : }
8064 :
8065 : /* -------------------------------------------------------------------- */
8066 : /* If the output is jpeg compressed, and the input is RGB make */
8067 : /* sure we note that. */
8068 : /* -------------------------------------------------------------------- */
8069 : uint16 nCompression;
8070 :
8071 229 : if( !TIFFGetField( hTIFF, TIFFTAG_COMPRESSION, &(nCompression) ) )
8072 0 : nCompression = COMPRESSION_NONE;
8073 :
8074 229 : if( nCompression == COMPRESSION_JPEG )
8075 : {
8076 33 : if( nBands >= 3
8077 14 : && (poSrcDS->GetRasterBand(1)->GetColorInterpretation()
8078 : == GCI_YCbCr_YBand)
8079 0 : && (poSrcDS->GetRasterBand(2)->GetColorInterpretation()
8080 : == GCI_YCbCr_CbBand)
8081 0 : && (poSrcDS->GetRasterBand(3)->GetColorInterpretation()
8082 : == GCI_YCbCr_CrBand) )
8083 : {
8084 : /* do nothing ... */
8085 : }
8086 : else
8087 : {
8088 : /* we assume RGB if it isn't explicitly YCbCr */
8089 19 : CPLDebug( "GTiff", "Setting JPEGCOLORMODE_RGB" );
8090 19 : TIFFSetField( hTIFF, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB );
8091 : }
8092 : }
8093 :
8094 : /* -------------------------------------------------------------------- */
8095 : /* Does the source image consist of one band, with a palette? */
8096 : /* If so, copy over. */
8097 : /* -------------------------------------------------------------------- */
8098 229 : if( (nBands == 1 || nBands == 2) && poSrcDS->GetRasterBand(1)->GetColorTable() != NULL
8099 : && eType == GDT_Byte )
8100 : {
8101 : unsigned short anTRed[256], anTGreen[256], anTBlue[256];
8102 : GDALColorTable *poCT;
8103 :
8104 4 : poCT = poSrcDS->GetRasterBand(1)->GetColorTable();
8105 :
8106 1028 : for( int iColor = 0; iColor < 256; iColor++ )
8107 : {
8108 1024 : if( iColor < poCT->GetColorEntryCount() )
8109 : {
8110 : GDALColorEntry sRGB;
8111 :
8112 477 : poCT->GetColorEntryAsRGB( iColor, &sRGB );
8113 :
8114 477 : anTRed[iColor] = (unsigned short) (257 * sRGB.c1);
8115 477 : anTGreen[iColor] = (unsigned short) (257 * sRGB.c2);
8116 477 : anTBlue[iColor] = (unsigned short) (257 * sRGB.c3);
8117 : }
8118 : else
8119 : {
8120 547 : anTRed[iColor] = anTGreen[iColor] = anTBlue[iColor] = 0;
8121 : }
8122 : }
8123 :
8124 4 : if( !bForcePhotometric )
8125 4 : TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE );
8126 4 : TIFFSetField( hTIFF, TIFFTAG_COLORMAP, anTRed, anTGreen, anTBlue );
8127 : }
8128 394 : else if( (nBands == 1 || nBands == 2)
8129 169 : && poSrcDS->GetRasterBand(1)->GetColorTable() != NULL
8130 : && eType == GDT_UInt16 )
8131 : {
8132 : unsigned short *panTRed, *panTGreen, *panTBlue;
8133 : GDALColorTable *poCT;
8134 :
8135 1 : panTRed = (unsigned short *) CPLMalloc(65536*sizeof(unsigned short));
8136 1 : panTGreen = (unsigned short *) CPLMalloc(65536*sizeof(unsigned short));
8137 1 : panTBlue = (unsigned short *) CPLMalloc(65536*sizeof(unsigned short));
8138 :
8139 1 : poCT = poSrcDS->GetRasterBand(1)->GetColorTable();
8140 :
8141 65537 : for( int iColor = 0; iColor < 65536; iColor++ )
8142 : {
8143 65536 : if( iColor < poCT->GetColorEntryCount() )
8144 : {
8145 : GDALColorEntry sRGB;
8146 :
8147 65536 : poCT->GetColorEntryAsRGB( iColor, &sRGB );
8148 :
8149 65536 : panTRed[iColor] = (unsigned short) (256 * sRGB.c1);
8150 65536 : panTGreen[iColor] = (unsigned short) (256 * sRGB.c2);
8151 65536 : panTBlue[iColor] = (unsigned short) (256 * sRGB.c3);
8152 : }
8153 : else
8154 : {
8155 0 : panTRed[iColor] = panTGreen[iColor] = panTBlue[iColor] = 0;
8156 : }
8157 : }
8158 :
8159 1 : if( !bForcePhotometric )
8160 1 : TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE );
8161 1 : TIFFSetField( hTIFF, TIFFTAG_COLORMAP, panTRed, panTGreen, panTBlue );
8162 :
8163 1 : CPLFree( panTRed );
8164 1 : CPLFree( panTGreen );
8165 1 : CPLFree( panTBlue );
8166 : }
8167 224 : else if( poSrcDS->GetRasterBand(1)->GetColorTable() != NULL )
8168 : CPLError( CE_Warning, CPLE_AppDefined,
8169 : "Unable to export color table to GeoTIFF file. Color tables\n"
8170 0 : "can only be written to 1 band or 2 bands Byte or UInt16 GeoTIFF files." );
8171 :
8172 235 : if( nBands == 2
8173 6 : && poSrcDS->GetRasterBand(1)->GetColorTable() != NULL
8174 : && (eType == GDT_Byte || eType == GDT_UInt16) )
8175 : {
8176 1 : uint16 v[1] = { EXTRASAMPLE_UNASSALPHA };
8177 :
8178 1 : TIFFSetField(hTIFF, TIFFTAG_EXTRASAMPLES, 1, v );
8179 : }
8180 :
8181 : /* -------------------------------------------------------------------- */
8182 : /* Transfer some TIFF specific metadata, if available. */
8183 : /* The return value will tell us if we need to try again later with*/
8184 : /* PAM because the profile doesn't allow to write some metadata */
8185 : /* as TIFF tag */
8186 : /* -------------------------------------------------------------------- */
8187 : int bHasWrittenMDInGeotiffTAG =
8188 : GTiffDataset::WriteMetadata( poSrcDS, hTIFF, FALSE, pszProfile,
8189 229 : pszFilename, papszOptions );
8190 :
8191 : /* -------------------------------------------------------------------- */
8192 : /* Write NoData value, if exist. */
8193 : /* -------------------------------------------------------------------- */
8194 229 : if( EQUAL(pszProfile,"GDALGeoTIFF") )
8195 : {
8196 : int bSuccess;
8197 : double dfNoData;
8198 :
8199 221 : dfNoData = poSrcDS->GetRasterBand(1)->GetNoDataValue( &bSuccess );
8200 221 : if ( bSuccess )
8201 29 : GTiffDataset::WriteNoDataValue( hTIFF, dfNoData );
8202 : }
8203 :
8204 : /* -------------------------------------------------------------------- */
8205 : /* Are we addressing PixelIsPoint mode? */
8206 : /* -------------------------------------------------------------------- */
8207 229 : bool bPixelIsPoint = false;
8208 229 : int bPointGeoIgnore = FALSE;
8209 :
8210 347 : if( poSrcDS->GetMetadataItem( GDALMD_AREA_OR_POINT )
8211 118 : && EQUAL(poSrcDS->GetMetadataItem(GDALMD_AREA_OR_POINT),
8212 : GDALMD_AOP_POINT) )
8213 : {
8214 6 : bPixelIsPoint = true;
8215 : bPointGeoIgnore =
8216 : CSLTestBoolean( CPLGetConfigOption("GTIFF_POINT_GEO_IGNORE",
8217 6 : "FALSE") );
8218 : }
8219 :
8220 : /* -------------------------------------------------------------------- */
8221 : /* Write affine transform if it is meaningful. */
8222 : /* -------------------------------------------------------------------- */
8223 229 : const char *pszProjection = NULL;
8224 : double adfGeoTransform[6];
8225 :
8226 406 : if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None
8227 161 : && (adfGeoTransform[0] != 0.0 || adfGeoTransform[1] != 1.0
8228 16 : || adfGeoTransform[2] != 0.0 || adfGeoTransform[3] != 0.0
8229 0 : || adfGeoTransform[4] != 0.0 || adfGeoTransform[5] != 1.0 ))
8230 : {
8231 153 : if( bGeoTIFF )
8232 : {
8233 443 : if( adfGeoTransform[2] == 0.0 && adfGeoTransform[4] == 0.0
8234 147 : && adfGeoTransform[5] < 0.0 )
8235 : {
8236 :
8237 : double adfPixelScale[3], adfTiePoints[6];
8238 :
8239 147 : adfPixelScale[0] = adfGeoTransform[1];
8240 147 : adfPixelScale[1] = fabs(adfGeoTransform[5]);
8241 147 : adfPixelScale[2] = 0.0;
8242 :
8243 147 : TIFFSetField( hTIFF, TIFFTAG_GEOPIXELSCALE, 3, adfPixelScale );
8244 :
8245 147 : adfTiePoints[0] = 0.0;
8246 147 : adfTiePoints[1] = 0.0;
8247 147 : adfTiePoints[2] = 0.0;
8248 147 : adfTiePoints[3] = adfGeoTransform[0];
8249 147 : adfTiePoints[4] = adfGeoTransform[3];
8250 147 : adfTiePoints[5] = 0.0;
8251 :
8252 147 : if( bPixelIsPoint && !bPointGeoIgnore )
8253 : {
8254 4 : adfTiePoints[3] += adfGeoTransform[1] * 0.5 + adfGeoTransform[2] * 0.5;
8255 4 : adfTiePoints[4] += adfGeoTransform[4] * 0.5 + adfGeoTransform[5] * 0.5;
8256 : }
8257 :
8258 147 : TIFFSetField( hTIFF, TIFFTAG_GEOTIEPOINTS, 6, adfTiePoints );
8259 : }
8260 : else
8261 : {
8262 : double adfMatrix[16];
8263 :
8264 2 : memset(adfMatrix,0,sizeof(double) * 16);
8265 :
8266 2 : adfMatrix[0] = adfGeoTransform[1];
8267 2 : adfMatrix[1] = adfGeoTransform[2];
8268 2 : adfMatrix[3] = adfGeoTransform[0];
8269 2 : adfMatrix[4] = adfGeoTransform[4];
8270 2 : adfMatrix[5] = adfGeoTransform[5];
8271 2 : adfMatrix[7] = adfGeoTransform[3];
8272 2 : adfMatrix[15] = 1.0;
8273 :
8274 2 : if( bPixelIsPoint && !bPointGeoIgnore )
8275 : {
8276 0 : adfMatrix[3] += adfGeoTransform[1] * 0.5 + adfGeoTransform[2] * 0.5;
8277 0 : adfMatrix[7] += adfGeoTransform[4] * 0.5 + adfGeoTransform[5] * 0.5;
8278 : }
8279 :
8280 2 : TIFFSetField( hTIFF, TIFFTAG_GEOTRANSMATRIX, 16, adfMatrix );
8281 : }
8282 :
8283 149 : pszProjection = poSrcDS->GetProjectionRef();
8284 : }
8285 :
8286 : /* -------------------------------------------------------------------- */
8287 : /* Do we need a TFW file? */
8288 : /* -------------------------------------------------------------------- */
8289 153 : if( CSLFetchBoolean( papszOptions, "TFW", FALSE ) )
8290 1 : GDALWriteWorldFile( pszFilename, "tfw", adfGeoTransform );
8291 152 : else if( CSLFetchBoolean( papszOptions, "WORLDFILE", FALSE ) )
8292 1 : GDALWriteWorldFile( pszFilename, "wld", adfGeoTransform );
8293 : }
8294 :
8295 : /* -------------------------------------------------------------------- */
8296 : /* Otherwise write tiepoints if they are available. */
8297 : /* -------------------------------------------------------------------- */
8298 76 : else if( poSrcDS->GetGCPCount() > 0 && bGeoTIFF )
8299 : {
8300 3 : const GDAL_GCP *pasGCPs = poSrcDS->GetGCPs();
8301 : double *padfTiePoints;
8302 :
8303 : padfTiePoints = (double *)
8304 3 : CPLMalloc(6*sizeof(double)*poSrcDS->GetGCPCount());
8305 :
8306 15 : for( int iGCP = 0; iGCP < poSrcDS->GetGCPCount(); iGCP++ )
8307 : {
8308 :
8309 12 : padfTiePoints[iGCP*6+0] = pasGCPs[iGCP].dfGCPPixel;
8310 12 : padfTiePoints[iGCP*6+1] = pasGCPs[iGCP].dfGCPLine;
8311 12 : padfTiePoints[iGCP*6+2] = 0;
8312 12 : padfTiePoints[iGCP*6+3] = pasGCPs[iGCP].dfGCPX;
8313 12 : padfTiePoints[iGCP*6+4] = pasGCPs[iGCP].dfGCPY;
8314 12 : padfTiePoints[iGCP*6+5] = pasGCPs[iGCP].dfGCPZ;
8315 :
8316 12 : if( bPixelIsPoint && !bPointGeoIgnore )
8317 : {
8318 0 : padfTiePoints[iGCP*6+0] += 0.5;
8319 0 : padfTiePoints[iGCP*6+1] += 0.5;
8320 : }
8321 : }
8322 :
8323 : TIFFSetField( hTIFF, TIFFTAG_GEOTIEPOINTS,
8324 3 : 6*poSrcDS->GetGCPCount(), padfTiePoints );
8325 3 : CPLFree( padfTiePoints );
8326 :
8327 3 : pszProjection = poSrcDS->GetGCPProjection();
8328 :
8329 3 : if( CSLFetchBoolean( papszOptions, "TFW", FALSE )
8330 : || CSLFetchBoolean( papszOptions, "WORLDFILE", FALSE ) )
8331 : {
8332 : CPLError(CE_Warning, CPLE_AppDefined,
8333 0 : "TFW=ON or WORLDFILE=ON creation options are ignored when GCPs are available");
8334 : }
8335 : }
8336 :
8337 : else
8338 73 : pszProjection = poSrcDS->GetProjectionRef();
8339 :
8340 : /* -------------------------------------------------------------------- */
8341 : /* Write the projection information, if possible. */
8342 : /* -------------------------------------------------------------------- */
8343 229 : if( pszProjection != NULL && strlen(pszProjection) > 0 && bGeoTIFF )
8344 : {
8345 : GTIF *psGTIF;
8346 :
8347 150 : psGTIF = GTIFNew( hTIFF );
8348 150 : GTIFSetFromOGISDefn( psGTIF, pszProjection );
8349 :
8350 265 : if( poSrcDS->GetMetadataItem( GDALMD_AREA_OR_POINT )
8351 115 : && EQUAL(poSrcDS->GetMetadataItem(GDALMD_AREA_OR_POINT),
8352 : GDALMD_AOP_POINT) )
8353 : {
8354 : GTIFKeySet(psGTIF, GTRasterTypeGeoKey, TYPE_SHORT, 1,
8355 6 : RasterPixelIsPoint);
8356 : }
8357 :
8358 150 : GTIFWriteKeys( psGTIF );
8359 150 : GTIFFree( psGTIF );
8360 : }
8361 :
8362 229 : int bDontReloadFirstBlock = FALSE;
8363 :
8364 : #ifdef HAVE_LIBJPEG
8365 229 : if (bCopyFromJPEG)
8366 : {
8367 : GTIFF_CopyFromJPEG_WriteAdditionalTags(hTIFF,
8368 8 : poSrcDS);
8369 : }
8370 : #else
8371 : if (0)
8372 : {
8373 : }
8374 : #endif
8375 :
8376 : #if !defined(BIGTIFF_SUPPORT)
8377 : /* -------------------------------------------------------------------- */
8378 : /* If we are writing jpeg compression we need to write some */
8379 : /* imagery to force the jpegtables to get created. This is, */
8380 : /* likely only needed with libtiff >= 3.9.3 (#3633) */
8381 : /* -------------------------------------------------------------------- */
8382 : else if( nCompression == COMPRESSION_JPEG
8383 : && strstr(TIFFLIB_VERSION_STR, "Version 3.9") != NULL )
8384 : {
8385 : CPLDebug( "GDAL",
8386 : "Writing zero block to force creation of JPEG tables." );
8387 : if( TIFFIsTiled( hTIFF ) )
8388 : {
8389 : int cc = TIFFTileSize( hTIFF );
8390 : unsigned char *pabyZeros = (unsigned char *) CPLCalloc(cc,1);
8391 : TIFFWriteEncodedTile(hTIFF, 0, pabyZeros, cc);
8392 : CPLFree( pabyZeros );
8393 : }
8394 : else
8395 : {
8396 : int cc = TIFFStripSize( hTIFF );
8397 : unsigned char *pabyZeros = (unsigned char *) CPLCalloc(cc,1);
8398 : TIFFWriteEncodedStrip(hTIFF, 0, pabyZeros, cc);
8399 : CPLFree( pabyZeros );
8400 : }
8401 : bDontReloadFirstBlock = TRUE;
8402 : }
8403 : #endif
8404 :
8405 : /* -------------------------------------------------------------------- */
8406 : /* Cleanup */
8407 : /* -------------------------------------------------------------------- */
8408 :
8409 229 : TIFFWriteCheck( hTIFF, TIFFIsTiled(hTIFF), "GTiffCreateCopy()");
8410 229 : TIFFWriteDirectory( hTIFF );
8411 229 : TIFFFlush( hTIFF );
8412 229 : XTIFFClose( hTIFF );
8413 229 : hTIFF = NULL;
8414 :
8415 229 : if( eErr != CE_None )
8416 : {
8417 0 : VSIUnlink( pszFilename );
8418 0 : return NULL;
8419 : }
8420 :
8421 : /* -------------------------------------------------------------------- */
8422 : /* Re-open as a dataset and copy over missing metadata using */
8423 : /* PAM facilities. */
8424 : /* -------------------------------------------------------------------- */
8425 : GTiffDataset *poDS;
8426 229 : CPLString osFileName("GTIFF_RAW:");
8427 :
8428 229 : osFileName += pszFilename;
8429 :
8430 229 : poDS = (GTiffDataset *) GDALOpen( osFileName, GA_Update );
8431 229 : if( poDS == NULL )
8432 0 : poDS = (GTiffDataset *) GDALOpen( osFileName, GA_ReadOnly );
8433 :
8434 229 : if ( poDS == NULL )
8435 : {
8436 0 : VSIUnlink( pszFilename );
8437 0 : return NULL;
8438 : }
8439 :
8440 229 : poDS->osProfile = pszProfile;
8441 229 : poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT & ~GCIF_MASK );
8442 229 : poDS->papszCreationOptions = CSLDuplicate( papszOptions );
8443 229 : poDS->bDontReloadFirstBlock = bDontReloadFirstBlock;
8444 :
8445 : /* -------------------------------------------------------------------- */
8446 : /* CloneInfo() doesn't merge metadata, it just replaces it totally */
8447 : /* So we have to merge it */
8448 : /* -------------------------------------------------------------------- */
8449 :
8450 229 : char **papszSRC_MD = poSrcDS->GetMetadata();
8451 229 : char **papszDST_MD = CSLDuplicate(poDS->GetMetadata());
8452 :
8453 229 : papszDST_MD = CSLMerge( papszDST_MD, papszSRC_MD );
8454 :
8455 229 : poDS->SetMetadata( papszDST_MD );
8456 229 : CSLDestroy( papszDST_MD );
8457 :
8458 : /* Depending on the PHOTOMETRIC tag, the TIFF file may not have */
8459 : /* the same band count as the source. Will fail later in GDALDatasetCopyWholeRaster anyway... */
8460 589 : for( int nBand = 1;
8461 : nBand <= MIN(poDS->GetRasterCount(), poSrcDS->GetRasterCount()) ;
8462 : nBand++ )
8463 : {
8464 360 : GDALRasterBand* poSrcBand = poSrcDS->GetRasterBand(nBand);
8465 360 : GDALRasterBand* poDstBand = poDS->GetRasterBand(nBand);
8466 360 : char **papszSRC_MD = poSrcBand->GetMetadata();
8467 360 : char **papszDST_MD = CSLDuplicate(poDstBand->GetMetadata());
8468 :
8469 360 : papszDST_MD = CSLMerge( papszDST_MD, papszSRC_MD );
8470 :
8471 360 : poDstBand->SetMetadata( papszDST_MD );
8472 360 : CSLDestroy( papszDST_MD );
8473 :
8474 : char** papszCatNames;
8475 360 : papszCatNames = poSrcBand->GetCategoryNames();
8476 360 : if (NULL != papszCatNames)
8477 0 : poDstBand->SetCategoryNames( papszCatNames );
8478 : }
8479 :
8480 229 : hTIFF = (TIFF*) poDS->GetInternalHandle(NULL);
8481 :
8482 : /* -------------------------------------------------------------------- */
8483 : /* Handle forcing xml:ESRI data to be written to PAM. */
8484 : /* -------------------------------------------------------------------- */
8485 229 : if( CSLTestBoolean(CPLGetConfigOption( "ESRI_XML_PAM", "NO" )) )
8486 : {
8487 1 : char **papszESRIMD = poSrcDS->GetMetadata("xml:ESRI");
8488 1 : if( papszESRIMD )
8489 : {
8490 1 : poDS->SetMetadata( papszESRIMD, "xml:ESRI");
8491 : }
8492 : }
8493 :
8494 : /* -------------------------------------------------------------------- */
8495 : /* Second chance : now that we have a PAM dataset, it is possible */
8496 : /* to write metadata that we couldn't be writen as TIFF tag */
8497 : /* -------------------------------------------------------------------- */
8498 229 : if (!bHasWrittenMDInGeotiffTAG)
8499 : GTiffDataset::WriteMetadata( poDS, hTIFF, TRUE, pszProfile,
8500 4 : pszFilename, papszOptions, TRUE /* don't write RPC and IMD file again */);
8501 :
8502 : /* To avoid unnecessary directory rewriting */
8503 229 : poDS->bMetadataChanged = FALSE;
8504 229 : poDS->bGeoTIFFInfoChanged = FALSE;
8505 :
8506 : /* We must re-set the compression level at this point, since it has */
8507 : /* been lost a few lines above when closing the newly create TIFF file */
8508 : /* The TIFFTAG_ZIPQUALITY & TIFFTAG_JPEGQUALITY are not store in the TIFF file. */
8509 : /* They are just TIFF session parameters */
8510 :
8511 229 : poDS->nZLevel = GTiffGetZLevel(papszOptions);
8512 229 : poDS->nLZMAPreset = GTiffGetLZMAPreset(papszOptions);
8513 229 : poDS->nJpegQuality = GTiffGetJpegQuality(papszOptions);
8514 :
8515 229 : if (nCompression == COMPRESSION_ADOBE_DEFLATE)
8516 : {
8517 4 : if (poDS->nZLevel != -1)
8518 : {
8519 0 : TIFFSetField( hTIFF, TIFFTAG_ZIPQUALITY, poDS->nZLevel );
8520 : }
8521 : }
8522 225 : else if( nCompression == COMPRESSION_JPEG)
8523 : {
8524 19 : if (poDS->nJpegQuality != -1)
8525 : {
8526 3 : TIFFSetField( hTIFF, TIFFTAG_JPEGQUALITY, poDS->nJpegQuality );
8527 : }
8528 : }
8529 206 : else if( nCompression == COMPRESSION_LZMA)
8530 : {
8531 0 : if (poDS->nLZMAPreset != -1)
8532 : {
8533 0 : TIFFSetField( hTIFF, TIFFTAG_LZMAPRESET, poDS->nLZMAPreset );
8534 : }
8535 : }
8536 :
8537 : /* Precreate (internal) mask, so that the IBuildOverviews() below */
8538 : /* has a chance to create also the overviews of the mask */
8539 229 : int nMaskFlags = poSrcDS->GetRasterBand(1)->GetMaskFlags();
8540 229 : if( eErr == CE_None
8541 : && !(nMaskFlags & (GMF_ALL_VALID|GMF_ALPHA|GMF_NODATA) )
8542 : && (nMaskFlags & GMF_PER_DATASET) )
8543 : {
8544 3 : eErr = poDS->CreateMaskBand( nMaskFlags );
8545 : }
8546 :
8547 : /* -------------------------------------------------------------------- */
8548 : /* Create and then copy existing overviews if requested */
8549 : /* We do it such that all the IFDs are at the beginning of the file, */
8550 : /* and that the imagery data for the smallest overview is written */
8551 : /* first, that way the file is more usable when embedded in a */
8552 : /* compressed stream. */
8553 : /* -------------------------------------------------------------------- */
8554 :
8555 : /* For scaled progress due to overview copying */
8556 229 : double dfTotalPixels = ((double)nXSize) * nYSize;
8557 229 : double dfCurPixels = 0;
8558 :
8559 229 : if (eErr == CE_None &&
8560 : nSrcOverviews != 0 &&
8561 : CSLFetchBoolean(papszOptions, "COPY_SRC_OVERVIEWS", FALSE))
8562 : {
8563 5 : eErr = poDS->CreateOverviewsFromSrcOverviews(poSrcDS);
8564 :
8565 5 : if (poDS->nOverviewCount != nSrcOverviews)
8566 : {
8567 : CPLError(CE_Failure, CPLE_AppDefined,
8568 : "Did only manage to instanciate %d overview levels, whereas source contains %d",
8569 0 : poDS->nOverviewCount, nSrcOverviews);
8570 0 : eErr = CE_Failure;
8571 : }
8572 :
8573 : int i;
8574 18 : for(i=0;i<nSrcOverviews;i++)
8575 : {
8576 13 : GDALRasterBand* poOvrBand = poSrcDS->GetRasterBand(1)->GetOverview(i);
8577 : dfTotalPixels += ((double)poOvrBand->GetXSize()) *
8578 13 : poOvrBand->GetYSize();
8579 : }
8580 :
8581 5 : char* papszCopyWholeRasterOptions[2] = { NULL, NULL };
8582 5 : if (nCompression != COMPRESSION_NONE)
8583 0 : papszCopyWholeRasterOptions[0] = (char*) "COMPRESSED=YES";
8584 : /* Now copy the imagery */
8585 17 : for(i=0;eErr == CE_None && i<nSrcOverviews;i++)
8586 : {
8587 : /* Begin with the smallest overview */
8588 12 : int iOvrLevel = nSrcOverviews-1-i;
8589 :
8590 : /* Create a fake dataset with the source overview level so that */
8591 : /* GDALDatasetCopyWholeRaster can cope with it */
8592 12 : GDALDataset* poSrcOvrDS = new GDALOverviewDS(poSrcDS, iOvrLevel);
8593 :
8594 : GDALRasterBand* poOvrBand =
8595 24 : poSrcDS->GetRasterBand(1)->GetOverview(iOvrLevel);
8596 : double dfNextCurPixels = dfCurPixels +
8597 12 : ((double)poOvrBand->GetXSize()) * poOvrBand->GetYSize();
8598 :
8599 : void* pScaledData = GDALCreateScaledProgress( dfCurPixels / dfTotalPixels,
8600 : dfNextCurPixels / dfTotalPixels,
8601 12 : pfnProgress, pProgressData);
8602 :
8603 : eErr = GDALDatasetCopyWholeRaster( (GDALDatasetH) poSrcOvrDS,
8604 12 : (GDALDatasetH) poDS->papoOverviewDS[iOvrLevel],
8605 : papszCopyWholeRasterOptions,
8606 24 : GDALScaledProgress, pScaledData );
8607 :
8608 12 : dfCurPixels = dfNextCurPixels;
8609 12 : GDALDestroyScaledProgress(pScaledData);
8610 :
8611 12 : delete poSrcOvrDS;
8612 12 : poDS->papoOverviewDS[iOvrLevel]->FlushCache();
8613 :
8614 : /* Copy mask of the overview */
8615 12 : if (eErr == CE_None && poDS->poMaskDS != NULL)
8616 : {
8617 2 : eErr = GDALRasterBandCopyWholeRaster( poOvrBand->GetMaskBand(),
8618 2 : poDS->papoOverviewDS[iOvrLevel]->poMaskDS->GetRasterBand(1),
8619 : papszCopyWholeRasterOptions,
8620 4 : GDALDummyProgress, NULL);
8621 2 : poDS->papoOverviewDS[iOvrLevel]->poMaskDS->FlushCache();
8622 : }
8623 : }
8624 : }
8625 :
8626 : /* -------------------------------------------------------------------- */
8627 : /* Copy actual imagery. */
8628 : /* -------------------------------------------------------------------- */
8629 : void* pScaledData = GDALCreateScaledProgress( dfCurPixels / dfTotalPixels,
8630 : 1.0,
8631 229 : pfnProgress, pProgressData);
8632 :
8633 229 : int bTryCopy = TRUE;
8634 :
8635 : #ifdef HAVE_LIBJPEG
8636 229 : if (bCopyFromJPEG)
8637 : {
8638 : eErr = GTIFF_CopyFromJPEG(poDS, poSrcDS,
8639 : pfnProgress, pProgressData,
8640 8 : bTryCopy);
8641 :
8642 : /* In case of failure in the decompression step, try normal copy */
8643 8 : if (bTryCopy)
8644 0 : eErr = CE_None;
8645 : }
8646 : #endif
8647 :
8648 : #ifdef JPEG_DIRECT_COPY
8649 : if (bDirectCopyFromJPEG)
8650 : {
8651 : eErr = GTIFF_DirectCopyFromJPEG(poDS, poSrcDS,
8652 : pfnProgress, pProgressData,
8653 : bTryCopy);
8654 :
8655 : /* In case of failure in the reading step, try normal copy */
8656 : if (bTryCopy)
8657 : eErr = CE_None;
8658 : }
8659 : #endif
8660 :
8661 232 : if (bTryCopy && (poDS->bTreatAsSplit || poDS->bTreatAsSplitBitmap))
8662 : {
8663 : /* For split bands, we use TIFFWriteScanline() interface */
8664 3 : CPLAssert(poDS->nBitsPerSample == 8 || poDS->nBitsPerSample == 1);
8665 :
8666 5 : if (poDS->nPlanarConfig == PLANARCONFIG_CONTIG && poDS->nBands > 1)
8667 : {
8668 : int j;
8669 2 : GByte* pabyScanline = (GByte *) CPLMalloc(TIFFScanlineSize(hTIFF));
8670 7050 : for(j=0;j<nYSize && eErr == CE_None;j++)
8671 : {
8672 : eErr = poSrcDS->RasterIO(GF_Read, 0, j, nXSize, 1,
8673 : pabyScanline, nXSize, 1,
8674 7048 : GDT_Byte, nBands, NULL, poDS->nBands, 0, 1);
8675 7048 : if (eErr == CE_None &&
8676 : TIFFWriteScanline( hTIFF, pabyScanline, j, 0) == -1)
8677 : {
8678 : CPLError( CE_Failure, CPLE_AppDefined,
8679 0 : "TIFFWriteScanline() failed." );
8680 0 : eErr = CE_Failure;
8681 : }
8682 7048 : if( !GDALScaledProgress( (j+1) * 1.0 / nYSize, NULL, pScaledData ) )
8683 0 : eErr = CE_Failure;
8684 : }
8685 2 : CPLFree(pabyScanline);
8686 : }
8687 : else
8688 : {
8689 : int iBand, j;
8690 1 : GByte* pabyScanline = (GByte *) CPLMalloc(TIFFScanlineSize(hTIFF));
8691 1 : eErr = CE_None;
8692 4 : for(iBand=1;iBand<=nBands && eErr == CE_None;iBand++)
8693 : {
8694 15003 : for(j=0;j<nYSize && eErr == CE_None;j++)
8695 : {
8696 : eErr = poSrcDS->GetRasterBand(iBand)->RasterIO(
8697 : GF_Read, 0, j, nXSize, 1,
8698 : pabyScanline, nXSize, 1,
8699 15000 : GDT_Byte, 0, 0);
8700 15000 : if (poDS->bTreatAsSplitBitmap)
8701 : {
8702 0 : for(int i=0;i<nXSize;i++)
8703 : {
8704 0 : GByte byVal = pabyScanline[i];
8705 0 : if ((i & 0x7) == 0)
8706 0 : pabyScanline[i >> 3] = 0;
8707 0 : if (byVal)
8708 0 : pabyScanline[i >> 3] |= (0x80 >> (i & 0x7));
8709 : }
8710 : }
8711 15000 : if (eErr == CE_None &&
8712 : TIFFWriteScanline( hTIFF, pabyScanline, j, (uint16) (iBand-1)) == -1)
8713 : {
8714 : CPLError( CE_Failure, CPLE_AppDefined,
8715 0 : "TIFFWriteScanline() failed." );
8716 0 : eErr = CE_Failure;
8717 : }
8718 15000 : if( !GDALScaledProgress( (j+1 + (iBand - 1) * nYSize) * 1.0 /
8719 : (nBands * nYSize), NULL, pScaledData ) )
8720 0 : eErr = CE_Failure;
8721 : }
8722 : }
8723 1 : CPLFree(pabyScanline);
8724 : }
8725 :
8726 : /* Necessary to be able to read the file without re-opening */
8727 : #if defined(HAVE_TIFFGETSIZEPROC)
8728 3 : TIFFSizeProc pfnSizeProc = TIFFGetSizeProc( hTIFF );
8729 :
8730 3 : TIFFFlushData( hTIFF );
8731 :
8732 3 : toff_t nNewDirOffset = pfnSizeProc( TIFFClientdata( hTIFF ) );
8733 3 : if( (nNewDirOffset % 2) == 1 )
8734 3 : nNewDirOffset++;
8735 : #endif
8736 :
8737 3 : TIFFFlush( hTIFF );
8738 :
8739 : #if defined(HAVE_TIFFGETSIZEPROC)
8740 3 : if( poDS->nDirOffset != TIFFCurrentDirOffset( hTIFF ) )
8741 : {
8742 1 : poDS->nDirOffset = nNewDirOffset;
8743 1 : CPLDebug( "GTiff", "directory moved during flush." );
8744 : }
8745 : #endif
8746 : }
8747 226 : else if (bTryCopy && eErr == CE_None)
8748 : {
8749 217 : char* papszCopyWholeRasterOptions[2] = { NULL, NULL };
8750 217 : if (nCompression != COMPRESSION_NONE)
8751 19 : papszCopyWholeRasterOptions[0] = (char*) "COMPRESSED=YES";
8752 : eErr = GDALDatasetCopyWholeRaster( (GDALDatasetH) poSrcDS,
8753 : (GDALDatasetH) poDS,
8754 : papszCopyWholeRasterOptions,
8755 217 : GDALScaledProgress, pScaledData );
8756 : }
8757 :
8758 229 : GDALDestroyScaledProgress(pScaledData);
8759 :
8760 229 : if (eErr == CE_None)
8761 : {
8762 227 : if (poDS->poMaskDS)
8763 : {
8764 3 : const char* papszOptions[2] = { "COMPRESSED=YES", NULL };
8765 : eErr = GDALRasterBandCopyWholeRaster(
8766 3 : poSrcDS->GetRasterBand(1)->GetMaskBand(),
8767 3 : poDS->GetRasterBand(1)->GetMaskBand(),
8768 : (char**)papszOptions,
8769 9 : GDALDummyProgress, NULL);
8770 : }
8771 : else
8772 224 : eErr = GDALDriver::DefaultCopyMasks( poSrcDS, poDS, bStrict );
8773 : }
8774 :
8775 229 : if( eErr == CE_Failure )
8776 : {
8777 2 : delete poDS;
8778 2 : poDS = NULL;
8779 :
8780 2 : if (CSLTestBoolean(CPLGetConfigOption("GTIFF_DELETE_ON_ERROR", "YES")))
8781 1 : VSIUnlink( pszFilename ); // should really delete more carefully.
8782 : }
8783 :
8784 229 : return poDS;
8785 : }
8786 :
8787 : /************************************************************************/
8788 : /* GetProjectionRef() */
8789 : /************************************************************************/
8790 :
8791 3571 : const char *GTiffDataset::GetProjectionRef()
8792 :
8793 : {
8794 3571 : if( nGCPCount == 0 )
8795 : {
8796 3541 : LookForProjection();
8797 :
8798 3541 : if( EQUAL(pszProjection,"") )
8799 108 : return GDALPamDataset::GetProjectionRef();
8800 : else
8801 3433 : return( pszProjection );
8802 : }
8803 : else
8804 30 : return "";
8805 : }
8806 :
8807 : /************************************************************************/
8808 : /* SetProjection() */
8809 : /************************************************************************/
8810 :
8811 743 : CPLErr GTiffDataset::SetProjection( const char * pszNewProjection )
8812 :
8813 : {
8814 743 : LookForProjection();
8815 :
8816 743 : if( !EQUALN(pszNewProjection,"GEOGCS",6)
8817 : && !EQUALN(pszNewProjection,"PROJCS",6)
8818 : && !EQUALN(pszNewProjection,"LOCAL_CS",8)
8819 : && !EQUALN(pszNewProjection,"COMPD_CS",8)
8820 : && !EQUALN(pszNewProjection,"GEOCCS",6)
8821 : && !EQUAL(pszNewProjection,"") )
8822 : {
8823 : CPLError( CE_Failure, CPLE_AppDefined,
8824 : "Only OGC WKT Projections supported for writing to GeoTIFF.\n"
8825 : "%s not supported.",
8826 0 : pszNewProjection );
8827 :
8828 0 : return CE_Failure;
8829 : }
8830 :
8831 743 : CPLFree( pszProjection );
8832 743 : pszProjection = CPLStrdup( pszNewProjection );
8833 :
8834 743 : bGeoTIFFInfoChanged = TRUE;
8835 :
8836 743 : return CE_None;
8837 : }
8838 :
8839 : /************************************************************************/
8840 : /* GetGeoTransform() */
8841 : /************************************************************************/
8842 :
8843 2400 : CPLErr GTiffDataset::GetGeoTransform( double * padfTransform )
8844 :
8845 : {
8846 2400 : memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
8847 :
8848 2400 : if( !bGeoTransformValid )
8849 107 : return CE_Failure;
8850 : else
8851 2293 : return CE_None;
8852 : }
8853 :
8854 : /************************************************************************/
8855 : /* SetGeoTransform() */
8856 : /************************************************************************/
8857 :
8858 707 : CPLErr GTiffDataset::SetGeoTransform( double * padfTransform )
8859 :
8860 : {
8861 707 : if( GetAccess() == GA_Update )
8862 : {
8863 707 : memcpy( adfGeoTransform, padfTransform, sizeof(double)*6 );
8864 707 : bGeoTransformValid = TRUE;
8865 707 : bGeoTIFFInfoChanged = TRUE;
8866 :
8867 707 : return( CE_None );
8868 : }
8869 : else
8870 : {
8871 : CPLError( CE_Failure, CPLE_NotSupported,
8872 0 : "Attempt to call SetGeoTransform() on a read-only GeoTIFF file." );
8873 0 : return CE_Failure;
8874 : }
8875 : }
8876 :
8877 : /************************************************************************/
8878 : /* GetGCPCount() */
8879 : /************************************************************************/
8880 :
8881 1270 : int GTiffDataset::GetGCPCount()
8882 :
8883 : {
8884 1270 : return nGCPCount;
8885 : }
8886 :
8887 : /************************************************************************/
8888 : /* GetGCPProjection() */
8889 : /************************************************************************/
8890 :
8891 65 : const char *GTiffDataset::GetGCPProjection()
8892 :
8893 : {
8894 65 : if( nGCPCount > 0 )
8895 : {
8896 63 : LookForProjection();
8897 : }
8898 65 : if (pszProjection != NULL)
8899 65 : return pszProjection;
8900 : else
8901 0 : return "";
8902 : }
8903 :
8904 : /************************************************************************/
8905 : /* GetGCPs() */
8906 : /************************************************************************/
8907 :
8908 35 : const GDAL_GCP *GTiffDataset::GetGCPs()
8909 :
8910 : {
8911 35 : return pasGCPList;
8912 : }
8913 :
8914 : /************************************************************************/
8915 : /* SetGCPs() */
8916 : /************************************************************************/
8917 :
8918 2 : CPLErr GTiffDataset::SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
8919 : const char *pszGCPProjection )
8920 : {
8921 2 : if( GetAccess() == GA_Update )
8922 : {
8923 2 : bLookedForProjection = TRUE;
8924 :
8925 2 : if( this->nGCPCount > 0 )
8926 : {
8927 0 : GDALDeinitGCPs( this->nGCPCount, this->pasGCPList );
8928 0 : CPLFree( this->pasGCPList );
8929 : }
8930 :
8931 2 : this->nGCPCount = nGCPCount;
8932 2 : this->pasGCPList = GDALDuplicateGCPs(nGCPCount, pasGCPList);
8933 :
8934 2 : CPLFree( this->pszProjection );
8935 2 : this->pszProjection = CPLStrdup( pszGCPProjection );
8936 2 : bGeoTIFFInfoChanged = TRUE;
8937 :
8938 2 : return CE_None;
8939 : }
8940 : else
8941 : {
8942 : CPLError( CE_Failure, CPLE_NotSupported,
8943 0 : "SetGCPs() is only supported on newly created GeoTIFF files." );
8944 0 : return CE_Failure;
8945 : }
8946 : }
8947 :
8948 : /************************************************************************/
8949 : /* GetMetadata() */
8950 : /************************************************************************/
8951 :
8952 6316 : char **GTiffDataset::GetMetadata( const char * pszDomain )
8953 :
8954 : {
8955 6316 : if( pszDomain != NULL && EQUAL(pszDomain,"ProxyOverviewRequest") )
8956 0 : return GDALPamDataset::GetMetadata( pszDomain );
8957 :
8958 8221 : else if( pszDomain != NULL && EQUAL(pszDomain,"RPC") )
8959 1905 : LoadRPCRPB();
8960 :
8961 5604 : else if( pszDomain != NULL && EQUAL(pszDomain,"IMD") )
8962 1193 : LoadIMDPVL();
8963 :
8964 3394 : else if( pszDomain != NULL && EQUAL(pszDomain,"SUBDATASETS") )
8965 176 : ScanDirectories();
8966 :
8967 3044 : else if( pszDomain != NULL && EQUAL(pszDomain,"EXIF") )
8968 2 : LoadEXIFMetadata();
8969 :
8970 3040 : else if( pszDomain == NULL || EQUAL(pszDomain, "") )
8971 2617 : LoadMDAreaOrPoint(); /* to set GDALMD_AREA_OR_POINT */
8972 :
8973 6316 : return oGTiffMDMD.GetMetadata( pszDomain );
8974 : }
8975 :
8976 : /************************************************************************/
8977 : /* SetMetadata() */
8978 : /************************************************************************/
8979 558 : CPLErr GTiffDataset::SetMetadata( char ** papszMD, const char *pszDomain )
8980 :
8981 : {
8982 558 : if( pszDomain == NULL || !EQUAL(pszDomain,"_temporary_") )
8983 558 : bMetadataChanged = TRUE;
8984 :
8985 558 : if( (pszDomain == NULL || EQUAL(pszDomain, "")) &&
8986 : CSLFetchNameValue(papszMD, GDALMD_AREA_OR_POINT) != NULL )
8987 : {
8988 : const char* pszPrevValue =
8989 414 : GetMetadataItem(GDALMD_AREA_OR_POINT);
8990 : const char* pszNewValue =
8991 414 : CSLFetchNameValue(papszMD, GDALMD_AREA_OR_POINT);
8992 414 : if (pszPrevValue == NULL || pszNewValue == NULL ||
8993 : !EQUAL(pszPrevValue, pszNewValue))
8994 : {
8995 273 : LookForProjection();
8996 273 : bGeoTIFFInfoChanged = TRUE;
8997 : }
8998 : }
8999 :
9000 558 : return oGTiffMDMD.SetMetadata( papszMD, pszDomain );
9001 : }
9002 :
9003 : /************************************************************************/
9004 : /* GetMetadataItem() */
9005 : /************************************************************************/
9006 :
9007 25171 : const char *GTiffDataset::GetMetadataItem( const char * pszName,
9008 : const char * pszDomain )
9009 :
9010 : {
9011 25171 : if( pszDomain != NULL && EQUAL(pszDomain,"ProxyOverviewRequest") )
9012 3 : return GDALPamDataset::GetMetadataItem( pszName, pszDomain );
9013 :
9014 25170 : else if( pszDomain != NULL && EQUAL(pszDomain,"RPC") )
9015 2 : LoadRPCRPB();
9016 :
9017 25168 : else if( pszDomain != NULL && EQUAL(pszDomain,"IMD") )
9018 2 : LoadIMDPVL();
9019 :
9020 25164 : else if( pszDomain != NULL && EQUAL(pszDomain,"SUBDATASETS") )
9021 0 : ScanDirectories();
9022 :
9023 25165 : else if( pszDomain != NULL && EQUAL(pszDomain,"EXIF") )
9024 1 : LoadEXIFMetadata();
9025 :
9026 25163 : else if( (pszDomain == NULL || EQUAL(pszDomain, "")) &&
9027 : pszName != NULL && EQUAL(pszName, GDALMD_AREA_OR_POINT) )
9028 : {
9029 2034 : LoadMDAreaOrPoint(); /* to set GDALMD_AREA_OR_POINT */
9030 : }
9031 :
9032 25168 : return oGTiffMDMD.GetMetadataItem( pszName, pszDomain );
9033 : }
9034 :
9035 : /************************************************************************/
9036 : /* SetMetadataItem() */
9037 : /************************************************************************/
9038 :
9039 5706 : CPLErr GTiffDataset::SetMetadataItem( const char *pszName,
9040 : const char *pszValue,
9041 : const char *pszDomain )
9042 :
9043 : {
9044 5706 : if( pszDomain == NULL || !EQUAL(pszDomain,"_temporary_") )
9045 5706 : bMetadataChanged = TRUE;
9046 :
9047 5706 : if( (pszDomain == NULL || EQUAL(pszDomain, "")) &&
9048 : pszName != NULL && EQUAL(pszName, GDALMD_AREA_OR_POINT) )
9049 : {
9050 8 : LookForProjection();
9051 8 : bGeoTIFFInfoChanged = TRUE;
9052 : }
9053 :
9054 5706 : return oGTiffMDMD.SetMetadataItem( pszName, pszValue, pszDomain );
9055 : }
9056 :
9057 : /************************************************************************/
9058 : /* GetInternalHandle() */
9059 : /************************************************************************/
9060 :
9061 313 : void *GTiffDataset::GetInternalHandle( const char * /* pszHandleName */ )
9062 :
9063 : {
9064 313 : return hTIFF;
9065 : }
9066 :
9067 :
9068 : /************************************************************************/
9069 : /* FindRPBFile() */
9070 : /************************************************************************/
9071 :
9072 2247 : int GTiffDataset::FindRPBFile()
9073 : {
9074 : osRPBFile = GDALFindAssociatedFile( osFilename, "RPB",
9075 2247 : oOvManager.GetSiblingFiles(), 0 );
9076 :
9077 2247 : return osRPBFile != "";
9078 : }
9079 :
9080 : /************************************************************************/
9081 : /* FindIMDFile() */
9082 : /************************************************************************/
9083 :
9084 2074 : int GTiffDataset::FindIMDFile()
9085 : {
9086 : osIMDFile = GDALFindAssociatedFile( osFilename, "IMD",
9087 2074 : oOvManager.GetSiblingFiles(), 0 );
9088 :
9089 2074 : return osIMDFile != "";
9090 : }
9091 :
9092 : /************************************************************************/
9093 : /* FindPVLFile() */
9094 : /************************************************************************/
9095 :
9096 2066 : int GTiffDataset::FindPVLFile()
9097 : {
9098 : osPVLFile = GDALFindAssociatedFile( osFilename, "PVL",
9099 2066 : oOvManager.GetSiblingFiles(), 0 );
9100 :
9101 2066 : return osPVLFile != "";
9102 : }
9103 :
9104 : /************************************************************************/
9105 : /* FindRPCFile() */
9106 : /************************************************************************/
9107 :
9108 2239 : int GTiffDataset::FindRPCFile()
9109 : {
9110 2239 : CPLString osSrcPath = osFilename;
9111 2239 : CPLString soPt(".");
9112 2239 : size_t found = osSrcPath.rfind(soPt);
9113 2239 : if (found == CPLString::npos)
9114 42 : return FALSE;
9115 2197 : osSrcPath.replace (found, osSrcPath.size() - found, "_rpc.txt");
9116 2197 : CPLString osTarget = osSrcPath;
9117 :
9118 2197 : char** papszSiblingFiles = oOvManager.GetSiblingFiles();
9119 2197 : if( papszSiblingFiles == NULL )
9120 : {
9121 : VSIStatBufL sStatBuf;
9122 :
9123 947 : if( VSIStatExL( osTarget, &sStatBuf, VSI_STAT_EXISTS_FLAG ) != 0 )
9124 : {
9125 947 : osSrcPath = osFilename;
9126 947 : osSrcPath.replace (found, osSrcPath.size() - found, "_RPC.TXT");
9127 947 : osTarget = osSrcPath;
9128 :
9129 947 : if( VSIStatExL( osTarget, &sStatBuf, VSI_STAT_EXISTS_FLAG ) != 0 )
9130 : {
9131 947 : osSrcPath = osFilename;
9132 947 : osSrcPath.replace (found, osSrcPath.size() - found, "_rpc.TXT");
9133 947 : osTarget = osSrcPath;
9134 :
9135 947 : if( VSIStatExL( osTarget, &sStatBuf, VSI_STAT_EXISTS_FLAG ) != 0 )
9136 : {
9137 947 : return FALSE;
9138 : }
9139 : }
9140 : }
9141 : }
9142 : else
9143 : {
9144 : int iSibling = CSLFindString( papszSiblingFiles,
9145 1250 : CPLGetFilename(osTarget) );
9146 1250 : if( iSibling < 0 )
9147 1249 : return FALSE;
9148 :
9149 1 : osTarget.resize(osTarget.size() - strlen(papszSiblingFiles[iSibling]));
9150 1 : osTarget += papszSiblingFiles[iSibling];
9151 : }
9152 :
9153 1 : osRPCFile = osTarget;
9154 1 : return TRUE;
9155 : }
9156 :
9157 : /************************************************************************/
9158 : /* LoadRPCRPB() */
9159 : /************************************************************************/
9160 :
9161 2881 : void GTiffDataset::LoadRPCRPB()
9162 : {
9163 2881 : if (bHasSearchedRPC)
9164 634 : return;
9165 :
9166 2247 : bHasSearchedRPC = TRUE;
9167 :
9168 2247 : char **papszRPCMD = NULL;
9169 : /* Read Digital Globe .RPB file */
9170 2247 : if (FindRPBFile())
9171 8 : papszRPCMD = GDALLoadRPBFile( osRPBFile.c_str(), NULL );
9172 :
9173 : /* Read GeoEye _rpc.txt file */
9174 2247 : if(papszRPCMD == NULL && FindRPCFile())
9175 1 : papszRPCMD = GDALLoadRPCFile( osRPCFile.c_str(), NULL );
9176 :
9177 2247 : if( papszRPCMD != NULL )
9178 : {
9179 9 : oGTiffMDMD.SetMetadata( papszRPCMD, "RPC" );
9180 9 : CSLDestroy( papszRPCMD );
9181 : }
9182 : else
9183 2238 : ReadRPCTag();
9184 : }
9185 :
9186 : /************************************************************************/
9187 : /* LoadIMDPVL() */
9188 : /************************************************************************/
9189 :
9190 2169 : void GTiffDataset::LoadIMDPVL()
9191 : {
9192 2169 : if (!bHasSearchedIMD)
9193 : {
9194 2074 : bHasSearchedIMD = TRUE;
9195 :
9196 2074 : if (FindIMDFile())
9197 : {
9198 8 : char **papszIMDMD = GDALLoadIMDFile( osIMDFile.c_str(), NULL );
9199 :
9200 8 : if( papszIMDMD != NULL )
9201 : {
9202 : papszIMDMD = CSLSetNameValue( papszIMDMD,
9203 8 : "md_type", "imd" );
9204 8 : oGTiffMDMD.SetMetadata( papszIMDMD, "IMD" );
9205 8 : CSLDestroy( papszIMDMD );
9206 : }
9207 : }
9208 : }
9209 : //the imd has priority
9210 2169 : if (!bHasSearchedPVL && osIMDFile.empty())
9211 : {
9212 2066 : bHasSearchedPVL = TRUE;
9213 :
9214 2066 : if (FindPVLFile())
9215 : {
9216 : /* -------------------------------------------------------------------- */
9217 : /* Read file and parse. */
9218 : /* -------------------------------------------------------------------- */
9219 0 : CPLKeywordParser oParser;
9220 :
9221 0 : VSILFILE *fp = VSIFOpenL( osPVLFile.c_str(), "r" );
9222 :
9223 0 : if( fp == NULL )
9224 : return;
9225 :
9226 0 : if( !oParser.Ingest( fp ) )
9227 : {
9228 0 : VSIFCloseL( fp );
9229 : return;
9230 : }
9231 :
9232 0 : VSIFCloseL( fp );
9233 :
9234 : /* -------------------------------------------------------------------- */
9235 : /* Consider version changing. */
9236 : /* -------------------------------------------------------------------- */
9237 0 : char **papszPVLMD = CSLDuplicate( oParser.GetAllKeywords() );
9238 :
9239 0 : if( papszPVLMD != NULL )
9240 : {
9241 : papszPVLMD = CSLSetNameValue( papszPVLMD,
9242 0 : "md_type", "pvl" );
9243 :
9244 0 : oGTiffMDMD.SetMetadata( papszPVLMD, "IMD" );
9245 0 : CSLDestroy( papszPVLMD );
9246 0 : }
9247 : }
9248 : }
9249 : }
9250 :
9251 : /************************************************************************/
9252 : /* LoadEXIFMetadata() */
9253 : /************************************************************************/
9254 :
9255 3 : void GTiffDataset::LoadEXIFMetadata()
9256 : {
9257 3 : if (bEXIFMetadataLoaded)
9258 0 : return;
9259 3 : bEXIFMetadataLoaded = TRUE;
9260 :
9261 3 : if (!SetDirectory())
9262 0 : return;
9263 :
9264 3 : VSILFILE* fp = (VSILFILE*) TIFFClientdata( hTIFF );
9265 :
9266 : GByte abyHeader[2];
9267 3 : VSIFSeekL(fp, 0, SEEK_SET);
9268 3 : VSIFReadL(abyHeader, 1, 2, fp);
9269 :
9270 3 : int bLittleEndian = abyHeader[0] == 'I' && abyHeader[1] == 'I';
9271 3 : int bSwabflag = bLittleEndian ^ CPL_IS_LSB;
9272 :
9273 3 : char** papszMetadata = NULL;
9274 : toff_t nOffset;
9275 :
9276 3 : if (TIFFGetField(hTIFF, TIFFTAG_EXIFIFD, &nOffset))
9277 : {
9278 2 : int nExifOffset = (int)nOffset, nInterOffset = 0, nGPSOffset = 0;
9279 : EXIFExtractMetadata(papszMetadata,
9280 : fp, (int)nOffset,
9281 : bSwabflag, 0,
9282 2 : nExifOffset, nInterOffset, nGPSOffset);
9283 : }
9284 :
9285 3 : if (TIFFGetField(hTIFF, TIFFTAG_GPSIFD, &nOffset))
9286 : {
9287 2 : int nExifOffset = 0, nInterOffset = 0, nGPSOffset = (int)nOffset;
9288 : EXIFExtractMetadata(papszMetadata,
9289 : fp, (int)nOffset,
9290 : bSwabflag, 0,
9291 2 : nExifOffset, nInterOffset, nGPSOffset);
9292 : }
9293 :
9294 3 : oGTiffMDMD.SetMetadata( papszMetadata, "EXIF" );
9295 3 : CSLDestroy( papszMetadata );
9296 : }
9297 :
9298 : /************************************************************************/
9299 : /* GetFileList() */
9300 : /************************************************************************/
9301 :
9302 974 : char **GTiffDataset::GetFileList()
9303 :
9304 : {
9305 974 : char **papszFileList = GDALPamDataset::GetFileList();
9306 :
9307 974 : LoadRPCRPB();
9308 974 : LoadIMDPVL();
9309 :
9310 974 : if (osIMDFile.size() != 0)
9311 4 : papszFileList = CSLAddString( papszFileList, osIMDFile );
9312 974 : if (osPVLFile.size() != 0)
9313 0 : papszFileList = CSLAddString( papszFileList, osPVLFile );
9314 974 : if (osRPBFile.size() != 0)
9315 2 : papszFileList = CSLAddString( papszFileList, osRPBFile );
9316 974 : if (osRPCFile.size() != 0)
9317 0 : papszFileList = CSLAddString( papszFileList, osRPCFile );
9318 :
9319 974 : if (osWldFilename.size() != 0 &&
9320 : CSLFindString(papszFileList, osWldFilename) == -1)
9321 : {
9322 3 : papszFileList = CSLAddString( papszFileList, osWldFilename );
9323 : }
9324 :
9325 974 : return papszFileList;
9326 : }
9327 :
9328 : /************************************************************************/
9329 : /* CreateMaskBand() */
9330 : /************************************************************************/
9331 :
9332 33 : CPLErr GTiffDataset::CreateMaskBand(int nFlags)
9333 : {
9334 33 : ScanDirectories();
9335 :
9336 33 : if (poMaskDS != NULL)
9337 : {
9338 : CPLError(CE_Failure, CPLE_AppDefined,
9339 0 : "This TIFF dataset has already an internal mask band");
9340 0 : return CE_Failure;
9341 : }
9342 33 : else if (CSLTestBoolean(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK", "NO")))
9343 : {
9344 : toff_t nOffset;
9345 : int bIsTiled;
9346 29 : int bIsOverview = FALSE;
9347 : uint32 nSubType;
9348 : int nCompression;
9349 :
9350 29 : if (nFlags != GMF_PER_DATASET)
9351 : {
9352 : CPLError(CE_Failure, CPLE_AppDefined,
9353 0 : "The only flag value supported for internal mask is GMF_PER_DATASET");
9354 0 : return CE_Failure;
9355 : }
9356 :
9357 29 : if( strstr(GDALGetMetadataItem(GDALGetDriverByName( "GTiff" ),
9358 : GDAL_DMD_CREATIONOPTIONLIST, NULL ),
9359 : "<Value>DEFLATE</Value>") != NULL )
9360 29 : nCompression = COMPRESSION_ADOBE_DEFLATE;
9361 : else
9362 0 : nCompression = COMPRESSION_PACKBITS;
9363 :
9364 : /* -------------------------------------------------------------------- */
9365 : /* If we don't have read access, then create the mask externally. */
9366 : /* -------------------------------------------------------------------- */
9367 29 : if( GetAccess() != GA_Update )
9368 : {
9369 : CPLError( CE_Warning, CPLE_AppDefined,
9370 : "File open for read-only accessing, "
9371 0 : "creating mask externally." );
9372 :
9373 0 : return GDALPamDataset::CreateMaskBand(nFlags);
9374 : }
9375 :
9376 29 : if (poBaseDS)
9377 : {
9378 12 : if (!poBaseDS->SetDirectory())
9379 0 : return CE_Failure;
9380 : }
9381 29 : if (!SetDirectory())
9382 0 : return CE_Failure;
9383 :
9384 29 : if( TIFFGetField(hTIFF, TIFFTAG_SUBFILETYPE, &nSubType))
9385 : {
9386 12 : bIsOverview = (nSubType & FILETYPE_REDUCEDIMAGE) != 0;
9387 :
9388 12 : if ((nSubType & FILETYPE_MASK) != 0)
9389 : {
9390 : CPLError( CE_Failure, CPLE_AppDefined,
9391 0 : "Cannot create a mask on a TIFF mask IFD !" );
9392 0 : return CE_Failure;
9393 : }
9394 : }
9395 :
9396 29 : bIsTiled = TIFFIsTiled(hTIFF);
9397 :
9398 29 : FlushDirectory();
9399 :
9400 : nOffset = GTIFFWriteDirectory(hTIFF,
9401 : (bIsOverview) ? FILETYPE_REDUCEDIMAGE | FILETYPE_MASK : FILETYPE_MASK,
9402 : nRasterXSize, nRasterYSize,
9403 : 1, PLANARCONFIG_CONTIG, 1,
9404 : nBlockXSize, nBlockYSize,
9405 : bIsTiled, nCompression,
9406 : PHOTOMETRIC_MASK, PREDICTOR_NONE,
9407 29 : SAMPLEFORMAT_UINT, NULL, NULL, NULL, 0, NULL, "");
9408 29 : if (nOffset == 0)
9409 0 : return CE_Failure;
9410 :
9411 29 : poMaskDS = new GTiffDataset();
9412 29 : poMaskDS->bPromoteTo8Bits = CSLTestBoolean(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK_TO_8BIT", "YES"));
9413 29 : if( poMaskDS->OpenOffset( hTIFF, ppoActiveDSRef, nOffset,
9414 : FALSE, GA_Update ) != CE_None)
9415 : {
9416 0 : delete poMaskDS;
9417 0 : poMaskDS = NULL;
9418 0 : return CE_Failure;
9419 : }
9420 :
9421 29 : return CE_None;
9422 : }
9423 : else
9424 : {
9425 4 : return GDALPamDataset::CreateMaskBand(nFlags);
9426 : }
9427 : }
9428 :
9429 : /************************************************************************/
9430 : /* CreateMaskBand() */
9431 : /************************************************************************/
9432 :
9433 12 : CPLErr GTiffRasterBand::CreateMaskBand(int nFlags)
9434 : {
9435 12 : poGDS->ScanDirectories();
9436 :
9437 12 : if (poGDS->poMaskDS != NULL)
9438 : {
9439 : CPLError(CE_Failure, CPLE_AppDefined,
9440 0 : "This TIFF dataset has already an internal mask band");
9441 0 : return CE_Failure;
9442 : }
9443 12 : else if (CSLTestBoolean(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK", "NO")))
9444 : {
9445 12 : return poGDS->CreateMaskBand(nFlags);
9446 : }
9447 : else
9448 : {
9449 0 : return GDALPamRasterBand::CreateMaskBand(nFlags);
9450 : }
9451 : }
9452 :
9453 : /************************************************************************/
9454 : /* PrepareTIFFErrorFormat() */
9455 : /* */
9456 : /* sometimes the "module" has stuff in it that has special */
9457 : /* meaning in a printf() style format, so we try to escape it. */
9458 : /* For now we hope the only thing we have to escape is %'s. */
9459 : /************************************************************************/
9460 :
9461 29 : static char *PrepareTIFFErrorFormat( const char *module, const char *fmt )
9462 :
9463 : {
9464 : char *pszModFmt;
9465 : int iIn, iOut;
9466 :
9467 29 : pszModFmt = (char *) CPLMalloc( strlen(module)*2 + strlen(fmt) + 2 );
9468 346 : for( iOut = 0, iIn = 0; module[iIn] != '\0'; iIn++ )
9469 : {
9470 317 : if( module[iIn] == '%' )
9471 : {
9472 0 : pszModFmt[iOut++] = '%';
9473 0 : pszModFmt[iOut++] = '%';
9474 : }
9475 : else
9476 317 : pszModFmt[iOut++] = module[iIn];
9477 : }
9478 29 : pszModFmt[iOut] = '\0';
9479 29 : strcat( pszModFmt, ":" );
9480 29 : strcat( pszModFmt, fmt );
9481 :
9482 29 : return pszModFmt;
9483 : }
9484 :
9485 : /************************************************************************/
9486 : /* GTiffWarningHandler() */
9487 : /************************************************************************/
9488 : void
9489 8 : GTiffWarningHandler(const char* module, const char* fmt, va_list ap )
9490 : {
9491 : char *pszModFmt;
9492 :
9493 8 : if( strstr(fmt,"nknown field") != NULL )
9494 0 : return;
9495 :
9496 8 : pszModFmt = PrepareTIFFErrorFormat( module, fmt );
9497 8 : if( strstr(fmt, "does not end in null byte") != NULL )
9498 : {
9499 2 : CPLString osMsg;
9500 2 : osMsg.vPrintf(pszModFmt, ap);
9501 2 : CPLDebug( "GTiff", "%s", osMsg.c_str() );
9502 : }
9503 : else
9504 6 : CPLErrorV( CE_Warning, CPLE_AppDefined, pszModFmt, ap );
9505 8 : CPLFree( pszModFmt );
9506 : }
9507 :
9508 : /************************************************************************/
9509 : /* GTiffErrorHandler() */
9510 : /************************************************************************/
9511 : void
9512 21 : GTiffErrorHandler(const char* module, const char* fmt, va_list ap )
9513 : {
9514 : char *pszModFmt;
9515 :
9516 21 : pszModFmt = PrepareTIFFErrorFormat( module, fmt );
9517 21 : CPLErrorV( CE_Failure, CPLE_AppDefined, pszModFmt, ap );
9518 21 : CPLFree( pszModFmt );
9519 21 : }
9520 :
9521 : /************************************************************************/
9522 : /* GTiffTagExtender() */
9523 : /* */
9524 : /* Install tags specially known to GDAL. */
9525 : /************************************************************************/
9526 :
9527 : static TIFFExtendProc _ParentExtender = NULL;
9528 :
9529 13404 : static void GTiffTagExtender(TIFF *tif)
9530 :
9531 : {
9532 : static const TIFFFieldInfo xtiffFieldInfo[] = {
9533 : { TIFFTAG_GDAL_METADATA, -1,-1, TIFF_ASCII, FIELD_CUSTOM,
9534 : TRUE, FALSE, (char*) "GDALMetadata" },
9535 : { TIFFTAG_GDAL_NODATA, -1,-1, TIFF_ASCII, FIELD_CUSTOM,
9536 : TRUE, FALSE, (char*) "GDALNoDataValue" },
9537 : { TIFFTAG_RPCCOEFFICIENT, -1,-1, TIFF_DOUBLE, FIELD_CUSTOM,
9538 : TRUE, TRUE, (char*) "RPCCoefficient" }
9539 : };
9540 :
9541 13404 : if (_ParentExtender)
9542 0 : (*_ParentExtender)(tif);
9543 :
9544 : TIFFMergeFieldInfo( tif, xtiffFieldInfo,
9545 13404 : sizeof(xtiffFieldInfo) / sizeof(xtiffFieldInfo[0]) );
9546 13404 : }
9547 :
9548 : /************************************************************************/
9549 : /* GTiffOneTimeInit() */
9550 : /* */
9551 : /* This is stuff that is initialized for the TIFF library just */
9552 : /* once. We deliberately defer the initialization till the */
9553 : /* first time we are likely to call into libtiff to avoid */
9554 : /* unnecessary paging in of the library for GDAL apps that */
9555 : /* don't use it. */
9556 : /************************************************************************/
9557 : #if defined(HAVE_DLFCN_H) && !defined(WIN32)
9558 : #include <dlfcn.h>
9559 : #endif
9560 :
9561 5190 : int GTiffOneTimeInit()
9562 :
9563 : {
9564 : static int bInitIsOk = TRUE;
9565 : static int bOneTimeInitDone = FALSE;
9566 : static void* hMutex = NULL;
9567 5190 : CPLMutexHolder oHolder( &hMutex);
9568 5190 : if( bOneTimeInitDone )
9569 4749 : return bInitIsOk;
9570 :
9571 441 : bOneTimeInitDone = TRUE;
9572 :
9573 : /* This is a frequent configuration error that is difficult to track down */
9574 : /* for people unaware of the issue : GDAL built against internal libtiff (4.X) */
9575 : /* but used by an application that links with external libtiff (3.X) */
9576 : /* Note: on my conf, the order that cause GDAL to crash - and that is detected */
9577 : /* by the following code - is "-ltiff -lgdal". "-lgdal -ltiff" works for the */
9578 : /* GTiff driver but probably breaks the application that believes it uses libtiff 3.X */
9579 : /* but we cannot detect that... */
9580 : #if defined(BIGTIFF_SUPPORT) && !defined(RENAME_INTERNAL_LIBTIFF_SYMBOLS)
9581 : #if defined(HAVE_DLFCN_H) && !defined(WIN32)
9582 : const char* (*pfnVersion)(void);
9583 : pfnVersion = (const char* (*)(void)) dlsym(RTLD_DEFAULT, "TIFFGetVersion");
9584 : if (pfnVersion)
9585 : {
9586 : const char* pszVersion = pfnVersion();
9587 : if (pszVersion && strstr(pszVersion, "Version 3.") != NULL)
9588 : {
9589 : CPLError(CE_Warning, CPLE_AppDefined,
9590 : "libtiff version mismatch : You're linking against libtiff 3.X, but GDAL has been compiled against libtiff >= 4.0.0");
9591 : }
9592 : }
9593 : #endif
9594 : #endif
9595 :
9596 441 : _ParentExtender = TIFFSetTagExtender(GTiffTagExtender);
9597 :
9598 441 : TIFFSetWarningHandler( GTiffWarningHandler );
9599 441 : TIFFSetErrorHandler( GTiffErrorHandler );
9600 :
9601 : // This only really needed if we are linked to an external libgeotiff
9602 : // with its own (lame) file searching logic.
9603 441 : SetCSVFilenameHook( GDALDefaultCSVFilename );
9604 :
9605 441 : return TRUE;
9606 : }
9607 :
9608 : /************************************************************************/
9609 : /* GDALDeregister_GTiff() */
9610 : /************************************************************************/
9611 :
9612 542 : void GDALDeregister_GTiff( GDALDriver * )
9613 :
9614 : {
9615 542 : CSVDeaccess( NULL );
9616 :
9617 : #if defined(LIBGEOTIFF_VERSION) && LIBGEOTIFF_VERSION > 1150
9618 542 : GTIFDeaccessCSV();
9619 : #endif
9620 542 : }
9621 :
9622 : /************************************************************************/
9623 : /* GTIFFGetCompressionMethod() */
9624 : /************************************************************************/
9625 :
9626 77 : int GTIFFGetCompressionMethod(const char* pszValue, const char* pszVariableName)
9627 : {
9628 77 : int nCompression = COMPRESSION_NONE;
9629 77 : if( EQUAL( pszValue, "NONE" ) )
9630 1 : nCompression = COMPRESSION_NONE;
9631 76 : else if( EQUAL( pszValue, "JPEG" ) )
9632 41 : nCompression = COMPRESSION_JPEG;
9633 35 : else if( EQUAL( pszValue, "LZW" ) )
9634 17 : nCompression = COMPRESSION_LZW;
9635 18 : else if( EQUAL( pszValue, "PACKBITS" ))
9636 2 : nCompression = COMPRESSION_PACKBITS;
9637 30 : else if( EQUAL( pszValue, "DEFLATE" ) || EQUAL( pszValue, "ZIP" ))
9638 14 : nCompression = COMPRESSION_ADOBE_DEFLATE;
9639 2 : else if( EQUAL( pszValue, "FAX3" )
9640 : || EQUAL( pszValue, "CCITTFAX3" ))
9641 0 : nCompression = COMPRESSION_CCITTFAX3;
9642 4 : else if( EQUAL( pszValue, "FAX4" )
9643 : || EQUAL( pszValue, "CCITTFAX4" ))
9644 2 : nCompression = COMPRESSION_CCITTFAX4;
9645 0 : else if( EQUAL( pszValue, "CCITTRLE" ) )
9646 0 : nCompression = COMPRESSION_CCITTRLE;
9647 0 : else if( EQUAL( pszValue, "LZMA" ) )
9648 0 : nCompression = COMPRESSION_LZMA;
9649 : else
9650 : CPLError( CE_Warning, CPLE_IllegalArg,
9651 : "%s=%s value not recognised, ignoring.",
9652 0 : pszVariableName,pszValue );
9653 :
9654 : #if defined(TIFFLIB_VERSION) && TIFFLIB_VERSION > 20031007 /* 3.6.0 */
9655 77 : if (nCompression != COMPRESSION_NONE &&
9656 : !TIFFIsCODECConfigured((uint16) nCompression))
9657 : {
9658 : CPLError( CE_Failure, CPLE_AppDefined,
9659 0 : "Cannot create TIFF file due to missing codec for %s.", pszValue );
9660 0 : return -1;
9661 : }
9662 : #endif
9663 :
9664 77 : return nCompression;
9665 : }
9666 : /************************************************************************/
9667 : /* GDALRegister_GTiff() */
9668 : /************************************************************************/
9669 :
9670 582 : void GDALRegister_GTiff()
9671 :
9672 : {
9673 582 : if( GDALGetDriverByName( "GTiff" ) == NULL )
9674 : {
9675 : GDALDriver *poDriver;
9676 : char szCreateOptions[3072];
9677 : char szOptionalCompressItems[500];
9678 561 : int bHasJPEG = FALSE, bHasLZW = FALSE, bHasDEFLATE = FALSE, bHasLZMA = FALSE;
9679 :
9680 561 : poDriver = new GDALDriver();
9681 :
9682 : /* -------------------------------------------------------------------- */
9683 : /* Determine which compression codecs are available that we */
9684 : /* want to advertise. If we are using an old libtiff we won't */
9685 : /* be able to find out so we just assume all are available. */
9686 : /* -------------------------------------------------------------------- */
9687 : strcpy( szOptionalCompressItems,
9688 561 : " <Value>NONE</Value>" );
9689 :
9690 : #if TIFFLIB_VERSION <= 20040919
9691 : strcat( szOptionalCompressItems,
9692 : " <Value>PACKBITS</Value>"
9693 : " <Value>JPEG</Value>"
9694 : " <Value>LZW</Value>"
9695 : " <Value>DEFLATE</Value>" );
9696 : bHasLZW = bHasDEFLATE = TRUE;
9697 : #else
9698 561 : TIFFCodec *c, *codecs = TIFFGetConfiguredCODECs();
9699 :
9700 10098 : for( c = codecs; c->name; c++ )
9701 : {
9702 9537 : if( c->scheme == COMPRESSION_PACKBITS )
9703 : strcat( szOptionalCompressItems,
9704 561 : " <Value>PACKBITS</Value>" );
9705 8976 : else if( c->scheme == COMPRESSION_JPEG )
9706 : {
9707 561 : bHasJPEG = TRUE;
9708 : strcat( szOptionalCompressItems,
9709 561 : " <Value>JPEG</Value>" );
9710 : }
9711 8415 : else if( c->scheme == COMPRESSION_LZW )
9712 : {
9713 561 : bHasLZW = TRUE;
9714 : strcat( szOptionalCompressItems,
9715 561 : " <Value>LZW</Value>" );
9716 : }
9717 7854 : else if( c->scheme == COMPRESSION_ADOBE_DEFLATE )
9718 : {
9719 561 : bHasDEFLATE = TRUE;
9720 : strcat( szOptionalCompressItems,
9721 561 : " <Value>DEFLATE</Value>" );
9722 : }
9723 7293 : else if( c->scheme == COMPRESSION_CCITTRLE )
9724 : strcat( szOptionalCompressItems,
9725 561 : " <Value>CCITTRLE</Value>" );
9726 6732 : else if( c->scheme == COMPRESSION_CCITTFAX3 )
9727 : strcat( szOptionalCompressItems,
9728 561 : " <Value>CCITTFAX3</Value>" );
9729 6171 : else if( c->scheme == COMPRESSION_CCITTFAX4 )
9730 : strcat( szOptionalCompressItems,
9731 561 : " <Value>CCITTFAX4</Value>" );
9732 5610 : else if( c->scheme == COMPRESSION_LZMA )
9733 : {
9734 561 : bHasLZMA = TRUE;
9735 : strcat( szOptionalCompressItems,
9736 561 : " <Value>LZMA</Value>" );
9737 : }
9738 : }
9739 561 : _TIFFfree( codecs );
9740 : #endif
9741 :
9742 : /* -------------------------------------------------------------------- */
9743 : /* Build full creation option list. */
9744 : /* -------------------------------------------------------------------- */
9745 : sprintf( szCreateOptions, "%s%s%s",
9746 : "<CreationOptionList>"
9747 : " <Option name='COMPRESS' type='string-select'>",
9748 : szOptionalCompressItems,
9749 561 : " </Option>");
9750 561 : if (bHasLZW || bHasDEFLATE)
9751 : strcat( szCreateOptions, ""
9752 561 : " <Option name='PREDICTOR' type='int' description='Predictor Type'/>");
9753 561 : if (bHasJPEG)
9754 : {
9755 : strcat( szCreateOptions, ""
9756 561 : " <Option name='JPEG_QUALITY' type='int' description='JPEG quality 1-100' default='75'/>" );
9757 : #ifdef JPEG_DIRECT_COPY
9758 : strcat( szCreateOptions, ""
9759 : " <Option name='JPEG_DIRECT_COPY' type='boolean' description='To copy without any decompression/recompression a JPEG source file' default='NO'/>");
9760 : #endif
9761 : }
9762 561 : if (bHasDEFLATE)
9763 : strcat( szCreateOptions, ""
9764 561 : " <Option name='ZLEVEL' type='int' description='DEFLATE compression level 1-9' default='6'/>");
9765 561 : if (bHasLZMA)
9766 : strcat( szCreateOptions, ""
9767 561 : " <Option name='LZMA_PRESET' type='int' description='LZMA compression level 0(fast)-9(slow)' default='6'/>");
9768 : strcat( szCreateOptions, ""
9769 : " <Option name='NBITS' type='int' description='BITS for sub-byte files (1-7), sub-uint16 (9-15), sub-uint32 (17-31)'/>"
9770 : " <Option name='INTERLEAVE' type='string-select' default='PIXEL'>"
9771 : " <Value>BAND</Value>"
9772 : " <Value>PIXEL</Value>"
9773 : " </Option>"
9774 : " <Option name='TILED' type='boolean' description='Switch to tiled format'/>"
9775 : " <Option name='TFW' type='boolean' description='Write out world file'/>"
9776 : " <Option name='RPB' type='boolean' description='Write out .RPB (RPC) file'/>"
9777 : " <Option name='BLOCKXSIZE' type='int' description='Tile Width'/>"
9778 : " <Option name='BLOCKYSIZE' type='int' description='Tile/Strip Height'/>"
9779 : " <Option name='PHOTOMETRIC' type='string-select'>"
9780 : " <Value>MINISBLACK</Value>"
9781 : " <Value>MINISWHITE</Value>"
9782 : " <Value>PALETTE</Value>"
9783 : " <Value>RGB</Value>"
9784 : " <Value>CMYK</Value>"
9785 : " <Value>YCBCR</Value>"
9786 : " <Value>CIELAB</Value>"
9787 : " <Value>ICCLAB</Value>"
9788 : " <Value>ITULAB</Value>"
9789 : " </Option>"
9790 : " <Option name='SPARSE_OK' type='boolean' description='Can newly created files have missing blocks?' default='FALSE'/>"
9791 : " <Option name='ALPHA' type='string-select' description='Mark first extrasample as being alpha'>"
9792 : " <Value>NON-PREMULTIPLIED</Value>"
9793 : " <Value>PREMULTIPLIED</Value>"
9794 : " <Value>UNSPECIFIED</Value>"
9795 : " <Value aliasOf='NON-PREMULTIPLIED'>YES</Value>"
9796 : " <Value aliasOf='UNSPECIFIED'>NO</Value>"
9797 : " </Option>"
9798 : " <Option name='PROFILE' type='string-select' default='GDALGeoTIFF'>"
9799 : " <Value>GDALGeoTIFF</Value>"
9800 : " <Value>GeoTIFF</Value>"
9801 : " <Value>BASELINE</Value>"
9802 : " </Option>"
9803 : " <Option name='PIXELTYPE' type='string-select'>"
9804 : " <Value>DEFAULT</Value>"
9805 : " <Value>SIGNEDBYTE</Value>"
9806 : " </Option>"
9807 : #ifdef BIGTIFF_SUPPORT
9808 : " <Option name='BIGTIFF' type='string-select' description='Force creation of BigTIFF file'>"
9809 : " <Value>YES</Value>"
9810 : " <Value>NO</Value>"
9811 : " <Value>IF_NEEDED</Value>"
9812 : " <Value>IF_SAFER</Value>"
9813 : " </Option>"
9814 : #endif
9815 : " <Option name='ENDIANNESS' type='string-select' default='NATIVE' description='Force endianness of created file. For DEBUG purpose mostly'>"
9816 : " <Value>NATIVE</Value>"
9817 : " <Value>INVERTED</Value>"
9818 : " <Value>LITTLE</Value>"
9819 : " <Value>BIG</Value>"
9820 : " </Option>"
9821 : " <Option name='COPY_SRC_OVERVIEWS' type='boolean' default='NO' description='Force copy of overviews of source dataset (CreateCopy())'/>"
9822 561 : "</CreationOptionList>" );
9823 :
9824 : /* -------------------------------------------------------------------- */
9825 : /* Set the driver details. */
9826 : /* -------------------------------------------------------------------- */
9827 561 : poDriver->SetDescription( "GTiff" );
9828 561 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "GeoTIFF" );
9829 561 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_gtiff.html" );
9830 561 : poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/tiff" );
9831 561 : poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "tif" );
9832 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
9833 : "Byte UInt16 Int16 UInt32 Int32 Float32 "
9834 561 : "Float64 CInt16 CInt32 CFloat32 CFloat64" );
9835 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
9836 561 : szCreateOptions );
9837 :
9838 561 : poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
9839 :
9840 561 : poDriver->pfnOpen = GTiffDataset::Open;
9841 561 : poDriver->pfnCreate = GTiffDataset::Create;
9842 561 : poDriver->pfnCreateCopy = GTiffDataset::CreateCopy;
9843 561 : poDriver->pfnUnloadDriver = GDALDeregister_GTiff;
9844 561 : poDriver->pfnIdentify = GTiffDataset::Identify;
9845 :
9846 561 : GetGDALDriverManager()->RegisterDriver( poDriver );
9847 : }
9848 582 : }
|