ACE2RasterBand::ACE2RasterBand( VSILFILE* fpRawIn, GDALDataType eDataTypeIn, int nXSize, int nYSize) : RawRasterBand( fpRawIn, 0, GDALGetDataTypeSizeBytes(eDataTypeIn), nXSize * GDALGetDataTypeSizeBytes(eDataTypeIn), eDataTypeIn, CPL_IS_LSB, nXSize, nYSize, TRUE, TRUE ) {}
CPLErr SRTMHGTRasterBand::IWriteBlock(int /*nBlockXOff*/, int nBlockYOff, void* pImage) { SRTMHGTDataset* poGDS = reinterpret_cast<SRTMHGTDataset *>( poDS ); if( poGDS->eAccess != GA_Update ) return CE_Failure; const int nDTSize = GDALGetDataTypeSizeBytes(eDataType); VSIFSeekL(poGDS->fpImage, nBlockYOff*nBlockXSize*nDTSize, SEEK_SET); #ifdef CPL_LSB if( nDTSize > 1 ) { memcpy(poGDS->panBuffer, pImage, nBlockXSize*nDTSize); GDALSwapWords(poGDS->panBuffer, nDTSize, nBlockXSize, nDTSize); VSIFWriteL( reinterpret_cast<unsigned char *>( poGDS->panBuffer ), nBlockXSize, nDTSize, poGDS->fpImage ); } else #endif { VSIFWriteL( reinterpret_cast<unsigned char *>( pImage ), nBlockXSize, nDTSize, poGDS->fpImage ); } return CE_None; }
CPLErr BTRasterBand::IReadBlock( int nBlockXOff, CPL_UNUSED int nBlockYOff, void * pImage ) { CPLAssert( nBlockYOff == 0 ); const int nDataSize = GDALGetDataTypeSizeBytes( eDataType ); /* -------------------------------------------------------------------- */ /* Seek to profile. */ /* -------------------------------------------------------------------- */ if( VSIFSeekL( fpImage, 256 + nBlockXOff * nDataSize * static_cast<vsi_l_offset>( nRasterYSize ), SEEK_SET ) != 0 ) { CPLError( CE_Failure, CPLE_FileIO, ".bt Seek failed:%s", VSIStrerror( errno ) ); return CE_Failure; } /* -------------------------------------------------------------------- */ /* Read the profile. */ /* -------------------------------------------------------------------- */ if( VSIFReadL( pImage, nDataSize, nRasterYSize, fpImage ) != static_cast<size_t>( nRasterYSize ) ) { CPLError( CE_Failure, CPLE_FileIO, ".bt Read failed:%s", VSIStrerror( errno ) ); return CE_Failure; } /* -------------------------------------------------------------------- */ /* Swap on MSB platforms. */ /* -------------------------------------------------------------------- */ #ifdef CPL_MSB GDALSwapWords( pImage, nDataSize, nRasterYSize, nDataSize ); #endif /* -------------------------------------------------------------------- */ /* Vertical flip, since GDAL expects values from top to bottom, */ /* but in .bt they are bottom to top. */ /* -------------------------------------------------------------------- */ for( int i = 0; i < nRasterYSize / 2; i++ ) { GByte abyWrk[8] = { 0 }; memcpy( abyWrk, reinterpret_cast<GByte *>(pImage) + i * nDataSize, nDataSize ); memcpy( reinterpret_cast<GByte *>(pImage) + i * nDataSize, reinterpret_cast<GByte *>(pImage) + (nRasterYSize - i - 1) * nDataSize, nDataSize ); memcpy( reinterpret_cast<GByte *>(pImage) + (nRasterYSize - i - 1) * nDataSize, abyWrk, nDataSize ); } return CE_None; }
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 */
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
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
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 SRTMHGTRasterBand::IReadBlock(int /*nBlockXOff*/, int nBlockYOff, void* pImage) { SRTMHGTDataset* poGDS = reinterpret_cast<SRTMHGTDataset *>( poDS ); /* -------------------------------------------------------------------- */ /* Load the desired data into the working buffer. */ /* -------------------------------------------------------------------- */ const int nDTSize = GDALGetDataTypeSizeBytes(eDataType); VSIFSeekL(poGDS->fpImage, nBlockYOff*nBlockXSize*nDTSize, SEEK_SET); VSIFReadL((unsigned char*)pImage, nBlockXSize, nDTSize, poGDS->fpImage); #ifdef CPL_LSB GDALSwapWords(pImage, nDTSize, nBlockXSize, nDTSize); #endif return CE_None; }
MEMRasterBand::MEMRasterBand( GDALDataset *poDSIn, int nBandIn, GByte *pabyDataIn, GDALDataType eTypeIn, GSpacing nPixelOffsetIn, GSpacing nLineOffsetIn, int bAssumeOwnership, const char * pszPixelType) : GDALPamRasterBand(FALSE), pabyData(pabyDataIn), // Skip nPixelOffset and nLineOffset. bOwnData(bAssumeOwnership), bNoDataSet(FALSE), dfNoData(0.0), poColorTable(NULL), eColorInterp(GCI_Undefined), pszUnitType(NULL), papszCategoryNames(NULL), dfOffset(0.0), dfScale(1.0), psSavedHistograms(NULL) { poDS = poDSIn; nBand = nBandIn; eAccess = poDS->GetAccess(); eDataType = eTypeIn; nBlockXSize = poDS->GetRasterXSize(); nBlockYSize = 1; if( nPixelOffsetIn == 0 ) nPixelOffsetIn = GDALGetDataTypeSizeBytes(eTypeIn); if( nLineOffsetIn == 0 ) nLineOffsetIn = nPixelOffsetIn * static_cast<size_t>(nBlockXSize); nPixelOffset = nPixelOffsetIn; nLineOffset = nLineOffsetIn; bOwnData = bAssumeOwnership; if( pszPixelType && EQUAL(pszPixelType,"SIGNEDBYTE") ) SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE", "IMAGE_STRUCTURE" ); }
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 RealPixelFunc( 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; const int nPixelSpaceSrc = GDALGetDataTypeSizeBytes( eSrcType ); const int nLineSpaceSrc = nPixelSpaceSrc * nXSize; /* ---- Set pixels ---- */ for( int iLine = 0; iLine < nYSize; ++iLine ) { GDALCopyWords( static_cast<GByte *>(papoSources[0]) + nLineSpaceSrc * iLine, eSrcType, nPixelSpaceSrc, static_cast<GByte *>(pData) + nLineSpace * iLine, eBufType, nPixelSpace, nXSize ); } /* ---- Return success ---- */ return CE_None; } // RealPixelFunc
/* * IRasterIO() */ CPLErr OGRNGWDataset::IRasterIO( GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize, void *pData, int nBufXSize, int nBufYSize, GDALDataType eBufType, int nBandCount, int *panBandMap, GSpacing nPixelSpace, GSpacing nLineSpace, GSpacing nBandSpace, GDALRasterIOExtraArg* psExtraArg ) { if( poRasterDS != nullptr ) { if( stPixelExtent.IsInit() ) { OGREnvelope stTestExtent; stTestExtent.MinX = static_cast<double>(nXOff); stTestExtent.MinY = static_cast<double>(nYOff); stTestExtent.MaxX = static_cast<double>(nXOff + nXSize); stTestExtent.MaxY = static_cast<double>(nYOff + nYSize); if( !stPixelExtent.Intersects(stTestExtent) ) { CPLDebug("NGW", "Raster extent in px is: %f, %f, %f, %f", stPixelExtent.MinX, stPixelExtent.MinY, stPixelExtent.MaxX, stPixelExtent.MaxY); CPLDebug("NGW", "RasterIO extent is: %f, %f, %f, %f", stTestExtent.MinX, stTestExtent.MinY, stTestExtent.MaxX, stTestExtent.MaxY); // Fill buffer transparent color. memset( pData, 0, nBufXSize * nBufYSize * nBandCount * GDALGetDataTypeSizeBytes(eBufType) ); return CE_None; } } } return GDALDataset::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize, eBufType, nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace, psExtraArg); }
CPLErr GDALNoDataValuesMaskBand::IReadBlock( int nXBlockOff, int nYBlockOff, void * pImage ) { int iBand; GDALDataType eWrkDT; /* -------------------------------------------------------------------- */ /* Decide on a working type. */ /* -------------------------------------------------------------------- */ switch( poDS->GetRasterBand(1)->GetRasterDataType() ) { case GDT_Byte: eWrkDT = GDT_Byte; break; case GDT_UInt16: case GDT_UInt32: eWrkDT = GDT_UInt32; break; case GDT_Int16: case GDT_Int32: case GDT_CInt16: case GDT_CInt32: eWrkDT = GDT_Int32; break; case GDT_Float32: case GDT_CFloat32: eWrkDT = GDT_Float32; break; case GDT_Float64: case GDT_CFloat64: eWrkDT = GDT_Float64; break; default: CPLAssert( FALSE ); eWrkDT = GDT_Float64; break; } /* -------------------------------------------------------------------- */ /* Read the image data. */ /* -------------------------------------------------------------------- */ CPLErr eErr; int nBands = poDS->GetRasterCount(); GByte *pabySrc = static_cast<GByte *>( VSI_MALLOC3_VERBOSE( nBands * GDALGetDataTypeSizeBytes(eWrkDT), nBlockXSize, nBlockYSize ) ); if (pabySrc == NULL) { return CE_Failure; } int nXSizeRequest = nBlockXSize; if (nXBlockOff * nBlockXSize + nBlockXSize > nRasterXSize) nXSizeRequest = nRasterXSize - nXBlockOff * nBlockXSize; int nYSizeRequest = nBlockYSize; if (nYBlockOff * nBlockYSize + nBlockYSize > nRasterYSize) nYSizeRequest = nRasterYSize - nYBlockOff * nBlockYSize; if (nXSizeRequest != nBlockXSize || nYSizeRequest != nBlockYSize) { /* memset the whole buffer to avoid Valgrind warnings in case we can't */ /* fetch a full block */ memset( pabySrc, 0, nBands * GDALGetDataTypeSizeBytes(eWrkDT) * nBlockXSize * nBlockYSize ); } int nBlockOffsetPixels = nBlockXSize * nBlockYSize; const int nBandOffsetByte = GDALGetDataTypeSizeBytes(eWrkDT) * nBlockXSize * nBlockYSize; for(iBand=0;iBand<nBands;iBand++) { eErr = poDS->GetRasterBand(iBand + 1)->RasterIO( GF_Read, nXBlockOff * nBlockXSize, nYBlockOff * nBlockYSize, nXSizeRequest, nYSizeRequest, pabySrc + iBand * nBandOffsetByte, nXSizeRequest, nYSizeRequest, eWrkDT, 0, nBlockXSize * GDALGetDataTypeSizeBytes(eWrkDT), NULL ); if( eErr != CE_None ) return eErr; } /* -------------------------------------------------------------------- */ /* Process different cases. */ /* -------------------------------------------------------------------- */ int i; switch( eWrkDT ) { case GDT_Byte: { GByte* pabyNoData = (GByte*) CPLMalloc(nBands * sizeof(GByte)); for(iBand=0;iBand<nBands;iBand++) { pabyNoData[iBand] = (GByte)padfNodataValues[iBand]; } for( i = nBlockXSize * nBlockYSize - 1; i >= 0; i-- ) { int nCountNoData = 0; for(iBand=0;iBand<nBands;iBand++) { if( pabySrc[i + iBand * nBlockOffsetPixels] == pabyNoData[iBand] ) nCountNoData ++; } if (nCountNoData == nBands) ((GByte *) pImage)[i] = 0; else ((GByte *) pImage)[i] = 255; } CPLFree(pabyNoData); } break; case GDT_UInt32: { GUInt32* panNoData = (GUInt32*) CPLMalloc(nBands * sizeof(GUInt32)); for(iBand=0;iBand<nBands;iBand++) { panNoData[iBand] = (GUInt32)padfNodataValues[iBand]; } for( i = nBlockXSize * nBlockYSize - 1; i >= 0; i-- ) { int nCountNoData = 0; for(iBand=0;iBand<nBands;iBand++) { if( ((GUInt32 *)pabySrc)[i + iBand * nBlockOffsetPixels] == panNoData[iBand] ) nCountNoData ++; } if (nCountNoData == nBands) ((GByte *) pImage)[i] = 0; else ((GByte *) pImage)[i] = 255; } CPLFree(panNoData); } break; case GDT_Int32: { GInt32* panNoData = (GInt32*) CPLMalloc(nBands * sizeof(GInt32)); for(iBand=0;iBand<nBands;iBand++) { panNoData[iBand] = (GInt32)padfNodataValues[iBand]; } for( i = nBlockXSize * nBlockYSize - 1; i >= 0; i-- ) { int nCountNoData = 0; for(iBand=0;iBand<nBands;iBand++) { if( ((GInt32 *)pabySrc)[i + iBand * nBlockOffsetPixels] == panNoData[iBand] ) nCountNoData ++; } if (nCountNoData == nBands) ((GByte *) pImage)[i] = 0; else ((GByte *) pImage)[i] = 255; } CPLFree(panNoData); } break; case GDT_Float32: { float* pafNoData = (float*) CPLMalloc(nBands * sizeof(float)); for(iBand=0;iBand<nBands;iBand++) { pafNoData[iBand] = (float)padfNodataValues[iBand]; } for( i = nBlockXSize * nBlockYSize - 1; i >= 0; i-- ) { int nCountNoData = 0; for(iBand=0;iBand<nBands;iBand++) { if( ((float *)pabySrc)[i + iBand * nBlockOffsetPixels] == pafNoData[iBand] ) nCountNoData ++; } if (nCountNoData == nBands) ((GByte *) pImage)[i] = 0; else ((GByte *) pImage)[i] = 255; } CPLFree(pafNoData); } break; case GDT_Float64: { double* padfNoData = (double*) CPLMalloc(nBands * sizeof(double)); for(iBand=0;iBand<nBands;iBand++) { padfNoData[iBand] = (double)padfNodataValues[iBand]; } for( i = nBlockXSize * nBlockYSize - 1; i >= 0; i-- ) { int nCountNoData = 0; for(iBand=0;iBand<nBands;iBand++) { if( ((double *)pabySrc)[i + iBand * nBlockOffsetPixels] == padfNoData[iBand] ) nCountNoData ++; } if (nCountNoData == nBands) ((GByte *) pImage)[i] = 0; else ((GByte *) pImage)[i] = 255; } CPLFree(padfNoData); } break; default: CPLAssert( FALSE ); break; } CPLFree( pabySrc ); return CE_None; }
CPLErr MEMDataset::AddBand( GDALDataType eType, char **papszOptions ) { const int nBandId = GetRasterCount() + 1; const GSpacing nPixelSize = GDALGetDataTypeSizeBytes(eType); /* -------------------------------------------------------------------- */ /* Do we need to allocate the memory ourselves? This is the */ /* simple case. */ /* -------------------------------------------------------------------- */ if( CSLFetchNameValue( papszOptions, "DATAPOINTER" ) == NULL ) { const GSpacing nTmp = nPixelSize * GetRasterXSize(); GByte *pData = NULL; #if SIZEOF_VOIDP == 4 if( nTmp > INT_MAX ) pData = NULL; else #endif pData = reinterpret_cast<GByte *>( VSI_CALLOC_VERBOSE((size_t)nTmp, GetRasterYSize() ) ); if( pData == NULL ) { return CE_Failure; } SetBand( nBandId, new MEMRasterBand( this, nBandId, pData, eType, nPixelSize, nPixelSize * GetRasterXSize(), TRUE ) ); return CE_None; } /* -------------------------------------------------------------------- */ /* Get layout of memory and other flags. */ /* -------------------------------------------------------------------- */ const char *pszDataPointer = CSLFetchNameValue(papszOptions, "DATAPOINTER"); GByte *pData = reinterpret_cast<GByte *>( CPLScanPointer( pszDataPointer, static_cast<int>(strlen(pszDataPointer)) ) ); const char *pszOption = CSLFetchNameValue(papszOptions, "PIXELOFFSET"); GSpacing nPixelOffset; if( pszOption == NULL ) nPixelOffset = nPixelSize; else nPixelOffset = CPLAtoGIntBig(pszOption); pszOption = CSLFetchNameValue(papszOptions, "LINEOFFSET"); GSpacing nLineOffset; if( pszOption == NULL ) nLineOffset = GetRasterXSize() * static_cast<size_t>( nPixelOffset ); else nLineOffset = CPLAtoGIntBig(pszOption); SetBand( nBandId, new MEMRasterBand( this, nBandId, pData, eType, nPixelOffset, nLineOffset, FALSE ) ); return CE_None; }
GDALDataset *MEMDataset::Open( GDALOpenInfo * poOpenInfo ) { /* -------------------------------------------------------------------- */ /* Do we have the special filename signature for MEM format */ /* description strings? */ /* -------------------------------------------------------------------- */ if( !STARTS_WITH_CI(poOpenInfo->pszFilename, "MEM:::") || poOpenInfo->fpL != NULL ) return NULL; char **papszOptions = CSLTokenizeStringComplex(poOpenInfo->pszFilename+6, ",", TRUE, FALSE ); /* -------------------------------------------------------------------- */ /* Verify we have all required fields */ /* -------------------------------------------------------------------- */ if( CSLFetchNameValue( papszOptions, "PIXELS" ) == NULL || CSLFetchNameValue( papszOptions, "LINES" ) == NULL || CSLFetchNameValue( papszOptions, "DATAPOINTER" ) == NULL ) { CPLError( CE_Failure, CPLE_AppDefined, "Missing required field (one of PIXELS, LINES or DATAPOINTER). " "Unable to access in-memory array." ); CSLDestroy( papszOptions ); return NULL; } /* -------------------------------------------------------------------- */ /* Create the new MEMDataset object. */ /* -------------------------------------------------------------------- */ MEMDataset *poDS = new MEMDataset(); poDS->nRasterXSize = atoi(CSLFetchNameValue(papszOptions,"PIXELS")); poDS->nRasterYSize = atoi(CSLFetchNameValue(papszOptions,"LINES")); poDS->eAccess = GA_Update; /* -------------------------------------------------------------------- */ /* Extract other information. */ /* -------------------------------------------------------------------- */ const char *pszOption = CSLFetchNameValue(papszOptions,"BANDS"); int nBands = 1; if( pszOption != NULL ) { nBands = atoi(pszOption); } if( !GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) || !GDALCheckBandCount(nBands, TRUE)) { CSLDestroy( papszOptions ); delete poDS; return NULL; } pszOption = CSLFetchNameValue(papszOptions,"DATATYPE"); GDALDataType eType = GDT_Byte; if( pszOption != NULL ) { if( atoi(pszOption) > 0 && atoi(pszOption) < GDT_TypeCount ) eType = static_cast<GDALDataType>( atoi(pszOption) ); else { eType = GDT_Unknown; for( int iType = 0; iType < GDT_TypeCount; iType++ ) { if( EQUAL(GDALGetDataTypeName((GDALDataType) iType), pszOption) ) { eType = static_cast<GDALDataType>( iType ); break; } } if( eType == GDT_Unknown ) { CPLError( CE_Failure, CPLE_AppDefined, "DATATYPE=%s not recognised.", pszOption ); CSLDestroy( papszOptions ); delete poDS; return NULL; } } } pszOption = CSLFetchNameValue(papszOptions, "PIXELOFFSET"); GSpacing nPixelOffset; if( pszOption == NULL ) nPixelOffset = GDALGetDataTypeSizeBytes(eType); else nPixelOffset = CPLScanUIntBig(pszOption, static_cast<int>(strlen(pszOption))); pszOption = CSLFetchNameValue(papszOptions, "LINEOFFSET"); GSpacing nLineOffset = 0; if( pszOption == NULL ) nLineOffset = poDS->nRasterXSize * static_cast<size_t>( nPixelOffset ); else nLineOffset = CPLScanUIntBig(pszOption, static_cast<int>(strlen(pszOption))); pszOption = CSLFetchNameValue(papszOptions, "BANDOFFSET"); GSpacing nBandOffset = 0; if( pszOption == NULL ) nBandOffset = nLineOffset * static_cast<size_t>( poDS->nRasterYSize ); else nBandOffset = CPLScanUIntBig(pszOption, static_cast<int>(strlen(pszOption))); const char *pszDataPointer = CSLFetchNameValue(papszOptions,"DATAPOINTER"); GByte *pabyData = reinterpret_cast<GByte *>( CPLScanPointer( pszDataPointer, static_cast<int>(strlen(pszDataPointer)) ) ); /* -------------------------------------------------------------------- */ /* Create band information objects. */ /* -------------------------------------------------------------------- */ for( int iBand = 0; iBand < nBands; iBand++ ) { poDS->SetBand( iBand+1, new MEMRasterBand( poDS, iBand+1, pabyData + iBand * nBandOffset, eType, nPixelOffset, nLineOffset, FALSE ) ); } /* -------------------------------------------------------------------- */ /* Try to return a regular handle on the file. */ /* -------------------------------------------------------------------- */ CSLDestroy( papszOptions ); return poDS; }
CPLErr GDALSimpleSURF::ConvertRGBToLuminosity( GDALRasterBand *red, GDALRasterBand *green, GDALRasterBand *blue, int nXSize, int nYSize, double **padfImg, int nHeight, int nWidth ) { if( red == nullptr || green == nullptr || blue == nullptr ) { CPLError(CE_Failure, CPLE_AppDefined, "Raster bands are not specified"); return CE_Failure; } if( nXSize > red->GetXSize() || nYSize > red->GetYSize() ) { CPLError(CE_Failure, CPLE_AppDefined, "Red band has less size than has been requested"); return CE_Failure; } if( padfImg == nullptr ) { CPLError(CE_Failure, CPLE_AppDefined, "Buffer isn't specified"); return CE_Failure; } const double forRed = 0.21; const double forGreen = 0.72; const double forBlue = 0.07; const GDALDataType eRedType = red->GetRasterDataType(); const GDALDataType eGreenType = green->GetRasterDataType(); const GDALDataType eBlueType = blue->GetRasterDataType(); const int dataRedSize = GDALGetDataTypeSizeBytes(eRedType); const int dataGreenSize = GDALGetDataTypeSizeBytes(eGreenType); const int dataBlueSize = GDALGetDataTypeSizeBytes(eBlueType); void *paRedLayer = CPLMalloc(dataRedSize * nWidth * nHeight); void *paGreenLayer = CPLMalloc(dataGreenSize * nWidth * nHeight); void *paBlueLayer = CPLMalloc(dataBlueSize * nWidth * nHeight); CPLErr eErr = red->RasterIO(GF_Read, 0, 0, nXSize, nYSize, paRedLayer, nWidth, nHeight, eRedType, 0, 0, nullptr); if( eErr == CE_None ) eErr = green->RasterIO(GF_Read, 0, 0, nXSize, nYSize, paGreenLayer, nWidth, nHeight, eGreenType, 0, 0, nullptr); if( eErr == CE_None ) eErr = blue->RasterIO(GF_Read, 0, 0, nXSize, nYSize, paBlueLayer, nWidth, nHeight, eBlueType, 0, 0, nullptr); double maxValue = 255.0; for( int row = 0; row < nHeight && eErr == CE_None; row++ ) for( int col = 0; col < nWidth; col++ ) { // Get RGB values. const double dfRedVal = SRCVAL(paRedLayer, eRedType, nWidth * row + col * dataRedSize); const double dfGreenVal = SRCVAL(paGreenLayer, eGreenType, nWidth * row + col * dataGreenSize); const double dfBlueVal = SRCVAL(paBlueLayer, eBlueType, nWidth * row + col * dataBlueSize); // Compute luminosity value. padfImg[row][col] = ( dfRedVal * forRed + dfGreenVal * forGreen + dfBlueVal * forBlue) / maxValue; } CPLFree(paRedLayer); CPLFree(paGreenLayer); CPLFree(paBlueLayer); return eErr; }
GDALDataset *ROIPACDataset::Open( GDALOpenInfo *poOpenInfo ) { /* -------------------------------------------------------------------- */ /* Confirm that the header is compatible with a ROIPAC dataset. */ /* -------------------------------------------------------------------- */ if ( !Identify(poOpenInfo) ) { return NULL; } /* -------------------------------------------------------------------- */ /* Open the .rsc file */ /* -------------------------------------------------------------------- */ CPLString osRscFilename = getRscFilename( poOpenInfo ); if ( osRscFilename.empty() ) { return NULL; } VSILFILE *fpRsc; if ( poOpenInfo->eAccess == GA_Update ) { fpRsc = VSIFOpenL( osRscFilename, "r+" ); } else { fpRsc = VSIFOpenL( osRscFilename, "r" ); } if ( fpRsc == NULL ) { return NULL; } /* -------------------------------------------------------------------- */ /* Load the .rsc information. */ /* -------------------------------------------------------------------- */ char **papszRsc = NULL; while ( true ) { const char *pszLine = CPLReadLineL( fpRsc ); if (pszLine == NULL) { break; } char **papszTokens = CSLTokenizeString2( pszLine, " \t", CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES | CSLT_PRESERVEQUOTES | CSLT_PRESERVEESCAPES ); if ( papszTokens == NULL || papszTokens[0] == NULL || papszTokens[1] == NULL ) { CSLDestroy ( papszTokens ); break; } papszRsc = CSLSetNameValue( papszRsc, papszTokens[0], papszTokens[1] ); CSLDestroy ( papszTokens ); } /* -------------------------------------------------------------------- */ /* Fetch required fields. */ /* -------------------------------------------------------------------- */ if ( CSLFetchNameValue( papszRsc, "WIDTH" ) == NULL || CSLFetchNameValue( papszRsc, "FILE_LENGTH" ) == NULL ) { CSLDestroy( papszRsc ); CPL_IGNORE_RET_VAL(VSIFCloseL( fpRsc )); return NULL; } const int nWidth = atoi( CSLFetchNameValue( papszRsc, "WIDTH" ) ); const int nFileLength = atoi( CSLFetchNameValue( papszRsc, "FILE_LENGTH" ) ); /* -------------------------------------------------------------------- */ /* Create a corresponding GDALDataset. */ /* -------------------------------------------------------------------- */ ROIPACDataset *poDS = new ROIPACDataset(); poDS->nRasterXSize = nWidth; poDS->nRasterYSize = nFileLength; poDS->eAccess = poOpenInfo->eAccess; poDS->fpRsc = fpRsc; poDS->pszRscFilename = CPLStrdup( osRscFilename.c_str() ); /* -------------------------------------------------------------------- */ /* Reopen file in update mode if necessary. */ /* -------------------------------------------------------------------- */ if( poOpenInfo->eAccess == GA_Update ) { poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb+" ); } else { poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb" ); } if( poDS->fpImage == NULL ) { delete poDS; CPLError( CE_Failure, CPLE_OpenFailed, "Failed to re-open %s within ROI_PAC driver.\n", poOpenInfo->pszFilename ); CSLDestroy( papszRsc ); return NULL; } /* -------------------------------------------------------------------- */ /* Create band information objects. */ /* -------------------------------------------------------------------- */ GDALDataType eDataType; int nBands; enum Interleave { LINE, PIXEL } eInterleave; const char *pszExtension = CPLGetExtension(poOpenInfo->pszFilename); if ( strcmp( pszExtension, "raw" ) == 0 ) { /* ------------------------------------------------------------ */ /* TODO: ROI_PAC raw images are what would be GDT_CInt8 typed, */ /* but since that type do not exist, we will have to implement */ /* a specific case in the RasterBand to convert it to */ /* GDT_CInt16 for example */ /* ------------------------------------------------------------ */ #if 0 eDataType = GDT_CInt8; nBands = 1; eInterleave = PIXEL; #else CPLError( CE_Failure, CPLE_NotSupported, "Reading ROI_PAC raw files is not supported yet." ); delete poDS; CSLDestroy( papszRsc ); return NULL; #endif } else if ( strcmp( pszExtension, "int" ) == 0 || strcmp( pszExtension, "slc" ) == 0 ) { eDataType = GDT_CFloat32; nBands = 1; eInterleave = PIXEL; } else if ( strcmp( pszExtension, "amp" ) == 0 ) { eDataType = GDT_Float32; nBands = 2; eInterleave = PIXEL; } else if ( strcmp( pszExtension, "cor" ) == 0 || strcmp( pszExtension, "hgt" ) == 0 || strcmp( pszExtension, "unw" ) == 0 || strcmp( pszExtension, "msk" ) == 0 || strcmp( pszExtension, "trans" ) == 0 ) { eDataType = GDT_Float32; nBands = 2; eInterleave = LINE; } else if ( strcmp( pszExtension, "dem" ) == 0 ) { eDataType = GDT_Int16; nBands = 1; eInterleave = PIXEL; } else if ( strcmp( pszExtension, "flg" ) == 0 ) { eDataType = GDT_Byte; nBands = 1; eInterleave = PIXEL; } else { /* Eeek */ delete poDS; CSLDestroy( papszRsc ); return NULL; } int nPixelOffset; int nLineOffset; int nBandOffset; if (eInterleave == LINE) { nPixelOffset = GDALGetDataTypeSize(eDataType)/8; nLineOffset = nPixelOffset * nWidth * nBands; nBandOffset = GDALGetDataTypeSize(eDataType)/8 * nWidth; } else { /* PIXEL */ nPixelOffset = GDALGetDataTypeSize(eDataType)/8 * nBands; nLineOffset = nPixelOffset * nWidth; nBandOffset = GDALGetDataTypeSize(eDataType)/8; if( nBands > 1 ) { // GDAL 2.0.[0-3] and 2.1.0 had a value of nLineOffset that was // equal to the theoretical nLineOffset multiplied by nBands... VSIFSeekL( poDS->fpImage, 0, SEEK_END ); const GUIntBig nWrongFileSize = GDALGetDataTypeSizeBytes(eDataType) * nWidth * (static_cast<GUIntBig>(nFileLength - 1) * nBands * nBands + nBands); if( VSIFTellL( poDS->fpImage ) == nWrongFileSize ) { CPLError(CE_Warning, CPLE_AppDefined, "This file has been incorrectly generated by an older " "GDAL version whose line offset computation was erroneous. " "Taking that into account, but the file should be re-encoded ideally"); nLineOffset = nLineOffset * nBands; } } } poDS->nBands = nBands; for (int b = 0; b < nBands; b++) { poDS->SetBand( b + 1, new ROIPACRasterBand( poDS, b + 1, poDS->fpImage, nBandOffset * b, nPixelOffset, nLineOffset, eDataType, TRUE, TRUE, FALSE ) ); } /* -------------------------------------------------------------------- */ /* Interpret georeferencing, if present. */ /* -------------------------------------------------------------------- */ if ( CSLFetchNameValue( papszRsc, "X_FIRST" ) != NULL && CSLFetchNameValue( papszRsc, "X_STEP" ) != NULL && CSLFetchNameValue( papszRsc, "Y_FIRST" ) != NULL && CSLFetchNameValue( papszRsc, "Y_STEP" ) != NULL ) { poDS->adfGeoTransform[0] = CPLAtof( CSLFetchNameValue( papszRsc, "X_FIRST" ) ); poDS->adfGeoTransform[1] = CPLAtof( CSLFetchNameValue( papszRsc, "X_STEP" ) ); poDS->adfGeoTransform[2] = 0.0; poDS->adfGeoTransform[3] = CPLAtof( CSLFetchNameValue( papszRsc, "Y_FIRST" ) ); poDS->adfGeoTransform[4] = 0.0; poDS->adfGeoTransform[5] = CPLAtof( CSLFetchNameValue( papszRsc, "Y_STEP" ) ); poDS->bValidGeoTransform = true; } if ( CSLFetchNameValue( papszRsc, "PROJECTION" ) != NULL ) { /* ------------------------------------------------------------ */ /* In ROI_PAC, images are georeferenced either with lat/long or */ /* UTM projection. However, using UTM projection is dangerous */ /* because there is no North/South field, or use of latitude */ /* bands! */ /* ------------------------------------------------------------ */ OGRSpatialReference oSRS; if ( strcmp( CSLFetchNameValue( papszRsc, "PROJECTION" ), "LL" ) == 0 ) { if ( CSLFetchNameValue( papszRsc, "DATUM" ) != NULL ) { oSRS.SetWellKnownGeogCS( CSLFetchNameValue( papszRsc, "DATUM" ) ); } else { oSRS.SetWellKnownGeogCS( "WGS84" ); } } else if( STARTS_WITH(CSLFetchNameValue( papszRsc, "PROJECTION" ), "UTM") ) { const char *pszZone = CSLFetchNameValue( papszRsc, "PROJECTION" ) + 3; oSRS.SetUTM( atoi( pszZone ), TRUE ); /* FIXME: north/south? */ if ( CSLFetchNameValue( papszRsc, "DATUM" ) != NULL ) { oSRS.SetWellKnownGeogCS( CSLFetchNameValue( papszRsc, "DATUM" ) ); } else { oSRS.SetWellKnownGeogCS( "NAD27" ); } } oSRS.exportToWkt( &poDS->pszProjection ); } if ( CSLFetchNameValue( papszRsc, "Z_OFFSET" ) != NULL ) { const double dfOffset = strtod( CSLFetchNameValue( papszRsc, "Z_OFFSET" ), NULL); for (int b = 1; b <= nBands; b++) { GDALRasterBand *poBand = poDS->GetRasterBand(b); poBand->SetOffset( dfOffset ); } } if ( CSLFetchNameValue( papszRsc, "Z_SCALE" ) != NULL ) { const double dfScale = strtod( CSLFetchNameValue( papszRsc, "Z_SCALE" ), NULL); for (int b = 1; b <= nBands; b++) { GDALRasterBand *poBand = poDS->GetRasterBand(b); poBand->SetScale( dfScale ); } } /* -------------------------------------------------------------------- */ /* Set all the other header metadata into the ROI_PAC domain */ /* -------------------------------------------------------------------- */ for (int i = 0; i < CSLCount( papszRsc ); i++) { char **papszTokens = CSLTokenizeString2( papszRsc[i], "=", CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES); if ( strcmp( papszTokens[0], "WIDTH" ) == 0 || strcmp( papszTokens[0], "FILE_LENGTH" ) == 0 || strcmp( papszTokens[0], "X_FIRST" ) == 0 || strcmp( papszTokens[0], "X_STEP" ) == 0 || strcmp( papszTokens[0], "Y_FIRST" ) == 0 || strcmp( papszTokens[0], "Y_STEP" ) == 0 || strcmp( papszTokens[0], "PROJECTION" ) == 0 || strcmp( papszTokens[0], "DATUM" ) == 0 || strcmp( papszTokens[0], "Z_OFFSET" ) == 0 || strcmp( papszTokens[0], "Z_SCALE" ) == 0 ) { CSLDestroy( papszTokens ); continue; } poDS->SetMetadataItem(papszTokens[0], papszTokens[1], "ROI_PAC"); CSLDestroy( papszTokens ); } /* -------------------------------------------------------------------- */ /* Free papszRsc */ /* -------------------------------------------------------------------- */ CSLDestroy( papszRsc ); /* -------------------------------------------------------------------- */ /* Initialize any PAM information. */ /* -------------------------------------------------------------------- */ poDS->SetDescription( poOpenInfo->pszFilename ); poDS->TryLoadXML(); /* -------------------------------------------------------------------- */ /* Check for overviews. */ /* -------------------------------------------------------------------- */ poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename ); return( poDS ); }
GDALDataset *PAuxDataset::Create( const char * pszFilename, int nXSize, int nYSize, int nBands, GDALDataType eType, char **papszOptions ) { const char *pszInterleave = CSLFetchNameValue( papszOptions, "INTERLEAVE" ); if( pszInterleave == nullptr ) pszInterleave = "BAND"; /* -------------------------------------------------------------------- */ /* Verify input options. */ /* -------------------------------------------------------------------- */ if( eType != GDT_Byte && eType != GDT_Float32 && eType != GDT_UInt16 && eType != GDT_Int16 ) { CPLError( CE_Failure, CPLE_AppDefined, "Attempt to create PCI .Aux labelled dataset with an illegal\n" "data type (%s).\n", GDALGetDataTypeName(eType) ); return nullptr; } /* -------------------------------------------------------------------- */ /* Sum the sizes of the band pixel types. */ /* -------------------------------------------------------------------- */ int nPixelSizeSum = 0; for( int iBand = 0; iBand < nBands; iBand++ ) nPixelSizeSum += GDALGetDataTypeSizeBytes(eType); /* -------------------------------------------------------------------- */ /* Try to create the file. */ /* -------------------------------------------------------------------- */ VSILFILE *fp = VSIFOpenL( pszFilename, "w" ); if( fp == nullptr ) { CPLError( CE_Failure, CPLE_OpenFailed, "Attempt to create file `%s' failed.\n", pszFilename ); return nullptr; } /* -------------------------------------------------------------------- */ /* Just write out a couple of bytes to establish the binary */ /* file, and then close it. */ /* -------------------------------------------------------------------- */ CPL_IGNORE_RET_VAL(VSIFWriteL( "\0\0", 2, 1, fp )); CPL_IGNORE_RET_VAL(VSIFCloseL( fp )); /* -------------------------------------------------------------------- */ /* Create the aux filename. */ /* -------------------------------------------------------------------- */ char *pszAuxFilename = static_cast<char *>( CPLMalloc( strlen( pszFilename ) + 5 ) ); strcpy( pszAuxFilename, pszFilename ); for( int i = static_cast<int>(strlen(pszAuxFilename))-1; i > 0; i-- ) { if( pszAuxFilename[i] == '.' ) { pszAuxFilename[i] = '\0'; break; } } strcat( pszAuxFilename, ".aux" ); /* -------------------------------------------------------------------- */ /* Open the file. */ /* -------------------------------------------------------------------- */ fp = VSIFOpenL( pszAuxFilename, "wt" ); if( fp == nullptr ) { CPLError( CE_Failure, CPLE_OpenFailed, "Attempt to create file `%s' failed.\n", pszAuxFilename ); return nullptr; } CPLFree( pszAuxFilename ); /* -------------------------------------------------------------------- */ /* We need to write out the original filename but without any */ /* path components in the AuxilaryTarget line. Do so now. */ /* -------------------------------------------------------------------- */ int iStart = static_cast<int>(strlen(pszFilename))-1; while( iStart > 0 && pszFilename[iStart-1] != '/' && pszFilename[iStart-1] != '\\' ) iStart--; CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "AuxilaryTarget: %s\n", pszFilename + iStart )); /* -------------------------------------------------------------------- */ /* Write out the raw definition for the dataset as a whole. */ /* -------------------------------------------------------------------- */ CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "RawDefinition: %d %d %d\n", nXSize, nYSize, nBands )); /* -------------------------------------------------------------------- */ /* Write out a definition for each band. We always write band */ /* sequential files for now as these are pretty efficiently */ /* handled by GDAL. */ /* -------------------------------------------------------------------- */ vsi_l_offset nImgOffset = 0; for( int iBand = 0; iBand < nBands; iBand++ ) { int nPixelOffset = 0; int nLineOffset = 0; vsi_l_offset nNextImgOffset = 0; /* -------------------------------------------------------------------- */ /* Establish our file layout based on supplied interleaving. */ /* -------------------------------------------------------------------- */ if( EQUAL(pszInterleave,"LINE") ) { nPixelOffset = GDALGetDataTypeSizeBytes(eType); nLineOffset = nXSize * nPixelSizeSum; nNextImgOffset = nImgOffset + nPixelOffset * nXSize; } else if( EQUAL(pszInterleave,"PIXEL") ) { nPixelOffset = nPixelSizeSum; nLineOffset = nXSize * nPixelOffset; nNextImgOffset = nImgOffset + GDALGetDataTypeSizeBytes(eType); } else /* default to band */ { nPixelOffset = GDALGetDataTypeSize(eType)/8; nLineOffset = nXSize * nPixelOffset; nNextImgOffset = nImgOffset + nYSize * static_cast<vsi_l_offset>( nLineOffset ); } /* -------------------------------------------------------------------- */ /* Write out line indicating layout. */ /* -------------------------------------------------------------------- */ const char *pszTypeName = nullptr; if( eType == GDT_Float32 ) pszTypeName = "32R"; else if( eType == GDT_Int16 ) pszTypeName = "16S"; else if( eType == GDT_UInt16 ) pszTypeName = "16U"; else pszTypeName = "8U"; CPL_IGNORE_RET_VAL( VSIFPrintfL( fp, "ChanDefinition-%d: %s " CPL_FRMT_GIB " %d %d %s\n", iBand+1, pszTypeName, static_cast<GIntBig>( nImgOffset ), nPixelOffset, nLineOffset, #ifdef CPL_LSB "Swapped" #else "Unswapped" #endif ) ); nImgOffset = nNextImgOffset; } /* -------------------------------------------------------------------- */ /* Cleanup */ /* -------------------------------------------------------------------- */ CPL_IGNORE_RET_VAL(VSIFCloseL( fp )); return static_cast<GDALDataset *>( GDALOpen( pszFilename, GA_Update ) ); }
GDALDataset *ISIS2Dataset::Open( GDALOpenInfo * poOpenInfo ) { /* -------------------------------------------------------------------- */ /* Does this look like a CUBE or an IMAGE Primary Data Object? */ /* -------------------------------------------------------------------- */ if( !Identify( poOpenInfo ) || poOpenInfo->fpL == nullptr ) return nullptr; VSILFILE *fpQube = poOpenInfo->fpL; poOpenInfo->fpL = nullptr; ISIS2Dataset *poDS = new ISIS2Dataset(); if( ! poDS->oKeywords.Ingest( fpQube, 0 ) ) { VSIFCloseL( fpQube ); delete poDS; return nullptr; } VSIFCloseL( fpQube ); /* -------------------------------------------------------------------- */ /* We assume the user is pointing to the label (i.e. .lab) file. */ /* -------------------------------------------------------------------- */ // QUBE can be inline or detached and point to an image name // ^QUBE = 76 // ^QUBE = ("ui31s015.img",6441<BYTES>) - has another label on the image // ^QUBE = "ui31s015.img" - which implies no label or skip value const char *pszQube = poDS->GetKeyword( "^QUBE" ); GUIntBig nQube = 0; int bByteLocation = FALSE; CPLString osTargetFile = poOpenInfo->pszFilename; if( pszQube[0] == '"' ) { const CPLString osTPath = CPLGetPath(poOpenInfo->pszFilename); CPLString osFilename = pszQube; poDS->CleanString( osFilename ); osTargetFile = CPLFormCIFilename( osTPath, osFilename, nullptr ); poDS->osExternalCube = osTargetFile; } else if( pszQube[0] == '(' ) { const CPLString osTPath = CPLGetPath(poOpenInfo->pszFilename); CPLString osFilename = poDS->GetKeywordSub("^QUBE",1,""); poDS->CleanString( osFilename ); osTargetFile = CPLFormCIFilename( osTPath, osFilename, nullptr ); poDS->osExternalCube = osTargetFile; nQube = atoi(poDS->GetKeywordSub("^QUBE",2,"1")); if( strstr(poDS->GetKeywordSub("^QUBE",2,"1"),"<BYTES>") != nullptr ) bByteLocation = true; } else { nQube = atoi(pszQube); if( strstr(pszQube,"<BYTES>") != nullptr ) bByteLocation = true; } /* -------------------------------------------------------------------- */ /* Check if file an ISIS2 header file? Read a few lines of text */ /* searching for something starting with nrows or ncols. */ /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ /* Checks to see if this is valid ISIS2 cube */ /* SUFFIX_ITEM tag in .cub file should be (0,0,0); no side-planes */ /* -------------------------------------------------------------------- */ const int s_ix = atoi(poDS->GetKeywordSub( "QUBE.SUFFIX_ITEMS", 1 )); const int s_iy = atoi(poDS->GetKeywordSub( "QUBE.SUFFIX_ITEMS", 2 )); const int s_iz = atoi(poDS->GetKeywordSub( "QUBE.SUFFIX_ITEMS", 3 )); if( s_ix != 0 || s_iy != 0 || s_iz != 0 ) { CPLError( CE_Failure, CPLE_OpenFailed, "*** ISIS 2 cube file has invalid SUFFIX_ITEMS parameters:\n" "*** gdal isis2 driver requires (0, 0, 0), thus no sideplanes or backplanes\n" "found: (%i, %i, %i)\n\n", s_ix, s_iy, s_iz ); delete poDS; return nullptr; } /**************** end SUFFIX_ITEM check ***********************/ /*********** Grab layout type (BSQ, BIP, BIL) ************/ // AXIS_NAME = (SAMPLE,LINE,BAND) /***********************************************************/ char szLayout[10] = "BSQ"; //default to band seq. const char *value = poDS->GetKeyword( "QUBE.AXIS_NAME", "" ); if (EQUAL(value,"(SAMPLE,LINE,BAND)") ) strcpy(szLayout,"BSQ"); else if (EQUAL(value,"(BAND,LINE,SAMPLE)") ) strcpy(szLayout,"BIP"); else if (EQUAL(value,"(SAMPLE,BAND,LINE)") || EQUAL(value,"") ) strcpy(szLayout,"BSQ"); else { CPLError( CE_Failure, CPLE_OpenFailed, "%s layout not supported. Abort\n\n", value); delete poDS; return nullptr; } /*********** Grab samples lines band ************/ const int nCols = atoi(poDS->GetKeywordSub("QUBE.CORE_ITEMS",1)); const int nRows = atoi(poDS->GetKeywordSub("QUBE.CORE_ITEMS",2)); const int nBands = atoi(poDS->GetKeywordSub("QUBE.CORE_ITEMS",3)); /*********** Grab Qube record bytes **********/ const int record_bytes = atoi(poDS->GetKeyword("RECORD_BYTES")); GUIntBig nSkipBytes = 0; if (nQube > 0 && bByteLocation ) nSkipBytes = (nQube - 1); else if( nQube > 0 ) nSkipBytes = (nQube - 1) * record_bytes; else nSkipBytes = 0; /*********** Grab samples lines band ************/ char chByteOrder = 'M'; //default to MSB CPLString osCoreItemType = poDS->GetKeyword( "QUBE.CORE_ITEM_TYPE" ); if( (EQUAL(osCoreItemType,"PC_INTEGER")) || (EQUAL(osCoreItemType,"PC_UNSIGNED_INTEGER")) || (EQUAL(osCoreItemType,"PC_REAL")) ) { chByteOrder = 'I'; } /******** Grab format type - isis2 only supports 8,16,32 *******/ GDALDataType eDataType = GDT_Byte; bool bNoDataSet = false; double dfNoData = 0.0; int itype = atoi(poDS->GetKeyword("QUBE.CORE_ITEM_BYTES","")); switch(itype) { case 1 : eDataType = GDT_Byte; dfNoData = NULL1; bNoDataSet = true; break; case 2 : if( strstr(osCoreItemType,"UNSIGNED") != nullptr ) { dfNoData = 0; eDataType = GDT_UInt16; } else { dfNoData = NULL2; eDataType = GDT_Int16; } bNoDataSet = true; break; case 4 : eDataType = GDT_Float32; dfNoData = NULL3; bNoDataSet = true; break; case 8 : eDataType = GDT_Float64; dfNoData = NULL3; bNoDataSet = true; break; default : CPLError( CE_Failure, CPLE_AppDefined, "Itype of %d is not supported in ISIS 2.", itype); delete poDS; return nullptr; } /*********** Grab Cellsize ************/ double dfXDim = 1.0; double dfYDim = 1.0; value = poDS->GetKeyword("QUBE.IMAGE_MAP_PROJECTION.MAP_SCALE"); if (strlen(value) > 0 ) { // Convert km to m dfXDim = static_cast<float>( CPLAtof(value) * 1000.0 ); dfYDim = static_cast<float>( CPLAtof(value) * 1000.0 * -1 ); } /*********** Grab LINE_PROJECTION_OFFSET ************/ double dfULYMap = 0.5; double yulcenter = 0.0; value = poDS->GetKeyword("QUBE.IMAGE_MAP_PROJECTION.LINE_PROJECTION_OFFSET"); if (strlen(value) > 0) { yulcenter = static_cast<float>( CPLAtof(value) ); yulcenter = ((yulcenter) * dfYDim); dfULYMap = yulcenter - (dfYDim/2); } /*********** Grab SAMPLE_PROJECTION_OFFSET ************/ double dfULXMap = 0.5; double xulcenter = 0.0; value = poDS->GetKeyword("QUBE.IMAGE_MAP_PROJECTION.SAMPLE_PROJECTION_OFFSET"); if( strlen(value) > 0 ) { xulcenter= static_cast<float>( CPLAtof(value) ); xulcenter = ((xulcenter) * dfXDim); dfULXMap = xulcenter - (dfXDim/2); } /*********** Grab TARGET_NAME ************/ /**** This is the planets name i.e. MARS ***/ CPLString target_name = poDS->GetKeyword("QUBE.TARGET_NAME"); /*********** Grab MAP_PROJECTION_TYPE ************/ CPLString map_proj_name = poDS->GetKeyword( "QUBE.IMAGE_MAP_PROJECTION.MAP_PROJECTION_TYPE"); poDS->CleanString( map_proj_name ); /*********** Grab SEMI-MAJOR ************/ const double semi_major = CPLAtof(poDS->GetKeyword( "QUBE.IMAGE_MAP_PROJECTION.A_AXIS_RADIUS")) * 1000.0; /*********** Grab semi-minor ************/ const double semi_minor = CPLAtof(poDS->GetKeyword( "QUBE.IMAGE_MAP_PROJECTION.C_AXIS_RADIUS")) * 1000.0; /*********** Grab CENTER_LAT ************/ const double center_lat = CPLAtof(poDS->GetKeyword( "QUBE.IMAGE_MAP_PROJECTION.CENTER_LATITUDE")); /*********** Grab CENTER_LON ************/ const double center_lon = CPLAtof(poDS->GetKeyword( "QUBE.IMAGE_MAP_PROJECTION.CENTER_LONGITUDE")); /*********** Grab 1st std parallel ************/ const double first_std_parallel = CPLAtof(poDS->GetKeyword( "QUBE.IMAGE_MAP_PROJECTION.FIRST_STANDARD_PARALLEL")); /*********** Grab 2nd std parallel ************/ const double second_std_parallel = CPLAtof(poDS->GetKeyword( "QUBE.IMAGE_MAP_PROJECTION.SECOND_STANDARD_PARALLEL")); /*** grab PROJECTION_LATITUDE_TYPE = "PLANETOCENTRIC" ****/ // Need to further study how ocentric/ographic will effect the gdal library. // So far we will use this fact to define a sphere or ellipse for some projections // Frank - may need to talk this over bool bIsGeographic = true; value = poDS->GetKeyword("CUBE.IMAGE_MAP_PROJECTION.PROJECTION_LATITUDE_TYPE"); if (EQUAL( value, "\"PLANETOCENTRIC\"" )) bIsGeographic = false; CPLDebug("ISIS2","using projection %s", map_proj_name.c_str() ); OGRSpatialReference oSRS; bool bProjectionSet = true; //Set oSRS projection and parameters if ((EQUAL( map_proj_name, "EQUIRECTANGULAR_CYLINDRICAL" )) || (EQUAL( map_proj_name, "EQUIRECTANGULAR" )) || (EQUAL( map_proj_name, "SIMPLE_CYLINDRICAL" )) ) { oSRS.OGRSpatialReference::SetEquirectangular2 ( 0.0, center_lon, center_lat, 0, 0 ); } else if (EQUAL( map_proj_name, "ORTHOGRAPHIC" )) { oSRS.OGRSpatialReference::SetOrthographic ( center_lat, center_lon, 0, 0 ); } else if ((EQUAL( map_proj_name, "SINUSOIDAL" )) || (EQUAL( map_proj_name, "SINUSOIDAL_EQUAL-AREA" ))) { oSRS.OGRSpatialReference::SetSinusoidal ( center_lon, 0, 0 ); } else if (EQUAL( map_proj_name, "MERCATOR" )) { oSRS.OGRSpatialReference::SetMercator ( center_lat, center_lon, 1, 0, 0 ); } else if (EQUAL( map_proj_name, "POLAR_STEREOGRAPHIC" )) { oSRS.OGRSpatialReference::SetPS ( center_lat, center_lon, 1, 0, 0 ); } else if (EQUAL( map_proj_name, "TRANSVERSE_MERCATOR" )) { oSRS.OGRSpatialReference::SetTM ( center_lat, center_lon, 1, 0, 0 ); } else if (EQUAL( map_proj_name, "LAMBERT_CONFORMAL_CONIC" )) { oSRS.OGRSpatialReference::SetLCC ( first_std_parallel, second_std_parallel, center_lat, center_lon, 0, 0 ); } else if (EQUAL( map_proj_name, "") ) { /* no projection */ bProjectionSet = false; } else { CPLDebug( "ISIS2", "Dataset projection %s is not supported. Continuing...", map_proj_name.c_str() ); bProjectionSet = false; } if (bProjectionSet) { //Create projection name, i.e. MERCATOR MARS and set as ProjCS keyword const CPLString proj_target_name = map_proj_name + " " + target_name; oSRS.SetProjCS(proj_target_name); //set ProjCS keyword //The geographic/geocentric name will be the same basic name as the body name //'GCS' = Geographic/Geocentric Coordinate System const CPLString geog_name = "GCS_" + target_name; //The datum and sphere names will be the same basic name aas the planet const CPLString datum_name = "D_" + target_name; // Might not be IAU defined so don't add. CPLString sphere_name = target_name; // + "_IAU_IAG"); //calculate inverse flattening from major and minor axis: 1/f = a/(a-b) double iflattening = 0.0; if ((semi_major - semi_minor) < 0.0000001) iflattening = 0; else iflattening = semi_major / (semi_major - semi_minor); //Set the body size but take into consideration which proj is being used to help w/ proj4 compatibility //The use of a Sphere, polar radius or ellipse here is based on how ISIS does it internally if ( ( (EQUAL( map_proj_name, "STEREOGRAPHIC" ) && (fabs(center_lat) == 90)) ) || (EQUAL( map_proj_name, "POLAR_STEREOGRAPHIC" ))) { if (bIsGeographic) { //Geograpraphic, so set an ellipse oSRS.SetGeogCS( geog_name, datum_name, sphere_name, semi_major, iflattening, "Reference_Meridian", 0.0 ); } else { //Geocentric, so force a sphere using the semi-minor axis. I hope... sphere_name += "_polarRadius"; oSRS.SetGeogCS( geog_name, datum_name, sphere_name, semi_minor, 0.0, "Reference_Meridian", 0.0 ); } } else if ( (EQUAL( map_proj_name, "SIMPLE_CYLINDRICAL" )) || (EQUAL( map_proj_name, "ORTHOGRAPHIC" )) || (EQUAL( map_proj_name, "STEREOGRAPHIC" )) || (EQUAL( map_proj_name, "SINUSOIDAL_EQUAL-AREA" )) || (EQUAL( map_proj_name, "SINUSOIDAL" )) ) { // ISIS uses the spherical equation for these projections so force // a sphere. oSRS.SetGeogCS( geog_name, datum_name, sphere_name, semi_major, 0.0, "Reference_Meridian", 0.0 ); } else if ((EQUAL( map_proj_name, "EQUIRECTANGULAR_CYLINDRICAL" )) || (EQUAL( map_proj_name, "EQUIRECTANGULAR" )) ) { //Calculate localRadius using ISIS3 simple elliptical method // not the more standard Radius of Curvature method //PI = 4 * atan(1); if (center_lon == 0) { //No need to calculate local radius oSRS.SetGeogCS( geog_name, datum_name, sphere_name, semi_major, 0.0, "Reference_Meridian", 0.0 ); } else { const double radLat = center_lat * M_PI / 180; // in radians const double localRadius = semi_major * semi_minor / sqrt(pow(semi_minor*cos(radLat),2) + pow(semi_major*sin(radLat),2) ); sphere_name += "_localRadius"; oSRS.SetGeogCS( geog_name, datum_name, sphere_name, localRadius, 0.0, "Reference_Meridian", 0.0 ); CPLDebug( "ISIS2", "local radius: %f", localRadius); } } else { //All other projections: Mercator, Transverse Mercator, Lambert Conformal, etc. //Geographic, so set an ellipse if (bIsGeographic) { oSRS.SetGeogCS( geog_name, datum_name, sphere_name, semi_major, iflattening, "Reference_Meridian", 0.0 ); } else { //Geocentric, so force a sphere. I hope... oSRS.SetGeogCS( geog_name, datum_name, sphere_name, semi_major, 0.0, "Reference_Meridian", 0.0 ); } } // translate back into a projection string. char *pszResult = nullptr; oSRS.exportToWkt( &pszResult ); poDS->osProjection = pszResult; CPLFree( pszResult ); } /* END ISIS2 Label Read */ /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /* -------------------------------------------------------------------- */ /* Did we get the required keywords? If not we return with */ /* this never having been considered to be a match. This isn't */ /* an error! */ /* -------------------------------------------------------------------- */ if( !GDALCheckDatasetDimensions(nCols, nRows) || !GDALCheckBandCount(nBands, false) ) { delete poDS; return nullptr; } /* -------------------------------------------------------------------- */ /* Capture some information from the file that is of interest. */ /* -------------------------------------------------------------------- */ poDS->nRasterXSize = nCols; poDS->nRasterYSize = nRows; /* -------------------------------------------------------------------- */ /* Open target binary file. */ /* -------------------------------------------------------------------- */ if( poOpenInfo->eAccess == GA_ReadOnly ) poDS->fpImage = VSIFOpenL( osTargetFile, "rb" ); else poDS->fpImage = VSIFOpenL( osTargetFile, "r+b" ); if( poDS->fpImage == nullptr ) { CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open %s with write permission.\n%s", osTargetFile.c_str(), VSIStrerror( errno ) ); delete poDS; return nullptr; } poDS->eAccess = poOpenInfo->eAccess; /* -------------------------------------------------------------------- */ /* Compute the line offset. */ /* -------------------------------------------------------------------- */ int nItemSize = GDALGetDataTypeSizeBytes(eDataType); int nLineOffset, nPixelOffset; vsi_l_offset nBandOffset; if( EQUAL(szLayout,"BIP") ) { nPixelOffset = nItemSize * nBands; if( nPixelOffset > INT_MAX / nBands ) { delete poDS; return nullptr; } nLineOffset = nPixelOffset * nCols; nBandOffset = nItemSize; } else if( EQUAL(szLayout,"BSQ") ) { nPixelOffset = nItemSize; if( nPixelOffset > INT_MAX / nCols ) { delete poDS; return nullptr; } nLineOffset = nPixelOffset * nCols; nBandOffset = static_cast<vsi_l_offset>(nLineOffset) * nRows; } else /* assume BIL */ { nPixelOffset = nItemSize; if( nPixelOffset > INT_MAX / nBands || nPixelOffset * nBands > INT_MAX / nCols ) { delete poDS; return nullptr; } nLineOffset = nItemSize * nBands * nCols; nBandOffset = static_cast<vsi_l_offset>(nItemSize) * nCols; } /* -------------------------------------------------------------------- */ /* Create band information objects. */ /* -------------------------------------------------------------------- */ poDS->nBands = nBands; for( int i = 0; i < poDS->nBands; i++ ) { RawRasterBand *poBand = new RawRasterBand( poDS, i+1, poDS->fpImage, nSkipBytes + nBandOffset * i, nPixelOffset, nLineOffset, eDataType, #ifdef CPL_LSB chByteOrder == 'I' || chByteOrder == 'L', #else chByteOrder == 'M', #endif RawRasterBand::OwnFP::NO ); if( bNoDataSet ) poBand->SetNoDataValue( dfNoData ); poDS->SetBand( i+1, poBand ); // Set offset/scale values at the PAM level. poBand->SetOffset( CPLAtofM(poDS->GetKeyword("QUBE.CORE_BASE","0.0"))); poBand->SetScale( CPLAtofM(poDS->GetKeyword("QUBE.CORE_MULTIPLIER","1.0"))); } /* -------------------------------------------------------------------- */ /* Check for a .prj file. For isis2 I would like to keep this in */ /* -------------------------------------------------------------------- */ const CPLString osPath = CPLGetPath( poOpenInfo->pszFilename ); const CPLString osName = CPLGetBasename(poOpenInfo->pszFilename); const char *pszPrjFile = CPLFormCIFilename( osPath, osName, "prj" ); VSILFILE *fp = VSIFOpenL( pszPrjFile, "r" ); if( fp != nullptr ) { VSIFCloseL( fp ); char **papszLines = CSLLoad( pszPrjFile ); OGRSpatialReference oSRS2; if( oSRS2.importFromESRI( papszLines ) == OGRERR_NONE ) { char *pszResult = nullptr; oSRS2.exportToWkt( &pszResult ); poDS->osProjection = pszResult; CPLFree( pszResult ); } CSLDestroy( papszLines ); } if( dfULXMap != 0.5 || dfULYMap != 0.5 || dfXDim != 1.0 || dfYDim != 1.0 ) { poDS->bGotTransform = TRUE; poDS->adfGeoTransform[0] = dfULXMap; poDS->adfGeoTransform[1] = dfXDim; poDS->adfGeoTransform[2] = 0.0; poDS->adfGeoTransform[3] = dfULYMap; poDS->adfGeoTransform[4] = 0.0; poDS->adfGeoTransform[5] = dfYDim; } if( !poDS->bGotTransform ) poDS->bGotTransform = GDALReadWorldFile( poOpenInfo->pszFilename, "cbw", poDS->adfGeoTransform ); if( !poDS->bGotTransform ) poDS->bGotTransform = GDALReadWorldFile( poOpenInfo->pszFilename, "wld", poDS->adfGeoTransform ); /* -------------------------------------------------------------------- */ /* Initialize any PAM information. */ /* -------------------------------------------------------------------- */ poDS->SetDescription( poOpenInfo->pszFilename ); poDS->TryLoadXML(); /* -------------------------------------------------------------------- */ /* Check for overviews. */ /* -------------------------------------------------------------------- */ poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename ); return poDS; }
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; }
CPLErr GDALNoDataMaskBand::IReadBlock( int nXBlockOff, int nYBlockOff, void * pImage ) { GDALDataType eWrkDT; /* -------------------------------------------------------------------- */ /* Decide on a working type. */ /* -------------------------------------------------------------------- */ switch( poParent->GetRasterDataType() ) { case GDT_Byte: eWrkDT = GDT_Byte; break; case GDT_UInt16: case GDT_UInt32: eWrkDT = GDT_UInt32; break; case GDT_Int16: case GDT_Int32: case GDT_CInt16: case GDT_CInt32: eWrkDT = GDT_Int32; break; case GDT_Float32: case GDT_CFloat32: eWrkDT = GDT_Float32; break; case GDT_Float64: case GDT_CFloat64: eWrkDT = GDT_Float64; break; default: CPLAssert( FALSE ); eWrkDT = GDT_Float64; break; } /* -------------------------------------------------------------------- */ /* Read the image data. */ /* -------------------------------------------------------------------- */ CPLErr eErr; GByte *pabySrc = static_cast<GByte *>( VSI_MALLOC3_VERBOSE( GDALGetDataTypeSizeBytes(eWrkDT), nBlockXSize, nBlockYSize ) ); if (pabySrc == NULL) { return CE_Failure; } int nXSizeRequest = nBlockXSize; if (nXBlockOff * nBlockXSize + nBlockXSize > nRasterXSize) nXSizeRequest = nRasterXSize - nXBlockOff * nBlockXSize; int nYSizeRequest = nBlockYSize; if (nYBlockOff * nBlockYSize + nBlockYSize > nRasterYSize) nYSizeRequest = nRasterYSize - nYBlockOff * nBlockYSize; if (nXSizeRequest != nBlockXSize || nYSizeRequest != nBlockYSize) { /* memset the whole buffer to avoid Valgrind warnings in case we can't */ /* fetch a full block */ memset( pabySrc, 0, GDALGetDataTypeSizeBytes(eWrkDT) * nBlockXSize * nBlockYSize ); } eErr = poParent->RasterIO( GF_Read, nXBlockOff * nBlockXSize, nYBlockOff * nBlockYSize, nXSizeRequest, nYSizeRequest, pabySrc, nXSizeRequest, nYSizeRequest, eWrkDT, 0, nBlockXSize * GDALGetDataTypeSizeBytes(eWrkDT), NULL ); if( eErr != CE_None ) { CPLFree(pabySrc); return eErr; } int bIsNoDataNan = CPLIsNan(dfNoDataValue); /* -------------------------------------------------------------------- */ /* Process different cases. */ /* -------------------------------------------------------------------- */ int i; switch( eWrkDT ) { case GDT_Byte: { GByte byNoData = (GByte) dfNoDataValue; for( i = nBlockXSize * nBlockYSize - 1; i >= 0; i-- ) { if( pabySrc[i] == byNoData ) ((GByte *) pImage)[i] = 0; else ((GByte *) pImage)[i] = 255; } } break; case GDT_UInt32: { GUInt32 nNoData = (GUInt32) dfNoDataValue; for( i = nBlockXSize * nBlockYSize - 1; i >= 0; i-- ) { if( ((GUInt32 *)pabySrc)[i] == nNoData ) ((GByte *) pImage)[i] = 0; else ((GByte *) pImage)[i] = 255; } } break; case GDT_Int32: { GInt32 nNoData = (GInt32) dfNoDataValue; for( i = nBlockXSize * nBlockYSize - 1; i >= 0; i-- ) { if( ((GInt32 *)pabySrc)[i] == nNoData ) ((GByte *) pImage)[i] = 0; else ((GByte *) pImage)[i] = 255; } } break; case GDT_Float32: { float fNoData = (float) dfNoDataValue; for( i = nBlockXSize * nBlockYSize - 1; i >= 0; i-- ) { float fVal =((float *)pabySrc)[i]; if( bIsNoDataNan && CPLIsNan(fVal)) ((GByte *) pImage)[i] = 0; else if( ARE_REAL_EQUAL(fVal, fNoData) ) ((GByte *) pImage)[i] = 0; else ((GByte *) pImage)[i] = 255; } } break; case GDT_Float64: { for( i = nBlockXSize * nBlockYSize - 1; i >= 0; i-- ) { double dfVal =((double *)pabySrc)[i]; if( bIsNoDataNan && CPLIsNan(dfVal)) ((GByte *) pImage)[i] = 0; else if( ARE_REAL_EQUAL(dfVal, dfNoDataValue) ) ((GByte *) pImage)[i] = 0; else ((GByte *) pImage)[i] = 255; } } break; default: CPLAssert( FALSE ); break; } CPLFree( pabySrc ); return CE_None; }
int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { VSILFILE* fp = VSIFileFromMemBuffer( "/vsimem/test.tar", reinterpret_cast<GByte*>(const_cast<uint8_t*>(buf)), len, FALSE ); VSIFCloseL(fp); CPLPushErrorHandler(CPLQuietErrorHandler); char** papszArgv = nullptr; // Prevent generating too big output raster. Make sure they are set at // the beginning to avoid being accidentally eaten by invalid arguments // afterwards. papszArgv = CSLAddString(papszArgv, "-limit_outsize"); papszArgv = CSLAddString(papszArgv, "1000000"); fp = VSIFOpenL("/vsitar//vsimem/test.tar/cmd.txt", "rb"); if( fp != nullptr ) { const char* pszLine = nullptr; while( (pszLine = CPLReadLineL(fp)) != nullptr ) { if( !EQUAL(pszLine, "-limit_outsize") ) papszArgv = CSLAddString(papszArgv, pszLine); } VSIFCloseL(fp); } int nXDim = -1; int nYDim = -1; bool bXDimPct = false; bool bYDimPct = false; bool bNonNearestResampling = false; int nBlockXSize = 0; int nBlockYSize = 0; bool bStatsEnabled = false; bool bHFA = false; if( papszArgv != nullptr ) { int nCount = CSLCount(papszArgv); for( int i = 0; i < nCount; i++ ) { if( EQUAL(papszArgv[i], "-outsize") && i + 2 < nCount ) { nXDim = atoi(papszArgv[i+1]); bXDimPct = (papszArgv[i+1][0] != '\0' && papszArgv[i+1][strlen(papszArgv[i+1])-1] == '%'); nYDim = atoi(papszArgv[i+2]); bYDimPct = (papszArgv[i+2][0] != '\0' && papszArgv[i+2][strlen(papszArgv[i+2])-1] == '%'); } else if( EQUAL(papszArgv[i], "-r") && i + 1 < nCount ) { bNonNearestResampling = !STARTS_WITH_CI(papszArgv[i+1], "NEAR"); } else if( EQUAL(papszArgv[i], "-co") && i + 1 < nCount ) { if( STARTS_WITH_CI(papszArgv[i+1], "BLOCKSIZE=") ) { nBlockXSize = std::max(nBlockXSize, atoi(papszArgv[i+1]+strlen("BLOCKSIZE="))); nBlockYSize = std::max(nBlockYSize, atoi(papszArgv[i+1]+strlen("BLOCKSIZE="))); } else if( STARTS_WITH_CI(papszArgv[i+1], "BLOCKXSIZE=") ) { nBlockXSize = std::max(nBlockXSize, atoi(papszArgv[i+1]+strlen("BLOCKXSIZE="))); } else if( STARTS_WITH_CI(papszArgv[i+1], "BLOCKYSIZE=") ) { nBlockYSize = std::max(nBlockYSize, atoi(papszArgv[i+1]+strlen("BLOCKYSIZE="))); } } else if( EQUAL(papszArgv[i], "-stats") ) { bStatsEnabled = true; } else if( EQUAL(papszArgv[i], "-of") && i + 1 < nCount ) { bHFA = EQUAL( papszArgv[i+1], "HFA" ); } } if( bHFA ) { // Disable statistics computation for HFA, as it can be time // consuming. // See https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=10067 papszArgv = CSLInsertString(papszArgv, 0, "-co"); papszArgv = CSLInsertString(papszArgv, 1, "STATISTICS=NO"); } } if( papszArgv != nullptr ) { GDALTranslateOptions* psOptions = GDALTranslateOptionsNew(papszArgv, nullptr); if( psOptions ) { GDALDatasetH hSrcDS = GDALOpen( "/vsitar//vsimem/test.tar/in", GA_ReadOnly ); if( hSrcDS != nullptr ) { // Also check that reading the source doesn't involve too // much memory GDALDataset* poSrcDS = reinterpret_cast<GDALDataset*>(hSrcDS); int nBands = poSrcDS->GetRasterCount(); if( nBands < 10 ) { // Prevent excessive downsampling which might require huge // memory allocation bool bOKForResampling = true; if( bNonNearestResampling && nXDim >= 0 && nYDim >= 0 ) { if( bXDimPct && nXDim > 0 ) { nXDim = static_cast<int>( poSrcDS->GetRasterXSize() / 100.0 * nXDim); } if( bYDimPct && nYDim > 0 ) { nYDim = static_cast<int>( poSrcDS->GetRasterYSize() / 100.0 * nYDim); } if( nXDim > 0 && poSrcDS->GetRasterXSize() / nXDim > 100 ) bOKForResampling = false; if( nYDim > 0 && poSrcDS->GetRasterYSize() / nYDim > 100 ) bOKForResampling = false; } bool bOKForSrc = true; if( nBands ) { const int nDTSize = GDALGetDataTypeSizeBytes( poSrcDS->GetRasterBand(1)->GetRasterDataType() ); vsi_l_offset nSize = static_cast<vsi_l_offset>(nBands) * poSrcDS->GetRasterXSize() * poSrcDS->GetRasterYSize() * nDTSize; if( nSize > 10 * 1024 * 1024 ) { bOKForSrc = false; } int nBXSize = 0, nBYSize = 0; GDALGetBlockSize( GDALGetRasterBand(hSrcDS, 1), &nBXSize, &nBYSize ); const char* pszInterleave = GDALGetMetadataItem( hSrcDS, "INTERLEAVE", "IMAGE_STRUCTURE" ); int nSimultaneousBands = (pszInterleave && EQUAL(pszInterleave, "PIXEL")) ? nBands : 1; if( static_cast<GIntBig>(nSimultaneousBands)* nBXSize * nBYSize * nDTSize > 10 * 1024 * 1024 ) { bOKForSrc = false; } if( static_cast<GIntBig>(nBlockXSize) * nBlockYSize > 10 * 1024 * 1024 / (nBands * nDTSize) ) { bOKForSrc = false; } } bool bOKForStats = true; if( nBands && bStatsEnabled ) { // Other types might be too slow with sanitization enabled // See https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=10029 bOKForStats = poSrcDS->GetRasterBand(1)->GetRasterDataType() == GDT_Byte; } if( bOKForSrc && bOKForResampling && bOKForStats ) { GDALDatasetH hOutDS = GDALTranslate("/vsimem/out", hSrcDS, psOptions, nullptr); if( hOutDS ) GDALClose(hOutDS); } } GDALClose(hSrcDS); } GDALTranslateOptionsFree(psOptions); } } CSLDestroy(papszArgv); VSIRmdirRecursive("/vsimem/"); CPLPopErrorHandler(); return 0; }
CPLErr GDALNoDataMaskBand::IReadBlock( int nXBlockOff, int nYBlockOff, void * pImage ) { GDALDataType eWrkDT = GDT_Unknown; /* -------------------------------------------------------------------- */ /* Decide on a working type. */ /* -------------------------------------------------------------------- */ switch( poParent->GetRasterDataType() ) { case GDT_Byte: eWrkDT = GDT_Byte; break; case GDT_UInt16: case GDT_UInt32: eWrkDT = GDT_UInt32; break; case GDT_Int16: case GDT_Int32: case GDT_CInt16: case GDT_CInt32: eWrkDT = GDT_Int32; break; case GDT_Float32: case GDT_CFloat32: eWrkDT = GDT_Float32; break; case GDT_Float64: case GDT_CFloat64: eWrkDT = GDT_Float64; break; default: CPLAssert( false ); eWrkDT = GDT_Float64; break; } /* -------------------------------------------------------------------- */ /* Read the image data. */ /* -------------------------------------------------------------------- */ // TODO(schwehr): pabySrc would probably be better as a void ptr. GByte *pabySrc = static_cast<GByte *>( VSI_MALLOC3_VERBOSE( GDALGetDataTypeSizeBytes(eWrkDT), nBlockXSize, nBlockYSize ) ); if (pabySrc == nullptr) { return CE_Failure; } int nXSizeRequest = nBlockXSize; if (nXBlockOff * nBlockXSize + nBlockXSize > nRasterXSize) nXSizeRequest = nRasterXSize - nXBlockOff * nBlockXSize; int nYSizeRequest = nBlockYSize; if (nYBlockOff * nBlockYSize + nBlockYSize > nRasterYSize) nYSizeRequest = nRasterYSize - nYBlockOff * nBlockYSize; if (nXSizeRequest != nBlockXSize || nYSizeRequest != nBlockYSize) { // memset the whole buffer to avoid Valgrind warnings in case RasterIO // fetches a partial block. memset( pabySrc, 0, GDALGetDataTypeSizeBytes(eWrkDT) * nBlockXSize * nBlockYSize ); } CPLErr eErr = poParent->RasterIO( GF_Read, nXBlockOff * nBlockXSize, nYBlockOff * nBlockYSize, nXSizeRequest, nYSizeRequest, pabySrc, nXSizeRequest, nYSizeRequest, eWrkDT, 0, nBlockXSize * GDALGetDataTypeSizeBytes(eWrkDT), nullptr ); if( eErr != CE_None ) { CPLFree(pabySrc); return eErr; } const bool bIsNoDataNan = CPLIsNan(dfNoDataValue) != 0; /* -------------------------------------------------------------------- */ /* Process different cases. */ /* -------------------------------------------------------------------- */ switch( eWrkDT ) { case GDT_Byte: { if( !GDALIsValueInRange<GByte>(dfNoDataValue) ) { memset(pImage, 255, nBlockXSize * nBlockYSize); } else { GByte byNoData = static_cast<GByte>( dfNoDataValue ); for( int i = 0; i < nBlockXSize * nBlockYSize; i++ ) { static_cast<GByte *>(pImage)[i] = pabySrc[i] == byNoData ? 0: 255; } } } break; case GDT_UInt32: { if( !GDALIsValueInRange<GUInt32>(dfNoDataValue) ) { memset(pImage, 255, nBlockXSize * nBlockYSize); } else { GUInt32 nNoData = static_cast<GUInt32>( dfNoDataValue ); for( int i = 0; i < nBlockXSize * nBlockYSize; i++ ) { static_cast<GByte *>(pImage)[i] = reinterpret_cast<GUInt32 *>(pabySrc)[i] == nNoData ? 0 : 255; } } } break; case GDT_Int32: { if( !GDALIsValueInRange<GInt32>(dfNoDataValue) ) { memset(pImage, 255, nBlockXSize * nBlockYSize); } else { GInt32 nNoData = static_cast<GInt32>( dfNoDataValue ); for( int i = 0; i < nBlockXSize * nBlockYSize; i++ ) { static_cast<GByte *>(pImage)[i] = reinterpret_cast<GInt32 *>(pabySrc)[i] == nNoData ? 0 : 255; } } } break; case GDT_Float32: { if( !bIsNoDataNan && !CPLIsInf(dfNoDataValue) && !GDALIsValueInRange<float>(dfNoDataValue) ) { memset(pImage, 255, nBlockXSize * nBlockYSize); } else { float fNoData = static_cast<float>( dfNoDataValue ); for( int i = 0; i < nBlockXSize * nBlockYSize; i++ ) { const float fVal = reinterpret_cast<float *>(pabySrc)[i]; if( bIsNoDataNan && CPLIsNan(fVal)) static_cast<GByte *>(pImage)[i] = 0; else if( ARE_REAL_EQUAL(fVal, fNoData) ) static_cast<GByte *>(pImage)[i] = 0; else static_cast<GByte *>(pImage)[i] = 255; } } } break; case GDT_Float64: { for( int i = 0; i < nBlockXSize * nBlockYSize; i++ ) { const double dfVal = reinterpret_cast<double *>(pabySrc)[i]; if( bIsNoDataNan && CPLIsNan(dfVal)) static_cast<GByte *>(pImage)[i] = 0; else if( ARE_REAL_EQUAL(dfVal, dfNoDataValue) ) static_cast<GByte *>(pImage)[i] = 0; else static_cast<GByte *>(pImage)[i] = 255; } } break; default: CPLAssert( false ); break; } CPLFree( pabySrc ); return CE_None; }
CPLErr BTRasterBand::IWriteBlock( int nBlockXOff, CPL_UNUSED int nBlockYOff, void * pImage ) { CPLAssert( nBlockYOff == 0 ); const int nDataSize = GDALGetDataTypeSizeBytes( eDataType ); /* -------------------------------------------------------------------- */ /* Seek to profile. */ /* -------------------------------------------------------------------- */ if( VSIFSeekL( fpImage, 256 + nBlockXOff * nDataSize * nRasterYSize, SEEK_SET ) != 0 ) { CPLError( CE_Failure, CPLE_FileIO, ".bt Seek failed:%s", VSIStrerror( errno ) ); return CE_Failure; } /* -------------------------------------------------------------------- */ /* Allocate working buffer. */ /* -------------------------------------------------------------------- */ GByte *pabyWrkBlock = static_cast<GByte *>( CPLMalloc(nDataSize * nRasterYSize) ); /* -------------------------------------------------------------------- */ /* Vertical flip data into work buffer, since GDAL expects */ /* values from top to bottom, but in .bt they are bottom to */ /* top. */ /* -------------------------------------------------------------------- */ for( int i = 0; i < nRasterYSize; i++ ) { memcpy( pabyWrkBlock + (nRasterYSize - i - 1) * nDataSize, reinterpret_cast<GByte *>(pImage) + i * nDataSize, nDataSize ); } /* -------------------------------------------------------------------- */ /* Swap on MSB platforms. */ /* -------------------------------------------------------------------- */ #ifdef CPL_MSB GDALSwapWords( pabyWrkBlock, nDataSize, nRasterYSize, nDataSize ); #endif /* -------------------------------------------------------------------- */ /* Read the profile. */ /* -------------------------------------------------------------------- */ if( VSIFWriteL( pabyWrkBlock, nDataSize, nRasterYSize, fpImage ) != static_cast<size_t>( nRasterYSize ) ) { CPLFree( pabyWrkBlock ); CPLError( CE_Failure, CPLE_FileIO, ".bt Write failed:%s", VSIStrerror( errno ) ); return CE_Failure; } CPLFree( pabyWrkBlock ); return CE_None; }
GDALDataset *KRODataset::Create( const char * pszFilename, int nXSize, int nYSize, int nBands, GDALDataType eType, char ** /* papszOptions */ ) { if( eType != GDT_Byte && eType != GDT_UInt16 && eType != GDT_Float32 ) { CPLError( CE_Failure, CPLE_AppDefined, "Attempt to create KRO file with unsupported data type '%s'.", GDALGetDataTypeName( eType ) ); return nullptr; } if( nXSize == 0 || nYSize == 0 || nBands == 0 ) { return nullptr; } /* -------------------------------------------------------------------- */ /* Try to create file. */ /* -------------------------------------------------------------------- */ VSILFILE *fp = VSIFOpenL( pszFilename, "wb" ); if( fp == nullptr ) { CPLError( CE_Failure, CPLE_OpenFailed, "Attempt to create file `%s' failed.", pszFilename ); return nullptr; } size_t nRet = VSIFWriteL("KRO\01", 4, 1, fp); /* -------------------------------------------------------------------- */ /* Create a file level header. */ /* -------------------------------------------------------------------- */ int nTmp = nXSize; CPL_MSBPTR32(&nTmp); nRet += VSIFWriteL(&nTmp, 4, 1, fp); nTmp = nYSize; CPL_MSBPTR32(&nTmp); nRet += VSIFWriteL(&nTmp, 4, 1, fp); nTmp = GDALGetDataTypeSizeBits(eType); CPL_MSBPTR32(&nTmp); nRet += VSIFWriteL(&nTmp, 4, 1, fp); nTmp = nBands; CPL_MSBPTR32(&nTmp); nRet += VSIFWriteL(&nTmp, 4, 1, fp); /* -------------------------------------------------------------------- */ /* Zero out image data */ /* -------------------------------------------------------------------- */ CPL_IGNORE_RET_VAL( VSIFSeekL( fp, static_cast<vsi_l_offset>(nXSize) * nYSize * GDALGetDataTypeSizeBytes(eType) * nBands - 1, SEEK_CUR)); GByte byNul = 0; nRet += VSIFWriteL(&byNul, 1, 1, fp); if( VSIFCloseL(fp) != 0 ) { CPLError( CE_Failure, CPLE_FileIO, "I/O error" ); return nullptr; } if( nRet != 6 ) return nullptr; return reinterpret_cast<GDALDataset *>( GDALOpen( pszFilename, GA_Update ) ); }
GDALDataset *GTXDataset::Open( GDALOpenInfo * poOpenInfo ) { if( !Identify( poOpenInfo ) ) return NULL; /* -------------------------------------------------------------------- */ /* Create a corresponding GDALDataset. */ /* -------------------------------------------------------------------- */ GTXDataset *poDS = new GTXDataset(); poDS->eAccess = poOpenInfo->eAccess; /* -------------------------------------------------------------------- */ /* Open the file. */ /* -------------------------------------------------------------------- */ if( poOpenInfo->eAccess == GA_ReadOnly ) poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb" ); else poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb+" ); if( poDS->fpImage == NULL ) { delete poDS; return NULL; } /* -------------------------------------------------------------------- */ /* Read the header. */ /* -------------------------------------------------------------------- */ poDS->adfGeoTransform[2] = 0.0; poDS->adfGeoTransform[4] = 0.0; CPL_IGNORE_RET_VAL(VSIFReadL( poDS->adfGeoTransform+3, 8, 1, poDS->fpImage )); CPL_IGNORE_RET_VAL(VSIFReadL( poDS->adfGeoTransform+0, 8, 1, poDS->fpImage )); CPL_IGNORE_RET_VAL(VSIFReadL( poDS->adfGeoTransform+5, 8, 1, poDS->fpImage )); CPL_IGNORE_RET_VAL(VSIFReadL( poDS->adfGeoTransform+1, 8, 1, poDS->fpImage )); CPL_IGNORE_RET_VAL(VSIFReadL( &(poDS->nRasterYSize), 4, 1, poDS->fpImage )); CPL_IGNORE_RET_VAL(VSIFReadL( &(poDS->nRasterXSize), 4, 1, poDS->fpImage )); CPL_MSBPTR32( &(poDS->nRasterYSize) ); CPL_MSBPTR32( &(poDS->nRasterXSize) ); CPL_MSBPTR64( poDS->adfGeoTransform + 0 ); CPL_MSBPTR64( poDS->adfGeoTransform + 1 ); CPL_MSBPTR64( poDS->adfGeoTransform + 3 ); CPL_MSBPTR64( poDS->adfGeoTransform + 5 ); poDS->adfGeoTransform[3] += poDS->adfGeoTransform[5] * (poDS->nRasterYSize-1); poDS->adfGeoTransform[0] -= poDS->adfGeoTransform[1] * 0.5; poDS->adfGeoTransform[3] += poDS->adfGeoTransform[5] * 0.5; poDS->adfGeoTransform[5] *= -1; if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize)) { delete poDS; return NULL; } /* -------------------------------------------------------------------- */ /* Guess the data type. Since October 1, 2009, it should be */ /* Float32. Before it was double. */ /* -------------------------------------------------------------------- */ CPL_IGNORE_RET_VAL(VSIFSeekL(poDS->fpImage, 0, SEEK_END)); const vsi_l_offset nSize = VSIFTellL(poDS->fpImage); GDALDataType eDT = GDT_Float32; if( nSize == 40 + 8 * static_cast<vsi_l_offset>(poDS->nRasterXSize) * poDS->nRasterYSize ) eDT = GDT_Float64; const int nDTSize = GDALGetDataTypeSizeBytes(eDT); /* -------------------------------------------------------------------- */ /* Create band information object. */ /* -------------------------------------------------------------------- */ RawRasterBand *poBand = new RawRasterBand( poDS, 1, poDS->fpImage, (poDS->nRasterYSize-1) * poDS->nRasterXSize*nDTSize + 40, nDTSize, poDS->nRasterXSize * -nDTSize, eDT, !CPL_IS_LSB, TRUE, FALSE ); poBand->SetNoDataValue( -88.8888 ); poDS->SetBand( 1, poBand ); /* -------------------------------------------------------------------- */ /* Initialize any PAM information. */ /* -------------------------------------------------------------------- */ poDS->SetDescription( poOpenInfo->pszFilename ); poDS->TryLoadXML(); /* -------------------------------------------------------------------- */ /* Check for overviews. */ /* -------------------------------------------------------------------- */ poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename ); return poDS; }
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; }
GDALDataset * AAIGDataset::CreateCopy( const char *pszFilename, GDALDataset *poSrcDS, int /* bStrict */, char **papszOptions, GDALProgressFunc pfnProgress, void *pProgressData ) { const int nBands = poSrcDS->GetRasterCount(); const int nXSize = poSrcDS->GetRasterXSize(); const int nYSize = poSrcDS->GetRasterYSize(); // Some rudimentary checks. if( nBands != 1 ) { CPLError(CE_Failure, CPLE_NotSupported, "AAIG driver doesn't support %d bands. Must be 1 band.", nBands); return nullptr; } if( !pfnProgress(0.0, nullptr, pProgressData) ) return nullptr; // Create the dataset. VSILFILE *fpImage = VSIFOpenL(pszFilename, "wt"); if( fpImage == nullptr ) { CPLError(CE_Failure, CPLE_OpenFailed, "Unable to create file %s.", pszFilename); return nullptr; } // Write ASCII Grid file header. double adfGeoTransform[6] = {}; char szHeader[2000] = {}; const char *pszForceCellsize = CSLFetchNameValue(papszOptions, "FORCE_CELLSIZE"); poSrcDS->GetGeoTransform(adfGeoTransform); if( std::abs(adfGeoTransform[1] + adfGeoTransform[5]) < 0.0000001 || std::abs(adfGeoTransform[1]-adfGeoTransform[5]) < 0.0000001 || (pszForceCellsize && CPLTestBool(pszForceCellsize)) ) { CPLsnprintf( szHeader, sizeof(szHeader), "ncols %d\n" "nrows %d\n" "xllcorner %.12f\n" "yllcorner %.12f\n" "cellsize %.12f\n", nXSize, nYSize, adfGeoTransform[0], adfGeoTransform[3] - nYSize * adfGeoTransform[1], adfGeoTransform[1]); } else { if( pszForceCellsize == nullptr ) CPLError(CE_Warning, CPLE_AppDefined, "Producing a Golden Surfer style file with DX and DY " "instead of CELLSIZE since the input pixels are " "non-square. Use the FORCE_CELLSIZE=TRUE creation " "option to force use of DX for even though this will " "be distorted. Most ASCII Grid readers (ArcGIS " "included) do not support the DX and DY parameters."); CPLsnprintf( szHeader, sizeof(szHeader), "ncols %d\n" "nrows %d\n" "xllcorner %.12f\n" "yllcorner %.12f\n" "dx %.12f\n" "dy %.12f\n", nXSize, nYSize, adfGeoTransform[0], adfGeoTransform[3] + nYSize * adfGeoTransform[5], adfGeoTransform[1], fabs(adfGeoTransform[5])); } // Builds the format string used for printing float values. char szFormatFloat[32] = { '\0' }; strcpy(szFormatFloat, " %.20g"); const char *pszDecimalPrecision = CSLFetchNameValue(papszOptions, "DECIMAL_PRECISION"); const char *pszSignificantDigits = CSLFetchNameValue(papszOptions, "SIGNIFICANT_DIGITS"); bool bIgnoreSigDigits = false; if( pszDecimalPrecision && pszSignificantDigits ) { CPLError(CE_Warning, CPLE_AppDefined, "Conflicting precision arguments, using DECIMAL_PRECISION"); bIgnoreSigDigits = true; } int nPrecision; if ( pszSignificantDigits && !bIgnoreSigDigits ) { nPrecision = atoi(pszSignificantDigits); if (nPrecision >= 0) snprintf(szFormatFloat, sizeof(szFormatFloat), " %%.%dg", nPrecision); CPLDebug("AAIGrid", "Setting precision format: %s", szFormatFloat); } else if( pszDecimalPrecision ) { nPrecision = atoi(pszDecimalPrecision); if ( nPrecision >= 0 ) snprintf(szFormatFloat, sizeof(szFormatFloat), " %%.%df", nPrecision); CPLDebug("AAIGrid", "Setting precision format: %s", szFormatFloat); } // Handle nodata (optionally). GDALRasterBand *poBand = poSrcDS->GetRasterBand(1); const bool bReadAsInt = poBand->GetRasterDataType() == GDT_Byte || poBand->GetRasterDataType() == GDT_Int16 || poBand->GetRasterDataType() == GDT_UInt16 || poBand->GetRasterDataType() == GDT_Int32; // Write `nodata' value to header if it is exists in source dataset int bSuccess = FALSE; const double dfNoData = poBand->GetNoDataValue(&bSuccess); if ( bSuccess ) { snprintf(szHeader + strlen(szHeader), sizeof(szHeader) - strlen(szHeader), "%s", "NODATA_value "); if( bReadAsInt ) snprintf(szHeader + strlen(szHeader), sizeof(szHeader) - strlen(szHeader), "%d", static_cast<int>(dfNoData)); else CPLsnprintf(szHeader + strlen(szHeader), sizeof(szHeader) - strlen(szHeader), szFormatFloat, dfNoData); snprintf(szHeader + strlen(szHeader), sizeof(szHeader) - strlen(szHeader), "%s", "\n"); } if( VSIFWriteL(szHeader, strlen(szHeader), 1, fpImage) != 1) { CPL_IGNORE_RET_VAL(VSIFCloseL(fpImage)); return nullptr; } // Loop over image, copying image data. // Write scanlines to output file int *panScanline = bReadAsInt ? static_cast<int *>(CPLMalloc( nXSize * GDALGetDataTypeSizeBytes(GDT_Int32))) : nullptr; double *padfScanline = bReadAsInt ? nullptr : static_cast<double *>(CPLMalloc( nXSize * GDALGetDataTypeSizeBytes(GDT_Float64))); CPLErr eErr = CE_None; bool bHasOutputDecimalDot = false; for( int iLine = 0; eErr == CE_None && iLine < nYSize; iLine++ ) { CPLString osBuf; eErr = poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1, bReadAsInt ? reinterpret_cast<void *>(panScanline) : reinterpret_cast<void *>(padfScanline), nXSize, 1, bReadAsInt ? GDT_Int32 : GDT_Float64, 0, 0, nullptr); if( bReadAsInt ) { for ( int iPixel = 0; iPixel < nXSize; iPixel++ ) { snprintf(szHeader, sizeof(szHeader), " %d", panScanline[iPixel]); osBuf += szHeader; if( (iPixel & 1023) == 0 || iPixel == nXSize - 1 ) { if ( VSIFWriteL(osBuf, static_cast<int>(osBuf.size()), 1, fpImage) != 1 ) { eErr = CE_Failure; CPLError(CE_Failure, CPLE_AppDefined, "Write failed, disk full?"); break; } osBuf = ""; } } } else { for ( int iPixel = 0; iPixel < nXSize; iPixel++ ) { CPLsnprintf(szHeader, sizeof(szHeader), szFormatFloat, padfScanline[iPixel]); // Make sure that as least one value has a decimal point (#6060) if( !bHasOutputDecimalDot ) { if( strchr(szHeader, '.') || strchr(szHeader, 'e') || strchr(szHeader, 'E') ) { bHasOutputDecimalDot = true; } else if( !CPLIsInf(padfScanline[iPixel]) && !CPLIsNan(padfScanline[iPixel]) ) { strcat(szHeader, ".0"); bHasOutputDecimalDot = true; } } osBuf += szHeader; if( (iPixel & 1023) == 0 || iPixel == nXSize - 1 ) { if ( VSIFWriteL(osBuf, static_cast<int>(osBuf.size()), 1, fpImage) != 1 ) { eErr = CE_Failure; CPLError(CE_Failure, CPLE_AppDefined, "Write failed, disk full?"); break; } osBuf = ""; } } } if( VSIFWriteL("\n", 1, 1, fpImage) != 1 ) eErr = CE_Failure; if( eErr == CE_None && !pfnProgress((iLine + 1) / static_cast<double>(nYSize), nullptr, pProgressData) ) { eErr = CE_Failure; CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated CreateCopy()"); } } CPLFree(panScanline); CPLFree(padfScanline); if( VSIFCloseL(fpImage) != 0 ) eErr = CE_Failure; if( eErr != CE_None ) return nullptr; // Try to write projection file. const char *pszOriginalProjection = poSrcDS->GetProjectionRef(); if( !EQUAL(pszOriginalProjection, "") ) { char *pszDirname = CPLStrdup(CPLGetPath(pszFilename)); char *pszBasename = CPLStrdup(CPLGetBasename(pszFilename)); char *pszPrjFilename = CPLStrdup(CPLFormFilename(pszDirname, pszBasename, "prj")); VSILFILE *fp = VSIFOpenL(pszPrjFilename, "wt"); if (fp != nullptr) { OGRSpatialReference oSRS; oSRS.importFromWkt(pszOriginalProjection); oSRS.morphToESRI(); char *pszESRIProjection = nullptr; oSRS.exportToWkt(&pszESRIProjection); CPL_IGNORE_RET_VAL(VSIFWriteL(pszESRIProjection, 1, strlen(pszESRIProjection), fp)); CPL_IGNORE_RET_VAL(VSIFCloseL(fp)); CPLFree(pszESRIProjection); } else { CPLError(CE_Failure, CPLE_FileIO, "Unable to create file %s.", pszPrjFilename); } CPLFree(pszDirname); CPLFree(pszBasename); CPLFree(pszPrjFilename); } // Re-open dataset, and copy any auxiliary pam information. // If writing to stdout, we can't reopen it, so return // a fake dataset to make the caller happy. CPLPushErrorHandler(CPLQuietErrorHandler); GDALPamDataset *poDS = reinterpret_cast<GDALPamDataset *>(GDALOpen(pszFilename, GA_ReadOnly)); CPLPopErrorHandler(); if (poDS) { poDS->CloneInfo(poSrcDS, GCIF_PAM_DEFAULT); return poDS; } CPLErrorReset(); AAIGDataset *poAAIG_DS = new AAIGDataset(); poAAIG_DS->nRasterXSize = nXSize; poAAIG_DS->nRasterYSize = nYSize; poAAIG_DS->nBands = 1; poAAIG_DS->SetBand(1, new AAIGRasterBand(poAAIG_DS, 1)); return poAAIG_DS; }
CPLErr JP2LuraRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void * pImage) { JP2LuraDataset *poGDS = reinterpret_cast<JP2LuraDataset *>(poDS); #ifdef DEBUG_VERBOSE CPLDebug("JP2Lura", "IReadBlock(nBand=%d,nLevel=%d %d,%d)", nBand, poGDS->iLevel, nBlockXOff, nBlockYOff); #endif int nXOff = nBlockXOff * nBlockXSize; int nYOff = nBlockYOff * nBlockYSize; int nXSize = nBlockXSize; int nYSize = nBlockYSize; if( nXOff + nXSize > nRasterXSize ) nXSize = nRasterXSize - nXOff; if( nYOff + nYSize > nRasterYSize ) nYSize = nRasterYSize - nYOff; GDALRasterIOExtraArg sExtraArgs; INIT_RASTERIO_EXTRA_ARG(sExtraArgs); const int nDTSizeBytes = GDALGetDataTypeSizeBytes(eDataType); CPLErr eErr = IRasterIO(GF_Read, nXOff, nYOff, nXSize, nYSize, pImage, nXSize, nYSize, eDataType, nDTSizeBytes, nDTSizeBytes * nXSize, &sExtraArgs); // Unpack previously packed buffer if needed if( eErr == CE_None && nXSize < nBlockXSize ) { GByte* pabyData = reinterpret_cast<GByte*>(pImage); for( int j = nYSize - 1; j >= 0; --j ) { memmove( pabyData + j * nBlockXSize * nDTSizeBytes, pabyData + j * nXSize * nDTSizeBytes, nXSize * nDTSizeBytes ); } } // Caching other bands while we have the cached buffer valid for( int iBand = 1;eErr == CE_None && iBand <= poGDS->nBands; iBand++ ) { if( iBand == nBand ) continue; JP2LuraRasterBand* poOtherBand = reinterpret_cast<JP2LuraRasterBand*>(poGDS->GetRasterBand(iBand)); GDALRasterBlock* poBlock = poOtherBand-> TryGetLockedBlockRef(nBlockXOff,nBlockYOff); if (poBlock != nullptr) { poBlock->DropLock(); continue; } poBlock = poOtherBand-> GetLockedBlockRef(nBlockXOff,nBlockYOff, TRUE); if (poBlock == nullptr) { continue; } GByte* pabyData = reinterpret_cast<GByte*>(poBlock->GetDataRef()); eErr = poOtherBand->IRasterIO(GF_Read, nXOff, nYOff, nXSize, nYSize, pabyData, nXSize, nYSize, eDataType, nDTSizeBytes, nDTSizeBytes * nXSize, &sExtraArgs); // Unpack previously packed buffer if needed if( eErr == CE_None && nXSize < nBlockXSize ) { for( int j = nYSize - 1; j >= 0; --j ) { memmove( pabyData + j * nBlockXSize * nDTSizeBytes, pabyData + j * nXSize * nDTSizeBytes, nXSize * nDTSizeBytes ); } } poBlock->DropLock(); } return eErr; }