Skip to content

Commit

Permalink
raster creation moved from QgsGdalProvider::create() to GDAL provider…
Browse files Browse the repository at this point in the history
… extern C function
  • Loading branch information
blazek committed Dec 20, 2012
1 parent c2aca4f commit d58d347
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 60 deletions.
4 changes: 3 additions & 1 deletion python/core/raster/qgsrasterdataprovider.sip
Expand Up @@ -249,7 +249,9 @@ class QgsRasterDataProvider : QgsDataProvider, QgsRasterInterface

/** Creates a new dataset with mDataSourceURI
@return true in case of success*/
virtual bool create( const QString& format, int nBands,
static QgsRasterDataProvider* create( const QString &providerKey,
const QString &uri,
const QString& format, int nBands,
QGis::DataType type,
int width, int height, double* geoTransform,
const QgsCoordinateReferenceSystem& crs,
Expand Down
27 changes: 27 additions & 0 deletions src/core/raster/qgsrasterdataprovider.cpp
Expand Up @@ -15,6 +15,7 @@
* *
***************************************************************************/

#include "qgsproviderregistry.h"
#include "qgsrasterdataprovider.h"
#include "qgsrasterprojector.h"
#include "qgslogger.h"
Expand Down Expand Up @@ -475,4 +476,30 @@ void QgsRasterDataProvider::setUserNoDataValue( int bandNo, QList<QgsRasterBlock
}
}

typedef QgsRasterDataProvider * createFunction_t( const QString&,
const QString&, int,
QGis::DataType,
int, int, double*,
const QgsCoordinateReferenceSystem&,
QStringList );

QgsRasterDataProvider* QgsRasterDataProvider::create( const QString &providerKey,
const QString &uri,
const QString& format, int nBands,
QGis::DataType type,
int width, int height, double* geoTransform,
const QgsCoordinateReferenceSystem& crs,
QStringList createOptions )
{
createFunction_t *createFn = ( createFunction_t* ) cast_to_fptr( QgsProviderRegistry::instance()->function( providerKey, "create" ) );
if ( !createFn )
{
QgsDebugMsg( "Cannot resolve 'create' function in " + providerKey + " provider" );
// TODO: it would be good to return invalid QgsRasterDataProvider
// with QgsError set, but QgsRasterDataProvider has pure virtual methods
return 0;
}
return createFn( uri, format, nBands, type, width, height, geoTransform, crs, createOptions );
}

// ENDS
11 changes: 11 additions & 0 deletions src/core/raster/qgsrasterdataprovider.h
Expand Up @@ -403,6 +403,7 @@ class CORE_EXPORT QgsRasterDataProvider : public QgsDataProvider, public QgsRast

/** Creates a new dataset with mDataSourceURI
@return true in case of success*/
#if 0
virtual bool create( const QString& format, int nBands,
QGis::DataType type,
int width, int height, double* geoTransform,
Expand All @@ -419,6 +420,16 @@ class CORE_EXPORT QgsRasterDataProvider : public QgsDataProvider, public QgsRast
Q_UNUSED( createOptions );
return false;
}
#endif

static QgsRasterDataProvider* create( const QString &providerKey,
const QString &uri,
const QString& format, int nBands,
QGis::DataType type,
int width, int height, double* geoTransform,
const QgsCoordinateReferenceSystem& crs,
QStringList createOptions = QStringList() );


/** Set no data value on created dataset
* @param bandNo band number
Expand Down
58 changes: 43 additions & 15 deletions src/core/raster/qgsrasterfilewriter.cpp
Expand Up @@ -873,11 +873,11 @@ QgsRasterDataProvider* QgsRasterFileWriter::createPartProvider( const QgsRectang

QString outputFile = outputUrl + "/" + partFileName( fileIndex );
//QgsRasterDataProvider* destProvider = QgsRasterLayer::loadProvider( mOutputProviderKey, outputFile );
QgsRasterDataProvider* destProvider = ( QgsRasterDataProvider* ) QgsProviderRegistry::instance()->provider( mOutputProviderKey, outputFile );
if ( !destProvider )
{
return 0;
}
//QgsRasterDataProvider* destProvider = ( QgsRasterDataProvider* ) QgsProviderRegistry::instance()->provider( mOutputProviderKey, outputFile );
//if ( !destProvider )
//{
// return 0;
//}

//geotransform
double geoTransform[6];
Expand All @@ -889,12 +889,29 @@ QgsRasterDataProvider* QgsRasterFileWriter::createPartProvider( const QgsRectang
geoTransform[5] = -mup;

// perhaps we need a separate createOptions for tiles ?
if ( !destProvider->create( mOutputFormat, nBands, type, iterCols, iterRows, geoTransform,
crs ) )
/*
if ( !destProvider->create( mOutputFormat, nBands, type, iterCols, iterRows, geoTransform,
crs ) )
{
delete destProvider;
return 0;
}
*/

QgsRasterDataProvider* destProvider = QgsRasterDataProvider::create( mOutputProviderKey, mOutputUrl, mOutputFormat, nBands, type, iterCols, iterRows, geoTransform, crs, mCreateOptions ) ;

if ( !destProvider )
{
return 0;
}

// TODO: return provider and report error
if ( !destProvider->isValid() )
{
delete destProvider;
return 0;
}

return destProvider;
}

