CPLErr VRTWarpedRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage ) { CPLErr eErr; VRTWarpedDataset *poWDS = (VRTWarpedDataset *) poDS; GDALRasterBlock *poBlock; poBlock = GetLockedBlockRef( nBlockXOff, nBlockYOff, TRUE ); eErr = poWDS->ProcessBlock( nBlockXOff, nBlockYOff ); if( eErr == CE_None && pImage != poBlock->GetDataRef() ) { int nDataBytes; nDataBytes = (GDALGetDataTypeSize(poBlock->GetDataType()) / 8) * poBlock->GetXSize() * poBlock->GetYSize(); memcpy( pImage, poBlock->GetDataRef(), nDataBytes ); } poBlock->DropLock(); return eErr; }
CPLErr VRTWarpedDataset::ProcessBlock( int iBlockX, int iBlockY ) { if( poWarper == NULL ) return CE_Failure; const GDALWarpOptions *psWO = poWarper->GetOptions(); /* -------------------------------------------------------------------- */ /* Allocate block of memory large enough to hold all the bands */ /* for this block. */ /* -------------------------------------------------------------------- */ int iBand; GByte *pabyDstBuffer; int nDstBufferSize; int nWordSize = (GDALGetDataTypeSize(psWO->eWorkingDataType) / 8); // FIXME? : risk of overflow in multiplication if nBlockXSize or nBlockYSize are very large nDstBufferSize = nBlockXSize * nBlockYSize * psWO->nBandCount * nWordSize; pabyDstBuffer = (GByte *) VSIMalloc(nDstBufferSize); if( pabyDstBuffer == NULL ) { CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory allocating %d byte buffer in VRTWarpedDataset::ProcessBlock()", nDstBufferSize ); return CE_Failure; } memset( pabyDstBuffer, 0, nDstBufferSize ); /* -------------------------------------------------------------------- */ /* Process INIT_DEST option to initialize the buffer prior to */ /* warping into it. */ /* NOTE:The following code is 99% similar in gdalwarpoperation.cpp and */ /* vrtwarped.cpp. Be careful to keep it in sync ! */ /* -------------------------------------------------------------------- */ const char *pszInitDest = CSLFetchNameValue( psWO->papszWarpOptions, "INIT_DEST" ); if( pszInitDest != NULL && !EQUAL(pszInitDest, "") ) { char **papszInitValues = CSLTokenizeStringComplex( pszInitDest, ",", FALSE, FALSE ); int nInitCount = CSLCount(papszInitValues); for( iBand = 0; iBand < psWO->nBandCount; iBand++ ) { double adfInitRealImag[2]; GByte *pBandData; int nBandSize = nBlockXSize * nBlockYSize * nWordSize; const char *pszBandInit = papszInitValues[MIN(iBand,nInitCount-1)]; if( EQUAL(pszBandInit,"NO_DATA") && psWO->padfDstNoDataReal != NULL ) { adfInitRealImag[0] = psWO->padfDstNoDataReal[iBand]; adfInitRealImag[1] = psWO->padfDstNoDataImag[iBand]; } else { CPLStringToComplex( pszBandInit, adfInitRealImag + 0, adfInitRealImag + 1); } pBandData = ((GByte *) pabyDstBuffer) + iBand * nBandSize; if( psWO->eWorkingDataType == GDT_Byte ) memset( pBandData, MAX(0,MIN(255,(int)adfInitRealImag[0])), nBandSize); else if( adfInitRealImag[0] == 0.0 && adfInitRealImag[1] == 0 ) { memset( pBandData, 0, nBandSize ); } else if( adfInitRealImag[1] == 0.0 ) { GDALCopyWords( &adfInitRealImag, GDT_Float64, 0, pBandData,psWO->eWorkingDataType,nWordSize, nBlockXSize * nBlockYSize ); } else { GDALCopyWords( &adfInitRealImag, GDT_CFloat64, 0, pBandData,psWO->eWorkingDataType,nWordSize, nBlockXSize * nBlockYSize ); } } CSLDestroy( papszInitValues ); } /* -------------------------------------------------------------------- */ /* Warp into this buffer. */ /* -------------------------------------------------------------------- */ CPLErr eErr; eErr = poWarper->WarpRegionToBuffer( iBlockX * nBlockXSize, iBlockY * nBlockYSize, nBlockXSize, nBlockYSize, pabyDstBuffer, psWO->eWorkingDataType ); if( eErr != CE_None ) { VSIFree( pabyDstBuffer ); return eErr; } /* -------------------------------------------------------------------- */ /* Copy out into cache blocks for each band. */ /* -------------------------------------------------------------------- */ for( iBand = 0; iBand < psWO->nBandCount; iBand++ ) { GDALRasterBand *poBand; GDALRasterBlock *poBlock; poBand = GetRasterBand(iBand+1); poBlock = poBand->GetLockedBlockRef( iBlockX, iBlockY, TRUE ); CPLAssert( poBlock != NULL && poBlock->GetDataRef() != NULL ); GDALCopyWords( pabyDstBuffer + iBand*nBlockXSize*nBlockYSize*nWordSize, psWO->eWorkingDataType, nWordSize, poBlock->GetDataRef(), poBlock->GetDataType(), GDALGetDataTypeSize(poBlock->GetDataType())/8, nBlockXSize * nBlockYSize ); poBlock->DropLock(); } VSIFree( pabyDstBuffer ); return CE_None; }