static CPLErr SqrtPixelFunc( void **papoSources, int nSources, void *pData, int nXSize, int nYSize, GDALDataType eSrcType, GDALDataType eBufType, int nPixelSpace, int nLineSpace ) { /* ---- Init ---- */ if( nSources != 1 ) return CE_Failure; if( GDALDataTypeIsComplex( eSrcType ) ) return CE_Failure; /* ---- Set pixels ---- */ for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) { for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) { // Source raster pixels may be obtained with SRCVAL macro. const double dfPixVal = sqrt( SRCVAL(papoSources[0], eSrcType, ii) ); GDALCopyWords( &dfPixVal, GDT_Float64, 0, static_cast<GByte *>(pData) + nLineSpace * iLine + iCol * nPixelSpace, eBufType, nPixelSpace, 1); } } /* ---- Return success ---- */ return CE_None; } // SqrtPixelFunc
CPLErr PowPixelFuncHelper(void **papoSources, int nSources, void *pData, int nXSize, int nYSize, GDALDataType eSrcType, GDALDataType eBufType, int nPixelSpace, int nLineSpace, double base, double fact) { int iLine, iCol, ii; double dfPixVal; /* ---- Init ---- */ if (nSources != 1) return CE_Failure; if (GDALDataTypeIsComplex( eSrcType )) return CE_Failure; /* ---- Set pixels ---- */ for( iLine = 0, ii= 0; iLine < nYSize; ++iLine ) { for( iCol = 0; iCol < nXSize; ++iCol, ++ii ) { /* Source raster pixels may be obtained with SRCVAL macro */ dfPixVal = SRCVAL(papoSources[0], eSrcType, ii); dfPixVal = pow(base, dfPixVal / fact); GDALCopyWords(&dfPixVal, GDT_Float64, 0, ((GByte *)pData) + nLineSpace * iLine + iCol * nPixelSpace, eBufType, nPixelSpace, 1); } } /* ---- Return success ---- */ return CE_None; } /* PowPixelFuncHelper */
CPLErr GFFRasterBand::IReadBlock( int /* nBlockXOff */ , int nBlockYOff, void *pImage ) { GFFDataset *poGDS = (GFFDataset *)poDS; long nOffset = poGDS->nLength; VSIFSeekL(poGDS->fp, nOffset + (poGDS->GetRasterXSize() * nBlockYOff * (nSampleSize)),SEEK_SET); /* Ingest entire range line */ if (VSIFReadL(pImage,nRasterBandMemory,1,poGDS->fp) != 1) return CE_Failure; #if defined(CPL_MSB) if( GDALDataTypeIsComplex( eDataType ) ) { int nWordSize = GDALGetDataTypeSize(eDataType)/16; GDALSwapWords( pImage, nWordSize, nBlockXSize, 2*nWordSize ); GDALSwapWords( ((GByte *) pImage)+nWordSize, nWordSize, nBlockXSize, 2*nWordSize ); } #endif return CE_None; }
// Test GDALDataTypeUnion() template<> template<> void object::test<6>() { for(int i=GDT_Byte;i<GDT_TypeCount;i++) { for(int j=GDT_Byte;j<GDT_TypeCount;j++) { GDALDataType eDT1 = static_cast<GDALDataType>(i); GDALDataType eDT2 = static_cast<GDALDataType>(j); GDALDataType eDT = GDALDataTypeUnion(eDT1,eDT2 ); ensure( eDT == GDALDataTypeUnion(eDT2,eDT1) ); ensure( GDALGetDataTypeSize(eDT) >= GDALGetDataTypeSize(eDT1) ); ensure( GDALGetDataTypeSize(eDT) >= GDALGetDataTypeSize(eDT2) ); ensure( (GDALDataTypeIsComplex(eDT) && (GDALDataTypeIsComplex(eDT1) || GDALDataTypeIsComplex(eDT2))) || (!(GDALDataTypeIsComplex(eDT) && !GDALDataTypeIsComplex(eDT1) && !GDALDataTypeIsComplex(eDT2))) ); } } }
static CPLErr SumPixelFunc(void **papoSources, int nSources, void *pData, int nXSize, int nYSize, GDALDataType eSrcType, GDALDataType eBufType, int nPixelSpace, int nLineSpace) { /* ---- Init ---- */ if( nSources < 2 ) return CE_Failure; /* ---- Set pixels ---- */ if( GDALDataTypeIsComplex( eSrcType ) ) { const int nOffset = GDALGetDataTypeSizeBytes( eSrcType ) / 2; /* ---- Set pixels ---- */ for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) { for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) { double adfSum[2] = { 0.0, 0.0 }; for( int iSrc = 0; iSrc < nSources; ++iSrc ) { const void * const pReal = papoSources[iSrc]; const void * const pImag = static_cast<const GByte *>(pReal) + nOffset; // Source raster pixels may be obtained with SRCVAL macro. adfSum[0] += SRCVAL(pReal, eSrcType, ii); adfSum[1] += SRCVAL(pImag, eSrcType, ii); } GDALCopyWords( adfSum, GDT_CFloat64, 0, static_cast<GByte *>(pData) + nLineSpace * iLine + iCol * nPixelSpace, eBufType, nPixelSpace, 1); } } } else { /* ---- Set pixels ---- */ for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) { for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) { double dfSum = 0; // Not complex. for( int iSrc = 0; iSrc < nSources; ++iSrc ) { // Source raster pixels may be obtained with SRCVAL macro. dfSum += SRCVAL(papoSources[iSrc], eSrcType, ii); } GDALCopyWords( &dfSum, GDT_Float64, 0, static_cast<GByte *>(pData) + nLineSpace * iLine + iCol * nPixelSpace, eBufType, nPixelSpace, 1); } } } /* ---- Return success ---- */ return CE_None; } /* SumPixelFunc */
CPLErr CMulPixelFunc(void **papoSources, int nSources, void *pData, int nXSize, int nYSize, GDALDataType eSrcType, GDALDataType eBufType, int nPixelSpace, int nLineSpace) { int ii, iLine, iCol; /* ---- Init ---- */ if (nSources != 2) return CE_Failure; /* ---- Set pixels ---- */ if (GDALDataTypeIsComplex( eSrcType )) { double adfPixVal[2], dfReal0, dfImag0, dfReal1, dfImag1; int nOffset = GDALGetDataTypeSize( eSrcType ) / 8 / 2; void *pReal0 = papoSources[0]; void *pImag0 = ((GByte *)papoSources[0]) + nOffset; void *pReal1 = papoSources[1]; void *pImag1 = ((GByte *)papoSources[1]) + nOffset; for( iLine = 0, ii= 0; iLine < nYSize; ++iLine ) { for( iCol = 0; iCol < nXSize; ++iCol, ++ii ) { /* Source raster pixels may be obtained with SRCVAL macro */ dfReal0 = SRCVAL(pReal0, eSrcType, ii); dfReal1 = SRCVAL(pReal1, eSrcType, ii); dfImag0 = SRCVAL(pImag0, eSrcType, ii); dfImag1 = SRCVAL(pImag1, eSrcType, ii); adfPixVal[0] = dfReal0 * dfReal1 + dfImag0 * dfImag1; adfPixVal[1] = dfReal1 * dfImag0 - dfReal0 * dfImag1; GDALCopyWords(adfPixVal, GDT_CFloat64, 0, ((GByte *)pData) + nLineSpace * iLine + iCol * nPixelSpace, eBufType, nPixelSpace, 1); } } } else { /* non complex */ double adfPixVal[2] = {0, 0}; for( iLine = 0, ii= 0; iLine < nYSize; ++iLine ) { for( iCol = 0; iCol < nXSize; ++iCol, ++ii ) { /* Source raster pixels may be obtained with SRCVAL macro */ adfPixVal[0] = SRCVAL(papoSources[0], eSrcType, ii) * SRCVAL(papoSources[1], eSrcType, ii); GDALCopyWords(adfPixVal, GDT_CFloat64, 0, ((GByte *)pData) + nLineSpace * iLine + iCol * nPixelSpace, eBufType, nPixelSpace, 1); } } } /* ---- Return success ---- */ return CE_None; } /* CMulPixelFunc */
static CPLErr DiffPixelFunc( void **papoSources, int nSources, void *pData, int nXSize, int nYSize, GDALDataType eSrcType, GDALDataType eBufType, int nPixelSpace, int nLineSpace) { /* ---- Init ---- */ if( nSources != 2 ) return CE_Failure; if( GDALDataTypeIsComplex( eSrcType ) ) { const int nOffset = GDALGetDataTypeSizeBytes( eSrcType ) / 2; const void * const pReal0 = papoSources[0]; const void * const pImag0 = static_cast<GByte *>(papoSources[0]) + nOffset; const void * const pReal1 = papoSources[1]; const void * const pImag1 = static_cast<GByte *>(papoSources[1]) + nOffset; /* ---- Set pixels ---- */ for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) { for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) { // Source raster pixels may be obtained with SRCVAL macro. double adfPixVal[2] = { SRCVAL(pReal0, eSrcType, ii) - SRCVAL(pReal1, eSrcType, ii), SRCVAL(pImag0, eSrcType, ii) - SRCVAL(pImag1, eSrcType, ii) }; GDALCopyWords( adfPixVal, GDT_CFloat64, 0, static_cast<GByte *>(pData) + nLineSpace * iLine + iCol * nPixelSpace, eBufType, nPixelSpace, 1 ); } } } else { /* ---- Set pixels ---- */ for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) { for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) { // Source raster pixels may be obtained with SRCVAL macro. // Not complex. const double dfPixVal = SRCVAL(papoSources[0], eSrcType, ii) - SRCVAL(papoSources[1], eSrcType, ii); GDALCopyWords( &dfPixVal, GDT_Float64, 0, static_cast<GByte *>(pData) + nLineSpace * iLine + iCol * nPixelSpace, eBufType, nPixelSpace, 1); } } } /* ---- Return success ---- */ return CE_None; } // DiffPixelFunc
static CPLErr Log10PixelFuncHelper( void **papoSources, int nSources, void *pData, int nXSize, int nYSize, GDALDataType eSrcType, GDALDataType eBufType, int nPixelSpace, int nLineSpace, double fact ) { /* ---- Init ---- */ if( nSources != 1 ) return CE_Failure; if( GDALDataTypeIsComplex( eSrcType ) ) { // Complex input datatype. const int nOffset = GDALGetDataTypeSizeBytes( eSrcType ) / 2; const void * const pReal = papoSources[0]; const void * const pImag = static_cast<GByte *>(papoSources[0]) + nOffset; /* ---- Set pixels ---- */ for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) { for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) { // Source raster pixels may be obtained with SRCVAL macro. const double dfReal = SRCVAL(pReal, eSrcType, ii); const double dfImag = SRCVAL(pImag, eSrcType, ii); const double dfPixVal = fact * log10( sqrt( dfReal * dfReal + dfImag * dfImag ) ); GDALCopyWords( &dfPixVal, GDT_Float64, 0, static_cast<GByte *>(pData) + nLineSpace * iLine + iCol * nPixelSpace, eBufType, nPixelSpace, 1 ); } } } else { /* ---- Set pixels ---- */ for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) { for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) { // Source raster pixels may be obtained with SRCVAL macro. const double dfPixVal = fact * log10( fabs( SRCVAL(papoSources[0], eSrcType, ii) ) ); GDALCopyWords( &dfPixVal, GDT_Float64, 0, static_cast<GByte *>(pData) + nLineSpace * iLine + iCol * nPixelSpace, eBufType, nPixelSpace, 1 ); } } } /* ---- Return success ---- */ return CE_None; } // Log10PixelFuncHelper
CPLErr InvPixelFunc(void **papoSources, int nSources, void *pData, int nXSize, int nYSize, GDALDataType eSrcType, GDALDataType eBufType, int nPixelSpace, int nLineSpace) { int iLine, iCol, ii; /* ---- Init ---- */ if (nSources != 1) return CE_Failure; /* ---- Set pixels ---- */ if (GDALDataTypeIsComplex( eSrcType )) { double adfPixVal[2], dfReal, dfImag, dfAux; int nOffset = GDALGetDataTypeSize( eSrcType ) / 8 / 2; void *pReal = papoSources[0]; void *pImag = ((GByte *)papoSources[0]) + nOffset; for( iLine = 0, ii= 0; iLine < nYSize; ++iLine ) { for( iCol = 0; iCol < nXSize; ++iCol, ++ii ) { /* Source raster pixels may be obtained with SRCVAL macro */ dfReal = SRCVAL(pReal, eSrcType, ii); dfImag = SRCVAL(pImag, eSrcType, ii); dfAux = dfReal * dfReal + dfImag * dfImag; adfPixVal[0] = +dfReal / dfAux; adfPixVal[1] = -dfImag / dfAux; GDALCopyWords(adfPixVal, GDT_CFloat64, 0, ((GByte *)pData) + nLineSpace * iLine + iCol * nPixelSpace, eBufType, nPixelSpace, 1); } } } else { /* non complex */ double dfPixVal; /* ---- Set pixels ---- */ for( iLine = 0, ii= 0; iLine < nYSize; ++iLine ) { for( iCol = 0; iCol < nXSize; ++iCol, ++ii ) { /* Source raster pixels may be obtained with SRCVAL macro */ dfPixVal = 1. / SRCVAL(papoSources[0], eSrcType, ii); GDALCopyWords(&dfPixVal, GDT_Float64, 0, ((GByte *)pData) + nLineSpace * iLine + iCol * nPixelSpace, eBufType, nPixelSpace, 1); } } } /* ---- Return success ---- */ return CE_None; } /* InvPixelFunc */
CPLErr Log10PixelFunc(void **papoSources, int nSources, void *pData, int nXSize, int nYSize, GDALDataType eSrcType, GDALDataType eBufType, int nPixelSpace, int nLineSpace) { int ii, iLine, iCol; /* ---- Init ---- */ if (nSources != 1) return CE_Failure; if (GDALDataTypeIsComplex( eSrcType )) { /* complex input datatype */ double dfReal, dfImag, dfPixVal; int nOffset = GDALGetDataTypeSize( eSrcType ) / 8 / 2; void *pReal = papoSources[0]; void *pImag = ((GByte *)papoSources[0]) + nOffset; /* ---- Set pixels ---- */ for( iLine = 0, ii = 0; iLine < nYSize; ++iLine ) { for( iCol = 0; iCol < nXSize; ++iCol, ++ii ) { /* Source raster pixels may be obtained with SRCVAL macro */ dfReal = SRCVAL(pReal, eSrcType, ii); dfImag = SRCVAL(pImag, eSrcType, ii); dfPixVal = log10( dfReal * dfReal + dfImag * dfImag ); GDALCopyWords(&dfPixVal, GDT_Float64, 0, ((GByte *)pData) + nLineSpace * iLine + iCol * nPixelSpace, eBufType, nPixelSpace, 1); } } } else { double dfPixVal; /* ---- Set pixels ---- */ for( iLine = 0, ii = 0; iLine < nYSize; ++iLine ) { for( iCol = 0; iCol < nXSize; ++iCol, ++ii ) { /* Source raster pixels may be obtained with SRCVAL macro */ dfPixVal = SRCVAL(papoSources[0], eSrcType, ii); dfPixVal = log10( abs( dfPixVal ) ); GDALCopyWords(&dfPixVal, GDT_Float64, 0, ((GByte *)pData) + nLineSpace * iLine + iCol * nPixelSpace, eBufType, nPixelSpace, 1); } } } /* ---- Return success ---- */ return CE_None; } /* Log10PixelFunc */
static CPLErr ConjPixelFunc( void **papoSources, int nSources, void *pData, int nXSize, int nYSize, GDALDataType eSrcType, GDALDataType eBufType, int nPixelSpace, int nLineSpace ) { /* ---- Init ---- */ if( nSources != 1 ) return CE_Failure; if( GDALDataTypeIsComplex( eSrcType ) && GDALDataTypeIsComplex( eBufType ) ) { const int nOffset = GDALGetDataTypeSizeBytes( eSrcType ) / 2; const void * const pReal = papoSources[0]; const void * const pImag = static_cast<GByte *>(papoSources[0]) + nOffset; /* ---- Set pixels ---- */ for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) { for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) { // Source raster pixels may be obtained with SRCVAL macro. const double adfPixVal[2] = { +SRCVAL(pReal, eSrcType, ii), // re -SRCVAL(pImag, eSrcType, ii) // im }; GDALCopyWords( adfPixVal, GDT_CFloat64, 0, static_cast<GByte *>(pData) + nLineSpace * iLine + iCol * nPixelSpace, eBufType, nPixelSpace, 1 ); } } } else { // No complex data type. return RealPixelFunc(papoSources, nSources, pData, nXSize, nYSize, eSrcType, eBufType, nPixelSpace, nLineSpace); } /* ---- Return success ---- */ return CE_None; } // ConjPixelFunc
static CPLErr PhasePixelFunc( void **papoSources, int nSources, void *pData, int nXSize, int nYSize, GDALDataType eSrcType, GDALDataType eBufType, int nPixelSpace, int nLineSpace ) { /* ---- Init ---- */ if( nSources != 1 ) return CE_Failure; if( GDALDataTypeIsComplex( eSrcType ) ) { const void * const pReal = papoSources[0]; const void * const pImag = static_cast<GByte *>(papoSources[0]) + GDALGetDataTypeSizeBytes( eSrcType ) / 2; /* ---- Set pixels ---- */ for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) { for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) { // Source raster pixels may be obtained with SRCVAL macro. const double dfReal = SRCVAL(pReal, eSrcType, ii); const double dfImag = SRCVAL(pImag, eSrcType, ii); const double dfPixVal = atan2(dfImag, dfReal); GDALCopyWords( &dfPixVal, GDT_Float64, 0, static_cast<GByte *>(pData) + nLineSpace * iLine + iCol * nPixelSpace, eBufType, nPixelSpace, 1 ); } } } else { /* ---- Set pixels ---- */ for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) { for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) { const void * const pReal = papoSources[0]; // Source raster pixels may be obtained with SRCVAL macro. const double dfReal = SRCVAL(pReal, eSrcType, ii); const double dfPixVal = (dfReal < 0) ? M_PI : 0.0; GDALCopyWords( &dfPixVal, GDT_Float64, 0, static_cast<GByte *>(pData) + nLineSpace * iLine + iCol * nPixelSpace, eBufType, nPixelSpace, 1 ); } } } /* ---- Return success ---- */ return CE_None; } // PhasePixelFunc
CPLErr ConjPixelFunc(void **papoSources, int nSources, void *pData, int nXSize, int nYSize, GDALDataType eSrcType, GDALDataType eBufType, int nPixelSpace, int nLineSpace) { /* ---- Init ---- */ if (nSources != 1) return CE_Failure; if (GDALDataTypeIsComplex( eSrcType ) && GDALDataTypeIsComplex( eBufType )) { int iLine, iCol, ii; double adfPixVal[2]; int nOffset = GDALGetDataTypeSize( eSrcType ) / 8 / 2; void *pReal = papoSources[0]; void *pImag = ((GByte *)papoSources[0]) + nOffset; /* ---- Set pixels ---- */ for( iLine = 0, ii= 0; iLine < nYSize; ++iLine ) { for( iCol = 0; iCol < nXSize; ++iCol, ++ii ) { /* Source raster pixels may be obtained with SRCVAL macro */ adfPixVal[0] = +SRCVAL(pReal, eSrcType, ii); /* re */ adfPixVal[1] = -SRCVAL(pImag, eSrcType, ii); /* im */ GDALCopyWords(adfPixVal, GDT_CFloat64, 0, ((GByte *)pData) + nLineSpace * iLine + iCol * nPixelSpace, eBufType, nPixelSpace, 1); } } } else { /* no complex data type */ return RealPixelFunc(papoSources, nSources, pData, nXSize, nYSize, eSrcType, eBufType, nPixelSpace, nLineSpace); } /* ---- Return success ---- */ return CE_None; } /* ConjPixelFunc */
CPLErr RawRasterBand::AccessBlock( vsi_l_offset nBlockOff, int nBlockSize, void * pData ) { int nBytesActuallyRead; /* -------------------------------------------------------------------- */ /* Seek to the right block. */ /* -------------------------------------------------------------------- */ if( Seek( nBlockOff, SEEK_SET ) == -1 ) { memset( pData, 0, nBlockSize ); return CE_None; } /* -------------------------------------------------------------------- */ /* Read the block. */ /* -------------------------------------------------------------------- */ nBytesActuallyRead = Read( pData, 1, nBlockSize ); if( nBytesActuallyRead < nBlockSize ) { memset( ((GByte *) pData) + nBytesActuallyRead, 0, nBlockSize - nBytesActuallyRead ); return CE_None; } /* -------------------------------------------------------------------- */ /* Byte swap the interesting data, if required. */ /* -------------------------------------------------------------------- */ if( !bNativeOrder && eDataType != GDT_Byte ) { if( GDALDataTypeIsComplex( eDataType ) ) { int nWordSize; nWordSize = GDALGetDataTypeSize(eDataType)/16; GDALSwapWords( pData, nWordSize, nBlockSize / nPixelOffset, nPixelOffset ); GDALSwapWords( ((GByte *) pData) + nWordSize, nWordSize, nBlockSize / nPixelOffset, nPixelOffset ); } else GDALSwapWords( pData, GDALGetDataTypeSize(eDataType) / 8, nBlockSize / nPixelOffset, nPixelOffset ); } return CE_None; }
Gdal::Band::Band(Gdal& owner_, GDALRasterBand *band_) : owner(owner_), band(band_) { size.cx = band->GetXSize(); size.cy = band->GetYSize(); band->GetBlockSize(&block_size.cx, &block_size.cy); block_count = idivceil(size, block_size); type = band->GetRasterDataType(); pixel_bytes = (GDALGetDataTypeSize(type) + 7) >> 3; complex = GDALDataTypeIsComplex(type); int nodata_flag; nodata_value = band->GetNoDataValue(&nodata_flag); is_nodata = !!nodata_flag; is_stat = false; nodata_int = fround(nodata_value); blocks.Alloc(block_count.cx * block_count.cy); }
static CPLErr ImagPixelFunc( void **papoSources, int nSources, void *pData, int nXSize, int nYSize, GDALDataType eSrcType, GDALDataType eBufType, int nPixelSpace, int nLineSpace ) { /* ---- Init ---- */ if( nSources != 1 ) return CE_Failure; if( GDALDataTypeIsComplex( eSrcType ) ) { const GDALDataType eSrcBaseType = GDALGetNonComplexDataType( eSrcType ); const int nPixelSpaceSrc = GDALGetDataTypeSizeBytes( eSrcType ); const int nLineSpaceSrc = nPixelSpaceSrc * nXSize; const void * const pImag = static_cast<GByte *>(papoSources[0]) + GDALGetDataTypeSizeBytes( eSrcType ) / 2; /* ---- Set pixels ---- */ for( int iLine = 0; iLine < nYSize; ++iLine ) { GDALCopyWords( static_cast<const GByte *>(pImag) + nLineSpaceSrc * iLine, eSrcBaseType, nPixelSpaceSrc, static_cast<GByte *>(pData) + nLineSpace * iLine, eBufType, nPixelSpace, nXSize ); } } else { const double dfImag = 0; /* ---- Set pixels ---- */ for( int iLine = 0; iLine < nYSize; ++iLine ) { // Always copy from the same location. GDALCopyWords( &dfImag, eSrcType, 0, static_cast<GByte *>(pData) + nLineSpace * iLine, eBufType, nPixelSpace, nXSize); } } /* ---- Return success ---- */ return CE_None; } // ImagPixelFunc
CPLErr ImagPixelFunc(void **papoSources, int nSources, void *pData, int nXSize, int nYSize, GDALDataType eSrcType, GDALDataType eBufType, int nPixelSpace, int nLineSpace) { int iLine; /* ---- Init ---- */ if (nSources != 1) return CE_Failure; if (GDALDataTypeIsComplex( eSrcType )) { int nPixelSpaceSrc = GDALGetDataTypeSize( eSrcType ) / 8; int nLineSpaceSrc = nPixelSpaceSrc * nXSize; void* pImag = ((GByte *)papoSources[0]) + GDALGetDataTypeSize( eSrcType ) / 8 / 2; /* ---- Set pixels ---- */ for( iLine = 0; iLine < nYSize; ++iLine ) { GDALCopyWords(((GByte *)pImag) + nLineSpaceSrc * iLine, eSrcType, nPixelSpaceSrc, ((GByte *)pData) + nLineSpace * iLine, eBufType, nPixelSpace, nXSize); } } else { double dfImag = 0; /* ---- Set pixels ---- */ for( iLine = 0; iLine < nYSize; ++iLine ) { /* always copy from the same location */ GDALCopyWords(&dfImag, eSrcType, 0, ((GByte *)pData) + nLineSpace * iLine, eBufType, nPixelSpace, nXSize); } } /* ---- Return success ---- */ return CE_None; } /* ImagPixelFunc */
CPLErr GTIFFBuildOverviews( const char * pszFilename, int nBands, GDALRasterBand **papoBandList, int nOverviews, int * panOverviewList, const char * pszResampling, GDALProgressFunc pfnProgress, void * pProgressData ) { if( nBands == 0 || nOverviews == 0 ) return CE_None; if( !GTiffOneTimeInit() ) return CE_Failure; TIFF *hOTIFF = nullptr; int nBitsPerPixel = 0; int nCompression = COMPRESSION_NONE; int nPhotometric = 0; int nSampleFormat = 0; int nPlanarConfig = 0; int iOverview = 0; int nXSize = 0; int nYSize = 0; /* -------------------------------------------------------------------- */ /* Verify that the list of bands is suitable for emitting in */ /* TIFF file. */ /* -------------------------------------------------------------------- */ for( int iBand = 0; iBand < nBands; iBand++ ) { int nBandBits = 0; int nBandFormat = 0; GDALRasterBand *hBand = papoBandList[iBand]; switch( hBand->GetRasterDataType() ) { case GDT_Byte: nBandBits = 8; nBandFormat = SAMPLEFORMAT_UINT; break; case GDT_UInt16: nBandBits = 16; nBandFormat = SAMPLEFORMAT_UINT; break; case GDT_Int16: nBandBits = 16; nBandFormat = SAMPLEFORMAT_INT; break; case GDT_UInt32: nBandBits = 32; nBandFormat = SAMPLEFORMAT_UINT; break; case GDT_Int32: nBandBits = 32; nBandFormat = SAMPLEFORMAT_INT; break; case GDT_Float32: nBandBits = 32; nBandFormat = SAMPLEFORMAT_IEEEFP; break; case GDT_Float64: nBandBits = 64; nBandFormat = SAMPLEFORMAT_IEEEFP; break; case GDT_CInt16: nBandBits = 32; nBandFormat = SAMPLEFORMAT_COMPLEXINT; break; case GDT_CInt32: nBandBits = 64; nBandFormat = SAMPLEFORMAT_COMPLEXINT; break; case GDT_CFloat32: nBandBits = 64; nBandFormat = SAMPLEFORMAT_COMPLEXIEEEFP; break; case GDT_CFloat64: nBandBits = 128; nBandFormat = SAMPLEFORMAT_COMPLEXIEEEFP; break; default: CPLAssert( false ); return CE_Failure; } if( hBand->GetMetadataItem( "NBITS", "IMAGE_STRUCTURE" ) ) { nBandBits = atoi(hBand->GetMetadataItem("NBITS", "IMAGE_STRUCTURE")); if( nBandBits == 1 && STARTS_WITH_CI(pszResampling, "AVERAGE_BIT2") ) nBandBits = 8; } if( iBand == 0 ) { nBitsPerPixel = nBandBits; nSampleFormat = nBandFormat; nXSize = hBand->GetXSize(); nYSize = hBand->GetYSize(); } else if( nBitsPerPixel != nBandBits || nSampleFormat != nBandFormat ) { CPLError( CE_Failure, CPLE_NotSupported, "GTIFFBuildOverviews() doesn't support a mixture of band" " data types." ); return CE_Failure; } else if( hBand->GetColorTable() != nullptr ) { CPLError( CE_Failure, CPLE_NotSupported, "GTIFFBuildOverviews() doesn't support building" " overviews of multiple colormapped bands." ); return CE_Failure; } else if( hBand->GetXSize() != nXSize || hBand->GetYSize() != nYSize ) { CPLError( CE_Failure, CPLE_NotSupported, "GTIFFBuildOverviews() doesn't support building" " overviews of different sized bands." ); return CE_Failure; } } /* -------------------------------------------------------------------- */ /* Use specified compression method. */ /* -------------------------------------------------------------------- */ const char *pszCompress = CPLGetConfigOption( "COMPRESS_OVERVIEW", nullptr ); if( pszCompress != nullptr && pszCompress[0] != '\0' ) { nCompression = GTIFFGetCompressionMethod(pszCompress, "COMPRESS_OVERVIEW"); if( nCompression < 0 ) return CE_Failure; } if( nCompression == COMPRESSION_JPEG && nBitsPerPixel > 8 ) { if( nBitsPerPixel > 16 ) { CPLError( CE_Failure, CPLE_NotSupported, "GTIFFBuildOverviews() doesn't support building" " JPEG compressed overviews of nBitsPerPixel > 16." ); return CE_Failure; } nBitsPerPixel = 12; } /* -------------------------------------------------------------------- */ /* Figure out the planar configuration to use. */ /* -------------------------------------------------------------------- */ if( nBands == 1 ) nPlanarConfig = PLANARCONFIG_CONTIG; else nPlanarConfig = PLANARCONFIG_SEPARATE; bool bSourceIsPixelInterleaved = false; bool bSourceIsJPEG2000 = false; if( nBands > 1 ) { GDALDataset* poSrcDS = papoBandList[0]->GetDataset(); if( poSrcDS ) { const char* pszSrcInterleave = poSrcDS->GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE"); if( pszSrcInterleave && EQUAL(pszSrcInterleave, "PIXEL") ) { bSourceIsPixelInterleaved = true; } } const char* pszSrcCompression = papoBandList[0]->GetMetadataItem("COMPRESSION", "IMAGE_STRUCTURE"); if( pszSrcCompression ) { bSourceIsJPEG2000 = EQUAL(pszSrcCompression, "JPEG2000"); } if( bSourceIsPixelInterleaved && bSourceIsJPEG2000 ) { nPlanarConfig = PLANARCONFIG_CONTIG; } } const char* pszInterleave = CPLGetConfigOption( "INTERLEAVE_OVERVIEW", nullptr ); if( pszInterleave != nullptr && pszInterleave[0] != '\0' ) { if( EQUAL( pszInterleave, "PIXEL" ) ) nPlanarConfig = PLANARCONFIG_CONTIG; else if( EQUAL( pszInterleave, "BAND" ) ) nPlanarConfig = PLANARCONFIG_SEPARATE; else { CPLError( CE_Failure, CPLE_AppDefined, "INTERLEAVE_OVERVIEW=%s unsupported, " "value must be PIXEL or BAND. ignoring", pszInterleave ); } } /* -------------------------------------------------------------------- */ /* Figure out the photometric interpretation to use. */ /* -------------------------------------------------------------------- */ if( nBands == 3 ) nPhotometric = PHOTOMETRIC_RGB; else if( papoBandList[0]->GetColorTable() != nullptr && !STARTS_WITH_CI(pszResampling, "AVERAGE_BIT2") ) { nPhotometric = PHOTOMETRIC_PALETTE; // Should set the colormap up at this point too! } else if( nBands >= 3 && papoBandList[0]->GetColorInterpretation() == GCI_RedBand && papoBandList[1]->GetColorInterpretation() == GCI_GreenBand && papoBandList[2]->GetColorInterpretation() == GCI_BlueBand ) { nPhotometric = PHOTOMETRIC_RGB; } else nPhotometric = PHOTOMETRIC_MINISBLACK; const char* pszPhotometric = CPLGetConfigOption( "PHOTOMETRIC_OVERVIEW", nullptr ); if( pszPhotometric != nullptr && pszPhotometric[0] != '\0' ) { if( EQUAL( pszPhotometric, "MINISBLACK" ) ) nPhotometric = PHOTOMETRIC_MINISBLACK; else if( EQUAL( pszPhotometric, "MINISWHITE" ) ) nPhotometric = PHOTOMETRIC_MINISWHITE; else if( EQUAL( pszPhotometric, "RGB" )) { nPhotometric = PHOTOMETRIC_RGB; } else if( EQUAL( pszPhotometric, "CMYK" )) { nPhotometric = PHOTOMETRIC_SEPARATED; } else if( EQUAL( pszPhotometric, "YCBCR" )) { nPhotometric = PHOTOMETRIC_YCBCR; // Because of subsampling, setting YCBCR without JPEG compression // leads to a crash currently. Would need to make // GTiffRasterBand::IWriteBlock() aware of subsampling so that it // doesn't overrun buffer size returned by libtiff. if( nCompression != COMPRESSION_JPEG ) { CPLError( CE_Failure, CPLE_NotSupported, "Currently, PHOTOMETRIC_OVERVIEW=YCBCR requires " "COMPRESS_OVERVIEW=JPEG" ); return CE_Failure; } if( pszInterleave != nullptr && pszInterleave[0] != '\0' && nPlanarConfig == PLANARCONFIG_SEPARATE ) { CPLError( CE_Failure, CPLE_NotSupported, "PHOTOMETRIC_OVERVIEW=YCBCR requires " "INTERLEAVE_OVERVIEW=PIXEL" ); return CE_Failure; } else { nPlanarConfig = PLANARCONFIG_CONTIG; } // YCBCR strictly requires 3 bands. Not less, not more // Issue an explicit error message as libtiff one is a bit cryptic: // JPEGLib:Bogus input colorspace. if( nBands != 3 ) { CPLError( CE_Failure, CPLE_NotSupported, "PHOTOMETRIC_OVERVIEW=YCBCR requires a source raster " "with only 3 bands (RGB)" ); return CE_Failure; } } else if( EQUAL( pszPhotometric, "CIELAB" )) { nPhotometric = PHOTOMETRIC_CIELAB; } else if( EQUAL( pszPhotometric, "ICCLAB" )) { nPhotometric = PHOTOMETRIC_ICCLAB; } else if( EQUAL( pszPhotometric, "ITULAB" )) { nPhotometric = PHOTOMETRIC_ITULAB; } else { CPLError( CE_Warning, CPLE_IllegalArg, "PHOTOMETRIC_OVERVIEW=%s value not recognised, ignoring.", pszPhotometric ); } } /* -------------------------------------------------------------------- */ /* Figure out the predictor value to use. */ /* -------------------------------------------------------------------- */ int nPredictor = PREDICTOR_NONE; if( nCompression == COMPRESSION_LZW || nCompression == COMPRESSION_ADOBE_DEFLATE ) { const char* pszPredictor = CPLGetConfigOption( "PREDICTOR_OVERVIEW", nullptr ); if( pszPredictor != nullptr ) { nPredictor = atoi( pszPredictor ); } } /* -------------------------------------------------------------------- */ /* Create the file, if it does not already exist. */ /* -------------------------------------------------------------------- */ VSIStatBufL sStatBuf; VSILFILE* fpL = nullptr; if( VSIStatExL( pszFilename, &sStatBuf, VSI_STAT_EXISTS_FLAG ) != 0 ) { /* -------------------------------------------------------------------- */ /* Compute the uncompressed size. */ /* -------------------------------------------------------------------- */ double dfUncompressedOverviewSize = 0; int nDataTypeSize = GDALGetDataTypeSizeBytes(papoBandList[0]->GetRasterDataType()); for( iOverview = 0; iOverview < nOverviews; iOverview++ ) { const int nOXSize = (nXSize + panOverviewList[iOverview] - 1) / panOverviewList[iOverview]; const int nOYSize = (nYSize + panOverviewList[iOverview] - 1) / panOverviewList[iOverview]; dfUncompressedOverviewSize += nOXSize * static_cast<double>(nOYSize) * nBands * nDataTypeSize; } if( nCompression == COMPRESSION_NONE && dfUncompressedOverviewSize > 4200000000.0 ) { #ifndef BIGTIFF_SUPPORT CPLError( CE_Failure, CPLE_NotSupported, "The overview file would be larger than 4GB, " "but this is the largest size a TIFF can be, " "and BigTIFF is unavailable. " "Creation failed." ); return CE_Failure; #endif } /* -------------------------------------------------------------------- */ /* Should the file be created as a bigtiff file? */ /* -------------------------------------------------------------------- */ const char *pszBIGTIFF = CPLGetConfigOption( "BIGTIFF_OVERVIEW", nullptr ); if( pszBIGTIFF == nullptr ) pszBIGTIFF = "IF_SAFER"; bool bCreateBigTIFF = false; if( EQUAL(pszBIGTIFF,"IF_NEEDED") ) { if( nCompression == COMPRESSION_NONE && dfUncompressedOverviewSize > 4200000000.0 ) bCreateBigTIFF = true; } else if( EQUAL(pszBIGTIFF,"IF_SAFER") ) { // Look at the size of the base image and suppose that // the added overview levels won't be more than 1/2 of // the size of the base image. The theory says 1/3 of the // base image size if the overview levels are 2, 4, 8, 16. // Thus take 1/2 as the security margin for 1/3. const double dfUncompressedImageSize = nXSize * static_cast<double>(nYSize) * nBands * nDataTypeSize; if( dfUncompressedImageSize * 0.5 > 4200000000.0 ) bCreateBigTIFF = true; } else { bCreateBigTIFF = CPLTestBool( pszBIGTIFF ); if( !bCreateBigTIFF && nCompression == COMPRESSION_NONE && dfUncompressedOverviewSize > 4200000000.0 ) { CPLError( CE_Failure, CPLE_NotSupported, "The overview file will be larger than 4GB, " "so BigTIFF is necessary. " "Creation failed."); return CE_Failure; } } #ifndef BIGTIFF_SUPPORT if( bCreateBigTIFF ) { CPLError( CE_Warning, CPLE_NotSupported, "BigTIFF requested, but GDAL built without BigTIFF " "enabled libtiff, request ignored." ); bCreateBigTIFF = false; } #endif if( bCreateBigTIFF ) CPLDebug( "GTiff", "File being created as a BigTIFF." ); fpL = VSIFOpenL( pszFilename, "w+" ); if( fpL == nullptr ) hOTIFF = nullptr; else hOTIFF = VSI_TIFFOpen( pszFilename, bCreateBigTIFF ? "w+8" : "w+", fpL ); if( hOTIFF == nullptr ) { if( CPLGetLastErrorNo() == 0 ) CPLError( CE_Failure, CPLE_OpenFailed, "Attempt to create new tiff file `%s' " "failed in VSI_TIFFOpen().", pszFilename ); if( fpL != nullptr ) CPL_IGNORE_RET_VAL(VSIFCloseL(fpL)); return CE_Failure; } } /* -------------------------------------------------------------------- */ /* Otherwise just open it for update access. */ /* -------------------------------------------------------------------- */ else { fpL = VSIFOpenL( pszFilename, "r+" ); if( fpL == nullptr ) hOTIFF = nullptr; else hOTIFF = VSI_TIFFOpen( pszFilename, "r+", fpL ); if( hOTIFF == nullptr ) { if( CPLGetLastErrorNo() == 0 ) CPLError( CE_Failure, CPLE_OpenFailed, "Attempt to create new tiff file `%s' " "failed in VSI_TIFFOpen().", pszFilename ); if( fpL != nullptr ) CPL_IGNORE_RET_VAL(VSIFCloseL(fpL)); return CE_Failure; } } /* -------------------------------------------------------------------- */ /* Do we have a palette? If so, create a TIFF compatible version. */ /* -------------------------------------------------------------------- */ unsigned short *panRed = nullptr; unsigned short *panGreen = nullptr; unsigned short *panBlue = nullptr; if( nPhotometric == PHOTOMETRIC_PALETTE ) { GDALColorTable *poCT = papoBandList[0]->GetColorTable(); int nColorCount = 65536; if( nBitsPerPixel <= 8 ) nColorCount = 256; panRed = static_cast<unsigned short *>( CPLCalloc(nColorCount, sizeof(unsigned short)) ); panGreen = static_cast<unsigned short *>( CPLCalloc(nColorCount, sizeof(unsigned short)) ); panBlue = static_cast<unsigned short *>( CPLCalloc(nColorCount, sizeof(unsigned short)) ); for( int iColor = 0; iColor < nColorCount; iColor++ ) { GDALColorEntry sRGB = { 0, 0, 0, 0 }; if( poCT->GetColorEntryAsRGB( iColor, &sRGB ) ) { // TODO(schwehr): Check for underflow. // Going from signed short to unsigned short. panRed[iColor] = static_cast<unsigned short>(257 * sRGB.c1); panGreen[iColor] = static_cast<unsigned short>(257 * sRGB.c2); panBlue[iColor] = static_cast<unsigned short>(257 * sRGB.c3); } } } /* -------------------------------------------------------------------- */ /* Do we need some metadata for the overviews? */ /* -------------------------------------------------------------------- */ CPLString osMetadata; GDALDataset *poBaseDS = papoBandList[0]->GetDataset(); GTIFFBuildOverviewMetadata( pszResampling, poBaseDS, osMetadata ); /* -------------------------------------------------------------------- */ /* Loop, creating overviews. */ /* -------------------------------------------------------------------- */ int nOvrBlockXSize = 0; int nOvrBlockYSize = 0; GTIFFGetOverviewBlockSize(&nOvrBlockXSize, &nOvrBlockYSize); CPLString osNoData; // don't move this in inner scope const char* pszNoData = nullptr; int bNoDataSet = FALSE; const double dfNoDataValue = papoBandList[0]->GetNoDataValue(&bNoDataSet); if( bNoDataSet ) { osNoData = GTiffFormatGDALNoDataTagValue(dfNoDataValue); pszNoData = osNoData.c_str(); } std::vector<uint16> anExtraSamples; for( int i = GTIFFGetMaxColorChannels(nPhotometric)+1; i <= nBands; i++ ) { if( papoBandList[i-1]->GetColorInterpretation() == GCI_AlphaBand ) { anExtraSamples.push_back( GTiffGetAlphaValue(CPLGetConfigOption("GTIFF_ALPHA", nullptr), DEFAULT_ALPHA_TYPE)); } else { anExtraSamples.push_back(EXTRASAMPLE_UNSPECIFIED); } } for( iOverview = 0; iOverview < nOverviews; iOverview++ ) { const int nOXSize = (nXSize + panOverviewList[iOverview] - 1) / panOverviewList[iOverview]; const int nOYSize = (nYSize + panOverviewList[iOverview] - 1) / panOverviewList[iOverview]; GTIFFWriteDirectory( hOTIFF, FILETYPE_REDUCEDIMAGE, nOXSize, nOYSize, nBitsPerPixel, nPlanarConfig, nBands, nOvrBlockXSize, nOvrBlockYSize, TRUE, nCompression, nPhotometric, nSampleFormat, nPredictor, panRed, panGreen, panBlue, static_cast<int>(anExtraSamples.size()), anExtraSamples.empty() ? nullptr : anExtraSamples.data(), osMetadata, CPLGetConfigOption( "JPEG_QUALITY_OVERVIEW", nullptr ), CPLGetConfigOption( "JPEG_TABLESMODE_OVERVIEW", nullptr ), pszNoData, nullptr ); } if( panRed ) { CPLFree(panRed); CPLFree(panGreen); CPLFree(panBlue); panRed = nullptr; panGreen = nullptr; panBlue = nullptr; } XTIFFClose( hOTIFF ); if( VSIFCloseL(fpL) != 0 ) return CE_Failure; fpL = nullptr; /* -------------------------------------------------------------------- */ /* Open the overview dataset so that we can get at the overview */ /* bands. */ /* -------------------------------------------------------------------- */ GDALDataset *hODS = GDALDataset::Open( pszFilename, GDAL_OF_RASTER | GDAL_OF_UPDATE ); if( hODS == nullptr ) return CE_Failure; /* -------------------------------------------------------------------- */ /* Do we need to set the jpeg quality? */ /* -------------------------------------------------------------------- */ TIFF *hTIFF = static_cast<TIFF *>( hODS->GetInternalHandle(nullptr) ); if( nCompression == COMPRESSION_JPEG && CPLGetConfigOption( "JPEG_QUALITY_OVERVIEW", nullptr ) != nullptr ) { const int nJpegQuality = atoi(CPLGetConfigOption("JPEG_QUALITY_OVERVIEW","75")); TIFFSetField( hTIFF, TIFFTAG_JPEGQUALITY, nJpegQuality ); GTIFFSetJpegQuality(GDALDataset::ToHandle(hODS), nJpegQuality); } if( nCompression == COMPRESSION_JPEG && CPLGetConfigOption( "JPEG_TABLESMODE_OVERVIEW", nullptr ) != nullptr ) { const int nJpegTablesMode = atoi(CPLGetConfigOption("JPEG_TABLESMODE_OVERVIEW", CPLSPrintf("%d", knGTIFFJpegTablesModeDefault))); TIFFSetField( hTIFF, TIFFTAG_JPEGTABLESMODE, nJpegTablesMode ); GTIFFSetJpegTablesMode(GDALDataset::ToHandle(hODS), nJpegTablesMode); } /* -------------------------------------------------------------------- */ /* Loop writing overview data. */ /* -------------------------------------------------------------------- */ int *panOverviewListSorted = static_cast<int*>(CPLMalloc(sizeof(int) * nOverviews)); memcpy( panOverviewListSorted, panOverviewList, sizeof(int) * nOverviews); std::sort(panOverviewListSorted, panOverviewListSorted + nOverviews); GTIFFSetInExternalOvr(true); CPLErr eErr = CE_None; if( ((bSourceIsPixelInterleaved && bSourceIsJPEG2000) || (nCompression != COMPRESSION_NONE)) && nPlanarConfig == PLANARCONFIG_CONTIG && !GDALDataTypeIsComplex(papoBandList[0]->GetRasterDataType()) && papoBandList[0]->GetColorTable() == nullptr && (STARTS_WITH_CI(pszResampling, "NEAR") || EQUAL(pszResampling, "AVERAGE") || EQUAL(pszResampling, "GAUSS") || EQUAL(pszResampling, "CUBIC") || EQUAL(pszResampling, "CUBICSPLINE") || EQUAL(pszResampling, "LANCZOS") || EQUAL(pszResampling, "BILINEAR")) ) { // In the case of pixel interleaved compressed overviews, we want to // generate the overviews for all the bands block by block, and not // band after band, in order to write the block once and not loose // space in the TIFF file. GDALRasterBand ***papapoOverviewBands = static_cast<GDALRasterBand ***>( CPLCalloc(sizeof(void *), nBands) ); for( int iBand = 0; iBand < nBands && eErr == CE_None; iBand++ ) { GDALRasterBand *poSrcBand = papoBandList[iBand]; GDALRasterBand *poDstBand = hODS->GetRasterBand( iBand + 1 ); papapoOverviewBands[iBand] = static_cast<GDALRasterBand **>( CPLCalloc(sizeof(void *), nOverviews) ); int bHasNoData = FALSE; const double noDataValue = poSrcBand->GetNoDataValue(&bHasNoData); if( bHasNoData ) poDstBand->SetNoDataValue(noDataValue); for( int i = 0; i < nOverviews && eErr == CE_None; i++ ) { for( int j = -1; j < poDstBand->GetOverviewCount() && eErr == CE_None; j++ ) { GDALRasterBand * poOverview = (j < 0 ) ? poDstBand : poDstBand->GetOverview( j ); if( poOverview == nullptr ) { eErr = CE_Failure; continue; } const int nOvFactor = GDALComputeOvFactor(poOverview->GetXSize(), poSrcBand->GetXSize(), poOverview->GetYSize(), poSrcBand->GetYSize()); if( nOvFactor == panOverviewListSorted[i] || nOvFactor == GDALOvLevelAdjust2( panOverviewListSorted[i], poSrcBand->GetXSize(), poSrcBand->GetYSize() ) ) { papapoOverviewBands[iBand][i] = poOverview; if( bHasNoData ) poOverview->SetNoDataValue(noDataValue); break; } } CPLAssert( papapoOverviewBands[iBand][i] != nullptr ); } } if( eErr == CE_None ) eErr = GDALRegenerateOverviewsMultiBand( nBands, papoBandList, nOverviews, papapoOverviewBands, pszResampling, pfnProgress, pProgressData ); for( int iBand = 0; iBand < nBands; iBand++ ) { CPLFree(papapoOverviewBands[iBand]); } CPLFree(papapoOverviewBands); } else { GDALRasterBand **papoOverviews = static_cast<GDALRasterBand **>( CPLCalloc( sizeof(void*), knMaxOverviews ) ); for( int iBand = 0; iBand < nBands && eErr == CE_None; iBand++ ) { GDALRasterBand *hSrcBand = papoBandList[iBand]; GDALRasterBand *hDstBand = hODS->GetRasterBand( iBand + 1 ); int bHasNoData = FALSE; const double noDataValue = hSrcBand->GetNoDataValue(&bHasNoData); if( bHasNoData ) hDstBand->SetNoDataValue(noDataValue); // FIXME: this logic regenerates all overview bands, not only the // ones requested. papoOverviews[0] = hDstBand; int nDstOverviews = hDstBand->GetOverviewCount() + 1; CPLAssert( nDstOverviews < knMaxOverviews ); nDstOverviews = std::min(knMaxOverviews, nDstOverviews); // TODO(schwehr): Convert to starting with i = 1 and remove +1. for( int i = 0; i < nDstOverviews - 1 && eErr == CE_None; i++ ) { papoOverviews[i+1] = hDstBand->GetOverview(i); if( papoOverviews[i+1] == nullptr ) { eErr = CE_Failure; } else { if( bHasNoData ) papoOverviews[i+1]->SetNoDataValue(noDataValue); } } void *pScaledProgressData = GDALCreateScaledProgress( iBand / static_cast<double>( nBands ), (iBand + 1) / static_cast<double>( nBands ), pfnProgress, pProgressData ); if( eErr == CE_None ) eErr = GDALRegenerateOverviews( hSrcBand, nDstOverviews, reinterpret_cast<GDALRasterBandH *>( papoOverviews ), pszResampling, GDALScaledProgress, pScaledProgressData ); GDALDestroyScaledProgress( pScaledProgressData ); } CPLFree( papoOverviews ); } /* -------------------------------------------------------------------- */ /* Cleanup */ /* -------------------------------------------------------------------- */ if( eErr == CE_None ) hODS->FlushCache(); delete hODS; GTIFFSetInExternalOvr(false); CPLFree(panOverviewListSorted); pfnProgress( 1.0, nullptr, pProgressData ); return eErr; }
CPLErr VRTFilteredSource::RasterIO( GDALDataType eBandDataType, int nXOff, int nYOff, int nXSize, int nYSize, void *pData, int nBufXSize, int nBufYSize, GDALDataType eBufType, GSpacing nPixelSpace, GSpacing nLineSpace, GDALRasterIOExtraArg* psExtraArg ) { /* -------------------------------------------------------------------- */ /* For now we don't support filtered access to non-full */ /* resolution requests. Just collect the data directly without */ /* any operator. */ /* -------------------------------------------------------------------- */ if( nBufXSize != nXSize || nBufYSize != nYSize ) { return VRTComplexSource::RasterIO( eBandDataType, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize, eBufType, nPixelSpace, nLineSpace, psExtraArg ); } // The window we will actually request from the source raster band. double dfReqXOff = 0.0; double dfReqYOff = 0.0; double dfReqXSize = 0.0; double dfReqYSize = 0.0; int nReqXOff = 0; int nReqYOff = 0; int nReqXSize = 0; int nReqYSize = 0; // The window we will actual set _within_ the pData buffer. int nOutXOff = 0; int nOutYOff = 0; int nOutXSize = 0; int nOutYSize = 0; if( !GetSrcDstWindow( nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, &dfReqXOff, &dfReqYOff, &dfReqXSize, &dfReqYSize, &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize, &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) ) return CE_None; pData = reinterpret_cast<GByte *>( pData ) + nPixelSpace * nOutXOff + nLineSpace * nOutYOff; /* -------------------------------------------------------------------- */ /* Determine the data type we want to request. We try to match */ /* the source or destination request, and if both those fail we */ /* fallback to the first supported type at least as expressive */ /* as the request. */ /* -------------------------------------------------------------------- */ GDALDataType eOperDataType = GDT_Unknown; if( IsTypeSupported( eBufType ) ) eOperDataType = eBufType; if( eOperDataType == GDT_Unknown && IsTypeSupported( m_poRasterBand->GetRasterDataType() ) ) eOperDataType = m_poRasterBand->GetRasterDataType(); if( eOperDataType == GDT_Unknown ) { for( int i = 0; i < m_nSupportedTypesCount; i++ ) { if( GDALDataTypeUnion( m_aeSupportedTypes[i], eBufType ) == m_aeSupportedTypes[i] ) { eOperDataType = m_aeSupportedTypes[i]; } } } if( eOperDataType == GDT_Unknown ) { eOperDataType = m_aeSupportedTypes[0]; for( int i = 1; i < m_nSupportedTypesCount; i++ ) { if( GDALGetDataTypeSize( m_aeSupportedTypes[i] ) > GDALGetDataTypeSize( eOperDataType ) ) { eOperDataType = m_aeSupportedTypes[i]; } } } /* -------------------------------------------------------------------- */ /* Allocate the buffer of data into which our imagery will be */ /* read, with the extra edge pixels as well. This will be the */ /* source data fed into the filter. */ /* -------------------------------------------------------------------- */ if( nOutXSize > INT_MAX - 2 * m_nExtraEdgePixels || nOutYSize > INT_MAX - 2 * m_nExtraEdgePixels ) { return CE_Failure; } const int nExtraXSize = nOutXSize + 2 * m_nExtraEdgePixels; const int nExtraYSize = nOutYSize + 2 * m_nExtraEdgePixels; GByte *pabyWorkData = static_cast<GByte *>( VSI_MALLOC3_VERBOSE( nExtraXSize, nExtraYSize, GDALGetDataTypeSizeBytes(eOperDataType)) ); if( pabyWorkData == nullptr ) { return CE_Failure; } const GPtrDiff_t nPixelOffset = GDALGetDataTypeSizeBytes( eOperDataType ); const GPtrDiff_t nLineOffset = nPixelOffset * nExtraXSize; memset( pabyWorkData, 0, nLineOffset * nExtraYSize ); /* -------------------------------------------------------------------- */ /* Allocate the output buffer in the same dimensions as the work */ /* buffer. This allows the filter process to write edge pixels */ /* if needed for two-pass (separable) filtering. */ /* -------------------------------------------------------------------- */ GByte *pabyOutData = static_cast<GByte *>( VSI_MALLOC3_VERBOSE( nExtraXSize, nExtraYSize, nPixelOffset ) ); if( pabyOutData == nullptr ) { CPLFree( pabyWorkData ); return CE_Failure; } /* -------------------------------------------------------------------- */ /* Figure out the extended window that we want to load. Note */ /* that we keep track of the file window as well as the amount */ /* we will need to edge fill past the edge of the source dataset. */ /* -------------------------------------------------------------------- */ int nFileXOff = nReqXOff - m_nExtraEdgePixels; int nFileYOff = nReqYOff - m_nExtraEdgePixels; int nFileXSize = nExtraXSize; int nFileYSize = nExtraYSize; int nTopFill = 0; int nLeftFill = 0; int nRightFill = 0; int nBottomFill = 0; if( nFileXOff < 0 ) { nLeftFill = -nFileXOff; nFileXOff = 0; nFileXSize -= nLeftFill; } if( nFileYOff < 0 ) { nTopFill = -nFileYOff; nFileYOff = 0; nFileYSize -= nTopFill; } if( nFileXOff + nFileXSize > m_poRasterBand->GetXSize() ) { nRightFill = nFileXOff + nFileXSize - m_poRasterBand->GetXSize(); nFileXSize -= nRightFill; } if( nFileYOff + nFileYSize > m_poRasterBand->GetYSize() ) { nBottomFill = nFileYOff + nFileYSize - m_poRasterBand->GetYSize(); nFileYSize -= nBottomFill; } /* -------------------------------------------------------------------- */ /* Load the data. */ /* -------------------------------------------------------------------- */ { const bool bIsComplex = CPL_TO_BOOL( GDALDataTypeIsComplex(eOperDataType) ); const CPLErr eErr = VRTComplexSource::RasterIOInternal<float>( nFileXOff, nFileYOff, nFileXSize, nFileYSize, pabyWorkData + nLineOffset * nTopFill + nPixelOffset * nLeftFill, nFileXSize, nFileYSize, eOperDataType, nPixelOffset, nLineOffset, psExtraArg, bIsComplex ? GDT_CFloat32 : GDT_Float32 ); if( eErr != CE_None ) { VSIFree( pabyWorkData ); VSIFree( pabyOutData ); return eErr; } } /* -------------------------------------------------------------------- */ /* Fill in missing areas. Note that we replicate the edge */ /* valid values out. We don't using "mirroring" which might be */ /* more suitable for some times of filters. We also don't mark */ /* these pixels as "nodata" though perhaps we should. */ /* -------------------------------------------------------------------- */ if( nLeftFill != 0 || nRightFill != 0 ) { for( int i = nTopFill; i < nExtraYSize - nBottomFill; i++ ) { if( nLeftFill != 0 ) GDALCopyWords( pabyWorkData + nPixelOffset * nLeftFill + i * nLineOffset, eOperDataType, 0, pabyWorkData + i * nLineOffset, eOperDataType, static_cast<int>(nPixelOffset), nLeftFill ); if( nRightFill != 0 ) GDALCopyWords( pabyWorkData + i * nLineOffset + nPixelOffset * (nExtraXSize - nRightFill - 1), eOperDataType, 0, pabyWorkData + i * nLineOffset + nPixelOffset * (nExtraXSize - nRightFill), eOperDataType, static_cast<int>(nPixelOffset), nRightFill ); } } for( int i = 0; i < nTopFill; i++ ) { memcpy( pabyWorkData + i * nLineOffset, pabyWorkData + nTopFill * nLineOffset, nLineOffset ); } for( int i = nExtraYSize - nBottomFill; i < nExtraYSize; i++ ) { memcpy( pabyWorkData + i * nLineOffset, pabyWorkData + (nExtraYSize - nBottomFill - 1) * nLineOffset, nLineOffset ); } /* -------------------------------------------------------------------- */ /* Filter the data. */ /* -------------------------------------------------------------------- */ const CPLErr eErr = FilterData( nExtraXSize, nExtraYSize, eOperDataType, pabyWorkData, pabyOutData ); VSIFree( pabyWorkData ); if( eErr != CE_None ) { VSIFree( pabyOutData ); return eErr; } /* -------------------------------------------------------------------- */ /* Copy from work buffer to target buffer. */ /* -------------------------------------------------------------------- */ GByte *pabySrcRow = pabyOutData + (nLineOffset + nPixelOffset) * m_nExtraEdgePixels; GByte *pabyDstRow = reinterpret_cast<GByte *>( pData ); for( int i = 0; i < nOutYSize; i++, pabySrcRow += nLineOffset, pabyDstRow += nLineSpace ) { GDALCopyWords( pabySrcRow, eOperDataType, static_cast<int>(nPixelOffset), pabyDstRow, eBufType, static_cast<int>(nPixelSpace), nOutXSize ); } VSIFree( pabyOutData ); return CE_None; }
int main( int argc, char ** argv ) { const char *pszLocX = NULL, *pszLocY = NULL; const char *pszSrcFilename = NULL; char *pszSourceSRS = NULL; std::vector<int> anBandList; bool bAsXML = false, bLIFOnly = false; bool bQuiet = false, bValOnly = false; int nOverview = -1; char **papszOpenOptions = NULL; GDALAllRegister(); argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 ); if( argc < 1 ) exit( -argc ); /* -------------------------------------------------------------------- */ /* Parse arguments. */ /* -------------------------------------------------------------------- */ int i; for( i = 1; i < argc; i++ ) { if( EQUAL(argv[i], "--utility_version") ) { printf("%s was compiled against GDAL %s and is running against GDAL %s\n", argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME")); return 0; } else if( EQUAL(argv[i],"-b") && i < argc-1 ) { anBandList.push_back( atoi(argv[++i]) ); } else if( EQUAL(argv[i],"-overview") && i < argc-1 ) { nOverview = atoi(argv[++i]) - 1; } else if( EQUAL(argv[i],"-l_srs") && i < argc-1 ) { CPLFree(pszSourceSRS); pszSourceSRS = SanitizeSRS(argv[++i]); } else if( EQUAL(argv[i],"-geoloc") ) { CPLFree(pszSourceSRS); pszSourceSRS = CPLStrdup("-geoloc"); } else if( EQUAL(argv[i],"-wgs84") ) { CPLFree(pszSourceSRS); pszSourceSRS = SanitizeSRS("WGS84"); } else if( EQUAL(argv[i],"-xml") ) { bAsXML = true; } else if( EQUAL(argv[i],"-lifonly") ) { bLIFOnly = true; bQuiet = true; } else if( EQUAL(argv[i],"-valonly") ) { bValOnly = true; bQuiet = true; } else if( EQUAL(argv[i], "-oo") && i < argc-1 ) { papszOpenOptions = CSLAddString( papszOpenOptions, argv[++i] ); } else if( argv[i][0] == '-' && !isdigit(argv[i][1]) ) Usage(); else if( pszSrcFilename == NULL ) pszSrcFilename = argv[i]; else if( pszLocX == NULL ) pszLocX = argv[i]; else if( pszLocY == NULL ) pszLocY = argv[i]; else Usage(); } if( pszSrcFilename == NULL || (pszLocX != NULL && pszLocY == NULL) ) Usage(); /* -------------------------------------------------------------------- */ /* Open source file. */ /* -------------------------------------------------------------------- */ GDALDatasetH hSrcDS = NULL; hSrcDS = GDALOpenEx( pszSrcFilename, GDAL_OF_RASTER, NULL, (const char* const* )papszOpenOptions, NULL ); if( hSrcDS == NULL ) exit( 1 ); /* -------------------------------------------------------------------- */ /* Setup coordinate transformation, if required */ /* -------------------------------------------------------------------- */ OGRSpatialReferenceH hSrcSRS = NULL, hTrgSRS = NULL; OGRCoordinateTransformationH hCT = NULL; if( pszSourceSRS != NULL && !EQUAL(pszSourceSRS,"-geoloc") ) { hSrcSRS = OSRNewSpatialReference( pszSourceSRS ); hTrgSRS = OSRNewSpatialReference( GDALGetProjectionRef( hSrcDS ) ); hCT = OCTNewCoordinateTransformation( hSrcSRS, hTrgSRS ); if( hCT == NULL ) exit( 1 ); } /* -------------------------------------------------------------------- */ /* If no bands were requested, we will query them all. */ /* -------------------------------------------------------------------- */ if( anBandList.size() == 0 ) { for( i = 0; i < GDALGetRasterCount( hSrcDS ); i++ ) anBandList.push_back( i+1 ); } /* -------------------------------------------------------------------- */ /* Turn the location into a pixel and line location. */ /* -------------------------------------------------------------------- */ int inputAvailable = 1; double dfGeoX; double dfGeoY; CPLString osXML; if( pszLocX == NULL && pszLocY == NULL ) { if (fscanf(stdin, "%lf %lf", &dfGeoX, &dfGeoY) != 2) { inputAvailable = 0; } } else { dfGeoX = CPLAtof(pszLocX); dfGeoY = CPLAtof(pszLocY); } while (inputAvailable) { int iPixel, iLine; if (hCT) { if( !OCTTransform( hCT, 1, &dfGeoX, &dfGeoY, NULL ) ) exit( 1 ); } if( pszSourceSRS != NULL ) { double adfGeoTransform[6], adfInvGeoTransform[6]; if( GDALGetGeoTransform( hSrcDS, adfGeoTransform ) != CE_None ) { CPLError(CE_Failure, CPLE_AppDefined, "Cannot get geotransform"); exit( 1 ); } if( !GDALInvGeoTransform( adfGeoTransform, adfInvGeoTransform ) ) { CPLError(CE_Failure, CPLE_AppDefined, "Cannot invert geotransform"); exit( 1 ); } iPixel = (int) floor( adfInvGeoTransform[0] + adfInvGeoTransform[1] * dfGeoX + adfInvGeoTransform[2] * dfGeoY ); iLine = (int) floor( adfInvGeoTransform[3] + adfInvGeoTransform[4] * dfGeoX + adfInvGeoTransform[5] * dfGeoY ); } else { iPixel = (int) floor(dfGeoX); iLine = (int) floor(dfGeoY); } /* -------------------------------------------------------------------- */ /* Prepare report. */ /* -------------------------------------------------------------------- */ CPLString osLine; if( bAsXML ) { osLine.Printf( "<Report pixel=\"%d\" line=\"%d\">", iPixel, iLine ); osXML += osLine; } else if( !bQuiet ) { printf( "Report:\n" ); printf( " Location: (%dP,%dL)\n", iPixel, iLine ); } int bPixelReport = TRUE; if( iPixel < 0 || iLine < 0 || iPixel >= GDALGetRasterXSize( hSrcDS ) || iLine >= GDALGetRasterYSize( hSrcDS ) ) { if( bAsXML ) osXML += "<Alert>Location is off this file! No further details to report.</Alert>"; else if( bValOnly ) printf("\n"); else if( !bQuiet ) printf( "\nLocation is off this file! No further details to report.\n"); bPixelReport = FALSE; } /* -------------------------------------------------------------------- */ /* Process each band. */ /* -------------------------------------------------------------------- */ for( i = 0; bPixelReport && i < (int) anBandList.size(); i++ ) { GDALRasterBandH hBand = GDALGetRasterBand( hSrcDS, anBandList[i] ); int iPixelToQuery = iPixel; int iLineToQuery = iLine; if (nOverview >= 0 && hBand != NULL) { GDALRasterBandH hOvrBand = GDALGetOverview(hBand, nOverview); if (hOvrBand != NULL) { int nOvrXSize = GDALGetRasterBandXSize(hOvrBand); int nOvrYSize = GDALGetRasterBandYSize(hOvrBand); iPixelToQuery = (int)(0.5 + 1.0 * iPixel / GDALGetRasterXSize( hSrcDS ) * nOvrXSize); iLineToQuery = (int)(0.5 + 1.0 * iLine / GDALGetRasterYSize( hSrcDS ) * nOvrYSize); if (iPixelToQuery >= nOvrXSize) iPixelToQuery = nOvrXSize - 1; if (iLineToQuery >= nOvrYSize) iLineToQuery = nOvrYSize - 1; } else { CPLError(CE_Failure, CPLE_AppDefined, "Cannot get overview %d of band %d", nOverview + 1, anBandList[i] ); } hBand = hOvrBand; } if (hBand == NULL) continue; if( bAsXML ) { osLine.Printf( "<BandReport band=\"%d\">", anBandList[i] ); osXML += osLine; } else if( !bQuiet ) { printf( " Band %d:\n", anBandList[i] ); } /* -------------------------------------------------------------------- */ /* Request location info for this location. It is possible */ /* only the VRT driver actually supports this. */ /* -------------------------------------------------------------------- */ CPLString osItem; osItem.Printf( "Pixel_%d_%d", iPixelToQuery, iLineToQuery ); const char *pszLI = GDALGetMetadataItem( hBand, osItem, "LocationInfo"); if( pszLI != NULL ) { if( bAsXML ) osXML += pszLI; else if( !bQuiet ) printf( " %s\n", pszLI ); else if( bLIFOnly ) { /* Extract all files, if any. */ CPLXMLNode *psRoot = CPLParseXMLString( pszLI ); if( psRoot != NULL && psRoot->psChild != NULL && psRoot->eType == CXT_Element && EQUAL(psRoot->pszValue,"LocationInfo") ) { CPLXMLNode *psNode; for( psNode = psRoot->psChild; psNode != NULL; psNode = psNode->psNext ) { if( psNode->eType == CXT_Element && EQUAL(psNode->pszValue,"File") && psNode->psChild != NULL ) { char* pszUnescaped = CPLUnescapeString( psNode->psChild->pszValue, NULL, CPLES_XML); printf( "%s\n", pszUnescaped ); CPLFree(pszUnescaped); } } } CPLDestroyXMLNode( psRoot ); } } /* -------------------------------------------------------------------- */ /* Report the pixel value of this band. */ /* -------------------------------------------------------------------- */ double adfPixel[2]; if( GDALRasterIO( hBand, GF_Read, iPixelToQuery, iLineToQuery, 1, 1, adfPixel, 1, 1, GDT_CFloat64, 0, 0) == CE_None ) { CPLString osValue; if( GDALDataTypeIsComplex( GDALGetRasterDataType( hBand ) ) ) osValue.Printf( "%.15g+%.15gi", adfPixel[0], adfPixel[1] ); else osValue.Printf( "%.15g", adfPixel[0] ); if( bAsXML ) { osXML += "<Value>"; osXML += osValue; osXML += "</Value>"; } else if( !bQuiet ) printf( " Value: %s\n", osValue.c_str() ); else if( bValOnly ) printf( "%s\n", osValue.c_str() ); // Report unscaled if we have scale/offset values. int bSuccess; double dfOffset = GDALGetRasterOffset( hBand, &bSuccess ); double dfScale = GDALGetRasterScale( hBand, &bSuccess ); if( dfOffset != 0.0 || dfScale != 1.0 ) { adfPixel[0] = adfPixel[0] * dfScale + dfOffset; adfPixel[1] = adfPixel[1] * dfScale + dfOffset; if( GDALDataTypeIsComplex( GDALGetRasterDataType( hBand ) ) ) osValue.Printf( "%.15g+%.15gi", adfPixel[0], adfPixel[1] ); else osValue.Printf( "%.15g", adfPixel[0] ); if( bAsXML ) { osXML += "<DescaledValue>"; osXML += osValue; osXML += "</DescaledValue>"; } else if( !bQuiet ) printf( " Descaled Value: %s\n", osValue.c_str() ); } } if( bAsXML ) osXML += "</BandReport>"; } osXML += "</Report>"; if( (pszLocX != NULL && pszLocY != NULL) || (fscanf(stdin, "%lf %lf", &dfGeoX, &dfGeoY) != 2) ) { inputAvailable = 0; } } /* -------------------------------------------------------------------- */ /* Finalize xml report and print. */ /* -------------------------------------------------------------------- */ if( bAsXML ) { CPLXMLNode *psRoot; char *pszFormattedXML; psRoot = CPLParseXMLString( osXML ); pszFormattedXML = CPLSerializeXMLTree( psRoot ); CPLDestroyXMLNode( psRoot ); printf( "%s", pszFormattedXML ); CPLFree( pszFormattedXML ); } /* -------------------------------------------------------------------- */ /* Cleanup */ /* -------------------------------------------------------------------- */ if (hCT) { OSRDestroySpatialReference( hSrcSRS ); OSRDestroySpatialReference( hTrgSRS ); OCTDestroyCoordinateTransformation( hCT ); } if (hSrcDS) GDALClose(hSrcDS); GDALDumpOpenDatasets( stderr ); GDALDestroyDriverManager(); CPLFree(pszSourceSRS); CSLDestroy(papszOpenOptions); CSLDestroy( argv ); return 0; }
CPLErr GTIFFBuildOverviews( const char * pszFilename, int nBands, GDALRasterBand **papoBandList, int nOverviews, int * panOverviewList, const char * pszResampling, GDALProgressFunc pfnProgress, void * pProgressData ) { TIFF *hOTIFF; int nBitsPerPixel=0, nCompression=COMPRESSION_NONE, nPhotometric=0; int nSampleFormat=0, nPlanarConfig, iOverview, iBand; int nXSize=0, nYSize=0; if( nBands == 0 || nOverviews == 0 ) return CE_None; if (!GTiffOneTimeInit()) return CE_Failure; /* -------------------------------------------------------------------- */ /* Verify that the list of bands is suitable for emitting in */ /* TIFF file. */ /* -------------------------------------------------------------------- */ for( iBand = 0; iBand < nBands; iBand++ ) { int nBandBits, nBandFormat; GDALRasterBand *hBand = papoBandList[iBand]; switch( hBand->GetRasterDataType() ) { case GDT_Byte: nBandBits = 8; nBandFormat = SAMPLEFORMAT_UINT; break; case GDT_UInt16: nBandBits = 16; nBandFormat = SAMPLEFORMAT_UINT; break; case GDT_Int16: nBandBits = 16; nBandFormat = SAMPLEFORMAT_INT; break; case GDT_UInt32: nBandBits = 32; nBandFormat = SAMPLEFORMAT_UINT; break; case GDT_Int32: nBandBits = 32; nBandFormat = SAMPLEFORMAT_INT; break; case GDT_Float32: nBandBits = 32; nBandFormat = SAMPLEFORMAT_IEEEFP; break; case GDT_Float64: nBandBits = 64; nBandFormat = SAMPLEFORMAT_IEEEFP; break; case GDT_CInt16: nBandBits = 32; nBandFormat = SAMPLEFORMAT_COMPLEXINT; break; case GDT_CInt32: nBandBits = 64; nBandFormat = SAMPLEFORMAT_COMPLEXINT; break; case GDT_CFloat32: nBandBits = 64; nBandFormat = SAMPLEFORMAT_COMPLEXIEEEFP; break; case GDT_CFloat64: nBandBits = 128; nBandFormat = SAMPLEFORMAT_COMPLEXIEEEFP; break; default: CPLAssert( FALSE ); return CE_Failure; } if( hBand->GetMetadataItem( "NBITS", "IMAGE_STRUCTURE" ) ) { nBandBits = atoi(hBand->GetMetadataItem("NBITS","IMAGE_STRUCTURE")); if( nBandBits == 1 && EQUALN(pszResampling,"AVERAGE_BIT2",12) ) nBandBits = 8; } if( iBand == 0 ) { nBitsPerPixel = nBandBits; nSampleFormat = nBandFormat; nXSize = hBand->GetXSize(); nYSize = hBand->GetYSize(); } else if( nBitsPerPixel != nBandBits || nSampleFormat != nBandFormat ) { CPLError( CE_Failure, CPLE_NotSupported, "GTIFFBuildOverviews() doesn't support a mixture of band" " data types." ); return CE_Failure; } else if( hBand->GetColorTable() != NULL ) { CPLError( CE_Failure, CPLE_NotSupported, "GTIFFBuildOverviews() doesn't support building" " overviews of multiple colormapped bands." ); return CE_Failure; } else if( hBand->GetXSize() != nXSize || hBand->GetYSize() != nYSize ) { CPLError( CE_Failure, CPLE_NotSupported, "GTIFFBuildOverviews() doesn't support building" " overviews of different sized bands." ); return CE_Failure; } } /* -------------------------------------------------------------------- */ /* Use specified compression method. */ /* -------------------------------------------------------------------- */ const char *pszCompress = CPLGetConfigOption( "COMPRESS_OVERVIEW", NULL ); if( pszCompress != NULL && pszCompress[0] != '\0' ) { nCompression = GTIFFGetCompressionMethod(pszCompress, "COMPRESS_OVERVIEW"); if (nCompression < 0) return CE_Failure; } if( nCompression == COMPRESSION_JPEG && nBitsPerPixel > 8 ) { if( nBitsPerPixel > 16 ) { CPLError( CE_Failure, CPLE_NotSupported, "GTIFFBuildOverviews() doesn't support building" " JPEG compressed overviews of nBitsPerPixel > 16." ); return CE_Failure; } nBitsPerPixel = 12; } /* -------------------------------------------------------------------- */ /* Figure out the planar configuration to use. */ /* -------------------------------------------------------------------- */ if( nBands == 1 ) nPlanarConfig = PLANARCONFIG_CONTIG; else nPlanarConfig = PLANARCONFIG_SEPARATE; const char* pszInterleave = CPLGetConfigOption( "INTERLEAVE_OVERVIEW", NULL ); if (pszInterleave != NULL && pszInterleave[0] != '\0') { if( EQUAL( pszInterleave, "PIXEL" ) ) nPlanarConfig = PLANARCONFIG_CONTIG; else if( EQUAL( pszInterleave, "BAND" ) ) nPlanarConfig = PLANARCONFIG_SEPARATE; else { CPLError( CE_Failure, CPLE_AppDefined, "INTERLEAVE_OVERVIEW=%s unsupported, value must be PIXEL or BAND. ignoring", pszInterleave ); } } /* -------------------------------------------------------------------- */ /* Figure out the photometric interpretation to use. */ /* -------------------------------------------------------------------- */ if( nBands == 3 ) nPhotometric = PHOTOMETRIC_RGB; else if( papoBandList[0]->GetColorTable() != NULL && !EQUALN(pszResampling,"AVERAGE_BIT2",12) ) { nPhotometric = PHOTOMETRIC_PALETTE; /* should set the colormap up at this point too! */ } else nPhotometric = PHOTOMETRIC_MINISBLACK; const char* pszPhotometric = CPLGetConfigOption( "PHOTOMETRIC_OVERVIEW", NULL ); if (pszPhotometric != NULL && pszPhotometric[0] != '\0') { if( EQUAL( pszPhotometric, "MINISBLACK" ) ) nPhotometric = PHOTOMETRIC_MINISBLACK; else if( EQUAL( pszPhotometric, "MINISWHITE" ) ) nPhotometric = PHOTOMETRIC_MINISWHITE; else if( EQUAL( pszPhotometric, "RGB" )) { nPhotometric = PHOTOMETRIC_RGB; } else if( EQUAL( pszPhotometric, "CMYK" )) { nPhotometric = PHOTOMETRIC_SEPARATED; } else if( EQUAL( pszPhotometric, "YCBCR" )) { nPhotometric = PHOTOMETRIC_YCBCR; /* Because of subsampling, setting YCBCR without JPEG compression leads */ /* to a crash currently. Would need to make GTiffRasterBand::IWriteBlock() */ /* aware of subsampling so that it doesn't overrun buffer size returned */ /* by libtiff */ if ( nCompression != COMPRESSION_JPEG ) { CPLError(CE_Failure, CPLE_NotSupported, "Currently, PHOTOMETRIC_OVERVIEW=YCBCR requires COMPRESS_OVERVIEW=JPEG"); return CE_Failure; } if (pszInterleave != NULL && pszInterleave[0] != '\0' && nPlanarConfig == PLANARCONFIG_SEPARATE) { CPLError(CE_Failure, CPLE_NotSupported, "PHOTOMETRIC_OVERVIEW=YCBCR requires INTERLEAVE_OVERVIEW=PIXEL"); return CE_Failure; } else { nPlanarConfig = PLANARCONFIG_CONTIG; } /* YCBCR strictly requires 3 bands. Not less, not more */ /* Issue an explicit error message as libtiff one is a bit cryptic : */ /* JPEGLib:Bogus input colorspace */ if ( nBands != 3 ) { CPLError(CE_Failure, CPLE_NotSupported, "PHOTOMETRIC_OVERVIEW=YCBCR requires a source raster with only 3 bands (RGB)"); return CE_Failure; } } else if( EQUAL( pszPhotometric, "CIELAB" )) { nPhotometric = PHOTOMETRIC_CIELAB; } else if( EQUAL( pszPhotometric, "ICCLAB" )) { nPhotometric = PHOTOMETRIC_ICCLAB; } else if( EQUAL( pszPhotometric, "ITULAB" )) { nPhotometric = PHOTOMETRIC_ITULAB; } else { CPLError( CE_Warning, CPLE_IllegalArg, "PHOTOMETRIC_OVERVIEW=%s value not recognised, ignoring.\n", pszPhotometric ); } } /* -------------------------------------------------------------------- */ /* Figure out the predictor value to use. */ /* -------------------------------------------------------------------- */ int nPredictor = PREDICTOR_NONE; if ( nCompression == COMPRESSION_LZW || nCompression == COMPRESSION_ADOBE_DEFLATE ) { const char* pszPredictor = CPLGetConfigOption( "PREDICTOR_OVERVIEW", NULL ); if( pszPredictor != NULL ) { nPredictor = atoi( pszPredictor ); } } /* -------------------------------------------------------------------- */ /* Create the file, if it does not already exist. */ /* -------------------------------------------------------------------- */ VSIStatBufL sStatBuf; VSILFILE* fpL = NULL; if( VSIStatExL( pszFilename, &sStatBuf, VSI_STAT_EXISTS_FLAG ) != 0 ) { /* -------------------------------------------------------------------- */ /* Compute the uncompressed size. */ /* -------------------------------------------------------------------- */ double dfUncompressedOverviewSize = 0; int nDataTypeSize = GDALGetDataTypeSize(papoBandList[0]->GetRasterDataType())/8; for( iOverview = 0; iOverview < nOverviews; iOverview++ ) { int nOXSize, nOYSize; nOXSize = (nXSize + panOverviewList[iOverview] - 1) / panOverviewList[iOverview]; nOYSize = (nYSize + panOverviewList[iOverview] - 1) / panOverviewList[iOverview]; dfUncompressedOverviewSize += nOXSize * ((double)nOYSize) * nBands * nDataTypeSize; } if( nCompression == COMPRESSION_NONE && dfUncompressedOverviewSize > 4200000000.0 ) { #ifndef BIGTIFF_SUPPORT CPLError( CE_Failure, CPLE_NotSupported, "The overview file would be larger than 4GB\n" "but this is the largest size a TIFF can be, and BigTIFF is unavailable.\n" "Creation failed." ); return CE_Failure; #endif } /* -------------------------------------------------------------------- */ /* Should the file be created as a bigtiff file? */ /* -------------------------------------------------------------------- */ const char *pszBIGTIFF = CPLGetConfigOption( "BIGTIFF_OVERVIEW", NULL ); if( pszBIGTIFF == NULL ) pszBIGTIFF = "IF_NEEDED"; int bCreateBigTIFF = FALSE; if( EQUAL(pszBIGTIFF,"IF_NEEDED") ) { if( nCompression == COMPRESSION_NONE && dfUncompressedOverviewSize > 4200000000.0 ) bCreateBigTIFF = TRUE; } else if( EQUAL(pszBIGTIFF,"IF_SAFER") ) { /* Look at the size of the base image and suppose that */ /* the added overview levels won't be more than 1/2 of */ /* the size of the base image. The theory says 1/3 of the */ /* base image size if the overview levels are 2, 4, 8, 16... */ /* Thus take 1/2 as the security margin for 1/3 */ double dfUncompressedImageSize = nXSize * ((double)nYSize) * nBands * nDataTypeSize; if( dfUncompressedImageSize * .5 > 4200000000.0 ) bCreateBigTIFF = TRUE; } else { bCreateBigTIFF = CSLTestBoolean( pszBIGTIFF ); if (!bCreateBigTIFF && nCompression == COMPRESSION_NONE && dfUncompressedOverviewSize > 4200000000.0 ) { CPLError( CE_Failure, CPLE_NotSupported, "The overview file will be larger than 4GB, so BigTIFF is necessary.\n" "Creation failed."); return CE_Failure; } } #ifndef BIGTIFF_SUPPORT if( bCreateBigTIFF ) { CPLError( CE_Warning, CPLE_NotSupported, "BigTIFF requested, but GDAL built without BigTIFF\n" "enabled libtiff, request ignored." ); bCreateBigTIFF = FALSE; } #endif if( bCreateBigTIFF ) CPLDebug( "GTiff", "File being created as a BigTIFF." ); fpL = VSIFOpenL( pszFilename, "w+" ); if( fpL == NULL ) hOTIFF = NULL; else hOTIFF = VSI_TIFFOpen( pszFilename, (bCreateBigTIFF) ? "w+8" : "w+", fpL ); if( hOTIFF == NULL ) { if( CPLGetLastErrorNo() == 0 ) CPLError( CE_Failure, CPLE_OpenFailed, "Attempt to create new tiff file `%s'\n" "failed in VSI_TIFFOpen().\n", pszFilename ); if( fpL != NULL ) VSIFCloseL(fpL); return CE_Failure; } } /* -------------------------------------------------------------------- */ /* Otherwise just open it for update access. */ /* -------------------------------------------------------------------- */ else { fpL = VSIFOpenL( pszFilename, "r+" ); if( fpL == NULL ) hOTIFF = NULL; else hOTIFF = VSI_TIFFOpen( pszFilename, "r+", fpL ); if( hOTIFF == NULL ) { if( CPLGetLastErrorNo() == 0 ) CPLError( CE_Failure, CPLE_OpenFailed, "Attempt to create new tiff file `%s'\n" "failed in VSI_TIFFOpen().\n", pszFilename ); if( fpL != NULL ) VSIFCloseL(fpL); return CE_Failure; } } /* -------------------------------------------------------------------- */ /* Do we have a palette? If so, create a TIFF compatible version. */ /* -------------------------------------------------------------------- */ unsigned short *panRed=NULL, *panGreen=NULL, *panBlue=NULL; if( nPhotometric == PHOTOMETRIC_PALETTE ) { GDALColorTable *poCT = papoBandList[0]->GetColorTable(); int nColorCount; if( nBitsPerPixel <= 8 ) nColorCount = 256; else nColorCount = 65536; panRed = (unsigned short *) CPLCalloc(nColorCount,sizeof(unsigned short)); panGreen = (unsigned short *) CPLCalloc(nColorCount,sizeof(unsigned short)); panBlue = (unsigned short *) CPLCalloc(nColorCount,sizeof(unsigned short)); for( int iColor = 0; iColor < nColorCount; iColor++ ) { GDALColorEntry sRGB; if( poCT->GetColorEntryAsRGB( iColor, &sRGB ) ) { panRed[iColor] = (unsigned short) (257 * sRGB.c1); panGreen[iColor] = (unsigned short) (257 * sRGB.c2); panBlue[iColor] = (unsigned short) (257 * sRGB.c3); } } } /* -------------------------------------------------------------------- */ /* Do we need some metadata for the overviews? */ /* -------------------------------------------------------------------- */ CPLString osMetadata; GDALDataset *poBaseDS = papoBandList[0]->GetDataset(); GTIFFBuildOverviewMetadata( pszResampling, poBaseDS, osMetadata ); /* -------------------------------------------------------------------- */ /* Loop, creating overviews. */ /* -------------------------------------------------------------------- */ int nOvrBlockXSize, nOvrBlockYSize; GTIFFGetOverviewBlockSize(&nOvrBlockXSize, &nOvrBlockYSize); for( iOverview = 0; iOverview < nOverviews; iOverview++ ) { int nOXSize, nOYSize; nOXSize = (nXSize + panOverviewList[iOverview] - 1) / panOverviewList[iOverview]; nOYSize = (nYSize + panOverviewList[iOverview] - 1) / panOverviewList[iOverview]; GTIFFWriteDirectory(hOTIFF, FILETYPE_REDUCEDIMAGE, nOXSize, nOYSize, nBitsPerPixel, nPlanarConfig, nBands, nOvrBlockXSize, nOvrBlockYSize, TRUE, nCompression, nPhotometric, nSampleFormat, nPredictor, panRed, panGreen, panBlue, 0, NULL, /* FIXME? how can we fetch extrasamples */ osMetadata ); } if (panRed) { CPLFree(panRed); CPLFree(panGreen); CPLFree(panBlue); panRed = panGreen = panBlue = NULL; } XTIFFClose( hOTIFF ); VSIFCloseL(fpL); fpL = NULL; /* -------------------------------------------------------------------- */ /* Open the overview dataset so that we can get at the overview */ /* bands. */ /* -------------------------------------------------------------------- */ GDALDataset *hODS; CPLErr eErr = CE_None; hODS = (GDALDataset *) GDALOpen( pszFilename, GA_Update ); if( hODS == NULL ) return CE_Failure; /* -------------------------------------------------------------------- */ /* Do we need to set the jpeg quality? */ /* -------------------------------------------------------------------- */ TIFF *hTIFF = (TIFF*) hODS->GetInternalHandle(NULL); if( nCompression == COMPRESSION_JPEG && CPLGetConfigOption( "JPEG_QUALITY_OVERVIEW", NULL ) != NULL ) { int nJpegQuality = atoi(CPLGetConfigOption("JPEG_QUALITY_OVERVIEW","75")); TIFFSetField( hTIFF, TIFFTAG_JPEGQUALITY, nJpegQuality ); GTIFFSetJpegQuality((GDALDatasetH)hODS, nJpegQuality); } /* -------------------------------------------------------------------- */ /* Loop writing overview data. */ /* -------------------------------------------------------------------- */ if (nCompression != COMPRESSION_NONE && nPlanarConfig == PLANARCONFIG_CONTIG && GDALDataTypeIsComplex(papoBandList[0]->GetRasterDataType()) == FALSE && papoBandList[0]->GetColorTable() == NULL && (EQUALN(pszResampling, "NEAR", 4) || EQUAL(pszResampling, "AVERAGE") || EQUAL(pszResampling, "GAUSS") || EQUAL(pszResampling, "CUBIC") || EQUAL(pszResampling, "CUBICSPLINE") || EQUAL(pszResampling, "LANCZOS") || EQUAL(pszResampling, "BILINEAR"))) { /* In the case of pixel interleaved compressed overviews, we want to generate */ /* the overviews for all the bands block by block, and not band after band, */ /* in order to write the block once and not loose space in the TIFF file */ GDALRasterBand ***papapoOverviewBands; papapoOverviewBands = (GDALRasterBand ***) CPLCalloc(sizeof(void*),nBands); for( iBand = 0; iBand < nBands && eErr == CE_None; iBand++ ) { GDALRasterBand *hSrcBand = papoBandList[iBand]; GDALRasterBand *hDstBand = hODS->GetRasterBand( iBand+1 ); papapoOverviewBands[iBand] = (GDALRasterBand **) CPLCalloc(sizeof(void*),nOverviews); papapoOverviewBands[iBand][0] = hDstBand; int bHasNoData; double noDataValue = hSrcBand->GetNoDataValue(&bHasNoData); if (bHasNoData) hDstBand->SetNoDataValue(noDataValue); for( int i = 0; i < nOverviews-1 && eErr == CE_None; i++ ) { papapoOverviewBands[iBand][i+1] = hDstBand->GetOverview(i); if (papapoOverviewBands[iBand][i+1] == NULL) eErr = CE_Failure; else { if (bHasNoData) papapoOverviewBands[iBand][i+1]->SetNoDataValue(noDataValue); } } } if (eErr == CE_None) eErr = GDALRegenerateOverviewsMultiBand(nBands, papoBandList, nOverviews, papapoOverviewBands, pszResampling, pfnProgress, pProgressData ); for( iBand = 0; iBand < nBands; iBand++ ) { CPLFree(papapoOverviewBands[iBand]); } CPLFree(papapoOverviewBands); } else { GDALRasterBand **papoOverviews; papoOverviews = (GDALRasterBand **) CPLCalloc(sizeof(void*),128); for( iBand = 0; iBand < nBands && eErr == CE_None; iBand++ ) { GDALRasterBand *hSrcBand = papoBandList[iBand]; GDALRasterBand *hDstBand; int nDstOverviews; hDstBand = hODS->GetRasterBand( iBand+1 ); int bHasNoData; double noDataValue = hSrcBand->GetNoDataValue(&bHasNoData); if (bHasNoData) hDstBand->SetNoDataValue(noDataValue); papoOverviews[0] = hDstBand; nDstOverviews = hDstBand->GetOverviewCount() + 1; CPLAssert( nDstOverviews < 128 ); nDstOverviews = MIN(128,nDstOverviews); for( int i = 0; i < nDstOverviews-1 && eErr == CE_None; i++ ) { papoOverviews[i+1] = hDstBand->GetOverview(i); if (papoOverviews[i+1] == NULL) eErr = CE_Failure; else { if (bHasNoData) papoOverviews[i+1]->SetNoDataValue(noDataValue); } } void *pScaledProgressData; pScaledProgressData = GDALCreateScaledProgress( iBand / (double) nBands, (iBand+1) / (double) nBands, pfnProgress, pProgressData ); if (eErr == CE_None) eErr = GDALRegenerateOverviews( (GDALRasterBandH) hSrcBand, nDstOverviews, (GDALRasterBandH *) papoOverviews, pszResampling, GDALScaledProgress, pScaledProgressData); GDALDestroyScaledProgress( pScaledProgressData ); } CPLFree( papoOverviews ); } /* -------------------------------------------------------------------- */ /* Cleanup */ /* -------------------------------------------------------------------- */ if (eErr == CE_None) hODS->FlushCache(); delete hODS; pfnProgress( 1.0, NULL, pProgressData ); return eErr; }
CPLErr RawRasterBand::AccessLine( int iLine ) { if (pLineBuffer == NULL) return CE_Failure; if( nLoadedScanline == iLine ) return CE_None; /* -------------------------------------------------------------------- */ /* Figure out where to start reading. */ /* -------------------------------------------------------------------- */ vsi_l_offset nReadStart; if( nPixelOffset >= 0 ) nReadStart = nImgOffset + (vsi_l_offset)iLine * nLineOffset; else { nReadStart = nImgOffset + (vsi_l_offset)iLine * nLineOffset - ABS(nPixelOffset) * (nBlockXSize-1); } /* -------------------------------------------------------------------- */ /* Seek to the right line. */ /* -------------------------------------------------------------------- */ if( Seek(nReadStart, SEEK_SET) == -1 ) { if (poDS != NULL && poDS->GetAccess() == GA_ReadOnly) { CPLError( CE_Failure, CPLE_FileIO, "Failed to seek to scanline %d @ %d.\n", iLine, (int) (nImgOffset + (vsi_l_offset)iLine * nLineOffset) ); return CE_Failure; } else { memset( pLineBuffer, 0, nPixelOffset * nBlockXSize ); nLoadedScanline = iLine; return CE_None; } } /* -------------------------------------------------------------------- */ /* Read the line. Take care not to request any more bytes than */ /* are needed, and not to lose a partially successful scanline */ /* read. */ /* -------------------------------------------------------------------- */ int nBytesToRead, nBytesActuallyRead; nBytesToRead = ABS(nPixelOffset) * (nBlockXSize - 1) + GDALGetDataTypeSize(GetRasterDataType()) / 8; nBytesActuallyRead = Read( pLineBuffer, 1, nBytesToRead ); if( nBytesActuallyRead < nBlockXSize ) { if (poDS != NULL && poDS->GetAccess() == GA_ReadOnly) { CPLError( CE_Failure, CPLE_FileIO, "Failed to read scanline %d.\n", iLine); return CE_Failure; } else { memset( ((GByte *) pLineBuffer) + nBytesActuallyRead, 0, nBytesToRead - nBytesActuallyRead ); } } /* -------------------------------------------------------------------- */ /* Byte swap the interesting data, if required. */ /* -------------------------------------------------------------------- */ if( !bNativeOrder && eDataType != GDT_Byte ) { if( GDALDataTypeIsComplex( eDataType ) ) { int nWordSize; nWordSize = GDALGetDataTypeSize(eDataType)/16; GDALSwapWords( pLineBuffer, nWordSize, nBlockXSize, ABS(nPixelOffset) ); GDALSwapWords( ((GByte *) pLineBuffer)+nWordSize, nWordSize, nBlockXSize, ABS(nPixelOffset) ); } else GDALSwapWords( pLineBuffer, GDALGetDataTypeSize(eDataType)/8, nBlockXSize, ABS(nPixelOffset) ); } nLoadedScanline = iLine; return CE_None; }
CPLErr MulPixelFunc(void **papoSources, int nSources, void *pData, int nXSize, int nYSize, GDALDataType eSrcType, GDALDataType eBufType, int nPixelSpace, int nLineSpace) { int iLine, iCol, ii, iSrc; /* ---- Init ---- */ if (nSources < 2) return CE_Failure; /* ---- Set pixels ---- */ if (GDALDataTypeIsComplex( eSrcType )) { double adfPixVal[2], dfOldR, dfOldI, dfNewR, dfNewI; void *pReal, *pImag; int nOffset = GDALGetDataTypeSize( eSrcType ) / 8 / 2; /* ---- Set pixels ---- */ for( iLine = 0, ii= 0; iLine < nYSize; ++iLine ) { for( iCol = 0; iCol < nXSize; ++iCol, ++ii ) { adfPixVal[0] = 1.; adfPixVal[1] = 0.; for( iSrc = 0; iSrc < nSources; ++iSrc ) { pReal = papoSources[iSrc]; pImag = ((GByte *)pReal) + nOffset; dfOldR = adfPixVal[0]; dfOldI = adfPixVal[1]; /* Source raster pixels may be obtained with SRCVAL macro */ dfNewR = SRCVAL(pReal, eSrcType, ii); dfNewI = SRCVAL(pImag, eSrcType, ii); adfPixVal[0] = dfOldR * dfNewR - dfOldI * dfNewI; adfPixVal[1] = dfOldR * dfNewI + dfOldI * dfNewR; } GDALCopyWords(adfPixVal, GDT_CFloat64, 0, ((GByte *)pData) + nLineSpace * iLine + iCol * nPixelSpace, eBufType, nPixelSpace, 1); } } } else { /* non complex */ double dfPixVal; /* ---- Set pixels ---- */ for( iLine = 0, ii= 0; iLine < nYSize; ++iLine ) { for( iCol = 0; iCol < nXSize; ++iCol, ++ii ) { dfPixVal = 1; for( iSrc = 0; iSrc < nSources; ++iSrc ) { /* Source raster pixels may be obtained with SRCVAL macro */ dfPixVal *= SRCVAL(papoSources[iSrc], eSrcType, ii); } GDALCopyWords(&dfPixVal, GDT_Float64, 0, ((GByte *)pData) + nLineSpace * iLine + iCol * nPixelSpace, eBufType, nPixelSpace, 1); } } } /* ---- Return success ---- */ return CE_None; } /* MulPixelFunc */
CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize, void * pData, int nBufXSize, int nBufYSize, GDALDataType eBufType, int nPixelSpace, int nLineSpace ) { int nBandDataSize = GDALGetDataTypeSize(eDataType) / 8; int nBufDataSize = GDALGetDataTypeSize( eBufType ) / 8; int nBytesToRW = nPixelOffset * nXSize; if( !CanUseDirectIO(nXOff, nYOff, nXSize, nYSize, eBufType ) ) { return GDALRasterBand::IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize, eBufType, nPixelSpace, nLineSpace ); } CPLDebug("RAW", "Using direct IO implementation"); /* ==================================================================== */ /* Read data. */ /* ==================================================================== */ if ( eRWFlag == GF_Read ) { /* -------------------------------------------------------------------- */ /* Do we have overviews that would be appropriate to satisfy */ /* this request? */ /* -------------------------------------------------------------------- */ if( (nBufXSize < nXSize || nBufYSize < nYSize) && GetOverviewCount() > 0 ) { if( OverviewRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize, eBufType, nPixelSpace, nLineSpace ) == CE_None ) return CE_None; } /* ==================================================================== */ /* 1. Simplest case when we should get contiguous block */ /* of uninterleaved pixels. */ /* ==================================================================== */ if ( nXSize == GetXSize() && nXSize == nBufXSize && nYSize == nBufYSize && eBufType == eDataType && nPixelOffset == nBandDataSize && nPixelSpace == nBufDataSize && nLineSpace == nPixelSpace * nXSize ) { vsi_l_offset nOffset = nImgOffset + (vsi_l_offset)nYOff * nLineOffset + nXOff; if ( AccessBlock( nOffset, nXSize * nYSize * nBandDataSize, pData ) != CE_None ) { CPLError( CE_Failure, CPLE_FileIO, "Failed to read %d bytes at " CPL_FRMT_GUIB ".", nXSize * nYSize * nBandDataSize, nOffset); } } /* ==================================================================== */ /* 2. Case when we need deinterleave and/or subsample data. */ /* ==================================================================== */ else { GByte *pabyData; double dfSrcXInc, dfSrcYInc; int iLine; dfSrcXInc = (double)nXSize / nBufXSize; dfSrcYInc = (double)nYSize / nBufYSize; pabyData = (GByte *) CPLMalloc( nBytesToRW ); for ( iLine = 0; iLine < nBufYSize; iLine++ ) { vsi_l_offset nOffset = nImgOffset + ((vsi_l_offset)nYOff + (vsi_l_offset)(iLine * dfSrcYInc)) * nLineOffset + nXOff * nPixelOffset; if ( AccessBlock( nOffset, nBytesToRW, pabyData ) != CE_None ) { CPLError( CE_Failure, CPLE_FileIO, "Failed to read %d bytes at " CPL_FRMT_GUIB ".", nBytesToRW, nOffset ); } /* -------------------------------------------------------------------- */ /* Copy data from disk buffer to user block buffer and subsample, */ /* if needed. */ /* -------------------------------------------------------------------- */ if ( nXSize == nBufXSize && nYSize == nBufYSize ) { GDALCopyWords( pabyData, eDataType, nPixelOffset, (GByte *)pData + (vsi_l_offset)iLine * nLineSpace, eBufType, nPixelSpace, nXSize ); } else { int iPixel; for ( iPixel = 0; iPixel < nBufXSize; iPixel++ ) { GDALCopyWords( pabyData + (vsi_l_offset)(iPixel * dfSrcXInc) * nPixelOffset, eDataType, nPixelOffset, (GByte *)pData + (vsi_l_offset)iLine * nLineSpace + (vsi_l_offset)iPixel * nPixelSpace, eBufType, nPixelSpace, 1 ); } } } CPLFree( pabyData ); } } /* ==================================================================== */ /* Write data. */ /* ==================================================================== */ else { int nBytesActuallyWritten; /* ==================================================================== */ /* 1. Simplest case when we should write contiguous block */ /* of uninterleaved pixels. */ /* ==================================================================== */ if ( nXSize == GetXSize() && nXSize == nBufXSize && nYSize == nBufYSize && eBufType == eDataType && nPixelOffset == nBandDataSize && nPixelSpace == nBufDataSize && nLineSpace == nPixelSpace * nXSize ) { /* -------------------------------------------------------------------- */ /* Byte swap the data buffer, if required. */ /* -------------------------------------------------------------------- */ if( !bNativeOrder && eDataType != GDT_Byte ) { if( GDALDataTypeIsComplex( eDataType ) ) { int nWordSize; nWordSize = GDALGetDataTypeSize(eDataType)/16; GDALSwapWords( pData, nWordSize, nXSize, nPixelOffset ); GDALSwapWords( ((GByte *) pData) + nWordSize, nWordSize, nXSize, nPixelOffset ); } else GDALSwapWords( pData, nBandDataSize, nXSize, nPixelOffset ); } /* -------------------------------------------------------------------- */ /* Seek to the right block. */ /* -------------------------------------------------------------------- */ vsi_l_offset nOffset = nImgOffset + (vsi_l_offset)nYOff * nLineOffset + nXOff; if( Seek( nOffset, SEEK_SET) == -1 ) { CPLError( CE_Failure, CPLE_FileIO, "Failed to seek to " CPL_FRMT_GUIB " to write data.\n", nOffset); return CE_Failure; } /* -------------------------------------------------------------------- */ /* Write the block. */ /* -------------------------------------------------------------------- */ nBytesToRW = nXSize * nYSize * nBandDataSize; nBytesActuallyWritten = Write( pData, 1, nBytesToRW ); if( nBytesActuallyWritten < nBytesToRW ) { CPLError( CE_Failure, CPLE_FileIO, "Failed to write %d bytes to file. %d bytes written", nBytesToRW, nBytesActuallyWritten ); return CE_Failure; } /* -------------------------------------------------------------------- */ /* Byte swap (if necessary) back into machine order so the */ /* buffer is still usable for reading purposes. */ /* -------------------------------------------------------------------- */ if( !bNativeOrder && eDataType != GDT_Byte ) { if( GDALDataTypeIsComplex( eDataType ) ) { int nWordSize; nWordSize = GDALGetDataTypeSize(eDataType)/16; GDALSwapWords( pData, nWordSize, nXSize, nPixelOffset ); GDALSwapWords( ((GByte *) pData) + nWordSize, nWordSize, nXSize, nPixelOffset ); } else GDALSwapWords( pData, nBandDataSize, nXSize, nPixelOffset ); } } /* ==================================================================== */ /* 2. Case when we need deinterleave and/or subsample data. */ /* ==================================================================== */ else { GByte *pabyData; double dfSrcXInc, dfSrcYInc; vsi_l_offset nBlockOff; int iLine; dfSrcXInc = (double)nXSize / nBufXSize; dfSrcYInc = (double)nYSize / nBufYSize; pabyData = (GByte *) CPLMalloc( nBytesToRW ); for ( iLine = 0; iLine < nBufYSize; iLine++ ) { nBlockOff = nImgOffset + ((vsi_l_offset)nYOff + (vsi_l_offset)(iLine*dfSrcYInc))*nLineOffset + nXOff * nPixelOffset; /* -------------------------------------------------------------------- */ /* If the data for this band is completely contiguous we don't */ /* have to worry about pre-reading from disk. */ /* -------------------------------------------------------------------- */ if( nPixelOffset > nBandDataSize ) AccessBlock( nBlockOff, nBytesToRW, pabyData ); /* -------------------------------------------------------------------- */ /* Copy data from user block buffer to disk buffer and subsample, */ /* if needed. */ /* -------------------------------------------------------------------- */ if ( nXSize == nBufXSize && nYSize == nBufYSize ) { GDALCopyWords( (GByte *)pData + (vsi_l_offset)iLine * nLineSpace, eBufType, nPixelSpace, pabyData, eDataType, nPixelOffset, nXSize ); } else { int iPixel; for ( iPixel = 0; iPixel < nBufXSize; iPixel++ ) { GDALCopyWords( (GByte *)pData+(vsi_l_offset)iLine*nLineSpace + (vsi_l_offset)iPixel * nPixelSpace, eBufType, nPixelSpace, pabyData + (vsi_l_offset)(iPixel * dfSrcXInc) * nPixelOffset, eDataType, nPixelOffset, 1 ); } } /* -------------------------------------------------------------------- */ /* Byte swap the data buffer, if required. */ /* -------------------------------------------------------------------- */ if( !bNativeOrder && eDataType != GDT_Byte ) { if( GDALDataTypeIsComplex( eDataType ) ) { int nWordSize; nWordSize = GDALGetDataTypeSize(eDataType)/16; GDALSwapWords( pabyData, nWordSize, nXSize, nPixelOffset ); GDALSwapWords( ((GByte *) pabyData) + nWordSize, nWordSize, nXSize, nPixelOffset ); } else GDALSwapWords( pabyData, nBandDataSize, nXSize, nPixelOffset ); } /* -------------------------------------------------------------------- */ /* Seek to the right line in block. */ /* -------------------------------------------------------------------- */ if( Seek( nBlockOff, SEEK_SET) == -1 ) { CPLError( CE_Failure, CPLE_FileIO, "Failed to seek to " CPL_FRMT_GUIB " to read.\n", nBlockOff ); return CE_Failure; } /* -------------------------------------------------------------------- */ /* Write the line of block. */ /* -------------------------------------------------------------------- */ nBytesActuallyWritten = Write( pabyData, 1, nBytesToRW ); if( nBytesActuallyWritten < nBytesToRW ) { CPLError( CE_Failure, CPLE_FileIO, "Failed to write %d bytes to file. %d bytes written", nBytesToRW, nBytesActuallyWritten ); return CE_Failure; } /* -------------------------------------------------------------------- */ /* Byte swap (if necessary) back into machine order so the */ /* buffer is still usable for reading purposes. */ /* -------------------------------------------------------------------- */ if( !bNativeOrder && eDataType != GDT_Byte ) { if( GDALDataTypeIsComplex( eDataType ) ) { int nWordSize; nWordSize = GDALGetDataTypeSize(eDataType)/16; GDALSwapWords( pabyData, nWordSize, nXSize, nPixelOffset ); GDALSwapWords( ((GByte *) pabyData) + nWordSize, nWordSize, nXSize, nPixelOffset ); } else GDALSwapWords( pabyData, nBandDataSize, nXSize, nPixelOffset ); } } bDirty = TRUE; CPLFree( pabyData ); } } return CE_None; }
int CPL_STDCALL GDALChecksumImage( GDALRasterBandH hBand, int nXOff, int nYOff, int nXSize, int nYSize ) { VALIDATE_POINTER1( hBand, "GDALChecksumImage", 0 ); const static int anPrimes[11] = { 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43 }; int iLine, i, nChecksum = 0, iPrime = 0, nCount; GDALDataType eDataType = GDALGetRasterDataType( hBand ); int bComplex = GDALDataTypeIsComplex( eDataType ); if (eDataType == GDT_Float32 || eDataType == GDT_Float64 || eDataType == GDT_CFloat32 || eDataType == GDT_CFloat64) { double* padfLineData; GDALDataType eDstDataType = (bComplex) ? GDT_CFloat64 : GDT_Float64; padfLineData = (double *) VSIMalloc2(nXSize, sizeof(double) * 2); if (padfLineData == NULL) { CPLError( CE_Failure, CPLE_OutOfMemory, "VSIMalloc2(): Out of memory in GDALChecksumImage. " "Checksum value couldn't be computed\n"); return 0; } for( iLine = nYOff; iLine < nYOff + nYSize; iLine++ ) { if (GDALRasterIO( hBand, GF_Read, nXOff, iLine, nXSize, 1, padfLineData, nXSize, 1, eDstDataType, 0, 0 ) != CE_None) { CPLError( CE_Failure, CPLE_FileIO, "Checksum value couldn't be computed due to I/O read error.\n"); break; } nCount = (bComplex) ? nXSize * 2 : nXSize; for( i = 0; i < nCount; i++ ) { double dfVal = padfLineData[i]; int nVal; if (CPLIsNan(dfVal) || CPLIsInf(dfVal)) { /* Most compilers seem to cast NaN or Inf to 0x80000000. */ /* but VC7 is an exception. So we force the result */ /* of such a cast */ nVal = 0x80000000; } else { /* Standard behaviour of GDALCopyWords when converting */ /* from floating point to Int32 */ dfVal += 0.5; if( dfVal < -2147483647.0 ) nVal = -2147483647; else if( dfVal > 2147483647 ) nVal = 2147483647; else nVal = (GInt32) floor(dfVal); } nChecksum += (nVal % anPrimes[iPrime++]); if( iPrime > 10 ) iPrime = 0; nChecksum &= 0xffff; } } CPLFree(padfLineData); } else { int *panLineData; GDALDataType eDstDataType = (bComplex) ? GDT_CInt32 : GDT_Int32; panLineData = (GInt32 *) VSIMalloc2(nXSize, sizeof(GInt32) * 2); if (panLineData == NULL) { CPLError( CE_Failure, CPLE_OutOfMemory, "VSIMalloc2(): Out of memory in GDALChecksumImage. " "Checksum value couldn't be computed\n"); return 0; } for( iLine = nYOff; iLine < nYOff + nYSize; iLine++ ) { if (GDALRasterIO( hBand, GF_Read, nXOff, iLine, nXSize, 1, panLineData, nXSize, 1, eDstDataType, 0, 0 ) != CE_None) { CPLError( CE_Failure, CPLE_FileIO, "Checksum value couldn't be computed due to I/O read error.\n"); break; } nCount = (bComplex) ? nXSize * 2 : nXSize; for( i = 0; i < nCount; i++ ) { nChecksum += (panLineData[i] % anPrimes[iPrime++]); if( iPrime > 10 ) iPrime = 0; nChecksum &= 0xffff; } } CPLFree( panLineData ); } return nChecksum; }
CPLErr RawRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff, void * pImage ) { CPLErr eErr = CE_None; CPLAssert( nBlockXOff == 0 ); if (pLineBuffer == NULL) return CE_Failure; /* -------------------------------------------------------------------- */ /* If the data for this band is completely contiguous we don't */ /* have to worry about pre-reading from disk. */ /* -------------------------------------------------------------------- */ if( ABS(nPixelOffset) > GDALGetDataTypeSize(eDataType) / 8 ) eErr = AccessLine( nBlockYOff ); /* -------------------------------------------------------------------- */ /* Copy data from user buffer into disk buffer. */ /* -------------------------------------------------------------------- */ GDALCopyWords( pImage, eDataType, GDALGetDataTypeSize(eDataType)/8, pLineStart, eDataType, nPixelOffset, nBlockXSize ); /* -------------------------------------------------------------------- */ /* Byte swap (if necessary) back into disk order before writing. */ /* -------------------------------------------------------------------- */ if( !bNativeOrder && eDataType != GDT_Byte ) { if( GDALDataTypeIsComplex( eDataType ) ) { int nWordSize; nWordSize = GDALGetDataTypeSize(eDataType)/16; GDALSwapWords( pLineBuffer, nWordSize, nBlockXSize, ABS(nPixelOffset) ); GDALSwapWords( ((GByte *) pLineBuffer)+nWordSize, nWordSize, nBlockXSize, ABS(nPixelOffset) ); } else GDALSwapWords( pLineBuffer, GDALGetDataTypeSize(eDataType)/8, nBlockXSize, ABS(nPixelOffset) ); } /* -------------------------------------------------------------------- */ /* Figure out where to start reading. */ /* -------------------------------------------------------------------- */ vsi_l_offset nWriteStart; if( nPixelOffset >= 0 ) nWriteStart = nImgOffset + (vsi_l_offset)nBlockYOff * nLineOffset; else { nWriteStart = nImgOffset + (vsi_l_offset)nBlockYOff * nLineOffset - ABS(nPixelOffset) * (nBlockXSize-1); } /* -------------------------------------------------------------------- */ /* Seek to correct location. */ /* -------------------------------------------------------------------- */ if( Seek( nWriteStart, SEEK_SET ) == -1 ) { CPLError( CE_Failure, CPLE_FileIO, "Failed to seek to scanline %d @ %d to write to file.\n", nBlockYOff, (int) (nImgOffset + nBlockYOff * nLineOffset) ); eErr = CE_Failure; } /* -------------------------------------------------------------------- */ /* Write data buffer. */ /* -------------------------------------------------------------------- */ int nBytesToWrite; nBytesToWrite = ABS(nPixelOffset) * (nBlockXSize - 1) + GDALGetDataTypeSize(GetRasterDataType()) / 8; if( eErr == CE_None && Write( pLineBuffer, 1, nBytesToWrite ) < (size_t) nBytesToWrite ) { CPLError( CE_Failure, CPLE_FileIO, "Failed to write scanline %d to file.\n", nBlockYOff ); eErr = CE_Failure; } /* -------------------------------------------------------------------- */ /* Byte swap (if necessary) back into machine order so the */ /* buffer is still usable for reading purposes. */ /* -------------------------------------------------------------------- */ if( !bNativeOrder && eDataType != GDT_Byte ) { if( GDALDataTypeIsComplex( eDataType ) ) { int nWordSize; nWordSize = GDALGetDataTypeSize(eDataType)/16; GDALSwapWords( pLineBuffer, nWordSize, nBlockXSize, ABS(nPixelOffset) ); GDALSwapWords( ((GByte *) pLineBuffer)+nWordSize, nWordSize, nBlockXSize, ABS(nPixelOffset) ); } else GDALSwapWords( pLineBuffer, GDALGetDataTypeSize(eDataType)/8, nBlockXSize, ABS(nPixelOffset) ); } bDirty = TRUE; return eErr; }
CPLErr GTIFFBuildOverviews( const char * pszFilename, int nBands, GDALRasterBand **papoBandList, int nOverviews, int * panOverviewList, const char * pszResampling, GDALProgressFunc pfnProgress, void * pProgressData ) { TIFF *hOTIFF; int nBitsPerPixel=0, nCompression=COMPRESSION_NONE, nPhotometric=0; int nSampleFormat=0, nPlanarConfig, iOverview, iBand; int nXSize=0, nYSize=0; if( nBands == 0 || nOverviews == 0 ) return CE_None; GTiffOneTimeInit(); /* -------------------------------------------------------------------- */ /* Verify that the list of bands is suitable for emitting in */ /* TIFF file. */ /* -------------------------------------------------------------------- */ for( iBand = 0; iBand < nBands; iBand++ ) { int nBandBits, nBandFormat; GDALRasterBand *hBand = papoBandList[iBand]; switch( hBand->GetRasterDataType() ) { case GDT_Byte: nBandBits = 8; nBandFormat = SAMPLEFORMAT_UINT; break; case GDT_UInt16: nBandBits = 16; nBandFormat = SAMPLEFORMAT_UINT; break; case GDT_Int16: nBandBits = 16; nBandFormat = SAMPLEFORMAT_INT; break; case GDT_UInt32: nBandBits = 32; nBandFormat = SAMPLEFORMAT_UINT; break; case GDT_Int32: nBandBits = 32; nBandFormat = SAMPLEFORMAT_INT; break; case GDT_Float32: nBandBits = 32; nBandFormat = SAMPLEFORMAT_IEEEFP; break; case GDT_Float64: nBandBits = 64; nBandFormat = SAMPLEFORMAT_IEEEFP; break; case GDT_CInt16: nBandBits = 32; nBandFormat = SAMPLEFORMAT_COMPLEXINT; break; case GDT_CFloat32: nBandBits = 64; nBandFormat = SAMPLEFORMAT_COMPLEXIEEEFP; break; case GDT_CFloat64: nBandBits = 128; nBandFormat = SAMPLEFORMAT_COMPLEXIEEEFP; break; default: CPLAssert( FALSE ); return CE_Failure; } if( iBand == 0 ) { nBitsPerPixel = nBandBits; nSampleFormat = nBandFormat; nXSize = hBand->GetXSize(); nYSize = hBand->GetYSize(); } else if( nBitsPerPixel != nBandBits || nSampleFormat != nBandFormat ) { CPLError( CE_Failure, CPLE_NotSupported, "GTIFFBuildOverviews() doesn't support a mixture of band" " data types." ); return CE_Failure; } else if( hBand->GetColorTable() != NULL ) { CPLError( CE_Failure, CPLE_NotSupported, "GTIFFBuildOverviews() doesn't support building" " overviews of multiple colormapped bands." ); return CE_Failure; } else if( hBand->GetXSize() != nXSize || hBand->GetYSize() != nYSize ) { CPLError( CE_Failure, CPLE_NotSupported, "GTIFFBuildOverviews() doesn't support building" " overviews of different sized bands." ); return CE_Failure; } } /* -------------------------------------------------------------------- */ /* Use specified compression method. */ /* -------------------------------------------------------------------- */ const char *pszCompress = CPLGetConfigOption( "COMPRESS_OVERVIEW", NULL ); if( pszCompress != NULL && pszCompress[0] != '\0' ) { if( EQUAL( pszCompress, "JPEG" ) ) nCompression = COMPRESSION_JPEG; else if( EQUAL( pszCompress, "LZW" ) ) nCompression = COMPRESSION_LZW; else if( EQUAL( pszCompress, "PACKBITS" )) nCompression = COMPRESSION_PACKBITS; else if( EQUAL( pszCompress, "DEFLATE" ) || EQUAL( pszCompress, "ZIP" )) nCompression = COMPRESSION_ADOBE_DEFLATE; else CPLError( CE_Warning, CPLE_IllegalArg, "COMPRESS_OVERVIEW=%s value not recognised, ignoring.", pszCompress ); } /* -------------------------------------------------------------------- */ /* Figure out the planar configuration to use. */ /* -------------------------------------------------------------------- */ if( nBands == 1 ) nPlanarConfig = PLANARCONFIG_CONTIG; else nPlanarConfig = PLANARCONFIG_SEPARATE; const char* pszInterleave = CPLGetConfigOption( "INTERLEAVE_OVERVIEW", NULL ); if (pszInterleave != NULL && pszInterleave[0] != '\0') { if( EQUAL( pszInterleave, "PIXEL" ) ) nPlanarConfig = PLANARCONFIG_CONTIG; else if( EQUAL( pszInterleave, "BAND" ) ) nPlanarConfig = PLANARCONFIG_SEPARATE; else { CPLError( CE_Failure, CPLE_AppDefined, "INTERLEAVE_OVERVIEW=%s unsupported, value must be PIXEL or BAND. ignoring", pszInterleave ); } } /* -------------------------------------------------------------------- */ /* Figure out the photometric interpretation to use. */ /* -------------------------------------------------------------------- */ if( nBands == 3 ) nPhotometric = PHOTOMETRIC_RGB; else if( papoBandList[0]->GetColorTable() != NULL && !EQUALN(pszResampling,"AVERAGE_BIT2",12) ) { nPhotometric = PHOTOMETRIC_PALETTE; /* should set the colormap up at this point too! */ } else nPhotometric = PHOTOMETRIC_MINISBLACK; const char* pszPhotometric = CPLGetConfigOption( "PHOTOMETRIC_OVERVIEW", NULL ); if (pszPhotometric != NULL && pszPhotometric[0] != '\0') { if( EQUAL( pszPhotometric, "MINISBLACK" ) ) nPhotometric = PHOTOMETRIC_MINISBLACK; else if( EQUAL( pszPhotometric, "MINISWHITE" ) ) nPhotometric = PHOTOMETRIC_MINISWHITE; else if( EQUAL( pszPhotometric, "RGB" )) { nPhotometric = PHOTOMETRIC_RGB; } else if( EQUAL( pszPhotometric, "CMYK" )) { nPhotometric = PHOTOMETRIC_SEPARATED; } else if( EQUAL( pszPhotometric, "YCBCR" )) { nPhotometric = PHOTOMETRIC_YCBCR; } else if( EQUAL( pszPhotometric, "CIELAB" )) { nPhotometric = PHOTOMETRIC_CIELAB; } else if( EQUAL( pszPhotometric, "ICCLAB" )) { nPhotometric = PHOTOMETRIC_ICCLAB; } else if( EQUAL( pszPhotometric, "ITULAB" )) { nPhotometric = PHOTOMETRIC_ITULAB; } else { CPLError( CE_Warning, CPLE_IllegalArg, "PHOTOMETRIC_OVERVIEW=%s value not recognised, ignoring.\n", pszPhotometric ); } } /* -------------------------------------------------------------------- */ /* Create the file, if it does not already exist. */ /* -------------------------------------------------------------------- */ VSIStatBuf sStatBuf; if( VSIStat( pszFilename, &sStatBuf ) != 0 ) { hOTIFF = XTIFFOpen( pszFilename, "w+" ); if( hOTIFF == NULL ) { if( CPLGetLastErrorNo() == 0 ) CPLError( CE_Failure, CPLE_OpenFailed, "Attempt to create new tiff file `%s'\n" "failed in XTIFFOpen().\n", pszFilename ); return CE_Failure; } } /* -------------------------------------------------------------------- */ /* Otherwise just open it for update access. */ /* -------------------------------------------------------------------- */ else { hOTIFF = XTIFFOpen( pszFilename, "r+" ); if( hOTIFF == NULL ) { if( CPLGetLastErrorNo() == 0 ) CPLError( CE_Failure, CPLE_OpenFailed, "Attempt to create new tiff file `%s'\n" "failed in XTIFFOpen().\n", pszFilename ); return CE_Failure; } } /* -------------------------------------------------------------------- */ /* Do we have a palette? If so, create a TIFF compatible version. */ /* -------------------------------------------------------------------- */ unsigned short *panRed=NULL, *panGreen=NULL, *panBlue=NULL; if( nPhotometric == PHOTOMETRIC_PALETTE ) { GDALColorTable *poCT = papoBandList[0]->GetColorTable(); int nColorCount; if( nBitsPerPixel <= 8 ) nColorCount = 256; else nColorCount = 65536; panRed = (unsigned short *) CPLCalloc(nColorCount,sizeof(unsigned short)); panGreen = (unsigned short *) CPLCalloc(nColorCount,sizeof(unsigned short)); panBlue = (unsigned short *) CPLCalloc(nColorCount,sizeof(unsigned short)); for( int iColor = 0; iColor < nColorCount; iColor++ ) { GDALColorEntry sRGB; if( poCT->GetColorEntryAsRGB( iColor, &sRGB ) ) { panRed[iColor] = (unsigned short) (257 * sRGB.c1); panGreen[iColor] = (unsigned short) (257 * sRGB.c2); panBlue[iColor] = (unsigned short) (257 * sRGB.c3); } } } /* -------------------------------------------------------------------- */ /* Do we need some metadata for the overviews? */ /* -------------------------------------------------------------------- */ CPLString osMetadata; GDALDataset *poBaseDS = papoBandList[0]->GetDataset(); GTIFFBuildOverviewMetadata( pszResampling, poBaseDS, osMetadata ); /* -------------------------------------------------------------------- */ /* Loop, creating overviews. */ /* -------------------------------------------------------------------- */ for( iOverview = 0; iOverview < nOverviews; iOverview++ ) { int nOXSize, nOYSize; uint32 nDirOffset; nOXSize = (nXSize + panOverviewList[iOverview] - 1) / panOverviewList[iOverview]; nOYSize = (nYSize + panOverviewList[iOverview] - 1) / panOverviewList[iOverview]; nDirOffset = GTIFFWriteDirectory(hOTIFF, FILETYPE_REDUCEDIMAGE, nOXSize, nOYSize, nBitsPerPixel, nPlanarConfig, nBands, 128, 128, TRUE, nCompression, nPhotometric, nSampleFormat, panRed, panGreen, panBlue, 0, NULL, /* FIXME ? how can we fetch extrasamples from here */ osMetadata ); } if (panRed) { CPLFree(panRed); CPLFree(panGreen); CPLFree(panBlue); panRed = panGreen = panBlue = NULL; } XTIFFClose( hOTIFF ); /* -------------------------------------------------------------------- */ /* Open the overview dataset so that we can get at the overview */ /* bands. */ /* -------------------------------------------------------------------- */ GDALDataset *hODS; hODS = (GDALDataset *) GDALOpen( pszFilename, GA_Update ); if( hODS == NULL ) return CE_Failure; /* -------------------------------------------------------------------- */ /* Loop writing overview data. */ /* -------------------------------------------------------------------- */ if (nCompression != COMPRESSION_NONE && nPlanarConfig == PLANARCONFIG_CONTIG && GDALDataTypeIsComplex(papoBandList[0]->GetRasterDataType()) == FALSE && papoBandList[0]->GetColorTable() == NULL && (EQUALN(pszResampling, "NEAR", 4) || EQUAL(pszResampling, "AVERAGE") || EQUAL(pszResampling, "GAUSS"))) { /* In the case of pixel interleaved compressed overviews, we want to generate */ /* the overviews for all the bands block by block, and not band after band, */ /* in order to write the block once and not loose space in the TIFF file */ GDALRasterBand ***papapoOverviewBands; papapoOverviewBands = (GDALRasterBand ***) CPLCalloc(sizeof(void*),nBands); for( iBand = 0; iBand < nBands; iBand++ ) { GDALRasterBand *hDstBand = hODS->GetRasterBand( iBand+1 ); papapoOverviewBands[iBand] = (GDALRasterBand **) CPLCalloc(sizeof(void*),nOverviews); papapoOverviewBands[iBand][0] = hDstBand; for( int i = 0; i < nOverviews-1; i++ ) { papapoOverviewBands[iBand][i+1] = hDstBand->GetOverview(i); } } GDALRegenerateOverviewsMultiBand(nBands, papoBandList, nOverviews, papapoOverviewBands, pszResampling, pfnProgress, pProgressData ); for( iBand = 0; iBand < nBands; iBand++ ) { CPLFree(papapoOverviewBands[iBand]); } CPLFree(papapoOverviewBands); } else { GDALRasterBand **papoOverviews; papoOverviews = (GDALRasterBand **) CPLCalloc(sizeof(void*),128); for( iBand = 0; iBand < nBands; iBand++ ) { GDALRasterBand *hSrcBand = papoBandList[iBand]; GDALRasterBand *hDstBand; int nDstOverviews; CPLErr eErr; hDstBand = hODS->GetRasterBand( iBand+1 ); papoOverviews[0] = hDstBand; nDstOverviews = hDstBand->GetOverviewCount() + 1; CPLAssert( nDstOverviews < 128 ); nDstOverviews = MIN(128,nDstOverviews); for( int i = 0; i < nDstOverviews-1; i++ ) { papoOverviews[i+1] = hDstBand->GetOverview(i); } void *pScaledProgressData; pScaledProgressData = GDALCreateScaledProgress( iBand / (double) nBands, (iBand+1) / (double) nBands, pfnProgress, pProgressData ); eErr = GDALRegenerateOverviews( (GDALRasterBandH) hSrcBand, nDstOverviews, (GDALRasterBandH *) papoOverviews, pszResampling, GDALScaledProgress, pScaledProgressData); GDALDestroyScaledProgress( pScaledProgressData ); if( eErr != CE_None ) { delete hODS; return eErr; } } CPLFree( papoOverviews ); } /* -------------------------------------------------------------------- */ /* Cleanup */ /* -------------------------------------------------------------------- */ hODS->FlushCache(); delete hODS; pfnProgress( 1.0, NULL, pProgressData ); return CE_None; }
CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize, void * pData, int nBufXSize, int nBufYSize, GDALDataType eBufType, int nPixelSpace, int nLineSpace ) { int nBandDataSize = GDALGetDataTypeSize(eDataType) / 8; int nBufDataSize = GDALGetDataTypeSize( eBufType ) / 8; int nBytesToRW = nPixelOffset * nXSize; /* -------------------------------------------------------------------- */ /* Use direct IO without caching if: */ /* */ /* GDAL_ONE_BIG_READ is enabled */ /* */ /* or */ /* */ /* the length of a scanline on disk is more than 50000 bytes, and the */ /* width of the requested chunk is less than 40% of the whole scanline */ /* and none of the requested scanlines are already in the cache. */ /* -------------------------------------------------------------------- */ if( nPixelOffset < 0 ) { return GDALRasterBand::IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize, eBufType, nPixelSpace, nLineSpace ); } if ( !CSLTestBoolean( CPLGetConfigOption( "GDAL_ONE_BIG_READ", "NO") ) ) { if ( nLineSize < 50000 || nBytesToRW > nLineSize / 5 * 2 || IsLineLoaded( nYOff, nYSize ) ) { return GDALRasterBand::IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize, eBufType, nPixelSpace, nLineSpace ); } } /* ==================================================================== */ /* Read data. */ /* ==================================================================== */ if ( eRWFlag == GF_Read ) { /* -------------------------------------------------------------------- */ /* Do we have overviews that would be appropriate to satisfy */ /* this request? */ /* -------------------------------------------------------------------- */ if( (nBufXSize < nXSize || nBufYSize < nYSize) && GetOverviewCount() > 0 ) { if( OverviewRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize, eBufType, nPixelSpace, nLineSpace ) == CE_None ) return CE_None; } /* ==================================================================== */ /* 1. Simplest case when we should get contiguous block */ /* of uninterleaved pixels. */ /* ==================================================================== */ if ( nXSize == GetXSize() && nXSize == nBufXSize && nYSize == nBufYSize && eBufType == eDataType && nPixelOffset == nBandDataSize && nPixelSpace == nBufDataSize && nLineSpace == nPixelSpace * nXSize ) { if ( AccessBlock( nImgOffset + (vsi_l_offset)nYOff * nLineOffset + nXOff, nXSize * nYSize * nBandDataSize, pData ) != CE_None ) { CPLError( CE_Failure, CPLE_FileIO, "Failed to read %d bytes at %lu.", nXSize * nYSize * nBandDataSize, (unsigned long) (nImgOffset + (vsi_l_offset)nYOff * nLineOffset + nXOff) ); } } /* ==================================================================== */ /* 2. Case when we need deinterleave and/or subsample data. */ /* ==================================================================== */ else { GByte *pabyData; double dfSrcXInc, dfSrcYInc; int iLine; dfSrcXInc = (double)nXSize / nBufXSize; dfSrcYInc = (double)nYSize / nBufYSize; pabyData = (GByte *) CPLMalloc( nBytesToRW ); for ( iLine = 0; iLine < nBufYSize; iLine++ ) { if ( AccessBlock( nImgOffset + ((vsi_l_offset)nYOff + (int)(iLine * dfSrcYInc)) * nLineOffset + nXOff * nPixelOffset, nBytesToRW, pabyData ) != CE_None ) { CPLError( CE_Failure, CPLE_FileIO, "Failed to read %d bytes at %lu.", nBytesToRW, (unsigned long)(nImgOffset + ((vsi_l_offset)nYOff + (int)(iLine * dfSrcYInc)) * nLineOffset + nXOff * nPixelOffset) ); } /* -------------------------------------------------------------------- */ /* Copy data from disk buffer to user block buffer and subsample, */ /* if needed. */ /* -------------------------------------------------------------------- */ if ( nXSize == nBufXSize && nYSize == nBufYSize ) { GDALCopyWords( pabyData, eDataType, nPixelOffset, (GByte *)pData + iLine * nLineSpace, eBufType, nPixelSpace, nXSize ); } else { int iPixel; for ( iPixel = 0; iPixel < nBufXSize; iPixel++ ) { GDALCopyWords( pabyData + (int)(iPixel * dfSrcXInc) * nPixelOffset, eDataType, 0, (GByte *)pData + iLine * nLineSpace + iPixel * nBufDataSize, eBufType, nPixelSpace, 1 ); } } } CPLFree( pabyData ); } } /* ==================================================================== */ /* Write data. */ /* ==================================================================== */ else { int nBytesActuallyWritten; /* ==================================================================== */ /* 1. Simplest case when we should write contiguous block */ /* of uninterleaved pixels. */ /* ==================================================================== */ if ( nXSize == GetXSize() && nXSize == nBufXSize && nYSize == nBufYSize && eBufType == eDataType && nPixelOffset == nBandDataSize && nPixelSpace == nBufDataSize && nLineSpace == nPixelSpace * nXSize ) { /* -------------------------------------------------------------------- */ /* Byte swap the data buffer, if required. */ /* -------------------------------------------------------------------- */ if( !bNativeOrder && eDataType != GDT_Byte ) { if( GDALDataTypeIsComplex( eDataType ) ) { int nWordSize; nWordSize = GDALGetDataTypeSize(eDataType)/16; GDALSwapWords( pData, nWordSize, nXSize, nPixelOffset ); GDALSwapWords( ((GByte *) pData) + nWordSize, nWordSize, nXSize, nPixelOffset ); } else GDALSwapWords( pData, nBandDataSize, nXSize, nPixelOffset ); } /* -------------------------------------------------------------------- */ /* Seek to the right block. */ /* -------------------------------------------------------------------- */ if( Seek( nImgOffset + (vsi_l_offset)nYOff * nLineOffset + nXOff, SEEK_SET) == -1 ) { CPLError( CE_Failure, CPLE_FileIO, "Failed to seek to %lu to write data.\n", (unsigned long)(nImgOffset + (vsi_l_offset)nYOff * nLineOffset + nXOff) ); return CE_Failure; } /* -------------------------------------------------------------------- */ /* Write the block. */ /* -------------------------------------------------------------------- */ nBytesToRW = nXSize * nYSize * nBandDataSize; nBytesActuallyWritten = Write( pData, 1, nBytesToRW ); if( nBytesActuallyWritten < nBytesToRW ) { CPLError( CE_Failure, CPLE_FileIO, "Failed to write %d bytes to file. %d bytes written", nBytesToRW, nBytesActuallyWritten ); return CE_Failure; } /* -------------------------------------------------------------------- */ /* Byte swap (if necessary) back into machine order so the */ /* buffer is still usable for reading purposes. */ /* -------------------------------------------------------------------- */ if( !bNativeOrder && eDataType != GDT_Byte ) { if( GDALDataTypeIsComplex( eDataType ) ) { int nWordSize; nWordSize = GDALGetDataTypeSize(eDataType)/16; GDALSwapWords( pData, nWordSize, nXSize, nPixelOffset ); GDALSwapWords( ((GByte *) pData) + nWordSize, nWordSize, nXSize, nPixelOffset ); } else GDALSwapWords( pData, nBandDataSize, nXSize, nPixelOffset ); } } /* ==================================================================== */ /* 2. Case when we need deinterleave and/or subsample data. */ /* ==================================================================== */ else { GByte *pabyData; double dfSrcXInc, dfSrcYInc; vsi_l_offset nBlockOff; int iLine; dfSrcXInc = (double)nXSize / nBufXSize; dfSrcYInc = (double)nYSize / nBufYSize; pabyData = (GByte *) CPLMalloc( nBytesToRW ); for ( iLine = 0; iLine < nBufYSize; iLine++ ) { nBlockOff = nImgOffset + ((vsi_l_offset)nYOff + (int)(iLine*dfSrcYInc))*nLineOffset + nXOff * nPixelOffset; /* -------------------------------------------------------------------- */ /* If the data for this band is completely contiguous we don't */ /* have to worry about pre-reading from disk. */ /* -------------------------------------------------------------------- */ if( nPixelOffset > nBandDataSize ) AccessBlock( nBlockOff, nBytesToRW, pabyData ); /* -------------------------------------------------------------------- */ /* Copy data from user block buffer to disk buffer and subsample, */ /* if needed. */ /* -------------------------------------------------------------------- */ if ( nXSize == nBufXSize && nYSize == nBufYSize ) { GDALCopyWords( (GByte *)pData + iLine * nLineSpace, eBufType, nPixelSpace, pabyData, eDataType, nPixelOffset, nXSize ); } else { int iPixel; for ( iPixel = 0; iPixel < nBufXSize; iPixel++ ) { GDALCopyWords( (GByte *)pData+iLine*nLineSpace + iPixel * nBufDataSize, eBufType, nPixelSpace, pabyData + (int)(iPixel * dfSrcXInc) * nPixelOffset, eDataType, 0, 1 ); } } /* -------------------------------------------------------------------- */ /* Byte swap the data buffer, if required. */ /* -------------------------------------------------------------------- */ if( !bNativeOrder && eDataType != GDT_Byte ) { if( GDALDataTypeIsComplex( eDataType ) ) { int nWordSize; nWordSize = GDALGetDataTypeSize(eDataType)/16; GDALSwapWords( pabyData, nWordSize, nXSize, nPixelOffset ); GDALSwapWords( ((GByte *) pabyData) + nWordSize, nWordSize, nXSize, nPixelOffset ); } else GDALSwapWords( pabyData, nBandDataSize, nXSize, nPixelOffset ); } /* -------------------------------------------------------------------- */ /* Seek to the right line in block. */ /* -------------------------------------------------------------------- */ if( Seek( nBlockOff, SEEK_SET) == -1 ) { CPLError( CE_Failure, CPLE_FileIO, "Failed to seek to %ld to read.\n", (long)nBlockOff ); return CE_Failure; } /* -------------------------------------------------------------------- */ /* Write the line of block. */ /* -------------------------------------------------------------------- */ nBytesActuallyWritten = Write( pabyData, 1, nBytesToRW ); if( nBytesActuallyWritten < nBytesToRW ) { CPLError( CE_Failure, CPLE_FileIO, "Failed to write %d bytes to file. %d bytes written", nBytesToRW, nBytesActuallyWritten ); return CE_Failure; } /* -------------------------------------------------------------------- */ /* Byte swap (if necessary) back into machine order so the */ /* buffer is still usable for reading purposes. */ /* -------------------------------------------------------------------- */ if( !bNativeOrder && eDataType != GDT_Byte ) { if( GDALDataTypeIsComplex( eDataType ) ) { int nWordSize; nWordSize = GDALGetDataTypeSize(eDataType)/16; GDALSwapWords( pabyData, nWordSize, nXSize, nPixelOffset ); GDALSwapWords( ((GByte *) pabyData) + nWordSize, nWordSize, nXSize, nPixelOffset ); } else GDALSwapWords( pabyData, nBandDataSize, nXSize, nPixelOffset ); } } bDirty = TRUE; CPLFree( pabyData ); } } return CE_None; }
CPLErr PhasePixelFunc(void **papoSources, int nSources, void *pData, int nXSize, int nYSize, GDALDataType eSrcType, GDALDataType eBufType, int nPixelSpace, int nLineSpace) { int ii, iLine, iCol; double dfPixVal, dfReal; /* ---- Init ---- */ if (nSources != 1) return CE_Failure; if (GDALDataTypeIsComplex( eSrcType )) { double dfImag; void *pReal = papoSources[0]; void *pImag = ((GByte *)papoSources[0]) + GDALGetDataTypeSize( eSrcType ) / 8 / 2; /* ---- Set pixels ---- */ for( iLine = 0, ii= 0; iLine < nYSize; ++iLine ) { for( iCol = 0; iCol < nXSize; ++iCol, ++ii ) { /* Source raster pixels may be obtained with SRCVAL macro */ dfReal = SRCVAL(pReal, eSrcType, ii); dfImag = SRCVAL(pImag, eSrcType, ii); dfPixVal = atan2(dfImag, dfReal); GDALCopyWords(&dfPixVal, GDT_Float64, 0, ((GByte *)pData) + nLineSpace * iLine + iCol * nPixelSpace, eBufType, nPixelSpace, 1); } } } else { /* ---- Set pixels ---- */ /* for( iLine = 0; iLine < nYSize; ++iLine ) { / * always copy from the same location * / GDALCopyWords(&dfImag, eSrcType, 0, ((GByte *)pData) + nLineSpace * iLine, eBufType, nPixelSpace, nXSize); } */ /* ---- Set pixels ---- */ double pi = atan2(0, -1); for( iLine = 0, ii= 0; iLine < nYSize; ++iLine ) { for( iCol = 0; iCol < nXSize; ++iCol, ++ii ) { void *pReal = papoSources[0]; /* Source raster pixels may be obtained with SRCVAL macro */ dfReal = SRCVAL(pReal, eSrcType, ii); dfPixVal = (dfReal < 0) ? pi : 0; GDALCopyWords(&dfPixVal, GDT_Float64, dfPixVal, ((GByte *)pData) + nLineSpace * iLine + iCol * nPixelSpace, eBufType, nPixelSpace, 1); } } } /* ---- Return success ---- */ return CE_None; } /* PhasePixelFunc */