Expand All @@ -909,24 +926,35 @@ QgsRasterDataProvider* QgsRasterFileWriter::initOutput( int nCols, int nRows, co
}
else
{
// TODO enable "use existing", has no effect for now, because using Create() in gdal provider
// should this belong in provider? should also test that source provider is gdal
// if ( mBuildPyramidsFlag == -4 && mOutputProviderKey == "gdal" && mOutputFormat.toLower() == "gtiff" )
// mCreateOptions << "COPY_SRC_OVERVIEWS=YES";

//QgsRasterDataProvider* destProvider = QgsRasterLayer::loadProvider( mOutputProviderKey, mOutputUrl );
QgsRasterDataProvider* destProvider = ( QgsRasterDataProvider* ) QgsProviderRegistry::instance()->provider( mOutputProviderKey, mOutputUrl );
//QgsRasterDataProvider* destProvider = ( QgsRasterDataProvider* ) QgsProviderRegistry::instance()->provider( mOutputProviderKey, mOutputUrl );
QgsRasterDataProvider* destProvider = QgsRasterDataProvider::create( mOutputProviderKey, mOutputUrl, mOutputFormat, nBands, type, nCols, nRows, geoTransform, crs, mCreateOptions ) ;

if ( !destProvider )
{
return 0;
}

// TODO enable "use existing", has no effect for now, because using Create() in gdal provider
// should this belong in provider? should also test that source provider is gdal
// if ( mBuildPyramidsFlag == -4 && mOutputProviderKey == "gdal" && mOutputFormat.toLower() == "gtiff" )
// mCreateOptions << "COPY_SRC_OVERVIEWS=YES";

if ( !destProvider->create( mOutputFormat, nBands, type, nCols, nRows, geoTransform,
crs, mCreateOptions ) )
// TODO: return provider and report error
if ( !destProvider->isValid() )
{
delete destProvider;
return 0;
}

/*
if ( !destProvider->create( mOutputFormat, nBands, type, nCols, nRows, geoTransform,
crs, mCreateOptions ) )
{
delete destProvider;
return 0;
}
*/
return destProvider;
}
}
Expand Down
64 changes: 29 additions & 35 deletions src/providers/gdal/qgsgdalprovider.cpp
Expand Up @@ -92,10 +92,17 @@ int CPL_STDCALL progressCallback( double dfComplete,
return true;
}

QgsGdalProvider::QgsGdalProvider( QString const & uri, QgsError error )
: QgsRasterDataProvider( uri )
, mValid( false )
{
setError( error );
}

