27
27
* DEALINGS IN THE SOFTWARE.
28
28
****************************************************************************/
30
/* If we use sunpro compiler on linux. Weird idea indeed ! */
31
#if defined(__SUNPRO_CC) && defined(__linux__)
33
#elif defined(__GNUC__) && !defined(_GNU_SOURCE)
34
/* Required to use RTLD_DEFAULT of dlfcn.h */
30
38
#include "gdal_pam.h"
31
39
#define CPL_SERV_H_INCLUDED
34
41
#include "xtiffio.h"
36
#include "geo_normalize.h"
37
42
#include "geovalues.h"
38
43
#include "cpl_string.h"
39
44
#include "cpl_csv.h"
40
45
#include "cpl_minixml.h"
41
46
#include "gt_overview.h"
42
47
#include "ogr_spatialref.h"
44
CPL_CVSID("$Id: geotiff.cpp 20144 2010-07-27 21:09:41Z rouault $");
47
char CPL_DLL * GTIFGetOGISDefn( GTIF *, GTIFDefn * );
48
int CPL_DLL GTIFSetFromOGISDefn( GTIF *, const char * );
49
const char * GDALDefaultCSVFilename( const char *pszBasename );
50
GUInt32 HalfToFloat( GUInt16 );
51
GUInt32 TripleToFloat( GUInt32 );
52
void GTiffOneTimeInit();
55
#define TIFFTAG_GDAL_METADATA 42112
56
#define TIFFTAG_GDAL_NODATA 42113
57
#define TIFFTAG_RPCCOEFFICIENT 50844
59
#if TIFFLIB_VERSION >= 20081217 && defined(BIGTIFF_SUPPORT)
60
# define HAVE_UNSETFIELD
63
TIFF* VSI_TIFFOpen(const char* name, const char* mode);
48
#include "tif_float.h"
51
#include "gt_wkt_srs.h"
53
#include "cpl_multiproc.h"
55
CPL_CVSID("$Id: geotiff.cpp 23561 2011-12-13 05:47:58Z warmerdam $");
57
/************************************************************************/
58
/* ==================================================================== */
60
/* ==================================================================== */
61
/************************************************************************/
63
/* GDALOverviewDS is not specific to GTiff and could probably be moved */
64
/* in gcore. It is currently used to generate a fake */
65
/* dataset from the overview levels of the source dataset that is taken */
68
#include "gdal_proxy.h"
70
class GDALOverviewBand;
72
class GDALOverviewDS : public GDALDataset
76
friend class GDALOverviewBand;
83
GDALOverviewDS(GDALDataset* poDS, int nOvrLevel);
84
virtual ~GDALOverviewDS();
86
virtual char **GetMetadata( const char * pszDomain = "" );
87
virtual const char *GetMetadataItem( const char * pszName,
88
const char * pszDomain = "" );
91
class GDALOverviewBand : public GDALProxyRasterBand
94
GDALRasterBand* poUnderlyingBand;
95
virtual GDALRasterBand* RefUnderlyingRasterBand();
98
GDALOverviewBand(GDALOverviewDS* poDS, int nBand);
99
virtual ~GDALOverviewBand();
102
GDALOverviewDS::GDALOverviewDS(GDALDataset* poDS, int nOvrLevel)
105
this->nOvrLevel = nOvrLevel;
106
eAccess = poDS->GetAccess();
107
nRasterXSize = poDS->GetRasterBand(1)->GetOverview(nOvrLevel)->GetXSize();
108
nRasterYSize = poDS->GetRasterBand(1)->GetOverview(nOvrLevel)->GetYSize();
109
poOvrDS = poDS->GetRasterBand(1)->GetOverview(nOvrLevel)->GetDataset();
110
nBands = poDS->GetRasterCount();
112
for(i=0;i<nBands;i++)
113
SetBand(i+1, new GDALOverviewBand(this, i+1));
116
GDALOverviewDS::~GDALOverviewDS()
121
char **GDALOverviewDS::GetMetadata( const char * pszDomain )
124
return poOvrDS->GetMetadata(pszDomain);
126
return poDS->GetMetadata(pszDomain);
129
const char *GDALOverviewDS::GetMetadataItem( const char * pszName, const char * pszDomain )
132
return poOvrDS->GetMetadataItem(pszName, pszDomain);
134
return poDS->GetMetadataItem(pszName, pszDomain);
137
GDALOverviewBand::GDALOverviewBand(GDALOverviewDS* poDS, int nBand)
141
poUnderlyingBand = poDS->poDS->GetRasterBand(nBand)->GetOverview(poDS->nOvrLevel);
142
nRasterXSize = poDS->nRasterXSize;
143
nRasterYSize = poDS->nRasterYSize;
144
eDataType = poUnderlyingBand->GetRasterDataType();
145
poUnderlyingBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
148
GDALOverviewBand::~GDALOverviewBand()
153
GDALRasterBand* GDALOverviewBand::RefUnderlyingRasterBand()
155
return poUnderlyingBand;
158
/************************************************************************/
160
/************************************************************************/
162
static int IsPowerOfTwo(unsigned int i)
174
/************************************************************************/
175
/* GTIFFGetOverviewBlockSize() */
176
/************************************************************************/
178
void GTIFFGetOverviewBlockSize(int* pnBlockXSize, int* pnBlockYSize)
180
static int bHasWarned = FALSE;
181
const char* pszVal = CPLGetConfigOption("GDAL_TIFF_OVR_BLOCKSIZE", "128");
182
int nOvrBlockSize = atoi(pszVal);
183
if (nOvrBlockSize < 64 || nOvrBlockSize > 4096 ||
184
!IsPowerOfTwo(nOvrBlockSize))
188
CPLError(CE_Warning, CPLE_NotSupported,
189
"Wrong value for GDAL_TIFF_OVR_BLOCKSIZE : %s. "
190
"Should be a power of 2 between 64 and 4096. Defaulting to 128",
197
*pnBlockXSize = nOvrBlockSize;
198
*pnBlockYSize = nOvrBlockSize;
474
674
/************************************************************************/
676
/************************************************************************/
678
/* Reads directly bytes from the file using ReadMultiRange(), and by-pass */
679
/* block reading. Restricted to simple TIFF configurations (single-band, un-tiled, */
680
/* uncompressed data, standard data types). Particularly usefull to extract */
681
/* sub-windows of data on a large /vsicurl dataset). */
683
CPLErr GTiffRasterBand::DirectIO( GDALRWFlag eRWFlag,
684
int nXOff, int nYOff, int nXSize, int nYSize,
685
void * pData, int nBufXSize, int nBufYSize,
686
GDALDataType eBufType,
687
int nPixelSpace, int nLineSpace )
689
if( !(eRWFlag == GF_Read && poGDS->nBands == 1 &&
690
poGDS->nCompression == COMPRESSION_NONE &&
691
(poGDS->nBitsPerSample == 8 || (poGDS->nBitsPerSample == 16) ||
692
poGDS->nBitsPerSample == 32 || poGDS->nBitsPerSample == 64) &&
693
poGDS->nBitsPerSample == GDALGetDataTypeSize(eDataType) &&
694
!TIFFIsTiled( poGDS->hTIFF )) )
699
/* ==================================================================== */
700
/* Do we have overviews that would be appropriate to satisfy */
702
/* ==================================================================== */
703
if( (nBufXSize < nXSize || nBufYSize < nYSize)
704
&& GetOverviewCount() > 0 && eRWFlag == GF_Read )
709
GDALBandGetBestOverviewLevel(this, nXOff, nYOff, nXSize, nYSize,
710
nBufXSize, nBufYSize);
713
GDALRasterBand* poOverviewBand = GetOverview(nOverview);
714
if (poOverviewBand == NULL)
717
return poOverviewBand->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
718
pData, nBufXSize, nBufYSize, eBufType,
719
nPixelSpace, nLineSpace );
723
/* Make sure that TIFFTAG_STRIPOFFSETS is up-to-date */
724
if (poGDS->GetAccess() == GA_Update)
727
/* Get strip offsets */
728
toff_t *panTIFFOffsets = NULL;
729
if ( !TIFFGetField( poGDS->hTIFF, TIFFTAG_STRIPOFFSETS, &panTIFFOffsets ) ||
730
panTIFFOffsets == NULL )
736
int nReqXSize = nXSize; /* sub-sampling or over-sampling can only be done at last stage */
737
int nReqYSize = MIN(nBufYSize, nYSize); /* we can do sub-sampling at the extraction stage */
738
void** ppData = (void**) VSIMalloc(nReqYSize * sizeof(void*));
739
vsi_l_offset* panOffsets = (vsi_l_offset*)
740
VSIMalloc(nReqYSize * sizeof(vsi_l_offset));
741
size_t* panSizes = (size_t*) VSIMalloc(nReqYSize * sizeof(size_t));
742
int eDTSize = GDALGetDataTypeSize(eDataType) / 8;
743
void* pTmpBuffer = NULL;
744
CPLErr eErr = CE_None;
746
if (ppData == NULL || panOffsets == NULL || panSizes == NULL)
748
else if (nXSize != nBufXSize || nYSize != nBufYSize ||
749
eBufType != eDataType ||
750
nPixelSpace != GDALGetDataTypeSize(eBufType) / 8)
752
/* We need a temporary buffer for over-sampling/sub-sampling */
753
/* and/or data type conversion */
754
pTmpBuffer = VSIMalloc(nReqXSize * nReqYSize * eDTSize);
755
if (pTmpBuffer == NULL)
759
/* Prepare data extraction */
760
for(iLine=0;eErr == CE_None && iLine<nReqYSize;iLine++)
762
if (pTmpBuffer == NULL)
763
ppData[iLine] = ((GByte*)pData) + iLine * nLineSpace;
765
ppData[iLine] = ((GByte*)pTmpBuffer) + iLine * nReqXSize * eDTSize;
767
if (nBufYSize < nYSize) /* Sub-sampling in y */
768
nSrcLine = nYOff + (int)((iLine + 0.5) * nYSize / nBufYSize);
770
nSrcLine = nYOff + iLine;
771
panOffsets[iLine] = panTIFFOffsets[nSrcLine / nBlockYSize];
772
if (panOffsets[iLine] == 0) /* We don't support sparse files */
775
panOffsets[iLine] += (nXOff + (nSrcLine % nBlockYSize) * nBlockXSize) * eDTSize;
776
panSizes[iLine] = nReqXSize * eDTSize;
779
/* Extract data from the file */
782
VSILFILE* fp = (VSILFILE*) TIFFClientdata( poGDS->hTIFF );
783
int nRet = VSIFReadMultiRangeL(nReqYSize, ppData, panOffsets, panSizes, fp);
788
/* Byte-swap if necessary */
789
if (eErr == CE_None && TIFFIsByteSwapped(poGDS->hTIFF))
791
for(iLine=0;iLine<nReqYSize;iLine++)
793
GDALSwapWords( ppData[iLine], eDTSize, nReqXSize, eDTSize);
797
/* Over-sampling/sub-sampling and/or data type conversion */
798
if (eErr == CE_None && pTmpBuffer != NULL)
800
for(int iY=0;iY<nBufYSize;iY++)
802
int iSrcY = (nBufYSize <= nYSize) ? iY :
803
(int)((iY + 0.5) * nYSize / nBufYSize);
804
if (nBufXSize == nXSize)
806
GDALCopyWords( ppData[iSrcY], eDataType, eDTSize,
807
((GByte*)pData) + iY * nLineSpace,
808
eBufType, nPixelSpace,
813
for(int iX=0;iX<nBufXSize;iX++)
815
int iSrcX = (nBufXSize == nXSize) ? iX :
816
(int)((iX+0.5) * nXSize / nBufXSize);
817
GDALCopyWords( ((GByte*)ppData[iSrcY]) + iSrcX * eDTSize,
819
((GByte*)pData) + iX * nPixelSpace + iY * nLineSpace,
835
/************************************************************************/
837
/************************************************************************/
839
CPLErr GTiffRasterBand::IRasterIO( GDALRWFlag eRWFlag,
840
int nXOff, int nYOff, int nXSize, int nYSize,
841
void * pData, int nBufXSize, int nBufYSize,
842
GDALDataType eBufType,
843
int nPixelSpace, int nLineSpace )
847
//CPLDebug("GTiff", "RasterIO(%d, %d, %d, %d, %d, %d)",
848
// nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize);
850
if (poGDS->bDirectIO)
852
eErr = DirectIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
853
pData, nBufXSize, nBufYSize, eBufType,
854
nPixelSpace, nLineSpace);
860
if (poGDS->nBands != 1 &&
861
poGDS->nPlanarConfig == PLANARCONFIG_CONTIG &&
862
eRWFlag == GF_Read &&
863
nXSize == nBufXSize && nYSize == nBufYSize)
865
int nBlockX1 = nXOff / nBlockXSize;
866
int nBlockY1 = nYOff / nBlockYSize;
867
int nBlockX2 = (nXOff + nXSize - 1) / nBlockXSize;
868
int nBlockY2 = (nYOff + nYSize - 1) / nBlockYSize;
869
int nXBlocks = nBlockX2 - nBlockX1 + 1;
870
int nYBlocks = nBlockY2 - nBlockY1 + 1;
871
GIntBig nRequiredMem = (GIntBig)poGDS->nBands * nXBlocks * nYBlocks *
872
nBlockXSize * nBlockYSize *
873
(GDALGetDataTypeSize(eDataType) / 8);
874
if (nRequiredMem > GDALGetCacheMax64())
876
if (!poGDS->bHasWarnedDisableAggressiveBandCaching)
878
CPLDebug("GTiff", "Disable aggressive band caching. Cache not big enough. "
879
"At least " CPL_FRMT_GIB " bytes necessary", nRequiredMem);
880
poGDS->bHasWarnedDisableAggressiveBandCaching = TRUE;
882
poGDS->bLoadingOtherBands = TRUE;
886
eErr = GDALPamRasterBand::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
887
pData, nBufXSize, nBufYSize, eBufType,
888
nPixelSpace, nLineSpace);
890
poGDS->bLoadingOtherBands = FALSE;
895
/************************************************************************/
475
896
/* IReadBlock() */
476
897
/************************************************************************/
2548
3236
/* WriteEncodedTile() */
2549
3237
/************************************************************************/
2551
int GTiffDataset::WriteEncodedTile(uint32 tile, void* data,
3239
int GTiffDataset::WriteEncodedTile(uint32 tile, GByte *pabyData,
2552
3240
int bPreserveDataBuffer)
2554
/* TIFFWriteEncodedTile can alter the passed buffer if byte-swapping is necessary */
2555
/* so we use a temporary buffer before calling it */
2556
3242
int cc = TIFFTileSize( hTIFF );
2557
if (bPreserveDataBuffer && TIFFIsByteSwapped(hTIFF))
3243
int bNeedTileFill = FALSE;
3244
int iRow=0, iColumn=0;
3245
int nBlocksPerRow=1, nBlocksPerColumn=1;
3248
** Do we need to spread edge values right or down for a partial
3249
** JPEG encoded tile? We do this to avoid edge artifacts.
3251
if( nCompression == COMPRESSION_JPEG )
3253
nBlocksPerRow = (nRasterXSize + nBlockXSize - 1) / nBlockXSize;
3254
nBlocksPerColumn = (nRasterYSize + nBlockYSize - 1) / nBlockYSize;
3256
iColumn = (tile % nBlocksPerBand) % nBlocksPerRow;
3257
iRow = (tile % nBlocksPerBand) / nBlocksPerRow;
3259
// Is this a partial right edge tile?
3260
if( iRow == nBlocksPerRow - 1
3261
&& nRasterXSize % nBlockXSize != 0 )
3262
bNeedTileFill = TRUE;
3264
// Is this a partial bottom edge tile?
3265
if( iColumn == nBlocksPerColumn - 1
3266
&& nRasterYSize % nBlockYSize != 0 )
3267
bNeedTileFill = TRUE;
3271
** If we need to fill out the tile, or if we want to prevent
3272
** TIFFWriteEncodedTile from altering the buffer as part of
3273
** byte swapping the data on write then we will need a temporary
3274
** working buffer. If not, we can just do a direct write.
3276
if (bPreserveDataBuffer
3277
&& (TIFFIsByteSwapped(hTIFF) || bNeedTileFill) )
2559
3279
if (cc != nTempWriteBufferSize)
2561
3281
pabyTempWriteBuffer = CPLRealloc(pabyTempWriteBuffer, cc);
2562
3282
nTempWriteBufferSize = cc;
2564
memcpy(pabyTempWriteBuffer, data, cc);
2565
return TIFFWriteEncodedTile(hTIFF, tile, pabyTempWriteBuffer, cc);
2568
return TIFFWriteEncodedTile(hTIFF, tile, data, cc);
3284
memcpy(pabyTempWriteBuffer, pabyData, cc);
3286
pabyData = (GByte *) pabyTempWriteBuffer;
3290
** Perform tile fill if needed.
3294
int nRightPixelsToFill = 0;
3295
int nBottomPixelsToFill = 0;
3296
int nPixelSize = cc / (nBlockXSize * nBlockYSize);
3297
unsigned int iX, iY, iSrcX, iSrcY;
3299
CPLDebug( "GTiff", "Filling out jpeg edge tile on write." );
3301
if( iColumn == nBlocksPerRow - 1 )
3302
nRightPixelsToFill = nBlockXSize * (iColumn+1) - nRasterXSize;
3303
if( iRow == nBlocksPerColumn - 1 )
3304
nBottomPixelsToFill = nBlockYSize * (iRow+1) - nRasterYSize;
3306
// Fill out to the right.
3307
iSrcX = nBlockXSize - nRightPixelsToFill - 1;
3309
for( iX = iSrcX+1; iX < nBlockXSize; iX++ )
3311
for( iY = 0; iY < nBlockYSize; iY++ )
3313
memcpy( pabyData + (nBlockXSize * iY + iX) * nPixelSize,
3314
pabyData + (nBlockXSize * iY + iSrcX) * nPixelSize,
3319
// now fill out the bottom.
3320
iSrcY = nBlockYSize - nBottomPixelsToFill - 1;
3321
for( iY = iSrcY+1; iY < nBlockYSize; iY++ )
3323
memcpy( pabyData + nBlockXSize * nPixelSize * iY,
3324
pabyData + nBlockXSize * nPixelSize * iSrcY,
3325
nPixelSize * nBlockXSize );
3329
return TIFFWriteEncodedTile(hTIFF, tile, pabyData, cc);
2571
3332
/************************************************************************/
2572
3333
/* WriteEncodedStrip() */
2573
3334
/************************************************************************/
2575
int GTiffDataset::WriteEncodedStrip(uint32 strip, void* data,
3336
int GTiffDataset::WriteEncodedStrip(uint32 strip, GByte* pabyData,
2576
3337
int bPreserveDataBuffer)
2578
3339
int cc = TIFFStripSize( hTIFF );
3073
3864
return CE_None;
3868
/************************************************************************/
3869
/* RegisterNewOverviewDataset() */
3870
/************************************************************************/
3872
CPLErr GTiffDataset::RegisterNewOverviewDataset(toff_t nOverviewOffset)
3874
GTiffDataset* poODS = new GTiffDataset();
3875
poODS->nJpegQuality = nJpegQuality;
3876
poODS->nZLevel = nZLevel;
3877
poODS->nLZMAPreset = nLZMAPreset;
3879
if( nCompression == COMPRESSION_JPEG )
3881
if ( CPLGetConfigOption( "JPEG_QUALITY_OVERVIEW", NULL ) != NULL )
3883
poODS->nJpegQuality = atoi(CPLGetConfigOption("JPEG_QUALITY_OVERVIEW","75"));
3885
TIFFSetField( hTIFF, TIFFTAG_JPEGQUALITY,
3886
poODS->nJpegQuality );
3889
if( poODS->OpenOffset( hTIFF, ppoActiveDSRef, nOverviewOffset, FALSE,
3890
GA_Update ) != CE_None )
3898
papoOverviewDS = (GTiffDataset **)
3899
CPLRealloc(papoOverviewDS,
3900
nOverviewCount * (sizeof(void*)));
3901
papoOverviewDS[nOverviewCount-1] = poODS;
3902
poODS->poBaseDS = this;
3907
/************************************************************************/
3908
/* CreateOverviewsFromSrcOverviews() */
3909
/************************************************************************/
3911
CPLErr GTiffDataset::CreateOverviewsFromSrcOverviews(GDALDataset* poSrcDS)
3913
CPLAssert(poSrcDS->GetRasterCount() != 0);
3914
CPLAssert(nOverviewCount == 0);
3918
/* -------------------------------------------------------------------- */
3919
/* Move to the directory for this dataset. */
3920
/* -------------------------------------------------------------------- */
3921
if (!SetDirectory())
3925
int nOvBitsPerSample = nBitsPerSample;
3927
/* -------------------------------------------------------------------- */
3928
/* Do we have a palette? If so, create a TIFF compatible version. */
3929
/* -------------------------------------------------------------------- */
3930
std::vector<unsigned short> anTRed, anTGreen, anTBlue;
3931
unsigned short *panRed=NULL, *panGreen=NULL, *panBlue=NULL;
3933
if( nPhotometric == PHOTOMETRIC_PALETTE && poColorTable != NULL )
3937
if( nOvBitsPerSample == 8 )
3939
else if( nOvBitsPerSample < 8 )
3940
nColors = 1 << nOvBitsPerSample;
3944
anTRed.resize(nColors,0);
3945
anTGreen.resize(nColors,0);
3946
anTBlue.resize(nColors,0);
3948
for( int iColor = 0; iColor < nColors; iColor++ )
3950
if( iColor < poColorTable->GetColorEntryCount() )
3952
GDALColorEntry sRGB;
3954
poColorTable->GetColorEntryAsRGB( iColor, &sRGB );
3956
anTRed[iColor] = (unsigned short) (256 * sRGB.c1);
3957
anTGreen[iColor] = (unsigned short) (256 * sRGB.c2);
3958
anTBlue[iColor] = (unsigned short) (256 * sRGB.c3);
3962
anTRed[iColor] = anTGreen[iColor] = anTBlue[iColor] = 0;
3966
panRed = &(anTRed[0]);
3967
panGreen = &(anTGreen[0]);
3968
panBlue = &(anTBlue[0]);
3971
/* -------------------------------------------------------------------- */
3972
/* Do we need some metadata for the overviews? */
3973
/* -------------------------------------------------------------------- */
3974
CPLString osMetadata;
3976
GTIFFBuildOverviewMetadata( "NONE", this, osMetadata );
3978
/* -------------------------------------------------------------------- */
3979
/* Fetch extra sample tag */
3980
/* -------------------------------------------------------------------- */
3981
uint16 *panExtraSampleValues = NULL;
3982
uint16 nExtraSamples = 0;
3984
if( TIFFGetField( hTIFF, TIFFTAG_EXTRASAMPLES, &nExtraSamples, &panExtraSampleValues) )
3986
uint16* panExtraSampleValuesNew = (uint16*) CPLMalloc(nExtraSamples * sizeof(uint16));
3987
memcpy(panExtraSampleValuesNew, panExtraSampleValues, nExtraSamples * sizeof(uint16));
3988
panExtraSampleValues = panExtraSampleValuesNew;
3992
panExtraSampleValues = NULL;
3996
/* -------------------------------------------------------------------- */
3997
/* Fetch predictor tag */
3998
/* -------------------------------------------------------------------- */
3999
uint16 nPredictor = PREDICTOR_NONE;
4000
if ( nCompression == COMPRESSION_LZW ||
4001
nCompression == COMPRESSION_ADOBE_DEFLATE )
4002
TIFFGetField( hTIFF, TIFFTAG_PREDICTOR, &nPredictor );
4003
int nOvrBlockXSize, nOvrBlockYSize;
4004
GTIFFGetOverviewBlockSize(&nOvrBlockXSize, &nOvrBlockYSize);
4006
int nSrcOverviews = poSrcDS->GetRasterBand(1)->GetOverviewCount();
4008
CPLErr eErr = CE_None;
4010
for(i=0;i<nSrcOverviews && eErr == CE_None;i++)
4012
GDALRasterBand* poOvrBand = poSrcDS->GetRasterBand(1)->GetOverview(i);
4014
int nOXSize = poOvrBand->GetXSize(), nOYSize = poOvrBand->GetYSize();
4016
toff_t nOverviewOffset =
4017
GTIFFWriteDirectory(hTIFF, FILETYPE_REDUCEDIMAGE,
4019
nOvBitsPerSample, nPlanarConfig,
4020
nSamplesPerPixel, nOvrBlockXSize, nOvrBlockYSize, TRUE,
4021
nCompression, nPhotometric, nSampleFormat,
4023
panRed, panGreen, panBlue,
4024
nExtraSamples, panExtraSampleValues,
4027
if( nOverviewOffset == 0 )
4030
eErr = RegisterNewOverviewDataset(nOverviewOffset);
4033
CPLFree(panExtraSampleValues);
4034
panExtraSampleValues = NULL;
4036
/* -------------------------------------------------------------------- */
4037
/* Create overviews for the mask. */
4038
/* -------------------------------------------------------------------- */
4039
if (eErr == CE_None)
4040
eErr = CreateInternalMaskOverviews(nOvrBlockXSize, nOvrBlockYSize);
4046
/************************************************************************/
4047
/* CreateInternalMaskOverviews() */
4048
/************************************************************************/
4050
CPLErr GTiffDataset::CreateInternalMaskOverviews(int nOvrBlockXSize,
4053
GTiffDataset *poODS;
4057
/* -------------------------------------------------------------------- */
4058
/* Create overviews for the mask. */
4059
/* -------------------------------------------------------------------- */
4060
CPLErr eErr = CE_None;
4062
if (poMaskDS != NULL &&
4063
poMaskDS->GetRasterCount() == 1 &&
4064
CSLTestBoolean(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK", "NO")))
4066
int nMaskOvrCompression;
4067
if( strstr(GDALGetMetadataItem(GDALGetDriverByName( "GTiff" ),
4068
GDAL_DMD_CREATIONOPTIONLIST, NULL ),
4069
"<Value>DEFLATE</Value>") != NULL )
4070
nMaskOvrCompression = COMPRESSION_ADOBE_DEFLATE;
4072
nMaskOvrCompression = COMPRESSION_PACKBITS;
4075
for( i = 0; i < nOverviewCount; i++ )
4077
if (papoOverviewDS[i]->poMaskDS == NULL)
4079
toff_t nOverviewOffset;
4082
GTIFFWriteDirectory(hTIFF, FILETYPE_REDUCEDIMAGE | FILETYPE_MASK,
4083
papoOverviewDS[i]->nRasterXSize, papoOverviewDS[i]->nRasterYSize,
4084
1, PLANARCONFIG_CONTIG,
4085
1, nOvrBlockXSize, nOvrBlockYSize, TRUE,
4086
nMaskOvrCompression, PHOTOMETRIC_MASK, SAMPLEFORMAT_UINT, PREDICTOR_NONE,
4087
NULL, NULL, NULL, 0, NULL,
4090
if( nOverviewOffset == 0 )
4096
poODS = new GTiffDataset();
4097
if( poODS->OpenOffset( hTIFF, ppoActiveDSRef,
4098
nOverviewOffset, FALSE,
4099
GA_Update ) != CE_None )
4106
poODS->bPromoteTo8Bits = CSLTestBoolean(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK_TO_8BIT", "YES"));
4107
poODS->poBaseDS = this;
4108
papoOverviewDS[i]->poMaskDS = poODS;
4109
poMaskDS->nOverviewCount++;
4110
poMaskDS->papoOverviewDS = (GTiffDataset **)
4111
CPLRealloc(poMaskDS->papoOverviewDS,
4112
poMaskDS->nOverviewCount * (sizeof(void*)));
4113
poMaskDS->papoOverviewDS[poMaskDS->nOverviewCount-1] = poODS;
3076
4122
/************************************************************************/
3077
4123
/* IBuildOverviews() */
3078
4124
/************************************************************************/
3567
4592
/* Write the transform. If we have a normal north-up image we */
3568
4593
/* use the tiepoint plus pixelscale otherwise we use a matrix. */
3569
4594
/* -------------------------------------------------------------------- */
3570
if( adfGeoTransform[2] == 0.0 && adfGeoTransform[4] == 0.0
3571
&& adfGeoTransform[5] < 0.0 )
3573
double adfPixelScale[3], adfTiePoints[6];
4595
if( adfGeoTransform[2] == 0.0 && adfGeoTransform[4] == 0.0
4596
&& adfGeoTransform[5] < 0.0 )
4598
double adfPixelScale[3], adfTiePoints[6];
3575
adfPixelScale[0] = adfGeoTransform[1];
3576
adfPixelScale[1] = fabs(adfGeoTransform[5]);
3577
adfPixelScale[2] = 0.0;
4600
adfPixelScale[0] = adfGeoTransform[1];
4601
adfPixelScale[1] = fabs(adfGeoTransform[5]);
4602
adfPixelScale[2] = 0.0;
3579
4604
if( !EQUAL(osProfile,"BASELINE") )
3580
4605
TIFFSetField( hTIFF, TIFFTAG_GEOPIXELSCALE, 3, adfPixelScale );
3582
adfTiePoints[0] = 0.0;
3583
adfTiePoints[1] = 0.0;
3584
adfTiePoints[2] = 0.0;
3585
adfTiePoints[3] = adfGeoTransform[0];
3586
adfTiePoints[4] = adfGeoTransform[3];
3587
adfTiePoints[5] = 0.0;
4607
adfTiePoints[0] = 0.0;
4608
adfTiePoints[1] = 0.0;
4609
adfTiePoints[2] = 0.0;
4610
adfTiePoints[3] = adfGeoTransform[0];
4611
adfTiePoints[4] = adfGeoTransform[3];
4612
adfTiePoints[5] = 0.0;
4614
if( bPixelIsPoint && !bPointGeoIgnore )
4616
adfTiePoints[3] += adfGeoTransform[1] * 0.5 + adfGeoTransform[2] * 0.5;
4617
adfTiePoints[4] += adfGeoTransform[4] * 0.5 + adfGeoTransform[5] * 0.5;
3589
4620
if( !EQUAL(osProfile,"BASELINE") )
3590
4621
TIFFSetField( hTIFF, TIFFTAG_GEOTIEPOINTS, 6, adfTiePoints );
3594
double adfMatrix[16];
3596
memset(adfMatrix,0,sizeof(double) * 16);
3598
adfMatrix[0] = adfGeoTransform[1];
3599
adfMatrix[1] = adfGeoTransform[2];
3600
adfMatrix[3] = adfGeoTransform[0];
3601
adfMatrix[4] = adfGeoTransform[4];
3602
adfMatrix[5] = adfGeoTransform[5];
3603
adfMatrix[7] = adfGeoTransform[3];
3604
adfMatrix[15] = 1.0;
4625
double adfMatrix[16];
4627
memset(adfMatrix,0,sizeof(double) * 16);
4629
adfMatrix[0] = adfGeoTransform[1];
4630
adfMatrix[1] = adfGeoTransform[2];
4631
adfMatrix[3] = adfGeoTransform[0];
4632
adfMatrix[4] = adfGeoTransform[4];
4633
adfMatrix[5] = adfGeoTransform[5];
4634
adfMatrix[7] = adfGeoTransform[3];
4635
adfMatrix[15] = 1.0;
4637
if( bPixelIsPoint && !bPointGeoIgnore )
4639
adfMatrix[3] += adfGeoTransform[1] * 0.5 + adfGeoTransform[2] * 0.5;
4640
adfMatrix[7] += adfGeoTransform[4] * 0.5 + adfGeoTransform[5] * 0.5;
3606
4643
if( !EQUAL(osProfile,"BASELINE") )
3607
4644
TIFFSetField( hTIFF, TIFFTAG_GEOTRANSMATRIX, 16, adfMatrix );
3610
4647
// Do we need a world file?
3611
4648
if( CSLFetchBoolean( papszCreationOptions, "TFW", FALSE ) )
5375
6582
/* -------------------------------------------------------------------- */
5378
char **papszSubdatasets = NULL;
5382
while( !TIFFLastDirectory( hTIFF )
5383
&& (iDirIndex == 0 || TIFFReadDirectory( hTIFF ) != 0) )
5385
toff_t nThisDir = TIFFCurrentDirOffset(hTIFF);
5386
uint32 nSubType = 0;
5388
*ppoActiveDSRef = NULL; // our directory no longer matches this ds
5392
if( !TIFFGetField(hTIFF, TIFFTAG_SUBFILETYPE, &nSubType) )
5395
/* Embedded overview of the main image */
5396
if ((nSubType & FILETYPE_REDUCEDIMAGE) != 0 &&
5397
(nSubType & FILETYPE_MASK) == 0 &&
5400
GTiffDataset *poODS;
5402
poODS = new GTiffDataset();
5403
if( poODS->OpenOffset( hTIFF, ppoActiveDSRef, nThisDir, FALSE,
5404
eAccess ) != CE_None
5405
|| poODS->GetRasterCount() != GetRasterCount() )
5411
CPLDebug( "GTiff", "Opened %dx%d overview.\n",
5412
poODS->GetRasterXSize(), poODS->GetRasterYSize());
5414
papoOverviewDS = (GTiffDataset **)
5415
CPLRealloc(papoOverviewDS,
5416
nOverviewCount * (sizeof(void*)));
5417
papoOverviewDS[nOverviewCount-1] = poODS;
5418
poODS->poBaseDS = this;
5422
/* Embedded mask of the main image */
5423
else if ((nSubType & FILETYPE_MASK) != 0 &&
5424
(nSubType & FILETYPE_REDUCEDIMAGE) == 0 &&
5427
poMaskDS = new GTiffDataset();
5429
/* The TIFF6 specification - page 37 - only allows 1 SamplesPerPixel and 1 BitsPerSample
5430
Here we support either 1 or 8 bit per sample
5431
and we support either 1 sample per pixel or as many samples as in the main image
5432
We don't check the value of the PhotometricInterpretation tag, which should be
5433
set to "Transparency mask" (4) according to the specification (page 36)
5434
... But the TIFF6 specification allows image masks to have a higher resolution than
5435
the main image, what we don't support here
5438
if( poMaskDS->OpenOffset( hTIFF, ppoActiveDSRef, nThisDir,
5439
FALSE, eAccess ) != CE_None
5440
|| poMaskDS->GetRasterCount() == 0
5441
|| !(poMaskDS->GetRasterCount() == 1 || poMaskDS->GetRasterCount() == GetRasterCount())
5442
|| poMaskDS->GetRasterXSize() != GetRasterXSize()
5443
|| poMaskDS->GetRasterYSize() != GetRasterYSize()
5444
|| poMaskDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte)
5451
CPLDebug( "GTiff", "Opened band mask.\n");
5452
poMaskDS->poBaseDS = this;
5456
/* Embedded mask of an overview */
5457
/* The TIFF6 specification allows the combination of the FILETYPE_xxxx masks */
5458
else if (nSubType & (FILETYPE_REDUCEDIMAGE | FILETYPE_MASK))
5460
GTiffDataset* poDS = new GTiffDataset();
5461
if( poDS->OpenOffset( hTIFF, ppoActiveDSRef, nThisDir, FALSE,
5462
eAccess ) != CE_None
5463
|| poDS->GetRasterCount() == 0
5464
|| poDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte)
6585
//ScanDirectories();
6591
/************************************************************************/
6592
/* ScanDirectories() */
6594
/* Scan through all the directories finding overviews, masks */
6595
/* and subdatasets. */
6596
/************************************************************************/
6598
void GTiffDataset::ScanDirectories()
6601
/* -------------------------------------------------------------------- */
6602
/* We only scan once. We do not scan for non-base datasets. */
6603
/* -------------------------------------------------------------------- */
6604
if( !bScanDeferred )
6607
bScanDeferred = FALSE;
6612
if( TIFFLastDirectory( hTIFF ) )
6615
CPLDebug( "GTiff", "ScanDirectories()" );
6617
/* ==================================================================== */
6618
/* Scan all directories. */
6619
/* ==================================================================== */
6620
char **papszSubdatasets = NULL;
6624
while( !TIFFLastDirectory( hTIFF )
6625
&& (iDirIndex == 0 || TIFFReadDirectory( hTIFF ) != 0) )
6627
toff_t nThisDir = TIFFCurrentDirOffset(hTIFF);
6628
uint32 nSubType = 0;
6630
*ppoActiveDSRef = NULL; // our directory no longer matches this ds
6634
if( !TIFFGetField(hTIFF, TIFFTAG_SUBFILETYPE, &nSubType) )
6637
/* Embedded overview of the main image */
6638
if ((nSubType & FILETYPE_REDUCEDIMAGE) != 0 &&
6639
(nSubType & FILETYPE_MASK) == 0 &&
6642
GTiffDataset *poODS;
6644
poODS = new GTiffDataset();
6645
if( poODS->OpenOffset( hTIFF, ppoActiveDSRef, nThisDir, FALSE,
6646
eAccess ) != CE_None
6647
|| poODS->GetRasterCount() != GetRasterCount() )
6653
CPLDebug( "GTiff", "Opened %dx%d overview.\n",
6654
poODS->GetRasterXSize(), poODS->GetRasterYSize());
6656
papoOverviewDS = (GTiffDataset **)
6657
CPLRealloc(papoOverviewDS,
6658
nOverviewCount * (sizeof(void*)));
6659
papoOverviewDS[nOverviewCount-1] = poODS;
6660
poODS->poBaseDS = this;
6664
/* Embedded mask of the main image */
6665
else if ((nSubType & FILETYPE_MASK) != 0 &&
6666
(nSubType & FILETYPE_REDUCEDIMAGE) == 0 &&
6669
poMaskDS = new GTiffDataset();
6671
/* The TIFF6 specification - page 37 - only allows 1 SamplesPerPixel and 1 BitsPerSample
6672
Here we support either 1 or 8 bit per sample
6673
and we support either 1 sample per pixel or as many samples as in the main image
6674
We don't check the value of the PhotometricInterpretation tag, which should be
6675
set to "Transparency mask" (4) according to the specification (page 36)
6676
... But the TIFF6 specification allows image masks to have a higher resolution than
6677
the main image, what we don't support here
6680
if( poMaskDS->OpenOffset( hTIFF, ppoActiveDSRef, nThisDir,
6681
FALSE, eAccess ) != CE_None
6682
|| poMaskDS->GetRasterCount() == 0
6683
|| !(poMaskDS->GetRasterCount() == 1 || poMaskDS->GetRasterCount() == GetRasterCount())
6684
|| poMaskDS->GetRasterXSize() != GetRasterXSize()
6685
|| poMaskDS->GetRasterYSize() != GetRasterYSize()
6686
|| poMaskDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte)
6693
CPLDebug( "GTiff", "Opened band mask.\n");
6694
poMaskDS->poBaseDS = this;
6696
poMaskDS->bPromoteTo8Bits = CSLTestBoolean(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK_TO_8BIT", "YES"));
6700
/* Embedded mask of an overview */
6701
/* The TIFF6 specification allows the combination of the FILETYPE_xxxx masks */
6702
else if ((nSubType & FILETYPE_REDUCEDIMAGE) != 0 &&
6703
(nSubType & FILETYPE_MASK) != 0)
6705
GTiffDataset* poDS = new GTiffDataset();
6706
if( poDS->OpenOffset( hTIFF, ppoActiveDSRef, nThisDir, FALSE,
6707
eAccess ) != CE_None
6708
|| poDS->GetRasterCount() == 0
6709
|| poDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte)
6716
for(i=0;i<nOverviewCount;i++)
6718
if (((GTiffDataset*)papoOverviewDS[i])->poMaskDS == NULL &&
6719
poDS->GetRasterXSize() == papoOverviewDS[i]->GetRasterXSize() &&
6720
poDS->GetRasterYSize() == papoOverviewDS[i]->GetRasterYSize() &&
6721
(poDS->GetRasterCount() == 1 || poDS->GetRasterCount() == GetRasterCount()))
6723
CPLDebug( "GTiff", "Opened band mask for %dx%d overview.\n",
6724
poDS->GetRasterXSize(), poDS->GetRasterYSize());
6725
((GTiffDataset*)papoOverviewDS[i])->poMaskDS = poDS;
6726
poDS->bPromoteTo8Bits = CSLTestBoolean(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK_TO_8BIT", "YES"));
6727
poDS->poBaseDS = this;
6731
if (i == nOverviewCount)
5471
for(i=0;i<nOverviewCount;i++)
5473
if (((GTiffDataset*)papoOverviewDS[i])->poMaskDS == NULL &&
5474
poDS->GetRasterXSize() == papoOverviewDS[i]->GetRasterXSize() &&
5475
poDS->GetRasterYSize() == papoOverviewDS[i]->GetRasterYSize() &&
5476
(poDS->GetRasterCount() == 1 || poDS->GetRasterCount() == GetRasterCount()))
5478
CPLDebug( "GTiff", "Opened band mask for %dx%d overview.\n",
5479
poDS->GetRasterXSize(), poDS->GetRasterYSize());
5480
((GTiffDataset*)papoOverviewDS[i])->poMaskDS = poDS;
5481
poDS->poBaseDS = this;
5485
if (i == nOverviewCount)
5491
else if( nSubType == 0 ) {
5492
CPLString osName, osDesc;
5493
uint32 nXSize, nYSize;
5496
TIFFGetField( hTIFF, TIFFTAG_IMAGEWIDTH, &nXSize );
5497
TIFFGetField( hTIFF, TIFFTAG_IMAGELENGTH, &nYSize );
5498
if( !TIFFGetField(hTIFF, TIFFTAG_SAMPLESPERPIXEL, &nSPP ) )
5501
osName.Printf( "SUBDATASET_%d_NAME=GTIFF_DIR:%d:%s",
5502
iDirIndex, iDirIndex, osFilename.c_str() );
5503
osDesc.Printf( "SUBDATASET_%d_DESC=Page %d (%dP x %dL x %dB)",
5504
iDirIndex, iDirIndex,
5505
(int)nXSize, (int)nYSize, nSPP );
5508
CSLAddString( papszSubdatasets, osName );
5510
CSLAddString( papszSubdatasets, osDesc );
5513
// Make sure we are stepping from the expected directory regardless
5514
// of churn done processing the above.
5515
if( TIFFCurrentDirOffset(hTIFF) != nThisDir )
5516
TIFFSetSubDirectory( hTIFF, nThisDir );
5517
*ppoActiveDSRef = NULL;
5520
/* If we have a mask for the main image, loop over the overviews, and if they */
5521
/* have a mask, let's set this mask as an overview of the main mask... */
5522
if (poMaskDS != NULL)
6737
else if( nSubType == 0 || nSubType == FILETYPE_PAGE ) {
6738
CPLString osName, osDesc;
6739
uint32 nXSize, nYSize;
6742
TIFFGetField( hTIFF, TIFFTAG_IMAGEWIDTH, &nXSize );
6743
TIFFGetField( hTIFF, TIFFTAG_IMAGELENGTH, &nYSize );
6744
if( !TIFFGetField(hTIFF, TIFFTAG_SAMPLESPERPIXEL, &nSPP ) )
6747
osName.Printf( "SUBDATASET_%d_NAME=GTIFF_DIR:%d:%s",
6748
iDirIndex, iDirIndex, osFilename.c_str() );
6749
osDesc.Printf( "SUBDATASET_%d_DESC=Page %d (%dP x %dL x %dB)",
6750
iDirIndex, iDirIndex,
6751
(int)nXSize, (int)nYSize, nSPP );
6754
CSLAddString( papszSubdatasets, osName );
6756
CSLAddString( papszSubdatasets, osDesc );
6759
// Make sure we are stepping from the expected directory regardless
6760
// of churn done processing the above.
6761
if( TIFFCurrentDirOffset(hTIFF) != nThisDir )
6762
TIFFSetSubDirectory( hTIFF, nThisDir );
6763
*ppoActiveDSRef = NULL;
6766
/* If we have a mask for the main image, loop over the overviews, and if they */
6767
/* have a mask, let's set this mask as an overview of the main mask... */
6768
if (poMaskDS != NULL)
6771
for(i=0;i<nOverviewCount;i++)
5525
for(i=0;i<nOverviewCount;i++)
6773
if (((GTiffDataset*)papoOverviewDS[i])->poMaskDS != NULL)
5527
if (((GTiffDataset*)papoOverviewDS[i])->poMaskDS != NULL)
5529
poMaskDS->nOverviewCount++;
5530
poMaskDS->papoOverviewDS = (GTiffDataset **)
5531
CPLRealloc(poMaskDS->papoOverviewDS,
5532
poMaskDS->nOverviewCount * (sizeof(void*)));
5533
poMaskDS->papoOverviewDS[poMaskDS->nOverviewCount-1] =
5534
((GTiffDataset*)papoOverviewDS[i])->poMaskDS;
6775
poMaskDS->nOverviewCount++;
6776
poMaskDS->papoOverviewDS = (GTiffDataset **)
6777
CPLRealloc(poMaskDS->papoOverviewDS,
6778
poMaskDS->nOverviewCount * (sizeof(void*)));
6779
poMaskDS->papoOverviewDS[poMaskDS->nOverviewCount-1] =
6780
((GTiffDataset*)papoOverviewDS[i])->poMaskDS;
5539
6785
/* -------------------------------------------------------------------- */
5540
6786
/* Only keep track of subdatasets if we have more than one */
5541
6787
/* subdataset (pair). */
5542
6788
/* -------------------------------------------------------------------- */
5543
if( CSLCount(papszSubdatasets) > 2 )
6789
if( CSLCount(papszSubdatasets) > 2 )
6791
oGTiffMDMD.SetMetadata( papszSubdatasets, "SUBDATASETS" );
6793
CSLDestroy( papszSubdatasets );
6798
static int GTiffGetLZMAPreset(char** papszOptions)
6800
int nLZMAPreset = -1;
6801
const char* pszValue = CSLFetchNameValue( papszOptions, "LZMA_PRESET" );
6802
if( pszValue != NULL )
6804
nLZMAPreset = atoi( pszValue );
6805
if (!(nLZMAPreset >= 0 && nLZMAPreset <= 9))
5545
oGTiffMDMD.SetMetadata( papszSubdatasets, "SUBDATASETS" );
6807
CPLError( CE_Warning, CPLE_IllegalArg,
6808
"LZMA_PRESET=%s value not recognised, ignoring.",
5547
CSLDestroy( papszSubdatasets );
5553
6817
static int GTiffGetZLevel(char** papszOptions)
5555
6819
int nZLevel = -1;
6825
8175
/* been lost a few lines above when closing the newly create TIFF file */
6826
8176
/* The TIFFTAG_ZIPQUALITY & TIFFTAG_JPEGQUALITY are not store in the TIFF file. */
6827
8177
/* They are just TIFF session parameters */
8179
poDS->nZLevel = GTiffGetZLevel(papszOptions);
8180
poDS->nLZMAPreset = GTiffGetLZMAPreset(papszOptions);
8181
poDS->nJpegQuality = GTiffGetJpegQuality(papszOptions);
6828
8183
if (nCompression == COMPRESSION_ADOBE_DEFLATE)
6830
int nZLevel = GTiffGetZLevel(papszOptions);
8185
if (poDS->nZLevel != -1)
6833
TIFFSetField( hTIFF, TIFFTAG_ZIPQUALITY, nZLevel );
8187
TIFFSetField( hTIFF, TIFFTAG_ZIPQUALITY, poDS->nZLevel );
6836
8190
else if( nCompression == COMPRESSION_JPEG)
6838
int nJpegQuality = GTiffGetJpegQuality(papszOptions);
6839
if (nJpegQuality != -1)
6841
TIFFSetField( hTIFF, TIFFTAG_JPEGQUALITY, nJpegQuality );
8192
if (poDS->nJpegQuality != -1)
8194
TIFFSetField( hTIFF, TIFFTAG_JPEGQUALITY, poDS->nJpegQuality );
8197
else if( nCompression == COMPRESSION_LZMA)
8199
if (poDS->nLZMAPreset != -1)
8201
TIFFSetField( hTIFF, TIFFTAG_LZMAPRESET, poDS->nLZMAPreset );
8205
/* Precreate (internal) mask, so that the IBuildOverviews() below */
8206
/* has a chance to create also the overviews of the mask */
8207
int nMaskFlags = poSrcDS->GetRasterBand(1)->GetMaskFlags();
8209
&& !(nMaskFlags & (GMF_ALL_VALID|GMF_ALPHA|GMF_NODATA) )
8210
&& (nMaskFlags & GMF_PER_DATASET) )
8212
eErr = poDS->CreateMaskBand( nMaskFlags );
8215
/* -------------------------------------------------------------------- */
8216
/* Create and then copy existing overviews if requested */
8217
/* We do it such that all the IFDs are at the beginning of the file, */
8218
/* and that the imagery data for the smallest overview is written */
8219
/* first, that way the file is more usable when embedded in a */
8220
/* compressed stream. */
8221
/* -------------------------------------------------------------------- */
8223
/* For scaled progress due to overview copying */
8224
double dfTotalPixels = ((double)nXSize) * nYSize;
8225
double dfCurPixels = 0;
8227
if (eErr == CE_None &&
8228
nSrcOverviews != 0 &&
8229
CSLFetchBoolean(papszOptions, "COPY_SRC_OVERVIEWS", FALSE))
8231
eErr = poDS->CreateOverviewsFromSrcOverviews(poSrcDS);
8233
if (poDS->nOverviewCount != nSrcOverviews)
8235
CPLError(CE_Failure, CPLE_AppDefined,
8236
"Did only manage to instanciate %d overview levels, whereas source contains %d",
8237
poDS->nOverviewCount, nSrcOverviews);
8242
for(i=0;i<nSrcOverviews;i++)
8244
GDALRasterBand* poOvrBand = poSrcDS->GetRasterBand(1)->GetOverview(i);
8245
dfTotalPixels += ((double)poOvrBand->GetXSize()) *
8246
poOvrBand->GetYSize();
8249
char* papszCopyWholeRasterOptions[2] = { NULL, NULL };
8250
if (nCompression != COMPRESSION_NONE)
8251
papszCopyWholeRasterOptions[0] = (char*) "COMPRESSED=YES";
8252
/* Now copy the imagery */
8253
for(i=0;eErr == CE_None && i<nSrcOverviews;i++)
8255
/* Begin with the smallest overview */
8256
int iOvrLevel = nSrcOverviews-1-i;
8258
/* Create a fake dataset with the source overview level so that */
8259
/* GDALDatasetCopyWholeRaster can cope with it */
8260
GDALDataset* poSrcOvrDS = new GDALOverviewDS(poSrcDS, iOvrLevel);
8262
GDALRasterBand* poOvrBand =
8263
poSrcDS->GetRasterBand(1)->GetOverview(iOvrLevel);
8264
double dfNextCurPixels = dfCurPixels +
8265
((double)poOvrBand->GetXSize()) * poOvrBand->GetYSize();
8267
void* pScaledData = GDALCreateScaledProgress( dfCurPixels / dfTotalPixels,
8268
dfNextCurPixels / dfTotalPixels,
8269
pfnProgress, pProgressData);
8271
eErr = GDALDatasetCopyWholeRaster( (GDALDatasetH) poSrcOvrDS,
8272
(GDALDatasetH) poDS->papoOverviewDS[iOvrLevel],
8273
papszCopyWholeRasterOptions,
8274
GDALScaledProgress, pScaledData );
8276
dfCurPixels = dfNextCurPixels;
8277
GDALDestroyScaledProgress(pScaledData);
8280
poDS->papoOverviewDS[iOvrLevel]->FlushCache();
8282
/* Copy mask of the overview */
8283
if (eErr == CE_None && poDS->poMaskDS != NULL)
8285
eErr = GDALRasterBandCopyWholeRaster( poOvrBand->GetMaskBand(),
8286
poDS->papoOverviewDS[iOvrLevel]->poMaskDS->GetRasterBand(1),
8287
papszCopyWholeRasterOptions,
8288
GDALDummyProgress, NULL);
8289
poDS->papoOverviewDS[iOvrLevel]->poMaskDS->FlushCache();
6845
8294
/* -------------------------------------------------------------------- */
6846
8295
/* Copy actual imagery. */
6847
8296
/* -------------------------------------------------------------------- */
8297
void* pScaledData = GDALCreateScaledProgress( dfCurPixels / dfTotalPixels,
8299
pfnProgress, pProgressData);
6849
8301
if (poDS->bTreatAsSplit || poDS->bTreatAsSplitBitmap)
8702
/************************************************************************/
8704
/************************************************************************/
8706
int GTiffDataset::FindRPBFile()
8708
osRPBFile = GDALFindAssociatedFile( osFilename, "RPB",
8709
oOvManager.GetSiblingFiles(), 0 );
8711
return osRPBFile != "";
8714
/************************************************************************/
8716
/************************************************************************/
8718
int GTiffDataset::FindIMDFile()
8720
osIMDFile = GDALFindAssociatedFile( osFilename, "IMD",
8721
oOvManager.GetSiblingFiles(), 0 );
8723
return osIMDFile != "";
8726
/************************************************************************/
8728
/************************************************************************/
8730
int GTiffDataset::FindRPCFile()
8732
CPLString osSrcPath = osFilename;
8733
CPLString soPt(".");
8734
size_t found = osSrcPath.rfind(soPt);
8735
if (found == CPLString::npos)
8737
osSrcPath.replace (found, osSrcPath.size() - found, "_rpc.txt");
8738
CPLString osTarget = osSrcPath;
8740
char** papszSiblingFiles = oOvManager.GetSiblingFiles();
8741
if( papszSiblingFiles == NULL )
8743
VSIStatBufL sStatBuf;
8745
if( VSIStatExL( osTarget, &sStatBuf, VSI_STAT_EXISTS_FLAG ) != 0 )
8747
osSrcPath = osFilename;
8748
osSrcPath.replace (found, osSrcPath.size() - found, "_RPC.TXT");
8749
osTarget = osSrcPath;
8751
if( VSIStatExL( osTarget, &sStatBuf, VSI_STAT_EXISTS_FLAG ) != 0 )
8753
osSrcPath = osFilename;
8754
osSrcPath.replace (found, osSrcPath.size() - found, "_rpc.TXT");
8755
osTarget = osSrcPath;
8757
if( VSIStatExL( osTarget, &sStatBuf, VSI_STAT_EXISTS_FLAG ) != 0 )
8766
int iSibling = CSLFindString( papszSiblingFiles,
8767
CPLGetFilename(osTarget) );
8771
osTarget.resize(osTarget.size() - strlen(papszSiblingFiles[iSibling]));
8772
osTarget += papszSiblingFiles[iSibling];
8775
osRPCFile = osTarget;
8779
/************************************************************************/
8781
/************************************************************************/
8783
void GTiffDataset::LoadRPCRPB()
8785
if (bHasSearchedRPC)
8788
bHasSearchedRPC = TRUE;
8790
char **papszRPCMD = NULL;
8791
/* Read Digital Globe .RPB file */
8793
papszRPCMD = GDALLoadRPBFile( osRPBFile.c_str(), NULL );
8795
/* Read GeoEye _rpc.txt file */
8796
if(papszRPCMD == NULL && FindRPCFile())
8797
papszRPCMD = GDALLoadRPCFile( osRPCFile.c_str(), NULL );
8799
if( papszRPCMD != NULL )
8801
oGTiffMDMD.SetMetadata( papszRPCMD, "RPC" );
8802
CSLDestroy( papszRPCMD );
8808
/************************************************************************/
8810
/************************************************************************/
8812
void GTiffDataset::LoadIMD()
8814
if (bHasSearchedIMD)
8817
bHasSearchedIMD = TRUE;
8821
char **papszIMDMD = GDALLoadIMDFile( osIMDFile.c_str(), NULL );
8823
if( papszIMDMD != NULL )
8825
oGTiffMDMD.SetMetadata( papszIMDMD, "IMD" );
8826
CSLDestroy( papszIMDMD );
7193
8831
/************************************************************************/
7194
8832
/* GetFileList() */
7195
8833
/************************************************************************/
7476
9153
/************************************************************************/
9154
/* GTIFFGetCompressionMethod() */
9155
/************************************************************************/
9157
int GTIFFGetCompressionMethod(const char* pszValue, const char* pszVariableName)
9159
int nCompression = COMPRESSION_NONE;
9160
if( EQUAL( pszValue, "NONE" ) )
9161
nCompression = COMPRESSION_NONE;
9162
else if( EQUAL( pszValue, "JPEG" ) )
9163
nCompression = COMPRESSION_JPEG;
9164
else if( EQUAL( pszValue, "LZW" ) )
9165
nCompression = COMPRESSION_LZW;
9166
else if( EQUAL( pszValue, "PACKBITS" ))
9167
nCompression = COMPRESSION_PACKBITS;
9168
else if( EQUAL( pszValue, "DEFLATE" ) || EQUAL( pszValue, "ZIP" ))
9169
nCompression = COMPRESSION_ADOBE_DEFLATE;
9170
else if( EQUAL( pszValue, "FAX3" )
9171
|| EQUAL( pszValue, "CCITTFAX3" ))
9172
nCompression = COMPRESSION_CCITTFAX3;
9173
else if( EQUAL( pszValue, "FAX4" )
9174
|| EQUAL( pszValue, "CCITTFAX4" ))
9175
nCompression = COMPRESSION_CCITTFAX4;
9176
else if( EQUAL( pszValue, "CCITTRLE" ) )
9177
nCompression = COMPRESSION_CCITTRLE;
9178
else if( EQUAL( pszValue, "LZMA" ) )
9179
nCompression = COMPRESSION_LZMA;
9181
CPLError( CE_Warning, CPLE_IllegalArg,
9182
"%s=%s value not recognised, ignoring.",
9183
pszVariableName,pszValue );
9185
#if defined(TIFFLIB_VERSION) && TIFFLIB_VERSION > 20031007 /* 3.6.0 */
9186
if (nCompression != COMPRESSION_NONE &&
9187
!TIFFIsCODECConfigured((uint16) nCompression))
9189
CPLError( CE_Failure, CPLE_AppDefined,
9190
"Cannot create TIFF file due to missing codec for %s.", pszValue );
9195
return nCompression;
9197
/************************************************************************/
7477
9198
/* GDALRegister_GTiff() */
7478
9199
/************************************************************************/