EVOLUTION-MANAGER
Edit File: deriveddataset.cpp
/****************************************************************************** * * Project: GDAL * Purpose: Implementation of derived subdatasets * Author: Julien Michel <julien dot michel at cnes dot fr> * ****************************************************************************** * Copyright (c) 2016 Julien Michel <julien dot michel at cnes dot fr> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ #include "../vrt/vrtdataset.h" #include "gdal_pam.h" #include "gdal_proxy.h" #include "derivedlist.h" CPL_CVSID("$Id: deriveddataset.cpp 35885 2016-10-24 06:23:09Z goatbar $"); class DerivedDataset : public VRTDataset { public: DerivedDataset( int nXSize, int nYSize ); ~DerivedDataset() {}; static int Identify( GDALOpenInfo * ); static GDALDataset *Open( GDALOpenInfo * ); }; DerivedDataset::DerivedDataset(int nXSize, int nYSize) : VRTDataset(nXSize, nYSize) { poDriver = NULL; SetWritable(FALSE); } int DerivedDataset::Identify(GDALOpenInfo * poOpenInfo) { /* Try to open original dataset */ CPLString filename(poOpenInfo->pszFilename); /* DERIVED_SUBDATASET should be first domain */ const size_t dsds_pos = filename.find("DERIVED_SUBDATASET:"); if (dsds_pos != 0) { /* Unable to Open in this case */ return FALSE; } return TRUE; } GDALDataset * DerivedDataset::Open( GDALOpenInfo * poOpenInfo ) { /* Try to open original dataset */ CPLString filename(poOpenInfo->pszFilename); /* DERIVED_SUBDATASET should be first domain */ const size_t dsds_pos = filename.find("DERIVED_SUBDATASET:"); const size_t nPrefixLen = strlen("DERIVED_SUBDATASET:"); if (dsds_pos != 0) { /* Unable to Open in this case */ return NULL; } /* Next, we need to now which derived dataset to compute */ const size_t alg_pos = filename.find(":",nPrefixLen+1); if (alg_pos == std::string::npos) { /* Unable to Open if we do not find the name of the derived dataset */ return NULL; } CPLString odDerivedName = filename.substr(nPrefixLen,alg_pos-nPrefixLen); CPLDebug("DerivedDataset::Open","Derived dataset requested: %s",odDerivedName.c_str()); CPLString pixelFunctionName = ""; bool datasetFound = false; unsigned int nbSupportedDerivedDS(0); GDALDataType type = GDT_Float64; const DerivedDatasetDescription * poDDSDesc = GDALGetDerivedDatasetDescriptions(&nbSupportedDerivedDS); for(unsigned int derivedId = 0; derivedId<nbSupportedDerivedDS;++derivedId) { if(odDerivedName == poDDSDesc[derivedId].pszDatasetName) { datasetFound = true; pixelFunctionName = poDDSDesc[derivedId].pszPixelFunction; type = GDALGetDataTypeByName(poDDSDesc[derivedId].pszOutputPixelType); } } if(!datasetFound) { return NULL; } CPLString odFilename = filename.substr(alg_pos+1,filename.size() - alg_pos); GDALDataset * poTmpDS = (GDALDataset*)GDALOpen(odFilename, GA_ReadOnly); if( poTmpDS == NULL ) return NULL; int nbBands = poTmpDS->GetRasterCount(); if(nbBands == 0) { GDALClose(poTmpDS); return NULL; } int nRows = poTmpDS->GetRasterYSize(); int nCols = poTmpDS->GetRasterXSize(); DerivedDataset * poDS = new DerivedDataset(nCols,nRows); // Transfer metadata poDS->SetMetadata(poTmpDS->GetMetadata()); // Transfer projection poDS->SetProjection(poTmpDS->GetProjectionRef()); // Transfer geotransform double padfTransform[6]; CPLErr transformOk = poTmpDS->GetGeoTransform(padfTransform); if(transformOk == CE_None) { poDS->SetGeoTransform(padfTransform); } // Transfer GCPs const char * gcpProjection = poTmpDS->GetGCPProjection(); int nbGcps = poTmpDS->GetGCPCount(); poDS->SetGCPs(nbGcps,poTmpDS->GetGCPs(),gcpProjection); // Map bands for(int nBand = 1; nBand <= nbBands; ++nBand) { VRTDerivedRasterBand *poBand = new VRTDerivedRasterBand(poDS,nBand,type,nCols,nRows); poDS->SetBand(nBand,poBand); poBand->SetPixelFunctionName(pixelFunctionName); poBand->SetSourceTransferType(poTmpDS->GetRasterBand(nBand)->GetRasterDataType()); GDALProxyPoolDataset* proxyDS = new GDALProxyPoolDataset( odFilename, poDS->nRasterXSize, poDS->nRasterYSize, GA_ReadOnly, TRUE); for(int j=0;j<nbBands;++j) { int blockXSize, blockYSize; poTmpDS->GetRasterBand(nBand)->GetBlockSize(&blockXSize,&blockYSize); proxyDS->AddSrcBandDescription(poTmpDS->GetRasterBand(nBand)->GetRasterDataType(), blockXSize, blockYSize); } poBand->AddComplexSource(proxyDS->GetRasterBand(nBand),0,0,nCols,nRows,0,0,nCols,nRows); proxyDS->Dereference(); } GDALClose(poTmpDS); // If dataset is a real file, initialize overview manager VSIStatBufL sStat; if( VSIStatL( odFilename, &sStat ) == 0 ) { CPLString path = CPLGetPath(odFilename); CPLString ovrFileName = "DERIVED_DATASET_"+odDerivedName+"_"+CPLGetFilename(odFilename); CPLString ovrFilePath = CPLFormFilename(path,ovrFileName,NULL); poDS->oOvManager.Initialize( poDS, ovrFilePath ); } return poDS; } void GDALRegister_Derived() { if( GDALGetDriverByName( "DERIVED" ) != NULL ) return; GDALDriver *poDriver = new GDALDriver(); poDriver->SetDescription( "DERIVED" ); #ifdef GDAL_DCAP_RASTER poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" ); #endif poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Derived datasets using VRT pixel functions" ); poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_derived.html" ); poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "NO" ); poDriver->pfnOpen = DerivedDataset::Open; poDriver->pfnIdentify = DerivedDataset::Identify; GetGDALDriverManager()->RegisterDriver( poDriver ); }