QgsGdalProvider::QgsGdalProvider( QString const & uri )
QgsGdalProvider::QgsGdalProvider( QString const & uri, bool update )
: QgsRasterDataProvider( uri )
, QgsGdalProviderBase()
, mUpdate( update )
, mValid( true )
{
QgsDebugMsg( "QgsGdalProvider: constructing with uri '" + uri + "'." );
Expand Down Expand Up @@ -126,28 +133,11 @@ QgsGdalProvider::QgsGdalProvider( QString const & uri )
setDataSourceUri( vsiPrefix + uri );
QgsDebugMsg( QString( "Trying %1 syntax, uri= %2" ).arg( vsiPrefix ).arg( dataSourceUri() ) );
}
else
{
// TODO: this constructor is also called for new rasters, in that case GDAL prints error:
// "ERROR 4: `pok.tif' does not exist in the file system, and is not recognised as a supported dataset name."
// To avoid this message, we test first if the file exists at all.
// This should be done better adding static create() method or something like that
// TODO: Cannot test for file existence, for example NetCDF with sublayers
// is using URI: NETCDF:"/path/to/file.cdf":layer1
/*
if ( !QFile::exists( uri ) )
{
QString msg = QString( "File does not exist: %1" ).arg( dataSourceUri() );
appendError( ERR( msg ) );
return;
}
*/
}

QString gdalUri = dataSourceUri();

CPLErrorReset();
mGdalBaseDataset = GDALOpen( TO8F( gdalUri ), GA_ReadOnly );
mGdalBaseDataset = GDALOpen( TO8F( gdalUri ), mUpdate ? GA_Update : GA_ReadOnly );

