1 : /******************************************************************************
2 : * $Id: geotiff.cpp 24277 2012-04-21 14:03:31Z 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 24277 2012-04-21 14:03:31Z 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 24 : GDALOverviewDS::GDALOverviewDS(GDALDataset* poDS, int nOvrLevel)
105 : {
106 24 : this->poDS = poDS;
107 24 : this->nOvrLevel = nOvrLevel;
108 24 : eAccess = poDS->GetAccess();
109 24 : nRasterXSize = poDS->GetRasterBand(1)->GetOverview(nOvrLevel)->GetXSize();
110 24 : nRasterYSize = poDS->GetRasterBand(1)->GetOverview(nOvrLevel)->GetYSize();
111 24 : poOvrDS = poDS->GetRasterBand(1)->GetOverview(nOvrLevel)->GetDataset();
112 24 : nBands = poDS->GetRasterCount();
113 : int i;
114 52 : for(i=0;i<nBands;i++)
115 28 : SetBand(i+1, new GDALOverviewBand(this, i+1));
116 24 : }
117 :
118 24 : GDALOverviewDS::~GDALOverviewDS()
119 : {
120 24 : FlushCache();
121 24 : }
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 60 : const char *GDALOverviewDS::GetMetadataItem( const char * pszName, const char * pszDomain )
132 : {
133 60 : if (poOvrDS != NULL)
134 60 : return poOvrDS->GetMetadataItem(pszName, pszDomain);
135 :
136 0 : return poDS->GetMetadataItem(pszName, pszDomain);
137 : }
138 :
139 28 : GDALOverviewBand::GDALOverviewBand(GDALOverviewDS* poDS, int nBand)
140 : {
141 28 : this->poDS = poDS;
142 28 : this->nBand = nBand;
143 28 : poUnderlyingBand = poDS->poDS->GetRasterBand(nBand)->GetOverview(poDS->nOvrLevel);
144 28 : nRasterXSize = poDS->nRasterXSize;
145 28 : nRasterYSize = poDS->nRasterYSize;
146 28 : eDataType = poUnderlyingBand->GetRasterDataType();
147 28 : poUnderlyingBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
148 28 : }
149 :
150 28 : GDALOverviewBand::~GDALOverviewBand()
151 : {
152 28 : FlushCache();
153 28 : }
154 :
155 100 : GDALRasterBand* GDALOverviewBand::RefUnderlyingRasterBand()
156 : {
157 100 : return poUnderlyingBand;
158 : }
159 :
160 : /************************************************************************/
161 : /* IsPowerOfTwo() */
162 : /************************************************************************/
163 :
164 318 : static int IsPowerOfTwo(unsigned int i)
165 : {
166 318 : int nBitSet = 0;
167 3188 : while(i != 0)
168 : {
169 2552 : if ((i & 1))
170 318 : nBitSet ++;
171 2552 : i >>= 1;
172 : }
173 318 : return nBitSet == 1;
174 : }
175 :
176 : /************************************************************************/
177 : /* GTIFFGetOverviewBlockSize() */
178 : /************************************************************************/
179 :
180 318 : void GTIFFGetOverviewBlockSize(int* pnBlockXSize, int* pnBlockYSize)
181 : {
182 : static int bHasWarned = FALSE;
183 318 : const char* pszVal = CPLGetConfigOption("GDAL_TIFF_OVR_BLOCKSIZE", "128");
184 318 : int nOvrBlockSize = atoi(pszVal);
185 318 : 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 318 : *pnBlockXSize = nOvrBlockSize;
200 318 : *pnBlockYSize = nOvrBlockSize;
201 318 : }
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 :
266 : void LookForProjection();
267 : #ifdef ESRI_BUILD
268 : void AdjustLinearUnit( short UOMLength );
269 : #endif
270 :
271 : double adfGeoTransform[6];
272 : int bGeoTransformValid;
273 :
274 : int bTreatAsRGBA;
275 : int bCrystalized;
276 :
277 : void Crystalize();
278 :
279 : GDALColorTable *poColorTable;
280 :
281 : void WriteGeoTIFFInfo();
282 : int SetDirectory( toff_t nDirOffset = 0 );
283 :
284 : int nOverviewCount;
285 : GTiffDataset **papoOverviewDS;
286 :
287 : int nGCPCount;
288 : GDAL_GCP *pasGCPList;
289 :
290 : int IsBlockAvailable( int nBlockId );
291 :
292 : int bGeoTIFFInfoChanged;
293 : int bNoDataSet;
294 : double dfNoDataValue;
295 :
296 : int bMetadataChanged;
297 :
298 : int bNeedsRewrite;
299 :
300 : void ApplyPamInfo();
301 : void PushMetadataToPam();
302 :
303 : GDALMultiDomainMetadata oGTiffMDMD;
304 :
305 : CPLString osProfile;
306 : char **papszCreationOptions;
307 :
308 : int bLoadingOtherBands;
309 :
310 : static void WriteRPCTag( TIFF *, char ** );
311 : void ReadRPCTag();
312 :
313 : void* pabyTempWriteBuffer;
314 : int nTempWriteBufferSize;
315 : int WriteEncodedTile(uint32 tile, GByte* pabyData, int bPreserveDataBuffer);
316 : int WriteEncodedStrip(uint32 strip, GByte* pabyData, int bPreserveDataBuffer);
317 :
318 : GTiffDataset* poMaskDS;
319 : GTiffDataset* poBaseDS;
320 :
321 : CPLString osFilename;
322 :
323 : int bFillEmptyTiles;
324 : void FillEmptyTiles(void);
325 :
326 : void FlushDirectory();
327 : CPLErr CleanOverviews();
328 :
329 : /* Used for the all-in-on-strip case */
330 : int nLastLineRead;
331 : int nLastBandRead;
332 : int bTreatAsSplit;
333 : int bTreatAsSplitBitmap;
334 :
335 : int bClipWarn;
336 :
337 : CPLString osRPBFile;
338 : int FindRPBFile();
339 : CPLString osRPCFile;
340 : int FindRPCFile();
341 : CPLString osIMDFile;
342 : int FindIMDFile();
343 : CPLString osPVLFile;
344 : int FindPVLFile();
345 : int bHasSearchedRPC;
346 : void LoadRPCRPB();
347 : int bHasSearchedIMD;
348 : int bHasSearchedPVL;
349 : void LoadIMDPVL();
350 :
351 : int bHasWarnedDisableAggressiveBandCaching;
352 :
353 : int bDontReloadFirstBlock; /* Hack for libtiff 3.X and #3633 */
354 :
355 : int nZLevel;
356 : int nLZMAPreset;
357 : int nJpegQuality;
358 :
359 : int bPromoteTo8Bits;
360 :
361 : int bDebugDontWriteBlocks;
362 :
363 : CPLErr RegisterNewOverviewDataset(toff_t nOverviewOffset);
364 : CPLErr CreateOverviewsFromSrcOverviews(GDALDataset* poSrcDS);
365 : CPLErr CreateInternalMaskOverviews(int nOvrBlockXSize,
366 : int nOvrBlockYSize);
367 :
368 : int bIsFinalized;
369 : int Finalize();
370 :
371 : int bIgnoreReadErrors;
372 :
373 : CPLString osWldFilename;
374 :
375 : int bDirectIO;
376 :
377 : protected:
378 : virtual int CloseDependentDatasets();
379 :
380 : public:
381 : GTiffDataset();
382 : ~GTiffDataset();
383 :
384 : virtual const char *GetProjectionRef(void);
385 : virtual CPLErr SetProjection( const char * );
386 : virtual CPLErr GetGeoTransform( double * );
387 : virtual CPLErr SetGeoTransform( double * );
388 :
389 : virtual int GetGCPCount();
390 : virtual const char *GetGCPProjection();
391 : virtual const GDAL_GCP *GetGCPs();
392 : CPLErr SetGCPs( int, const GDAL_GCP *, const char * );
393 :
394 : virtual char **GetFileList(void);
395 :
396 : virtual CPLErr IBuildOverviews( const char *, int, int *, int, int *,
397 : GDALProgressFunc, void * );
398 :
399 : CPLErr OpenOffset( TIFF *, GTiffDataset **ppoActiveDSRef,
400 : toff_t nDirOffset, int bBaseIn, GDALAccess,
401 : int bAllowRGBAInterface = TRUE, int bReadGeoTransform = FALSE,
402 : char** papszSiblingFiles = NULL);
403 :
404 : static GDALDataset *OpenDir( GDALOpenInfo * );
405 : static GDALDataset *Open( GDALOpenInfo * );
406 : static int Identify( GDALOpenInfo * );
407 : static GDALDataset *Create( const char * pszFilename,
408 : int nXSize, int nYSize, int nBands,
409 : GDALDataType eType, char ** papszParmList );
410 : static GDALDataset *CreateCopy( const char * pszFilename,
411 : GDALDataset *poSrcDS,
412 : int bStrict, char ** papszOptions,
413 : GDALProgressFunc pfnProgress,
414 : void * pProgressData );
415 : virtual void FlushCache( void );
416 :
417 : virtual CPLErr SetMetadata( char **, const char * = "" );
418 : virtual char **GetMetadata( const char * pszDomain = "" );
419 : virtual CPLErr SetMetadataItem( const char*, const char*,
420 : const char* = "" );
421 : virtual const char *GetMetadataItem( const char * pszName,
422 : const char * pszDomain = "" );
423 : virtual void *GetInternalHandle( const char * );
424 :
425 : virtual CPLErr CreateMaskBand( int nFlags );
426 :
427 : // only needed by createcopy and close code.
428 : static int WriteMetadata( GDALDataset *, TIFF *, int, const char *,
429 : const char *, char **, int bExcludeRPBandIMGFileWriting = FALSE );
430 : static void WriteNoDataValue( TIFF *, double );
431 :
432 : static TIFF * CreateLL( const char * pszFilename,
433 : int nXSize, int nYSize, int nBands,
434 : GDALDataType eType,
435 : double dfExtraSpaceForOverviews,
436 : char **papszParmList );
437 :
438 : CPLErr WriteEncodedTileOrStrip(uint32 tile_or_strip, void* data, int bPreserveDataBuffer);
439 : };
440 :
441 : /************************************************************************/
442 : /* GTIFFSetJpegQuality() */
443 : /* Called by GTIFFBuildOverviews() to set the jpeg quality on the IFD */
444 : /* of the .ovr file */
445 : /************************************************************************/
446 :
447 8 : void GTIFFSetJpegQuality(GDALDatasetH hGTIFFDS, int nJpegQuality)
448 : {
449 8 : CPLAssert(EQUAL(GDALGetDriverShortName(GDALGetDatasetDriver(hGTIFFDS)), "GTIFF"));
450 :
451 8 : GTiffDataset* poDS = (GTiffDataset*)hGTIFFDS;
452 8 : poDS->nJpegQuality = nJpegQuality;
453 :
454 8 : poDS->ScanDirectories();
455 :
456 : int i;
457 14 : for(i=0;i<poDS->nOverviewCount;i++)
458 6 : poDS->papoOverviewDS[i]->nJpegQuality = nJpegQuality;
459 8 : }
460 :
461 : /************************************************************************/
462 : /* ==================================================================== */
463 : /* GTiffRasterBand */
464 : /* ==================================================================== */
465 : /************************************************************************/
466 :
467 : class GTiffRasterBand : public GDALPamRasterBand
468 799660 : {
469 : friend class GTiffDataset;
470 :
471 : GDALColorInterp eBandInterp;
472 :
473 : int bHaveOffsetScale;
474 : double dfOffset;
475 : double dfScale;
476 : CPLString osUnitType;
477 :
478 : CPLErr DirectIO( GDALRWFlag eRWFlag,
479 : int nXOff, int nYOff, int nXSize, int nYSize,
480 : void * pData, int nBufXSize, int nBufYSize,
481 : GDALDataType eBufType,
482 : int nPixelSpace, int nLineSpace );
483 :
484 : protected:
485 : GTiffDataset *poGDS;
486 : GDALMultiDomainMetadata oGTiffMDMD;
487 :
488 : int bNoDataSet;
489 : double dfNoDataValue;
490 :
491 : void NullBlock( void *pData );
492 : CPLErr FillCacheForOtherBands( int nBlockXOff, int nBlockYOff );
493 :
494 : public:
495 : GTiffRasterBand( GTiffDataset *, int );
496 :
497 : virtual CPLErr IReadBlock( int, int, void * );
498 : virtual CPLErr IWriteBlock( int, int, void * );
499 :
500 : virtual CPLErr IRasterIO( GDALRWFlag eRWFlag,
501 : int nXOff, int nYOff, int nXSize, int nYSize,
502 : void * pData, int nBufXSize, int nBufYSize,
503 : GDALDataType eBufType,
504 : int nPixelSpace, int nLineSpace );
505 :
506 : virtual GDALColorInterp GetColorInterpretation();
507 : virtual GDALColorTable *GetColorTable();
508 : virtual CPLErr SetColorTable( GDALColorTable * );
509 : virtual double GetNoDataValue( int * );
510 : virtual CPLErr SetNoDataValue( double );
511 :
512 : virtual double GetOffset( int *pbSuccess = NULL );
513 : virtual CPLErr SetOffset( double dfNewValue );
514 : virtual double GetScale( int *pbSuccess = NULL );
515 : virtual CPLErr SetScale( double dfNewValue );
516 : virtual const char* GetUnitType();
517 : virtual CPLErr SetUnitType( const char *pszNewValue );
518 : virtual CPLErr SetColorInterpretation( GDALColorInterp );
519 :
520 : virtual CPLErr SetMetadata( char **, const char * = "" );
521 : virtual char **GetMetadata( const char * pszDomain = "" );
522 : virtual CPLErr SetMetadataItem( const char*, const char*,
523 : const char* = "" );
524 : virtual const char *GetMetadataItem( const char * pszName,
525 : const char * pszDomain = "" );
526 : virtual int GetOverviewCount();
527 : virtual GDALRasterBand *GetOverview( int );
528 :
529 : virtual GDALRasterBand *GetMaskBand();
530 : virtual int GetMaskFlags();
531 : virtual CPLErr CreateMaskBand( int nFlags );
532 : };
533 :
534 : /************************************************************************/
535 : /* GTiffRasterBand() */
536 : /************************************************************************/
537 :
538 799660 : GTiffRasterBand::GTiffRasterBand( GTiffDataset *poDS, int nBand )
539 :
540 : {
541 799660 : poGDS = poDS;
542 :
543 799660 : this->poDS = poDS;
544 799660 : this->nBand = nBand;
545 :
546 799660 : bHaveOffsetScale = FALSE;
547 799660 : dfOffset = 0.0;
548 799660 : dfScale = 1.0;
549 :
550 : /* -------------------------------------------------------------------- */
551 : /* Get the GDAL data type. */
552 : /* -------------------------------------------------------------------- */
553 799660 : uint16 nSampleFormat = poDS->nSampleFormat;
554 :
555 799660 : eDataType = GDT_Unknown;
556 :
557 799660 : if( poDS->nBitsPerSample <= 8 )
558 : {
559 794200 : eDataType = GDT_Byte;
560 794200 : if( nSampleFormat == SAMPLEFORMAT_INT )
561 18 : SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE", "IMAGE_STRUCTURE" );
562 :
563 : }
564 5460 : else if( poDS->nBitsPerSample <= 16 )
565 : {
566 1286 : if( nSampleFormat == SAMPLEFORMAT_INT )
567 542 : eDataType = GDT_Int16;
568 : else
569 744 : eDataType = GDT_UInt16;
570 : }
571 4174 : else if( poDS->nBitsPerSample == 32 )
572 : {
573 2306 : if( nSampleFormat == SAMPLEFORMAT_COMPLEXINT )
574 380 : eDataType = GDT_CInt16;
575 1926 : else if( nSampleFormat == SAMPLEFORMAT_IEEEFP )
576 1004 : eDataType = GDT_Float32;
577 922 : else if( nSampleFormat == SAMPLEFORMAT_INT )
578 462 : eDataType = GDT_Int32;
579 : else
580 460 : eDataType = GDT_UInt32;
581 : }
582 1868 : else if( poDS->nBitsPerSample == 64 )
583 : {
584 1322 : if( nSampleFormat == SAMPLEFORMAT_IEEEFP )
585 538 : eDataType = GDT_Float64;
586 784 : else if( nSampleFormat == SAMPLEFORMAT_COMPLEXIEEEFP )
587 406 : eDataType = GDT_CFloat32;
588 378 : else if( nSampleFormat == SAMPLEFORMAT_COMPLEXINT )
589 378 : eDataType = GDT_CInt32;
590 : }
591 546 : else if( poDS->nBitsPerSample == 128 )
592 : {
593 410 : if( nSampleFormat == SAMPLEFORMAT_COMPLEXIEEEFP )
594 410 : eDataType = GDT_CFloat64;
595 : }
596 :
597 : /* -------------------------------------------------------------------- */
598 : /* Try to work out band color interpretation. */
599 : /* -------------------------------------------------------------------- */
600 799660 : int bLookForExtraSamples = FALSE;
601 :
602 799836 : if( poDS->poColorTable != NULL && nBand == 1 )
603 176 : eBandInterp = GCI_PaletteIndex;
604 799484 : else if( poDS->nPhotometric == PHOTOMETRIC_RGB
605 : || (poDS->nPhotometric == PHOTOMETRIC_YCBCR
606 : && poDS->nCompression == COMPRESSION_JPEG
607 : && CSLTestBoolean( CPLGetConfigOption("CONVERT_YCBCR_TO_RGB",
608 : "YES") )) )
609 : {
610 3232 : if( nBand == 1 )
611 1014 : eBandInterp = GCI_RedBand;
612 2218 : else if( nBand == 2 )
613 1014 : eBandInterp = GCI_GreenBand;
614 1204 : else if( nBand == 3 )
615 1014 : eBandInterp = GCI_BlueBand;
616 : else
617 190 : bLookForExtraSamples = TRUE;
618 : }
619 796252 : else if( poDS->nPhotometric == PHOTOMETRIC_YCBCR )
620 : {
621 8 : if( nBand == 1 )
622 2 : eBandInterp = GCI_YCbCr_YBand;
623 6 : else if( nBand == 2 )
624 2 : eBandInterp = GCI_YCbCr_CbBand;
625 4 : else if( nBand == 3 )
626 2 : eBandInterp = GCI_YCbCr_CrBand;
627 : else
628 2 : bLookForExtraSamples = TRUE;
629 : }
630 796244 : else if( poDS->nPhotometric == PHOTOMETRIC_SEPARATED )
631 : {
632 80 : if( nBand == 1 )
633 20 : eBandInterp = GCI_CyanBand;
634 60 : else if( nBand == 2 )
635 20 : eBandInterp = GCI_MagentaBand;
636 40 : else if( nBand == 3 )
637 20 : eBandInterp = GCI_YellowBand;
638 20 : else if( nBand == 4 )
639 20 : eBandInterp = GCI_BlackBand;
640 : else
641 0 : bLookForExtraSamples = TRUE;
642 : }
643 804914 : else if( poDS->nPhotometric == PHOTOMETRIC_MINISBLACK && nBand == 1 )
644 8750 : eBandInterp = GCI_GrayIndex;
645 : else
646 787414 : bLookForExtraSamples = TRUE;
647 :
648 799660 : if( bLookForExtraSamples )
649 : {
650 : uint16 *v;
651 787606 : uint16 count = 0;
652 :
653 787606 : if( TIFFGetField( poDS->hTIFF, TIFFTAG_EXTRASAMPLES, &count, &v ) )
654 : {
655 : int nBaseSamples;
656 787266 : nBaseSamples = poDS->nSamplesPerPixel - count;
657 :
658 2361804 : if( nBand > nBaseSamples
659 787266 : && (v[nBand-nBaseSamples-1] == EXTRASAMPLE_ASSOCALPHA
660 787088 : || v[nBand-nBaseSamples-1] == EXTRASAMPLE_UNASSALPHA) )
661 184 : eBandInterp = GCI_AlphaBand;
662 : else
663 787082 : eBandInterp = GCI_Undefined;
664 : }
665 : else
666 340 : eBandInterp = GCI_Undefined;
667 : }
668 :
669 : /* -------------------------------------------------------------------- */
670 : /* Establish block size for strip or tiles. */
671 : /* -------------------------------------------------------------------- */
672 799660 : nBlockXSize = poDS->nBlockXSize;
673 799660 : nBlockYSize = poDS->nBlockYSize;
674 :
675 799660 : bNoDataSet = FALSE;
676 799660 : dfNoDataValue = -9999.0;
677 799660 : }
678 :
679 : /************************************************************************/
680 : /* DirectIO() */
681 : /************************************************************************/
682 :
683 : /* Reads directly bytes from the file using ReadMultiRange(), and by-pass */
684 : /* block reading. Restricted to simple TIFF configurations (un-tiled, */
685 : /* uncompressed data, standard data types). Particularly usefull to extract */
686 : /* sub-windows of data on a large /vsicurl dataset). */
687 :
688 2 : CPLErr GTiffRasterBand::DirectIO( GDALRWFlag eRWFlag,
689 : int nXOff, int nYOff, int nXSize, int nYSize,
690 : void * pData, int nBufXSize, int nBufYSize,
691 : GDALDataType eBufType,
692 : int nPixelSpace, int nLineSpace )
693 : {
694 2 : if( !(eRWFlag == GF_Read &&
695 : poGDS->nCompression == COMPRESSION_NONE &&
696 : (poGDS->nPhotometric == PHOTOMETRIC_MINISBLACK ||
697 : poGDS->nPhotometric == PHOTOMETRIC_RGB ||
698 : poGDS->nPhotometric == PHOTOMETRIC_PALETTE) &&
699 : (poGDS->nBitsPerSample == 8 || (poGDS->nBitsPerSample == 16) ||
700 : poGDS->nBitsPerSample == 32 || poGDS->nBitsPerSample == 64) &&
701 : poGDS->nBitsPerSample == GDALGetDataTypeSize(eDataType) &&
702 : !TIFFIsTiled( poGDS->hTIFF )) )
703 : {
704 0 : return CE_Failure;
705 : }
706 :
707 : /*CPLDebug("GTiff", "DirectIO(%d,%d,%d,%d -> %dx%d)",
708 : nXOff, nYOff, nXSize, nYSize,
709 : nBufXSize, nBufYSize);*/
710 :
711 : /* ==================================================================== */
712 : /* Do we have overviews that would be appropriate to satisfy */
713 : /* this request? */
714 : /* ==================================================================== */
715 4 : if( (nBufXSize < nXSize || nBufYSize < nYSize)
716 2 : && GetOverviewCount() > 0 && eRWFlag == GF_Read )
717 : {
718 : int nOverview;
719 :
720 : nOverview =
721 : GDALBandGetBestOverviewLevel(this, nXOff, nYOff, nXSize, nYSize,
722 0 : nBufXSize, nBufYSize);
723 0 : if (nOverview >= 0)
724 : {
725 0 : GDALRasterBand* poOverviewBand = GetOverview(nOverview);
726 0 : if (poOverviewBand == NULL)
727 0 : return CE_Failure;
728 :
729 : return poOverviewBand->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
730 : pData, nBufXSize, nBufYSize, eBufType,
731 0 : nPixelSpace, nLineSpace );
732 : }
733 : }
734 :
735 : /* Make sure that TIFFTAG_STRIPOFFSETS is up-to-date */
736 2 : if (poGDS->GetAccess() == GA_Update)
737 0 : poGDS->FlushCache();
738 :
739 : /* Get strip offsets */
740 2 : toff_t *panTIFFOffsets = NULL;
741 2 : if ( !TIFFGetField( poGDS->hTIFF, TIFFTAG_STRIPOFFSETS, &panTIFFOffsets ) ||
742 : panTIFFOffsets == NULL )
743 : {
744 0 : return CE_Failure;
745 : }
746 :
747 : int iLine;
748 2 : int nReqXSize = nXSize; /* sub-sampling or over-sampling can only be done at last stage */
749 2 : int nReqYSize = MIN(nBufYSize, nYSize); /* we can do sub-sampling at the extraction stage */
750 2 : void** ppData = (void**) VSIMalloc(nReqYSize * sizeof(void*));
751 : vsi_l_offset* panOffsets = (vsi_l_offset*)
752 2 : VSIMalloc(nReqYSize * sizeof(vsi_l_offset));
753 2 : size_t* panSizes = (size_t*) VSIMalloc(nReqYSize * sizeof(size_t));
754 2 : int eDTSize = GDALGetDataTypeSize(eDataType) / 8;
755 2 : void* pTmpBuffer = NULL;
756 2 : CPLErr eErr = CE_None;
757 2 : int nContigBands = ((poGDS->nPlanarConfig == PLANARCONFIG_CONTIG) ? poGDS->nBands : 1);
758 2 : int ePixelSize = eDTSize * nContigBands;
759 :
760 2 : if (ppData == NULL || panOffsets == NULL || panSizes == NULL)
761 0 : eErr = CE_Failure;
762 2 : else if (nXSize != nBufXSize || nYSize != nBufYSize ||
763 : eBufType != eDataType ||
764 : nPixelSpace != GDALGetDataTypeSize(eBufType) / 8 ||
765 : nContigBands > 1)
766 : {
767 : /* We need a temporary buffer for over-sampling/sub-sampling */
768 : /* and/or data type conversion */
769 2 : pTmpBuffer = VSIMalloc(nReqXSize * nReqYSize * ePixelSize);
770 2 : if (pTmpBuffer == NULL)
771 0 : eErr = CE_Failure;
772 : }
773 :
774 : /* Prepare data extraction */
775 258 : for(iLine=0;eErr == CE_None && iLine<nReqYSize;iLine++)
776 : {
777 256 : if (pTmpBuffer == NULL)
778 0 : ppData[iLine] = ((GByte*)pData) + iLine * nLineSpace;
779 : else
780 256 : ppData[iLine] = ((GByte*)pTmpBuffer) + iLine * nReqXSize * ePixelSize;
781 : int nSrcLine;
782 256 : if (nBufYSize < nYSize) /* Sub-sampling in y */
783 256 : nSrcLine = nYOff + (int)((iLine + 0.5) * nYSize / nBufYSize);
784 : else
785 0 : nSrcLine = nYOff + iLine;
786 :
787 256 : int nBlockXOff = 0;
788 256 : int nBlockYOff = nSrcLine / nBlockYSize;
789 256 : int nYOffsetInBlock = nSrcLine % nBlockYSize;
790 256 : int nBlocksPerRow = (nRasterXSize + nBlockXSize - 1) / nBlockXSize;
791 256 : int nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
792 256 : if( poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE )
793 : {
794 0 : nBlockId += (nBand-1) * poGDS->nBlocksPerBand;
795 : }
796 :
797 256 : panOffsets[iLine] = panTIFFOffsets[nBlockId];
798 256 : if (panOffsets[iLine] == 0) /* We don't support sparse files */
799 0 : eErr = CE_Failure;
800 :
801 256 : panOffsets[iLine] += (nXOff + nYOffsetInBlock * nBlockXSize) * ePixelSize;
802 256 : panSizes[iLine] = nReqXSize * ePixelSize;
803 : }
804 :
805 : /* Extract data from the file */
806 2 : if (eErr == CE_None)
807 : {
808 2 : VSILFILE* fp = (VSILFILE*) TIFFClientdata( poGDS->hTIFF );
809 2 : int nRet = VSIFReadMultiRangeL(nReqYSize, ppData, panOffsets, panSizes, fp);
810 2 : if (nRet != 0)
811 0 : eErr = CE_Failure;
812 : }
813 :
814 : /* Byte-swap if necessary */
815 2 : if (eErr == CE_None && TIFFIsByteSwapped(poGDS->hTIFF))
816 : {
817 0 : for(iLine=0;iLine<nReqYSize;iLine++)
818 : {
819 0 : GDALSwapWords( ppData[iLine], eDTSize, nReqXSize * nContigBands, eDTSize);
820 : }
821 : }
822 :
823 : /* Over-sampling/sub-sampling and/or data type conversion */
824 2 : if (eErr == CE_None && pTmpBuffer != NULL)
825 : {
826 258 : for(int iY=0;iY<nBufYSize;iY++)
827 : {
828 : int iSrcY = (nBufYSize <= nYSize) ? iY :
829 256 : (int)((iY + 0.5) * nYSize / nBufYSize);
830 256 : if (nBufXSize == nXSize && nContigBands == 1)
831 : {
832 : GDALCopyWords( ppData[iSrcY], eDataType, eDTSize,
833 : ((GByte*)pData) + iY * nLineSpace,
834 : eBufType, nPixelSpace,
835 0 : nReqXSize);
836 : }
837 : else
838 : {
839 256 : GByte* pabySrcData = ((GByte*)ppData[iSrcY]) +
840 256 : ((nContigBands > 1) ? (nBand-1) : 0) * eDTSize;
841 256 : GByte* pabyDstData = ((GByte*)pData) + iY * nLineSpace;
842 33024 : for(int iX=0;iX<nBufXSize;iX++)
843 : {
844 : int iSrcX = (nBufXSize == nXSize) ? iX :
845 32768 : (int)((iX+0.5) * nXSize / nBufXSize);
846 : GDALCopyWords( pabySrcData + iSrcX * ePixelSize,
847 : eDataType, 0,
848 : pabyDstData + iX * nPixelSpace,
849 32768 : eBufType, 0, 1);
850 : }
851 : }
852 : }
853 : }
854 :
855 : /* Cleanup */
856 2 : CPLFree(pTmpBuffer);
857 2 : CPLFree(ppData);
858 2 : CPLFree(panOffsets);
859 2 : CPLFree(panSizes);
860 :
861 2 : return eErr;
862 : }
863 :
864 : /************************************************************************/
865 : /* IRasterIO() */
866 : /************************************************************************/
867 :
868 1432778 : CPLErr GTiffRasterBand::IRasterIO( GDALRWFlag eRWFlag,
869 : int nXOff, int nYOff, int nXSize, int nYSize,
870 : void * pData, int nBufXSize, int nBufYSize,
871 : GDALDataType eBufType,
872 : int nPixelSpace, int nLineSpace )
873 : {
874 : CPLErr eErr;
875 :
876 : //CPLDebug("GTiff", "RasterIO(%d, %d, %d, %d, %d, %d)",
877 : // nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize);
878 :
879 1432778 : if (poGDS->bDirectIO)
880 : {
881 : eErr = DirectIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
882 : pData, nBufXSize, nBufYSize, eBufType,
883 2 : nPixelSpace, nLineSpace);
884 :
885 2 : if (eErr == CE_None)
886 2 : return eErr;
887 : }
888 :
889 1432776 : if (poGDS->nBands != 1 &&
890 : poGDS->nPlanarConfig == PLANARCONFIG_CONTIG &&
891 : eRWFlag == GF_Read &&
892 : nXSize == nBufXSize && nYSize == nBufYSize)
893 : {
894 326722 : int nBlockX1 = nXOff / nBlockXSize;
895 326722 : int nBlockY1 = nYOff / nBlockYSize;
896 326722 : int nBlockX2 = (nXOff + nXSize - 1) / nBlockXSize;
897 326722 : int nBlockY2 = (nYOff + nYSize - 1) / nBlockYSize;
898 326722 : int nXBlocks = nBlockX2 - nBlockX1 + 1;
899 326722 : int nYBlocks = nBlockY2 - nBlockY1 + 1;
900 : GIntBig nRequiredMem = (GIntBig)poGDS->nBands * nXBlocks * nYBlocks *
901 : nBlockXSize * nBlockYSize *
902 326722 : (GDALGetDataTypeSize(eDataType) / 8);
903 326722 : if (nRequiredMem > GDALGetCacheMax64())
904 : {
905 42 : if (!poGDS->bHasWarnedDisableAggressiveBandCaching)
906 : {
907 : CPLDebug("GTiff", "Disable aggressive band caching. Cache not big enough. "
908 2 : "At least " CPL_FRMT_GIB " bytes necessary", nRequiredMem);
909 2 : poGDS->bHasWarnedDisableAggressiveBandCaching = TRUE;
910 : }
911 42 : poGDS->bLoadingOtherBands = TRUE;
912 : }
913 : }
914 :
915 : eErr = GDALPamRasterBand::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
916 : pData, nBufXSize, nBufYSize, eBufType,
917 1432776 : nPixelSpace, nLineSpace);
918 :
919 1432776 : poGDS->bLoadingOtherBands = FALSE;
920 :
921 1432776 : return eErr;
922 : }
923 :
924 : /************************************************************************/
925 : /* IReadBlock() */
926 : /************************************************************************/
927 :
928 196158 : CPLErr GTiffRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
929 : void * pImage )
930 :
931 : {
932 : int nBlockBufSize, nBlockId, nBlockIdBand0;
933 196158 : CPLErr eErr = CE_None;
934 :
935 196158 : if (!poGDS->SetDirectory())
936 0 : return CE_Failure;
937 :
938 196158 : if( TIFFIsTiled(poGDS->hTIFF) )
939 26938 : nBlockBufSize = TIFFTileSize( poGDS->hTIFF );
940 : else
941 : {
942 169220 : CPLAssert( nBlockXOff == 0 );
943 169220 : nBlockBufSize = TIFFStripSize( poGDS->hTIFF );
944 : }
945 :
946 196158 : CPLAssert(nBlocksPerRow != 0);
947 196158 : nBlockIdBand0 = nBlockXOff + nBlockYOff * nBlocksPerRow;
948 196158 : if( poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE )
949 2242 : nBlockId = nBlockIdBand0 + (nBand-1) * poGDS->nBlocksPerBand;
950 : else
951 193916 : nBlockId = nBlockIdBand0;
952 :
953 : /* -------------------------------------------------------------------- */
954 : /* The bottom most partial tiles and strips are sometimes only */
955 : /* partially encoded. This code reduces the requested data so */
956 : /* an error won't be reported in this case. (#1179) */
957 : /* -------------------------------------------------------------------- */
958 196158 : int nBlockReqSize = nBlockBufSize;
959 :
960 196158 : if( (nBlockYOff+1) * nBlockYSize > nRasterYSize )
961 : {
962 : nBlockReqSize = (nBlockBufSize / nBlockYSize)
963 3082 : * (nBlockYSize - (((nBlockYOff+1) * nBlockYSize) % nRasterYSize));
964 : }
965 :
966 : /* -------------------------------------------------------------------- */
967 : /* Handle the case of a strip or tile that doesn't exist yet. */
968 : /* Just set to zeros and return. */
969 : /* -------------------------------------------------------------------- */
970 196158 : if( !poGDS->IsBlockAvailable(nBlockId) )
971 : {
972 26346 : NullBlock( pImage );
973 26346 : return CE_None;
974 : }
975 :
976 : /* -------------------------------------------------------------------- */
977 : /* Handle simple case (separate, onesampleperpixel) */
978 : /* -------------------------------------------------------------------- */
979 169812 : if( poGDS->nBands == 1
980 : || poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE )
981 : {
982 26258 : if( nBlockReqSize < nBlockBufSize )
983 844 : memset( pImage, 0, nBlockBufSize );
984 :
985 26258 : if( TIFFIsTiled( poGDS->hTIFF ) )
986 : {
987 17136 : if( TIFFReadEncodedTile( poGDS->hTIFF, nBlockId, pImage,
988 : nBlockReqSize ) == -1
989 : && !poGDS->bIgnoreReadErrors )
990 : {
991 2 : memset( pImage, 0, nBlockBufSize );
992 : CPLError( CE_Failure, CPLE_AppDefined,
993 2 : "TIFFReadEncodedTile() failed.\n" );
994 :
995 2 : eErr = CE_Failure;
996 : }
997 : }
998 : else
999 : {
1000 9122 : if( TIFFReadEncodedStrip( poGDS->hTIFF, nBlockId, pImage,
1001 : nBlockReqSize ) == -1
1002 : && !poGDS->bIgnoreReadErrors )
1003 : {
1004 2 : memset( pImage, 0, nBlockBufSize );
1005 : CPLError( CE_Failure, CPLE_AppDefined,
1006 2 : "TIFFReadEncodedStrip() failed.\n" );
1007 :
1008 2 : eErr = CE_Failure;
1009 : }
1010 : }
1011 :
1012 26258 : return eErr;
1013 : }
1014 :
1015 : /* -------------------------------------------------------------------- */
1016 : /* Load desired block */
1017 : /* -------------------------------------------------------------------- */
1018 143554 : eErr = poGDS->LoadBlockBuf( nBlockId );
1019 143554 : if( eErr != CE_None )
1020 : {
1021 : memset( pImage, 0,
1022 : nBlockXSize * nBlockYSize
1023 0 : * (GDALGetDataTypeSize(eDataType) / 8) );
1024 0 : return eErr;
1025 : }
1026 :
1027 : /* -------------------------------------------------------------------- */
1028 : /* Special case for YCbCr subsampled data. */
1029 : /* -------------------------------------------------------------------- */
1030 : #ifdef notdef
1031 : if( (eBandInterp == GCI_YCbCr_YBand
1032 : || eBandInterp == GCI_YCbCr_CbBand
1033 : || eBandInterp == GCI_YCbCr_CrBand)
1034 : && poGDS->nBitsPerSample == 8 )
1035 : {
1036 : uint16 hs, vs;
1037 : int iX, iY;
1038 :
1039 : TIFFGetFieldDefaulted( poGDS->hTIFF, TIFFTAG_YCBCRSUBSAMPLING,
1040 : &hs, &vs);
1041 :
1042 : for( iY = 0; iY < nBlockYSize; iY++ )
1043 : {
1044 : for( iX = 0; iX < nBlockXSize; iX++ )
1045 : {
1046 : int iBlock = (iY / vs) * (nBlockXSize/hs) + (iX / hs);
1047 : GByte *pabySrcBlock = poGDS->pabyBlockBuf +
1048 : (vs * hs + 2) * iBlock;
1049 :
1050 : if( eBandInterp == GCI_YCbCr_YBand )
1051 : ((GByte *)pImage)[iY*nBlockXSize + iX] =
1052 : pabySrcBlock[(iX % hs) + (iY % vs) * hs];
1053 : else if( eBandInterp == GCI_YCbCr_CbBand )
1054 : ((GByte *)pImage)[iY*nBlockXSize + iX] =
1055 : pabySrcBlock[vs * hs + 0];
1056 : else if( eBandInterp == GCI_YCbCr_CrBand )
1057 : ((GByte *)pImage)[iY*nBlockXSize + iX] =
1058 : pabySrcBlock[vs * hs + 1];
1059 : }
1060 : }
1061 :
1062 : return CE_None;
1063 : }
1064 : #endif
1065 :
1066 : /* -------------------------------------------------------------------- */
1067 : /* Handle simple case of eight bit data, and pixel interleaving. */
1068 : /* -------------------------------------------------------------------- */
1069 143554 : if( poGDS->nBitsPerSample == 8 )
1070 : {
1071 : int i, nBlockPixels;
1072 : GByte *pabyImage;
1073 143366 : GByte *pabyImageDest = (GByte*)pImage;
1074 143366 : int nBands = poGDS->nBands;
1075 :
1076 143366 : pabyImage = poGDS->pabyBlockBuf + nBand - 1;
1077 :
1078 143366 : nBlockPixels = nBlockXSize * nBlockYSize;
1079 :
1080 : /* ==================================================================== */
1081 : /* Optimization for high number of words to transfer and some */
1082 : /* typical band numbers : we unroll the loop. */
1083 : /* ==================================================================== */
1084 : #define COPY_TO_DST_BUFFER(nBands) \
1085 : if (nBlockPixels > 100) \
1086 : { \
1087 : for ( i = nBlockPixels / 16; i != 0; i -- ) \
1088 : { \
1089 : pabyImageDest[0] = pabyImage[0*nBands]; \
1090 : pabyImageDest[1] = pabyImage[1*nBands]; \
1091 : pabyImageDest[2] = pabyImage[2*nBands]; \
1092 : pabyImageDest[3] = pabyImage[3*nBands]; \
1093 : pabyImageDest[4] = pabyImage[4*nBands]; \
1094 : pabyImageDest[5] = pabyImage[5*nBands]; \
1095 : pabyImageDest[6] = pabyImage[6*nBands]; \
1096 : pabyImageDest[7] = pabyImage[7*nBands]; \
1097 : pabyImageDest[8] = pabyImage[8*nBands]; \
1098 : pabyImageDest[9] = pabyImage[9*nBands]; \
1099 : pabyImageDest[10] = pabyImage[10*nBands]; \
1100 : pabyImageDest[11] = pabyImage[11*nBands]; \
1101 : pabyImageDest[12] = pabyImage[12*nBands]; \
1102 : pabyImageDest[13] = pabyImage[13*nBands]; \
1103 : pabyImageDest[14] = pabyImage[14*nBands]; \
1104 : pabyImageDest[15] = pabyImage[15*nBands]; \
1105 : pabyImageDest += 16; \
1106 : pabyImage += 16*nBands; \
1107 : } \
1108 : nBlockPixels = nBlockPixels % 16; \
1109 : } \
1110 : for( i = 0; i < nBlockPixels; i++ ) \
1111 : { \
1112 : pabyImageDest[i] = *pabyImage; \
1113 : pabyImage += nBands; \
1114 : }
1115 :
1116 143366 : switch (nBands)
1117 : {
1118 8990 : case 3: COPY_TO_DST_BUFFER(3); break;
1119 3168 : case 4: COPY_TO_DST_BUFFER(4); break;
1120 : default:
1121 : {
1122 1015866 : for( i = 0; i < nBlockPixels; i++ )
1123 : {
1124 884658 : pabyImageDest[i] = *pabyImage;
1125 884658 : pabyImage += nBands;
1126 : }
1127 : }
1128 : }
1129 : #undef COPY_TO_DST_BUFFER
1130 : }
1131 :
1132 : else
1133 : {
1134 : int i, nBlockPixels, nWordBytes;
1135 : GByte *pabyImage;
1136 :
1137 188 : nWordBytes = poGDS->nBitsPerSample / 8;
1138 188 : pabyImage = poGDS->pabyBlockBuf + (nBand - 1) * nWordBytes;
1139 :
1140 188 : nBlockPixels = nBlockXSize * nBlockYSize;
1141 1103644 : for( i = 0; i < nBlockPixels; i++ )
1142 : {
1143 5510880 : for( int j = 0; j < nWordBytes; j++ )
1144 : {
1145 4407424 : ((GByte *) pImage)[i*nWordBytes + j] = pabyImage[j];
1146 : }
1147 1103456 : pabyImage += poGDS->nBands * nWordBytes;
1148 : }
1149 : }
1150 :
1151 143554 : if (eErr == CE_None)
1152 143554 : eErr = FillCacheForOtherBands(nBlockXOff, nBlockYOff);
1153 :
1154 143554 : return eErr;
1155 : }
1156 :
1157 :
1158 : /************************************************************************/
1159 : /* FillCacheForOtherBands() */
1160 : /************************************************************************/
1161 :
1162 143586 : CPLErr GTiffRasterBand::FillCacheForOtherBands( int nBlockXOff, int nBlockYOff )
1163 :
1164 : {
1165 143586 : CPLErr eErr = CE_None;
1166 : /* -------------------------------------------------------------------- */
1167 : /* In the fairly common case of pixel interleaved 8bit data */
1168 : /* that is multi-band, lets push the rest of the data into the */
1169 : /* block cache too, to avoid (hopefully) having to redecode it. */
1170 : /* */
1171 : /* Our following logic actually depends on the fact that the */
1172 : /* this block is already loaded, so subsequent calls will end */
1173 : /* up back in this method and pull from the loaded block. */
1174 : /* */
1175 : /* Be careful not entering this portion of code from */
1176 : /* the other bands, otherwise we'll get very deep nested calls */
1177 : /* and O(nBands^2) performance ! */
1178 : /* */
1179 : /* If there are many bands and the block cache size is not big */
1180 : /* enough to accomodate the size of all the blocks, don't enter */
1181 : /* -------------------------------------------------------------------- */
1182 143586 : if( poGDS->nBands != 1 && !poGDS->bLoadingOtherBands &&
1183 : nBlockXSize * nBlockYSize * (GDALGetDataTypeSize(eDataType) / 8) < GDALGetCacheMax64() / poGDS->nBands)
1184 : {
1185 : int iOtherBand;
1186 :
1187 3928 : poGDS->bLoadingOtherBands = TRUE;
1188 :
1189 147508 : for( iOtherBand = 1; iOtherBand <= poGDS->nBands; iOtherBand++ )
1190 : {
1191 143580 : if( iOtherBand == nBand )
1192 3928 : continue;
1193 :
1194 : GDALRasterBlock *poBlock;
1195 :
1196 : poBlock = poGDS->GetRasterBand(iOtherBand)->
1197 139652 : GetLockedBlockRef(nBlockXOff,nBlockYOff);
1198 139652 : if (poBlock == NULL)
1199 : {
1200 0 : eErr = CE_Failure;
1201 0 : break;
1202 : }
1203 139652 : poBlock->DropLock();
1204 : }
1205 :
1206 3928 : poGDS->bLoadingOtherBands = FALSE;
1207 : }
1208 :
1209 143586 : return eErr;
1210 : }
1211 :
1212 : /************************************************************************/
1213 : /* IWriteBlock() */
1214 : /************************************************************************/
1215 :
1216 48430 : CPLErr GTiffRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
1217 : void * pImage )
1218 :
1219 : {
1220 : int nBlockId;
1221 48430 : CPLErr eErr = CE_None;
1222 :
1223 48430 : if (poGDS->bDebugDontWriteBlocks)
1224 14048 : return CE_None;
1225 :
1226 34382 : if (poGDS->bWriteErrorInFlushBlockBuf)
1227 : {
1228 : /* Report as an error if a previously loaded block couldn't be */
1229 : /* written correctly */
1230 0 : poGDS->bWriteErrorInFlushBlockBuf = FALSE;
1231 0 : return CE_Failure;
1232 : }
1233 :
1234 34382 : if (!poGDS->SetDirectory())
1235 0 : return CE_Failure;
1236 :
1237 : CPLAssert( poGDS != NULL
1238 : && nBlockXOff >= 0
1239 : && nBlockYOff >= 0
1240 34382 : && pImage != NULL );
1241 34382 : CPLAssert(nBlocksPerRow != 0);
1242 :
1243 : /* -------------------------------------------------------------------- */
1244 : /* Handle case of "separate" images */
1245 : /* -------------------------------------------------------------------- */
1246 34382 : if( poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE
1247 : || poGDS->nBands == 1 )
1248 : {
1249 : nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow
1250 30152 : + (nBand-1) * poGDS->nBlocksPerBand;
1251 :
1252 30152 : eErr = poGDS->WriteEncodedTileOrStrip(nBlockId, pImage, TRUE);
1253 :
1254 30152 : return eErr;
1255 : }
1256 :
1257 : /* -------------------------------------------------------------------- */
1258 : /* Handle case of pixel interleaved (PLANARCONFIG_CONTIG) images. */
1259 : /* -------------------------------------------------------------------- */
1260 4230 : nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
1261 :
1262 4230 : eErr = poGDS->LoadBlockBuf( nBlockId );
1263 4230 : if( eErr != CE_None )
1264 0 : return eErr;
1265 :
1266 : /* -------------------------------------------------------------------- */
1267 : /* On write of pixel interleaved data, we might as well flush */
1268 : /* out any other bands that are dirty in our cache. This is */
1269 : /* especially helpful when writing compressed blocks. */
1270 : /* -------------------------------------------------------------------- */
1271 : int iBand;
1272 4230 : int nWordBytes = poGDS->nBitsPerSample / 8;
1273 4230 : int nBands = poGDS->nBands;
1274 :
1275 17408 : for( iBand = 0; iBand < nBands; iBand++ )
1276 : {
1277 13178 : const GByte *pabyThisImage = NULL;
1278 13178 : GDALRasterBlock *poBlock = NULL;
1279 :
1280 13178 : if( iBand+1 == nBand )
1281 4230 : pabyThisImage = (GByte *) pImage;
1282 : else
1283 : {
1284 : poBlock = ((GTiffRasterBand *)poGDS->GetRasterBand( iBand+1 ))
1285 8948 : ->TryGetLockedBlockRef( nBlockXOff, nBlockYOff );
1286 :
1287 8948 : if( poBlock == NULL )
1288 234 : continue;
1289 :
1290 8714 : if( !poBlock->GetDirty() )
1291 : {
1292 180 : poBlock->DropLock();
1293 180 : continue;
1294 : }
1295 :
1296 8534 : pabyThisImage = (GByte *) poBlock->GetDataRef();
1297 : }
1298 :
1299 12764 : int i, nBlockPixels = nBlockXSize * nBlockYSize;
1300 12764 : GByte *pabyOut = poGDS->pabyBlockBuf + iBand*nWordBytes;
1301 :
1302 12764 : if (nWordBytes == 1)
1303 : {
1304 :
1305 : /* ==================================================================== */
1306 : /* Optimization for high number of words to transfer and some */
1307 : /* typical band numbers : we unroll the loop. */
1308 : /* ==================================================================== */
1309 : #define COPY_TO_DST_BUFFER(nBands) \
1310 : if (nBlockPixels > 100) \
1311 : { \
1312 : for ( i = nBlockPixels / 16; i != 0; i -- ) \
1313 : { \
1314 : pabyOut[0*nBands] = pabyThisImage[0]; \
1315 : pabyOut[1*nBands] = pabyThisImage[1]; \
1316 : pabyOut[2*nBands] = pabyThisImage[2]; \
1317 : pabyOut[3*nBands] = pabyThisImage[3]; \
1318 : pabyOut[4*nBands] = pabyThisImage[4]; \
1319 : pabyOut[5*nBands] = pabyThisImage[5]; \
1320 : pabyOut[6*nBands] = pabyThisImage[6]; \
1321 : pabyOut[7*nBands] = pabyThisImage[7]; \
1322 : pabyOut[8*nBands] = pabyThisImage[8]; \
1323 : pabyOut[9*nBands] = pabyThisImage[9]; \
1324 : pabyOut[10*nBands] = pabyThisImage[10]; \
1325 : pabyOut[11*nBands] = pabyThisImage[11]; \
1326 : pabyOut[12*nBands] = pabyThisImage[12]; \
1327 : pabyOut[13*nBands] = pabyThisImage[13]; \
1328 : pabyOut[14*nBands] = pabyThisImage[14]; \
1329 : pabyOut[15*nBands] = pabyThisImage[15]; \
1330 : pabyThisImage += 16; \
1331 : pabyOut += 16*nBands; \
1332 : } \
1333 : nBlockPixels = nBlockPixels % 16; \
1334 : } \
1335 : for( i = 0; i < nBlockPixels; i++ ) \
1336 : { \
1337 : *pabyOut = pabyThisImage[i]; \
1338 : pabyOut += nBands; \
1339 : }
1340 :
1341 12636 : switch (nBands)
1342 : {
1343 10540 : case 3: COPY_TO_DST_BUFFER(3); break;
1344 1978 : case 4: COPY_TO_DST_BUFFER(4); break;
1345 : default:
1346 : {
1347 461810 : for( i = 0; i < nBlockPixels; i++ )
1348 : {
1349 461692 : *pabyOut = pabyThisImage[i];
1350 461692 : pabyOut += nBands;
1351 : }
1352 : }
1353 : }
1354 : #undef COPY_TO_DST_BUFFER
1355 : }
1356 : else
1357 : {
1358 410992 : for( i = 0; i < nBlockPixels; i++ )
1359 : {
1360 410864 : memcpy( pabyOut, pabyThisImage, nWordBytes );
1361 :
1362 410864 : pabyOut += nWordBytes * nBands;
1363 410864 : pabyThisImage += nWordBytes;
1364 : }
1365 : }
1366 :
1367 12764 : if( poBlock != NULL )
1368 : {
1369 8534 : poBlock->MarkClean();
1370 8534 : poBlock->DropLock();
1371 : }
1372 : }
1373 :
1374 4230 : poGDS->bLoadedBlockDirty = TRUE;
1375 :
1376 4230 : return CE_None;
1377 : }
1378 :
1379 : /************************************************************************/
1380 : /* GetOffset() */
1381 : /************************************************************************/
1382 :
1383 267888 : double GTiffRasterBand::GetOffset( int *pbSuccess )
1384 :
1385 : {
1386 267888 : if( pbSuccess )
1387 266838 : *pbSuccess = bHaveOffsetScale;
1388 267888 : return dfOffset;
1389 : }
1390 :
1391 : /************************************************************************/
1392 : /* SetOffset() */
1393 : /************************************************************************/
1394 :
1395 20 : CPLErr GTiffRasterBand::SetOffset( double dfNewValue )
1396 :
1397 : {
1398 20 : if( !bHaveOffsetScale || dfNewValue != dfOffset )
1399 20 : poGDS->bMetadataChanged = TRUE;
1400 :
1401 20 : bHaveOffsetScale = TRUE;
1402 20 : dfOffset = dfNewValue;
1403 20 : return CE_None;
1404 : }
1405 :
1406 : /************************************************************************/
1407 : /* GetScale() */
1408 : /************************************************************************/
1409 :
1410 267888 : double GTiffRasterBand::GetScale( int *pbSuccess )
1411 :
1412 : {
1413 267888 : if( pbSuccess )
1414 1980 : *pbSuccess = bHaveOffsetScale;
1415 267888 : return dfScale;
1416 : }
1417 :
1418 : /************************************************************************/
1419 : /* SetScale() */
1420 : /************************************************************************/
1421 :
1422 20 : CPLErr GTiffRasterBand::SetScale( double dfNewValue )
1423 :
1424 : {
1425 20 : if( !bHaveOffsetScale || dfNewValue != dfScale )
1426 20 : poGDS->bMetadataChanged = TRUE;
1427 :
1428 20 : bHaveOffsetScale = TRUE;
1429 20 : dfScale = dfNewValue;
1430 20 : return CE_None;
1431 : }
1432 :
1433 : /************************************************************************/
1434 : /* GetUnitType() */
1435 : /************************************************************************/
1436 :
1437 267114 : const char* GTiffRasterBand::GetUnitType()
1438 :
1439 : {
1440 267114 : return osUnitType.c_str();
1441 : }
1442 :
1443 : /************************************************************************/
1444 : /* SetUnitType() */
1445 : /************************************************************************/
1446 :
1447 36 : CPLErr GTiffRasterBand::SetUnitType( const char* pszNewValue )
1448 :
1449 : {
1450 36 : CPLString osNewValue(pszNewValue ? pszNewValue : "");
1451 36 : if( osNewValue.compare(osUnitType) != 0 )
1452 34 : poGDS->bMetadataChanged = TRUE;
1453 :
1454 36 : osUnitType = osNewValue;
1455 36 : return CE_None;
1456 : }
1457 :
1458 : /************************************************************************/
1459 : /* GetMetadata() */
1460 : /************************************************************************/
1461 :
1462 4780 : char **GTiffRasterBand::GetMetadata( const char * pszDomain )
1463 :
1464 : {
1465 4780 : return oGTiffMDMD.GetMetadata( pszDomain );
1466 : }
1467 :
1468 : /************************************************************************/
1469 : /* SetMetadata() */
1470 : /************************************************************************/
1471 :
1472 672 : CPLErr GTiffRasterBand::SetMetadata( char ** papszMD, const char *pszDomain )
1473 :
1474 : {
1475 672 : if( pszDomain == NULL || !EQUAL(pszDomain,"_temporary_") )
1476 : {
1477 672 : if( papszMD != NULL )
1478 68 : poGDS->bMetadataChanged = TRUE;
1479 : }
1480 :
1481 672 : return oGTiffMDMD.SetMetadata( papszMD, pszDomain );
1482 : }
1483 :
1484 : /************************************************************************/
1485 : /* GetMetadataItem() */
1486 : /************************************************************************/
1487 :
1488 8712 : const char *GTiffRasterBand::GetMetadataItem( const char * pszName,
1489 : const char * pszDomain )
1490 :
1491 : {
1492 8712 : return oGTiffMDMD.GetMetadataItem( pszName, pszDomain );
1493 : }
1494 :
1495 : /************************************************************************/
1496 : /* SetMetadataItem() */
1497 : /************************************************************************/
1498 :
1499 1316 : CPLErr GTiffRasterBand::SetMetadataItem( const char *pszName,
1500 : const char *pszValue,
1501 : const char *pszDomain )
1502 :
1503 : {
1504 1316 : if( pszDomain == NULL || !EQUAL(pszDomain,"_temporary_") )
1505 1316 : poGDS->bMetadataChanged = TRUE;
1506 :
1507 1316 : return oGTiffMDMD.SetMetadataItem( pszName, pszValue, pszDomain );
1508 : }
1509 :
1510 : /************************************************************************/
1511 : /* GetColorInterpretation() */
1512 : /************************************************************************/
1513 :
1514 6818 : GDALColorInterp GTiffRasterBand::GetColorInterpretation()
1515 :
1516 : {
1517 6818 : return eBandInterp;
1518 : }
1519 :
1520 : /************************************************************************/
1521 : /* SetColorInterpretation() */
1522 : /************************************************************************/
1523 :
1524 62 : CPLErr GTiffRasterBand::SetColorInterpretation( GDALColorInterp eInterp )
1525 :
1526 : {
1527 62 : if( eInterp == eBandInterp )
1528 46 : return CE_None;
1529 :
1530 16 : if( poGDS->bCrystalized )
1531 0 : return GDALPamRasterBand::SetColorInterpretation( eInterp );
1532 :
1533 : /* greyscale + alpha */
1534 16 : else if( eInterp == GCI_AlphaBand
1535 : && nBand == 2
1536 : && poGDS->nSamplesPerPixel == 2
1537 : && poGDS->nPhotometric == PHOTOMETRIC_MINISBLACK )
1538 : {
1539 2 : uint16 v[1] = { EXTRASAMPLE_ASSOCALPHA };
1540 :
1541 2 : TIFFSetField(poGDS->hTIFF, TIFFTAG_EXTRASAMPLES, 1, v);
1542 2 : eBandInterp = eInterp;
1543 2 : return CE_None;
1544 : }
1545 :
1546 : /* RGB + alpha */
1547 14 : else if( eInterp == GCI_AlphaBand
1548 : && nBand == 4
1549 : && poGDS->nSamplesPerPixel == 4
1550 : && poGDS->nPhotometric == PHOTOMETRIC_RGB )
1551 : {
1552 2 : uint16 v[1] = { EXTRASAMPLE_ASSOCALPHA };
1553 :
1554 2 : TIFFSetField(poGDS->hTIFF, TIFFTAG_EXTRASAMPLES, 1, v);
1555 2 : eBandInterp = eInterp;
1556 2 : return CE_None;
1557 : }
1558 :
1559 : else
1560 12 : return GDALPamRasterBand::SetColorInterpretation( eInterp );
1561 : }
1562 :
1563 : /************************************************************************/
1564 : /* GetColorTable() */
1565 : /************************************************************************/
1566 :
1567 4428 : GDALColorTable *GTiffRasterBand::GetColorTable()
1568 :
1569 : {
1570 4428 : if( nBand == 1 )
1571 3604 : return poGDS->poColorTable;
1572 : else
1573 824 : return NULL;
1574 : }
1575 :
1576 : /************************************************************************/
1577 : /* SetColorTable() */
1578 : /************************************************************************/
1579 :
1580 30 : CPLErr GTiffRasterBand::SetColorTable( GDALColorTable * poCT )
1581 :
1582 : {
1583 : /* -------------------------------------------------------------------- */
1584 : /* Check if this is even a candidate for applying a PCT. */
1585 : /* -------------------------------------------------------------------- */
1586 30 : if( nBand != 1)
1587 : {
1588 : CPLError( CE_Failure, CPLE_NotSupported,
1589 0 : "SetColorTable() can only be called on band 1." );
1590 0 : return CE_Failure;
1591 : }
1592 :
1593 30 : if( poGDS->nSamplesPerPixel != 1 && poGDS->nSamplesPerPixel != 2)
1594 : {
1595 : CPLError( CE_Failure, CPLE_NotSupported,
1596 0 : "SetColorTable() not supported for multi-sample TIFF files." );
1597 0 : return CE_Failure;
1598 : }
1599 :
1600 30 : if( eDataType != GDT_Byte && eDataType != GDT_UInt16 )
1601 : {
1602 : CPLError( CE_Failure, CPLE_NotSupported,
1603 0 : "SetColorTable() only supported for Byte or UInt16 bands in TIFF format." );
1604 0 : return CE_Failure;
1605 : }
1606 :
1607 : /* -------------------------------------------------------------------- */
1608 : /* We are careful about calling SetDirectory() to avoid */
1609 : /* prematurely crystalizing the directory. (#2820) */
1610 : /* -------------------------------------------------------------------- */
1611 30 : if( poGDS->bCrystalized )
1612 : {
1613 8 : if (!poGDS->SetDirectory())
1614 0 : return CE_Failure;
1615 : }
1616 :
1617 : /* -------------------------------------------------------------------- */
1618 : /* Is this really a request to clear the color table? */
1619 : /* -------------------------------------------------------------------- */
1620 30 : if( poCT == NULL || poCT->GetColorEntryCount() == 0 )
1621 : {
1622 : TIFFSetField( poGDS->hTIFF, TIFFTAG_PHOTOMETRIC,
1623 2 : PHOTOMETRIC_MINISBLACK );
1624 :
1625 : #ifdef HAVE_UNSETFIELD
1626 2 : TIFFUnsetField( poGDS->hTIFF, TIFFTAG_COLORMAP );
1627 : #else
1628 : CPLDebug( "GTiff",
1629 : "TIFFUnsetField() not supported, colormap may not be cleared." );
1630 : #endif
1631 :
1632 2 : if( poGDS->poColorTable )
1633 : {
1634 2 : delete poGDS->poColorTable;
1635 2 : poGDS->poColorTable = NULL;
1636 : }
1637 :
1638 2 : return CE_None;
1639 : }
1640 :
1641 : /* -------------------------------------------------------------------- */
1642 : /* Write out the colortable, and update the configuration. */
1643 : /* -------------------------------------------------------------------- */
1644 : int nColors;
1645 :
1646 28 : if( eDataType == GDT_Byte )
1647 26 : nColors = 256;
1648 : else
1649 2 : nColors = 65536;
1650 :
1651 : unsigned short *panTRed, *panTGreen, *panTBlue;
1652 :
1653 28 : panTRed = (unsigned short *) CPLMalloc(sizeof(unsigned short)*nColors);
1654 28 : panTGreen = (unsigned short *) CPLMalloc(sizeof(unsigned short)*nColors);
1655 28 : panTBlue = (unsigned short *) CPLMalloc(sizeof(unsigned short)*nColors);
1656 :
1657 137756 : for( int iColor = 0; iColor < nColors; iColor++ )
1658 : {
1659 137728 : if( iColor < poCT->GetColorEntryCount() )
1660 : {
1661 : GDALColorEntry sRGB;
1662 :
1663 1648 : poCT->GetColorEntryAsRGB( iColor, &sRGB );
1664 :
1665 1648 : panTRed[iColor] = (unsigned short) (257 * sRGB.c1);
1666 1648 : panTGreen[iColor] = (unsigned short) (257 * sRGB.c2);
1667 1648 : panTBlue[iColor] = (unsigned short) (257 * sRGB.c3);
1668 : }
1669 : else
1670 : {
1671 136080 : panTRed[iColor] = panTGreen[iColor] = panTBlue[iColor] = 0;
1672 : }
1673 : }
1674 :
1675 28 : TIFFSetField( poGDS->hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE );
1676 : TIFFSetField( poGDS->hTIFF, TIFFTAG_COLORMAP,
1677 28 : panTRed, panTGreen, panTBlue );
1678 :
1679 28 : CPLFree( panTRed );
1680 28 : CPLFree( panTGreen );
1681 28 : CPLFree( panTBlue );
1682 :
1683 28 : if( poGDS->poColorTable )
1684 6 : delete poGDS->poColorTable;
1685 :
1686 : /* libtiff 3.X needs setting this in all cases (creation or update) */
1687 : /* whereas libtiff 4.X would just need it if there */
1688 : /* was no color table before */
1689 : #if 0
1690 : else
1691 : #endif
1692 28 : poGDS->bNeedsRewrite = TRUE;
1693 :
1694 28 : poGDS->poColorTable = poCT->Clone();
1695 28 : eBandInterp = GCI_PaletteIndex;
1696 :
1697 28 : return CE_None;
1698 : }
1699 :
1700 : /************************************************************************/
1701 : /* GetNoDataValue() */
1702 : /************************************************************************/
1703 :
1704 39676 : double GTiffRasterBand::GetNoDataValue( int * pbSuccess )
1705 :
1706 : {
1707 39676 : if( bNoDataSet )
1708 : {
1709 182 : if( pbSuccess )
1710 164 : *pbSuccess = TRUE;
1711 :
1712 182 : return dfNoDataValue;
1713 : }
1714 :
1715 39494 : if( poGDS->bNoDataSet )
1716 : {
1717 490 : if( pbSuccess )
1718 458 : *pbSuccess = TRUE;
1719 :
1720 490 : return poGDS->dfNoDataValue;
1721 : }
1722 :
1723 39004 : return GDALPamRasterBand::GetNoDataValue( pbSuccess );
1724 : }
1725 :
1726 : /************************************************************************/
1727 : /* SetNoDataValue() */
1728 : /************************************************************************/
1729 :
1730 128 : CPLErr GTiffRasterBand::SetNoDataValue( double dfNoData )
1731 :
1732 : {
1733 128 : if( poGDS->bNoDataSet && poGDS->dfNoDataValue == dfNoData )
1734 32 : return CE_None;
1735 :
1736 96 : if (!poGDS->SetDirectory()) // needed to call TIFFSetField().
1737 0 : return CE_Failure;
1738 :
1739 96 : poGDS->bNoDataSet = TRUE;
1740 96 : poGDS->dfNoDataValue = dfNoData;
1741 :
1742 96 : poGDS->WriteNoDataValue( poGDS->hTIFF, dfNoData );
1743 96 : poGDS->bNeedsRewrite = TRUE;
1744 :
1745 96 : bNoDataSet = TRUE;
1746 96 : dfNoDataValue = dfNoData;
1747 96 : return CE_None;
1748 : }
1749 :
1750 : /************************************************************************/
1751 : /* NullBlock() */
1752 : /* */
1753 : /* Set the block data to the null value if it is set, or zero */
1754 : /* if there is no null data value. */
1755 : /************************************************************************/
1756 :
1757 27478 : void GTiffRasterBand::NullBlock( void *pData )
1758 :
1759 : {
1760 27478 : int nWords = nBlockXSize * nBlockYSize;
1761 27478 : int nChunkSize = MAX(1,GDALGetDataTypeSize(eDataType)/8);
1762 :
1763 : int bNoDataSet;
1764 27478 : double dfNoData = GetNoDataValue( &bNoDataSet );
1765 27478 : if( !bNoDataSet )
1766 : {
1767 : #ifdef ESRI_BUILD
1768 : if ( poGDS->nBitsPerSample >= 2 )
1769 : memset( pData, 0, nWords*nChunkSize );
1770 : else
1771 : memset( pData, 1, nWords*nChunkSize );
1772 : #else
1773 27310 : memset( pData, 0, nWords*nChunkSize );
1774 : #endif
1775 : }
1776 : else
1777 : {
1778 : /* Will convert nodata value to the right type and copy efficiently */
1779 : GDALCopyWords( &dfNoData, GDT_Float64, 0,
1780 168 : pData, eDataType, nChunkSize, nWords);
1781 : }
1782 27478 : }
1783 :
1784 : /************************************************************************/
1785 : /* GetOverviewCount() */
1786 : /************************************************************************/
1787 :
1788 601852 : int GTiffRasterBand::GetOverviewCount()
1789 :
1790 : {
1791 601852 : poGDS->ScanDirectories();
1792 :
1793 601852 : if( poGDS->nOverviewCount > 0 )
1794 1844 : return poGDS->nOverviewCount;
1795 : else
1796 600008 : return GDALRasterBand::GetOverviewCount();
1797 : }
1798 :
1799 : /************************************************************************/
1800 : /* GetOverview() */
1801 : /************************************************************************/
1802 :
1803 2106 : GDALRasterBand *GTiffRasterBand::GetOverview( int i )
1804 :
1805 : {
1806 2106 : poGDS->ScanDirectories();
1807 :
1808 2106 : if( poGDS->nOverviewCount > 0 )
1809 : {
1810 1538 : if( i < 0 || i >= poGDS->nOverviewCount )
1811 0 : return NULL;
1812 : else
1813 1538 : return poGDS->papoOverviewDS[i]->GetRasterBand(nBand);
1814 : }
1815 : else
1816 568 : return GDALRasterBand::GetOverview( i );
1817 : }
1818 :
1819 : /************************************************************************/
1820 : /* GetMaskFlags() */
1821 : /************************************************************************/
1822 :
1823 6494 : int GTiffRasterBand::GetMaskFlags()
1824 : {
1825 6494 : poGDS->ScanDirectories();
1826 :
1827 6494 : if( poGDS->poMaskDS != NULL )
1828 : {
1829 102 : if( poGDS->poMaskDS->GetRasterCount() == 1)
1830 : {
1831 90 : return GMF_PER_DATASET;
1832 : }
1833 : else
1834 : {
1835 12 : return 0;
1836 : }
1837 : }
1838 : else
1839 6392 : return GDALPamRasterBand::GetMaskFlags();
1840 : }
1841 :
1842 : /************************************************************************/
1843 : /* GetMaskBand() */
1844 : /************************************************************************/
1845 :
1846 4902 : GDALRasterBand *GTiffRasterBand::GetMaskBand()
1847 : {
1848 4902 : poGDS->ScanDirectories();
1849 :
1850 4902 : if( poGDS->poMaskDS != NULL )
1851 : {
1852 2838 : if( poGDS->poMaskDS->GetRasterCount() == 1)
1853 2826 : return poGDS->poMaskDS->GetRasterBand(1);
1854 : else
1855 12 : return poGDS->poMaskDS->GetRasterBand(nBand);
1856 : }
1857 : else
1858 2064 : return GDALPamRasterBand::GetMaskBand();
1859 : }
1860 :
1861 : /************************************************************************/
1862 : /* ==================================================================== */
1863 : /* GTiffSplitBand */
1864 : /* ==================================================================== */
1865 : /************************************************************************/
1866 :
1867 : class GTiffSplitBand : public GTiffRasterBand
1868 : {
1869 : friend class GTiffDataset;
1870 :
1871 : public:
1872 :
1873 : GTiffSplitBand( GTiffDataset *, int );
1874 : virtual ~GTiffSplitBand();
1875 :
1876 : virtual CPLErr IReadBlock( int, int, void * );
1877 : virtual CPLErr IWriteBlock( int, int, void * );
1878 : };
1879 :
1880 : /************************************************************************/
1881 : /* GTiffSplitBand() */
1882 : /************************************************************************/
1883 :
1884 54 : GTiffSplitBand::GTiffSplitBand( GTiffDataset *poDS, int nBand )
1885 54 : : GTiffRasterBand( poDS, nBand )
1886 :
1887 : {
1888 54 : nBlockXSize = poDS->GetRasterXSize();
1889 54 : nBlockYSize = 1;
1890 54 : }
1891 :
1892 : /************************************************************************/
1893 : /* ~GTiffSplitBand() */
1894 : /************************************************************************/
1895 :
1896 54 : GTiffSplitBand::~GTiffSplitBand()
1897 : {
1898 54 : }
1899 :
1900 : /************************************************************************/
1901 : /* IReadBlock() */
1902 : /************************************************************************/
1903 :
1904 139712 : CPLErr GTiffSplitBand::IReadBlock( int nBlockXOff, int nBlockYOff,
1905 : void * pImage )
1906 :
1907 : {
1908 : (void) nBlockXOff;
1909 :
1910 : /* Optimization when reading the same line in a contig multi-band TIFF */
1911 139712 : if( poGDS->nPlanarConfig == PLANARCONFIG_CONTIG && poGDS->nBands > 1 &&
1912 : poGDS->nLastLineRead == nBlockYOff )
1913 : {
1914 18 : goto extract_band_data;
1915 : }
1916 :
1917 139694 : if (!poGDS->SetDirectory())
1918 0 : return CE_Failure;
1919 :
1920 219388 : if (poGDS->nPlanarConfig == PLANARCONFIG_CONTIG &&
1921 : poGDS->nBands > 1)
1922 : {
1923 79694 : if (poGDS->pabyBlockBuf == NULL)
1924 8 : poGDS->pabyBlockBuf = (GByte *) CPLMalloc(TIFFScanlineSize(poGDS->hTIFF));
1925 : }
1926 : else
1927 : {
1928 60000 : CPLAssert(TIFFScanlineSize(poGDS->hTIFF) == nBlockXSize);
1929 : }
1930 :
1931 : /* -------------------------------------------------------------------- */
1932 : /* Read through to target scanline. */
1933 : /* -------------------------------------------------------------------- */
1934 139694 : if( poGDS->nLastLineRead >= nBlockYOff )
1935 62 : poGDS->nLastLineRead = -1;
1936 :
1937 139694 : if( poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE && poGDS->nBands > 1 )
1938 : {
1939 : /* If we change of band, we must start reading the */
1940 : /* new strip from its beginning */
1941 60000 : if ( poGDS->nLastBandRead != nBand )
1942 40 : poGDS->nLastLineRead = -1;
1943 60000 : poGDS->nLastBandRead = nBand;
1944 : }
1945 :
1946 517708 : while( poGDS->nLastLineRead < nBlockYOff )
1947 : {
1948 238320 : if( TIFFReadScanline( poGDS->hTIFF,
1949 : poGDS->pabyBlockBuf ? poGDS->pabyBlockBuf : pImage,
1950 : ++poGDS->nLastLineRead,
1951 : (poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE) ? (uint16) (nBand-1) : 0 ) == -1
1952 : && !poGDS->bIgnoreReadErrors )
1953 : {
1954 : CPLError( CE_Failure, CPLE_AppDefined,
1955 0 : "TIFFReadScanline() failed." );
1956 0 : return CE_Failure;
1957 : }
1958 : }
1959 :
1960 : extract_band_data:
1961 : /* -------------------------------------------------------------------- */
1962 : /* Extract band data from contig buffer. */
1963 : /* -------------------------------------------------------------------- */
1964 139712 : if ( poGDS->pabyBlockBuf != NULL )
1965 : {
1966 79712 : int iPixel, iSrcOffset= nBand - 1, iDstOffset=0;
1967 :
1968 27894208 : for( iPixel = 0; iPixel < nBlockXSize; iPixel++, iSrcOffset+=poGDS->nBands, iDstOffset++ )
1969 : {
1970 27814496 : ((GByte *) pImage)[iDstOffset] = poGDS->pabyBlockBuf[iSrcOffset];
1971 : }
1972 : }
1973 :
1974 139712 : return CE_None;
1975 : }
1976 :
1977 : /************************************************************************/
1978 : /* IWriteBlock() */
1979 : /************************************************************************/
1980 :
1981 0 : CPLErr GTiffSplitBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
1982 : void * pImage )
1983 :
1984 : {
1985 : (void) nBlockXOff;
1986 : (void) nBlockYOff;
1987 : (void) pImage;
1988 :
1989 : CPLError( CE_Failure, CPLE_AppDefined,
1990 0 : "Split bands are read-only." );
1991 0 : return CE_Failure;
1992 : }
1993 :
1994 : /************************************************************************/
1995 : /* ==================================================================== */
1996 : /* GTiffRGBABand */
1997 : /* ==================================================================== */
1998 : /************************************************************************/
1999 :
2000 : class GTiffRGBABand : public GTiffRasterBand
2001 40 : {
2002 : friend class GTiffDataset;
2003 :
2004 : public:
2005 :
2006 : GTiffRGBABand( GTiffDataset *, int );
2007 :
2008 : virtual CPLErr IReadBlock( int, int, void * );
2009 : virtual CPLErr IWriteBlock( int, int, void * );
2010 :
2011 : virtual GDALColorInterp GetColorInterpretation();
2012 : };
2013 :
2014 :
2015 : /************************************************************************/
2016 : /* GTiffRGBABand() */
2017 : /************************************************************************/
2018 :
2019 40 : GTiffRGBABand::GTiffRGBABand( GTiffDataset *poDS, int nBand )
2020 40 : : GTiffRasterBand( poDS, nBand )
2021 :
2022 : {
2023 40 : eDataType = GDT_Byte;
2024 40 : }
2025 :
2026 : /************************************************************************/
2027 : /* IWriteBlock() */
2028 : /************************************************************************/
2029 :
2030 0 : CPLErr GTiffRGBABand::IWriteBlock( int, int, void * )
2031 :
2032 : {
2033 : CPLError( CE_Failure, CPLE_AppDefined,
2034 0 : "RGBA interpreted raster bands are read-only." );
2035 0 : return CE_Failure;
2036 : }
2037 :
2038 : /************************************************************************/
2039 : /* IReadBlock() */
2040 : /************************************************************************/
2041 :
2042 32 : CPLErr GTiffRGBABand::IReadBlock( int nBlockXOff, int nBlockYOff,
2043 : void * pImage )
2044 :
2045 : {
2046 : int nBlockBufSize, nBlockId;
2047 32 : CPLErr eErr = CE_None;
2048 :
2049 32 : if (!poGDS->SetDirectory())
2050 0 : return CE_Failure;
2051 :
2052 32 : CPLAssert(nBlocksPerRow != 0);
2053 32 : nBlockBufSize = 4 * nBlockXSize * nBlockYSize;
2054 32 : nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
2055 :
2056 : /* -------------------------------------------------------------------- */
2057 : /* Allocate a temporary buffer for this strip. */
2058 : /* -------------------------------------------------------------------- */
2059 32 : if( poGDS->pabyBlockBuf == NULL )
2060 : {
2061 6 : poGDS->pabyBlockBuf = (GByte *) VSIMalloc3( 4, nBlockXSize, nBlockYSize );
2062 6 : if( poGDS->pabyBlockBuf == NULL )
2063 0 : return( CE_Failure );
2064 : }
2065 :
2066 : /* -------------------------------------------------------------------- */
2067 : /* Read the strip */
2068 : /* -------------------------------------------------------------------- */
2069 32 : if( poGDS->nLoadedBlock != nBlockId )
2070 : {
2071 8 : if( TIFFIsTiled( poGDS->hTIFF ) )
2072 : {
2073 2 : if( TIFFReadRGBATile(poGDS->hTIFF,
2074 : nBlockXOff * nBlockXSize,
2075 : nBlockYOff * nBlockYSize,
2076 : (uint32 *) poGDS->pabyBlockBuf) == -1
2077 : && !poGDS->bIgnoreReadErrors )
2078 : {
2079 : /* Once TIFFError() is properly hooked, this can go away */
2080 : CPLError( CE_Failure, CPLE_AppDefined,
2081 0 : "TIFFReadRGBATile() failed." );
2082 :
2083 0 : memset( poGDS->pabyBlockBuf, 0, nBlockBufSize );
2084 :
2085 0 : eErr = CE_Failure;
2086 : }
2087 : }
2088 : else
2089 : {
2090 6 : if( TIFFReadRGBAStrip(poGDS->hTIFF,
2091 : nBlockId * nBlockYSize,
2092 : (uint32 *) poGDS->pabyBlockBuf) == -1
2093 : && !poGDS->bIgnoreReadErrors )
2094 : {
2095 : /* Once TIFFError() is properly hooked, this can go away */
2096 : CPLError( CE_Failure, CPLE_AppDefined,
2097 0 : "TIFFReadRGBAStrip() failed." );
2098 :
2099 0 : memset( poGDS->pabyBlockBuf, 0, nBlockBufSize );
2100 :
2101 0 : eErr = CE_Failure;
2102 : }
2103 : }
2104 : }
2105 :
2106 32 : poGDS->nLoadedBlock = nBlockId;
2107 :
2108 : /* -------------------------------------------------------------------- */
2109 : /* Handle simple case of eight bit data, and pixel interleaving. */
2110 : /* -------------------------------------------------------------------- */
2111 : int iDestLine, nBO;
2112 : int nThisBlockYSize;
2113 :
2114 32 : if( (nBlockYOff+1) * nBlockYSize > GetYSize()
2115 : && !TIFFIsTiled( poGDS->hTIFF ) )
2116 8 : nThisBlockYSize = GetYSize() - nBlockYOff * nBlockYSize;
2117 : else
2118 24 : nThisBlockYSize = nBlockYSize;
2119 :
2120 : #ifdef CPL_LSB
2121 32 : nBO = nBand - 1;
2122 : #else
2123 : nBO = 4 - nBand;
2124 : #endif
2125 :
2126 2232 : for( iDestLine = 0; iDestLine < nThisBlockYSize; iDestLine++ )
2127 : {
2128 : int nSrcOffset;
2129 :
2130 2200 : nSrcOffset = (nThisBlockYSize - iDestLine - 1) * nBlockXSize * 4;
2131 :
2132 : GDALCopyWords( poGDS->pabyBlockBuf + nBO + nSrcOffset, GDT_Byte, 4,
2133 : ((GByte *) pImage)+iDestLine*nBlockXSize, GDT_Byte, 1,
2134 2200 : nBlockXSize );
2135 : }
2136 :
2137 32 : if (eErr == CE_None)
2138 32 : eErr = FillCacheForOtherBands(nBlockXOff, nBlockYOff);
2139 :
2140 32 : return eErr;
2141 : }
2142 :
2143 : /************************************************************************/
2144 : /* GetColorInterpretation() */
2145 : /************************************************************************/
2146 :
2147 12 : GDALColorInterp GTiffRGBABand::GetColorInterpretation()
2148 :
2149 : {
2150 12 : if( nBand == 1 )
2151 4 : return GCI_RedBand;
2152 8 : else if( nBand == 2 )
2153 2 : return GCI_GreenBand;
2154 6 : else if( nBand == 3 )
2155 2 : return GCI_BlueBand;
2156 : else
2157 4 : return GCI_AlphaBand;
2158 : }
2159 :
2160 : /************************************************************************/
2161 : /* ==================================================================== */
2162 : /* GTiffOddBitsBand */
2163 : /* ==================================================================== */
2164 : /************************************************************************/
2165 :
2166 : class GTiffOddBitsBand : public GTiffRasterBand
2167 : {
2168 : friend class GTiffDataset;
2169 : public:
2170 :
2171 : GTiffOddBitsBand( GTiffDataset *, int );
2172 : virtual ~GTiffOddBitsBand();
2173 :
2174 : virtual CPLErr IReadBlock( int, int, void * );
2175 : virtual CPLErr IWriteBlock( int, int, void * );
2176 : };
2177 :
2178 :
2179 : /************************************************************************/
2180 : /* GTiffOddBitsBand() */
2181 : /************************************************************************/
2182 :
2183 764 : GTiffOddBitsBand::GTiffOddBitsBand( GTiffDataset *poGDS, int nBand )
2184 764 : : GTiffRasterBand( poGDS, nBand )
2185 :
2186 : {
2187 764 : eDataType = GDT_Byte;
2188 764 : if( poGDS->nSampleFormat == SAMPLEFORMAT_IEEEFP )
2189 4 : eDataType = GDT_Float32;
2190 954 : else if( poGDS->nBitsPerSample > 8 && poGDS->nBitsPerSample < 16 )
2191 194 : eDataType = GDT_UInt16;
2192 566 : else if( poGDS->nBitsPerSample > 16 )
2193 134 : eDataType = GDT_UInt32;
2194 764 : }
2195 :
2196 : /************************************************************************/
2197 : /* ~GTiffOddBitsBand() */
2198 : /************************************************************************/
2199 :
2200 764 : GTiffOddBitsBand::~GTiffOddBitsBand()
2201 :
2202 : {
2203 764 : }
2204 :
2205 : /************************************************************************/
2206 : /* IWriteBlock() */
2207 : /************************************************************************/
2208 :
2209 882 : CPLErr GTiffOddBitsBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
2210 : void *pImage )
2211 :
2212 : {
2213 : int nBlockId;
2214 882 : CPLErr eErr = CE_None;
2215 :
2216 882 : if (poGDS->bWriteErrorInFlushBlockBuf)
2217 : {
2218 : /* Report as an error if a previously loaded block couldn't be */
2219 : /* written correctly */
2220 0 : poGDS->bWriteErrorInFlushBlockBuf = FALSE;
2221 0 : return CE_Failure;
2222 : }
2223 :
2224 882 : if (!poGDS->SetDirectory())
2225 0 : return CE_Failure;
2226 :
2227 : CPLAssert( poGDS != NULL
2228 : && nBlockXOff >= 0
2229 : && nBlockYOff >= 0
2230 882 : && pImage != NULL );
2231 :
2232 882 : if( eDataType == GDT_Float32 && poGDS->nBitsPerSample < 32 )
2233 : {
2234 : CPLError(CE_Failure, CPLE_NotSupported,
2235 0 : "Writing float data with nBitsPerSample < 32 is unsupported");
2236 0 : return CE_Failure;
2237 : }
2238 :
2239 : /* -------------------------------------------------------------------- */
2240 : /* Load the block buffer. */
2241 : /* -------------------------------------------------------------------- */
2242 882 : CPLAssert(nBlocksPerRow != 0);
2243 882 : nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
2244 :
2245 882 : if( poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE )
2246 36 : nBlockId += (nBand-1) * poGDS->nBlocksPerBand;
2247 :
2248 : /* Only read content from disk in the CONTIG case */
2249 : eErr = poGDS->LoadBlockBuf( nBlockId,
2250 882 : poGDS->nPlanarConfig == PLANARCONFIG_CONTIG && poGDS->nBands > 1 );
2251 882 : if( eErr != CE_None )
2252 0 : return eErr;
2253 :
2254 882 : GUInt32 nMaxVal = (1 << poGDS->nBitsPerSample) - 1;
2255 :
2256 : /* -------------------------------------------------------------------- */
2257 : /* Handle case of "separate" images or single band images where */
2258 : /* no interleaving with other data is required. */
2259 : /* -------------------------------------------------------------------- */
2260 882 : if( poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE
2261 : || poGDS->nBands == 1 )
2262 : {
2263 850 : int iBit, iPixel, iBitOffset = 0;
2264 : int iX, iY, nBitsPerLine;
2265 :
2266 : // bits per line rounds up to next byte boundary.
2267 850 : nBitsPerLine = nBlockXSize * poGDS->nBitsPerSample;
2268 850 : if( (nBitsPerLine & 7) != 0 )
2269 70 : nBitsPerLine = (nBitsPerLine + 7) & (~7);
2270 :
2271 : /* Initialize to zero as we set the buffer with binary or operations */
2272 850 : if (poGDS->nBitsPerSample != 24)
2273 840 : memset(poGDS->pabyBlockBuf, 0, (nBitsPerLine / 8) * nBlockYSize);
2274 :
2275 850 : iPixel = 0;
2276 81518 : for( iY = 0; iY < nBlockYSize; iY++ )
2277 : {
2278 80668 : iBitOffset = iY * nBitsPerLine;
2279 :
2280 : /* Small optimization in 1 bit case */
2281 80668 : if (poGDS->nBitsPerSample == 1)
2282 : {
2283 36357526 : for( iX = 0; iX < nBlockXSize; iX++ )
2284 : {
2285 36278054 : if (((GByte *) pImage)[iPixel++])
2286 20524268 : poGDS->pabyBlockBuf[iBitOffset>>3] |= (0x80 >>(iBitOffset & 7));
2287 36278054 : iBitOffset++;
2288 : }
2289 :
2290 79472 : continue;
2291 : }
2292 :
2293 78736 : for( iX = 0; iX < nBlockXSize; iX++ )
2294 : {
2295 77540 : GUInt32 nInWord = 0;
2296 77540 : if( eDataType == GDT_Byte )
2297 800 : nInWord = ((GByte *) pImage)[iPixel++];
2298 76740 : else if( eDataType == GDT_UInt16 )
2299 71138 : nInWord = ((GUInt16 *) pImage)[iPixel++];
2300 5602 : else if( eDataType == GDT_UInt32 )
2301 5602 : nInWord = ((GUInt32 *) pImage)[iPixel++];
2302 : else
2303 0 : CPLAssert(0);
2304 :
2305 77540 : if (nInWord > nMaxVal)
2306 : {
2307 800 : nInWord = nMaxVal;
2308 800 : if( !poGDS->bClipWarn )
2309 : {
2310 2 : poGDS->bClipWarn = TRUE;
2311 : CPLError( CE_Warning, CPLE_AppDefined,
2312 2 : "One or more pixels clipped to fit %d bit domain.", poGDS->nBitsPerSample );
2313 : }
2314 : }
2315 :
2316 77540 : if (poGDS->nBitsPerSample == 24)
2317 : {
2318 : /* -------------------------------------------------------------------- */
2319 : /* Special case for 24bit data which is pre-byteswapped since */
2320 : /* the size falls on a byte boundary ... ugg (#2361). */
2321 : /* -------------------------------------------------------------------- */
2322 : #ifdef CPL_MSB
2323 : poGDS->pabyBlockBuf[(iBitOffset>>3) + 0] =
2324 : (GByte) nInWord;
2325 : poGDS->pabyBlockBuf[(iBitOffset>>3) + 1] =
2326 : (GByte) (nInWord >> 8);
2327 : poGDS->pabyBlockBuf[(iBitOffset>>3) + 2] =
2328 : (GByte) (nInWord >> 16);
2329 : #else
2330 2800 : poGDS->pabyBlockBuf[(iBitOffset>>3) + 0] =
2331 2800 : (GByte) (nInWord >> 16);
2332 2800 : poGDS->pabyBlockBuf[(iBitOffset>>3) + 1] =
2333 2800 : (GByte) (nInWord >> 8);
2334 2800 : poGDS->pabyBlockBuf[(iBitOffset>>3) + 2] =
2335 2800 : (GByte) nInWord;
2336 : #endif
2337 2800 : iBitOffset += 24;
2338 : }
2339 : else
2340 : {
2341 971624 : for( iBit = 0; iBit < poGDS->nBitsPerSample; iBit++ )
2342 : {
2343 896884 : if (nInWord & (1 << (poGDS->nBitsPerSample - 1 - iBit)))
2344 36970 : poGDS->pabyBlockBuf[iBitOffset>>3] |= (0x80 >>(iBitOffset & 7));
2345 896884 : iBitOffset++;
2346 : }
2347 : }
2348 : }
2349 : }
2350 :
2351 850 : poGDS->bLoadedBlockDirty = TRUE;
2352 :
2353 850 : return eErr;
2354 : }
2355 :
2356 : /* -------------------------------------------------------------------- */
2357 : /* Handle case of pixel interleaved (PLANARCONFIG_CONTIG) images. */
2358 : /* -------------------------------------------------------------------- */
2359 :
2360 : /* -------------------------------------------------------------------- */
2361 : /* On write of pixel interleaved data, we might as well flush */
2362 : /* out any other bands that are dirty in our cache. This is */
2363 : /* especially helpful when writing compressed blocks. */
2364 : /* -------------------------------------------------------------------- */
2365 : int iBand;
2366 :
2367 108 : for( iBand = 0; iBand < poGDS->nBands; iBand++ )
2368 : {
2369 76 : const GByte *pabyThisImage = NULL;
2370 76 : GDALRasterBlock *poBlock = NULL;
2371 76 : int iBit, iPixel, iBitOffset = 0;
2372 : int iPixelBitSkip, iBandBitOffset, iX, iY, nBitsPerLine;
2373 :
2374 76 : if( iBand+1 == nBand )
2375 32 : pabyThisImage = (GByte *) pImage;
2376 : else
2377 : {
2378 : poBlock = ((GTiffOddBitsBand *)poGDS->GetRasterBand( iBand+1 ))
2379 44 : ->TryGetLockedBlockRef( nBlockXOff, nBlockYOff );
2380 :
2381 44 : if( poBlock == NULL )
2382 20 : continue;
2383 :
2384 24 : if( !poBlock->GetDirty() )
2385 : {
2386 0 : poBlock->DropLock();
2387 0 : continue;
2388 : }
2389 :
2390 24 : pabyThisImage = (GByte *) poBlock->GetDataRef();
2391 : }
2392 :
2393 56 : iPixelBitSkip = poGDS->nBitsPerSample * poGDS->nBands;
2394 56 : iBandBitOffset = iBand * poGDS->nBitsPerSample;
2395 :
2396 : // bits per line rounds up to next byte boundary.
2397 56 : nBitsPerLine = nBlockXSize * iPixelBitSkip;
2398 56 : if( (nBitsPerLine & 7) != 0 )
2399 30 : nBitsPerLine = (nBitsPerLine + 7) & (~7);
2400 :
2401 56 : iPixel = 0;
2402 1342 : for( iY = 0; iY < nBlockYSize; iY++ )
2403 : {
2404 1286 : iBitOffset = iBandBitOffset + iY * nBitsPerLine;
2405 :
2406 45232 : for( iX = 0; iX < nBlockXSize; iX++ )
2407 : {
2408 43946 : GUInt32 nInWord = 0;
2409 43946 : if( eDataType == GDT_Byte )
2410 8170 : nInWord = ((GByte *) pabyThisImage)[iPixel++];
2411 35776 : else if( eDataType == GDT_UInt16 )
2412 30176 : nInWord = ((GUInt16 *) pabyThisImage)[iPixel++];
2413 5600 : else if( eDataType == GDT_UInt32 )
2414 5600 : nInWord = ((GUInt32 *) pabyThisImage)[iPixel++];
2415 : else
2416 0 : CPLAssert(0);
2417 :
2418 43946 : if (nInWord > nMaxVal)
2419 : {
2420 0 : nInWord = nMaxVal;
2421 0 : if( !poGDS->bClipWarn )
2422 : {
2423 0 : poGDS->bClipWarn = TRUE;
2424 : CPLError( CE_Warning, CPLE_AppDefined,
2425 0 : "One or more pixels clipped to fit %d bit domain.", poGDS->nBitsPerSample );
2426 : }
2427 : }
2428 :
2429 43946 : if (poGDS->nBitsPerSample == 24)
2430 : {
2431 : /* -------------------------------------------------------------------- */
2432 : /* Special case for 24bit data which is pre-byteswapped since */
2433 : /* the size falls on a byte boundary ... ugg (#2361). */
2434 : /* -------------------------------------------------------------------- */
2435 : #ifdef CPL_MSB
2436 : poGDS->pabyBlockBuf[(iBitOffset>>3) + 0] =
2437 : (GByte) nInWord;
2438 : poGDS->pabyBlockBuf[(iBitOffset>>3) + 1] =
2439 : (GByte) (nInWord >> 8);
2440 : poGDS->pabyBlockBuf[(iBitOffset>>3) + 2] =
2441 : (GByte) (nInWord >> 16);
2442 : #else
2443 2800 : poGDS->pabyBlockBuf[(iBitOffset>>3) + 0] =
2444 2800 : (GByte) (nInWord >> 16);
2445 2800 : poGDS->pabyBlockBuf[(iBitOffset>>3) + 1] =
2446 2800 : (GByte) (nInWord >> 8);
2447 2800 : poGDS->pabyBlockBuf[(iBitOffset>>3) + 2] =
2448 2800 : (GByte) nInWord;
2449 : #endif
2450 2800 : iBitOffset += 24;
2451 : }
2452 : else
2453 : {
2454 497248 : for( iBit = 0; iBit < poGDS->nBitsPerSample; iBit++ )
2455 : {
2456 456102 : if (nInWord & (1 << (poGDS->nBitsPerSample - 1 - iBit)))
2457 203790 : poGDS->pabyBlockBuf[iBitOffset>>3] |= (0x80 >>(iBitOffset & 7));
2458 : else
2459 : {
2460 : /* We must explictly unset the bit as we may update an existing block */
2461 252312 : poGDS->pabyBlockBuf[iBitOffset>>3] &= ~(0x80 >>(iBitOffset & 7));
2462 : }
2463 :
2464 456102 : iBitOffset++;
2465 : }
2466 : }
2467 :
2468 43946 : iBitOffset= iBitOffset + iPixelBitSkip - poGDS->nBitsPerSample;
2469 : }
2470 : }
2471 :
2472 56 : if( poBlock != NULL )
2473 : {
2474 24 : poBlock->MarkClean();
2475 24 : poBlock->DropLock();
2476 : }
2477 : }
2478 :
2479 32 : poGDS->bLoadedBlockDirty = TRUE;
2480 :
2481 32 : return CE_None;
2482 : }
2483 :
2484 : /************************************************************************/
2485 : /* IReadBlock() */
2486 : /************************************************************************/
2487 :
2488 1628 : CPLErr GTiffOddBitsBand::IReadBlock( int nBlockXOff, int nBlockYOff,
2489 : void * pImage )
2490 :
2491 : {
2492 : int nBlockId;
2493 1628 : CPLErr eErr = CE_None;
2494 :
2495 1628 : if (!poGDS->SetDirectory())
2496 0 : return CE_Failure;
2497 :
2498 1628 : CPLAssert(nBlocksPerRow != 0);
2499 1628 : nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
2500 :
2501 1628 : if( poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE )
2502 40 : nBlockId += (nBand-1) * poGDS->nBlocksPerBand;
2503 :
2504 : /* -------------------------------------------------------------------- */
2505 : /* Handle the case of a strip in a writable file that doesn't */
2506 : /* exist yet, but that we want to read. Just set to zeros and */
2507 : /* return. */
2508 : /* -------------------------------------------------------------------- */
2509 1628 : if( !poGDS->IsBlockAvailable(nBlockId) )
2510 : {
2511 1132 : NullBlock( pImage );
2512 1132 : return CE_None;
2513 : }
2514 :
2515 : /* -------------------------------------------------------------------- */
2516 : /* Load the block buffer. */
2517 : /* -------------------------------------------------------------------- */
2518 496 : eErr = poGDS->LoadBlockBuf( nBlockId );
2519 496 : if( eErr != CE_None )
2520 0 : return eErr;
2521 :
2522 828 : if ( poGDS->nBitsPerSample == 1 && (poGDS->nBands == 1 || poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE ) )
2523 : {
2524 : /* -------------------------------------------------------------------- */
2525 : /* Translate 1bit data to eight bit. */
2526 : /* -------------------------------------------------------------------- */
2527 332 : int iDstOffset=0, iLine;
2528 332 : register GByte *pabyBlockBuf = poGDS->pabyBlockBuf;
2529 :
2530 35678 : for( iLine = 0; iLine < nBlockYSize; iLine++ )
2531 : {
2532 : int iSrcOffset, iPixel;
2533 :
2534 35346 : iSrcOffset = ((nBlockXSize+7) >> 3) * 8 * iLine;
2535 :
2536 35346 : GByte bSetVal = (poGDS->bPromoteTo8Bits) ? 255 : 1;
2537 :
2538 9449760 : for( iPixel = 0; iPixel < nBlockXSize; iPixel++, iSrcOffset++ )
2539 : {
2540 9414414 : if( pabyBlockBuf[iSrcOffset >>3] & (0x80 >> (iSrcOffset & 0x7)) )
2541 3068844 : ((GByte *) pImage)[iDstOffset++] = bSetVal;
2542 : else
2543 6345570 : ((GByte *) pImage)[iDstOffset++] = 0;
2544 : }
2545 : }
2546 : }
2547 : /* -------------------------------------------------------------------- */
2548 : /* Handle the case of 16- and 24-bit floating point data as per */
2549 : /* TIFF Technical Note 3. */
2550 : /* -------------------------------------------------------------------- */
2551 168 : else if( eDataType == GDT_Float32 && poGDS->nBitsPerSample < 32 )
2552 : {
2553 : int i, nBlockPixels, nWordBytes, iSkipBytes;
2554 : GByte *pabyImage;
2555 :
2556 4 : nWordBytes = poGDS->nBitsPerSample / 8;
2557 4 : pabyImage = poGDS->pabyBlockBuf + (nBand - 1) * nWordBytes;
2558 : iSkipBytes = ( poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE ) ?
2559 4 : nWordBytes : poGDS->nBands * nWordBytes;
2560 :
2561 4 : nBlockPixels = nBlockXSize * nBlockYSize;
2562 4 : if ( poGDS->nBitsPerSample == 16 )
2563 : {
2564 802 : for( i = 0; i < nBlockPixels; i++ )
2565 : {
2566 800 : ((GUInt32 *) pImage)[i] =
2567 800 : HalfToFloat( *((GUInt16 *)pabyImage) );
2568 800 : pabyImage += iSkipBytes;
2569 : }
2570 : }
2571 2 : else if ( poGDS->nBitsPerSample == 24 )
2572 : {
2573 802 : for( i = 0; i < nBlockPixels; i++ )
2574 : {
2575 : #ifdef CPL_MSB
2576 : ((GUInt32 *) pImage)[i] =
2577 : TripleToFloat( ((GUInt32)*(pabyImage + 0) << 16)
2578 : | ((GUInt32)*(pabyImage + 1) << 8)
2579 : | (GUInt32)*(pabyImage + 2) );
2580 : #else
2581 800 : ((GUInt32 *) pImage)[i] =
2582 : TripleToFloat( ((GUInt32)*(pabyImage + 2) << 16)
2583 : | ((GUInt32)*(pabyImage + 1) << 8)
2584 800 : | (GUInt32)*pabyImage );
2585 : #endif
2586 800 : pabyImage += iSkipBytes;
2587 : }
2588 : }
2589 : }
2590 :
2591 : /* -------------------------------------------------------------------- */
2592 : /* Special case for moving 12bit data somewhat more efficiently. */
2593 : /* -------------------------------------------------------------------- */
2594 160 : else if( poGDS->nBitsPerSample == 12 )
2595 : {
2596 40 : int iPixel, iBitOffset = 0;
2597 : int iPixelBitSkip, iBandBitOffset, iX, iY, nBitsPerLine;
2598 :
2599 40 : if( poGDS->nPlanarConfig == PLANARCONFIG_CONTIG )
2600 : {
2601 34 : iPixelBitSkip = poGDS->nBands * poGDS->nBitsPerSample;
2602 34 : iBandBitOffset = (nBand-1) * poGDS->nBitsPerSample;
2603 : }
2604 : else
2605 : {
2606 6 : iPixelBitSkip = poGDS->nBitsPerSample;
2607 6 : iBandBitOffset = 0;
2608 : }
2609 :
2610 : // bits per line rounds up to next byte boundary.
2611 40 : nBitsPerLine = nBlockXSize * iPixelBitSkip;
2612 40 : if( (nBitsPerLine & 7) != 0 )
2613 0 : nBitsPerLine = (nBitsPerLine + 7) & (~7);
2614 :
2615 40 : iPixel = 0;
2616 1808 : for( iY = 0; iY < nBlockYSize; iY++ )
2617 : {
2618 1768 : iBitOffset = iBandBitOffset + iY * nBitsPerLine;
2619 :
2620 131048 : for( iX = 0; iX < nBlockXSize; iX++ )
2621 : {
2622 129280 : int iByte = iBitOffset>>3;
2623 :
2624 129280 : if( (iBitOffset & 0x7) == 0 )
2625 : {
2626 : /* starting on byte boundary */
2627 :
2628 129680 : ((GUInt16 *) pImage)[iPixel++] =
2629 64840 : (poGDS->pabyBlockBuf[iByte] << 4)
2630 64840 : | (poGDS->pabyBlockBuf[iByte+1] >> 4);
2631 : }
2632 : else
2633 : {
2634 : /* starting off byte boundary */
2635 :
2636 128880 : ((GUInt16 *) pImage)[iPixel++] =
2637 64440 : ((poGDS->pabyBlockBuf[iByte] & 0xf) << 8)
2638 64440 : | (poGDS->pabyBlockBuf[iByte+1]);
2639 : }
2640 129280 : iBitOffset += iPixelBitSkip;
2641 : }
2642 : }
2643 : }
2644 :
2645 : /* -------------------------------------------------------------------- */
2646 : /* Special case for 24bit data which is pre-byteswapped since */
2647 : /* the size falls on a byte boundary ... ugg (#2361). */
2648 : /* -------------------------------------------------------------------- */
2649 120 : else if( poGDS->nBitsPerSample == 24 )
2650 : {
2651 : int iPixel;
2652 : int iPixelByteSkip, iBandByteOffset, iX, iY, nBytesPerLine;
2653 :
2654 22 : if( poGDS->nPlanarConfig == PLANARCONFIG_CONTIG )
2655 : {
2656 16 : iPixelByteSkip = (poGDS->nBands * poGDS->nBitsPerSample) / 8;
2657 16 : iBandByteOffset = ((nBand-1) * poGDS->nBitsPerSample) / 8;
2658 : }
2659 : else
2660 : {
2661 6 : iPixelByteSkip = poGDS->nBitsPerSample / 8;
2662 6 : iBandByteOffset = 0;
2663 : }
2664 :
2665 22 : nBytesPerLine = nBlockXSize * iPixelByteSkip;
2666 :
2667 22 : iPixel = 0;
2668 382 : for( iY = 0; iY < nBlockYSize; iY++ )
2669 : {
2670 : GByte *pabyImage =
2671 360 : poGDS->pabyBlockBuf + iBandByteOffset + iY * nBytesPerLine;
2672 :
2673 6760 : for( iX = 0; iX < nBlockXSize; iX++ )
2674 : {
2675 : #ifdef CPL_MSB
2676 : ((GUInt32 *) pImage)[iPixel++] =
2677 : ((GUInt32)*(pabyImage + 2) << 16)
2678 : | ((GUInt32)*(pabyImage + 1) << 8)
2679 : | (GUInt32)*(pabyImage + 0);
2680 : #else
2681 12800 : ((GUInt32 *) pImage)[iPixel++] =
2682 : ((GUInt32)*(pabyImage + 0) << 16)
2683 : | ((GUInt32)*(pabyImage + 1) << 8)
2684 6400 : | (GUInt32)*(pabyImage + 2);
2685 : #endif
2686 6400 : pabyImage += iPixelByteSkip;
2687 : }
2688 : }
2689 : }
2690 :
2691 : /* -------------------------------------------------------------------- */
2692 : /* Handle 1-32 bit integer data. */
2693 : /* -------------------------------------------------------------------- */
2694 : else
2695 : {
2696 98 : int iBit, iPixel, iBitOffset = 0;
2697 : int iPixelBitSkip, iBandBitOffset, iX, iY, nBitsPerLine;
2698 :
2699 98 : if( poGDS->nPlanarConfig == PLANARCONFIG_CONTIG )
2700 : {
2701 86 : iPixelBitSkip = poGDS->nBands * poGDS->nBitsPerSample;
2702 86 : iBandBitOffset = (nBand-1) * poGDS->nBitsPerSample;
2703 : }
2704 : else
2705 : {
2706 12 : iPixelBitSkip = poGDS->nBitsPerSample;
2707 12 : iBandBitOffset = 0;
2708 : }
2709 :
2710 : // bits per line rounds up to next byte boundary.
2711 98 : nBitsPerLine = nBlockXSize * iPixelBitSkip;
2712 98 : if( (nBitsPerLine & 7) != 0 )
2713 96 : nBitsPerLine = (nBitsPerLine + 7) & (~7);
2714 :
2715 98 : register GByte *pabyBlockBuf = poGDS->pabyBlockBuf;
2716 98 : iPixel = 0;
2717 :
2718 4570 : for( iY = 0; iY < nBlockYSize; iY++ )
2719 : {
2720 4472 : iBitOffset = iBandBitOffset + iY * nBitsPerLine;
2721 :
2722 361080 : for( iX = 0; iX < nBlockXSize; iX++ )
2723 : {
2724 356608 : int nOutWord = 0;
2725 :
2726 904684 : for( iBit = 0; iBit < poGDS->nBitsPerSample; iBit++ )
2727 : {
2728 548076 : if( pabyBlockBuf[iBitOffset>>3]
2729 : & (0x80 >>(iBitOffset & 7)) )
2730 275392 : nOutWord |= (1 << (poGDS->nBitsPerSample - 1 - iBit));
2731 548076 : iBitOffset++;
2732 : }
2733 :
2734 356608 : iBitOffset= iBitOffset + iPixelBitSkip - poGDS->nBitsPerSample;
2735 :
2736 356608 : if( eDataType == GDT_Byte )
2737 344604 : ((GByte *) pImage)[iPixel++] = (GByte) nOutWord;
2738 12004 : else if( eDataType == GDT_UInt16 )
2739 6402 : ((GUInt16 *) pImage)[iPixel++] = (GUInt16) nOutWord;
2740 5602 : else if( eDataType == GDT_UInt32 )
2741 5602 : ((GUInt32 *) pImage)[iPixel++] = nOutWord;
2742 : else
2743 0 : CPLAssert(0);
2744 : }
2745 : }
2746 : }
2747 :
2748 496 : return CE_None;
2749 : }
2750 :
2751 :
2752 : /************************************************************************/
2753 : /* ==================================================================== */
2754 : /* GTiffBitmapBand */
2755 : /* ==================================================================== */
2756 : /************************************************************************/
2757 :
2758 : class GTiffBitmapBand : public GTiffOddBitsBand
2759 : {
2760 : friend class GTiffDataset;
2761 :
2762 : GDALColorTable *poColorTable;
2763 :
2764 : public:
2765 :
2766 : GTiffBitmapBand( GTiffDataset *, int );
2767 : virtual ~GTiffBitmapBand();
2768 :
2769 : virtual GDALColorInterp GetColorInterpretation();
2770 : virtual GDALColorTable *GetColorTable();
2771 : };
2772 :
2773 :
2774 : /************************************************************************/
2775 : /* GTiffBitmapBand() */
2776 : /************************************************************************/
2777 :
2778 256 : GTiffBitmapBand::GTiffBitmapBand( GTiffDataset *poDS, int nBand )
2779 256 : : GTiffOddBitsBand( poDS, nBand )
2780 :
2781 : {
2782 256 : eDataType = GDT_Byte;
2783 :
2784 256 : if( poDS->poColorTable != NULL )
2785 34 : poColorTable = poDS->poColorTable->Clone();
2786 : else
2787 : {
2788 : #ifdef ESRI_BUILD
2789 : poColorTable = NULL;
2790 : #else
2791 : GDALColorEntry oWhite, oBlack;
2792 :
2793 222 : oWhite.c1 = 255;
2794 222 : oWhite.c2 = 255;
2795 222 : oWhite.c3 = 255;
2796 222 : oWhite.c4 = 255;
2797 :
2798 222 : oBlack.c1 = 0;
2799 222 : oBlack.c2 = 0;
2800 222 : oBlack.c3 = 0;
2801 222 : oBlack.c4 = 255;
2802 :
2803 222 : poColorTable = new GDALColorTable();
2804 :
2805 222 : if( poDS->nPhotometric == PHOTOMETRIC_MINISWHITE )
2806 : {
2807 0 : poColorTable->SetColorEntry( 0, &oWhite );
2808 0 : poColorTable->SetColorEntry( 1, &oBlack );
2809 : }
2810 : else
2811 : {
2812 222 : poColorTable->SetColorEntry( 0, &oBlack );
2813 222 : poColorTable->SetColorEntry( 1, &oWhite );
2814 : }
2815 : #endif /* not defined ESRI_BUILD */
2816 : }
2817 256 : }
2818 :
2819 : /************************************************************************/
2820 : /* ~GTiffBitmapBand() */
2821 : /************************************************************************/
2822 :
2823 256 : GTiffBitmapBand::~GTiffBitmapBand()
2824 :
2825 : {
2826 256 : delete poColorTable;
2827 256 : }
2828 :
2829 : /************************************************************************/
2830 : /* GetColorInterpretation() */
2831 : /************************************************************************/
2832 :
2833 42 : GDALColorInterp GTiffBitmapBand::GetColorInterpretation()
2834 :
2835 : {
2836 42 : if (poGDS->bPromoteTo8Bits)
2837 26 : return GCI_Undefined;
2838 : else
2839 16 : return GCI_PaletteIndex;
2840 : }
2841 :
2842 : /************************************************************************/
2843 : /* GetColorTable() */
2844 : /************************************************************************/
2845 :
2846 24 : GDALColorTable *GTiffBitmapBand::GetColorTable()
2847 :
2848 : {
2849 24 : if (poGDS->bPromoteTo8Bits)
2850 0 : return NULL;
2851 : else
2852 24 : return poColorTable;
2853 : }
2854 :
2855 : /************************************************************************/
2856 : /* ==================================================================== */
2857 : /* GTiffSplitBitmapBand */
2858 : /* ==================================================================== */
2859 : /************************************************************************/
2860 :
2861 : class GTiffSplitBitmapBand : public GTiffBitmapBand
2862 : {
2863 : friend class GTiffDataset;
2864 :
2865 : public:
2866 :
2867 : GTiffSplitBitmapBand( GTiffDataset *, int );
2868 : virtual ~GTiffSplitBitmapBand();
2869 :
2870 : virtual CPLErr IReadBlock( int, int, void * );
2871 : virtual CPLErr IWriteBlock( int, int, void * );
2872 : };
2873 :
2874 :
2875 : /************************************************************************/
2876 : /* GTiffSplitBitmapBand() */
2877 : /************************************************************************/
2878 :
2879 8 : GTiffSplitBitmapBand::GTiffSplitBitmapBand( GTiffDataset *poDS, int nBand )
2880 8 : : GTiffBitmapBand( poDS, nBand )
2881 :
2882 : {
2883 8 : nBlockXSize = poDS->GetRasterXSize();
2884 8 : nBlockYSize = 1;
2885 8 : }
2886 :
2887 : /************************************************************************/
2888 : /* ~GTiffSplitBitmapBand() */
2889 : /************************************************************************/
2890 :
2891 8 : GTiffSplitBitmapBand::~GTiffSplitBitmapBand()
2892 :
2893 : {
2894 8 : }
2895 :
2896 :
2897 : /************************************************************************/
2898 : /* IReadBlock() */
2899 : /************************************************************************/
2900 :
2901 43200 : CPLErr GTiffSplitBitmapBand::IReadBlock( int nBlockXOff, int nBlockYOff,
2902 : void * pImage )
2903 :
2904 : {
2905 : (void) nBlockXOff;
2906 :
2907 43200 : if (!poGDS->SetDirectory())
2908 0 : return CE_Failure;
2909 :
2910 43200 : if (poGDS->pabyBlockBuf == NULL)
2911 6 : poGDS->pabyBlockBuf = (GByte *) CPLMalloc(TIFFScanlineSize(poGDS->hTIFF));
2912 :
2913 : /* -------------------------------------------------------------------- */
2914 : /* Read through to target scanline. */
2915 : /* -------------------------------------------------------------------- */
2916 43200 : if( poGDS->nLastLineRead >= nBlockYOff )
2917 0 : poGDS->nLastLineRead = -1;
2918 :
2919 129600 : while( poGDS->nLastLineRead < nBlockYOff )
2920 : {
2921 43200 : if( TIFFReadScanline( poGDS->hTIFF, poGDS->pabyBlockBuf, ++poGDS->nLastLineRead, 0 ) == -1
2922 : && !poGDS->bIgnoreReadErrors )
2923 : {
2924 : CPLError( CE_Failure, CPLE_AppDefined,
2925 0 : "TIFFReadScanline() failed." );
2926 0 : return CE_Failure;
2927 : }
2928 : }
2929 :
2930 : /* -------------------------------------------------------------------- */
2931 : /* Translate 1bit data to eight bit. */
2932 : /* -------------------------------------------------------------------- */
2933 43200 : int iPixel, iSrcOffset=0, iDstOffset=0;
2934 :
2935 43243200 : for( iPixel = 0; iPixel < nBlockXSize; iPixel++, iSrcOffset++ )
2936 : {
2937 43200000 : if( poGDS->pabyBlockBuf[iSrcOffset >>3] & (0x80 >> (iSrcOffset & 0x7)) )
2938 42487260 : ((GByte *) pImage)[iDstOffset++] = 1;
2939 : else
2940 712740 : ((GByte *) pImage)[iDstOffset++] = 0;
2941 : }
2942 :
2943 43200 : return CE_None;
2944 : }
2945 :
2946 : /************************************************************************/
2947 : /* IWriteBlock() */
2948 : /************************************************************************/
2949 :
2950 0 : CPLErr GTiffSplitBitmapBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
2951 : void * pImage )
2952 :
2953 : {
2954 : (void) nBlockXOff;
2955 : (void) nBlockYOff;
2956 : (void) pImage;
2957 :
2958 : CPLError( CE_Failure, CPLE_AppDefined,
2959 0 : "Split bitmap bands are read-only." );
2960 0 : return CE_Failure;
2961 : }
2962 :
2963 : /************************************************************************/
2964 : /* ==================================================================== */
2965 : /* GTiffDataset */
2966 : /* ==================================================================== */
2967 : /************************************************************************/
2968 :
2969 :
2970 : /************************************************************************/
2971 : /* GTiffDataset() */
2972 : /************************************************************************/
2973 :
2974 10184 : GTiffDataset::GTiffDataset()
2975 :
2976 : {
2977 10184 : nLoadedBlock = -1;
2978 10184 : bLoadedBlockDirty = FALSE;
2979 10184 : pabyBlockBuf = NULL;
2980 10184 : bWriteErrorInFlushBlockBuf = FALSE;
2981 10184 : hTIFF = NULL;
2982 10184 : bNeedsRewrite = FALSE;
2983 10184 : bMetadataChanged = FALSE;
2984 10184 : bGeoTIFFInfoChanged = FALSE;
2985 10184 : bCrystalized = TRUE;
2986 10184 : poColorTable = NULL;
2987 10184 : bNoDataSet = FALSE;
2988 10184 : dfNoDataValue = -9999.0;
2989 10184 : pszProjection = CPLStrdup("");
2990 10184 : bLookedForProjection = FALSE;
2991 10184 : bBase = TRUE;
2992 10184 : bCloseTIFFHandle = FALSE;
2993 10184 : bTreatAsRGBA = FALSE;
2994 10184 : nOverviewCount = 0;
2995 10184 : papoOverviewDS = NULL;
2996 10184 : nDirOffset = 0;
2997 10184 : poActiveDS = NULL;
2998 10184 : ppoActiveDSRef = NULL;
2999 :
3000 10184 : bGeoTransformValid = FALSE;
3001 10184 : adfGeoTransform[0] = 0.0;
3002 10184 : adfGeoTransform[1] = 1.0;
3003 10184 : adfGeoTransform[2] = 0.0;
3004 10184 : adfGeoTransform[3] = 0.0;
3005 10184 : adfGeoTransform[4] = 0.0;
3006 10184 : adfGeoTransform[5] = 1.0;
3007 :
3008 10184 : nGCPCount = 0;
3009 10184 : pasGCPList = NULL;
3010 :
3011 10184 : osProfile = "GDALGeoTIFF";
3012 :
3013 10184 : papszCreationOptions = NULL;
3014 :
3015 10184 : nTempWriteBufferSize = 0;
3016 10184 : pabyTempWriteBuffer = NULL;
3017 :
3018 10184 : poMaskDS = NULL;
3019 10184 : poBaseDS = NULL;
3020 :
3021 10184 : bFillEmptyTiles = FALSE;
3022 10184 : bLoadingOtherBands = FALSE;
3023 10184 : nLastLineRead = -1;
3024 10184 : nLastBandRead = -1;
3025 10184 : bTreatAsSplit = FALSE;
3026 10184 : bTreatAsSplitBitmap = FALSE;
3027 10184 : bClipWarn = FALSE;
3028 10184 : bHasWarnedDisableAggressiveBandCaching = FALSE;
3029 10184 : bDontReloadFirstBlock = FALSE;
3030 :
3031 10184 : nZLevel = -1;
3032 10184 : nLZMAPreset = -1;
3033 10184 : nJpegQuality = -1;
3034 :
3035 10184 : bPromoteTo8Bits = FALSE;
3036 :
3037 10184 : bDebugDontWriteBlocks = CSLTestBoolean(CPLGetConfigOption("GTIFF_DONT_WRITE_BLOCKS", "NO"));
3038 :
3039 10184 : bIsFinalized = FALSE;
3040 10184 : bIgnoreReadErrors = CSLTestBoolean(CPLGetConfigOption("GTIFF_IGNORE_READ_ERRORS", "NO"));
3041 :
3042 10184 : bHasSearchedRPC = FALSE;
3043 10184 : bHasSearchedIMD = FALSE;
3044 10184 : bHasSearchedPVL = FALSE;
3045 :
3046 10184 : bScanDeferred = TRUE;
3047 :
3048 10184 : bDirectIO = CSLTestBoolean(CPLGetConfigOption("GTIFF_DIRECT_IO", "NO"));
3049 10184 : }
3050 :
3051 : /************************************************************************/
3052 : /* ~GTiffDataset() */
3053 : /************************************************************************/
3054 :
3055 10184 : GTiffDataset::~GTiffDataset()
3056 :
3057 : {
3058 10184 : Finalize();
3059 10184 : }
3060 :
3061 : /************************************************************************/
3062 : /* Finalize() */
3063 : /************************************************************************/
3064 :
3065 10186 : int GTiffDataset::Finalize()
3066 : {
3067 10186 : if (bIsFinalized)
3068 2 : return FALSE;
3069 :
3070 10184 : int bHasDroppedRef = FALSE;
3071 :
3072 10184 : Crystalize();
3073 :
3074 : /* -------------------------------------------------------------------- */
3075 : /* Handle forcing xml:ESRI data to be written to PAM. */
3076 : /* -------------------------------------------------------------------- */
3077 10184 : if( CSLTestBoolean(CPLGetConfigOption( "ESRI_XML_PAM", "NO" )) )
3078 : {
3079 14 : char **papszESRIMD = GetMetadata("xml:ESRI");
3080 14 : if( papszESRIMD )
3081 : {
3082 10 : GDALPamDataset::SetMetadata( papszESRIMD, "xml:ESRI");
3083 : }
3084 : }
3085 :
3086 : /* -------------------------------------------------------------------- */
3087 : /* Ensure any blocks write cached by GDAL gets pushed through libtiff.*/
3088 : /* -------------------------------------------------------------------- */
3089 10184 : GDALPamDataset::FlushCache();
3090 :
3091 : /* -------------------------------------------------------------------- */
3092 : /* Fill in missing blocks with empty data. */
3093 : /* -------------------------------------------------------------------- */
3094 10184 : if( bFillEmptyTiles )
3095 : {
3096 1864 : FillEmptyTiles();
3097 1864 : bFillEmptyTiles = FALSE;
3098 : }
3099 :
3100 : /* -------------------------------------------------------------------- */
3101 : /* Force a complete flush, including either rewriting(moving) */
3102 : /* of writing in place the current directory. */
3103 : /* -------------------------------------------------------------------- */
3104 10184 : FlushCache();
3105 :
3106 : /* -------------------------------------------------------------------- */
3107 : /* If there is still changed metadata, then presumably we want */
3108 : /* to push it into PAM. */
3109 : /* -------------------------------------------------------------------- */
3110 10184 : if( bMetadataChanged )
3111 : {
3112 60 : PushMetadataToPam();
3113 60 : bMetadataChanged = FALSE;
3114 60 : GDALPamDataset::FlushCache();
3115 : }
3116 :
3117 : /* -------------------------------------------------------------------- */
3118 : /* Cleanup overviews. */
3119 : /* -------------------------------------------------------------------- */
3120 10184 : if( bBase )
3121 : {
3122 9952 : for( int i = 0; i < nOverviewCount; i++ )
3123 : {
3124 510 : delete papoOverviewDS[i];
3125 510 : bHasDroppedRef = TRUE;
3126 : }
3127 9442 : nOverviewCount = 0;
3128 : }
3129 :
3130 : /* If we are a mask dataset, we can have overviews, but we don't */
3131 : /* own them. We can only free the array, not the overviews themselves */
3132 10184 : CPLFree( papoOverviewDS );
3133 10184 : papoOverviewDS = NULL;
3134 :
3135 : /* poMaskDS is owned by the main image and the overviews */
3136 : /* so because of the latter case, we can delete it even if */
3137 : /* we are not the base image */
3138 10184 : if (poMaskDS)
3139 : {
3140 216 : delete poMaskDS;
3141 216 : poMaskDS = NULL;
3142 216 : bHasDroppedRef = TRUE;
3143 : }
3144 :
3145 10184 : if( poColorTable != NULL )
3146 196 : delete poColorTable;
3147 10184 : poColorTable = NULL;
3148 :
3149 10184 : if( bBase || bCloseTIFFHandle )
3150 : {
3151 9454 : XTIFFClose( hTIFF );
3152 9454 : hTIFF = NULL;
3153 : }
3154 :
3155 10184 : if( nGCPCount > 0 )
3156 : {
3157 58 : GDALDeinitGCPs( nGCPCount, pasGCPList );
3158 58 : CPLFree( pasGCPList );
3159 58 : pasGCPList = NULL;
3160 58 : nGCPCount = 0;
3161 : }
3162 :
3163 10184 : CPLFree( pszProjection );
3164 10184 : pszProjection = NULL;
3165 :
3166 10184 : CSLDestroy( papszCreationOptions );
3167 10184 : papszCreationOptions = NULL;
3168 :
3169 10184 : CPLFree(pabyTempWriteBuffer);
3170 10184 : pabyTempWriteBuffer = NULL;
3171 :
3172 10184 : if( *ppoActiveDSRef == this )
3173 9654 : *ppoActiveDSRef = NULL;
3174 10184 : ppoActiveDSRef = NULL;
3175 :
3176 10184 : bIsFinalized = TRUE;
3177 :
3178 10184 : return bHasDroppedRef;
3179 : }
3180 :
3181 : /************************************************************************/
3182 : /* CloseDependentDatasets() */
3183 : /************************************************************************/
3184 :
3185 2 : int GTiffDataset::CloseDependentDatasets()
3186 : {
3187 2 : if (!bBase)
3188 0 : return FALSE;
3189 :
3190 2 : int bHasDroppedRef = GDALPamDataset::CloseDependentDatasets();
3191 :
3192 2 : bHasDroppedRef |= Finalize();
3193 :
3194 2 : return bHasDroppedRef;
3195 : }
3196 :
3197 : /************************************************************************/
3198 : /* FillEmptyTiles() */
3199 : /************************************************************************/
3200 :
3201 1864 : void GTiffDataset::FillEmptyTiles()
3202 :
3203 : {
3204 1864 : toff_t *panByteCounts = NULL;
3205 : int nBlockCount, iBlock;
3206 :
3207 1864 : if (!SetDirectory())
3208 0 : return;
3209 :
3210 : /* -------------------------------------------------------------------- */
3211 : /* How many blocks are there in this file? */
3212 : /* -------------------------------------------------------------------- */
3213 1864 : if( nPlanarConfig == PLANARCONFIG_SEPARATE )
3214 14 : nBlockCount = nBlocksPerBand * nBands;
3215 : else
3216 1850 : nBlockCount = nBlocksPerBand;
3217 :
3218 : /* -------------------------------------------------------------------- */
3219 : /* Fetch block maps. */
3220 : /* -------------------------------------------------------------------- */
3221 1864 : if( TIFFIsTiled( hTIFF ) )
3222 36 : TIFFGetField( hTIFF, TIFFTAG_TILEBYTECOUNTS, &panByteCounts );
3223 : else
3224 1828 : TIFFGetField( hTIFF, TIFFTAG_STRIPBYTECOUNTS, &panByteCounts );
3225 :
3226 1864 : if (panByteCounts == NULL)
3227 : {
3228 : /* Got here with libtiff 3.9.3 and tiff_write_8 test */
3229 0 : CPLError(CE_Failure, CPLE_AppDefined, "FillEmptyTiles() failed because panByteCounts == NULL");
3230 0 : return;
3231 : }
3232 :
3233 : /* -------------------------------------------------------------------- */
3234 : /* Prepare a blank data buffer to write for uninitialized blocks. */
3235 : /* -------------------------------------------------------------------- */
3236 : int nBlockBytes;
3237 :
3238 1864 : if( TIFFIsTiled( hTIFF ) )
3239 36 : nBlockBytes = TIFFTileSize(hTIFF);
3240 : else
3241 1828 : nBlockBytes = TIFFStripSize(hTIFF);
3242 :
3243 1864 : GByte *pabyData = (GByte *) VSICalloc(nBlockBytes,1);
3244 1864 : if (pabyData == NULL)
3245 : {
3246 : CPLError(CE_Failure, CPLE_OutOfMemory,
3247 0 : "Cannot allocate %d bytes", nBlockBytes);
3248 0 : return;
3249 : }
3250 :
3251 : /* -------------------------------------------------------------------- */
3252 : /* Check all blocks, writing out data for uninitialized blocks. */
3253 : /* -------------------------------------------------------------------- */
3254 199286 : for( iBlock = 0; iBlock < nBlockCount; iBlock++ )
3255 : {
3256 197422 : if( panByteCounts[iBlock] == 0 )
3257 : {
3258 175258 : if( WriteEncodedTileOrStrip( iBlock, pabyData, FALSE ) != CE_None )
3259 0 : break;
3260 : }
3261 : }
3262 :
3263 1864 : CPLFree( pabyData );
3264 : }
3265 :
3266 : /************************************************************************/
3267 : /* WriteEncodedTile() */
3268 : /************************************************************************/
3269 :
3270 19342 : int GTiffDataset::WriteEncodedTile(uint32 tile, GByte *pabyData,
3271 : int bPreserveDataBuffer)
3272 : {
3273 19342 : int cc = TIFFTileSize( hTIFF );
3274 19342 : int bNeedTileFill = FALSE;
3275 19342 : int iRow=0, iColumn=0;
3276 19342 : int nBlocksPerRow=1, nBlocksPerColumn=1;
3277 :
3278 : /*
3279 : ** Do we need to spread edge values right or down for a partial
3280 : ** JPEG encoded tile? We do this to avoid edge artifacts.
3281 : */
3282 19342 : if( nCompression == COMPRESSION_JPEG )
3283 : {
3284 700 : nBlocksPerRow = (nRasterXSize + nBlockXSize - 1) / nBlockXSize;
3285 700 : nBlocksPerColumn = (nRasterYSize + nBlockYSize - 1) / nBlockYSize;
3286 :
3287 700 : iColumn = (tile % nBlocksPerBand) % nBlocksPerRow;
3288 700 : iRow = (tile % nBlocksPerBand) / nBlocksPerRow;
3289 :
3290 : // Is this a partial right edge tile?
3291 700 : if( iRow == nBlocksPerRow - 1
3292 : && nRasterXSize % nBlockXSize != 0 )
3293 54 : bNeedTileFill = TRUE;
3294 :
3295 : // Is this a partial bottom edge tile?
3296 700 : if( iColumn == nBlocksPerColumn - 1
3297 : && nRasterYSize % nBlockYSize != 0 )
3298 74 : bNeedTileFill = TRUE;
3299 : }
3300 :
3301 : /*
3302 : ** If we need to fill out the tile, or if we want to prevent
3303 : ** TIFFWriteEncodedTile from altering the buffer as part of
3304 : ** byte swapping the data on write then we will need a temporary
3305 : ** working buffer. If not, we can just do a direct write.
3306 : */
3307 19342 : if (bPreserveDataBuffer
3308 : && (TIFFIsByteSwapped(hTIFF) || bNeedTileFill) )
3309 : {
3310 152 : if (cc != nTempWriteBufferSize)
3311 : {
3312 58 : pabyTempWriteBuffer = CPLRealloc(pabyTempWriteBuffer, cc);
3313 58 : nTempWriteBufferSize = cc;
3314 : }
3315 152 : memcpy(pabyTempWriteBuffer, pabyData, cc);
3316 :
3317 152 : pabyData = (GByte *) pabyTempWriteBuffer;
3318 : }
3319 :
3320 : /*
3321 : ** Perform tile fill if needed.
3322 : */
3323 19342 : if( bNeedTileFill )
3324 : {
3325 74 : int nRightPixelsToFill = 0;
3326 74 : int nBottomPixelsToFill = 0;
3327 74 : int nPixelSize = cc / (nBlockXSize * nBlockYSize);
3328 : unsigned int iX, iY, iSrcX, iSrcY;
3329 :
3330 74 : CPLDebug( "GTiff", "Filling out jpeg edge tile on write." );
3331 :
3332 74 : if( iColumn == nBlocksPerRow - 1 )
3333 54 : nRightPixelsToFill = nBlockXSize * (iColumn+1) - nRasterXSize;
3334 74 : if( iRow == nBlocksPerColumn - 1 )
3335 58 : nBottomPixelsToFill = nBlockYSize * (iRow+1) - nRasterYSize;
3336 :
3337 : // Fill out to the right.
3338 74 : iSrcX = nBlockXSize - nRightPixelsToFill - 1;
3339 :
3340 4066 : for( iX = iSrcX+1; iX < nBlockXSize; iX++ )
3341 : {
3342 514968 : for( iY = 0; iY < nBlockYSize; iY++ )
3343 : {
3344 : memcpy( pabyData + (nBlockXSize * iY + iX) * nPixelSize,
3345 : pabyData + (nBlockXSize * iY + iSrcX) * nPixelSize,
3346 510976 : nPixelSize );
3347 : }
3348 : }
3349 :
3350 : // now fill out the bottom.
3351 74 : iSrcY = nBlockYSize - nBottomPixelsToFill - 1;
3352 4346 : for( iY = iSrcY+1; iY < nBlockYSize; iY++ )
3353 : {
3354 : memcpy( pabyData + nBlockXSize * nPixelSize * iY,
3355 : pabyData + nBlockXSize * nPixelSize * iSrcY,
3356 4272 : nPixelSize * nBlockXSize );
3357 : }
3358 : }
3359 :
3360 19342 : return TIFFWriteEncodedTile(hTIFF, tile, pabyData, cc);
3361 : }
3362 :
3363 : /************************************************************************/
3364 : /* WriteEncodedStrip() */
3365 : /************************************************************************/
3366 :
3367 191180 : int GTiffDataset::WriteEncodedStrip(uint32 strip, GByte* pabyData,
3368 : int bPreserveDataBuffer)
3369 : {
3370 191180 : int cc = TIFFStripSize( hTIFF );
3371 :
3372 : /* -------------------------------------------------------------------- */
3373 : /* If this is the last strip in the image, and is partial, then */
3374 : /* we need to trim the number of scanlines written to the */
3375 : /* amount of valid data we have. (#2748) */
3376 : /* -------------------------------------------------------------------- */
3377 191180 : int nStripWithinBand = strip % nBlocksPerBand;
3378 :
3379 191180 : if( (int) ((nStripWithinBand+1) * nRowsPerStrip) > GetRasterYSize() )
3380 : {
3381 : cc = (cc / nRowsPerStrip)
3382 328 : * (GetRasterYSize() - nStripWithinBand * nRowsPerStrip);
3383 : CPLDebug( "GTiff", "Adjusted bytes to write from %d to %d.",
3384 328 : (int) TIFFStripSize(hTIFF), cc );
3385 : }
3386 :
3387 : /* -------------------------------------------------------------------- */
3388 : /* TIFFWriteEncodedStrip can alter the passed buffer if */
3389 : /* byte-swapping is necessary so we use a temporary buffer */
3390 : /* before calling it. */
3391 : /* -------------------------------------------------------------------- */
3392 191180 : if (bPreserveDataBuffer && TIFFIsByteSwapped(hTIFF))
3393 : {
3394 56 : if (cc != nTempWriteBufferSize)
3395 : {
3396 44 : pabyTempWriteBuffer = CPLRealloc(pabyTempWriteBuffer, cc);
3397 44 : nTempWriteBufferSize = cc;
3398 : }
3399 56 : memcpy(pabyTempWriteBuffer, pabyData, cc);
3400 56 : return TIFFWriteEncodedStrip(hTIFF, strip, pabyTempWriteBuffer, cc);
3401 : }
3402 : else
3403 191124 : return TIFFWriteEncodedStrip(hTIFF, strip, pabyData, cc);
3404 : }
3405 :
3406 : /************************************************************************/
3407 : /* WriteEncodedTileOrStrip() */
3408 : /************************************************************************/
3409 :
3410 210522 : CPLErr GTiffDataset::WriteEncodedTileOrStrip(uint32 tile_or_strip, void* data,
3411 : int bPreserveDataBuffer)
3412 : {
3413 210522 : CPLErr eErr = CE_None;
3414 :
3415 210522 : if( TIFFIsTiled( hTIFF ) )
3416 : {
3417 19342 : if( WriteEncodedTile(tile_or_strip, (GByte*) data,
3418 : bPreserveDataBuffer) == -1 )
3419 : {
3420 0 : eErr = CE_Failure;
3421 : }
3422 : }
3423 : else
3424 : {
3425 191180 : if( WriteEncodedStrip(tile_or_strip, (GByte *) data,
3426 : bPreserveDataBuffer) == -1 )
3427 : {
3428 0 : eErr = CE_Failure;
3429 : }
3430 : }
3431 :
3432 210522 : return eErr;
3433 : }
3434 :
3435 : /************************************************************************/
3436 : /* FlushBlockBuf() */
3437 : /************************************************************************/
3438 :
3439 445426 : CPLErr GTiffDataset::FlushBlockBuf()
3440 :
3441 : {
3442 445426 : CPLErr eErr = CE_None;
3443 :
3444 445426 : if( nLoadedBlock < 0 || !bLoadedBlockDirty )
3445 440314 : return CE_None;
3446 :
3447 5112 : bLoadedBlockDirty = FALSE;
3448 :
3449 5112 : if (!SetDirectory())
3450 0 : return CE_Failure;
3451 :
3452 5112 : eErr = WriteEncodedTileOrStrip(nLoadedBlock, pabyBlockBuf, TRUE);
3453 5112 : if (eErr != CE_None)
3454 : {
3455 : CPLError( CE_Failure, CPLE_AppDefined,
3456 0 : "WriteEncodedTile/Strip() failed." );
3457 0 : bWriteErrorInFlushBlockBuf = TRUE;
3458 : }
3459 :
3460 5112 : return eErr;
3461 : }
3462 :
3463 : /************************************************************************/
3464 : /* LoadBlockBuf() */
3465 : /* */
3466 : /* Load working block buffer with request block (tile/strip). */
3467 : /************************************************************************/
3468 :
3469 149162 : CPLErr GTiffDataset::LoadBlockBuf( int nBlockId, int bReadFromDisk )
3470 :
3471 : {
3472 : int nBlockBufSize;
3473 149162 : CPLErr eErr = CE_None;
3474 :
3475 149162 : if( nLoadedBlock == nBlockId )
3476 139822 : return CE_None;
3477 :
3478 : /* -------------------------------------------------------------------- */
3479 : /* If we have a dirty loaded block, flush it out first. */
3480 : /* -------------------------------------------------------------------- */
3481 9340 : if( nLoadedBlock != -1 && bLoadedBlockDirty )
3482 : {
3483 0 : eErr = FlushBlockBuf();
3484 0 : if( eErr != CE_None )
3485 0 : return eErr;
3486 : }
3487 :
3488 : /* -------------------------------------------------------------------- */
3489 : /* Get block size. */
3490 : /* -------------------------------------------------------------------- */
3491 9340 : if( TIFFIsTiled(hTIFF) )
3492 1672 : nBlockBufSize = TIFFTileSize( hTIFF );
3493 : else
3494 7668 : nBlockBufSize = TIFFStripSize( hTIFF );
3495 :
3496 9340 : if ( !nBlockBufSize )
3497 : {
3498 : CPLError( CE_Failure, CPLE_AppDefined,
3499 0 : "Bogus block size; unable to allocate a buffer.");
3500 0 : return CE_Failure;
3501 : }
3502 :
3503 : /* -------------------------------------------------------------------- */
3504 : /* Allocate a temporary buffer for this strip. */
3505 : /* -------------------------------------------------------------------- */
3506 9340 : if( pabyBlockBuf == NULL )
3507 : {
3508 1012 : pabyBlockBuf = (GByte *) VSICalloc( 1, nBlockBufSize );
3509 1012 : if( pabyBlockBuf == NULL )
3510 : {
3511 : CPLError( CE_Failure, CPLE_OutOfMemory,
3512 : "Unable to allocate %d bytes for a temporary strip "
3513 : "buffer in GTIFF driver.",
3514 0 : nBlockBufSize );
3515 :
3516 0 : return( CE_Failure );
3517 : }
3518 : }
3519 :
3520 : /* -------------------------------------------------------------------- */
3521 : /* When called from ::IWriteBlock in separate cases (or in single band */
3522 : /* geotiffs), the ::IWriteBlock will override the content of the buffer*/
3523 : /* with pImage, so we don't need to read data from disk */
3524 : /* -------------------------------------------------------------------- */
3525 9340 : if( !bReadFromDisk )
3526 : {
3527 838 : nLoadedBlock = nBlockId;
3528 838 : return CE_None;
3529 : }
3530 :
3531 : /* libtiff 3.X doesn't like mixing read&write of JPEG compressed blocks */
3532 : /* The below hack is necessary due to another hack that consist in */
3533 : /* writing zero block to force creation of JPEG tables */
3534 8502 : if( nBlockId == 0 && bDontReloadFirstBlock )
3535 : {
3536 0 : bDontReloadFirstBlock = FALSE;
3537 0 : memset( pabyBlockBuf, 0, nBlockBufSize );
3538 0 : nLoadedBlock = nBlockId;
3539 0 : return CE_None;
3540 : }
3541 :
3542 : /* -------------------------------------------------------------------- */
3543 : /* The bottom most partial tiles and strips are sometimes only */
3544 : /* partially encoded. This code reduces the requested data so */
3545 : /* an error won't be reported in this case. (#1179) */
3546 : /* -------------------------------------------------------------------- */
3547 8502 : int nBlockReqSize = nBlockBufSize;
3548 8502 : int nBlocksPerRow = (nRasterXSize + nBlockXSize - 1) / nBlockXSize;
3549 8502 : int nBlockYOff = (nBlockId % nBlocksPerBand) / nBlocksPerRow;
3550 :
3551 8502 : if( (int)((nBlockYOff+1) * nBlockYSize) > nRasterYSize )
3552 : {
3553 : nBlockReqSize = (nBlockBufSize / nBlockYSize)
3554 430 : * (nBlockYSize - (((nBlockYOff+1) * nBlockYSize) % nRasterYSize));
3555 430 : memset( pabyBlockBuf, 0, nBlockBufSize );
3556 : }
3557 :
3558 : /* -------------------------------------------------------------------- */
3559 : /* If we don't have this block already loaded, and we know it */
3560 : /* doesn't yet exist on disk, just zero the memory buffer and */
3561 : /* pretend we loaded it. */
3562 : /* -------------------------------------------------------------------- */
3563 8502 : if( !IsBlockAvailable( nBlockId ) )
3564 : {
3565 4138 : memset( pabyBlockBuf, 0, nBlockBufSize );
3566 4138 : nLoadedBlock = nBlockId;
3567 4138 : return CE_None;
3568 : }
3569 :
3570 : /* -------------------------------------------------------------------- */
3571 : /* Load the block, if it isn't our current block. */
3572 : /* -------------------------------------------------------------------- */
3573 4364 : if( TIFFIsTiled( hTIFF ) )
3574 : {
3575 678 : if( TIFFReadEncodedTile(hTIFF, nBlockId, pabyBlockBuf,
3576 : nBlockReqSize) == -1
3577 : && !bIgnoreReadErrors )
3578 : {
3579 : /* Once TIFFError() is properly hooked, this can go away */
3580 : CPLError( CE_Failure, CPLE_AppDefined,
3581 0 : "TIFFReadEncodedTile() failed." );
3582 :
3583 0 : memset( pabyBlockBuf, 0, nBlockBufSize );
3584 :
3585 0 : eErr = CE_Failure;
3586 : }
3587 : }
3588 : else
3589 : {
3590 3686 : if( TIFFReadEncodedStrip(hTIFF, nBlockId, pabyBlockBuf,
3591 : nBlockReqSize) == -1
3592 : && !bIgnoreReadErrors )
3593 : {
3594 : /* Once TIFFError() is properly hooked, this can go away */
3595 : CPLError( CE_Failure, CPLE_AppDefined,
3596 0 : "TIFFReadEncodedStrip() failed." );
3597 :
3598 0 : memset( pabyBlockBuf, 0, nBlockBufSize );
3599 :
3600 0 : eErr = CE_Failure;
3601 : }
3602 : }
3603 :
3604 4364 : nLoadedBlock = nBlockId;
3605 4364 : bLoadedBlockDirty = FALSE;
3606 :
3607 4364 : return eErr;
3608 : }
3609 :
3610 :
3611 : /************************************************************************/
3612 : /* Crystalize() */
3613 : /* */
3614 : /* Make sure that the directory information is written out for */
3615 : /* a new file, require before writing any imagery data. */
3616 : /************************************************************************/
3617 :
3618 455322 : void GTiffDataset::Crystalize()
3619 :
3620 : {
3621 455322 : if( !bCrystalized )
3622 : {
3623 : WriteMetadata( this, hTIFF, TRUE, osProfile, osFilename,
3624 1900 : papszCreationOptions );
3625 1900 : WriteGeoTIFFInfo();
3626 :
3627 1900 : bMetadataChanged = FALSE;
3628 1900 : bGeoTIFFInfoChanged = FALSE;
3629 1900 : bNeedsRewrite = FALSE;
3630 :
3631 1900 : bCrystalized = TRUE;
3632 :
3633 1900 : TIFFWriteCheck( hTIFF, TIFFIsTiled(hTIFF), "GTiffDataset::Crystalize");
3634 :
3635 : // Keep zip and tiff quality, and jpegcolormode which get reset when we call
3636 : // TIFFWriteDirectory
3637 1900 : int jquality = -1, zquality = -1, nColorMode = -1;
3638 1900 : TIFFGetField(hTIFF, TIFFTAG_JPEGQUALITY, &jquality);
3639 1900 : TIFFGetField(hTIFF, TIFFTAG_ZIPQUALITY, &zquality);
3640 1900 : TIFFGetField( hTIFF, TIFFTAG_JPEGCOLORMODE, &nColorMode );
3641 :
3642 1900 : TIFFWriteDirectory( hTIFF );
3643 1900 : TIFFSetDirectory( hTIFF, 0 );
3644 :
3645 :
3646 : // Now, reset zip and tiff quality and jpegcolormode.
3647 1900 : if(jquality > 0)
3648 28 : TIFFSetField(hTIFF, TIFFTAG_JPEGQUALITY, jquality);
3649 1900 : if(zquality > 0)
3650 0 : TIFFSetField(hTIFF, TIFFTAG_ZIPQUALITY, zquality);
3651 1900 : if (nColorMode >= 0)
3652 28 : TIFFSetField(hTIFF, TIFFTAG_JPEGCOLORMODE, nColorMode);
3653 :
3654 1900 : nDirOffset = TIFFCurrentDirOffset( hTIFF );
3655 : }
3656 455322 : }
3657 :
3658 :
3659 : /************************************************************************/
3660 : /* IsBlockAvailable() */
3661 : /* */
3662 : /* Return TRUE if the indicated strip/tile is available. We */
3663 : /* establish this by testing if the stripbytecount is zero. If */
3664 : /* zero then the block has never been committed to disk. */
3665 : /************************************************************************/
3666 :
3667 206288 : int GTiffDataset::IsBlockAvailable( int nBlockId )
3668 :
3669 : {
3670 206288 : toff_t *panByteCounts = NULL;
3671 :
3672 206288 : if( ( TIFFIsTiled( hTIFF )
3673 : && TIFFGetField( hTIFF, TIFFTAG_TILEBYTECOUNTS, &panByteCounts ) )
3674 : || ( !TIFFIsTiled( hTIFF )
3675 : && TIFFGetField( hTIFF, TIFFTAG_STRIPBYTECOUNTS, &panByteCounts ) ) )
3676 : {
3677 206288 : if( panByteCounts == NULL )
3678 0 : return FALSE;
3679 : else
3680 206288 : return panByteCounts[nBlockId] != 0;
3681 : }
3682 : else
3683 0 : return FALSE;
3684 : }
3685 :
3686 : /************************************************************************/
3687 : /* FlushCache() */
3688 : /* */
3689 : /* We override this so we can also flush out local tiff strip */
3690 : /* cache if need be. */
3691 : /************************************************************************/
3692 :
3693 11402 : void GTiffDataset::FlushCache()
3694 :
3695 : {
3696 11402 : if (bIsFinalized)
3697 0 : return;
3698 :
3699 11402 : GDALPamDataset::FlushCache();
3700 :
3701 11402 : if( bLoadedBlockDirty && nLoadedBlock != -1 )
3702 288 : FlushBlockBuf();
3703 :
3704 11402 : CPLFree( pabyBlockBuf );
3705 11402 : pabyBlockBuf = NULL;
3706 11402 : nLoadedBlock = -1;
3707 11402 : bLoadedBlockDirty = FALSE;
3708 :
3709 11402 : if (!SetDirectory())
3710 0 : return;
3711 11402 : FlushDirectory();
3712 : }
3713 :
3714 : /************************************************************************/
3715 : /* FlushDirectory() */
3716 : /************************************************************************/
3717 :
3718 14032 : void GTiffDataset::FlushDirectory()
3719 :
3720 : {
3721 14032 : if( GetAccess() == GA_Update )
3722 : {
3723 6702 : if( bMetadataChanged )
3724 : {
3725 30 : if (!SetDirectory())
3726 0 : return;
3727 : bNeedsRewrite =
3728 : WriteMetadata( this, hTIFF, TRUE, osProfile, osFilename,
3729 30 : papszCreationOptions );
3730 30 : bMetadataChanged = FALSE;
3731 : }
3732 :
3733 6702 : if( bGeoTIFFInfoChanged )
3734 : {
3735 32 : if (!SetDirectory())
3736 0 : return;
3737 32 : WriteGeoTIFFInfo();
3738 : }
3739 :
3740 6702 : if( bNeedsRewrite )
3741 : {
3742 : #if defined(TIFFLIB_VERSION)
3743 : #if defined(HAVE_TIFFGETSIZEPROC)
3744 144 : if (!SetDirectory())
3745 0 : return;
3746 :
3747 144 : TIFFSizeProc pfnSizeProc = TIFFGetSizeProc( hTIFF );
3748 :
3749 144 : nDirOffset = pfnSizeProc( TIFFClientdata( hTIFF ) );
3750 144 : if( (nDirOffset % 2) == 1 )
3751 28 : nDirOffset++;
3752 :
3753 144 : TIFFRewriteDirectory( hTIFF );
3754 :
3755 144 : TIFFSetSubDirectory( hTIFF, nDirOffset );
3756 : #elif TIFFLIB_VERSION > 20010925 && TIFFLIB_VERSION != 20011807
3757 : if (!SetDirectory())
3758 : return;
3759 :
3760 : TIFFRewriteDirectory( hTIFF );
3761 : #endif
3762 : #endif
3763 144 : bNeedsRewrite = FALSE;
3764 : }
3765 : }
3766 :
3767 : // there are some circumstances in which we can reach this point
3768 : // without having made this our directory (SetDirectory()) in which
3769 : // case we should not risk a flush.
3770 14032 : if( GetAccess() == GA_Update && TIFFCurrentDirOffset(hTIFF) == nDirOffset )
3771 : {
3772 : #if defined(BIGTIFF_SUPPORT)
3773 6666 : TIFFSizeProc pfnSizeProc = TIFFGetSizeProc( hTIFF );
3774 :
3775 6666 : toff_t nNewDirOffset = pfnSizeProc( TIFFClientdata( hTIFF ) );
3776 6666 : if( (nNewDirOffset % 2) == 1 )
3777 824 : nNewDirOffset++;
3778 :
3779 6666 : TIFFFlush( hTIFF );
3780 :
3781 6666 : if( nDirOffset != TIFFCurrentDirOffset( hTIFF ) )
3782 : {
3783 104 : nDirOffset = nNewDirOffset;
3784 : CPLDebug( "GTiff",
3785 104 : "directory moved during flush in FlushDirectory()" );
3786 : }
3787 : #else
3788 : /* For libtiff 3.X, the above causes regressions and crashes in */
3789 : /* tiff_write.py and tiff_ovr.py */
3790 : TIFFFlush( hTIFF );
3791 : #endif
3792 : }
3793 : }
3794 :
3795 : /************************************************************************/
3796 : /* TIFF_OvLevelAdjust() */
3797 : /* */
3798 : /* Some overview levels cannot be achieved closely enough to be */
3799 : /* recognised as the desired overview level. This function */
3800 : /* will adjust an overview level to one that is achievable on */
3801 : /* the given raster size. */
3802 : /* */
3803 : /* For instance a 1200x1200 image on which a 256 level overview */
3804 : /* is request will end up generating a 5x5 overview. However, */
3805 : /* this will appear to the system be a level 240 overview. */
3806 : /* This function will adjust 256 to 240 based on knowledge of */
3807 : /* the image size. */
3808 : /* */
3809 : /* This is a copy of the GDALOvLevelAdjust() function in */
3810 : /* gdaldefaultoverviews.cpp. */
3811 : /************************************************************************/
3812 :
3813 302 : static int TIFF_OvLevelAdjust( int nOvLevel, int nXSize )
3814 :
3815 : {
3816 302 : int nOXSize = (nXSize + nOvLevel - 1) / nOvLevel;
3817 :
3818 302 : return (int) (0.5 + nXSize / (double) nOXSize);
3819 : }
3820 :
3821 : /************************************************************************/
3822 : /* CleanOverviews() */
3823 : /************************************************************************/
3824 :
3825 4 : CPLErr GTiffDataset::CleanOverviews()
3826 :
3827 : {
3828 4 : CPLAssert( bBase );
3829 :
3830 4 : ScanDirectories();
3831 :
3832 4 : FlushDirectory();
3833 4 : *ppoActiveDSRef = NULL;
3834 :
3835 : /* -------------------------------------------------------------------- */
3836 : /* Cleanup overviews objects, and get offsets to all overview */
3837 : /* directories. */
3838 : /* -------------------------------------------------------------------- */
3839 4 : std::vector<toff_t> anOvDirOffsets;
3840 : int i;
3841 :
3842 8 : for( i = 0; i < nOverviewCount; i++ )
3843 : {
3844 4 : anOvDirOffsets.push_back( papoOverviewDS[i]->nDirOffset );
3845 4 : delete papoOverviewDS[i];
3846 : }
3847 :
3848 : /* -------------------------------------------------------------------- */
3849 : /* Loop through all the directories, translating the offsets */
3850 : /* into indexes we can use with TIFFUnlinkDirectory(). */
3851 : /* -------------------------------------------------------------------- */
3852 4 : std::vector<uint16> anOvDirIndexes;
3853 4 : int iThisOffset = 1;
3854 :
3855 4 : TIFFSetDirectory( hTIFF, 0 );
3856 :
3857 4 : for( ; TRUE; )
3858 : {
3859 16 : for( i = 0; i < nOverviewCount; i++ )
3860 : {
3861 8 : if( anOvDirOffsets[i] == TIFFCurrentDirOffset( hTIFF ) )
3862 : {
3863 : CPLDebug( "GTiff", "%d -> %d",
3864 4 : (int) anOvDirOffsets[i], iThisOffset );
3865 4 : anOvDirIndexes.push_back( (uint16) iThisOffset );
3866 : }
3867 : }
3868 :
3869 8 : if( TIFFLastDirectory( hTIFF ) )
3870 : break;
3871 :
3872 4 : TIFFReadDirectory( hTIFF );
3873 4 : iThisOffset++;
3874 : }
3875 :
3876 : /* -------------------------------------------------------------------- */
3877 : /* Actually unlink the target directories. Note that we do */
3878 : /* this from last to first so as to avoid renumbering any of */
3879 : /* the earlier directories we need to remove. */
3880 : /* -------------------------------------------------------------------- */
3881 12 : while( !anOvDirIndexes.empty() )
3882 : {
3883 4 : TIFFUnlinkDirectory( hTIFF, anOvDirIndexes.back() );
3884 4 : anOvDirIndexes.pop_back();
3885 : }
3886 :
3887 4 : CPLFree( papoOverviewDS );
3888 :
3889 4 : nOverviewCount = 0;
3890 4 : papoOverviewDS = NULL;
3891 :
3892 4 : if (!SetDirectory())
3893 0 : return CE_Failure;
3894 :
3895 4 : return CE_None;
3896 : }
3897 :
3898 :
3899 : /************************************************************************/
3900 : /* RegisterNewOverviewDataset() */
3901 : /************************************************************************/
3902 :
3903 246 : CPLErr GTiffDataset::RegisterNewOverviewDataset(toff_t nOverviewOffset)
3904 : {
3905 246 : GTiffDataset* poODS = new GTiffDataset();
3906 246 : poODS->nJpegQuality = nJpegQuality;
3907 246 : poODS->nZLevel = nZLevel;
3908 246 : poODS->nLZMAPreset = nLZMAPreset;
3909 :
3910 246 : if( nCompression == COMPRESSION_JPEG )
3911 : {
3912 36 : if ( CPLGetConfigOption( "JPEG_QUALITY_OVERVIEW", NULL ) != NULL )
3913 : {
3914 16 : poODS->nJpegQuality = atoi(CPLGetConfigOption("JPEG_QUALITY_OVERVIEW","75"));
3915 : }
3916 : TIFFSetField( hTIFF, TIFFTAG_JPEGQUALITY,
3917 36 : poODS->nJpegQuality );
3918 : }
3919 :
3920 246 : if( poODS->OpenOffset( hTIFF, ppoActiveDSRef, nOverviewOffset, FALSE,
3921 : GA_Update ) != CE_None )
3922 : {
3923 0 : delete poODS;
3924 0 : return CE_Failure;
3925 : }
3926 : else
3927 : {
3928 246 : nOverviewCount++;
3929 : papoOverviewDS = (GTiffDataset **)
3930 : CPLRealloc(papoOverviewDS,
3931 246 : nOverviewCount * (sizeof(void*)));
3932 246 : papoOverviewDS[nOverviewCount-1] = poODS;
3933 246 : poODS->poBaseDS = this;
3934 246 : return CE_None;
3935 : }
3936 : }
3937 :
3938 : /************************************************************************/
3939 : /* CreateOverviewsFromSrcOverviews() */
3940 : /************************************************************************/
3941 :
3942 10 : CPLErr GTiffDataset::CreateOverviewsFromSrcOverviews(GDALDataset* poSrcDS)
3943 : {
3944 10 : CPLAssert(poSrcDS->GetRasterCount() != 0);
3945 10 : CPLAssert(nOverviewCount == 0);
3946 :
3947 10 : ScanDirectories();
3948 :
3949 : /* -------------------------------------------------------------------- */
3950 : /* Move to the directory for this dataset. */
3951 : /* -------------------------------------------------------------------- */
3952 10 : if (!SetDirectory())
3953 0 : return CE_Failure;
3954 10 : FlushDirectory();
3955 :
3956 10 : int nOvBitsPerSample = nBitsPerSample;
3957 :
3958 : /* -------------------------------------------------------------------- */
3959 : /* Do we have a palette? If so, create a TIFF compatible version. */
3960 : /* -------------------------------------------------------------------- */
3961 10 : std::vector<unsigned short> anTRed, anTGreen, anTBlue;
3962 10 : unsigned short *panRed=NULL, *panGreen=NULL, *panBlue=NULL;
3963 :
3964 10 : if( nPhotometric == PHOTOMETRIC_PALETTE && poColorTable != NULL )
3965 : {
3966 : int nColors;
3967 :
3968 0 : if( nOvBitsPerSample == 8 )
3969 0 : nColors = 256;
3970 0 : else if( nOvBitsPerSample < 8 )
3971 0 : nColors = 1 << nOvBitsPerSample;
3972 : else
3973 0 : nColors = 65536;
3974 :
3975 0 : anTRed.resize(nColors,0);
3976 0 : anTGreen.resize(nColors,0);
3977 0 : anTBlue.resize(nColors,0);
3978 :
3979 0 : for( int iColor = 0; iColor < nColors; iColor++ )
3980 : {
3981 0 : if( iColor < poColorTable->GetColorEntryCount() )
3982 : {
3983 : GDALColorEntry sRGB;
3984 :
3985 0 : poColorTable->GetColorEntryAsRGB( iColor, &sRGB );
3986 :
3987 0 : anTRed[iColor] = (unsigned short) (256 * sRGB.c1);
3988 0 : anTGreen[iColor] = (unsigned short) (256 * sRGB.c2);
3989 0 : anTBlue[iColor] = (unsigned short) (256 * sRGB.c3);
3990 : }
3991 : else
3992 : {
3993 0 : anTRed[iColor] = anTGreen[iColor] = anTBlue[iColor] = 0;
3994 : }
3995 : }
3996 :
3997 0 : panRed = &(anTRed[0]);
3998 0 : panGreen = &(anTGreen[0]);
3999 0 : panBlue = &(anTBlue[0]);
4000 : }
4001 :
4002 : /* -------------------------------------------------------------------- */
4003 : /* Do we need some metadata for the overviews? */
4004 : /* -------------------------------------------------------------------- */
4005 10 : CPLString osMetadata;
4006 :
4007 10 : GTIFFBuildOverviewMetadata( "NONE", this, osMetadata );
4008 :
4009 : /* -------------------------------------------------------------------- */
4010 : /* Fetch extra sample tag */
4011 : /* -------------------------------------------------------------------- */
4012 10 : uint16 *panExtraSampleValues = NULL;
4013 10 : uint16 nExtraSamples = 0;
4014 :
4015 10 : if( TIFFGetField( hTIFF, TIFFTAG_EXTRASAMPLES, &nExtraSamples, &panExtraSampleValues) )
4016 : {
4017 0 : uint16* panExtraSampleValuesNew = (uint16*) CPLMalloc(nExtraSamples * sizeof(uint16));
4018 0 : memcpy(panExtraSampleValuesNew, panExtraSampleValues, nExtraSamples * sizeof(uint16));
4019 0 : panExtraSampleValues = panExtraSampleValuesNew;
4020 : }
4021 : else
4022 : {
4023 10 : panExtraSampleValues = NULL;
4024 10 : nExtraSamples = 0;
4025 : }
4026 :
4027 : /* -------------------------------------------------------------------- */
4028 : /* Fetch predictor tag */
4029 : /* -------------------------------------------------------------------- */
4030 10 : uint16 nPredictor = PREDICTOR_NONE;
4031 10 : if ( nCompression == COMPRESSION_LZW ||
4032 : nCompression == COMPRESSION_ADOBE_DEFLATE )
4033 0 : TIFFGetField( hTIFF, TIFFTAG_PREDICTOR, &nPredictor );
4034 : int nOvrBlockXSize, nOvrBlockYSize;
4035 10 : GTIFFGetOverviewBlockSize(&nOvrBlockXSize, &nOvrBlockYSize);
4036 :
4037 10 : int nSrcOverviews = poSrcDS->GetRasterBand(1)->GetOverviewCount();
4038 : int i;
4039 10 : CPLErr eErr = CE_None;
4040 :
4041 36 : for(i=0;i<nSrcOverviews && eErr == CE_None;i++)
4042 : {
4043 26 : GDALRasterBand* poOvrBand = poSrcDS->GetRasterBand(1)->GetOverview(i);
4044 :
4045 26 : int nOXSize = poOvrBand->GetXSize(), nOYSize = poOvrBand->GetYSize();
4046 :
4047 : toff_t nOverviewOffset =
4048 : GTIFFWriteDirectory(hTIFF, FILETYPE_REDUCEDIMAGE,
4049 : nOXSize, nOYSize,
4050 : nOvBitsPerSample, nPlanarConfig,
4051 : nSamplesPerPixel, nOvrBlockXSize, nOvrBlockYSize, TRUE,
4052 : nCompression, nPhotometric, nSampleFormat,
4053 : nPredictor,
4054 : panRed, panGreen, panBlue,
4055 : nExtraSamples, panExtraSampleValues,
4056 26 : osMetadata );
4057 :
4058 26 : if( nOverviewOffset == 0 )
4059 0 : eErr = CE_Failure;
4060 : else
4061 26 : eErr = RegisterNewOverviewDataset(nOverviewOffset);
4062 : }
4063 :
4064 10 : CPLFree(panExtraSampleValues);
4065 10 : panExtraSampleValues = NULL;
4066 :
4067 : /* -------------------------------------------------------------------- */
4068 : /* Create overviews for the mask. */
4069 : /* -------------------------------------------------------------------- */
4070 10 : if (eErr == CE_None)
4071 10 : eErr = CreateInternalMaskOverviews(nOvrBlockXSize, nOvrBlockYSize);
4072 :
4073 10 : return eErr;
4074 : }
4075 :
4076 :
4077 : /************************************************************************/
4078 : /* CreateInternalMaskOverviews() */
4079 : /************************************************************************/
4080 :
4081 168 : CPLErr GTiffDataset::CreateInternalMaskOverviews(int nOvrBlockXSize,
4082 : int nOvrBlockYSize)
4083 : {
4084 : GTiffDataset *poODS;
4085 :
4086 168 : ScanDirectories();
4087 :
4088 : /* -------------------------------------------------------------------- */
4089 : /* Create overviews for the mask. */
4090 : /* -------------------------------------------------------------------- */
4091 168 : CPLErr eErr = CE_None;
4092 :
4093 168 : if (poMaskDS != NULL &&
4094 : poMaskDS->GetRasterCount() == 1 &&
4095 : CSLTestBoolean(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK", "NO")))
4096 : {
4097 : int nMaskOvrCompression;
4098 8 : if( strstr(GDALGetMetadataItem(GDALGetDriverByName( "GTiff" ),
4099 : GDAL_DMD_CREATIONOPTIONLIST, NULL ),
4100 : "<Value>DEFLATE</Value>") != NULL )
4101 8 : nMaskOvrCompression = COMPRESSION_ADOBE_DEFLATE;
4102 : else
4103 0 : nMaskOvrCompression = COMPRESSION_PACKBITS;
4104 :
4105 : int i;
4106 24 : for( i = 0; i < nOverviewCount; i++ )
4107 : {
4108 16 : if (papoOverviewDS[i]->poMaskDS == NULL)
4109 : {
4110 : toff_t nOverviewOffset;
4111 :
4112 : nOverviewOffset =
4113 : GTIFFWriteDirectory(hTIFF, FILETYPE_REDUCEDIMAGE | FILETYPE_MASK,
4114 32 : papoOverviewDS[i]->nRasterXSize, papoOverviewDS[i]->nRasterYSize,
4115 : 1, PLANARCONFIG_CONTIG,
4116 : 1, nOvrBlockXSize, nOvrBlockYSize, TRUE,
4117 : nMaskOvrCompression, PHOTOMETRIC_MASK, SAMPLEFORMAT_UINT, PREDICTOR_NONE,
4118 : NULL, NULL, NULL, 0, NULL,
4119 48 : "" );
4120 :
4121 16 : if( nOverviewOffset == 0 )
4122 : {
4123 0 : eErr = CE_Failure;
4124 0 : continue;
4125 : }
4126 :
4127 16 : poODS = new GTiffDataset();
4128 16 : if( poODS->OpenOffset( hTIFF, ppoActiveDSRef,
4129 : nOverviewOffset, FALSE,
4130 : GA_Update ) != CE_None )
4131 : {
4132 0 : delete poODS;
4133 0 : eErr = CE_Failure;
4134 : }
4135 : else
4136 : {
4137 16 : poODS->bPromoteTo8Bits = CSLTestBoolean(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK_TO_8BIT", "YES"));
4138 16 : poODS->poBaseDS = this;
4139 16 : papoOverviewDS[i]->poMaskDS = poODS;
4140 16 : poMaskDS->nOverviewCount++;
4141 : poMaskDS->papoOverviewDS = (GTiffDataset **)
4142 : CPLRealloc(poMaskDS->papoOverviewDS,
4143 16 : poMaskDS->nOverviewCount * (sizeof(void*)));
4144 16 : poMaskDS->papoOverviewDS[poMaskDS->nOverviewCount-1] = poODS;
4145 : }
4146 : }
4147 : }
4148 : }
4149 :
4150 168 : return eErr;
4151 : }
4152 :
4153 : /************************************************************************/
4154 : /* IBuildOverviews() */
4155 : /************************************************************************/
4156 :
4157 294 : CPLErr GTiffDataset::IBuildOverviews(
4158 : const char * pszResampling,
4159 : int nOverviews, int * panOverviewList,
4160 : int nBands, int * panBandList,
4161 : GDALProgressFunc pfnProgress, void * pProgressData )
4162 :
4163 : {
4164 294 : CPLErr eErr = CE_None;
4165 : int i;
4166 : GTiffDataset *poODS;
4167 294 : int bUseGenericHandling = FALSE;
4168 :
4169 294 : ScanDirectories();
4170 :
4171 : /* -------------------------------------------------------------------- */
4172 : /* If RRD or external OVR overviews requested, then invoke */
4173 : /* generic handling. */
4174 : /* -------------------------------------------------------------------- */
4175 294 : if( CSLTestBoolean(CPLGetConfigOption( "USE_RRD", "NO" ))
4176 : || CSLTestBoolean(CPLGetConfigOption( "TIFF_USE_OVR", "NO" )) )
4177 : {
4178 4 : bUseGenericHandling = TRUE;
4179 : }
4180 :
4181 : /* -------------------------------------------------------------------- */
4182 : /* If we don't have read access, then create the overviews */
4183 : /* externally. */
4184 : /* -------------------------------------------------------------------- */
4185 294 : if( GetAccess() != GA_Update )
4186 : {
4187 : CPLDebug( "GTiff",
4188 : "File open for read-only accessing, "
4189 126 : "creating overviews externally." );
4190 :
4191 126 : bUseGenericHandling = TRUE;
4192 : }
4193 :
4194 294 : if( bUseGenericHandling )
4195 : {
4196 130 : if (nOverviewCount != 0)
4197 : {
4198 : CPLError(CE_Failure, CPLE_NotSupported,
4199 0 : "Cannot add external overviews when there are already internal overviews");
4200 0 : return CE_Failure;
4201 : }
4202 :
4203 : return GDALDataset::IBuildOverviews(
4204 : pszResampling, nOverviews, panOverviewList,
4205 130 : nBands, panBandList, pfnProgress, pProgressData );
4206 : }
4207 :
4208 : /* -------------------------------------------------------------------- */
4209 : /* Our TIFF overview support currently only works safely if all */
4210 : /* bands are handled at the same time. */
4211 : /* -------------------------------------------------------------------- */
4212 164 : if( nBands != GetRasterCount() )
4213 : {
4214 : CPLError( CE_Failure, CPLE_NotSupported,
4215 : "Generation of overviews in TIFF currently only"
4216 : " supported when operating on all bands.\n"
4217 0 : "Operation failed.\n" );
4218 0 : return CE_Failure;
4219 : }
4220 :
4221 : /* -------------------------------------------------------------------- */
4222 : /* Initialize progress counter. */
4223 : /* -------------------------------------------------------------------- */
4224 164 : if( !pfnProgress( 0.0, NULL, pProgressData ) )
4225 : {
4226 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
4227 0 : return CE_Failure;
4228 : }
4229 :
4230 : /* -------------------------------------------------------------------- */
4231 : /* If zero overviews were requested, we need to clear all */
4232 : /* existing overviews. */
4233 : /* -------------------------------------------------------------------- */
4234 164 : if( nOverviews == 0 )
4235 : {
4236 6 : if( nOverviewCount == 0 )
4237 : return GDALDataset::IBuildOverviews(
4238 : pszResampling, nOverviews, panOverviewList,
4239 2 : nBands, panBandList, pfnProgress, pProgressData );
4240 : else
4241 4 : return CleanOverviews();
4242 : }
4243 :
4244 : /* -------------------------------------------------------------------- */
4245 : /* Move to the directory for this dataset. */
4246 : /* -------------------------------------------------------------------- */
4247 158 : if (!SetDirectory())
4248 0 : return CE_Failure;
4249 158 : FlushDirectory();
4250 :
4251 : /* -------------------------------------------------------------------- */
4252 : /* If we are averaging bit data to grayscale we need to create */
4253 : /* 8bit overviews. */
4254 : /* -------------------------------------------------------------------- */
4255 158 : int nOvBitsPerSample = nBitsPerSample;
4256 :
4257 158 : if( EQUALN(pszResampling,"AVERAGE_BIT2",12) )
4258 4 : nOvBitsPerSample = 8;
4259 :
4260 : /* -------------------------------------------------------------------- */
4261 : /* Do we have a palette? If so, create a TIFF compatible version. */
4262 : /* -------------------------------------------------------------------- */
4263 158 : std::vector<unsigned short> anTRed, anTGreen, anTBlue;
4264 158 : unsigned short *panRed=NULL, *panGreen=NULL, *panBlue=NULL;
4265 :
4266 158 : if( nPhotometric == PHOTOMETRIC_PALETTE && poColorTable != NULL )
4267 : {
4268 : int nColors;
4269 :
4270 18 : if( nOvBitsPerSample == 8 )
4271 18 : nColors = 256;
4272 0 : else if( nOvBitsPerSample < 8 )
4273 0 : nColors = 1 << nOvBitsPerSample;
4274 : else
4275 0 : nColors = 65536;
4276 :
4277 18 : anTRed.resize(nColors,0);
4278 18 : anTGreen.resize(nColors,0);
4279 18 : anTBlue.resize(nColors,0);
4280 :
4281 4626 : for( int iColor = 0; iColor < nColors; iColor++ )
4282 : {
4283 4608 : if( iColor < poColorTable->GetColorEntryCount() )
4284 : {
4285 : GDALColorEntry sRGB;
4286 :
4287 4608 : poColorTable->GetColorEntryAsRGB( iColor, &sRGB );
4288 :
4289 4608 : anTRed[iColor] = (unsigned short) (256 * sRGB.c1);
4290 4608 : anTGreen[iColor] = (unsigned short) (256 * sRGB.c2);
4291 4608 : anTBlue[iColor] = (unsigned short) (256 * sRGB.c3);
4292 : }
4293 : else
4294 : {
4295 0 : anTRed[iColor] = anTGreen[iColor] = anTBlue[iColor] = 0;
4296 : }
4297 : }
4298 :
4299 18 : panRed = &(anTRed[0]);
4300 18 : panGreen = &(anTGreen[0]);
4301 18 : panBlue = &(anTBlue[0]);
4302 : }
4303 :
4304 : /* -------------------------------------------------------------------- */
4305 : /* Do we need some metadata for the overviews? */
4306 : /* -------------------------------------------------------------------- */
4307 158 : CPLString osMetadata;
4308 :
4309 158 : GTIFFBuildOverviewMetadata( pszResampling, this, osMetadata );
4310 :
4311 : /* -------------------------------------------------------------------- */
4312 : /* Fetch extra sample tag */
4313 : /* -------------------------------------------------------------------- */
4314 158 : uint16 *panExtraSampleValues = NULL;
4315 158 : uint16 nExtraSamples = 0;
4316 :
4317 158 : if( TIFFGetField( hTIFF, TIFFTAG_EXTRASAMPLES, &nExtraSamples, &panExtraSampleValues) )
4318 : {
4319 16 : uint16* panExtraSampleValuesNew = (uint16*) CPLMalloc(nExtraSamples * sizeof(uint16));
4320 16 : memcpy(panExtraSampleValuesNew, panExtraSampleValues, nExtraSamples * sizeof(uint16));
4321 16 : panExtraSampleValues = panExtraSampleValuesNew;
4322 : }
4323 : else
4324 : {
4325 142 : panExtraSampleValues = NULL;
4326 142 : nExtraSamples = 0;
4327 : }
4328 :
4329 : /* -------------------------------------------------------------------- */
4330 : /* Fetch predictor tag */
4331 : /* -------------------------------------------------------------------- */
4332 158 : uint16 nPredictor = PREDICTOR_NONE;
4333 158 : if ( nCompression == COMPRESSION_LZW ||
4334 : nCompression == COMPRESSION_ADOBE_DEFLATE )
4335 14 : TIFFGetField( hTIFF, TIFFTAG_PREDICTOR, &nPredictor );
4336 :
4337 : /* -------------------------------------------------------------------- */
4338 : /* Establish which of the overview levels we already have, and */
4339 : /* which are new. We assume that band 1 of the file is */
4340 : /* representative. */
4341 : /* -------------------------------------------------------------------- */
4342 : int nOvrBlockXSize, nOvrBlockYSize;
4343 158 : GTIFFGetOverviewBlockSize(&nOvrBlockXSize, &nOvrBlockYSize);
4344 406 : for( i = 0; i < nOverviews && eErr == CE_None; i++ )
4345 : {
4346 : int j;
4347 :
4348 398 : for( j = 0; j < nOverviewCount && eErr == CE_None; j++ )
4349 : {
4350 : int nOvFactor;
4351 :
4352 150 : poODS = papoOverviewDS[j];
4353 :
4354 : nOvFactor = (int)
4355 150 : (0.5 + GetRasterXSize() / (double) poODS->GetRasterXSize());
4356 :
4357 150 : if( nOvFactor == panOverviewList[i]
4358 : || nOvFactor == TIFF_OvLevelAdjust( panOverviewList[i],
4359 : GetRasterXSize() ) )
4360 28 : panOverviewList[i] *= -1;
4361 : }
4362 :
4363 248 : if( panOverviewList[i] > 0 )
4364 : {
4365 : toff_t nOverviewOffset;
4366 : int nOXSize, nOYSize;
4367 :
4368 220 : nOXSize = (GetRasterXSize() + panOverviewList[i] - 1)
4369 440 : / panOverviewList[i];
4370 220 : nOYSize = (GetRasterYSize() + panOverviewList[i] - 1)
4371 440 : / panOverviewList[i];
4372 :
4373 : nOverviewOffset =
4374 : GTIFFWriteDirectory(hTIFF, FILETYPE_REDUCEDIMAGE,
4375 : nOXSize, nOYSize,
4376 : nOvBitsPerSample, nPlanarConfig,
4377 : nSamplesPerPixel, nOvrBlockXSize, nOvrBlockYSize, TRUE,
4378 : nCompression, nPhotometric, nSampleFormat,
4379 : nPredictor,
4380 : panRed, panGreen, panBlue,
4381 : nExtraSamples, panExtraSampleValues,
4382 220 : osMetadata );
4383 :
4384 :
4385 220 : if( nOverviewOffset == 0 )
4386 0 : eErr = CE_Failure;
4387 : else
4388 220 : eErr = RegisterNewOverviewDataset(nOverviewOffset);
4389 : }
4390 : else
4391 28 : panOverviewList[i] *= -1;
4392 : }
4393 :
4394 158 : CPLFree(panExtraSampleValues);
4395 158 : panExtraSampleValues = NULL;
4396 :
4397 : /* -------------------------------------------------------------------- */
4398 : /* Create overviews for the mask. */
4399 : /* -------------------------------------------------------------------- */
4400 158 : if (eErr == CE_None)
4401 158 : eErr = CreateInternalMaskOverviews(nOvrBlockXSize, nOvrBlockYSize);
4402 : else
4403 0 : return eErr;
4404 :
4405 : /* -------------------------------------------------------------------- */
4406 : /* Refresh overviews for the mask */
4407 : /* -------------------------------------------------------------------- */
4408 180 : if (poMaskDS != NULL &&
4409 : poMaskDS->GetRasterCount() == 1)
4410 : {
4411 : GDALRasterBand **papoOverviewBands;
4412 22 : int nMaskOverviews = 0;
4413 :
4414 22 : papoOverviewBands = (GDALRasterBand **) CPLCalloc(sizeof(void*),nOverviewCount);
4415 66 : for( i = 0; i < nOverviewCount; i++ )
4416 : {
4417 44 : if (papoOverviewDS[i]->poMaskDS != NULL)
4418 : {
4419 72 : papoOverviewBands[nMaskOverviews ++] =
4420 36 : papoOverviewDS[i]->poMaskDS->GetRasterBand(1);
4421 : }
4422 : }
4423 : eErr = GDALRegenerateOverviews( (GDALRasterBandH)
4424 : poMaskDS->GetRasterBand(1),
4425 : nMaskOverviews,
4426 : (GDALRasterBandH *) papoOverviewBands,
4427 22 : pszResampling, GDALDummyProgress, NULL);
4428 22 : CPLFree(papoOverviewBands);
4429 : }
4430 :
4431 :
4432 : /* -------------------------------------------------------------------- */
4433 : /* Refresh old overviews that were listed. */
4434 : /* -------------------------------------------------------------------- */
4435 190 : if (nCompression != COMPRESSION_NONE &&
4436 : nPlanarConfig == PLANARCONFIG_CONTIG &&
4437 : GDALDataTypeIsComplex(GetRasterBand( panBandList[0] )->GetRasterDataType()) == FALSE &&
4438 32 : GetRasterBand( panBandList[0] )->GetColorTable() == NULL &&
4439 : (EQUALN(pszResampling, "NEAR", 4) || EQUAL(pszResampling, "AVERAGE") || EQUAL(pszResampling, "GAUSS")))
4440 : {
4441 : /* In the case of pixel interleaved compressed overviews, we want to generate */
4442 : /* the overviews for all the bands block by block, and not band after band, */
4443 : /* in order to write the block once and not loose space in the TIFF file */
4444 :
4445 : GDALRasterBand ***papapoOverviewBands;
4446 : GDALRasterBand **papoBandList;
4447 :
4448 32 : int nNewOverviews = 0;
4449 : int iBand;
4450 :
4451 32 : papapoOverviewBands = (GDALRasterBand ***) CPLCalloc(sizeof(void*),nBands);
4452 32 : papoBandList = (GDALRasterBand **) CPLCalloc(sizeof(void*),nBands);
4453 120 : for( iBand = 0; iBand < nBands; iBand++ )
4454 : {
4455 88 : GDALRasterBand* poBand = GetRasterBand( panBandList[iBand] );
4456 :
4457 88 : papoBandList[iBand] = poBand;
4458 88 : papapoOverviewBands[iBand] = (GDALRasterBand **) CPLCalloc(sizeof(void*), poBand->GetOverviewCount());
4459 :
4460 88 : int iCurOverview = 0;
4461 228 : for( i = 0; i < nOverviews; i++ )
4462 : {
4463 : int j;
4464 :
4465 192 : for( j = 0; j < poBand->GetOverviewCount(); j++ )
4466 : {
4467 : int nOvFactor;
4468 192 : GDALRasterBand * poOverview = poBand->GetOverview( j );
4469 :
4470 : nOvFactor = (int)
4471 192 : (0.5 + poBand->GetXSize() / (double) poOverview->GetXSize());
4472 :
4473 : int bHasNoData;
4474 192 : double noDataValue = poBand->GetNoDataValue(&bHasNoData);
4475 :
4476 192 : if (bHasNoData)
4477 36 : poOverview->SetNoDataValue(noDataValue);
4478 :
4479 192 : if( nOvFactor == panOverviewList[i]
4480 : || nOvFactor == TIFF_OvLevelAdjust( panOverviewList[i],
4481 : poBand->GetXSize() ) )
4482 : {
4483 140 : papapoOverviewBands[iBand][iCurOverview] = poOverview;
4484 140 : iCurOverview++ ;
4485 140 : break;
4486 : }
4487 : }
4488 : }
4489 :
4490 88 : if (nNewOverviews == 0)
4491 32 : nNewOverviews = iCurOverview;
4492 56 : else if (nNewOverviews != iCurOverview)
4493 : {
4494 0 : CPLAssert(0);
4495 0 : return CE_Failure;
4496 : }
4497 : }
4498 :
4499 : GDALRegenerateOverviewsMultiBand(nBands, papoBandList,
4500 : nNewOverviews, papapoOverviewBands,
4501 32 : pszResampling, pfnProgress, pProgressData );
4502 :
4503 120 : for( iBand = 0; iBand < nBands; iBand++ )
4504 : {
4505 88 : CPLFree(papapoOverviewBands[iBand]);
4506 : }
4507 32 : CPLFree(papapoOverviewBands);
4508 32 : CPLFree(papoBandList);
4509 : }
4510 : else
4511 : {
4512 : GDALRasterBand **papoOverviewBands;
4513 :
4514 : papoOverviewBands = (GDALRasterBand **)
4515 126 : CPLCalloc(sizeof(void*),nOverviews);
4516 :
4517 296 : for( int iBand = 0; iBand < nBands && eErr == CE_None; iBand++ )
4518 : {
4519 : GDALRasterBand *poBand;
4520 : int nNewOverviews;
4521 :
4522 170 : poBand = GetRasterBand( panBandList[iBand] );
4523 :
4524 170 : nNewOverviews = 0;
4525 446 : for( i = 0; i < nOverviews && poBand != NULL; i++ )
4526 : {
4527 : int j;
4528 :
4529 402 : for( j = 0; j < poBand->GetOverviewCount(); j++ )
4530 : {
4531 : int nOvFactor;
4532 402 : GDALRasterBand * poOverview = poBand->GetOverview( j );
4533 :
4534 : int bHasNoData;
4535 402 : double noDataValue = poBand->GetNoDataValue(&bHasNoData);
4536 :
4537 402 : if (bHasNoData)
4538 14 : poOverview->SetNoDataValue(noDataValue);
4539 :
4540 : nOvFactor = (int)
4541 402 : (0.5 + poBand->GetXSize() / (double) poOverview->GetXSize());
4542 :
4543 402 : if( nOvFactor == panOverviewList[i]
4544 : || nOvFactor == TIFF_OvLevelAdjust( panOverviewList[i],
4545 : poBand->GetXSize() ) )
4546 : {
4547 276 : papoOverviewBands[nNewOverviews++] = poOverview;
4548 276 : break;
4549 : }
4550 : }
4551 : }
4552 :
4553 : void *pScaledProgressData;
4554 :
4555 : pScaledProgressData =
4556 : GDALCreateScaledProgress( iBand / (double) nBands,
4557 : (iBand+1) / (double) nBands,
4558 170 : pfnProgress, pProgressData );
4559 :
4560 : eErr = GDALRegenerateOverviews( (GDALRasterBandH) poBand,
4561 : nNewOverviews,
4562 : (GDALRasterBandH *) papoOverviewBands,
4563 : pszResampling,
4564 : GDALScaledProgress,
4565 170 : pScaledProgressData);
4566 :
4567 170 : GDALDestroyScaledProgress( pScaledProgressData );
4568 : }
4569 :
4570 : /* -------------------------------------------------------------------- */
4571 : /* Cleanup */
4572 : /* -------------------------------------------------------------------- */
4573 126 : CPLFree( papoOverviewBands );
4574 : }
4575 :
4576 :
4577 158 : pfnProgress( 1.0, NULL, pProgressData );
4578 :
4579 158 : return eErr;
4580 : }
4581 :
4582 :
4583 : /************************************************************************/
4584 : /* WriteGeoTIFFInfo() */
4585 : /************************************************************************/
4586 :
4587 1932 : void GTiffDataset::WriteGeoTIFFInfo()
4588 :
4589 : {
4590 1932 : bool bPixelIsPoint = false;
4591 1932 : int bPointGeoIgnore = FALSE;
4592 :
4593 2482 : if( GetMetadataItem( GDALMD_AREA_OR_POINT )
4594 550 : && EQUAL(GetMetadataItem(GDALMD_AREA_OR_POINT),
4595 : GDALMD_AOP_POINT) )
4596 : {
4597 8 : bPixelIsPoint = true;
4598 : bPointGeoIgnore =
4599 : CSLTestBoolean( CPLGetConfigOption("GTIFF_POINT_GEO_IGNORE",
4600 8 : "FALSE") );
4601 : }
4602 :
4603 : /* -------------------------------------------------------------------- */
4604 : /* If the geotransform is the default, don't bother writing it. */
4605 : /* -------------------------------------------------------------------- */
4606 6060 : if( adfGeoTransform[0] != 0.0 || adfGeoTransform[1] != 1.0
4607 1112 : || adfGeoTransform[2] != 0.0 || adfGeoTransform[3] != 0.0
4608 1626 : || adfGeoTransform[4] != 0.0 || ABS(adfGeoTransform[5]) != 1.0 )
4609 : {
4610 1390 : bNeedsRewrite = TRUE;
4611 :
4612 : /* -------------------------------------------------------------------- */
4613 : /* Clear old tags to ensure we don't end up with conflicting */
4614 : /* information. (#2625) */
4615 : /* -------------------------------------------------------------------- */
4616 : #ifdef HAVE_UNSETFIELD
4617 1390 : TIFFUnsetField( hTIFF, TIFFTAG_GEOPIXELSCALE );
4618 1390 : TIFFUnsetField( hTIFF, TIFFTAG_GEOTIEPOINTS );
4619 1390 : TIFFUnsetField( hTIFF, TIFFTAG_GEOTRANSMATRIX );
4620 : #endif
4621 :
4622 : /* -------------------------------------------------------------------- */
4623 : /* Write the transform. If we have a normal north-up image we */
4624 : /* use the tiepoint plus pixelscale otherwise we use a matrix. */
4625 : /* -------------------------------------------------------------------- */
4626 4160 : if( adfGeoTransform[2] == 0.0 && adfGeoTransform[4] == 0.0
4627 1386 : && adfGeoTransform[5] < 0.0 )
4628 : {
4629 : double adfPixelScale[3], adfTiePoints[6];
4630 :
4631 1384 : adfPixelScale[0] = adfGeoTransform[1];
4632 1384 : adfPixelScale[1] = fabs(adfGeoTransform[5]);
4633 1384 : adfPixelScale[2] = 0.0;
4634 :
4635 1384 : if( !EQUAL(osProfile,"BASELINE") )
4636 1374 : TIFFSetField( hTIFF, TIFFTAG_GEOPIXELSCALE, 3, adfPixelScale );
4637 :
4638 1384 : adfTiePoints[0] = 0.0;
4639 1384 : adfTiePoints[1] = 0.0;
4640 1384 : adfTiePoints[2] = 0.0;
4641 1384 : adfTiePoints[3] = adfGeoTransform[0];
4642 1384 : adfTiePoints[4] = adfGeoTransform[3];
4643 1384 : adfTiePoints[5] = 0.0;
4644 :
4645 1384 : if( bPixelIsPoint && !bPointGeoIgnore )
4646 : {
4647 0 : adfTiePoints[3] += adfGeoTransform[1] * 0.5 + adfGeoTransform[2] * 0.5;
4648 0 : adfTiePoints[4] += adfGeoTransform[4] * 0.5 + adfGeoTransform[5] * 0.5;
4649 : }
4650 :
4651 1384 : if( !EQUAL(osProfile,"BASELINE") )
4652 1374 : TIFFSetField( hTIFF, TIFFTAG_GEOTIEPOINTS, 6, adfTiePoints );
4653 : }
4654 : else
4655 : {
4656 : double adfMatrix[16];
4657 :
4658 6 : memset(adfMatrix,0,sizeof(double) * 16);
4659 :
4660 6 : adfMatrix[0] = adfGeoTransform[1];
4661 6 : adfMatrix[1] = adfGeoTransform[2];
4662 6 : adfMatrix[3] = adfGeoTransform[0];
4663 6 : adfMatrix[4] = adfGeoTransform[4];
4664 6 : adfMatrix[5] = adfGeoTransform[5];
4665 6 : adfMatrix[7] = adfGeoTransform[3];
4666 6 : adfMatrix[15] = 1.0;
4667 :
4668 6 : if( bPixelIsPoint && !bPointGeoIgnore )
4669 : {
4670 0 : adfMatrix[3] += adfGeoTransform[1] * 0.5 + adfGeoTransform[2] * 0.5;
4671 0 : adfMatrix[7] += adfGeoTransform[4] * 0.5 + adfGeoTransform[5] * 0.5;
4672 : }
4673 :
4674 6 : if( !EQUAL(osProfile,"BASELINE") )
4675 6 : TIFFSetField( hTIFF, TIFFTAG_GEOTRANSMATRIX, 16, adfMatrix );
4676 : }
4677 :
4678 : // Do we need a world file?
4679 1390 : if( CSLFetchBoolean( papszCreationOptions, "TFW", FALSE ) )
4680 4 : GDALWriteWorldFile( osFilename, "tfw", adfGeoTransform );
4681 1386 : else if( CSLFetchBoolean( papszCreationOptions, "WORLDFILE", FALSE ) )
4682 4 : GDALWriteWorldFile( osFilename, "wld", adfGeoTransform );
4683 : }
4684 542 : else if( GetGCPCount() > 0 )
4685 : {
4686 : double *padfTiePoints;
4687 : int iGCP;
4688 :
4689 4 : bNeedsRewrite = TRUE;
4690 :
4691 : padfTiePoints = (double *)
4692 4 : CPLMalloc( 6 * sizeof(double) * GetGCPCount() );
4693 :
4694 28 : for( iGCP = 0; iGCP < GetGCPCount(); iGCP++ )
4695 : {
4696 :
4697 24 : padfTiePoints[iGCP*6+0] = pasGCPList[iGCP].dfGCPPixel;
4698 24 : padfTiePoints[iGCP*6+1] = pasGCPList[iGCP].dfGCPLine;
4699 24 : padfTiePoints[iGCP*6+2] = 0;
4700 24 : padfTiePoints[iGCP*6+3] = pasGCPList[iGCP].dfGCPX;
4701 24 : padfTiePoints[iGCP*6+4] = pasGCPList[iGCP].dfGCPY;
4702 24 : padfTiePoints[iGCP*6+5] = pasGCPList[iGCP].dfGCPZ;
4703 :
4704 24 : if( bPixelIsPoint && !bPointGeoIgnore )
4705 : {
4706 0 : padfTiePoints[iGCP*6+0] += 0.5;
4707 0 : padfTiePoints[iGCP*6+1] += 0.5;
4708 : }
4709 : }
4710 :
4711 4 : if( !EQUAL(osProfile,"BASELINE") )
4712 : TIFFSetField( hTIFF, TIFFTAG_GEOTIEPOINTS,
4713 4 : 6 * GetGCPCount(), padfTiePoints );
4714 4 : CPLFree( padfTiePoints );
4715 : }
4716 :
4717 : /* -------------------------------------------------------------------- */
4718 : /* Write out projection definition. */
4719 : /* -------------------------------------------------------------------- */
4720 1932 : if( pszProjection != NULL && !EQUAL( pszProjection, "" )
4721 : && !EQUAL(osProfile,"BASELINE") )
4722 : {
4723 : GTIF *psGTIF;
4724 :
4725 1476 : bNeedsRewrite = TRUE;
4726 :
4727 : // If we have existing geokeys, try to wipe them
4728 : // by writing a dummy goekey directory. (#2546)
4729 1476 : uint16 *panVI = NULL;
4730 : uint16 nKeyCount;
4731 :
4732 1476 : if( TIFFGetField( hTIFF, TIFFTAG_GEOKEYDIRECTORY,
4733 : &nKeyCount, &panVI ) )
4734 : {
4735 20 : GUInt16 anGKVersionInfo[4] = { 1, 1, 0, 0 };
4736 20 : double adfDummyDoubleParams[1] = { 0.0 };
4737 : TIFFSetField( hTIFF, TIFFTAG_GEOKEYDIRECTORY,
4738 20 : 4, anGKVersionInfo );
4739 : TIFFSetField( hTIFF, TIFFTAG_GEODOUBLEPARAMS,
4740 20 : 1, adfDummyDoubleParams );
4741 20 : TIFFSetField( hTIFF, TIFFTAG_GEOASCIIPARAMS, "" );
4742 : }
4743 :
4744 1476 : psGTIF = GTIFNew( hTIFF );
4745 :
4746 : // set according to coordinate system.
4747 1476 : GTIFSetFromOGISDefn( psGTIF, pszProjection );
4748 :
4749 1476 : if( bPixelIsPoint )
4750 : {
4751 : GTIFKeySet(psGTIF, GTRasterTypeGeoKey, TYPE_SHORT, 1,
4752 8 : RasterPixelIsPoint);
4753 : }
4754 :
4755 1476 : GTIFWriteKeys( psGTIF );
4756 1476 : GTIFFree( psGTIF );
4757 : }
4758 1932 : }
4759 :
4760 : /************************************************************************/
4761 : /* AppendMetadataItem() */
4762 : /************************************************************************/
4763 :
4764 502 : static void AppendMetadataItem( CPLXMLNode **ppsRoot, CPLXMLNode **ppsTail,
4765 : const char *pszKey, const char *pszValue,
4766 : int nBand, const char *pszRole,
4767 : const char *pszDomain )
4768 :
4769 : {
4770 : char szBandId[32];
4771 : CPLXMLNode *psItem;
4772 :
4773 : /* -------------------------------------------------------------------- */
4774 : /* Create the Item element, and subcomponents. */
4775 : /* -------------------------------------------------------------------- */
4776 502 : psItem = CPLCreateXMLNode( NULL, CXT_Element, "Item" );
4777 : CPLCreateXMLNode( CPLCreateXMLNode( psItem, CXT_Attribute, "name"),
4778 502 : CXT_Text, pszKey );
4779 :
4780 502 : if( nBand > 0 )
4781 : {
4782 94 : sprintf( szBandId, "%d", nBand - 1 );
4783 : CPLCreateXMLNode( CPLCreateXMLNode( psItem,CXT_Attribute,"sample"),
4784 94 : CXT_Text, szBandId );
4785 : }
4786 :
4787 502 : if( pszRole != NULL )
4788 : CPLCreateXMLNode( CPLCreateXMLNode( psItem,CXT_Attribute,"role"),
4789 18 : CXT_Text, pszRole );
4790 :
4791 502 : if( pszDomain != NULL && strlen(pszDomain) > 0 )
4792 : CPLCreateXMLNode( CPLCreateXMLNode( psItem,CXT_Attribute,"domain"),
4793 2 : CXT_Text, pszDomain );
4794 :
4795 502 : char *pszEscapedItemValue = CPLEscapeString(pszValue,-1,CPLES_XML);
4796 502 : CPLCreateXMLNode( psItem, CXT_Text, pszEscapedItemValue );
4797 502 : CPLFree( pszEscapedItemValue );
4798 :
4799 : /* -------------------------------------------------------------------- */
4800 : /* Create root, if missing. */
4801 : /* -------------------------------------------------------------------- */
4802 502 : if( *ppsRoot == NULL )
4803 126 : *ppsRoot = CPLCreateXMLNode( NULL, CXT_Element, "GDALMetadata" );
4804 :
4805 : /* -------------------------------------------------------------------- */
4806 : /* Append item to tail. We keep track of the tail to avoid */
4807 : /* O(nsquared) time as the list gets longer. */
4808 : /* -------------------------------------------------------------------- */
4809 502 : if( *ppsTail == NULL )
4810 126 : CPLAddXMLChild( *ppsRoot, psItem );
4811 : else
4812 376 : CPLAddXMLSibling( *ppsTail, psItem );
4813 :
4814 502 : *ppsTail = psItem;
4815 502 : }
4816 :
4817 : /************************************************************************/
4818 : /* WriteMDMDMetadata() */
4819 : /************************************************************************/
4820 :
4821 266722 : static void WriteMDMetadata( GDALMultiDomainMetadata *poMDMD, TIFF *hTIFF,
4822 : CPLXMLNode **ppsRoot, CPLXMLNode **ppsTail,
4823 : int nBand, const char *pszProfile )
4824 :
4825 : {
4826 : int iDomain;
4827 : char **papszDomainList;
4828 :
4829 : (void) pszProfile;
4830 :
4831 : /* ==================================================================== */
4832 : /* Process each domain. */
4833 : /* ==================================================================== */
4834 266722 : papszDomainList = poMDMD->GetDomainList();
4835 267702 : for( iDomain = 0; papszDomainList && papszDomainList[iDomain]; iDomain++ )
4836 : {
4837 980 : char **papszMD = poMDMD->GetMetadata( papszDomainList[iDomain] );
4838 : int iItem;
4839 980 : int bIsXML = FALSE;
4840 :
4841 980 : if( EQUAL(papszDomainList[iDomain], "IMAGE_STRUCTURE") )
4842 110 : continue; // ignored
4843 870 : if( EQUAL(papszDomainList[iDomain], "RPC") )
4844 0 : continue; // handled elsewhere
4845 870 : if( EQUAL(papszDomainList[iDomain], "xml:ESRI")
4846 : && CSLTestBoolean(CPLGetConfigOption( "ESRI_XML_PAM", "NO" )) )
4847 2 : continue; // handled elsewhere
4848 :
4849 868 : if( EQUALN(papszDomainList[iDomain], "xml:",4 ) )
4850 2 : bIsXML = TRUE;
4851 :
4852 : /* -------------------------------------------------------------------- */
4853 : /* Process each item in this domain. */
4854 : /* -------------------------------------------------------------------- */
4855 2096 : for( iItem = 0; papszMD && papszMD[iItem]; iItem++ )
4856 : {
4857 : const char *pszItemValue;
4858 1228 : char *pszItemName = NULL;
4859 :
4860 1228 : if( bIsXML )
4861 : {
4862 2 : pszItemName = CPLStrdup("doc");
4863 2 : pszItemValue = papszMD[iItem];
4864 : }
4865 : else
4866 : {
4867 1226 : pszItemValue = CPLParseNameValue( papszMD[iItem], &pszItemName);
4868 : }
4869 :
4870 : /* -------------------------------------------------------------------- */
4871 : /* Convert into XML item or handle as a special TIFF tag. */
4872 : /* -------------------------------------------------------------------- */
4873 1286 : if( strlen(papszDomainList[iDomain]) == 0
4874 : && nBand == 0 && EQUALN(pszItemName,"TIFFTAG_",8) )
4875 : {
4876 58 : if( EQUAL(pszItemName,"TIFFTAG_DOCUMENTNAME") )
4877 8 : TIFFSetField( hTIFF, TIFFTAG_DOCUMENTNAME, pszItemValue );
4878 50 : else if( EQUAL(pszItemName,"TIFFTAG_IMAGEDESCRIPTION") )
4879 2 : TIFFSetField( hTIFF, TIFFTAG_IMAGEDESCRIPTION, pszItemValue );
4880 48 : else if( EQUAL(pszItemName,"TIFFTAG_SOFTWARE") )
4881 4 : TIFFSetField( hTIFF, TIFFTAG_SOFTWARE, pszItemValue );
4882 44 : else if( EQUAL(pszItemName,"TIFFTAG_DATETIME") )
4883 2 : TIFFSetField( hTIFF, TIFFTAG_DATETIME, pszItemValue );
4884 42 : else if( EQUAL(pszItemName,"TIFFTAG_ARTIST") )
4885 2 : TIFFSetField( hTIFF, TIFFTAG_ARTIST, pszItemValue );
4886 40 : else if( EQUAL(pszItemName,"TIFFTAG_HOSTCOMPUTER") )
4887 2 : TIFFSetField( hTIFF, TIFFTAG_HOSTCOMPUTER, pszItemValue );
4888 38 : else if( EQUAL(pszItemName,"TIFFTAG_COPYRIGHT") )
4889 2 : TIFFSetField( hTIFF, TIFFTAG_COPYRIGHT, pszItemValue );
4890 36 : else if( EQUAL(pszItemName,"TIFFTAG_XRESOLUTION") )
4891 12 : TIFFSetField( hTIFF, TIFFTAG_XRESOLUTION, CPLAtof(pszItemValue) );
4892 24 : else if( EQUAL(pszItemName,"TIFFTAG_YRESOLUTION") )
4893 12 : TIFFSetField( hTIFF, TIFFTAG_YRESOLUTION, CPLAtof(pszItemValue) );
4894 12 : else if( EQUAL(pszItemName,"TIFFTAG_RESOLUTIONUNIT") )
4895 12 : TIFFSetField( hTIFF, TIFFTAG_RESOLUTIONUNIT, atoi(pszItemValue) );
4896 0 : else if( EQUAL(pszItemName,"TIFFTAG_MINSAMPLEVALUE") )
4897 0 : TIFFSetField( hTIFF, TIFFTAG_MINSAMPLEVALUE, atoi(pszItemValue) );
4898 0 : else if( EQUAL(pszItemName,"TIFFTAG_MAXSAMPLEVALUE") )
4899 0 : TIFFSetField( hTIFF, TIFFTAG_MAXSAMPLEVALUE, atoi(pszItemValue) );
4900 : else
4901 : CPLError(CE_Warning, CPLE_NotSupported,
4902 : "%s metadata item is unhandled and will not be written",
4903 0 : pszItemName);
4904 : }
4905 1170 : else if( nBand == 0 && EQUAL(pszItemName,GDALMD_AREA_OR_POINT) )
4906 : /* do nothing, handled elsewhere */;
4907 : else
4908 : AppendMetadataItem( ppsRoot, ppsTail,
4909 : pszItemName, pszItemValue,
4910 484 : nBand, NULL, papszDomainList[iDomain] );
4911 :
4912 1228 : CPLFree( pszItemName );
4913 : }
4914 : }
4915 266722 : }
4916 :
4917 : /************************************************************************/
4918 : /* WriteMetadata() */
4919 : /************************************************************************/
4920 :
4921 2354 : int GTiffDataset::WriteMetadata( GDALDataset *poSrcDS, TIFF *hTIFF,
4922 : int bSrcIsGeoTIFF,
4923 : const char *pszProfile,
4924 : const char *pszTIFFFilename,
4925 : char **papszCreationOptions,
4926 : int bExcludeRPBandIMGFileWriting)
4927 :
4928 : {
4929 : /* -------------------------------------------------------------------- */
4930 : /* Convert all the remaining metadata into a simple XML */
4931 : /* format. */
4932 : /* -------------------------------------------------------------------- */
4933 2354 : CPLXMLNode *psRoot = NULL, *psTail = NULL;
4934 :
4935 2354 : if( bSrcIsGeoTIFF )
4936 : {
4937 : WriteMDMetadata( &(((GTiffDataset *)poSrcDS)->oGTiffMDMD),
4938 1938 : hTIFF, &psRoot, &psTail, 0, pszProfile );
4939 : }
4940 : else
4941 : {
4942 416 : char **papszMD = poSrcDS->GetMetadata();
4943 :
4944 416 : if( CSLCount(papszMD) > 0 )
4945 : {
4946 196 : GDALMultiDomainMetadata oMDMD;
4947 196 : oMDMD.SetMetadata( papszMD );
4948 :
4949 196 : WriteMDMetadata( &oMDMD, hTIFF, &psRoot, &psTail, 0, pszProfile );
4950 : }
4951 : }
4952 :
4953 : /* -------------------------------------------------------------------- */
4954 : /* Handle RPC data written to an RPB file. */
4955 : /* -------------------------------------------------------------------- */
4956 2354 : char **papszRPCMD = poSrcDS->GetMetadata("RPC");
4957 2354 : if( papszRPCMD != NULL && !bExcludeRPBandIMGFileWriting )
4958 : {
4959 8 : if( EQUAL(pszProfile,"GDALGeoTIFF") )
4960 4 : WriteRPCTag( hTIFF, papszRPCMD );
4961 :
4962 8 : if( !EQUAL(pszProfile,"GDALGeoTIFF")
4963 : || CSLFetchBoolean( papszCreationOptions, "RPB", FALSE ) )
4964 : {
4965 4 : GDALWriteRPBFile( pszTIFFFilename, papszRPCMD );
4966 : }
4967 : }
4968 :
4969 : /* -------------------------------------------------------------------- */
4970 : /* Handle metadata data written to an IMD file. */
4971 : /* -------------------------------------------------------------------- */
4972 2354 : char **papszIMDMD = poSrcDS->GetMetadata("IMD");
4973 2354 : if( papszIMDMD != NULL && !bExcludeRPBandIMGFileWriting)
4974 : {
4975 8 : GDALWriteIMDFile( pszTIFFFilename, papszIMDMD );
4976 : }
4977 :
4978 : /* -------------------------------------------------------------------- */
4979 : /* We also need to address band specific metadata, and special */
4980 : /* "role" metadata. */
4981 : /* -------------------------------------------------------------------- */
4982 : int nBand;
4983 267546 : for( nBand = 1; nBand <= poSrcDS->GetRasterCount(); nBand++ )
4984 : {
4985 265192 : GDALRasterBand *poBand = poSrcDS->GetRasterBand( nBand );
4986 :
4987 265192 : if( bSrcIsGeoTIFF )
4988 : {
4989 : WriteMDMetadata( &(((GTiffRasterBand *)poBand)->oGTiffMDMD),
4990 264534 : hTIFF, &psRoot, &psTail, nBand, pszProfile );
4991 : }
4992 : else
4993 : {
4994 658 : char **papszMD = poBand->GetMetadata();
4995 :
4996 658 : if( CSLCount(papszMD) > 0 )
4997 : {
4998 54 : GDALMultiDomainMetadata oMDMD;
4999 54 : oMDMD.SetMetadata( papszMD );
5000 :
5001 : WriteMDMetadata( &oMDMD, hTIFF, &psRoot, &psTail, nBand,
5002 54 : pszProfile );
5003 : }
5004 : }
5005 :
5006 : int bSuccess;
5007 265192 : double dfOffset = poBand->GetOffset( &bSuccess );
5008 265192 : double dfScale = poBand->GetScale();
5009 :
5010 265192 : if( bSuccess && (dfOffset != 0.0 || dfScale != 1.0) )
5011 : {
5012 : char szValue[128];
5013 :
5014 4 : sprintf( szValue, "%.18g", dfOffset );
5015 : AppendMetadataItem( &psRoot, &psTail, "OFFSET", szValue, nBand,
5016 4 : "offset", "" );
5017 4 : sprintf( szValue, "%.18g", dfScale );
5018 : AppendMetadataItem( &psRoot, &psTail, "SCALE", szValue, nBand,
5019 4 : "scale", "" );
5020 : }
5021 :
5022 265192 : const char* pszUnitType = poBand->GetUnitType();
5023 265192 : if (pszUnitType != NULL && pszUnitType[0] != '\0')
5024 : AppendMetadataItem( &psRoot, &psTail, "UNITTYPE", pszUnitType, nBand,
5025 10 : "unittype", "" );
5026 : }
5027 :
5028 : /* -------------------------------------------------------------------- */
5029 : /* Write out the generic XML metadata if there is any. */
5030 : /* -------------------------------------------------------------------- */
5031 2354 : if( psRoot != NULL )
5032 : {
5033 126 : int bRet = TRUE;
5034 :
5035 126 : if( EQUAL(pszProfile,"GDALGeoTIFF") )
5036 : {
5037 106 : char *pszXML_MD = CPLSerializeXMLTree( psRoot );
5038 106 : if( strlen(pszXML_MD) > 32000 )
5039 : {
5040 2 : if( bSrcIsGeoTIFF )
5041 2 : ((GTiffDataset *) poSrcDS)->PushMetadataToPam();
5042 : else
5043 0 : bRet = FALSE;
5044 : CPLError( CE_Warning, CPLE_AppDefined,
5045 2 : "Lost metadata writing to GeoTIFF ... too large to fit in tag." );
5046 : }
5047 : else
5048 : {
5049 104 : TIFFSetField( hTIFF, TIFFTAG_GDAL_METADATA, pszXML_MD );
5050 : }
5051 106 : CPLFree( pszXML_MD );
5052 : }
5053 : else
5054 : {
5055 20 : if( bSrcIsGeoTIFF )
5056 12 : ((GTiffDataset *) poSrcDS)->PushMetadataToPam();
5057 : else
5058 8 : bRet = FALSE;
5059 : }
5060 :
5061 126 : CPLDestroyXMLNode( psRoot );
5062 :
5063 126 : return bRet;
5064 : }
5065 : else
5066 : {
5067 : /* If we have no more metadata but it existed before, remove the GDAL_METADATA tag */
5068 2228 : if( EQUAL(pszProfile,"GDALGeoTIFF") )
5069 : {
5070 2216 : char* pszText = NULL;
5071 2216 : if( TIFFGetField( hTIFF, TIFFTAG_GDAL_METADATA, &pszText ) )
5072 : {
5073 : #ifdef HAVE_UNSETFIELD
5074 4 : TIFFUnsetField( hTIFF, TIFFTAG_GDAL_METADATA );
5075 : #else
5076 : TIFFSetField( hTIFF, TIFFTAG_GDAL_METADATA, "" );
5077 : #endif
5078 : }
5079 : }
5080 : }
5081 :
5082 2228 : return TRUE;
5083 : }
5084 :
5085 : /************************************************************************/
5086 : /* PushMetadataToPam() */
5087 : /* */
5088 : /* When producing a strict profile TIFF or if our aggregate */
5089 : /* metadata is too big for a single tiff tag we may end up */
5090 : /* needing to write it via the PAM mechanisms. This method */
5091 : /* copies all the appropriate metadata into the PAM level */
5092 : /* metadata object but with special care to avoid copying */
5093 : /* metadata handled in other ways in TIFF format. */
5094 : /************************************************************************/
5095 :
5096 74 : void GTiffDataset::PushMetadataToPam()
5097 :
5098 : {
5099 : int nBand;
5100 246 : for( nBand = 0; nBand <= GetRasterCount(); nBand++ )
5101 : {
5102 : GDALMultiDomainMetadata *poSrcMDMD;
5103 172 : GTiffRasterBand *poBand = NULL;
5104 :
5105 172 : if( nBand == 0 )
5106 74 : poSrcMDMD = &(this->oGTiffMDMD);
5107 : else
5108 : {
5109 98 : poBand = (GTiffRasterBand *) GetRasterBand(nBand);
5110 98 : poSrcMDMD = &(poBand->oGTiffMDMD);
5111 : }
5112 :
5113 : /* -------------------------------------------------------------------- */
5114 : /* Loop over the available domains. */
5115 : /* -------------------------------------------------------------------- */
5116 : int iDomain, i;
5117 : char **papszDomainList;
5118 :
5119 172 : papszDomainList = poSrcMDMD->GetDomainList();
5120 738 : for( iDomain = 0;
5121 360 : papszDomainList && papszDomainList[iDomain];
5122 : iDomain++ )
5123 : {
5124 206 : char **papszMD = poSrcMDMD->GetMetadata( papszDomainList[iDomain] );
5125 :
5126 824 : if( EQUAL(papszDomainList[iDomain],"RPC")
5127 206 : || EQUAL(papszDomainList[iDomain],"IMD")
5128 206 : || EQUAL(papszDomainList[iDomain],"_temporary_")
5129 206 : || EQUAL(papszDomainList[iDomain],"IMAGE_STRUCTURE") )
5130 80 : continue;
5131 :
5132 126 : papszMD = CSLDuplicate(papszMD);
5133 :
5134 442 : for( i = CSLCount(papszMD)-1; i >= 0; i-- )
5135 : {
5136 620 : if( EQUALN(papszMD[i],"TIFFTAG_",8)
5137 304 : || EQUALN(papszMD[i],GDALMD_AREA_OR_POINT,
5138 : strlen(GDALMD_AREA_OR_POINT)) )
5139 52 : papszMD = CSLRemoveStrings( papszMD, i, 1, NULL );
5140 : }
5141 :
5142 126 : if( nBand == 0 )
5143 54 : GDALPamDataset::SetMetadata( papszMD, papszDomainList[iDomain]);
5144 : else
5145 72 : poBand->GDALPamRasterBand::SetMetadata( papszMD, papszDomainList[iDomain]);
5146 :
5147 126 : CSLDestroy( papszMD );
5148 : }
5149 :
5150 : /* -------------------------------------------------------------------- */
5151 : /* Handle some "special domain" stuff. */
5152 : /* -------------------------------------------------------------------- */
5153 172 : if( poBand != NULL )
5154 : {
5155 98 : poBand->GDALPamRasterBand::SetOffset( poBand->GetOffset() );
5156 98 : poBand->GDALPamRasterBand::SetScale( poBand->GetScale() );
5157 98 : poBand->GDALPamRasterBand::SetUnitType( poBand->GetUnitType() );
5158 : }
5159 : }
5160 74 : }
5161 :
5162 : /************************************************************************/
5163 : /* WriteRPCTag() */
5164 : /* */
5165 : /* Format a TAG according to: */
5166 : /* */
5167 : /* http://geotiff.maptools.org/rpc_prop.html */
5168 : /************************************************************************/
5169 :
5170 : /* static */
5171 4 : void GTiffDataset::WriteRPCTag( TIFF *hTIFF, char **papszRPCMD )
5172 :
5173 : {
5174 : double adfRPCTag[92];
5175 : GDALRPCInfo sRPC;
5176 :
5177 4 : if( !GDALExtractRPCInfo( papszRPCMD, &sRPC ) )
5178 0 : return;
5179 :
5180 4 : adfRPCTag[0] = -1.0; // Error Bias
5181 4 : adfRPCTag[1] = -1.0; // Error Random
5182 :
5183 4 : adfRPCTag[2] = sRPC.dfLINE_OFF;
5184 4 : adfRPCTag[3] = sRPC.dfSAMP_OFF;
5185 4 : adfRPCTag[4] = sRPC.dfLAT_OFF;
5186 4 : adfRPCTag[5] = sRPC.dfLONG_OFF;
5187 4 : adfRPCTag[6] = sRPC.dfHEIGHT_OFF;
5188 4 : adfRPCTag[7] = sRPC.dfLINE_SCALE;
5189 4 : adfRPCTag[8] = sRPC.dfSAMP_SCALE;
5190 4 : adfRPCTag[9] = sRPC.dfLAT_SCALE;
5191 4 : adfRPCTag[10] = sRPC.dfLONG_SCALE;
5192 4 : adfRPCTag[11] = sRPC.dfHEIGHT_SCALE;
5193 :
5194 4 : memcpy( adfRPCTag + 12, sRPC.adfLINE_NUM_COEFF, sizeof(double) * 20 );
5195 4 : memcpy( adfRPCTag + 32, sRPC.adfLINE_DEN_COEFF, sizeof(double) * 20 );
5196 4 : memcpy( adfRPCTag + 52, sRPC.adfSAMP_NUM_COEFF, sizeof(double) * 20 );
5197 4 : memcpy( adfRPCTag + 72, sRPC.adfSAMP_DEN_COEFF, sizeof(double) * 20 );
5198 :
5199 4 : TIFFSetField( hTIFF, TIFFTAG_RPCCOEFFICIENT, 92, adfRPCTag );
5200 : }
5201 :
5202 : /************************************************************************/
5203 : /* ReadRPCTag() */
5204 : /* */
5205 : /* Format a TAG according to: */
5206 : /* */
5207 : /* http://geotiff.maptools.org/rpc_prop.html */
5208 : /************************************************************************/
5209 :
5210 4394 : void GTiffDataset::ReadRPCTag()
5211 :
5212 : {
5213 : double *padfRPCTag;
5214 4394 : char **papszMD = NULL;
5215 4394 : CPLString osField;
5216 4394 : CPLString osMultiField;
5217 : int i;
5218 : uint16 nCount;
5219 :
5220 4394 : if( !TIFFGetField( hTIFF, TIFFTAG_RPCCOEFFICIENT, &nCount, &padfRPCTag )
5221 : || nCount != 92 )
5222 : return;
5223 :
5224 12 : osField.Printf( "%.15g", padfRPCTag[2] );
5225 12 : papszMD = CSLSetNameValue( papszMD, "LINE_OFF", osField );
5226 :
5227 12 : osField.Printf( "%.15g", padfRPCTag[3] );
5228 12 : papszMD = CSLSetNameValue( papszMD, "SAMP_OFF", osField );
5229 :
5230 12 : osField.Printf( "%.15g", padfRPCTag[4] );
5231 12 : papszMD = CSLSetNameValue( papszMD, "LAT_OFF", osField );
5232 :
5233 12 : osField.Printf( "%.15g", padfRPCTag[5] );
5234 12 : papszMD = CSLSetNameValue( papszMD, "LONG_OFF", osField );
5235 :
5236 12 : osField.Printf( "%.15g", padfRPCTag[6] );
5237 12 : papszMD = CSLSetNameValue( papszMD, "HEIGHT_OFF", osField );
5238 :
5239 12 : osField.Printf( "%.15g", padfRPCTag[7] );
5240 12 : papszMD = CSLSetNameValue( papszMD, "LINE_SCALE", osField );
5241 :
5242 12 : osField.Printf( "%.15g", padfRPCTag[8] );
5243 12 : papszMD = CSLSetNameValue( papszMD, "SAMP_SCALE", osField );
5244 :
5245 12 : osField.Printf( "%.15g", padfRPCTag[9] );
5246 12 : papszMD = CSLSetNameValue( papszMD, "LAT_SCALE", osField );
5247 :
5248 12 : osField.Printf( "%.15g", padfRPCTag[10] );
5249 12 : papszMD = CSLSetNameValue( papszMD, "LONG_SCALE", osField );
5250 :
5251 12 : osField.Printf( "%.15g", padfRPCTag[11] );
5252 12 : papszMD = CSLSetNameValue( papszMD, "HEIGHT_SCALE", osField );
5253 :
5254 252 : for( i = 0; i < 20; i++ )
5255 : {
5256 240 : osField.Printf( "%.15g", padfRPCTag[12+i] );
5257 240 : if( i > 0 )
5258 228 : osMultiField += " ";
5259 : else
5260 12 : osMultiField = "";
5261 240 : osMultiField += osField;
5262 : }
5263 12 : papszMD = CSLSetNameValue( papszMD, "LINE_NUM_COEFF", osMultiField );
5264 :
5265 252 : for( i = 0; i < 20; i++ )
5266 : {
5267 240 : osField.Printf( "%.15g", padfRPCTag[32+i] );
5268 240 : if( i > 0 )
5269 228 : osMultiField += " ";
5270 : else
5271 12 : osMultiField = "";
5272 240 : osMultiField += osField;
5273 : }
5274 12 : papszMD = CSLSetNameValue( papszMD, "LINE_DEN_COEFF", osMultiField );
5275 :
5276 252 : for( i = 0; i < 20; i++ )
5277 : {
5278 240 : osField.Printf( "%.15g", padfRPCTag[52+i] );
5279 240 : if( i > 0 )
5280 228 : osMultiField += " ";
5281 : else
5282 12 : osMultiField = "";
5283 240 : osMultiField += osField;
5284 : }
5285 12 : papszMD = CSLSetNameValue( papszMD, "SAMP_NUM_COEFF", osMultiField );
5286 :
5287 252 : for( i = 0; i < 20; i++ )
5288 : {
5289 240 : osField.Printf( "%.15g", padfRPCTag[72+i] );
5290 240 : if( i > 0 )
5291 228 : osMultiField += " ";
5292 : else
5293 12 : osMultiField = "";
5294 240 : osMultiField += osField;
5295 : }
5296 12 : papszMD = CSLSetNameValue( papszMD, "SAMP_DEN_COEFF", osMultiField );
5297 :
5298 12 : oGTiffMDMD.SetMetadata( papszMD, "RPC" );
5299 12 : CSLDestroy( papszMD );
5300 : }
5301 :
5302 : /************************************************************************/
5303 : /* WriteNoDataValue() */
5304 : /************************************************************************/
5305 :
5306 138 : void GTiffDataset::WriteNoDataValue( TIFF *hTIFF, double dfNoData )
5307 :
5308 : {
5309 : char szVal[400];
5310 138 : if (CPLIsNan(dfNoData))
5311 2 : strcpy(szVal, "nan");
5312 : else
5313 136 : snprintf(szVal, sizeof(szVal), "%.18g", dfNoData);
5314 138 : TIFFSetField( hTIFF, TIFFTAG_GDAL_NODATA, szVal );
5315 138 : }
5316 :
5317 : /************************************************************************/
5318 : /* SetDirectory() */
5319 : /************************************************************************/
5320 :
5321 445138 : int GTiffDataset::SetDirectory( toff_t nNewOffset )
5322 :
5323 : {
5324 445138 : Crystalize();
5325 :
5326 445138 : FlushBlockBuf();
5327 :
5328 445138 : if( nNewOffset == 0 )
5329 436854 : nNewOffset = nDirOffset;
5330 :
5331 445138 : if( TIFFCurrentDirOffset(hTIFF) == nNewOffset )
5332 : {
5333 442200 : CPLAssert( *ppoActiveDSRef == this || *ppoActiveDSRef == NULL );
5334 442200 : *ppoActiveDSRef = this;
5335 442200 : return TRUE;
5336 : }
5337 :
5338 2938 : if( GetAccess() == GA_Update )
5339 : {
5340 2370 : if( *ppoActiveDSRef != NULL )
5341 2134 : (*ppoActiveDSRef)->FlushDirectory();
5342 : }
5343 :
5344 2938 : if( nNewOffset == 0)
5345 0 : return TRUE;
5346 :
5347 2938 : (*ppoActiveDSRef) = this;
5348 :
5349 2938 : int nSetDirResult = TIFFSetSubDirectory( hTIFF, nNewOffset );
5350 2938 : if (!nSetDirResult)
5351 0 : return nSetDirResult;
5352 :
5353 : /* -------------------------------------------------------------------- */
5354 : /* YCbCr JPEG compressed images should be translated on the fly */
5355 : /* to RGB by libtiff/libjpeg unless specifically requested */
5356 : /* otherwise. */
5357 : /* -------------------------------------------------------------------- */
5358 2938 : if( !TIFFGetField( hTIFF, TIFFTAG_COMPRESSION, &(nCompression) ) )
5359 0 : nCompression = COMPRESSION_NONE;
5360 :
5361 2938 : if( !TIFFGetField( hTIFF, TIFFTAG_PHOTOMETRIC, &(nPhotometric) ) )
5362 0 : nPhotometric = PHOTOMETRIC_MINISBLACK;
5363 :
5364 2938 : if( nCompression == COMPRESSION_JPEG
5365 : && nPhotometric == PHOTOMETRIC_YCBCR
5366 : && CSLTestBoolean( CPLGetConfigOption("CONVERT_YCBCR_TO_RGB",
5367 : "YES") ) )
5368 : {
5369 : int nColorMode;
5370 :
5371 432 : TIFFGetField( hTIFF, TIFFTAG_JPEGCOLORMODE, &nColorMode );
5372 432 : if( nColorMode != JPEGCOLORMODE_RGB )
5373 432 : TIFFSetField(hTIFF, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
5374 : }
5375 :
5376 : /* -------------------------------------------------------------------- */
5377 : /* Propogate any quality settings. */
5378 : /* -------------------------------------------------------------------- */
5379 2938 : if( GetAccess() == GA_Update )
5380 : {
5381 : // Now, reset zip and jpeg quality.
5382 2370 : if(nJpegQuality > 0 && nCompression == COMPRESSION_JPEG)
5383 : {
5384 : CPLDebug( "GTiff", "Propgate JPEG_QUALITY(%d) in SetDirectory()",
5385 268 : nJpegQuality );
5386 268 : TIFFSetField(hTIFF, TIFFTAG_JPEGQUALITY, nJpegQuality);
5387 : }
5388 2370 : if(nZLevel > 0 && nCompression == COMPRESSION_ADOBE_DEFLATE)
5389 0 : TIFFSetField(hTIFF, TIFFTAG_ZIPQUALITY, nZLevel);
5390 2370 : if(nLZMAPreset > 0 && nCompression == COMPRESSION_LZMA)
5391 0 : TIFFSetField(hTIFF, TIFFTAG_LZMAPRESET, nLZMAPreset);
5392 : }
5393 :
5394 2938 : return nSetDirResult;
5395 : }
5396 :
5397 : /************************************************************************/
5398 : /* Identify() */
5399 : /************************************************************************/
5400 :
5401 36630 : int GTiffDataset::Identify( GDALOpenInfo * poOpenInfo )
5402 :
5403 : {
5404 36630 : const char *pszFilename = poOpenInfo->pszFilename;
5405 36630 : if( EQUALN(pszFilename,"GTIFF_RAW:", strlen("GTIFF_RAW:")) )
5406 : {
5407 428 : pszFilename += strlen("GTIFF_RAW:");
5408 428 : GDALOpenInfo oOpenInfo( pszFilename, poOpenInfo->eAccess );
5409 428 : return Identify(&oOpenInfo);
5410 : }
5411 :
5412 : /* -------------------------------------------------------------------- */
5413 : /* We have a special hook for handling opening a specific */
5414 : /* directory of a TIFF file. */
5415 : /* -------------------------------------------------------------------- */
5416 36202 : if( EQUALN(pszFilename,"GTIFF_DIR:",strlen("GTIFF_DIR:")) )
5417 12 : return TRUE;
5418 :
5419 : /* -------------------------------------------------------------------- */
5420 : /* First we check to see if the file has the expected header */
5421 : /* bytes. */
5422 : /* -------------------------------------------------------------------- */
5423 36190 : if( poOpenInfo->nHeaderBytes < 2 )
5424 22166 : return FALSE;
5425 :
5426 20720 : if( (poOpenInfo->pabyHeader[0] != 'I' || poOpenInfo->pabyHeader[1] != 'I')
5427 6696 : && (poOpenInfo->pabyHeader[0] != 'M' || poOpenInfo->pabyHeader[1] != 'M'))
5428 6406 : return FALSE;
5429 :
5430 : #ifndef BIGTIFF_SUPPORT
5431 : if( (poOpenInfo->pabyHeader[2] == 0x2B && poOpenInfo->pabyHeader[3] == 0) ||
5432 : (poOpenInfo->pabyHeader[2] == 0 && poOpenInfo->pabyHeader[3] == 0x2B) )
5433 : {
5434 : CPLError( CE_Failure, CPLE_OpenFailed,
5435 : "This is a BigTIFF file. BigTIFF is not supported by this\n"
5436 : "version of GDAL and libtiff." );
5437 : return FALSE;
5438 : }
5439 : #endif
5440 :
5441 8148 : if( (poOpenInfo->pabyHeader[2] != 0x2A || poOpenInfo->pabyHeader[3] != 0)
5442 342 : && (poOpenInfo->pabyHeader[3] != 0x2A || poOpenInfo->pabyHeader[2] != 0)
5443 156 : && (poOpenInfo->pabyHeader[2] != 0x2B || poOpenInfo->pabyHeader[3] != 0)
5444 32 : && (poOpenInfo->pabyHeader[3] != 0x2B || poOpenInfo->pabyHeader[2] != 0))
5445 0 : return FALSE;
5446 :
5447 7618 : return TRUE;
5448 : }
5449 :
5450 : /************************************************************************/
5451 : /* Open() */
5452 : /************************************************************************/
5453 :
5454 16970 : GDALDataset *GTiffDataset::Open( GDALOpenInfo * poOpenInfo )
5455 :
5456 : {
5457 : TIFF *hTIFF;
5458 16970 : int bAllowRGBAInterface = TRUE;
5459 16970 : const char *pszFilename = poOpenInfo->pszFilename;
5460 :
5461 : /* -------------------------------------------------------------------- */
5462 : /* Check if it looks like a TIFF file. */
5463 : /* -------------------------------------------------------------------- */
5464 16970 : if (!Identify(poOpenInfo))
5465 9416 : return NULL;
5466 :
5467 7554 : if( EQUALN(pszFilename,"GTIFF_RAW:", strlen("GTIFF_RAW:")) )
5468 : {
5469 428 : bAllowRGBAInterface = FALSE;
5470 428 : pszFilename += strlen("GTIFF_RAW:");
5471 : }
5472 :
5473 : /* -------------------------------------------------------------------- */
5474 : /* We have a special hook for handling opening a specific */
5475 : /* directory of a TIFF file. */
5476 : /* -------------------------------------------------------------------- */
5477 7554 : if( EQUALN(pszFilename,"GTIFF_DIR:",strlen("GTIFF_DIR:")) )
5478 12 : return OpenDir( poOpenInfo );
5479 :
5480 7542 : if (!GTiffOneTimeInit())
5481 0 : return NULL;
5482 :
5483 : /* -------------------------------------------------------------------- */
5484 : /* Try opening the dataset. */
5485 : /* -------------------------------------------------------------------- */
5486 7542 : if( poOpenInfo->eAccess == GA_ReadOnly )
5487 6656 : hTIFF = VSI_TIFFOpen( pszFilename, "r" );
5488 : else
5489 886 : hTIFF = VSI_TIFFOpen( pszFilename, "r+" );
5490 :
5491 7542 : if( hTIFF == NULL )
5492 0 : return( NULL );
5493 :
5494 : /* -------------------------------------------------------------------- */
5495 : /* Create a corresponding GDALDataset. */
5496 : /* -------------------------------------------------------------------- */
5497 : GTiffDataset *poDS;
5498 :
5499 7542 : poDS = new GTiffDataset();
5500 7542 : poDS->SetDescription( pszFilename );
5501 15084 : poDS->osFilename = pszFilename;
5502 7542 : poDS->poActiveDS = poDS;
5503 :
5504 7542 : if( poDS->OpenOffset( hTIFF, &(poDS->poActiveDS),
5505 : TIFFCurrentDirOffset(hTIFF), TRUE,
5506 : poOpenInfo->eAccess,
5507 : bAllowRGBAInterface, TRUE,
5508 : poOpenInfo->papszSiblingFiles) != CE_None )
5509 : {
5510 0 : delete poDS;
5511 0 : return NULL;
5512 : }
5513 :
5514 : /* -------------------------------------------------------------------- */
5515 : /* Initialize any PAM information. */
5516 : /* -------------------------------------------------------------------- */
5517 7542 : poDS->TryLoadXML( poOpenInfo->papszSiblingFiles);
5518 7542 : poDS->ApplyPamInfo();
5519 :
5520 : int i;
5521 541562 : for(i=1;i<=poDS->nBands;i++)
5522 : {
5523 534020 : GTiffRasterBand* poBand = (GTiffRasterBand*) poDS->GetRasterBand(i);
5524 :
5525 : /* Load scale, offset and unittype from PAM if available */
5526 534020 : if (!poBand->bHaveOffsetScale)
5527 : {
5528 534008 : poBand->dfScale = poBand->GDALPamRasterBand::GetScale(&poBand->bHaveOffsetScale);
5529 534008 : poBand->dfOffset = poBand->GDALPamRasterBand::GetOffset();
5530 : }
5531 534020 : if (poBand->osUnitType.size() == 0)
5532 : {
5533 533994 : const char* pszUnitType = poBand->GDALPamRasterBand::GetUnitType();
5534 533994 : if (pszUnitType)
5535 533994 : poBand->osUnitType = pszUnitType;
5536 : }
5537 : }
5538 :
5539 7542 : poDS->bMetadataChanged = FALSE;
5540 7542 : poDS->bGeoTIFFInfoChanged = FALSE;
5541 :
5542 : /* -------------------------------------------------------------------- */
5543 : /* Check for external overviews. */
5544 : /* -------------------------------------------------------------------- */
5545 7542 : poDS->oOvManager.Initialize( poDS, pszFilename, poOpenInfo->papszSiblingFiles );
5546 :
5547 7542 : return poDS;
5548 : }
5549 :
5550 : /************************************************************************/
5551 : /* LookForProjection() */
5552 : /************************************************************************/
5553 :
5554 12660 : void GTiffDataset::LookForProjection()
5555 :
5556 : {
5557 12660 : if( bLookedForProjection )
5558 10724 : return;
5559 :
5560 1936 : bLookedForProjection = TRUE;
5561 1936 : if (!SetDirectory())
5562 0 : return;
5563 :
5564 : /* -------------------------------------------------------------------- */
5565 : /* Capture the GeoTIFF projection, if available. */
5566 : /* -------------------------------------------------------------------- */
5567 : GTIF *hGTIF;
5568 : GTIFDefn sGTIFDefn;
5569 :
5570 1936 : CPLFree( pszProjection );
5571 1936 : pszProjection = NULL;
5572 :
5573 1936 : hGTIF = GTIFNew(hTIFF);
5574 :
5575 1936 : if ( !hGTIF )
5576 : {
5577 : CPLError( CE_Warning, CPLE_AppDefined,
5578 0 : "GeoTIFF tags apparently corrupt, they are being ignored." );
5579 : }
5580 : else
5581 : {
5582 1936 : if( GTIFGetDefn( hGTIF, &sGTIFDefn ) )
5583 : {
5584 1856 : pszProjection = GTIFGetOGISDefn( hGTIF, &sGTIFDefn );
5585 :
5586 : // Should we simplify away vertical CS stuff?
5587 1856 : if( EQUALN(pszProjection,"COMPD_CS",8)
5588 : && !CSLTestBoolean( CPLGetConfigOption("GTIFF_REPORT_COMPD_CS",
5589 : "NO") ) )
5590 : {
5591 2 : OGRSpatialReference oSRS;
5592 :
5593 2 : CPLDebug( "GTiff", "Got COMPD_CS, but stripping it." );
5594 2 : char *pszWKT = pszProjection;
5595 2 : oSRS.importFromWkt( &pszWKT );
5596 2 : CPLFree( pszProjection );
5597 :
5598 2 : oSRS.StripVertical();
5599 2 : oSRS.exportToWkt( &pszProjection );
5600 : }
5601 : }
5602 :
5603 : // Is this a pixel-is-point dataset?
5604 : short nRasterType;
5605 :
5606 : // check the tif linear unit and the CS linear unit
5607 : #ifdef ESRI_BUILD
5608 : AdjustLinearUnit(sGTIFDefn.UOMLength);
5609 : #endif
5610 :
5611 1936 : if( GTIFKeyGet(hGTIF, GTRasterTypeGeoKey, &nRasterType,
5612 : 0, 1 ) == 1 )
5613 : {
5614 1854 : if( nRasterType == (short) RasterPixelIsPoint )
5615 42 : oGTiffMDMD.SetMetadataItem( GDALMD_AREA_OR_POINT, GDALMD_AOP_POINT );
5616 : else
5617 1812 : oGTiffMDMD.SetMetadataItem( GDALMD_AREA_OR_POINT, GDALMD_AOP_AREA );
5618 : }
5619 :
5620 1936 : GTIFFree( hGTIF );
5621 : }
5622 :
5623 1936 : if( pszProjection == NULL )
5624 : {
5625 80 : pszProjection = CPLStrdup( "" );
5626 : }
5627 :
5628 1936 : bGeoTIFFInfoChanged = FALSE;
5629 : }
5630 :
5631 : /************************************************************************/
5632 : /* AdjustLinearUnit() */
5633 : /* */
5634 : /* The following code is only used in ESRI Builds and there is */
5635 : /* outstanding discussion on whether it is even appropriate */
5636 : /* then. */
5637 : /************************************************************************/
5638 : #ifdef ESRI_BUILD
5639 :
5640 : void GTiffDataset::AdjustLinearUnit(short UOMLength)
5641 : {
5642 : if (!pszProjection || strlen(pszProjection) == 0)
5643 : return;
5644 : if( UOMLength == 9001)
5645 : {
5646 : char* pstr = strstr(pszProjection, "PARAMETER");
5647 : if (!pstr)
5648 : return;
5649 : pstr = strstr(pstr, "UNIT[");
5650 : if (!pstr)
5651 : return;
5652 : pstr = strchr(pstr, ',') + 1;
5653 : if (!pstr)
5654 : return;
5655 : char* pstr1 = strchr(pstr, ']');
5656 : if (!pstr1 || pstr1 - pstr >= 128)
5657 : return;
5658 : char csUnitStr[128];
5659 : strncpy(csUnitStr, pstr, pstr1-pstr);
5660 : csUnitStr[pstr1-pstr] = '\0';
5661 : double csUnit = CPLAtof(csUnitStr);
5662 : if(fabs(csUnit - 1.0) > 0.000001)
5663 : {
5664 : for(long i=0; i<6; i++)
5665 : adfGeoTransform[i] /= csUnit;
5666 : }
5667 : }
5668 : }
5669 :
5670 : #endif /* def ESRI_BUILD */
5671 :
5672 : /************************************************************************/
5673 : /* ApplyPamInfo() */
5674 : /* */
5675 : /* PAM Information, if available, overrides the GeoTIFF */
5676 : /* geotransform and projection definition. Check for them */
5677 : /* now. */
5678 : /************************************************************************/
5679 :
5680 7542 : void GTiffDataset::ApplyPamInfo()
5681 :
5682 : {
5683 : double adfPamGeoTransform[6];
5684 :
5685 7542 : if( GDALPamDataset::GetGeoTransform( adfPamGeoTransform ) == CE_None
5686 0 : && (adfPamGeoTransform[0] != 0.0 || adfPamGeoTransform[1] != 1.0
5687 0 : || adfPamGeoTransform[2] != 0.0 || adfPamGeoTransform[3] != 0.0
5688 0 : || adfPamGeoTransform[4] != 0.0 || adfPamGeoTransform[5] != 1.0 ))
5689 : {
5690 0 : memcpy( adfGeoTransform, adfPamGeoTransform, sizeof(double)*6 );
5691 0 : bGeoTransformValid = TRUE;
5692 : }
5693 :
5694 7542 : const char *pszPamSRS = GDALPamDataset::GetProjectionRef();
5695 :
5696 7542 : if( pszPamSRS != NULL && strlen(pszPamSRS) > 0 )
5697 : {
5698 4 : CPLFree( pszProjection );
5699 4 : pszProjection = CPLStrdup( pszPamSRS );
5700 4 : bLookedForProjection = TRUE;
5701 : }
5702 :
5703 7542 : int nPamGCPCount = GDALPamDataset::GetGCPCount();
5704 7542 : if( nPamGCPCount > 0 )
5705 : {
5706 4 : if( nGCPCount > 0 )
5707 : {
5708 0 : GDALDeinitGCPs( nGCPCount, pasGCPList );
5709 0 : CPLFree( pasGCPList );
5710 0 : pasGCPList = NULL;
5711 : }
5712 :
5713 4 : nGCPCount = nPamGCPCount;
5714 4 : pasGCPList = GDALDuplicateGCPs(nGCPCount, GDALPamDataset::GetGCPs());
5715 :
5716 4 : CPLFree( pszProjection );
5717 4 : pszProjection = NULL;
5718 :
5719 4 : const char *pszPamGCPProjection = GDALPamDataset::GetGCPProjection();
5720 4 : if( pszPamGCPProjection != NULL && strlen(pszPamGCPProjection) > 0 )
5721 4 : pszProjection = CPLStrdup(pszPamGCPProjection);
5722 :
5723 4 : bLookedForProjection = TRUE;
5724 : }
5725 :
5726 : /* -------------------------------------------------------------------- */
5727 : /* Copy any PAM metadata into our GeoTIFF context, and with */
5728 : /* the PAM info overriding the GeoTIFF context. */
5729 : /* -------------------------------------------------------------------- */
5730 7542 : char **papszPamDomains = oMDMD.GetDomainList();
5731 :
5732 7574 : for( int iDomain = 0; papszPamDomains && papszPamDomains[iDomain] != NULL; iDomain++ )
5733 : {
5734 32 : const char *pszDomain = papszPamDomains[iDomain];
5735 32 : char **papszGT_MD = CSLDuplicate(oGTiffMDMD.GetMetadata( pszDomain ));
5736 32 : char **papszPAM_MD = oMDMD.GetMetadata( pszDomain );
5737 :
5738 32 : papszGT_MD = CSLMerge( papszGT_MD, papszPAM_MD );
5739 :
5740 32 : oGTiffMDMD.SetMetadata( papszGT_MD, pszDomain );
5741 32 : CSLDestroy( papszGT_MD );
5742 : }
5743 :
5744 541562 : for( int i = 1; i <= GetRasterCount(); i++)
5745 : {
5746 534020 : GTiffRasterBand* poBand = (GTiffRasterBand *)GetRasterBand(i);
5747 534020 : papszPamDomains = poBand->oMDMD.GetDomainList();
5748 :
5749 534080 : for( int iDomain = 0; papszPamDomains && papszPamDomains[iDomain] != NULL; iDomain++ )
5750 : {
5751 60 : const char *pszDomain = papszPamDomains[iDomain];
5752 60 : char **papszGT_MD = CSLDuplicate(poBand->oGTiffMDMD.GetMetadata( pszDomain ));
5753 60 : char **papszPAM_MD = poBand->oMDMD.GetMetadata( pszDomain );
5754 :
5755 60 : papszGT_MD = CSLMerge( papszGT_MD, papszPAM_MD );
5756 :
5757 60 : poBand->oGTiffMDMD.SetMetadata( papszGT_MD, pszDomain );
5758 60 : CSLDestroy( papszGT_MD );
5759 : }
5760 : }
5761 7542 : }
5762 :
5763 : /************************************************************************/
5764 : /* OpenDir() */
5765 : /* */
5766 : /* Open a specific directory as encoded into a filename. */
5767 : /************************************************************************/
5768 :
5769 12 : GDALDataset *GTiffDataset::OpenDir( GDALOpenInfo * poOpenInfo )
5770 :
5771 : {
5772 12 : int bAllowRGBAInterface = TRUE;
5773 12 : const char* pszFilename = poOpenInfo->pszFilename;
5774 12 : if( EQUALN(pszFilename,"GTIFF_RAW:", strlen("GTIFF_RAW:")) )
5775 : {
5776 0 : bAllowRGBAInterface = FALSE;
5777 0 : pszFilename += strlen("GTIFF_RAW:");
5778 : }
5779 :
5780 12 : if( !EQUALN(pszFilename,"GTIFF_DIR:",strlen("GTIFF_DIR:")) )
5781 0 : return NULL;
5782 :
5783 : /* -------------------------------------------------------------------- */
5784 : /* Split out filename, and dir#/offset. */
5785 : /* -------------------------------------------------------------------- */
5786 12 : pszFilename += strlen("GTIFF_DIR:");
5787 12 : int bAbsolute = FALSE;
5788 : toff_t nOffset;
5789 :
5790 12 : if( EQUALN(pszFilename,"off:",4) )
5791 : {
5792 2 : bAbsolute = TRUE;
5793 2 : pszFilename += 4;
5794 : }
5795 :
5796 12 : nOffset = atol(pszFilename);
5797 12 : pszFilename += 1;
5798 :
5799 40 : while( *pszFilename != '\0' && pszFilename[-1] != ':' )
5800 16 : pszFilename++;
5801 :
5802 12 : if( *pszFilename == '\0' || nOffset == 0 )
5803 : {
5804 : CPLError( CE_Failure, CPLE_OpenFailed,
5805 : "Unable to extract offset or filename, should take the form\n"
5806 0 : "GTIFF_DIR:<dir>:filename or GTIFF_DIR:off:<dir_offset>:filename" );
5807 0 : return NULL;
5808 : }
5809 :
5810 : /* -------------------------------------------------------------------- */
5811 : /* Try opening the dataset. */
5812 : /* -------------------------------------------------------------------- */
5813 : TIFF *hTIFF;
5814 :
5815 12 : if (!GTiffOneTimeInit())
5816 0 : return NULL;
5817 :
5818 12 : hTIFF = VSI_TIFFOpen( pszFilename, "r" );
5819 12 : if( hTIFF == NULL )
5820 0 : return( NULL );
5821 :
5822 : /* -------------------------------------------------------------------- */
5823 : /* If a directory was requested by index, advance to it now. */
5824 : /* -------------------------------------------------------------------- */
5825 12 : if( !bAbsolute )
5826 : {
5827 24 : while( nOffset > 1 )
5828 : {
5829 4 : if( TIFFReadDirectory( hTIFF ) == 0 )
5830 : {
5831 0 : XTIFFClose( hTIFF );
5832 : CPLError( CE_Failure, CPLE_OpenFailed,
5833 0 : "Requested directory %lu not found.", (long unsigned int)nOffset );
5834 0 : return NULL;
5835 : }
5836 4 : nOffset--;
5837 : }
5838 :
5839 10 : nOffset = TIFFCurrentDirOffset( hTIFF );
5840 : }
5841 :
5842 : /* -------------------------------------------------------------------- */
5843 : /* Create a corresponding GDALDataset. */
5844 : /* -------------------------------------------------------------------- */
5845 : GTiffDataset *poDS;
5846 :
5847 12 : poDS = new GTiffDataset();
5848 12 : poDS->SetDescription( poOpenInfo->pszFilename );
5849 24 : poDS->osFilename = poOpenInfo->pszFilename;
5850 12 : poDS->poActiveDS = poDS;
5851 :
5852 24 : if( !EQUAL(pszFilename,poOpenInfo->pszFilename)
5853 : && !EQUALN(poOpenInfo->pszFilename,"GTIFF_RAW:",10) )
5854 : {
5855 12 : poDS->SetPhysicalFilename( pszFilename );
5856 12 : poDS->SetSubdatasetName( poOpenInfo->pszFilename );
5857 12 : poDS->osFilename = pszFilename;
5858 : }
5859 :
5860 12 : if (poOpenInfo->eAccess == GA_Update)
5861 : {
5862 : CPLError( CE_Warning, CPLE_AppDefined,
5863 0 : "Opening a specific TIFF directory is not supported in update mode. Switching to read-only" );
5864 : }
5865 :
5866 12 : if( poDS->OpenOffset( hTIFF, &(poDS->poActiveDS),
5867 : nOffset, FALSE, GA_ReadOnly,
5868 : bAllowRGBAInterface, TRUE,
5869 : poOpenInfo->papszSiblingFiles ) != CE_None )
5870 : {
5871 0 : delete poDS;
5872 0 : return NULL;
5873 : }
5874 : else
5875 : {
5876 12 : poDS->bCloseTIFFHandle = TRUE;
5877 12 : return poDS;
5878 : }
5879 : }
5880 :
5881 : /************************************************************************/
5882 : /* OpenOffset() */
5883 : /* */
5884 : /* Initialize the GTiffDataset based on a passed in file */
5885 : /* handle, and directory offset to utilize. This is called for */
5886 : /* full res, and overview pages. */
5887 : /************************************************************************/
5888 :
5889 8284 : CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
5890 : GTiffDataset **ppoActiveDSRef,
5891 : toff_t nDirOffsetIn,
5892 : int bBaseIn, GDALAccess eAccess,
5893 : int bAllowRGBAInterface,
5894 : int bReadGeoTransform,
5895 : char** papszSiblingFiles )
5896 :
5897 : {
5898 : uint32 nXSize, nYSize;
5899 8284 : int bTreatAsBitmap = FALSE;
5900 8284 : int bTreatAsOdd = FALSE;
5901 :
5902 8284 : this->eAccess = eAccess;
5903 :
5904 8284 : hTIFF = hTIFFIn;
5905 8284 : this->ppoActiveDSRef = ppoActiveDSRef;
5906 :
5907 8284 : nDirOffset = nDirOffsetIn;
5908 :
5909 8284 : if (!SetDirectory( nDirOffsetIn ))
5910 0 : return CE_Failure;
5911 :
5912 8284 : bBase = bBaseIn;
5913 :
5914 8284 : this->eAccess = eAccess;
5915 :
5916 : /* -------------------------------------------------------------------- */
5917 : /* Capture some information from the file that is of interest. */
5918 : /* -------------------------------------------------------------------- */
5919 8284 : TIFFGetField( hTIFF, TIFFTAG_IMAGEWIDTH, &nXSize );
5920 8284 : TIFFGetField( hTIFF, TIFFTAG_IMAGELENGTH, &nYSize );
5921 8284 : nRasterXSize = nXSize;
5922 8284 : nRasterYSize = nYSize;
5923 :
5924 8284 : if( !TIFFGetField(hTIFF, TIFFTAG_SAMPLESPERPIXEL, &nSamplesPerPixel ) )
5925 0 : nBands = 1;
5926 : else
5927 8284 : nBands = nSamplesPerPixel;
5928 :
5929 8284 : if( !TIFFGetField(hTIFF, TIFFTAG_BITSPERSAMPLE, &(nBitsPerSample)) )
5930 0 : nBitsPerSample = 1;
5931 :
5932 8284 : if( !TIFFGetField( hTIFF, TIFFTAG_PLANARCONFIG, &(nPlanarConfig) ) )
5933 0 : nPlanarConfig = PLANARCONFIG_CONTIG;
5934 :
5935 8284 : if( !TIFFGetField( hTIFF, TIFFTAG_PHOTOMETRIC, &(nPhotometric) ) )
5936 0 : nPhotometric = PHOTOMETRIC_MINISBLACK;
5937 :
5938 8284 : if( !TIFFGetField( hTIFF, TIFFTAG_SAMPLEFORMAT, &(nSampleFormat) ) )
5939 76 : nSampleFormat = SAMPLEFORMAT_UINT;
5940 :
5941 8284 : if( !TIFFGetField( hTIFF, TIFFTAG_COMPRESSION, &(nCompression) ) )
5942 0 : nCompression = COMPRESSION_NONE;
5943 :
5944 : #if defined(TIFFLIB_VERSION) && TIFFLIB_VERSION > 20031007 /* 3.6.0 */
5945 8284 : if (nCompression != COMPRESSION_NONE &&
5946 : !TIFFIsCODECConfigured(nCompression))
5947 : {
5948 : CPLError( CE_Failure, CPLE_AppDefined,
5949 0 : "Cannot open TIFF file due to missing codec." );
5950 0 : return CE_Failure;
5951 : }
5952 : #endif
5953 :
5954 : /* -------------------------------------------------------------------- */
5955 : /* YCbCr JPEG compressed images should be translated on the fly */
5956 : /* to RGB by libtiff/libjpeg unless specifically requested */
5957 : /* otherwise. */
5958 : /* -------------------------------------------------------------------- */
5959 8284 : if( nCompression == COMPRESSION_JPEG
5960 : && nPhotometric == PHOTOMETRIC_YCBCR
5961 : && CSLTestBoolean( CPLGetConfigOption("CONVERT_YCBCR_TO_RGB",
5962 : "YES") ) )
5963 : {
5964 : int nColorMode;
5965 :
5966 236 : SetMetadataItem( "SOURCE_COLOR_SPACE", "YCbCr", "IMAGE_STRUCTURE" );
5967 236 : if ( !TIFFGetField( hTIFF, TIFFTAG_JPEGCOLORMODE, &nColorMode ) ||
5968 : nColorMode != JPEGCOLORMODE_RGB )
5969 200 : TIFFSetField(hTIFF, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
5970 : }
5971 :
5972 : /* -------------------------------------------------------------------- */
5973 : /* Get strip/tile layout. */
5974 : /* -------------------------------------------------------------------- */
5975 8284 : if( TIFFIsTiled(hTIFF) )
5976 : {
5977 1360 : TIFFGetField( hTIFF, TIFFTAG_TILEWIDTH, &(nBlockXSize) );
5978 1360 : TIFFGetField( hTIFF, TIFFTAG_TILELENGTH, &(nBlockYSize) );
5979 : }
5980 : else
5981 : {
5982 6924 : if( !TIFFGetField( hTIFF, TIFFTAG_ROWSPERSTRIP,
5983 : &(nRowsPerStrip) ) )
5984 : {
5985 : CPLError( CE_Warning, CPLE_AppDefined,
5986 0 : "RowsPerStrip not defined ... assuming all one strip." );
5987 0 : nRowsPerStrip = nYSize; /* dummy value */
5988 : }
5989 :
5990 : // If the rows per strip is larger than the file we will get
5991 : // confused. libtiff internally will treat the rowsperstrip as
5992 : // the image height and it is best if we do too. (#4468)
5993 6924 : if (nRowsPerStrip > (uint32)nRasterYSize)
5994 22 : nRowsPerStrip = nRasterYSize;
5995 :
5996 6924 : nBlockXSize = nRasterXSize;
5997 6924 : nBlockYSize = nRowsPerStrip;
5998 : }
5999 :
6000 : nBlocksPerBand =
6001 : ((nYSize + nBlockYSize - 1) / nBlockYSize)
6002 8284 : * ((nXSize + nBlockXSize - 1) / nBlockXSize);
6003 :
6004 : /* -------------------------------------------------------------------- */
6005 : /* Should we handle this using the GTiffBitmapBand? */
6006 : /* -------------------------------------------------------------------- */
6007 8284 : if( nBitsPerSample == 1 && nBands == 1 )
6008 : {
6009 256 : bTreatAsBitmap = TRUE;
6010 :
6011 : // Lets treat large "one row" bitmaps using the scanline api.
6012 256 : if( !TIFFIsTiled(hTIFF)
6013 : && nBlockYSize == nYSize
6014 : && nYSize > 2000
6015 : && bAllowRGBAInterface )
6016 8 : bTreatAsSplitBitmap = TRUE;
6017 : }
6018 :
6019 : /* -------------------------------------------------------------------- */
6020 : /* Should we treat this via the RGBA interface? */
6021 : /* -------------------------------------------------------------------- */
6022 8284 : if( bAllowRGBAInterface &&
6023 : !bTreatAsBitmap && !(nBitsPerSample > 8)
6024 : && (nPhotometric == PHOTOMETRIC_CIELAB ||
6025 : nPhotometric == PHOTOMETRIC_LOGL ||
6026 : nPhotometric == PHOTOMETRIC_LOGLUV ||
6027 : nPhotometric == PHOTOMETRIC_SEPARATED ||
6028 : ( nPhotometric == PHOTOMETRIC_YCBCR
6029 : && nCompression != COMPRESSION_JPEG )) )
6030 : {
6031 : char szMessage[1024];
6032 :
6033 10 : if( TIFFRGBAImageOK( hTIFF, szMessage ) == 1 )
6034 : {
6035 10 : const char* pszSourceColorSpace = NULL;
6036 10 : switch (nPhotometric)
6037 : {
6038 : case PHOTOMETRIC_CIELAB:
6039 2 : pszSourceColorSpace = "CIELAB";
6040 2 : break;
6041 : case PHOTOMETRIC_LOGL:
6042 0 : pszSourceColorSpace = "LOGL";
6043 0 : break;
6044 : case PHOTOMETRIC_LOGLUV:
6045 0 : pszSourceColorSpace = "LOGLUV";
6046 0 : break;
6047 : case PHOTOMETRIC_SEPARATED:
6048 6 : pszSourceColorSpace = "CMYK";
6049 6 : break;
6050 : case PHOTOMETRIC_YCBCR:
6051 2 : pszSourceColorSpace = "YCbCr";
6052 : break;
6053 : }
6054 10 : if (pszSourceColorSpace)
6055 10 : SetMetadataItem( "SOURCE_COLOR_SPACE", pszSourceColorSpace, "IMAGE_STRUCTURE" );
6056 10 : bTreatAsRGBA = TRUE;
6057 10 : nBands = 4;
6058 : }
6059 : else
6060 : {
6061 0 : CPLDebug( "GTiff", "TIFFRGBAImageOK says:\n%s", szMessage );
6062 : }
6063 : }
6064 :
6065 : /* -------------------------------------------------------------------- */
6066 : /* Should we treat this via the split interface? */
6067 : /* -------------------------------------------------------------------- */
6068 8284 : if( !TIFFIsTiled(hTIFF)
6069 : && nBitsPerSample == 8
6070 : && nBlockYSize == nYSize
6071 : && nYSize > 2000
6072 : && !bTreatAsRGBA
6073 : && CSLTestBoolean(CPLGetConfigOption("GDAL_ENABLE_TIFF_SPLIT", "YES")))
6074 : {
6075 : /* libtiff 3.9.2 (20091104) and older, libtiff 4.0.0beta5 (also 20091104) */
6076 : /* and older will crash when trying to open a all-in-one-strip */
6077 : /* YCbCr JPEG compressed TIFF (see #3259). */
6078 : #if (TIFFLIB_VERSION <= 20091104 && !defined(BIGTIFF_SUPPORT)) || \
6079 : (TIFFLIB_VERSION <= 20091104 && defined(BIGTIFF_SUPPORT))
6080 : if (nPhotometric == PHOTOMETRIC_YCBCR &&
6081 : nCompression == COMPRESSION_JPEG)
6082 : {
6083 : CPLDebug("GTiff", "Avoid using split band to open all-in-one-strip "
6084 : "YCbCr JPEG compressed TIFF because of older libtiff");
6085 : }
6086 : else
6087 : #endif
6088 18 : bTreatAsSplit = TRUE;
6089 : }
6090 :
6091 : /* -------------------------------------------------------------------- */
6092 : /* Should we treat this via the odd bits interface? */
6093 : /* -------------------------------------------------------------------- */
6094 8284 : if ( nSampleFormat == SAMPLEFORMAT_IEEEFP )
6095 : {
6096 978 : if ( nBitsPerSample == 16 || nBitsPerSample == 24 )
6097 4 : bTreatAsOdd = TRUE;
6098 : }
6099 7306 : else if ( !bTreatAsRGBA && !bTreatAsBitmap
6100 : && nBitsPerSample != 8
6101 : && nBitsPerSample != 16
6102 : && nBitsPerSample != 32
6103 : && nBitsPerSample != 64
6104 : && nBitsPerSample != 128 )
6105 230 : bTreatAsOdd = TRUE;
6106 :
6107 8284 : int bMinIsWhite = nPhotometric == PHOTOMETRIC_MINISWHITE;
6108 :
6109 : /* -------------------------------------------------------------------- */
6110 : /* Capture the color table if there is one. */
6111 : /* -------------------------------------------------------------------- */
6112 : unsigned short *panRed, *panGreen, *panBlue;
6113 :
6114 8284 : if( bTreatAsRGBA
6115 : || TIFFGetField( hTIFF, TIFFTAG_COLORMAP,
6116 : &panRed, &panGreen, &panBlue) == 0 )
6117 : {
6118 : // Build inverted palette if we have inverted photometric.
6119 : // Pixel values remains unchanged. Avoid doing this for *deep*
6120 : // data types (per #1882)
6121 8142 : if( nBitsPerSample <= 16 && nPhotometric == PHOTOMETRIC_MINISWHITE )
6122 : {
6123 : GDALColorEntry oEntry;
6124 : int iColor, nColorCount;
6125 :
6126 14 : poColorTable = new GDALColorTable();
6127 14 : nColorCount = 1 << nBitsPerSample;
6128 :
6129 42 : for ( iColor = 0; iColor < nColorCount; iColor++ )
6130 : {
6131 : oEntry.c1 = oEntry.c2 = oEntry.c3 = (short)
6132 28 : ((255 * (nColorCount - 1 - iColor)) / (nColorCount-1));
6133 28 : oEntry.c4 = 255;
6134 28 : poColorTable->SetColorEntry( iColor, &oEntry );
6135 : }
6136 :
6137 14 : nPhotometric = PHOTOMETRIC_PALETTE;
6138 : }
6139 : else
6140 8114 : poColorTable = NULL;
6141 : }
6142 : else
6143 : {
6144 156 : int nColorCount, nMaxColor = 0;
6145 : GDALColorEntry oEntry;
6146 :
6147 156 : poColorTable = new GDALColorTable();
6148 :
6149 156 : nColorCount = 1 << nBitsPerSample;
6150 :
6151 687812 : for( int iColor = nColorCount - 1; iColor >= 0; iColor-- )
6152 : {
6153 687656 : oEntry.c1 = panRed[iColor] / 256;
6154 687656 : oEntry.c2 = panGreen[iColor] / 256;
6155 687656 : oEntry.c3 = panBlue[iColor] / 256;
6156 687656 : oEntry.c4 = 255;
6157 :
6158 687656 : poColorTable->SetColorEntry( iColor, &oEntry );
6159 :
6160 687656 : nMaxColor = MAX(nMaxColor,panRed[iColor]);
6161 687656 : nMaxColor = MAX(nMaxColor,panGreen[iColor]);
6162 687656 : nMaxColor = MAX(nMaxColor,panBlue[iColor]);
6163 : }
6164 :
6165 : // Bug 1384 - Some TIFF files are generated with color map entry
6166 : // values in range 0-255 instead of 0-65535 - try to handle these
6167 : // gracefully.
6168 156 : if( nMaxColor > 0 && nMaxColor < 256 )
6169 : {
6170 0 : CPLDebug( "GTiff", "TIFF ColorTable seems to be improperly scaled, fixing up." );
6171 :
6172 0 : for( int iColor = nColorCount - 1; iColor >= 0; iColor-- )
6173 : {
6174 0 : oEntry.c1 = panRed[iColor];
6175 0 : oEntry.c2 = panGreen[iColor];
6176 0 : oEntry.c3 = panBlue[iColor];
6177 0 : oEntry.c4 = 255;
6178 :
6179 0 : poColorTable->SetColorEntry( iColor, &oEntry );
6180 : }
6181 : }
6182 : }
6183 :
6184 : /* -------------------------------------------------------------------- */
6185 : /* Create band information objects. */
6186 : /* -------------------------------------------------------------------- */
6187 543452 : for( int iBand = 0; iBand < nBands; iBand++ )
6188 : {
6189 535168 : if( bTreatAsRGBA )
6190 40 : SetBand( iBand+1, new GTiffRGBABand( this, iBand+1 ) );
6191 535128 : else if( bTreatAsSplitBitmap )
6192 8 : SetBand( iBand+1, new GTiffSplitBitmapBand( this, iBand+1 ) );
6193 535120 : else if( bTreatAsSplit )
6194 54 : SetBand( iBand+1, new GTiffSplitBand( this, iBand+1 ) );
6195 535066 : else if( bTreatAsBitmap )
6196 248 : SetBand( iBand+1, new GTiffBitmapBand( this, iBand+1 ) );
6197 534818 : else if( bTreatAsOdd )
6198 462 : SetBand( iBand+1, new GTiffOddBitsBand( this, iBand+1 ) );
6199 : else
6200 534356 : SetBand( iBand+1, new GTiffRasterBand( this, iBand+1 ) );
6201 : }
6202 :
6203 8284 : if( GetRasterBand(1)->GetRasterDataType() == GDT_Unknown )
6204 : {
6205 : CPLError( CE_Failure, CPLE_NotSupported,
6206 0 : "Unsupported TIFF configuration." );
6207 0 : return CE_Failure;
6208 : }
6209 :
6210 : /* -------------------------------------------------------------------- */
6211 : /* Get the transform or gcps from the GeoTIFF file. */
6212 : /* -------------------------------------------------------------------- */
6213 8284 : if( bReadGeoTransform )
6214 : {
6215 7554 : char *pszTabWKT = NULL;
6216 : double *padfTiePoints, *padfScale, *padfMatrix;
6217 : uint16 nCount;
6218 7554 : bool bPixelIsPoint = false;
6219 : short nRasterType;
6220 : GTIF *psGTIF;
6221 7554 : int bPointGeoIgnore = FALSE;
6222 :
6223 7554 : psGTIF = GTIFNew( hTIFF ); // I wonder how expensive this is?
6224 :
6225 7554 : if( psGTIF )
6226 : {
6227 7552 : if( GTIFKeyGet(psGTIF, GTRasterTypeGeoKey, &nRasterType,
6228 : 0, 1 ) == 1
6229 : && nRasterType == (short) RasterPixelIsPoint )
6230 : {
6231 62 : bPixelIsPoint = true;
6232 : bPointGeoIgnore =
6233 : CSLTestBoolean( CPLGetConfigOption("GTIFF_POINT_GEO_IGNORE",
6234 62 : "FALSE") );
6235 : }
6236 :
6237 7552 : GTIFFree( psGTIF );
6238 : }
6239 :
6240 7554 : adfGeoTransform[0] = 0.0;
6241 7554 : adfGeoTransform[1] = 1.0;
6242 7554 : adfGeoTransform[2] = 0.0;
6243 7554 : adfGeoTransform[3] = 0.0;
6244 7554 : adfGeoTransform[4] = 0.0;
6245 7554 : adfGeoTransform[5] = 1.0;
6246 :
6247 18310 : if( TIFFGetField(hTIFF,TIFFTAG_GEOPIXELSCALE,&nCount,&padfScale )
6248 : && nCount >= 2
6249 10756 : && padfScale[0] != 0.0 && padfScale[1] != 0.0 )
6250 : {
6251 5378 : adfGeoTransform[1] = padfScale[0];
6252 5378 : adfGeoTransform[5] = - ABS(padfScale[1]);
6253 :
6254 5378 : if( TIFFGetField(hTIFF,TIFFTAG_GEOTIEPOINTS,&nCount,&padfTiePoints )
6255 : && nCount >= 6 )
6256 : {
6257 : adfGeoTransform[0] =
6258 5378 : padfTiePoints[3] - padfTiePoints[0] * adfGeoTransform[1];
6259 : adfGeoTransform[3] =
6260 5378 : padfTiePoints[4] - padfTiePoints[1] * adfGeoTransform[5];
6261 :
6262 5378 : if( bPixelIsPoint && !bPointGeoIgnore )
6263 : {
6264 30 : adfGeoTransform[0] -= (adfGeoTransform[1] * 0.5 + adfGeoTransform[2] * 0.5);
6265 30 : adfGeoTransform[3] -= (adfGeoTransform[4] * 0.5 + adfGeoTransform[5] * 0.5);
6266 : }
6267 :
6268 5378 : bGeoTransformValid = TRUE;
6269 : }
6270 : }
6271 :
6272 2176 : else if( TIFFGetField(hTIFF,TIFFTAG_GEOTRANSMATRIX,&nCount,&padfMatrix )
6273 : && nCount == 16 )
6274 : {
6275 28 : adfGeoTransform[0] = padfMatrix[3];
6276 28 : adfGeoTransform[1] = padfMatrix[0];
6277 28 : adfGeoTransform[2] = padfMatrix[1];
6278 28 : adfGeoTransform[3] = padfMatrix[7];
6279 28 : adfGeoTransform[4] = padfMatrix[4];
6280 28 : adfGeoTransform[5] = padfMatrix[5];
6281 :
6282 28 : if( bPixelIsPoint && !bPointGeoIgnore )
6283 : {
6284 8 : adfGeoTransform[0] -= (adfGeoTransform[1] * 0.5 + adfGeoTransform[2] * 0.5);
6285 8 : adfGeoTransform[3] -= (adfGeoTransform[4] * 0.5 + adfGeoTransform[5] * 0.5);
6286 : }
6287 :
6288 28 : bGeoTransformValid = TRUE;
6289 : }
6290 :
6291 : /* -------------------------------------------------------------------- */
6292 : /* Otherwise try looking for a .tfw, .tifw or .wld file. */
6293 : /* -------------------------------------------------------------------- */
6294 : else
6295 : {
6296 2148 : char* pszWldFilename = NULL;
6297 :
6298 : bGeoTransformValid =
6299 : GDALReadWorldFile2( osFilename, NULL, adfGeoTransform,
6300 2148 : papszSiblingFiles, &pszWldFilename);
6301 :
6302 2148 : if( !bGeoTransformValid )
6303 : {
6304 : bGeoTransformValid =
6305 : GDALReadWorldFile2( osFilename, "wld", adfGeoTransform,
6306 2138 : papszSiblingFiles, &pszWldFilename);
6307 : }
6308 :
6309 2148 : if( !bGeoTransformValid )
6310 : {
6311 : int bTabFileOK =
6312 : GDALReadTabFile2( osFilename, adfGeoTransform,
6313 : &pszTabWKT, &nGCPCount, &pasGCPList,
6314 2128 : papszSiblingFiles, &pszWldFilename );
6315 :
6316 2128 : if( bTabFileOK && nGCPCount == 0 )
6317 4 : bGeoTransformValid = TRUE;
6318 : }
6319 :
6320 2148 : if (pszWldFilename)
6321 : {
6322 24 : osWldFilename = pszWldFilename;
6323 24 : CPLFree(pszWldFilename);
6324 : }
6325 : }
6326 :
6327 : /* -------------------------------------------------------------------- */
6328 : /* Check for GCPs. Note, we will allow there to be GCPs and a */
6329 : /* transform in some circumstances. */
6330 : /* -------------------------------------------------------------------- */
6331 7554 : if( TIFFGetField(hTIFF,TIFFTAG_GEOTIEPOINTS,&nCount,&padfTiePoints )
6332 : && !bGeoTransformValid )
6333 : {
6334 50 : nGCPCount = nCount / 6;
6335 50 : pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),nGCPCount);
6336 :
6337 258 : for( int iGCP = 0; iGCP < nGCPCount; iGCP++ )
6338 : {
6339 : char szID[32];
6340 :
6341 208 : sprintf( szID, "%d", iGCP+1 );
6342 208 : pasGCPList[iGCP].pszId = CPLStrdup( szID );
6343 208 : pasGCPList[iGCP].pszInfo = CPLStrdup("");
6344 208 : pasGCPList[iGCP].dfGCPPixel = padfTiePoints[iGCP*6+0];
6345 208 : pasGCPList[iGCP].dfGCPLine = padfTiePoints[iGCP*6+1];
6346 208 : pasGCPList[iGCP].dfGCPX = padfTiePoints[iGCP*6+3];
6347 208 : pasGCPList[iGCP].dfGCPY = padfTiePoints[iGCP*6+4];
6348 208 : pasGCPList[iGCP].dfGCPZ = padfTiePoints[iGCP*6+5];
6349 :
6350 208 : if( bPixelIsPoint && !bPointGeoIgnore )
6351 : {
6352 0 : pasGCPList[iGCP].dfGCPPixel -= 0.5;
6353 0 : pasGCPList[iGCP].dfGCPLine -= 0.5;
6354 : }
6355 : }
6356 : }
6357 :
6358 : /* -------------------------------------------------------------------- */
6359 : /* Did we find a tab file? If so we will use it's coordinate */
6360 : /* system and give it precidence. */
6361 : /* -------------------------------------------------------------------- */
6362 7558 : if( pszTabWKT != NULL
6363 4 : && (pszProjection == NULL || pszProjection[0] == '\0') )
6364 : {
6365 4 : CPLFree( pszProjection );
6366 4 : pszProjection = pszTabWKT;
6367 4 : pszTabWKT = NULL;
6368 4 : bLookedForProjection = TRUE;
6369 : }
6370 :
6371 7554 : CPLFree( pszTabWKT );
6372 7554 : bGeoTIFFInfoChanged = FALSE;
6373 : }
6374 :
6375 : /* -------------------------------------------------------------------- */
6376 : /* Capture some other potentially interesting information. */
6377 : /* -------------------------------------------------------------------- */
6378 : char *pszText, szWorkMDI[200];
6379 : float fResolution;
6380 : uint16 nShort;
6381 :
6382 8284 : if( TIFFGetField( hTIFF, TIFFTAG_DOCUMENTNAME, &pszText ) )
6383 42 : SetMetadataItem( "TIFFTAG_DOCUMENTNAME", pszText );
6384 :
6385 8284 : if( TIFFGetField( hTIFF, TIFFTAG_IMAGEDESCRIPTION, &pszText ) )
6386 12 : SetMetadataItem( "TIFFTAG_IMAGEDESCRIPTION", pszText );
6387 :
6388 8284 : if( TIFFGetField( hTIFF, TIFFTAG_SOFTWARE, &pszText ) )
6389 20 : SetMetadataItem( "TIFFTAG_SOFTWARE", pszText );
6390 :
6391 8284 : if( TIFFGetField( hTIFF, TIFFTAG_DATETIME, &pszText ) )
6392 10 : SetMetadataItem( "TIFFTAG_DATETIME", pszText );
6393 :
6394 8284 : if( TIFFGetField( hTIFF, TIFFTAG_ARTIST, &pszText ) )
6395 4 : SetMetadataItem( "TIFFTAG_ARTIST", pszText );
6396 :
6397 8284 : if( TIFFGetField( hTIFF, TIFFTAG_HOSTCOMPUTER, &pszText ) )
6398 4 : SetMetadataItem( "TIFFTAG_HOSTCOMPUTER", pszText );
6399 :
6400 8284 : if( TIFFGetField( hTIFF, TIFFTAG_COPYRIGHT, &pszText ) )
6401 4 : SetMetadataItem( "TIFFTAG_COPYRIGHT", pszText );
6402 :
6403 8284 : if( TIFFGetField( hTIFF, TIFFTAG_XRESOLUTION, &fResolution ) )
6404 : {
6405 82 : sprintf( szWorkMDI, "%.8g", fResolution );
6406 82 : SetMetadataItem( "TIFFTAG_XRESOLUTION", szWorkMDI );
6407 : }
6408 :
6409 8284 : if( TIFFGetField( hTIFF, TIFFTAG_YRESOLUTION, &fResolution ) )
6410 : {
6411 82 : sprintf( szWorkMDI, "%.8g", fResolution );
6412 82 : SetMetadataItem( "TIFFTAG_YRESOLUTION", szWorkMDI );
6413 : }
6414 :
6415 8284 : if( TIFFGetField( hTIFF, TIFFTAG_MINSAMPLEVALUE, &nShort ) )
6416 : {
6417 0 : sprintf( szWorkMDI, "%d", nShort );
6418 0 : SetMetadataItem( "TIFFTAG_MINSAMPLEVALUE", szWorkMDI );
6419 : }
6420 :
6421 8284 : if( TIFFGetField( hTIFF, TIFFTAG_MAXSAMPLEVALUE, &nShort ) )
6422 : {
6423 0 : sprintf( szWorkMDI, "%d", nShort );
6424 0 : SetMetadataItem( "TIFFTAG_MAXSAMPLEVALUE", szWorkMDI );
6425 : }
6426 :
6427 8284 : if( TIFFGetField( hTIFF, TIFFTAG_RESOLUTIONUNIT, &nShort ) )
6428 : {
6429 82 : if( nShort == RESUNIT_NONE )
6430 26 : sprintf( szWorkMDI, "%d (unitless)", nShort );
6431 56 : else if( nShort == RESUNIT_INCH )
6432 56 : sprintf( szWorkMDI, "%d (pixels/inch)", nShort );
6433 0 : else if( nShort == RESUNIT_CENTIMETER )
6434 0 : sprintf( szWorkMDI, "%d (pixels/cm)", nShort );
6435 : else
6436 0 : sprintf( szWorkMDI, "%d", nShort );
6437 82 : SetMetadataItem( "TIFFTAG_RESOLUTIONUNIT", szWorkMDI );
6438 : }
6439 :
6440 : int nTagSize;
6441 : void* pData;
6442 8284 : if( TIFFGetField( hTIFF, TIFFTAG_XMLPACKET, &nTagSize, &pData ) )
6443 : {
6444 4 : char* pszXMP = (char*)VSIMalloc(nTagSize + 1);
6445 4 : if (pszXMP)
6446 : {
6447 4 : memcpy(pszXMP, pData, nTagSize);
6448 4 : pszXMP[nTagSize] = '\0';
6449 :
6450 : char *apszMDList[2];
6451 4 : apszMDList[0] = pszXMP;
6452 4 : apszMDList[1] = NULL;
6453 4 : SetMetadata(apszMDList, "xml:XMP");
6454 :
6455 4 : CPLFree(pszXMP);
6456 : }
6457 : }
6458 :
6459 8284 : if( nCompression == COMPRESSION_NONE )
6460 : /* no compression tag */;
6461 842 : else if( nCompression == COMPRESSION_CCITTRLE )
6462 0 : SetMetadataItem( "COMPRESSION", "CCITTRLE", "IMAGE_STRUCTURE" );
6463 842 : else if( nCompression == COMPRESSION_CCITTFAX3 )
6464 0 : SetMetadataItem( "COMPRESSION", "CCITTFAX3", "IMAGE_STRUCTURE" );
6465 842 : else if( nCompression == COMPRESSION_CCITTFAX4 )
6466 18 : SetMetadataItem( "COMPRESSION", "CCITTFAX4", "IMAGE_STRUCTURE" );
6467 824 : else if( nCompression == COMPRESSION_LZW )
6468 78 : SetMetadataItem( "COMPRESSION", "LZW", "IMAGE_STRUCTURE" );
6469 746 : else if( nCompression == COMPRESSION_OJPEG )
6470 2 : SetMetadataItem( "COMPRESSION", "OJPEG", "IMAGE_STRUCTURE" );
6471 744 : else if( nCompression == COMPRESSION_JPEG )
6472 : {
6473 298 : if ( nPhotometric == PHOTOMETRIC_YCBCR )
6474 236 : SetMetadataItem( "COMPRESSION", "YCbCr JPEG", "IMAGE_STRUCTURE" );
6475 : else
6476 62 : SetMetadataItem( "COMPRESSION", "JPEG", "IMAGE_STRUCTURE" );
6477 : }
6478 446 : else if( nCompression == COMPRESSION_NEXT )
6479 0 : SetMetadataItem( "COMPRESSION", "NEXT", "IMAGE_STRUCTURE" );
6480 446 : else if( nCompression == COMPRESSION_CCITTRLEW )
6481 0 : SetMetadataItem( "COMPRESSION", "CCITTRLEW", "IMAGE_STRUCTURE" );
6482 446 : else if( nCompression == COMPRESSION_PACKBITS )
6483 20 : SetMetadataItem( "COMPRESSION", "PACKBITS", "IMAGE_STRUCTURE" );
6484 426 : else if( nCompression == COMPRESSION_THUNDERSCAN )
6485 0 : SetMetadataItem( "COMPRESSION", "THUNDERSCAN", "IMAGE_STRUCTURE" );
6486 426 : else if( nCompression == COMPRESSION_PIXARFILM )
6487 0 : SetMetadataItem( "COMPRESSION", "PIXARFILM", "IMAGE_STRUCTURE" );
6488 426 : else if( nCompression == COMPRESSION_PIXARLOG )
6489 0 : SetMetadataItem( "COMPRESSION", "PIXARLOG", "IMAGE_STRUCTURE" );
6490 426 : else if( nCompression == COMPRESSION_DEFLATE )
6491 140 : SetMetadataItem( "COMPRESSION", "DEFLATE", "IMAGE_STRUCTURE" );
6492 286 : else if( nCompression == COMPRESSION_ADOBE_DEFLATE )
6493 286 : SetMetadataItem( "COMPRESSION", "DEFLATE", "IMAGE_STRUCTURE" );
6494 0 : else if( nCompression == COMPRESSION_DCS )
6495 0 : SetMetadataItem( "COMPRESSION", "DCS", "IMAGE_STRUCTURE" );
6496 0 : else if( nCompression == COMPRESSION_JBIG )
6497 0 : SetMetadataItem( "COMPRESSION", "JBIG", "IMAGE_STRUCTURE" );
6498 0 : else if( nCompression == COMPRESSION_SGILOG )
6499 0 : SetMetadataItem( "COMPRESSION", "SGILOG", "IMAGE_STRUCTURE" );
6500 0 : else if( nCompression == COMPRESSION_SGILOG24 )
6501 0 : SetMetadataItem( "COMPRESSION", "SGILOG24", "IMAGE_STRUCTURE" );
6502 0 : else if( nCompression == COMPRESSION_JP2000 )
6503 0 : SetMetadataItem( "COMPRESSION", "JP2000", "IMAGE_STRUCTURE" );
6504 0 : else if( nCompression == COMPRESSION_LZMA )
6505 0 : SetMetadataItem( "COMPRESSION", "LZMA", "IMAGE_STRUCTURE" );
6506 :
6507 : else
6508 : {
6509 0 : CPLString oComp;
6510 : SetMetadataItem( "COMPRESSION",
6511 0 : (const char *) oComp.Printf( "%d", nCompression));
6512 : }
6513 :
6514 9258 : if( nPlanarConfig == PLANARCONFIG_CONTIG && nBands != 1 )
6515 974 : SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" );
6516 : else
6517 7310 : SetMetadataItem( "INTERLEAVE", "BAND", "IMAGE_STRUCTURE" );
6518 :
6519 8284 : if( (GetRasterBand(1)->GetRasterDataType() == GDT_Byte && nBitsPerSample != 8 ) ||
6520 : (GetRasterBand(1)->GetRasterDataType() == GDT_UInt16 && nBitsPerSample != 16) ||
6521 : (GetRasterBand(1)->GetRasterDataType() == GDT_UInt32 && nBitsPerSample != 32) )
6522 : {
6523 2400 : for (int i = 0; i < nBands; ++i)
6524 : GetRasterBand(i+1)->SetMetadataItem( "NBITS",
6525 : CPLString().Printf( "%d", (int)nBitsPerSample ),
6526 714 : "IMAGE_STRUCTURE" );
6527 : }
6528 :
6529 8284 : if( bMinIsWhite )
6530 16 : SetMetadataItem( "MINISWHITE", "YES", "IMAGE_STRUCTURE" );
6531 :
6532 8284 : if( TIFFGetField( hTIFF, TIFFTAG_GDAL_METADATA, &pszText ) )
6533 : {
6534 398 : CPLXMLNode *psRoot = CPLParseXMLString( pszText );
6535 398 : CPLXMLNode *psItem = NULL;
6536 :
6537 398 : if( psRoot != NULL && psRoot->eType == CXT_Element
6538 : && EQUAL(psRoot->pszValue,"GDALMetadata") )
6539 398 : psItem = psRoot->psChild;
6540 :
6541 2084 : for( ; psItem != NULL; psItem = psItem->psNext )
6542 : {
6543 : const char *pszKey, *pszValue, *pszRole, *pszDomain;
6544 : char *pszUnescapedValue;
6545 1686 : int nBand, bIsXML = FALSE;
6546 :
6547 1686 : if( psItem->eType != CXT_Element
6548 : || !EQUAL(psItem->pszValue,"Item") )
6549 0 : continue;
6550 :
6551 1686 : pszKey = CPLGetXMLValue( psItem, "name", NULL );
6552 1686 : pszValue = CPLGetXMLValue( psItem, NULL, NULL );
6553 1686 : nBand = atoi(CPLGetXMLValue( psItem, "sample", "-1" )) + 1;
6554 1686 : pszRole = CPLGetXMLValue( psItem, "role", "" );
6555 1686 : pszDomain = CPLGetXMLValue( psItem, "domain", "" );
6556 :
6557 1686 : if( pszKey == NULL || pszValue == NULL )
6558 74 : continue;
6559 :
6560 1612 : if( EQUALN(pszDomain,"xml:",4) )
6561 4 : bIsXML = TRUE;
6562 :
6563 : pszUnescapedValue = CPLUnescapeString( pszValue, NULL,
6564 1612 : CPLES_XML );
6565 1612 : if( nBand == 0 )
6566 : {
6567 1264 : if( bIsXML )
6568 : {
6569 4 : char *apszMD[2] = { pszUnescapedValue, NULL };
6570 4 : SetMetadata( apszMD, pszDomain );
6571 : }
6572 : else
6573 1260 : SetMetadataItem( pszKey, pszUnescapedValue, pszDomain );
6574 : }
6575 : else
6576 : {
6577 348 : GDALRasterBand *poBand = GetRasterBand(nBand);
6578 348 : if( poBand != NULL )
6579 : {
6580 348 : if( EQUAL(pszRole,"scale") )
6581 12 : poBand->SetScale( CPLAtofM(pszUnescapedValue) );
6582 336 : else if( EQUAL(pszRole,"offset") )
6583 12 : poBand->SetOffset( CPLAtofM(pszUnescapedValue) );
6584 324 : else if( EQUAL(pszRole,"unittype") )
6585 26 : poBand->SetUnitType( pszUnescapedValue );
6586 : else
6587 : {
6588 298 : if( bIsXML )
6589 : {
6590 0 : char *apszMD[2] = { pszUnescapedValue, NULL };
6591 0 : poBand->SetMetadata( apszMD, pszDomain );
6592 : }
6593 : else
6594 : poBand->SetMetadataItem(pszKey,pszUnescapedValue,
6595 298 : pszDomain );
6596 : }
6597 : }
6598 : }
6599 1612 : CPLFree( pszUnescapedValue );
6600 : }
6601 :
6602 398 : CPLDestroyXMLNode( psRoot );
6603 : }
6604 :
6605 8284 : bMetadataChanged = FALSE;
6606 :
6607 : /* -------------------------------------------------------------------- */
6608 : /* Check for NODATA */
6609 : /* -------------------------------------------------------------------- */
6610 8284 : if( TIFFGetField( hTIFF, TIFFTAG_GDAL_NODATA, &pszText ) )
6611 : {
6612 330 : bNoDataSet = TRUE;
6613 330 : dfNoDataValue = CPLAtofM( pszText );
6614 : }
6615 :
6616 : /* -------------------------------------------------------------------- */
6617 : /* If this is a "base" raster, we should scan for any */
6618 : /* associated overviews, internal mask bands and subdatasets. */
6619 : /* -------------------------------------------------------------------- */
6620 8284 : if( bBase )
6621 : {
6622 : //ScanDirectories();
6623 : }
6624 :
6625 8284 : return( CE_None );
6626 : }
6627 :
6628 : /************************************************************************/
6629 : /* ScanDirectories() */
6630 : /* */
6631 : /* Scan through all the directories finding overviews, masks */
6632 : /* and subdatasets. */
6633 : /************************************************************************/
6634 :
6635 616266 : void GTiffDataset::ScanDirectories()
6636 :
6637 : {
6638 : /* -------------------------------------------------------------------- */
6639 : /* We only scan once. We do not scan for non-base datasets. */
6640 : /* -------------------------------------------------------------------- */
6641 616266 : if( !bScanDeferred )
6642 613666 : return;
6643 :
6644 2600 : bScanDeferred = FALSE;
6645 :
6646 2600 : if( !bBase )
6647 114 : return;
6648 :
6649 2486 : if( TIFFLastDirectory( hTIFF ) )
6650 2220 : return;
6651 :
6652 266 : CPLDebug( "GTiff", "ScanDirectories()" );
6653 :
6654 : /* ==================================================================== */
6655 : /* Scan all directories. */
6656 : /* ==================================================================== */
6657 266 : char **papszSubdatasets = NULL;
6658 266 : int iDirIndex = 0;
6659 :
6660 266 : FlushDirectory();
6661 1210 : while( !TIFFLastDirectory( hTIFF )
6662 : && (iDirIndex == 0 || TIFFReadDirectory( hTIFF ) != 0) )
6663 : {
6664 678 : toff_t nThisDir = TIFFCurrentDirOffset(hTIFF);
6665 678 : uint32 nSubType = 0;
6666 :
6667 678 : *ppoActiveDSRef = NULL; // our directory no longer matches this ds
6668 :
6669 678 : iDirIndex++;
6670 :
6671 678 : if( !TIFFGetField(hTIFF, TIFFTAG_SUBFILETYPE, &nSubType) )
6672 146 : nSubType = 0;
6673 :
6674 : /* Embedded overview of the main image */
6675 946 : if ((nSubType & FILETYPE_REDUCEDIMAGE) != 0 &&
6676 : (nSubType & FILETYPE_MASK) == 0 &&
6677 : iDirIndex != 1 )
6678 : {
6679 : GTiffDataset *poODS;
6680 :
6681 268 : poODS = new GTiffDataset();
6682 536 : if( poODS->OpenOffset( hTIFF, ppoActiveDSRef, nThisDir, FALSE,
6683 : eAccess ) != CE_None
6684 : || poODS->GetRasterCount() != GetRasterCount() )
6685 : {
6686 0 : delete poODS;
6687 : }
6688 : else
6689 : {
6690 : CPLDebug( "GTiff", "Opened %dx%d overview.\n",
6691 268 : poODS->GetRasterXSize(), poODS->GetRasterYSize());
6692 268 : nOverviewCount++;
6693 : papoOverviewDS = (GTiffDataset **)
6694 : CPLRealloc(papoOverviewDS,
6695 268 : nOverviewCount * (sizeof(void*)));
6696 268 : papoOverviewDS[nOverviewCount-1] = poODS;
6697 268 : poODS->poBaseDS = this;
6698 : }
6699 : }
6700 :
6701 : /* Embedded mask of the main image */
6702 488 : else if ((nSubType & FILETYPE_MASK) != 0 &&
6703 : (nSubType & FILETYPE_REDUCEDIMAGE) == 0 &&
6704 : poMaskDS == NULL )
6705 : {
6706 78 : poMaskDS = new GTiffDataset();
6707 :
6708 : /* The TIFF6 specification - page 37 - only allows 1 SamplesPerPixel and 1 BitsPerSample
6709 : Here we support either 1 or 8 bit per sample
6710 : and we support either 1 sample per pixel or as many samples as in the main image
6711 : We don't check the value of the PhotometricInterpretation tag, which should be
6712 : set to "Transparency mask" (4) according to the specification (page 36)
6713 : ... But the TIFF6 specification allows image masks to have a higher resolution than
6714 : the main image, what we don't support here
6715 : */
6716 :
6717 156 : if( poMaskDS->OpenOffset( hTIFF, ppoActiveDSRef, nThisDir,
6718 : FALSE, eAccess ) != CE_None
6719 : || poMaskDS->GetRasterCount() == 0
6720 : || !(poMaskDS->GetRasterCount() == 1 || poMaskDS->GetRasterCount() == GetRasterCount())
6721 : || poMaskDS->GetRasterXSize() != GetRasterXSize()
6722 : || poMaskDS->GetRasterYSize() != GetRasterYSize()
6723 : || poMaskDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte)
6724 : {
6725 0 : delete poMaskDS;
6726 0 : poMaskDS = NULL;
6727 : }
6728 : else
6729 : {
6730 78 : CPLDebug( "GTiff", "Opened band mask.\n");
6731 78 : poMaskDS->poBaseDS = this;
6732 :
6733 78 : poMaskDS->bPromoteTo8Bits = CSLTestBoolean(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK_TO_8BIT", "YES"));
6734 : }
6735 : }
6736 :
6737 : /* Embedded mask of an overview */
6738 : /* The TIFF6 specification allows the combination of the FILETYPE_xxxx masks */
6739 396 : else if ((nSubType & FILETYPE_REDUCEDIMAGE) != 0 &&
6740 : (nSubType & FILETYPE_MASK) != 0)
6741 : {
6742 64 : GTiffDataset* poDS = new GTiffDataset();
6743 128 : if( poDS->OpenOffset( hTIFF, ppoActiveDSRef, nThisDir, FALSE,
6744 : eAccess ) != CE_None
6745 : || poDS->GetRasterCount() == 0
6746 : || poDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte)
6747 : {
6748 0 : delete poDS;
6749 : }
6750 : else
6751 : {
6752 : int i;
6753 94 : for(i=0;i<nOverviewCount;i++)
6754 : {
6755 222 : if (((GTiffDataset*)papoOverviewDS[i])->poMaskDS == NULL &&
6756 64 : poDS->GetRasterXSize() == papoOverviewDS[i]->GetRasterXSize() &&
6757 64 : poDS->GetRasterYSize() == papoOverviewDS[i]->GetRasterYSize() &&
6758 : (poDS->GetRasterCount() == 1 || poDS->GetRasterCount() == GetRasterCount()))
6759 : {
6760 : CPLDebug( "GTiff", "Opened band mask for %dx%d overview.\n",
6761 64 : poDS->GetRasterXSize(), poDS->GetRasterYSize());
6762 64 : ((GTiffDataset*)papoOverviewDS[i])->poMaskDS = poDS;
6763 64 : poDS->bPromoteTo8Bits = CSLTestBoolean(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK_TO_8BIT", "YES"));
6764 64 : poDS->poBaseDS = this;
6765 64 : break;
6766 : }
6767 : }
6768 64 : if (i == nOverviewCount)
6769 : {
6770 0 : delete poDS;
6771 : }
6772 : }
6773 : }
6774 268 : else if( nSubType == 0 || nSubType == FILETYPE_PAGE ) {
6775 146 : CPLString osName, osDesc;
6776 : uint32 nXSize, nYSize;
6777 : uint16 nSPP;
6778 :
6779 146 : TIFFGetField( hTIFF, TIFFTAG_IMAGEWIDTH, &nXSize );
6780 146 : TIFFGetField( hTIFF, TIFFTAG_IMAGELENGTH, &nYSize );
6781 146 : if( !TIFFGetField(hTIFF, TIFFTAG_SAMPLESPERPIXEL, &nSPP ) )
6782 0 : nSPP = 1;
6783 :
6784 : osName.Printf( "SUBDATASET_%d_NAME=GTIFF_DIR:%d:%s",
6785 146 : iDirIndex, iDirIndex, osFilename.c_str() );
6786 : osDesc.Printf( "SUBDATASET_%d_DESC=Page %d (%dP x %dL x %dB)",
6787 : iDirIndex, iDirIndex,
6788 146 : (int)nXSize, (int)nYSize, nSPP );
6789 :
6790 : papszSubdatasets =
6791 146 : CSLAddString( papszSubdatasets, osName );
6792 : papszSubdatasets =
6793 146 : CSLAddString( papszSubdatasets, osDesc );
6794 : }
6795 :
6796 : // Make sure we are stepping from the expected directory regardless
6797 : // of churn done processing the above.
6798 678 : if( TIFFCurrentDirOffset(hTIFF) != nThisDir )
6799 0 : TIFFSetSubDirectory( hTIFF, nThisDir );
6800 678 : *ppoActiveDSRef = NULL;
6801 : }
6802 :
6803 : /* If we have a mask for the main image, loop over the overviews, and if they */
6804 : /* have a mask, let's set this mask as an overview of the main mask... */
6805 266 : if (poMaskDS != NULL)
6806 : {
6807 : int i;
6808 142 : for(i=0;i<nOverviewCount;i++)
6809 : {
6810 64 : if (((GTiffDataset*)papoOverviewDS[i])->poMaskDS != NULL)
6811 : {
6812 64 : poMaskDS->nOverviewCount++;
6813 : poMaskDS->papoOverviewDS = (GTiffDataset **)
6814 : CPLRealloc(poMaskDS->papoOverviewDS,
6815 64 : poMaskDS->nOverviewCount * (sizeof(void*)));
6816 64 : poMaskDS->papoOverviewDS[poMaskDS->nOverviewCount-1] =
6817 64 : ((GTiffDataset*)papoOverviewDS[i])->poMaskDS;
6818 : }
6819 : }
6820 : }
6821 :
6822 : /* -------------------------------------------------------------------- */
6823 : /* Only keep track of subdatasets if we have more than one */
6824 : /* subdataset (pair). */
6825 : /* -------------------------------------------------------------------- */
6826 266 : if( CSLCount(papszSubdatasets) > 2 )
6827 : {
6828 2 : oGTiffMDMD.SetMetadata( papszSubdatasets, "SUBDATASETS" );
6829 : }
6830 266 : CSLDestroy( papszSubdatasets );
6831 :
6832 : }
6833 :
6834 :
6835 4638 : static int GTiffGetLZMAPreset(char** papszOptions)
6836 : {
6837 4638 : int nLZMAPreset = -1;
6838 4638 : const char* pszValue = CSLFetchNameValue( papszOptions, "LZMA_PRESET" );
6839 4638 : if( pszValue != NULL )
6840 : {
6841 0 : nLZMAPreset = atoi( pszValue );
6842 0 : if (!(nLZMAPreset >= 0 && nLZMAPreset <= 9))
6843 : {
6844 : CPLError( CE_Warning, CPLE_IllegalArg,
6845 : "LZMA_PRESET=%s value not recognised, ignoring.",
6846 0 : pszValue );
6847 0 : nLZMAPreset = -1;
6848 : }
6849 : }
6850 4638 : return nLZMAPreset;
6851 : }
6852 :
6853 :
6854 4638 : static int GTiffGetZLevel(char** papszOptions)
6855 : {
6856 4638 : int nZLevel = -1;
6857 4638 : const char* pszValue = CSLFetchNameValue( papszOptions, "ZLEVEL" );
6858 4638 : if( pszValue != NULL )
6859 : {
6860 0 : nZLevel = atoi( pszValue );
6861 0 : if (!(nZLevel >= 1 && nZLevel <= 9))
6862 : {
6863 : CPLError( CE_Warning, CPLE_IllegalArg,
6864 : "ZLEVEL=%s value not recognised, ignoring.",
6865 0 : pszValue );
6866 0 : nZLevel = -1;
6867 : }
6868 : }
6869 4638 : return nZLevel;
6870 : }
6871 :
6872 4638 : static int GTiffGetJpegQuality(char** papszOptions)
6873 : {
6874 4638 : int nJpegQuality = -1;
6875 4638 : const char* pszValue = CSLFetchNameValue( papszOptions, "JPEG_QUALITY" );
6876 4638 : if( pszValue != NULL )
6877 : {
6878 56 : nJpegQuality = atoi( pszValue );
6879 56 : if (!(nJpegQuality >= 1 && nJpegQuality <= 100))
6880 : {
6881 : CPLError( CE_Warning, CPLE_IllegalArg,
6882 : "JPEG_QUALITY=%s value not recognised, ignoring.",
6883 0 : pszValue );
6884 0 : nJpegQuality = -1;
6885 : }
6886 : }
6887 4638 : return nJpegQuality;
6888 : }
6889 :
6890 : /************************************************************************/
6891 : /* GTiffCreate() */
6892 : /* */
6893 : /* Shared functionality between GTiffDataset::Create() and */
6894 : /* GTiffCreateCopy() for creating TIFF file based on a set of */
6895 : /* options and a configuration. */
6896 : /************************************************************************/
6897 :
6898 2324 : TIFF *GTiffDataset::CreateLL( const char * pszFilename,
6899 : int nXSize, int nYSize, int nBands,
6900 : GDALDataType eType,
6901 : double dfExtraSpaceForOverviews,
6902 : char **papszParmList )
6903 :
6904 : {
6905 : TIFF *hTIFF;
6906 2324 : int nBlockXSize = 0, nBlockYSize = 0;
6907 2324 : int bTiled = FALSE;
6908 2324 : int nCompression = COMPRESSION_NONE;
6909 2324 : int nPredictor = PREDICTOR_NONE, nJpegQuality = -1, nZLevel = -1,
6910 2324 : nLZMAPreset = -1;
6911 : uint16 nSampleFormat;
6912 : int nPlanar;
6913 : const char *pszValue;
6914 : const char *pszProfile;
6915 2324 : int bCreateBigTIFF = FALSE;
6916 :
6917 2324 : if (!GTiffOneTimeInit())
6918 0 : return NULL;
6919 :
6920 : /* -------------------------------------------------------------------- */
6921 : /* Blow on a few errors. */
6922 : /* -------------------------------------------------------------------- */
6923 2324 : if( nXSize < 1 || nYSize < 1 || nBands < 1 )
6924 : {
6925 : CPLError( CE_Failure, CPLE_AppDefined,
6926 : "Attempt to create %dx%dx%d TIFF file, but width, height and bands\n"
6927 : "must be positive.",
6928 2 : nXSize, nYSize, nBands );
6929 :
6930 2 : return NULL;
6931 : }
6932 :
6933 2322 : if (nBands > 65535)
6934 : {
6935 : CPLError( CE_Failure, CPLE_AppDefined,
6936 : "Attempt to create %dx%dx%d TIFF file, but bands\n"
6937 : "must be lesser or equal to 65535.",
6938 0 : nXSize, nYSize, nBands );
6939 :
6940 0 : return NULL;
6941 : }
6942 :
6943 : /* -------------------------------------------------------------------- */
6944 : /* Setup values based on options. */
6945 : /* -------------------------------------------------------------------- */
6946 2322 : pszProfile = CSLFetchNameValue(papszParmList,"PROFILE");
6947 2322 : if( pszProfile == NULL )
6948 2296 : pszProfile = "GDALGeoTIFF";
6949 :
6950 2322 : if( CSLFetchBoolean( papszParmList, "TILED", FALSE ) )
6951 54 : bTiled = TRUE;
6952 :
6953 2322 : pszValue = CSLFetchNameValue(papszParmList,"BLOCKXSIZE");
6954 2322 : if( pszValue != NULL )
6955 28 : nBlockXSize = atoi( pszValue );
6956 :
6957 2322 : pszValue = CSLFetchNameValue(papszParmList,"BLOCKYSIZE");
6958 2322 : if( pszValue != NULL )
6959 44 : nBlockYSize = atoi( pszValue );
6960 :
6961 2322 : pszValue = CSLFetchNameValue(papszParmList,"INTERLEAVE");
6962 2322 : if( pszValue != NULL )
6963 : {
6964 50 : if( EQUAL( pszValue, "PIXEL" ) )
6965 26 : nPlanar = PLANARCONFIG_CONTIG;
6966 24 : else if( EQUAL( pszValue, "BAND" ) )
6967 24 : nPlanar = PLANARCONFIG_SEPARATE;
6968 : else
6969 : {
6970 : CPLError( CE_Failure, CPLE_AppDefined,
6971 : "INTERLEAVE=%s unsupported, value must be PIXEL or BAND.",
6972 0 : pszValue );
6973 0 : return NULL;
6974 : }
6975 : }
6976 : else
6977 : {
6978 2272 : nPlanar = PLANARCONFIG_CONTIG;
6979 : }
6980 :
6981 2322 : pszValue = CSLFetchNameValue( papszParmList, "COMPRESS" );
6982 2322 : if( pszValue != NULL )
6983 : {
6984 124 : nCompression = GTIFFGetCompressionMethod(pszValue, "COMPRESS");
6985 124 : if (nCompression < 0)
6986 0 : return NULL;
6987 : }
6988 :
6989 2322 : pszValue = CSLFetchNameValue( papszParmList, "PREDICTOR" );
6990 2322 : if( pszValue != NULL )
6991 8 : nPredictor = atoi( pszValue );
6992 :
6993 2322 : nZLevel = GTiffGetZLevel(papszParmList);
6994 2322 : nLZMAPreset = GTiffGetLZMAPreset(papszParmList);
6995 2322 : nJpegQuality = GTiffGetJpegQuality(papszParmList);
6996 :
6997 : /* -------------------------------------------------------------------- */
6998 : /* Compute the uncompressed size. */
6999 : /* -------------------------------------------------------------------- */
7000 : double dfUncompressedImageSize;
7001 :
7002 : dfUncompressedImageSize =
7003 2322 : nXSize * ((double)nYSize) * nBands * (GDALGetDataTypeSize(eType)/8);
7004 2322 : dfUncompressedImageSize += dfExtraSpaceForOverviews;
7005 :
7006 2322 : if( nCompression == COMPRESSION_NONE
7007 : && dfUncompressedImageSize > 4200000000.0 )
7008 : {
7009 : #ifndef BIGTIFF_SUPPORT
7010 : CPLError( CE_Failure, CPLE_NotSupported,
7011 : "A %d pixels x %d lines x %d bands %s image would be larger than 4GB\n"
7012 : "but this is the largest size a TIFF can be, and BigTIFF is unavailable.\n"
7013 : "Creation failed.",
7014 : nXSize, nYSize, nBands, GDALGetDataTypeName(eType) );
7015 : return NULL;
7016 : #endif
7017 : }
7018 :
7019 : /* -------------------------------------------------------------------- */
7020 : /* Should the file be created as a bigtiff file? */
7021 : /* -------------------------------------------------------------------- */
7022 2322 : const char *pszBIGTIFF = CSLFetchNameValue(papszParmList, "BIGTIFF");
7023 :
7024 2322 : if( pszBIGTIFF == NULL )
7025 2308 : pszBIGTIFF = "IF_NEEDED";
7026 :
7027 2322 : if( EQUAL(pszBIGTIFF,"IF_NEEDED") )
7028 : {
7029 2310 : if( nCompression == COMPRESSION_NONE
7030 : && dfUncompressedImageSize > 4200000000.0 )
7031 20 : bCreateBigTIFF = TRUE;
7032 : }
7033 12 : else if( EQUAL(pszBIGTIFF,"IF_SAFER") )
7034 : {
7035 8 : if( dfUncompressedImageSize > 2000000000.0 )
7036 2 : bCreateBigTIFF = TRUE;
7037 : }
7038 :
7039 : else
7040 : {
7041 4 : bCreateBigTIFF = CSLTestBoolean( pszBIGTIFF );
7042 4 : if (!bCreateBigTIFF && nCompression == COMPRESSION_NONE &&
7043 : dfUncompressedImageSize > 4200000000.0 )
7044 : {
7045 : CPLError( CE_Failure, CPLE_NotSupported,
7046 : "The TIFF file will be larger than 4GB, so BigTIFF is necessary.\n"
7047 2 : "Creation failed.");
7048 2 : return NULL;
7049 : }
7050 : }
7051 :
7052 : #ifndef BIGTIFF_SUPPORT
7053 : if( bCreateBigTIFF )
7054 : {
7055 : CPLError( CE_Warning, CPLE_NotSupported,
7056 : "BigTIFF requested, but GDAL built without BigTIFF\n"
7057 : "enabled libtiff, request ignored." );
7058 : bCreateBigTIFF = FALSE;
7059 : }
7060 : #endif
7061 :
7062 2320 : if( bCreateBigTIFF )
7063 24 : CPLDebug( "GTiff", "File being created as a BigTIFF." );
7064 :
7065 : /* -------------------------------------------------------------------- */
7066 : /* Check if the user wishes a particular endianness */
7067 : /* -------------------------------------------------------------------- */
7068 :
7069 2320 : int eEndianness = ENDIANNESS_NATIVE;
7070 2320 : pszValue = CSLFetchNameValue(papszParmList, "ENDIANNESS");
7071 2320 : if ( pszValue == NULL )
7072 2308 : pszValue = CPLGetConfigOption( "GDAL_TIFF_ENDIANNESS", NULL );
7073 2320 : if ( pszValue != NULL )
7074 : {
7075 1544 : if (EQUAL(pszValue, "LITTLE"))
7076 12 : eEndianness = ENDIANNESS_LITTLE;
7077 1532 : else if (EQUAL(pszValue, "BIG"))
7078 0 : eEndianness = ENDIANNESS_BIG;
7079 1532 : else if (EQUAL(pszValue, "INVERTED"))
7080 : {
7081 : #ifdef CPL_LSB
7082 52 : eEndianness = ENDIANNESS_BIG;
7083 : #else
7084 : eEndianness = ENDIANNESS_LITTLE;
7085 : #endif
7086 : }
7087 1480 : else if (!EQUAL(pszValue, "NATIVE"))
7088 : {
7089 : CPLError( CE_Warning, CPLE_NotSupported,
7090 0 : "ENDIANNESS=%s not supported. Defaulting to NATIVE", pszValue );
7091 : }
7092 : }
7093 :
7094 : /* -------------------------------------------------------------------- */
7095 : /* Try opening the dataset. */
7096 : /* -------------------------------------------------------------------- */
7097 :
7098 : char szOpeningFlag[5];
7099 2320 : strcpy(szOpeningFlag, "w+");
7100 2320 : if (bCreateBigTIFF)
7101 24 : strcat(szOpeningFlag, "8");
7102 2320 : if (eEndianness == ENDIANNESS_BIG)
7103 52 : strcat(szOpeningFlag, "b");
7104 2268 : else if (eEndianness == ENDIANNESS_LITTLE)
7105 12 : strcat(szOpeningFlag, "l");
7106 2320 : hTIFF = VSI_TIFFOpen( pszFilename, szOpeningFlag );
7107 2320 : if( hTIFF == NULL )
7108 : {
7109 4 : if( CPLGetLastErrorNo() == 0 )
7110 : CPLError( CE_Failure, CPLE_OpenFailed,
7111 : "Attempt to create new tiff file `%s'\n"
7112 : "failed in XTIFFOpen().\n",
7113 0 : pszFilename );
7114 4 : return NULL;
7115 : }
7116 :
7117 : /* -------------------------------------------------------------------- */
7118 : /* How many bits per sample? We have a special case if NBITS */
7119 : /* specified for GDT_Byte, GDT_UInt16, GDT_UInt32. */
7120 : /* -------------------------------------------------------------------- */
7121 2316 : int nBitsPerSample = GDALGetDataTypeSize(eType);
7122 2316 : if (CSLFetchNameValue(papszParmList, "NBITS") != NULL)
7123 : {
7124 76 : int nMinBits = 0, nMaxBits = 0;
7125 76 : nBitsPerSample = atoi(CSLFetchNameValue(papszParmList, "NBITS"));
7126 76 : if( eType == GDT_Byte )
7127 : {
7128 26 : nMinBits = 1;
7129 26 : nMaxBits = 8;
7130 : }
7131 50 : else if( eType == GDT_UInt16 )
7132 : {
7133 26 : nMinBits = 9;
7134 26 : nMaxBits = 16;
7135 : }
7136 24 : else if( eType == GDT_UInt32 )
7137 : {
7138 24 : nMinBits = 17;
7139 24 : nMaxBits = 32;
7140 : }
7141 : else
7142 : {
7143 : CPLError(CE_Warning, CPLE_NotSupported,
7144 : "NBITS is not supported for data type %s",
7145 0 : GDALGetDataTypeName(eType));
7146 0 : nBitsPerSample = GDALGetDataTypeSize(eType);
7147 : }
7148 :
7149 76 : if (nMinBits != 0)
7150 : {
7151 76 : if (nBitsPerSample < nMinBits)
7152 : {
7153 : CPLError(CE_Warning, CPLE_AppDefined,
7154 : "NBITS=%d is invalid for data type %s. Using NBITS=%d",
7155 0 : nBitsPerSample, GDALGetDataTypeName(eType), nMinBits);
7156 0 : nBitsPerSample = nMinBits;
7157 : }
7158 76 : else if (nBitsPerSample > nMaxBits)
7159 : {
7160 : CPLError(CE_Warning, CPLE_AppDefined,
7161 : "NBITS=%d is invalid for data type %s. Using NBITS=%d",
7162 0 : nBitsPerSample, GDALGetDataTypeName(eType), nMaxBits);
7163 0 : nBitsPerSample = nMaxBits;
7164 : }
7165 : }
7166 : }
7167 :
7168 : /* -------------------------------------------------------------------- */
7169 : /* Do we have a custom pixel type (just used for signed byte now). */
7170 : /* -------------------------------------------------------------------- */
7171 2316 : const char *pszPixelType = CSLFetchNameValue( papszParmList, "PIXELTYPE" );
7172 2316 : if( pszPixelType == NULL )
7173 2312 : pszPixelType = "";
7174 :
7175 : /* -------------------------------------------------------------------- */
7176 : /* Setup some standard flags. */
7177 : /* -------------------------------------------------------------------- */
7178 2316 : TIFFSetField( hTIFF, TIFFTAG_IMAGEWIDTH, nXSize );
7179 2316 : TIFFSetField( hTIFF, TIFFTAG_IMAGELENGTH, nYSize );
7180 2316 : TIFFSetField( hTIFF, TIFFTAG_BITSPERSAMPLE, nBitsPerSample );
7181 :
7182 2562 : if( (eType == GDT_Byte && EQUAL(pszPixelType,"SIGNEDBYTE"))
7183 : || eType == GDT_Int16 || eType == GDT_Int32 )
7184 246 : nSampleFormat = SAMPLEFORMAT_INT;
7185 2274 : else if( eType == GDT_CInt16 || eType == GDT_CInt32 )
7186 204 : nSampleFormat = SAMPLEFORMAT_COMPLEXINT;
7187 2134 : else if( eType == GDT_Float32 || eType == GDT_Float64 )
7188 268 : nSampleFormat = SAMPLEFORMAT_IEEEFP;
7189 1814 : else if( eType == GDT_CFloat32 || eType == GDT_CFloat64 )
7190 216 : nSampleFormat = SAMPLEFORMAT_COMPLEXIEEEFP;
7191 : else
7192 1382 : nSampleFormat = SAMPLEFORMAT_UINT;
7193 :
7194 2316 : TIFFSetField( hTIFF, TIFFTAG_SAMPLEFORMAT, nSampleFormat );
7195 2316 : TIFFSetField( hTIFF, TIFFTAG_SAMPLESPERPIXEL, nBands );
7196 2316 : TIFFSetField( hTIFF, TIFFTAG_PLANARCONFIG, nPlanar );
7197 :
7198 : /* -------------------------------------------------------------------- */
7199 : /* Setup Photometric Interpretation. Take this value from the user */
7200 : /* passed option or guess correct value otherwise. */
7201 : /* -------------------------------------------------------------------- */
7202 2316 : int nSamplesAccountedFor = 1;
7203 2316 : int bForceColorTable = FALSE;
7204 :
7205 2316 : pszValue = CSLFetchNameValue(papszParmList,"PHOTOMETRIC");
7206 2316 : if( pszValue != NULL )
7207 : {
7208 62 : if( EQUAL( pszValue, "MINISBLACK" ) )
7209 0 : TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK );
7210 62 : else if( EQUAL( pszValue, "MINISWHITE" ) )
7211 4 : TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE );
7212 58 : else if( EQUAL( pszValue, "PALETTE" ))
7213 : {
7214 6 : TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE );
7215 6 : nSamplesAccountedFor = 1;
7216 6 : bForceColorTable = TRUE;
7217 : }
7218 52 : else if( EQUAL( pszValue, "RGB" ))
7219 : {
7220 4 : TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB );
7221 4 : nSamplesAccountedFor = 3;
7222 : }
7223 48 : else if( EQUAL( pszValue, "CMYK" ))
7224 : {
7225 4 : TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_SEPARATED );
7226 4 : nSamplesAccountedFor = 4;
7227 : }
7228 44 : else if( EQUAL( pszValue, "YCBCR" ))
7229 : {
7230 : /* Because of subsampling, setting YCBCR without JPEG compression leads */
7231 : /* to a crash currently. Would need to make GTiffRasterBand::IWriteBlock() */
7232 : /* aware of subsampling so that it doesn't overrun buffer size returned */
7233 : /* by libtiff */
7234 44 : if ( nCompression != COMPRESSION_JPEG )
7235 : {
7236 : CPLError(CE_Failure, CPLE_NotSupported,
7237 0 : "Currently, PHOTOMETRIC=YCBCR requires COMPRESS=JPEG");
7238 0 : XTIFFClose(hTIFF);
7239 0 : return NULL;
7240 : }
7241 :
7242 44 : if ( nPlanar == PLANARCONFIG_SEPARATE )
7243 : {
7244 : CPLError(CE_Failure, CPLE_NotSupported,
7245 0 : "PHOTOMETRIC=YCBCR requires INTERLEAVE=PIXEL");
7246 0 : XTIFFClose(hTIFF);
7247 0 : return NULL;
7248 : }
7249 :
7250 : /* YCBCR strictly requires 3 bands. Not less, not more */
7251 : /* Issue an explicit error message as libtiff one is a bit cryptic : */
7252 : /* TIFFVStripSize64:Invalid td_samplesperpixel value */
7253 44 : if ( nBands != 3 )
7254 : {
7255 : CPLError(CE_Failure, CPLE_NotSupported,
7256 0 : "PHOTOMETRIC=YCBCR requires a source raster with only 3 bands (RGB)");
7257 0 : XTIFFClose(hTIFF);
7258 0 : return NULL;
7259 : }
7260 :
7261 44 : TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_YCBCR );
7262 44 : nSamplesAccountedFor = 3;
7263 : }
7264 0 : else if( EQUAL( pszValue, "CIELAB" ))
7265 : {
7266 0 : TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_CIELAB );
7267 0 : nSamplesAccountedFor = 3;
7268 : }
7269 0 : else if( EQUAL( pszValue, "ICCLAB" ))
7270 : {
7271 0 : TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_ICCLAB );
7272 0 : nSamplesAccountedFor = 3;
7273 : }
7274 0 : else if( EQUAL( pszValue, "ITULAB" ))
7275 : {
7276 0 : TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_ITULAB );
7277 0 : nSamplesAccountedFor = 3;
7278 : }
7279 : else
7280 : {
7281 : CPLError( CE_Warning, CPLE_IllegalArg,
7282 : "PHOTOMETRIC=%s value not recognised, ignoring.\n"
7283 : "Set the Photometric Interpretation as MINISBLACK.",
7284 0 : pszValue );
7285 0 : TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK );
7286 : }
7287 :
7288 62 : if ( nBands < nSamplesAccountedFor )
7289 : {
7290 : CPLError( CE_Warning, CPLE_IllegalArg,
7291 : "PHOTOMETRIC=%s value does not correspond to number "
7292 : "of bands (%d), ignoring.\n"
7293 : "Set the Photometric Interpretation as MINISBLACK.",
7294 0 : pszValue, nBands );
7295 0 : TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK );
7296 : }
7297 : }
7298 : else
7299 : {
7300 : /*
7301 : * If image contains 3 or 4 bands and datatype is Byte then we will
7302 : * assume it is RGB. In all other cases assume it is MINISBLACK.
7303 : */
7304 2360 : if( nBands == 3 && eType == GDT_Byte )
7305 : {
7306 106 : TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB );
7307 106 : nSamplesAccountedFor = 3;
7308 : }
7309 2202 : else if( nBands == 4 && eType == GDT_Byte )
7310 : {
7311 : uint16 v[1];
7312 :
7313 54 : v[0] = EXTRASAMPLE_ASSOCALPHA;
7314 54 : TIFFSetField(hTIFF, TIFFTAG_EXTRASAMPLES, 1, v);
7315 54 : TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB );
7316 54 : nSamplesAccountedFor = 4;
7317 : }
7318 : else
7319 : {
7320 2094 : TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK );
7321 2094 : nSamplesAccountedFor = 1;
7322 : }
7323 : }
7324 :
7325 : /* -------------------------------------------------------------------- */
7326 : /* If there are extra samples, we need to mark them with an */
7327 : /* appropriate extrasamples definition here. */
7328 : /* -------------------------------------------------------------------- */
7329 2316 : if( nBands > nSamplesAccountedFor )
7330 : {
7331 : uint16 *v;
7332 : int i;
7333 128 : int nExtraSamples = nBands - nSamplesAccountedFor;
7334 :
7335 128 : v = (uint16 *) CPLMalloc( sizeof(uint16) * nExtraSamples );
7336 :
7337 128 : if( CSLFetchBoolean(papszParmList,"ALPHA",FALSE) )
7338 2 : v[0] = EXTRASAMPLE_ASSOCALPHA;
7339 : else
7340 126 : v[0] = EXTRASAMPLE_UNSPECIFIED;
7341 :
7342 262352 : for( i = 1; i < nExtraSamples; i++ )
7343 262224 : v[i] = EXTRASAMPLE_UNSPECIFIED;
7344 :
7345 128 : TIFFSetField(hTIFF, TIFFTAG_EXTRASAMPLES, nExtraSamples, v );
7346 :
7347 128 : CPLFree(v);
7348 : }
7349 :
7350 : /* Set the compression method before asking the default strip size */
7351 : /* This is usefull when translating to a JPEG-In-TIFF file where */
7352 : /* the default strip size is 8 or 16 depending on the photometric value */
7353 2316 : TIFFSetField( hTIFF, TIFFTAG_COMPRESSION, nCompression );
7354 :
7355 : /* -------------------------------------------------------------------- */
7356 : /* Setup tiling/stripping flags. */
7357 : /* -------------------------------------------------------------------- */
7358 2316 : if( bTiled )
7359 : {
7360 54 : if( nBlockXSize == 0 )
7361 28 : nBlockXSize = 256;
7362 :
7363 54 : if( nBlockYSize == 0 )
7364 28 : nBlockYSize = 256;
7365 :
7366 54 : if (!TIFFSetField( hTIFF, TIFFTAG_TILEWIDTH, nBlockXSize ) ||
7367 : !TIFFSetField( hTIFF, TIFFTAG_TILELENGTH, nBlockYSize ))
7368 : {
7369 0 : XTIFFClose(hTIFF);
7370 0 : return NULL;
7371 : }
7372 : }
7373 : else
7374 : {
7375 : uint32 nRowsPerStrip;
7376 :
7377 2262 : if( nBlockYSize == 0 )
7378 2244 : nRowsPerStrip = MIN(nYSize, (int)TIFFDefaultStripSize(hTIFF,0));
7379 : else
7380 18 : nRowsPerStrip = nBlockYSize;
7381 :
7382 2262 : TIFFSetField( hTIFF, TIFFTAG_ROWSPERSTRIP, nRowsPerStrip );
7383 : }
7384 :
7385 : /* -------------------------------------------------------------------- */
7386 : /* Set compression related tags. */
7387 : /* -------------------------------------------------------------------- */
7388 2316 : if ( nCompression == COMPRESSION_LZW ||
7389 : nCompression == COMPRESSION_ADOBE_DEFLATE )
7390 52 : TIFFSetField( hTIFF, TIFFTAG_PREDICTOR, nPredictor );
7391 2316 : if (nCompression == COMPRESSION_ADOBE_DEFLATE
7392 : && nZLevel != -1)
7393 0 : TIFFSetField( hTIFF, TIFFTAG_ZIPQUALITY, nZLevel );
7394 2344 : else if( nCompression == COMPRESSION_JPEG
7395 : && nJpegQuality != -1 )
7396 28 : TIFFSetField( hTIFF, TIFFTAG_JPEGQUALITY, nJpegQuality );
7397 2288 : else if( nCompression == COMPRESSION_LZMA && nLZMAPreset != -1)
7398 0 : TIFFSetField( hTIFF, TIFFTAG_LZMAPRESET, nLZMAPreset );
7399 :
7400 : /* -------------------------------------------------------------------- */
7401 : /* If we forced production of a file with photometric=palette, */
7402 : /* we need to push out a default color table. */
7403 : /* -------------------------------------------------------------------- */
7404 2316 : if( bForceColorTable )
7405 : {
7406 : int nColors;
7407 :
7408 6 : if( eType == GDT_Byte )
7409 6 : nColors = 256;
7410 : else
7411 0 : nColors = 65536;
7412 :
7413 : unsigned short *panTRed, *panTGreen, *panTBlue;
7414 :
7415 6 : panTRed = (unsigned short *) CPLMalloc(sizeof(unsigned short)*nColors);
7416 6 : panTGreen = (unsigned short *) CPLMalloc(sizeof(unsigned short)*nColors);
7417 6 : panTBlue = (unsigned short *) CPLMalloc(sizeof(unsigned short)*nColors);
7418 :
7419 1542 : for( int iColor = 0; iColor < nColors; iColor++ )
7420 : {
7421 1536 : if( eType == GDT_Byte )
7422 : {
7423 1536 : panTRed[iColor] = (unsigned short) (257 * iColor);
7424 1536 : panTGreen[iColor] = (unsigned short) (257 * iColor);
7425 1536 : panTBlue[iColor] = (unsigned short) (257 * iColor);
7426 : }
7427 : else
7428 : {
7429 0 : panTRed[iColor] = (unsigned short) iColor;
7430 0 : panTGreen[iColor] = (unsigned short) iColor;
7431 0 : panTBlue[iColor] = (unsigned short) iColor;
7432 : }
7433 : }
7434 :
7435 : TIFFSetField( hTIFF, TIFFTAG_COLORMAP,
7436 6 : panTRed, panTGreen, panTBlue );
7437 :
7438 6 : CPLFree( panTRed );
7439 6 : CPLFree( panTGreen );
7440 6 : CPLFree( panTBlue );
7441 : }
7442 :
7443 2316 : return( hTIFF );
7444 : }
7445 :
7446 : /************************************************************************/
7447 : /* Create() */
7448 : /* */
7449 : /* Create a new GeoTIFF or TIFF file. */
7450 : /************************************************************************/
7451 :
7452 1904 : GDALDataset *GTiffDataset::Create( const char * pszFilename,
7453 : int nXSize, int nYSize, int nBands,
7454 : GDALDataType eType,
7455 : char **papszParmList )
7456 :
7457 : {
7458 : GTiffDataset * poDS;
7459 : TIFF *hTIFF;
7460 :
7461 : /* -------------------------------------------------------------------- */
7462 : /* Create the underlying TIFF file. */
7463 : /* -------------------------------------------------------------------- */
7464 : hTIFF = CreateLL( pszFilename, nXSize, nYSize, nBands,
7465 1904 : eType, 0, papszParmList );
7466 :
7467 1904 : if( hTIFF == NULL )
7468 4 : return NULL;
7469 :
7470 : /* -------------------------------------------------------------------- */
7471 : /* Create the new GTiffDataset object. */
7472 : /* -------------------------------------------------------------------- */
7473 1900 : poDS = new GTiffDataset();
7474 1900 : poDS->hTIFF = hTIFF;
7475 1900 : poDS->poActiveDS = poDS;
7476 1900 : poDS->ppoActiveDSRef = &(poDS->poActiveDS);
7477 :
7478 1900 : poDS->nRasterXSize = nXSize;
7479 1900 : poDS->nRasterYSize = nYSize;
7480 1900 : poDS->eAccess = GA_Update;
7481 1900 : poDS->bCrystalized = FALSE;
7482 1900 : poDS->nSamplesPerPixel = (uint16) nBands;
7483 3800 : poDS->osFilename = pszFilename;
7484 :
7485 : /* Avoid premature crystalization that will cause directory re-writting */
7486 : /* if GetProjectionRef() or GetGeoTransform() are called on the newly created GeoTIFF */
7487 1900 : poDS->bLookedForProjection = TRUE;
7488 :
7489 1900 : TIFFGetField( hTIFF, TIFFTAG_SAMPLEFORMAT, &(poDS->nSampleFormat) );
7490 1900 : TIFFGetField( hTIFF, TIFFTAG_PLANARCONFIG, &(poDS->nPlanarConfig) );
7491 1900 : TIFFGetField( hTIFF, TIFFTAG_PHOTOMETRIC, &(poDS->nPhotometric) );
7492 1900 : TIFFGetField( hTIFF, TIFFTAG_BITSPERSAMPLE, &(poDS->nBitsPerSample) );
7493 1900 : TIFFGetField( hTIFF, TIFFTAG_COMPRESSION, &(poDS->nCompression) );
7494 :
7495 1900 : if( TIFFIsTiled(hTIFF) )
7496 : {
7497 40 : TIFFGetField( hTIFF, TIFFTAG_TILEWIDTH, &(poDS->nBlockXSize) );
7498 40 : TIFFGetField( hTIFF, TIFFTAG_TILELENGTH, &(poDS->nBlockYSize) );
7499 : }
7500 : else
7501 : {
7502 1860 : if( !TIFFGetField( hTIFF, TIFFTAG_ROWSPERSTRIP,
7503 : &(poDS->nRowsPerStrip) ) )
7504 0 : poDS->nRowsPerStrip = 1; /* dummy value */
7505 :
7506 1860 : poDS->nBlockXSize = nXSize;
7507 1860 : poDS->nBlockYSize = MIN((int)poDS->nRowsPerStrip,nYSize);
7508 : }
7509 :
7510 : poDS->nBlocksPerBand =
7511 : ((nYSize + poDS->nBlockYSize - 1) / poDS->nBlockYSize)
7512 1900 : * ((nXSize + poDS->nBlockXSize - 1) / poDS->nBlockXSize);
7513 :
7514 1900 : if( CSLFetchNameValue( papszParmList, "PROFILE" ) != NULL )
7515 8 : poDS->osProfile = CSLFetchNameValue( papszParmList, "PROFILE" );
7516 :
7517 : /* -------------------------------------------------------------------- */
7518 : /* YCbCr JPEG compressed images should be translated on the fly */
7519 : /* to RGB by libtiff/libjpeg unless specifically requested */
7520 : /* otherwise. */
7521 : /* -------------------------------------------------------------------- */
7522 1900 : if( poDS->nCompression == COMPRESSION_JPEG
7523 : && poDS->nPhotometric == PHOTOMETRIC_YCBCR
7524 : && CSLTestBoolean( CPLGetConfigOption("CONVERT_YCBCR_TO_RGB",
7525 : "YES") ) )
7526 : {
7527 : int nColorMode;
7528 :
7529 26 : poDS->SetMetadataItem( "SOURCE_COLOR_SPACE", "YCbCr", "IMAGE_STRUCTURE" );
7530 26 : if ( !TIFFGetField( hTIFF, TIFFTAG_JPEGCOLORMODE, &nColorMode ) ||
7531 : nColorMode != JPEGCOLORMODE_RGB )
7532 26 : TIFFSetField(hTIFF, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
7533 : }
7534 :
7535 : /* -------------------------------------------------------------------- */
7536 : /* Read palette back as a color table if it has one. */
7537 : /* -------------------------------------------------------------------- */
7538 : unsigned short *panRed, *panGreen, *panBlue;
7539 :
7540 1900 : if( poDS->nPhotometric == PHOTOMETRIC_PALETTE
7541 : && TIFFGetField( hTIFF, TIFFTAG_COLORMAP,
7542 : &panRed, &panGreen, &panBlue) )
7543 : {
7544 : int nColorCount;
7545 : GDALColorEntry oEntry;
7546 :
7547 6 : poDS->poColorTable = new GDALColorTable();
7548 :
7549 6 : nColorCount = 1 << poDS->nBitsPerSample;
7550 :
7551 1542 : for( int iColor = nColorCount - 1; iColor >= 0; iColor-- )
7552 : {
7553 1536 : oEntry.c1 = panRed[iColor] / 256;
7554 1536 : oEntry.c2 = panGreen[iColor] / 256;
7555 1536 : oEntry.c3 = panBlue[iColor] / 256;
7556 1536 : oEntry.c4 = 255;
7557 :
7558 1536 : poDS->poColorTable->SetColorEntry( iColor, &oEntry );
7559 : }
7560 : }
7561 :
7562 : /* -------------------------------------------------------------------- */
7563 : /* Do we want to ensure all blocks get written out on close to */
7564 : /* avoid sparse files? */
7565 : /* -------------------------------------------------------------------- */
7566 1900 : if( !CSLFetchBoolean( papszParmList, "SPARSE_OK", FALSE ) )
7567 1864 : poDS->bFillEmptyTiles = TRUE;
7568 :
7569 : /* -------------------------------------------------------------------- */
7570 : /* Preserve creation options for consulting later (for instance */
7571 : /* to decide if a TFW file should be written). */
7572 : /* -------------------------------------------------------------------- */
7573 1900 : poDS->papszCreationOptions = CSLDuplicate( papszParmList );
7574 :
7575 1900 : poDS->nZLevel = GTiffGetZLevel(papszParmList);
7576 1900 : poDS->nLZMAPreset = GTiffGetLZMAPreset(papszParmList);
7577 1900 : poDS->nJpegQuality = GTiffGetJpegQuality(papszParmList);
7578 :
7579 : #if !defined(BIGTIFF_SUPPORT)
7580 : /* -------------------------------------------------------------------- */
7581 : /* If we are writing jpeg compression we need to write some */
7582 : /* imagery to force the jpegtables to get created. This is, */
7583 : /* likely only needed with libtiff >= 3.9.3 (#3633) */
7584 : /* -------------------------------------------------------------------- */
7585 : if( poDS->nCompression == COMPRESSION_JPEG
7586 : && strstr(TIFFLIB_VERSION_STR, "Version 3.9") != NULL )
7587 : {
7588 : CPLDebug( "GDAL",
7589 : "Writing zero block to force creation of JPEG tables." );
7590 : if( TIFFIsTiled( hTIFF ) )
7591 : {
7592 : int cc = TIFFTileSize( hTIFF );
7593 : unsigned char *pabyZeros = (unsigned char *) CPLCalloc(cc,1);
7594 : TIFFWriteEncodedTile(hTIFF, 0, pabyZeros, cc);
7595 : CPLFree( pabyZeros );
7596 : }
7597 : else
7598 : {
7599 : int cc = TIFFStripSize( hTIFF );
7600 : unsigned char *pabyZeros = (unsigned char *) CPLCalloc(cc,1);
7601 : TIFFWriteEncodedStrip(hTIFF, 0, pabyZeros, cc);
7602 : CPLFree( pabyZeros );
7603 : }
7604 : poDS->bDontReloadFirstBlock = TRUE;
7605 : }
7606 : #endif
7607 :
7608 : /* -------------------------------------------------------------------- */
7609 : /* Create band information objects. */
7610 : /* -------------------------------------------------------------------- */
7611 : int iBand;
7612 :
7613 266392 : for( iBand = 0; iBand < nBands; iBand++ )
7614 : {
7615 528938 : if( poDS->nBitsPerSample == 8 ||
7616 : poDS->nBitsPerSample == 16 ||
7617 : poDS->nBitsPerSample == 32 ||
7618 : poDS->nBitsPerSample == 64 ||
7619 : poDS->nBitsPerSample == 128)
7620 264446 : poDS->SetBand( iBand+1, new GTiffRasterBand( poDS, iBand+1 ) );
7621 : else
7622 : {
7623 46 : poDS->SetBand( iBand+1, new GTiffOddBitsBand( poDS, iBand+1 ) );
7624 : poDS->GetRasterBand( iBand+1 )->
7625 : SetMetadataItem( "NBITS",
7626 : CPLString().Printf("%d",poDS->nBitsPerSample),
7627 92 : "IMAGE_STRUCTURE" );
7628 : }
7629 : }
7630 :
7631 1900 : poDS->oOvManager.Initialize( poDS, pszFilename );
7632 :
7633 1900 : return( poDS );
7634 : }
7635 :
7636 : /************************************************************************/
7637 : /* CreateCopy() */
7638 : /************************************************************************/
7639 :
7640 : GDALDataset *
7641 422 : GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
7642 : int bStrict, char ** papszOptions,
7643 : GDALProgressFunc pfnProgress, void * pProgressData )
7644 :
7645 : {
7646 : TIFF *hTIFF;
7647 422 : int nXSize = poSrcDS->GetRasterXSize();
7648 422 : int nYSize = poSrcDS->GetRasterYSize();
7649 422 : int nBands = poSrcDS->GetRasterCount();
7650 : int iBand;
7651 422 : CPLErr eErr = CE_None;
7652 : uint16 nPlanarConfig;
7653 : uint16 nBitsPerSample;
7654 : GDALRasterBand *poPBand;
7655 :
7656 422 : if( poSrcDS->GetRasterCount() == 0 )
7657 : {
7658 : CPLError( CE_Failure, CPLE_AppDefined,
7659 2 : "Unable to export GeoTIFF files with zero bands." );
7660 2 : return NULL;
7661 : }
7662 :
7663 420 : poPBand = poSrcDS->GetRasterBand(1);
7664 420 : GDALDataType eType = poPBand->GetRasterDataType();
7665 :
7666 : /* -------------------------------------------------------------------- */
7667 : /* Check, whether all bands in input dataset has the same type. */
7668 : /* -------------------------------------------------------------------- */
7669 662 : for ( iBand = 2; iBand <= nBands; iBand++ )
7670 : {
7671 242 : if ( eType != poSrcDS->GetRasterBand(iBand)->GetRasterDataType() )
7672 : {
7673 0 : if ( bStrict )
7674 : {
7675 : CPLError( CE_Failure, CPLE_AppDefined,
7676 : "Unable to export GeoTIFF file with different datatypes per\n"
7677 0 : "different bands. All bands should have the same types in TIFF." );
7678 0 : return NULL;
7679 : }
7680 : else
7681 : {
7682 : CPLError( CE_Warning, CPLE_AppDefined,
7683 : "Unable to export GeoTIFF file with different datatypes per\n"
7684 0 : "different bands. All bands should have the same types in TIFF." );
7685 : }
7686 : }
7687 : }
7688 :
7689 420 : if( !pfnProgress( 0.0, NULL, pProgressData ) )
7690 0 : return NULL;
7691 :
7692 : /* -------------------------------------------------------------------- */
7693 : /* Capture the profile. */
7694 : /* -------------------------------------------------------------------- */
7695 : const char *pszProfile;
7696 : int bGeoTIFF;
7697 :
7698 420 : pszProfile = CSLFetchNameValue(papszOptions,"PROFILE");
7699 420 : if( pszProfile == NULL )
7700 402 : pszProfile = "GDALGeoTIFF";
7701 :
7702 420 : if( !EQUAL(pszProfile,"BASELINE")
7703 : && !EQUAL(pszProfile,"GeoTIFF")
7704 : && !EQUAL(pszProfile,"GDALGeoTIFF") )
7705 : {
7706 : CPLError( CE_Failure, CPLE_AppDefined,
7707 : "PROFILE=%s not supported in GTIFF driver.",
7708 0 : pszProfile );
7709 0 : return NULL;
7710 : }
7711 :
7712 420 : if( EQUAL(pszProfile,"BASELINE") )
7713 12 : bGeoTIFF = FALSE;
7714 : else
7715 408 : bGeoTIFF = TRUE;
7716 :
7717 : /* -------------------------------------------------------------------- */
7718 : /* Special handling for NBITS. Copy from band metadata if found. */
7719 : /* -------------------------------------------------------------------- */
7720 420 : char **papszCreateOptions = CSLDuplicate( papszOptions );
7721 :
7722 430 : if( poPBand->GetMetadataItem( "NBITS", "IMAGE_STRUCTURE" ) != NULL
7723 10 : && atoi(poPBand->GetMetadataItem( "NBITS", "IMAGE_STRUCTURE" )) > 0
7724 : && CSLFetchNameValue( papszCreateOptions, "NBITS") == NULL )
7725 : {
7726 : papszCreateOptions =
7727 : CSLSetNameValue( papszCreateOptions, "NBITS",
7728 : poPBand->GetMetadataItem( "NBITS",
7729 6 : "IMAGE_STRUCTURE" ) );
7730 : }
7731 :
7732 690 : if( CSLFetchNameValue( papszOptions, "PIXELTYPE" ) == NULL
7733 : && eType == GDT_Byte
7734 270 : && poPBand->GetMetadataItem( "PIXELTYPE", "IMAGE_STRUCTURE" ) )
7735 : {
7736 : papszCreateOptions =
7737 : CSLSetNameValue( papszCreateOptions, "PIXELTYPE",
7738 : poPBand->GetMetadataItem(
7739 0 : "PIXELTYPE", "IMAGE_STRUCTURE" ) );
7740 : }
7741 :
7742 420 : int nSrcOverviews = poSrcDS->GetRasterBand(1)->GetOverviewCount();
7743 420 : double dfExtraSpaceForOverviews = 0;
7744 420 : if (nSrcOverviews != 0 &&
7745 : CSLFetchBoolean(papszOptions, "COPY_SRC_OVERVIEWS", FALSE))
7746 : {
7747 : int i;
7748 36 : for(i=0;i<nSrcOverviews;i++)
7749 : {
7750 26 : dfExtraSpaceForOverviews += ((double)poSrcDS->GetRasterBand(1)->GetOverview(i)->GetXSize()) *
7751 52 : poSrcDS->GetRasterBand(1)->GetOverview(i)->GetYSize();
7752 : }
7753 10 : dfExtraSpaceForOverviews *= nBands * (GDALGetDataTypeSize(eType) / 8);
7754 : }
7755 :
7756 : /* -------------------------------------------------------------------- */
7757 : /* Should we use optimized way of copying from an input JPEG */
7758 : /* dataset ? */
7759 : /* -------------------------------------------------------------------- */
7760 420 : int bCopyFromJPEG = FALSE;
7761 420 : int bDirectCopyFromJPEG = FALSE;
7762 :
7763 : /* Note: JPEG_DIRECT_COPY is not defined by default, because it is mainly */
7764 : /* usefull for debugging purposes */
7765 : #ifdef JPEG_DIRECT_COPY
7766 : if (CSLFetchBoolean(papszCreateOptions, "JPEG_DIRECT_COPY", FALSE) &&
7767 : GTIFF_CanDirectCopyFromJPEG(poSrcDS, papszCreateOptions))
7768 : {
7769 : CPLDebug("GTiff", "Using special direct copy mode from a JPEG dataset");
7770 :
7771 : bDirectCopyFromJPEG = TRUE;
7772 : }
7773 : #endif
7774 :
7775 : #ifdef HAVE_LIBJPEG
7776 : /* when CreateCopy'ing() from a JPEG dataset, and asking for COMPRESS=JPEG, */
7777 : /* use DCT coefficients (unless other options are incompatible, like strip/tile dimensions, */
7778 : /* specifying JPEG_QUALITY option, incompatible PHOTOMETRIC with the source colorspace, etc...) */
7779 : /* to avoid the lossy steps involved by uncompression/recompression */
7780 420 : if (!bDirectCopyFromJPEG && GTIFF_CanCopyFromJPEG(poSrcDS, papszCreateOptions))
7781 : {
7782 16 : CPLDebug("GTiff", "Using special copy mode from a JPEG dataset");
7783 :
7784 16 : bCopyFromJPEG = TRUE;
7785 : }
7786 : #endif
7787 :
7788 : /* -------------------------------------------------------------------- */
7789 : /* Create the file. */
7790 : /* -------------------------------------------------------------------- */
7791 : hTIFF = CreateLL( pszFilename, nXSize, nYSize, nBands,
7792 420 : eType, dfExtraSpaceForOverviews, papszCreateOptions );
7793 :
7794 420 : CSLDestroy( papszCreateOptions );
7795 :
7796 420 : if( hTIFF == NULL )
7797 4 : return NULL;
7798 :
7799 416 : TIFFGetField( hTIFF, TIFFTAG_PLANARCONFIG, &nPlanarConfig );
7800 416 : TIFFGetField(hTIFF, TIFFTAG_BITSPERSAMPLE, &nBitsPerSample );
7801 :
7802 : /* -------------------------------------------------------------------- */
7803 : /* Are we really producing an RGBA image? If so, set the */
7804 : /* associated alpha information. */
7805 : /* -------------------------------------------------------------------- */
7806 : int bForcePhotometric =
7807 416 : CSLFetchNameValue(papszOptions,"PHOTOMETRIC") != NULL;
7808 :
7809 426 : if( nBands == 4 && !bForcePhotometric
7810 10 : && poSrcDS->GetRasterBand(4)->GetColorInterpretation()==GCI_AlphaBand)
7811 : {
7812 : uint16 v[1];
7813 :
7814 6 : v[0] = EXTRASAMPLE_ASSOCALPHA;
7815 6 : TIFFSetField(hTIFF, TIFFTAG_EXTRASAMPLES, 1, v);
7816 6 : TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB );
7817 : }
7818 :
7819 : /* -------------------------------------------------------------------- */
7820 : /* If the output is jpeg compressed, and the input is RGB make */
7821 : /* sure we note that. */
7822 : /* -------------------------------------------------------------------- */
7823 : uint16 nCompression;
7824 :
7825 416 : if( !TIFFGetField( hTIFF, TIFFTAG_COMPRESSION, &(nCompression) ) )
7826 0 : nCompression = COMPRESSION_NONE;
7827 :
7828 416 : if( nCompression == COMPRESSION_JPEG )
7829 : {
7830 58 : if( nBands >= 3
7831 24 : && (poSrcDS->GetRasterBand(1)->GetColorInterpretation()
7832 : == GCI_YCbCr_YBand)
7833 0 : && (poSrcDS->GetRasterBand(2)->GetColorInterpretation()
7834 : == GCI_YCbCr_CbBand)
7835 0 : && (poSrcDS->GetRasterBand(3)->GetColorInterpretation()
7836 : == GCI_YCbCr_CrBand) )
7837 : {
7838 : /* do nothing ... */
7839 : }
7840 : else
7841 : {
7842 : /* we assume RGB if it isn't explicitly YCbCr */
7843 34 : CPLDebug( "GTiff", "Setting JPEGCOLORMODE_RGB" );
7844 34 : TIFFSetField( hTIFF, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB );
7845 : }
7846 : }
7847 :
7848 : /* -------------------------------------------------------------------- */
7849 : /* Does the source image consist of one band, with a palette? */
7850 : /* If so, copy over. */
7851 : /* -------------------------------------------------------------------- */
7852 416 : if( (nBands == 1 || nBands == 2) && poSrcDS->GetRasterBand(1)->GetColorTable() != NULL
7853 : && eType == GDT_Byte )
7854 : {
7855 : unsigned short anTRed[256], anTGreen[256], anTBlue[256];
7856 : GDALColorTable *poCT;
7857 :
7858 8 : poCT = poSrcDS->GetRasterBand(1)->GetColorTable();
7859 :
7860 2056 : for( int iColor = 0; iColor < 256; iColor++ )
7861 : {
7862 2048 : if( iColor < poCT->GetColorEntryCount() )
7863 : {
7864 : GDALColorEntry sRGB;
7865 :
7866 954 : poCT->GetColorEntryAsRGB( iColor, &sRGB );
7867 :
7868 954 : anTRed[iColor] = (unsigned short) (257 * sRGB.c1);
7869 954 : anTGreen[iColor] = (unsigned short) (257 * sRGB.c2);
7870 954 : anTBlue[iColor] = (unsigned short) (257 * sRGB.c3);
7871 : }
7872 : else
7873 : {
7874 1094 : anTRed[iColor] = anTGreen[iColor] = anTBlue[iColor] = 0;
7875 : }
7876 : }
7877 :
7878 8 : if( !bForcePhotometric )
7879 8 : TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE );
7880 8 : TIFFSetField( hTIFF, TIFFTAG_COLORMAP, anTRed, anTGreen, anTBlue );
7881 : }
7882 712 : else if( (nBands == 1 || nBands == 2)
7883 304 : && poSrcDS->GetRasterBand(1)->GetColorTable() != NULL
7884 : && eType == GDT_UInt16 )
7885 : {
7886 : unsigned short *panTRed, *panTGreen, *panTBlue;
7887 : GDALColorTable *poCT;
7888 :
7889 2 : panTRed = (unsigned short *) CPLMalloc(65536*sizeof(unsigned short));
7890 2 : panTGreen = (unsigned short *) CPLMalloc(65536*sizeof(unsigned short));
7891 2 : panTBlue = (unsigned short *) CPLMalloc(65536*sizeof(unsigned short));
7892 :
7893 2 : poCT = poSrcDS->GetRasterBand(1)->GetColorTable();
7894 :
7895 131074 : for( int iColor = 0; iColor < 65536; iColor++ )
7896 : {
7897 131072 : if( iColor < poCT->GetColorEntryCount() )
7898 : {
7899 : GDALColorEntry sRGB;
7900 :
7901 131072 : poCT->GetColorEntryAsRGB( iColor, &sRGB );
7902 :
7903 131072 : panTRed[iColor] = (unsigned short) (256 * sRGB.c1);
7904 131072 : panTGreen[iColor] = (unsigned short) (256 * sRGB.c2);
7905 131072 : panTBlue[iColor] = (unsigned short) (256 * sRGB.c3);
7906 : }
7907 : else
7908 : {
7909 0 : panTRed[iColor] = panTGreen[iColor] = panTBlue[iColor] = 0;
7910 : }
7911 : }
7912 :
7913 2 : if( !bForcePhotometric )
7914 2 : TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE );
7915 2 : TIFFSetField( hTIFF, TIFFTAG_COLORMAP, panTRed, panTGreen, panTBlue );
7916 :
7917 2 : CPLFree( panTRed );
7918 2 : CPLFree( panTGreen );
7919 2 : CPLFree( panTBlue );
7920 : }
7921 406 : else if( poSrcDS->GetRasterBand(1)->GetColorTable() != NULL )
7922 : CPLError( CE_Warning, CPLE_AppDefined,
7923 : "Unable to export color table to GeoTIFF file. Color tables\n"
7924 0 : "can only be written to 1 band or 2 bands Byte or UInt16 GeoTIFF files." );
7925 :
7926 428 : if( nBands == 2
7927 12 : && poSrcDS->GetRasterBand(1)->GetColorTable() != NULL
7928 : && (eType == GDT_Byte || eType == GDT_UInt16) )
7929 : {
7930 2 : uint16 v[1] = { EXTRASAMPLE_UNASSALPHA };
7931 :
7932 2 : TIFFSetField(hTIFF, TIFFTAG_EXTRASAMPLES, 1, v );
7933 : }
7934 :
7935 : /* -------------------------------------------------------------------- */
7936 : /* Transfer some TIFF specific metadata, if available. */
7937 : /* The return value will tell us if we need to try again later with*/
7938 : /* PAM because the profile doesn't allow to write some metadata */
7939 : /* as TIFF tag */
7940 : /* -------------------------------------------------------------------- */
7941 : int bHasWrittenMDInGeotiffTAG =
7942 : GTiffDataset::WriteMetadata( poSrcDS, hTIFF, FALSE, pszProfile,
7943 416 : pszFilename, papszOptions );
7944 :
7945 : /* -------------------------------------------------------------------- */
7946 : /* Write NoData value, if exist. */
7947 : /* -------------------------------------------------------------------- */
7948 416 : if( EQUAL(pszProfile,"GDALGeoTIFF") )
7949 : {
7950 : int bSuccess;
7951 : double dfNoData;
7952 :
7953 400 : dfNoData = poSrcDS->GetRasterBand(1)->GetNoDataValue( &bSuccess );
7954 400 : if ( bSuccess )
7955 42 : GTiffDataset::WriteNoDataValue( hTIFF, dfNoData );
7956 : }
7957 :
7958 : /* -------------------------------------------------------------------- */
7959 : /* Are we addressing PixelIsPoint mode? */
7960 : /* -------------------------------------------------------------------- */
7961 416 : bool bPixelIsPoint = false;
7962 416 : int bPointGeoIgnore = FALSE;
7963 :
7964 636 : if( poSrcDS->GetMetadataItem( GDALMD_AREA_OR_POINT )
7965 220 : && EQUAL(poSrcDS->GetMetadataItem(GDALMD_AREA_OR_POINT),
7966 : GDALMD_AOP_POINT) )
7967 : {
7968 12 : bPixelIsPoint = true;
7969 : bPointGeoIgnore =
7970 : CSLTestBoolean( CPLGetConfigOption("GTIFF_POINT_GEO_IGNORE",
7971 12 : "FALSE") );
7972 : }
7973 :
7974 : /* -------------------------------------------------------------------- */
7975 : /* Write affine transform if it is meaningful. */
7976 : /* -------------------------------------------------------------------- */
7977 416 : const char *pszProjection = NULL;
7978 : double adfGeoTransform[6];
7979 :
7980 694 : if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None
7981 278 : && (adfGeoTransform[0] != 0.0 || adfGeoTransform[1] != 1.0
7982 0 : || adfGeoTransform[2] != 0.0 || adfGeoTransform[3] != 0.0
7983 0 : || adfGeoTransform[4] != 0.0 || adfGeoTransform[5] != 1.0 ))
7984 : {
7985 278 : if( bGeoTIFF )
7986 : {
7987 802 : if( adfGeoTransform[2] == 0.0 && adfGeoTransform[4] == 0.0
7988 266 : && adfGeoTransform[5] < 0.0 )
7989 : {
7990 :
7991 : double adfPixelScale[3], adfTiePoints[6];
7992 :
7993 266 : adfPixelScale[0] = adfGeoTransform[1];
7994 266 : adfPixelScale[1] = fabs(adfGeoTransform[5]);
7995 266 : adfPixelScale[2] = 0.0;
7996 :
7997 266 : TIFFSetField( hTIFF, TIFFTAG_GEOPIXELSCALE, 3, adfPixelScale );
7998 :
7999 266 : adfTiePoints[0] = 0.0;
8000 266 : adfTiePoints[1] = 0.0;
8001 266 : adfTiePoints[2] = 0.0;
8002 266 : adfTiePoints[3] = adfGeoTransform[0];
8003 266 : adfTiePoints[4] = adfGeoTransform[3];
8004 266 : adfTiePoints[5] = 0.0;
8005 :
8006 266 : if( bPixelIsPoint && !bPointGeoIgnore )
8007 : {
8008 8 : adfTiePoints[3] += adfGeoTransform[1] * 0.5 + adfGeoTransform[2] * 0.5;
8009 8 : adfTiePoints[4] += adfGeoTransform[4] * 0.5 + adfGeoTransform[5] * 0.5;
8010 : }
8011 :
8012 266 : TIFFSetField( hTIFF, TIFFTAG_GEOTIEPOINTS, 6, adfTiePoints );
8013 : }
8014 : else
8015 : {
8016 : double adfMatrix[16];
8017 :
8018 4 : memset(adfMatrix,0,sizeof(double) * 16);
8019 :
8020 4 : adfMatrix[0] = adfGeoTransform[1];
8021 4 : adfMatrix[1] = adfGeoTransform[2];
8022 4 : adfMatrix[3] = adfGeoTransform[0];
8023 4 : adfMatrix[4] = adfGeoTransform[4];
8024 4 : adfMatrix[5] = adfGeoTransform[5];
8025 4 : adfMatrix[7] = adfGeoTransform[3];
8026 4 : adfMatrix[15] = 1.0;
8027 :
8028 4 : if( bPixelIsPoint && !bPointGeoIgnore )
8029 : {
8030 0 : adfMatrix[3] += adfGeoTransform[1] * 0.5 + adfGeoTransform[2] * 0.5;
8031 0 : adfMatrix[7] += adfGeoTransform[4] * 0.5 + adfGeoTransform[5] * 0.5;
8032 : }
8033 :
8034 4 : TIFFSetField( hTIFF, TIFFTAG_GEOTRANSMATRIX, 16, adfMatrix );
8035 : }
8036 :
8037 270 : pszProjection = poSrcDS->GetProjectionRef();
8038 : }
8039 :
8040 : /* -------------------------------------------------------------------- */
8041 : /* Do we need a TFW file? */
8042 : /* -------------------------------------------------------------------- */
8043 278 : if( CSLFetchBoolean( papszOptions, "TFW", FALSE ) )
8044 2 : GDALWriteWorldFile( pszFilename, "tfw", adfGeoTransform );
8045 276 : else if( CSLFetchBoolean( papszOptions, "WORLDFILE", FALSE ) )
8046 2 : GDALWriteWorldFile( pszFilename, "wld", adfGeoTransform );
8047 : }
8048 :
8049 : /* -------------------------------------------------------------------- */
8050 : /* Otherwise write tiepoints if they are available. */
8051 : /* -------------------------------------------------------------------- */
8052 138 : else if( poSrcDS->GetGCPCount() > 0 && bGeoTIFF )
8053 : {
8054 6 : const GDAL_GCP *pasGCPs = poSrcDS->GetGCPs();
8055 : double *padfTiePoints;
8056 :
8057 : padfTiePoints = (double *)
8058 6 : CPLMalloc(6*sizeof(double)*poSrcDS->GetGCPCount());
8059 :
8060 30 : for( int iGCP = 0; iGCP < poSrcDS->GetGCPCount(); iGCP++ )
8061 : {
8062 :
8063 24 : padfTiePoints[iGCP*6+0] = pasGCPs[iGCP].dfGCPPixel;
8064 24 : padfTiePoints[iGCP*6+1] = pasGCPs[iGCP].dfGCPLine;
8065 24 : padfTiePoints[iGCP*6+2] = 0;
8066 24 : padfTiePoints[iGCP*6+3] = pasGCPs[iGCP].dfGCPX;
8067 24 : padfTiePoints[iGCP*6+4] = pasGCPs[iGCP].dfGCPY;
8068 24 : padfTiePoints[iGCP*6+5] = pasGCPs[iGCP].dfGCPZ;
8069 :
8070 24 : if( bPixelIsPoint && !bPointGeoIgnore )
8071 : {
8072 0 : padfTiePoints[iGCP*6+0] += 0.5;
8073 0 : padfTiePoints[iGCP*6+1] += 0.5;
8074 : }
8075 : }
8076 :
8077 : TIFFSetField( hTIFF, TIFFTAG_GEOTIEPOINTS,
8078 6 : 6*poSrcDS->GetGCPCount(), padfTiePoints );
8079 6 : CPLFree( padfTiePoints );
8080 :
8081 6 : pszProjection = poSrcDS->GetGCPProjection();
8082 :
8083 6 : if( CSLFetchBoolean( papszOptions, "TFW", FALSE )
8084 : || CSLFetchBoolean( papszOptions, "WORLDFILE", FALSE ) )
8085 : {
8086 : CPLError(CE_Warning, CPLE_AppDefined,
8087 0 : "TFW=ON or WORLDFILE=ON creation options are ignored when GCPs are available");
8088 : }
8089 : }
8090 :
8091 : else
8092 132 : pszProjection = poSrcDS->GetProjectionRef();
8093 :
8094 : /* -------------------------------------------------------------------- */
8095 : /* Write the projection information, if possible. */
8096 : /* -------------------------------------------------------------------- */
8097 416 : if( pszProjection != NULL && strlen(pszProjection) > 0 && bGeoTIFF )
8098 : {
8099 : GTIF *psGTIF;
8100 :
8101 272 : psGTIF = GTIFNew( hTIFF );
8102 272 : GTIFSetFromOGISDefn( psGTIF, pszProjection );
8103 :
8104 486 : if( poSrcDS->GetMetadataItem( GDALMD_AREA_OR_POINT )
8105 214 : && EQUAL(poSrcDS->GetMetadataItem(GDALMD_AREA_OR_POINT),
8106 : GDALMD_AOP_POINT) )
8107 : {
8108 : GTIFKeySet(psGTIF, GTRasterTypeGeoKey, TYPE_SHORT, 1,
8109 12 : RasterPixelIsPoint);
8110 : }
8111 :
8112 272 : GTIFWriteKeys( psGTIF );
8113 272 : GTIFFree( psGTIF );
8114 : }
8115 :
8116 416 : int bDontReloadFirstBlock = FALSE;
8117 :
8118 : #ifdef HAVE_LIBJPEG
8119 416 : if (bCopyFromJPEG)
8120 : {
8121 : GTIFF_CopyFromJPEG_WriteAdditionalTags(hTIFF,
8122 16 : poSrcDS);
8123 : }
8124 : #else
8125 : if (0)
8126 : {
8127 : }
8128 : #endif
8129 :
8130 : #if !defined(BIGTIFF_SUPPORT)
8131 : /* -------------------------------------------------------------------- */
8132 : /* If we are writing jpeg compression we need to write some */
8133 : /* imagery to force the jpegtables to get created. This is, */
8134 : /* likely only needed with libtiff >= 3.9.3 (#3633) */
8135 : /* -------------------------------------------------------------------- */
8136 : else if( nCompression == COMPRESSION_JPEG
8137 : && strstr(TIFFLIB_VERSION_STR, "Version 3.9") != NULL )
8138 : {
8139 : CPLDebug( "GDAL",
8140 : "Writing zero block to force creation of JPEG tables." );
8141 : if( TIFFIsTiled( hTIFF ) )
8142 : {
8143 : int cc = TIFFTileSize( hTIFF );
8144 : unsigned char *pabyZeros = (unsigned char *) CPLCalloc(cc,1);
8145 : TIFFWriteEncodedTile(hTIFF, 0, pabyZeros, cc);
8146 : CPLFree( pabyZeros );
8147 : }
8148 : else
8149 : {
8150 : int cc = TIFFStripSize( hTIFF );
8151 : unsigned char *pabyZeros = (unsigned char *) CPLCalloc(cc,1);
8152 : TIFFWriteEncodedStrip(hTIFF, 0, pabyZeros, cc);
8153 : CPLFree( pabyZeros );
8154 : }
8155 : bDontReloadFirstBlock = TRUE;
8156 : }
8157 : #endif
8158 :
8159 : /* -------------------------------------------------------------------- */
8160 : /* Cleanup */
8161 : /* -------------------------------------------------------------------- */
8162 :
8163 416 : TIFFWriteCheck( hTIFF, TIFFIsTiled(hTIFF), "GTiffCreateCopy()");
8164 416 : TIFFWriteDirectory( hTIFF );
8165 416 : TIFFFlush( hTIFF );
8166 416 : XTIFFClose( hTIFF );
8167 416 : hTIFF = NULL;
8168 :
8169 416 : if( eErr != CE_None )
8170 : {
8171 0 : VSIUnlink( pszFilename );
8172 0 : return NULL;
8173 : }
8174 :
8175 : /* -------------------------------------------------------------------- */
8176 : /* Re-open as a dataset and copy over missing metadata using */
8177 : /* PAM facilities. */
8178 : /* -------------------------------------------------------------------- */
8179 : GTiffDataset *poDS;
8180 416 : CPLString osFileName("GTIFF_RAW:");
8181 :
8182 416 : osFileName += pszFilename;
8183 :
8184 416 : poDS = (GTiffDataset *) GDALOpen( osFileName, GA_Update );
8185 416 : if( poDS == NULL )
8186 0 : poDS = (GTiffDataset *) GDALOpen( osFileName, GA_ReadOnly );
8187 :
8188 416 : if ( poDS == NULL )
8189 : {
8190 0 : VSIUnlink( pszFilename );
8191 0 : return NULL;
8192 : }
8193 :
8194 416 : poDS->osProfile = pszProfile;
8195 416 : poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT & ~GCIF_MASK );
8196 416 : poDS->papszCreationOptions = CSLDuplicate( papszOptions );
8197 416 : poDS->bDontReloadFirstBlock = bDontReloadFirstBlock;
8198 :
8199 : /* -------------------------------------------------------------------- */
8200 : /* CloneInfo() doesn't merge metadata, it just replaces it totally */
8201 : /* So we have to merge it */
8202 : /* -------------------------------------------------------------------- */
8203 :
8204 416 : char **papszSRC_MD = poSrcDS->GetMetadata();
8205 416 : char **papszDST_MD = CSLDuplicate(poDS->GetMetadata());
8206 :
8207 416 : papszDST_MD = CSLMerge( papszDST_MD, papszSRC_MD );
8208 :
8209 416 : poDS->SetMetadata( papszDST_MD );
8210 416 : CSLDestroy( papszDST_MD );
8211 :
8212 : /* Depending on the PHOTOMETRIC tag, the TIFF file may not have */
8213 : /* the same band count as the source. Will fail later in GDALDatasetCopyWholeRaster anyway... */
8214 1074 : for( int nBand = 1;
8215 : nBand <= MIN(poDS->GetRasterCount(), poSrcDS->GetRasterCount()) ;
8216 : nBand++ )
8217 : {
8218 658 : GDALRasterBand* poSrcBand = poSrcDS->GetRasterBand(nBand);
8219 658 : GDALRasterBand* poDstBand = poDS->GetRasterBand(nBand);
8220 658 : char **papszSRC_MD = poSrcBand->GetMetadata();
8221 658 : char **papszDST_MD = CSLDuplicate(poDstBand->GetMetadata());
8222 :
8223 658 : papszDST_MD = CSLMerge( papszDST_MD, papszSRC_MD );
8224 :
8225 658 : poDstBand->SetMetadata( papszDST_MD );
8226 658 : CSLDestroy( papszDST_MD );
8227 :
8228 : char** papszCatNames;
8229 658 : papszCatNames = poSrcBand->GetCategoryNames();
8230 658 : if (NULL != papszCatNames)
8231 0 : poDstBand->SetCategoryNames( papszCatNames );
8232 : }
8233 :
8234 416 : hTIFF = (TIFF*) poDS->GetInternalHandle(NULL);
8235 :
8236 : /* -------------------------------------------------------------------- */
8237 : /* Handle forcing xml:ESRI data to be written to PAM. */
8238 : /* -------------------------------------------------------------------- */
8239 416 : if( CSLTestBoolean(CPLGetConfigOption( "ESRI_XML_PAM", "NO" )) )
8240 : {
8241 2 : char **papszESRIMD = poSrcDS->GetMetadata("xml:ESRI");
8242 2 : if( papszESRIMD )
8243 : {
8244 2 : poDS->SetMetadata( papszESRIMD, "xml:ESRI");
8245 : }
8246 : }
8247 :
8248 : /* -------------------------------------------------------------------- */
8249 : /* Second chance : now that we have a PAM dataset, it is possible */
8250 : /* to write metadata that we couldn't be writen as TIFF tag */
8251 : /* -------------------------------------------------------------------- */
8252 416 : if (!bHasWrittenMDInGeotiffTAG)
8253 : GTiffDataset::WriteMetadata( poDS, hTIFF, TRUE, pszProfile,
8254 8 : pszFilename, papszOptions, TRUE /* don't write RPC and IMD file again */);
8255 :
8256 : /* To avoid unnecessary directory rewriting */
8257 416 : poDS->bMetadataChanged = FALSE;
8258 416 : poDS->bGeoTIFFInfoChanged = FALSE;
8259 :
8260 : /* We must re-set the compression level at this point, since it has */
8261 : /* been lost a few lines above when closing the newly create TIFF file */
8262 : /* The TIFFTAG_ZIPQUALITY & TIFFTAG_JPEGQUALITY are not store in the TIFF file. */
8263 : /* They are just TIFF session parameters */
8264 :
8265 416 : poDS->nZLevel = GTiffGetZLevel(papszOptions);
8266 416 : poDS->nLZMAPreset = GTiffGetLZMAPreset(papszOptions);
8267 416 : poDS->nJpegQuality = GTiffGetJpegQuality(papszOptions);
8268 :
8269 416 : if (nCompression == COMPRESSION_ADOBE_DEFLATE)
8270 : {
8271 8 : if (poDS->nZLevel != -1)
8272 : {
8273 0 : TIFFSetField( hTIFF, TIFFTAG_ZIPQUALITY, poDS->nZLevel );
8274 : }
8275 : }
8276 408 : else if( nCompression == COMPRESSION_JPEG)
8277 : {
8278 34 : if (poDS->nJpegQuality != -1)
8279 : {
8280 6 : TIFFSetField( hTIFF, TIFFTAG_JPEGQUALITY, poDS->nJpegQuality );
8281 : }
8282 : }
8283 374 : else if( nCompression == COMPRESSION_LZMA)
8284 : {
8285 0 : if (poDS->nLZMAPreset != -1)
8286 : {
8287 0 : TIFFSetField( hTIFF, TIFFTAG_LZMAPRESET, poDS->nLZMAPreset );
8288 : }
8289 : }
8290 :
8291 : /* Precreate (internal) mask, so that the IBuildOverviews() below */
8292 : /* has a chance to create also the overviews of the mask */
8293 416 : int nMaskFlags = poSrcDS->GetRasterBand(1)->GetMaskFlags();
8294 416 : if( eErr == CE_None
8295 : && !(nMaskFlags & (GMF_ALL_VALID|GMF_ALPHA|GMF_NODATA) )
8296 : && (nMaskFlags & GMF_PER_DATASET) )
8297 : {
8298 6 : eErr = poDS->CreateMaskBand( nMaskFlags );
8299 : }
8300 :
8301 : /* -------------------------------------------------------------------- */
8302 : /* Create and then copy existing overviews if requested */
8303 : /* We do it such that all the IFDs are at the beginning of the file, */
8304 : /* and that the imagery data for the smallest overview is written */
8305 : /* first, that way the file is more usable when embedded in a */
8306 : /* compressed stream. */
8307 : /* -------------------------------------------------------------------- */
8308 :
8309 : /* For scaled progress due to overview copying */
8310 416 : double dfTotalPixels = ((double)nXSize) * nYSize;
8311 416 : double dfCurPixels = 0;
8312 :
8313 416 : if (eErr == CE_None &&
8314 : nSrcOverviews != 0 &&
8315 : CSLFetchBoolean(papszOptions, "COPY_SRC_OVERVIEWS", FALSE))
8316 : {
8317 10 : eErr = poDS->CreateOverviewsFromSrcOverviews(poSrcDS);
8318 :
8319 10 : if (poDS->nOverviewCount != nSrcOverviews)
8320 : {
8321 : CPLError(CE_Failure, CPLE_AppDefined,
8322 : "Did only manage to instanciate %d overview levels, whereas source contains %d",
8323 0 : poDS->nOverviewCount, nSrcOverviews);
8324 0 : eErr = CE_Failure;
8325 : }
8326 :
8327 : int i;
8328 36 : for(i=0;i<nSrcOverviews;i++)
8329 : {
8330 26 : GDALRasterBand* poOvrBand = poSrcDS->GetRasterBand(1)->GetOverview(i);
8331 : dfTotalPixels += ((double)poOvrBand->GetXSize()) *
8332 26 : poOvrBand->GetYSize();
8333 : }
8334 :
8335 10 : char* papszCopyWholeRasterOptions[2] = { NULL, NULL };
8336 10 : if (nCompression != COMPRESSION_NONE)
8337 0 : papszCopyWholeRasterOptions[0] = (char*) "COMPRESSED=YES";
8338 : /* Now copy the imagery */
8339 34 : for(i=0;eErr == CE_None && i<nSrcOverviews;i++)
8340 : {
8341 : /* Begin with the smallest overview */
8342 24 : int iOvrLevel = nSrcOverviews-1-i;
8343 :
8344 : /* Create a fake dataset with the source overview level so that */
8345 : /* GDALDatasetCopyWholeRaster can cope with it */
8346 24 : GDALDataset* poSrcOvrDS = new GDALOverviewDS(poSrcDS, iOvrLevel);
8347 :
8348 : GDALRasterBand* poOvrBand =
8349 48 : poSrcDS->GetRasterBand(1)->GetOverview(iOvrLevel);
8350 : double dfNextCurPixels = dfCurPixels +
8351 24 : ((double)poOvrBand->GetXSize()) * poOvrBand->GetYSize();
8352 :
8353 : void* pScaledData = GDALCreateScaledProgress( dfCurPixels / dfTotalPixels,
8354 : dfNextCurPixels / dfTotalPixels,
8355 24 : pfnProgress, pProgressData);
8356 :
8357 : eErr = GDALDatasetCopyWholeRaster( (GDALDatasetH) poSrcOvrDS,
8358 24 : (GDALDatasetH) poDS->papoOverviewDS[iOvrLevel],
8359 : papszCopyWholeRasterOptions,
8360 48 : GDALScaledProgress, pScaledData );
8361 :
8362 24 : dfCurPixels = dfNextCurPixels;
8363 24 : GDALDestroyScaledProgress(pScaledData);
8364 :
8365 24 : delete poSrcOvrDS;
8366 24 : poDS->papoOverviewDS[iOvrLevel]->FlushCache();
8367 :
8368 : /* Copy mask of the overview */
8369 24 : if (eErr == CE_None && poDS->poMaskDS != NULL)
8370 : {
8371 4 : eErr = GDALRasterBandCopyWholeRaster( poOvrBand->GetMaskBand(),
8372 4 : poDS->papoOverviewDS[iOvrLevel]->poMaskDS->GetRasterBand(1),
8373 : papszCopyWholeRasterOptions,
8374 8 : GDALDummyProgress, NULL);
8375 4 : poDS->papoOverviewDS[iOvrLevel]->poMaskDS->FlushCache();
8376 : }
8377 : }
8378 : }
8379 :
8380 : /* -------------------------------------------------------------------- */
8381 : /* Copy actual imagery. */
8382 : /* -------------------------------------------------------------------- */
8383 : void* pScaledData = GDALCreateScaledProgress( dfCurPixels / dfTotalPixels,
8384 : 1.0,
8385 416 : pfnProgress, pProgressData);
8386 :
8387 416 : int bTryCopy = TRUE;
8388 :
8389 : #ifdef HAVE_LIBJPEG
8390 416 : if (bCopyFromJPEG)
8391 : {
8392 : eErr = GTIFF_CopyFromJPEG(poDS, poSrcDS,
8393 : pfnProgress, pProgressData,
8394 16 : bTryCopy);
8395 :
8396 : /* In case of failure in the decompression step, try normal copy */
8397 16 : if (bTryCopy)
8398 0 : eErr = CE_None;
8399 : }
8400 : #endif
8401 :
8402 : #ifdef JPEG_DIRECT_COPY
8403 : if (bDirectCopyFromJPEG)
8404 : {
8405 : eErr = GTIFF_DirectCopyFromJPEG(poDS, poSrcDS,
8406 : pfnProgress, pProgressData,
8407 : bTryCopy);
8408 :
8409 : /* In case of failure in the reading step, try normal copy */
8410 : if (bTryCopy)
8411 : eErr = CE_None;
8412 : }
8413 : #endif
8414 :
8415 422 : if (bTryCopy && (poDS->bTreatAsSplit || poDS->bTreatAsSplitBitmap))
8416 : {
8417 : /* For split bands, we use TIFFWriteScanline() interface */
8418 6 : CPLAssert(poDS->nBitsPerSample == 8 || poDS->nBitsPerSample == 1);
8419 :
8420 10 : if (poDS->nPlanarConfig == PLANARCONFIG_CONTIG && poDS->nBands > 1)
8421 : {
8422 : int j;
8423 4 : GByte* pabyScanline = (GByte *) CPLMalloc(TIFFScanlineSize(hTIFF));
8424 14100 : for(j=0;j<nYSize && eErr == CE_None;j++)
8425 : {
8426 : eErr = poSrcDS->RasterIO(GF_Read, 0, j, nXSize, 1,
8427 : pabyScanline, nXSize, 1,
8428 14096 : GDT_Byte, nBands, NULL, poDS->nBands, 0, 1);
8429 14096 : if (eErr == CE_None &&
8430 : TIFFWriteScanline( hTIFF, pabyScanline, j, 0) == -1)
8431 : {
8432 : CPLError( CE_Failure, CPLE_AppDefined,
8433 0 : "TIFFWriteScanline() failed." );
8434 0 : eErr = CE_Failure;
8435 : }
8436 14096 : if( !GDALScaledProgress( (j+1) * 1.0 / nYSize, NULL, pScaledData ) )
8437 0 : eErr = CE_Failure;
8438 : }
8439 4 : CPLFree(pabyScanline);
8440 : }
8441 : else
8442 : {
8443 : int iBand, j;
8444 2 : GByte* pabyScanline = (GByte *) CPLMalloc(TIFFScanlineSize(hTIFF));
8445 2 : eErr = CE_None;
8446 8 : for(iBand=1;iBand<=nBands && eErr == CE_None;iBand++)
8447 : {
8448 30006 : for(j=0;j<nYSize && eErr == CE_None;j++)
8449 : {
8450 : eErr = poSrcDS->GetRasterBand(iBand)->RasterIO(
8451 : GF_Read, 0, j, nXSize, 1,
8452 : pabyScanline, nXSize, 1,
8453 30000 : GDT_Byte, 0, 0);
8454 30000 : if (poDS->bTreatAsSplitBitmap)
8455 : {
8456 0 : for(int i=0;i<nXSize;i++)
8457 : {
8458 0 : GByte byVal = pabyScanline[i];
8459 0 : if ((i & 0x7) == 0)
8460 0 : pabyScanline[i >> 3] = 0;
8461 0 : if (byVal)
8462 0 : pabyScanline[i >> 3] |= (0x80 >> (i & 0x7));
8463 : }
8464 : }
8465 30000 : if (eErr == CE_None &&
8466 : TIFFWriteScanline( hTIFF, pabyScanline, j, (uint16) (iBand-1)) == -1)
8467 : {
8468 : CPLError( CE_Failure, CPLE_AppDefined,
8469 0 : "TIFFWriteScanline() failed." );
8470 0 : eErr = CE_Failure;
8471 : }
8472 30000 : if( !GDALScaledProgress( (j+1 + (iBand - 1) * nYSize) * 1.0 /
8473 : (nBands * nYSize), NULL, pScaledData ) )
8474 0 : eErr = CE_Failure;
8475 : }
8476 : }
8477 2 : CPLFree(pabyScanline);
8478 : }
8479 :
8480 : /* Necessary to be able to read the file without re-opening */
8481 : #if defined(HAVE_TIFFGETSIZEPROC)
8482 6 : TIFFSizeProc pfnSizeProc = TIFFGetSizeProc( hTIFF );
8483 :
8484 6 : TIFFFlushData( hTIFF );
8485 :
8486 6 : toff_t nNewDirOffset = pfnSizeProc( TIFFClientdata( hTIFF ) );
8487 6 : if( (nNewDirOffset % 2) == 1 )
8488 6 : nNewDirOffset++;
8489 : #endif
8490 :
8491 6 : TIFFFlush( hTIFF );
8492 :
8493 : #if defined(HAVE_TIFFGETSIZEPROC)
8494 6 : if( poDS->nDirOffset != TIFFCurrentDirOffset( hTIFF ) )
8495 : {
8496 2 : poDS->nDirOffset = nNewDirOffset;
8497 2 : CPLDebug( "GTiff", "directory moved during flush." );
8498 : }
8499 : #endif
8500 : }
8501 410 : else if (bTryCopy && eErr == CE_None)
8502 : {
8503 392 : char* papszCopyWholeRasterOptions[2] = { NULL, NULL };
8504 392 : if (nCompression != COMPRESSION_NONE)
8505 34 : papszCopyWholeRasterOptions[0] = (char*) "COMPRESSED=YES";
8506 : eErr = GDALDatasetCopyWholeRaster( (GDALDatasetH) poSrcDS,
8507 : (GDALDatasetH) poDS,
8508 : papszCopyWholeRasterOptions,
8509 392 : GDALScaledProgress, pScaledData );
8510 : }
8511 :
8512 416 : GDALDestroyScaledProgress(pScaledData);
8513 :
8514 416 : if (eErr == CE_None)
8515 : {
8516 414 : if (poDS->poMaskDS)
8517 : {
8518 6 : const char* papszOptions[2] = { "COMPRESSED=YES", NULL };
8519 : eErr = GDALRasterBandCopyWholeRaster(
8520 6 : poSrcDS->GetRasterBand(1)->GetMaskBand(),
8521 6 : poDS->GetRasterBand(1)->GetMaskBand(),
8522 : (char**)papszOptions,
8523 18 : GDALDummyProgress, NULL);
8524 : }
8525 : else
8526 408 : eErr = GDALDriver::DefaultCopyMasks( poSrcDS, poDS, bStrict );
8527 : }
8528 :
8529 416 : if( eErr == CE_Failure )
8530 : {
8531 2 : delete poDS;
8532 2 : poDS = NULL;
8533 :
8534 2 : if (CSLTestBoolean(CPLGetConfigOption("GTIFF_DELETE_ON_ERROR", "YES")))
8535 0 : VSIUnlink( pszFilename ); // should really delete more carefully.
8536 : }
8537 :
8538 416 : return poDS;
8539 : }
8540 :
8541 : /************************************************************************/
8542 : /* GetProjectionRef() */
8543 : /************************************************************************/
8544 :
8545 6626 : const char *GTiffDataset::GetProjectionRef()
8546 :
8547 : {
8548 6626 : if( nGCPCount == 0 )
8549 : {
8550 6566 : LookForProjection();
8551 :
8552 6566 : if( EQUAL(pszProjection,"") )
8553 186 : return GDALPamDataset::GetProjectionRef();
8554 : else
8555 6380 : return( pszProjection );
8556 : }
8557 : else
8558 60 : return "";
8559 : }
8560 :
8561 : /************************************************************************/
8562 : /* SetProjection() */
8563 : /************************************************************************/
8564 :
8565 1464 : CPLErr GTiffDataset::SetProjection( const char * pszNewProjection )
8566 :
8567 : {
8568 1464 : LookForProjection();
8569 :
8570 1464 : if( !EQUALN(pszNewProjection,"GEOGCS",6)
8571 : && !EQUALN(pszNewProjection,"PROJCS",6)
8572 : && !EQUALN(pszNewProjection,"LOCAL_CS",8)
8573 : && !EQUALN(pszNewProjection,"COMPD_CS",8)
8574 : && !EQUALN(pszNewProjection,"GEOCCS",6)
8575 : && !EQUAL(pszNewProjection,"") )
8576 : {
8577 : CPLError( CE_Failure, CPLE_AppDefined,
8578 : "Only OGC WKT Projections supported for writing to GeoTIFF.\n"
8579 : "%s not supported.",
8580 0 : pszNewProjection );
8581 :
8582 0 : return CE_Failure;
8583 : }
8584 :
8585 1464 : CPLFree( pszProjection );
8586 1464 : pszProjection = CPLStrdup( pszNewProjection );
8587 :
8588 1464 : bGeoTIFFInfoChanged = TRUE;
8589 :
8590 1464 : return CE_None;
8591 : }
8592 :
8593 : /************************************************************************/
8594 : /* GetGeoTransform() */
8595 : /************************************************************************/
8596 :
8597 4334 : CPLErr GTiffDataset::GetGeoTransform( double * padfTransform )
8598 :
8599 : {
8600 4334 : memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
8601 :
8602 4334 : if( !bGeoTransformValid )
8603 190 : return CE_Failure;
8604 : else
8605 4144 : return CE_None;
8606 : }
8607 :
8608 : /************************************************************************/
8609 : /* SetGeoTransform() */
8610 : /************************************************************************/
8611 :
8612 1394 : CPLErr GTiffDataset::SetGeoTransform( double * padfTransform )
8613 :
8614 : {
8615 1394 : if( GetAccess() == GA_Update )
8616 : {
8617 1394 : memcpy( adfGeoTransform, padfTransform, sizeof(double)*6 );
8618 1394 : bGeoTransformValid = TRUE;
8619 1394 : bGeoTIFFInfoChanged = TRUE;
8620 :
8621 1394 : return( CE_None );
8622 : }
8623 : else
8624 : {
8625 : CPLError( CE_Failure, CPLE_NotSupported,
8626 0 : "Attempt to call SetGeoTransform() on a read-only GeoTIFF file." );
8627 0 : return CE_Failure;
8628 : }
8629 : }
8630 :
8631 : /************************************************************************/
8632 : /* GetGCPCount() */
8633 : /************************************************************************/
8634 :
8635 2346 : int GTiffDataset::GetGCPCount()
8636 :
8637 : {
8638 2346 : return nGCPCount;
8639 : }
8640 :
8641 : /************************************************************************/
8642 : /* GetGCPProjection() */
8643 : /************************************************************************/
8644 :
8645 130 : const char *GTiffDataset::GetGCPProjection()
8646 :
8647 : {
8648 130 : if( nGCPCount > 0 )
8649 : {
8650 126 : LookForProjection();
8651 : }
8652 130 : if (pszProjection != NULL)
8653 130 : return pszProjection;
8654 : else
8655 0 : return "";
8656 : }
8657 :
8658 : /************************************************************************/
8659 : /* GetGCPs() */
8660 : /************************************************************************/
8661 :
8662 70 : const GDAL_GCP *GTiffDataset::GetGCPs()
8663 :
8664 : {
8665 70 : return pasGCPList;
8666 : }
8667 :
8668 : /************************************************************************/
8669 : /* SetGCPs() */
8670 : /************************************************************************/
8671 :
8672 4 : CPLErr GTiffDataset::SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
8673 : const char *pszGCPProjection )
8674 : {
8675 4 : if( GetAccess() == GA_Update )
8676 : {
8677 4 : bLookedForProjection = TRUE;
8678 :
8679 4 : if( this->nGCPCount > 0 )
8680 : {
8681 0 : GDALDeinitGCPs( this->nGCPCount, this->pasGCPList );
8682 0 : CPLFree( this->pasGCPList );
8683 : }
8684 :
8685 4 : this->nGCPCount = nGCPCount;
8686 4 : this->pasGCPList = GDALDuplicateGCPs(nGCPCount, pasGCPList);
8687 :
8688 4 : CPLFree( this->pszProjection );
8689 4 : this->pszProjection = CPLStrdup( pszGCPProjection );
8690 4 : bGeoTIFFInfoChanged = TRUE;
8691 :
8692 4 : return CE_None;
8693 : }
8694 : else
8695 : {
8696 : CPLError( CE_Failure, CPLE_NotSupported,
8697 0 : "SetGCPs() is only supported on newly created GeoTIFF files." );
8698 0 : return CE_Failure;
8699 : }
8700 : }
8701 :
8702 : /************************************************************************/
8703 : /* GetMetadata() */
8704 : /************************************************************************/
8705 :
8706 11792 : char **GTiffDataset::GetMetadata( const char * pszDomain )
8707 :
8708 : {
8709 11792 : if( pszDomain != NULL && EQUAL(pszDomain,"ProxyOverviewRequest") )
8710 0 : return GDALPamDataset::GetMetadata( pszDomain );
8711 :
8712 15388 : else if( pszDomain != NULL && EQUAL(pszDomain,"RPC") )
8713 3596 : LoadRPCRPB();
8714 :
8715 10514 : else if( pszDomain != NULL && EQUAL(pszDomain,"IMD") )
8716 2318 : LoadIMDPVL();
8717 :
8718 5878 : else if( pszDomain != NULL && EQUAL(pszDomain,"SUBDATASETS") )
8719 338 : ScanDirectories();
8720 :
8721 : /* FIXME ? Should we call LookForProjection() to load GDALMD_AREA_OR_POINT ? */
8722 : /* This can impact performances */
8723 :
8724 11792 : return oGTiffMDMD.GetMetadata( pszDomain );
8725 : }
8726 :
8727 : /************************************************************************/
8728 : /* SetMetadata() */
8729 : /************************************************************************/
8730 1042 : CPLErr GTiffDataset::SetMetadata( char ** papszMD, const char *pszDomain )
8731 :
8732 : {
8733 1042 : if( pszDomain == NULL || !EQUAL(pszDomain,"_temporary_") )
8734 1042 : bMetadataChanged = TRUE;
8735 :
8736 1042 : if( (pszDomain == NULL || EQUAL(pszDomain, "")) &&
8737 : CSLFetchNameValue(papszMD, GDALMD_AREA_OR_POINT) != NULL )
8738 : {
8739 : const char* pszPrevValue =
8740 802 : GetMetadataItem(GDALMD_AREA_OR_POINT);
8741 : const char* pszNewValue =
8742 802 : CSLFetchNameValue(papszMD, GDALMD_AREA_OR_POINT);
8743 802 : if (pszPrevValue == NULL || pszNewValue == NULL ||
8744 : !EQUAL(pszPrevValue, pszNewValue))
8745 : {
8746 540 : LookForProjection();
8747 540 : bGeoTIFFInfoChanged = TRUE;
8748 : }
8749 : }
8750 :
8751 1042 : return oGTiffMDMD.SetMetadata( papszMD, pszDomain );
8752 : }
8753 :
8754 : /************************************************************************/
8755 : /* GetMetadataItem() */
8756 : /************************************************************************/
8757 :
8758 49316 : const char *GTiffDataset::GetMetadataItem( const char * pszName,
8759 : const char * pszDomain )
8760 :
8761 : {
8762 49316 : if( pszDomain != NULL && EQUAL(pszDomain,"ProxyOverviewRequest") )
8763 6 : return GDALPamDataset::GetMetadataItem( pszName, pszDomain );
8764 :
8765 49314 : else if( pszDomain != NULL && EQUAL(pszDomain,"RPC") )
8766 4 : LoadRPCRPB();
8767 :
8768 49310 : else if( pszDomain != NULL && EQUAL(pszDomain,"IMD") )
8769 4 : LoadIMDPVL();
8770 :
8771 49302 : else if( pszDomain != NULL && EQUAL(pszDomain,"SUBDATASETS") )
8772 0 : ScanDirectories();
8773 :
8774 49302 : else if( (pszDomain == NULL || EQUAL(pszDomain, "")) &&
8775 : pszName != NULL && EQUAL(pszName, GDALMD_AREA_OR_POINT) )
8776 : {
8777 3948 : LookForProjection();
8778 : }
8779 :
8780 49310 : return oGTiffMDMD.GetMetadataItem( pszName, pszDomain );
8781 : }
8782 :
8783 : /************************************************************************/
8784 : /* SetMetadataItem() */
8785 : /************************************************************************/
8786 :
8787 11058 : CPLErr GTiffDataset::SetMetadataItem( const char *pszName,
8788 : const char *pszValue,
8789 : const char *pszDomain )
8790 :
8791 : {
8792 11058 : if( pszDomain == NULL || !EQUAL(pszDomain,"_temporary_") )
8793 11058 : bMetadataChanged = TRUE;
8794 :
8795 11058 : if( (pszDomain == NULL || EQUAL(pszDomain, "")) &&
8796 : pszName != NULL && EQUAL(pszName, GDALMD_AREA_OR_POINT) )
8797 : {
8798 16 : LookForProjection();
8799 16 : bGeoTIFFInfoChanged = TRUE;
8800 : }
8801 :
8802 11058 : return oGTiffMDMD.SetMetadataItem( pszName, pszValue, pszDomain );
8803 : }
8804 :
8805 : /************************************************************************/
8806 : /* GetInternalHandle() */
8807 : /************************************************************************/
8808 :
8809 582 : void *GTiffDataset::GetInternalHandle( const char * /* pszHandleName */ )
8810 :
8811 : {
8812 582 : return hTIFF;
8813 : }
8814 :
8815 :
8816 : /************************************************************************/
8817 : /* FindRPBFile() */
8818 : /************************************************************************/
8819 :
8820 4412 : int GTiffDataset::FindRPBFile()
8821 : {
8822 : osRPBFile = GDALFindAssociatedFile( osFilename, "RPB",
8823 4412 : oOvManager.GetSiblingFiles(), 0 );
8824 :
8825 4412 : return osRPBFile != "";
8826 : }
8827 :
8828 : /************************************************************************/
8829 : /* FindIMDFile() */
8830 : /************************************************************************/
8831 :
8832 4070 : int GTiffDataset::FindIMDFile()
8833 : {
8834 : osIMDFile = GDALFindAssociatedFile( osFilename, "IMD",
8835 4070 : oOvManager.GetSiblingFiles(), 0 );
8836 :
8837 4070 : return osIMDFile != "";
8838 : }
8839 :
8840 : /************************************************************************/
8841 : /* FindPVLFile() */
8842 : /************************************************************************/
8843 :
8844 4054 : int GTiffDataset::FindPVLFile()
8845 : {
8846 : osPVLFile = GDALFindAssociatedFile( osFilename, "PVL",
8847 4054 : oOvManager.GetSiblingFiles(), 0 );
8848 :
8849 4054 : return osPVLFile != "";
8850 : }
8851 :
8852 : /************************************************************************/
8853 : /* FindRPCFile() */
8854 : /************************************************************************/
8855 :
8856 4396 : int GTiffDataset::FindRPCFile()
8857 : {
8858 4396 : CPLString osSrcPath = osFilename;
8859 4396 : CPLString soPt(".");
8860 4396 : size_t found = osSrcPath.rfind(soPt);
8861 4396 : if (found == CPLString::npos)
8862 80 : return FALSE;
8863 4316 : osSrcPath.replace (found, osSrcPath.size() - found, "_rpc.txt");
8864 4316 : CPLString osTarget = osSrcPath;
8865 :
8866 4316 : char** papszSiblingFiles = oOvManager.GetSiblingFiles();
8867 4316 : if( papszSiblingFiles == NULL )
8868 : {
8869 : VSIStatBufL sStatBuf;
8870 :
8871 1848 : if( VSIStatExL( osTarget, &sStatBuf, VSI_STAT_EXISTS_FLAG ) != 0 )
8872 : {
8873 1848 : osSrcPath = osFilename;
8874 1848 : osSrcPath.replace (found, osSrcPath.size() - found, "_RPC.TXT");
8875 1848 : osTarget = osSrcPath;
8876 :
8877 1848 : if( VSIStatExL( osTarget, &sStatBuf, VSI_STAT_EXISTS_FLAG ) != 0 )
8878 : {
8879 1848 : osSrcPath = osFilename;
8880 1848 : osSrcPath.replace (found, osSrcPath.size() - found, "_rpc.TXT");
8881 1848 : osTarget = osSrcPath;
8882 :
8883 1848 : if( VSIStatExL( osTarget, &sStatBuf, VSI_STAT_EXISTS_FLAG ) != 0 )
8884 : {
8885 1848 : return FALSE;
8886 : }
8887 : }
8888 : }
8889 : }
8890 : else
8891 : {
8892 : int iSibling = CSLFindString( papszSiblingFiles,
8893 2468 : CPLGetFilename(osTarget) );
8894 2468 : if( iSibling < 0 )
8895 2466 : return FALSE;
8896 :
8897 2 : osTarget.resize(osTarget.size() - strlen(papszSiblingFiles[iSibling]));
8898 2 : osTarget += papszSiblingFiles[iSibling];
8899 : }
8900 :
8901 2 : osRPCFile = osTarget;
8902 2 : return TRUE;
8903 : }
8904 :
8905 : /************************************************************************/
8906 : /* LoadRPCRPB() */
8907 : /************************************************************************/
8908 :
8909 5534 : void GTiffDataset::LoadRPCRPB()
8910 : {
8911 5534 : if (bHasSearchedRPC)
8912 1122 : return;
8913 :
8914 4412 : bHasSearchedRPC = TRUE;
8915 :
8916 4412 : char **papszRPCMD = NULL;
8917 : /* Read Digital Globe .RPB file */
8918 4412 : if (FindRPBFile())
8919 16 : papszRPCMD = GDALLoadRPBFile( osRPBFile.c_str(), NULL );
8920 :
8921 : /* Read GeoEye _rpc.txt file */
8922 4412 : if(papszRPCMD == NULL && FindRPCFile())
8923 2 : papszRPCMD = GDALLoadRPCFile( osRPCFile.c_str(), NULL );
8924 :
8925 4412 : if( papszRPCMD != NULL )
8926 : {
8927 18 : oGTiffMDMD.SetMetadata( papszRPCMD, "RPC" );
8928 18 : CSLDestroy( papszRPCMD );
8929 : }
8930 : else
8931 4394 : ReadRPCTag();
8932 : }
8933 :
8934 : /************************************************************************/
8935 : /* LoadIMDPVL() */
8936 : /************************************************************************/
8937 :
8938 4256 : void GTiffDataset::LoadIMDPVL()
8939 : {
8940 4256 : if (!bHasSearchedIMD)
8941 : {
8942 4070 : bHasSearchedIMD = TRUE;
8943 :
8944 4070 : if (FindIMDFile())
8945 : {
8946 16 : char **papszIMDMD = GDALLoadIMDFile( osIMDFile.c_str(), NULL );
8947 :
8948 16 : if( papszIMDMD != NULL )
8949 : {
8950 : papszIMDMD = CSLSetNameValue( papszIMDMD,
8951 16 : "md_type", "imd" );
8952 16 : oGTiffMDMD.SetMetadata( papszIMDMD, "IMD" );
8953 16 : CSLDestroy( papszIMDMD );
8954 : }
8955 : }
8956 : }
8957 : //the imd has priority
8958 4256 : if (!bHasSearchedPVL && osIMDFile.empty())
8959 : {
8960 4054 : bHasSearchedPVL = TRUE;
8961 :
8962 4054 : if (FindPVLFile())
8963 : {
8964 : /* -------------------------------------------------------------------- */
8965 : /* Read file and parse. */
8966 : /* -------------------------------------------------------------------- */
8967 0 : CPLKeywordParser oParser;
8968 :
8969 0 : VSILFILE *fp = VSIFOpenL( osPVLFile.c_str(), "r" );
8970 :
8971 0 : if( fp == NULL )
8972 : return;
8973 :
8974 0 : if( !oParser.Ingest( fp ) )
8975 : {
8976 0 : VSIFCloseL( fp );
8977 : return;
8978 : }
8979 :
8980 0 : VSIFCloseL( fp );
8981 :
8982 : /* -------------------------------------------------------------------- */
8983 : /* Consider version changing. */
8984 : /* -------------------------------------------------------------------- */
8985 0 : char **papszPVLMD = CSLDuplicate( oParser.GetAllKeywords() );
8986 :
8987 0 : if( papszPVLMD != NULL )
8988 : {
8989 : papszPVLMD = CSLSetNameValue( papszPVLMD,
8990 0 : "md_type", "pvl" );
8991 :
8992 0 : oGTiffMDMD.SetMetadata( papszPVLMD, "IMD" );
8993 0 : CSLDestroy( papszPVLMD );
8994 0 : }
8995 : }
8996 : }
8997 : }
8998 :
8999 : /************************************************************************/
9000 : /* GetFileList() */
9001 : /************************************************************************/
9002 :
9003 1934 : char **GTiffDataset::GetFileList()
9004 :
9005 : {
9006 1934 : char **papszFileList = GDALPamDataset::GetFileList();
9007 :
9008 1934 : LoadRPCRPB();
9009 1934 : LoadIMDPVL();
9010 :
9011 1934 : if (osIMDFile.size() != 0)
9012 8 : papszFileList = CSLAddString( papszFileList, osIMDFile );
9013 1934 : if (osPVLFile.size() != 0)
9014 0 : papszFileList = CSLAddString( papszFileList, osPVLFile );
9015 1934 : if (osRPBFile.size() != 0)
9016 4 : papszFileList = CSLAddString( papszFileList, osRPBFile );
9017 1934 : if (osRPCFile.size() != 0)
9018 0 : papszFileList = CSLAddString( papszFileList, osRPCFile );
9019 :
9020 1934 : if (osWldFilename.size() != 0 &&
9021 : CSLFindString(papszFileList, osWldFilename) == -1)
9022 : {
9023 6 : papszFileList = CSLAddString( papszFileList, osWldFilename );
9024 : }
9025 :
9026 1934 : return papszFileList;
9027 : }
9028 :
9029 : /************************************************************************/
9030 : /* CreateMaskBand() */
9031 : /************************************************************************/
9032 :
9033 66 : CPLErr GTiffDataset::CreateMaskBand(int nFlags)
9034 : {
9035 66 : ScanDirectories();
9036 :
9037 66 : if (poMaskDS != NULL)
9038 : {
9039 : CPLError(CE_Failure, CPLE_AppDefined,
9040 0 : "This TIFF dataset has already an internal mask band");
9041 0 : return CE_Failure;
9042 : }
9043 66 : else if (CSLTestBoolean(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK", "NO")))
9044 : {
9045 : toff_t nOffset;
9046 : int bIsTiled;
9047 58 : int bIsOverview = FALSE;
9048 : uint32 nSubType;
9049 : int nCompression;
9050 :
9051 58 : if (nFlags != GMF_PER_DATASET)
9052 : {
9053 : CPLError(CE_Failure, CPLE_AppDefined,
9054 0 : "The only flag value supported for internal mask is GMF_PER_DATASET");
9055 0 : return CE_Failure;
9056 : }
9057 :
9058 58 : if( strstr(GDALGetMetadataItem(GDALGetDriverByName( "GTiff" ),
9059 : GDAL_DMD_CREATIONOPTIONLIST, NULL ),
9060 : "<Value>DEFLATE</Value>") != NULL )
9061 58 : nCompression = COMPRESSION_ADOBE_DEFLATE;
9062 : else
9063 0 : nCompression = COMPRESSION_PACKBITS;
9064 :
9065 : /* -------------------------------------------------------------------- */
9066 : /* If we don't have read access, then create the mask externally. */
9067 : /* -------------------------------------------------------------------- */
9068 58 : if( GetAccess() != GA_Update )
9069 : {
9070 : CPLError( CE_Warning, CPLE_AppDefined,
9071 : "File open for read-only accessing, "
9072 0 : "creating mask externally." );
9073 :
9074 0 : return GDALPamDataset::CreateMaskBand(nFlags);
9075 : }
9076 :
9077 58 : if (poBaseDS)
9078 : {
9079 24 : if (!poBaseDS->SetDirectory())
9080 0 : return CE_Failure;
9081 : }
9082 58 : if (!SetDirectory())
9083 0 : return CE_Failure;
9084 :
9085 58 : if( TIFFGetField(hTIFF, TIFFTAG_SUBFILETYPE, &nSubType))
9086 : {
9087 24 : bIsOverview = (nSubType & FILETYPE_REDUCEDIMAGE) != 0;
9088 :
9089 24 : if ((nSubType & FILETYPE_MASK) != 0)
9090 : {
9091 : CPLError( CE_Failure, CPLE_AppDefined,
9092 0 : "Cannot create a mask on a TIFF mask IFD !" );
9093 0 : return CE_Failure;
9094 : }
9095 : }
9096 :
9097 58 : bIsTiled = TIFFIsTiled(hTIFF);
9098 :
9099 58 : FlushDirectory();
9100 :
9101 : nOffset = GTIFFWriteDirectory(hTIFF,
9102 : (bIsOverview) ? FILETYPE_REDUCEDIMAGE | FILETYPE_MASK : FILETYPE_MASK,
9103 : nRasterXSize, nRasterYSize,
9104 : 1, PLANARCONFIG_CONTIG, 1,
9105 : nBlockXSize, nBlockYSize,
9106 : bIsTiled, nCompression,
9107 : PHOTOMETRIC_MASK, PREDICTOR_NONE,
9108 58 : SAMPLEFORMAT_UINT, NULL, NULL, NULL, 0, NULL, "");
9109 58 : if (nOffset == 0)
9110 0 : return CE_Failure;
9111 :
9112 58 : poMaskDS = new GTiffDataset();
9113 58 : poMaskDS->bPromoteTo8Bits = CSLTestBoolean(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK_TO_8BIT", "YES"));
9114 58 : if( poMaskDS->OpenOffset( hTIFF, ppoActiveDSRef, nOffset,
9115 : FALSE, GA_Update ) != CE_None)
9116 : {
9117 0 : delete poMaskDS;
9118 0 : poMaskDS = NULL;
9119 0 : return CE_Failure;
9120 : }
9121 :
9122 58 : return CE_None;
9123 : }
9124 : else
9125 : {
9126 8 : return GDALPamDataset::CreateMaskBand(nFlags);
9127 : }
9128 : }
9129 :
9130 : /************************************************************************/
9131 : /* CreateMaskBand() */
9132 : /************************************************************************/
9133 :
9134 24 : CPLErr GTiffRasterBand::CreateMaskBand(int nFlags)
9135 : {
9136 24 : poGDS->ScanDirectories();
9137 :
9138 24 : if (poGDS->poMaskDS != NULL)
9139 : {
9140 : CPLError(CE_Failure, CPLE_AppDefined,
9141 0 : "This TIFF dataset has already an internal mask band");
9142 0 : return CE_Failure;
9143 : }
9144 24 : else if (CSLTestBoolean(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK", "NO")))
9145 : {
9146 24 : return poGDS->CreateMaskBand(nFlags);
9147 : }
9148 : else
9149 : {
9150 0 : return GDALPamRasterBand::CreateMaskBand(nFlags);
9151 : }
9152 : }
9153 :
9154 : /************************************************************************/
9155 : /* PrepareTIFFErrorFormat() */
9156 : /* */
9157 : /* sometimes the "module" has stuff in it that has special */
9158 : /* meaning in a printf() style format, so we try to escape it. */
9159 : /* For now we hope the only thing we have to escape is %'s. */
9160 : /************************************************************************/
9161 :
9162 18 : static char *PrepareTIFFErrorFormat( const char *module, const char *fmt )
9163 :
9164 : {
9165 : char *pszModFmt;
9166 : int iIn, iOut;
9167 :
9168 18 : pszModFmt = (char *) CPLMalloc( strlen(module)*2 + strlen(fmt) + 2 );
9169 250 : for( iOut = 0, iIn = 0; module[iIn] != '\0'; iIn++ )
9170 : {
9171 232 : if( module[iIn] == '%' )
9172 : {
9173 0 : pszModFmt[iOut++] = '%';
9174 0 : pszModFmt[iOut++] = '%';
9175 : }
9176 : else
9177 232 : pszModFmt[iOut++] = module[iIn];
9178 : }
9179 18 : pszModFmt[iOut] = '\0';
9180 18 : strcat( pszModFmt, ":" );
9181 18 : strcat( pszModFmt, fmt );
9182 :
9183 18 : return pszModFmt;
9184 : }
9185 :
9186 : /************************************************************************/
9187 : /* GTiffWarningHandler() */
9188 : /************************************************************************/
9189 : void
9190 6 : GTiffWarningHandler(const char* module, const char* fmt, va_list ap )
9191 : {
9192 : char *pszModFmt;
9193 :
9194 6 : if( strstr(fmt,"nknown field") != NULL )
9195 0 : return;
9196 :
9197 6 : pszModFmt = PrepareTIFFErrorFormat( module, fmt );
9198 6 : if( strstr(fmt, "does not end in null byte") != NULL )
9199 : {
9200 2 : CPLString osMsg;
9201 2 : osMsg.vPrintf(pszModFmt, ap);
9202 2 : CPLDebug( "GTiff", "%s", osMsg.c_str() );
9203 : }
9204 : else
9205 4 : CPLErrorV( CE_Warning, CPLE_AppDefined, pszModFmt, ap );
9206 6 : CPLFree( pszModFmt );
9207 : }
9208 :
9209 : /************************************************************************/
9210 : /* GTiffErrorHandler() */
9211 : /************************************************************************/
9212 : void
9213 12 : GTiffErrorHandler(const char* module, const char* fmt, va_list ap )
9214 : {
9215 : char *pszModFmt;
9216 :
9217 12 : pszModFmt = PrepareTIFFErrorFormat( module, fmt );
9218 12 : CPLErrorV( CE_Failure, CPLE_AppDefined, pszModFmt, ap );
9219 12 : CPLFree( pszModFmt );
9220 12 : }
9221 :
9222 : /************************************************************************/
9223 : /* GTiffTagExtender() */
9224 : /* */
9225 : /* Install tags specially known to GDAL. */
9226 : /************************************************************************/
9227 :
9228 : static TIFFExtendProc _ParentExtender = NULL;
9229 :
9230 20116 : static void GTiffTagExtender(TIFF *tif)
9231 :
9232 : {
9233 : static const TIFFFieldInfo xtiffFieldInfo[] = {
9234 : { TIFFTAG_GDAL_METADATA, -1,-1, TIFF_ASCII, FIELD_CUSTOM,
9235 : TRUE, FALSE, (char*) "GDALMetadata" },
9236 : { TIFFTAG_GDAL_NODATA, -1,-1, TIFF_ASCII, FIELD_CUSTOM,
9237 : TRUE, FALSE, (char*) "GDALNoDataValue" },
9238 : { TIFFTAG_RPCCOEFFICIENT, -1,-1, TIFF_DOUBLE, FIELD_CUSTOM,
9239 : TRUE, TRUE, (char*) "RPCCoefficient" }
9240 : };
9241 :
9242 20116 : if (_ParentExtender)
9243 0 : (*_ParentExtender)(tif);
9244 :
9245 : TIFFMergeFieldInfo( tif, xtiffFieldInfo,
9246 20116 : sizeof(xtiffFieldInfo) / sizeof(xtiffFieldInfo[0]) );
9247 20116 : }
9248 :
9249 : /************************************************************************/
9250 : /* GTiffOneTimeInit() */
9251 : /* */
9252 : /* This is stuff that is initialized for the TIFF library just */
9253 : /* once. We deliberately defer the initialization till the */
9254 : /* first time we are likely to call into libtiff to avoid */
9255 : /* unnecessary paging in of the library for GDAL apps that */
9256 : /* don't use it. */
9257 : /************************************************************************/
9258 : #if defined(HAVE_DLFCN_H) && !defined(WIN32)
9259 : #include <dlfcn.h>
9260 : #endif
9261 :
9262 10034 : int GTiffOneTimeInit()
9263 :
9264 : {
9265 : static int bInitIsOk = TRUE;
9266 : static int bOneTimeInitDone = FALSE;
9267 : static void* hMutex = NULL;
9268 10034 : CPLMutexHolder oHolder( &hMutex);
9269 10034 : if( bOneTimeInitDone )
9270 9174 : return bInitIsOk;
9271 :
9272 860 : bOneTimeInitDone = TRUE;
9273 :
9274 : /* This is a frequent configuration error that is difficult to track down */
9275 : /* for people unaware of the issue : GDAL built against internal libtiff (4.X) */
9276 : /* but used by an application that links with external libtiff (3.X) */
9277 : /* Note: on my conf, the order that cause GDAL to crash - and that is detected */
9278 : /* by the following code - is "-ltiff -lgdal". "-lgdal -ltiff" works for the */
9279 : /* GTiff driver but probably breaks the application that believes it uses libtiff 3.X */
9280 : /* but we cannot detect that... */
9281 : #if defined(BIGTIFF_SUPPORT) && !defined(RENAME_INTERNAL_LIBTIFF_SYMBOLS)
9282 : #if defined(HAVE_DLFCN_H) && !defined(WIN32)
9283 : const char* (*pfnVersion)(void);
9284 : pfnVersion = (const char* (*)(void)) dlsym(RTLD_DEFAULT, "TIFFGetVersion");
9285 : if (pfnVersion)
9286 : {
9287 : const char* pszVersion = pfnVersion();
9288 : if (pszVersion && strstr(pszVersion, "Version 3.") != NULL)
9289 : {
9290 : CPLError(CE_Warning, CPLE_AppDefined,
9291 : "libtiff version mismatch : You're linking against libtiff 3.X, but GDAL has been compiled against libtiff >= 4.0.0");
9292 : }
9293 : }
9294 : #endif
9295 : #endif
9296 :
9297 860 : _ParentExtender = TIFFSetTagExtender(GTiffTagExtender);
9298 :
9299 860 : TIFFSetWarningHandler( GTiffWarningHandler );
9300 860 : TIFFSetErrorHandler( GTiffErrorHandler );
9301 :
9302 : // This only really needed if we are linked to an external libgeotiff
9303 : // with its own (lame) file searching logic.
9304 860 : SetCSVFilenameHook( GDALDefaultCSVFilename );
9305 :
9306 860 : return TRUE;
9307 : }
9308 :
9309 : /************************************************************************/
9310 : /* GDALDeregister_GTiff() */
9311 : /************************************************************************/
9312 :
9313 1057 : void GDALDeregister_GTiff( GDALDriver * )
9314 :
9315 : {
9316 1057 : CSVDeaccess( NULL );
9317 :
9318 : #if defined(LIBGEOTIFF_VERSION) && LIBGEOTIFF_VERSION > 1150
9319 1057 : GTIFDeaccessCSV();
9320 : #endif
9321 1057 : }
9322 :
9323 : /************************************************************************/
9324 : /* GTIFFGetCompressionMethod() */
9325 : /************************************************************************/
9326 :
9327 148 : int GTIFFGetCompressionMethod(const char* pszValue, const char* pszVariableName)
9328 : {
9329 148 : int nCompression = COMPRESSION_NONE;
9330 148 : if( EQUAL( pszValue, "NONE" ) )
9331 2 : nCompression = COMPRESSION_NONE;
9332 146 : else if( EQUAL( pszValue, "JPEG" ) )
9333 78 : nCompression = COMPRESSION_JPEG;
9334 68 : else if( EQUAL( pszValue, "LZW" ) )
9335 34 : nCompression = COMPRESSION_LZW;
9336 34 : else if( EQUAL( pszValue, "PACKBITS" ))
9337 4 : nCompression = COMPRESSION_PACKBITS;
9338 56 : else if( EQUAL( pszValue, "DEFLATE" ) || EQUAL( pszValue, "ZIP" ))
9339 26 : nCompression = COMPRESSION_ADOBE_DEFLATE;
9340 4 : else if( EQUAL( pszValue, "FAX3" )
9341 : || EQUAL( pszValue, "CCITTFAX3" ))
9342 0 : nCompression = COMPRESSION_CCITTFAX3;
9343 8 : else if( EQUAL( pszValue, "FAX4" )
9344 : || EQUAL( pszValue, "CCITTFAX4" ))
9345 4 : nCompression = COMPRESSION_CCITTFAX4;
9346 0 : else if( EQUAL( pszValue, "CCITTRLE" ) )
9347 0 : nCompression = COMPRESSION_CCITTRLE;
9348 0 : else if( EQUAL( pszValue, "LZMA" ) )
9349 0 : nCompression = COMPRESSION_LZMA;
9350 : else
9351 : CPLError( CE_Warning, CPLE_IllegalArg,
9352 : "%s=%s value not recognised, ignoring.",
9353 0 : pszVariableName,pszValue );
9354 :
9355 : #if defined(TIFFLIB_VERSION) && TIFFLIB_VERSION > 20031007 /* 3.6.0 */
9356 148 : if (nCompression != COMPRESSION_NONE &&
9357 : !TIFFIsCODECConfigured((uint16) nCompression))
9358 : {
9359 : CPLError( CE_Failure, CPLE_AppDefined,
9360 0 : "Cannot create TIFF file due to missing codec for %s.", pszValue );
9361 0 : return -1;
9362 : }
9363 : #endif
9364 :
9365 148 : return nCompression;
9366 : }
9367 : /************************************************************************/
9368 : /* GDALRegister_GTiff() */
9369 : /************************************************************************/
9370 :
9371 1135 : void GDALRegister_GTiff()
9372 :
9373 : {
9374 1135 : if( GDALGetDriverByName( "GTiff" ) == NULL )
9375 : {
9376 : GDALDriver *poDriver;
9377 : char szCreateOptions[3072];
9378 : char szOptionalCompressItems[500];
9379 1093 : int bHasJPEG = FALSE, bHasLZW = FALSE, bHasDEFLATE = FALSE, bHasLZMA = FALSE;
9380 :
9381 1093 : poDriver = new GDALDriver();
9382 :
9383 : /* -------------------------------------------------------------------- */
9384 : /* Determine which compression codecs are available that we */
9385 : /* want to advertise. If we are using an old libtiff we won't */
9386 : /* be able to find out so we just assume all are available. */
9387 : /* -------------------------------------------------------------------- */
9388 : strcpy( szOptionalCompressItems,
9389 1093 : " <Value>NONE</Value>" );
9390 :
9391 : #if TIFFLIB_VERSION <= 20040919
9392 : strcat( szOptionalCompressItems,
9393 : " <Value>PACKBITS</Value>"
9394 : " <Value>JPEG</Value>"
9395 : " <Value>LZW</Value>"
9396 : " <Value>DEFLATE</Value>" );
9397 : bHasLZW = bHasDEFLATE = TRUE;
9398 : #else
9399 1093 : TIFFCodec *c, *codecs = TIFFGetConfiguredCODECs();
9400 :
9401 19674 : for( c = codecs; c->name; c++ )
9402 : {
9403 18581 : if( c->scheme == COMPRESSION_PACKBITS )
9404 : strcat( szOptionalCompressItems,
9405 1093 : " <Value>PACKBITS</Value>" );
9406 17488 : else if( c->scheme == COMPRESSION_JPEG )
9407 : {
9408 1093 : bHasJPEG = TRUE;
9409 : strcat( szOptionalCompressItems,
9410 1093 : " <Value>JPEG</Value>" );
9411 : }
9412 16395 : else if( c->scheme == COMPRESSION_LZW )
9413 : {
9414 1093 : bHasLZW = TRUE;
9415 : strcat( szOptionalCompressItems,
9416 1093 : " <Value>LZW</Value>" );
9417 : }
9418 15302 : else if( c->scheme == COMPRESSION_ADOBE_DEFLATE )
9419 : {
9420 1093 : bHasDEFLATE = TRUE;
9421 : strcat( szOptionalCompressItems,
9422 1093 : " <Value>DEFLATE</Value>" );
9423 : }
9424 14209 : else if( c->scheme == COMPRESSION_CCITTRLE )
9425 : strcat( szOptionalCompressItems,
9426 1093 : " <Value>CCITTRLE</Value>" );
9427 13116 : else if( c->scheme == COMPRESSION_CCITTFAX3 )
9428 : strcat( szOptionalCompressItems,
9429 1093 : " <Value>CCITTFAX3</Value>" );
9430 12023 : else if( c->scheme == COMPRESSION_CCITTFAX4 )
9431 : strcat( szOptionalCompressItems,
9432 1093 : " <Value>CCITTFAX4</Value>" );
9433 10930 : else if( c->scheme == COMPRESSION_LZMA )
9434 : {
9435 1093 : bHasLZMA = TRUE;
9436 : strcat( szOptionalCompressItems,
9437 1093 : " <Value>LZMA</Value>" );
9438 : }
9439 : }
9440 1093 : _TIFFfree( codecs );
9441 : #endif
9442 :
9443 : /* -------------------------------------------------------------------- */
9444 : /* Build full creation option list. */
9445 : /* -------------------------------------------------------------------- */
9446 : sprintf( szCreateOptions, "%s%s%s",
9447 : "<CreationOptionList>"
9448 : " <Option name='COMPRESS' type='string-select'>",
9449 : szOptionalCompressItems,
9450 1093 : " </Option>");
9451 1093 : if (bHasLZW || bHasDEFLATE)
9452 : strcat( szCreateOptions, ""
9453 1093 : " <Option name='PREDICTOR' type='int' description='Predictor Type'/>");
9454 1093 : if (bHasJPEG)
9455 : {
9456 : strcat( szCreateOptions, ""
9457 1093 : " <Option name='JPEG_QUALITY' type='int' description='JPEG quality 1-100' default='75'/>" );
9458 : #ifdef JPEG_DIRECT_COPY
9459 : strcat( szCreateOptions, ""
9460 : " <Option name='JPEG_DIRECT_COPY' type='boolean' description='To copy without any decompression/recompression a JPEG source file' default='NO'/>");
9461 : #endif
9462 : }
9463 1093 : if (bHasDEFLATE)
9464 : strcat( szCreateOptions, ""
9465 1093 : " <Option name='ZLEVEL' type='int' description='DEFLATE compression level 1-9' default='6'/>");
9466 1093 : if (bHasLZMA)
9467 : strcat( szCreateOptions, ""
9468 1093 : " <Option name='LZMA_PRESET' type='int' description='LZMA compression level 0(fast)-9(slow)' default='6'/>");
9469 : strcat( szCreateOptions, ""
9470 : " <Option name='NBITS' type='int' description='BITS for sub-byte files (1-7), sub-uint16 (9-15), sub-uint32 (17-31)'/>"
9471 : " <Option name='INTERLEAVE' type='string-select' default='PIXEL'>"
9472 : " <Value>BAND</Value>"
9473 : " <Value>PIXEL</Value>"
9474 : " </Option>"
9475 : " <Option name='TILED' type='boolean' description='Switch to tiled format'/>"
9476 : " <Option name='TFW' type='boolean' description='Write out world file'/>"
9477 : " <Option name='RPB' type='boolean' description='Write out .RPB (RPC) file'/>"
9478 : " <Option name='BLOCKXSIZE' type='int' description='Tile Width'/>"
9479 : " <Option name='BLOCKYSIZE' type='int' description='Tile/Strip Height'/>"
9480 : " <Option name='PHOTOMETRIC' type='string-select'>"
9481 : " <Value>MINISBLACK</Value>"
9482 : " <Value>MINISWHITE</Value>"
9483 : " <Value>PALETTE</Value>"
9484 : " <Value>RGB</Value>"
9485 : " <Value>CMYK</Value>"
9486 : " <Value>YCBCR</Value>"
9487 : " <Value>CIELAB</Value>"
9488 : " <Value>ICCLAB</Value>"
9489 : " <Value>ITULAB</Value>"
9490 : " </Option>"
9491 : " <Option name='SPARSE_OK' type='boolean' description='Can newly created files have missing blocks?' default='FALSE'/>"
9492 : " <Option name='ALPHA' type='boolean' description='Mark first extrasample as being alpha'/>"
9493 : " <Option name='PROFILE' type='string-select' default='GDALGeoTIFF'>"
9494 : " <Value>GDALGeoTIFF</Value>"
9495 : " <Value>GeoTIFF</Value>"
9496 : " <Value>BASELINE</Value>"
9497 : " </Option>"
9498 : " <Option name='PIXELTYPE' type='string-select'>"
9499 : " <Value>DEFAULT</Value>"
9500 : " <Value>SIGNEDBYTE</Value>"
9501 : " </Option>"
9502 : #ifdef BIGTIFF_SUPPORT
9503 : " <Option name='BIGTIFF' type='string-select' description='Force creation of BigTIFF file'>"
9504 : " <Value>YES</Value>"
9505 : " <Value>NO</Value>"
9506 : " <Value>IF_NEEDED</Value>"
9507 : " <Value>IF_SAFER</Value>"
9508 : " </Option>"
9509 : #endif
9510 : " <Option name='ENDIANNESS' type='string-select' default='NATIVE' description='Force endianness of created file. For DEBUG purpose mostly'>"
9511 : " <Value>NATIVE</Value>"
9512 : " <Value>INVERTED</Value>"
9513 : " <Value>LITTLE</Value>"
9514 : " <Value>BIG</Value>"
9515 : " </Option>"
9516 : " <Option name='COPY_SRC_OVERVIEWS' type='boolean' default='NO' description='Force copy of overviews of source dataset (CreateCopy())'/>"
9517 1093 : "</CreationOptionList>" );
9518 :
9519 : /* -------------------------------------------------------------------- */
9520 : /* Set the driver details. */
9521 : /* -------------------------------------------------------------------- */
9522 1093 : poDriver->SetDescription( "GTiff" );
9523 1093 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "GeoTIFF" );
9524 1093 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_gtiff.html" );
9525 1093 : poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/tiff" );
9526 1093 : poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "tif" );
9527 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
9528 : "Byte UInt16 Int16 UInt32 Int32 Float32 "
9529 1093 : "Float64 CInt16 CInt32 CFloat32 CFloat64" );
9530 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
9531 1093 : szCreateOptions );
9532 :
9533 1093 : poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
9534 :
9535 1093 : poDriver->pfnOpen = GTiffDataset::Open;
9536 1093 : poDriver->pfnCreate = GTiffDataset::Create;
9537 1093 : poDriver->pfnCreateCopy = GTiffDataset::CreateCopy;
9538 1093 : poDriver->pfnUnloadDriver = GDALDeregister_GTiff;
9539 1093 : poDriver->pfnIdentify = GTiffDataset::Identify;
9540 :
9541 1093 : GetGDALDriverManager()->RegisterDriver( poDriver );
9542 : }
9543 1135 : }
|