if ( !mGdalBaseDataset )
{
Expand Down Expand Up @@ -1481,7 +1471,7 @@ QString QgsGdalProvider::buildPyramids( QList<QgsRasterPyramid> const & theRaste
//something bad happenend
//QString myString = QString (CPLGetLastError());
GDALClose( mGdalBaseDataset );
mGdalBaseDataset = GDALOpen( TO8F( dataSourceUri() ), GA_ReadOnly );
mGdalBaseDataset = GDALOpen( TO8F( dataSourceUri() ), mUpdate ? GA_Update : GA_ReadOnly );
//Since we are not a virtual warped dataset, mGdalDataSet and mGdalBaseDataset are supposed to be the same
mGdalDataset = mGdalBaseDataset;

Expand Down Expand Up @@ -1523,7 +1513,7 @@ QString QgsGdalProvider::buildPyramids( QList<QgsRasterPyramid> const & theRaste
QgsDebugMsg( "Reopening dataset ..." );
//close the gdal dataset and reopen it in read only mode
GDALClose( mGdalBaseDataset );
mGdalBaseDataset = GDALOpen( TO8F( dataSourceUri() ), GA_ReadOnly );
mGdalBaseDataset = GDALOpen( TO8F( dataSourceUri() ), mUpdate ? GA_Update : GA_ReadOnly );
//Since we are not a virtual warped dataset, mGdalDataSet and mGdalBaseDataset are supposed to be the same
mGdalDataset = mGdalBaseDataset;
}
Expand Down Expand Up @@ -2401,17 +2391,27 @@ char** papszFromStringList( const QStringList& list )
return papszRetList;
}

#if 0
bool QgsGdalProvider::create( const QString& format, int nBands,
QGis::DataType type,
int width, int height, double* geoTransform,
const QgsCoordinateReferenceSystem& crs,
QStringList createOptions )
#endif
QGISEXTERN QgsGdalProvider * create(
const QString &uri,
const QString& format, int nBands,
QGis::DataType type,
int width, int height, double* geoTransform,
const QgsCoordinateReferenceSystem& crs,
QStringList createOptions )
{
//get driver
GDALDriverH driver = GDALGetDriverByName( format.toLocal8Bit().data() );
if ( !driver )
{
return false;
QgsError error( "Cannot load GDAL driver " + format, "GDAL provider" );
return new QgsGdalProvider( uri, error );
}

QString tmpStr = "create options:";
Expand All @@ -2420,27 +2420,21 @@ bool QgsGdalProvider::create( const QString& format, int nBands,
QgsDebugMsg( tmpStr );

//create dataset
CPLErrorReset();
char **papszOptions = papszFromStringList( createOptions );
GDALDatasetH dataset = GDALCreate( driver, dataSourceUri().toLocal8Bit().data(), width, height, nBands, ( GDALDataType )type, papszOptions );
GDALDatasetH dataset = GDALCreate( driver, uri.toLocal8Bit().data(), width, height, nBands, ( GDALDataType )type, papszOptions );
CSLDestroy( papszOptions );
if ( dataset == NULL )
{
return false;
QgsError error( QString( "Cannot create new dataset %1:\n%2" ).arg( uri ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) ), "GDAL provider" );
return new QgsGdalProvider( uri, error );
}

mGeoTransform[0] = geoTransform[0];
mGeoTransform[1] = geoTransform[1];
mGeoTransform[2] = geoTransform[2];
mGeoTransform[3] = geoTransform[3];
mGeoTransform[4] = geoTransform[4];
mGeoTransform[5] = geoTransform[5];

GDALSetGeoTransform( dataset, mGeoTransform );
GDALSetGeoTransform( dataset, geoTransform );
GDALSetProjection( dataset, crs.toWkt().toLocal8Bit().data() );
GDALClose( dataset );

mGdalBaseDataset = dataset;
initBaseDataset();
return mValid;
return new QgsGdalProvider( uri, true );
}

bool QgsGdalProvider::write( void* data, int band, int width, int height, int xOffset, int yOffset )
Expand Down
10 changes: 9 additions & 1 deletion src/providers/gdal/qgsgdalprovider.h
Expand Up @@ -65,7 +65,10 @@ class QgsGdalProvider : public QgsRasterDataProvider, QgsGdalProviderBase
* otherwise we contact the host directly.
*
*/
QgsGdalProvider( QString const & uri = 0 );
QgsGdalProvider( QString const & uri = 0, bool update = false );

/** Create invalid provider with error */
QgsGdalProvider( QString const & uri, QgsError error );

//! Destructor
~QgsGdalProvider();
Expand Down Expand Up @@ -234,11 +237,13 @@ class QgsGdalProvider : public QgsRasterDataProvider, QgsGdalProviderBase

/** Creates a new dataset with mDataSourceURI
@return true in case of success*/
/*
bool create( const QString& format, int nBands,
QGis::DataType type,
int width, int height, double* geoTransform,
const QgsCoordinateReferenceSystem& crs,
QStringList createOptions = QStringList() );
*/

/**Writes into the provider datasource*/
bool write( void* data, int band, int width, int height, int xOffset, int yOffset );
Expand All @@ -257,6 +262,9 @@ class QgsGdalProvider : public QgsRasterDataProvider, QgsGdalProviderBase
void statusChanged( QString );

private:
// update mode
bool mUpdate;

// initialize CRS from wkt
bool crsFromWkt( const char *wkt );

Expand Down
12 changes: 4 additions & 8 deletions src/providers/grass/qgsgrassgislib.cpp
Expand Up @@ -573,12 +573,6 @@ int QgsGrassGisLib::G_open_raster_new( const char *name, RASTER_MAP_TYPE wr_type
raster.name = name;
//raster.writer = new QgsRasterFileWriter( dataSource );

raster.provider = ( QgsRasterDataProvider* )QgsProviderRegistry::instance()->provider( providerKey, dataSource );
if ( !raster.provider )
{
fatal( "Cannot load raster provider with data source: " + dataSource );
}

QString outputFormat = "GTiff";
int nBands = 1;
QGis::DataType type = qgisRasterType( wr_type );
Expand All @@ -591,11 +585,13 @@ int QgsGrassGisLib::G_open_raster_new( const char *name, RASTER_MAP_TYPE wr_type
geoTransform[4] = 0.0;
geoTransform[5] = -1. * mExtent.height() / mRows;

if ( !raster.provider->create( outputFormat, nBands, type, mColumns, mRows, geoTransform, mCrs ) )
raster.provider = QgsRasterDataProvider::create( providerKey, dataSource, outputFormat, nBands, type, mColumns, mRows, geoTransform, mCrs );
if ( !raster.provider || !raster.provider->isValid() )
{
delete raster.provider;
if ( raster.provider ) delete raster.provider;
fatal( "Cannot create output data source: " + dataSource );
}

raster.band = 1;
double noDataValue = std::numeric_limits<double>::quiet_NaN();
switch ( wr_type )
Expand Down

0 comments on commit d58d347

Please sign in to comment.