Skip to content

Commit d58d347

Browse files
committedDec 20, 2012
raster creation moved from QgsGdalProvider::create() to GDAL provider extern C function
1 parent c2aca4f commit d58d347

File tree

7 files changed

+126
-60
lines changed

7 files changed

+126
-60
lines changed
 

‎python/core/raster/qgsrasterdataprovider.sip

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,9 @@ class QgsRasterDataProvider : QgsDataProvider, QgsRasterInterface
249249

250250
/** Creates a new dataset with mDataSourceURI
251251
@return true in case of success*/
252-
virtual bool create( const QString& format, int nBands,
252+
static QgsRasterDataProvider* create( const QString &providerKey,
253+
const QString &uri,
254+
const QString& format, int nBands,
253255
QGis::DataType type,
254256
int width, int height, double* geoTransform,
255257
const QgsCoordinateReferenceSystem& crs,

‎src/core/raster/qgsrasterdataprovider.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
* *
1616
***************************************************************************/
1717

18+
#include "qgsproviderregistry.h"
1819
#include "qgsrasterdataprovider.h"
1920
#include "qgsrasterprojector.h"
2021
#include "qgslogger.h"
@@ -475,4 +476,30 @@ void QgsRasterDataProvider::setUserNoDataValue( int bandNo, QList<QgsRasterBlock
475476
}
476477
}
477478

479+
typedef QgsRasterDataProvider * createFunction_t( const QString&,
480+
const QString&, int,
481+
QGis::DataType,
482+
int, int, double*,
483+
const QgsCoordinateReferenceSystem&,
484+
QStringList );
485+
486+
QgsRasterDataProvider* QgsRasterDataProvider::create( const QString &providerKey,
487+
const QString &uri,
488+
const QString& format, int nBands,
489+
QGis::DataType type,
490+
int width, int height, double* geoTransform,
491+
const QgsCoordinateReferenceSystem& crs,
492+
QStringList createOptions )
493+
{
494+
createFunction_t *createFn = ( createFunction_t* ) cast_to_fptr( QgsProviderRegistry::instance()->function( providerKey, "create" ) );
495+
if ( !createFn )
496+
{
497+
QgsDebugMsg( "Cannot resolve 'create' function in " + providerKey + " provider" );
498+
// TODO: it would be good to return invalid QgsRasterDataProvider
499+
// with QgsError set, but QgsRasterDataProvider has pure virtual methods
500+
return 0;
501+
}
502+
return createFn( uri, format, nBands, type, width, height, geoTransform, crs, createOptions );
503+
}
504+
478505
// ENDS

‎src/core/raster/qgsrasterdataprovider.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,7 @@ class CORE_EXPORT QgsRasterDataProvider : public QgsDataProvider, public QgsRast
403403

404404
/** Creates a new dataset with mDataSourceURI
405405
@return true in case of success*/
406+
#if 0
406407
virtual bool create( const QString& format, int nBands,
407408
QGis::DataType type,
408409
int width, int height, double* geoTransform,
@@ -419,6 +420,16 @@ class CORE_EXPORT QgsRasterDataProvider : public QgsDataProvider, public QgsRast
419420
Q_UNUSED( createOptions );
420421
return false;
421422
}
423+
#endif
424+
425+
static QgsRasterDataProvider* create( const QString &providerKey,
426+
const QString &uri,
427+
const QString& format, int nBands,
428+
QGis::DataType type,
429+
int width, int height, double* geoTransform,
430+
const QgsCoordinateReferenceSystem& crs,
431+
QStringList createOptions = QStringList() );
432+
422433

423434
/** Set no data value on created dataset
424435
* @param bandNo band number

‎src/core/raster/qgsrasterfilewriter.cpp

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -873,11 +873,11 @@ QgsRasterDataProvider* QgsRasterFileWriter::createPartProvider( const QgsRectang
873873

874874
QString outputFile = outputUrl + "/" + partFileName( fileIndex );
875875
//QgsRasterDataProvider* destProvider = QgsRasterLayer::loadProvider( mOutputProviderKey, outputFile );
876-
QgsRasterDataProvider* destProvider = ( QgsRasterDataProvider* ) QgsProviderRegistry::instance()->provider( mOutputProviderKey, outputFile );
877-
if ( !destProvider )
878-
{
879-
return 0;
880-
}
876+
//QgsRasterDataProvider* destProvider = ( QgsRasterDataProvider* ) QgsProviderRegistry::instance()->provider( mOutputProviderKey, outputFile );
877+
//if ( !destProvider )
878+
//{
879+
// return 0;
880+
//}
881881

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

891891
// perhaps we need a separate createOptions for tiles ?
892-
if ( !destProvider->create( mOutputFormat, nBands, type, iterCols, iterRows, geoTransform,
893-
crs ) )
892+
/*
893+
if ( !destProvider->create( mOutputFormat, nBands, type, iterCols, iterRows, geoTransform,
894+
crs ) )
895+
{
896+
delete destProvider;
897+
return 0;
898+
}
899+
*/
900+
901+
QgsRasterDataProvider* destProvider = QgsRasterDataProvider::create( mOutputProviderKey, mOutputUrl, mOutputFormat, nBands, type, iterCols, iterRows, geoTransform, crs, mCreateOptions ) ;
902+
903+
if ( !destProvider )
904+
{
905+
return 0;
906+
}
907+
908+
// TODO: return provider and report error
909+
if ( !destProvider->isValid() )
894910
{
895911
delete destProvider;
896912
return 0;
897913
}
914+
898915
return destProvider;
899916
}
900917

@@ -909,24 +926,35 @@ QgsRasterDataProvider* QgsRasterFileWriter::initOutput( int nCols, int nRows, co
909926
}
910927
else
911928
{
929+
// TODO enable "use existing", has no effect for now, because using Create() in gdal provider
930+
// should this belong in provider? should also test that source provider is gdal
931+
// if ( mBuildPyramidsFlag == -4 && mOutputProviderKey == "gdal" && mOutputFormat.toLower() == "gtiff" )
932+
// mCreateOptions << "COPY_SRC_OVERVIEWS=YES";
933+
912934
//QgsRasterDataProvider* destProvider = QgsRasterLayer::loadProvider( mOutputProviderKey, mOutputUrl );
913-
QgsRasterDataProvider* destProvider = ( QgsRasterDataProvider* ) QgsProviderRegistry::instance()->provider( mOutputProviderKey, mOutputUrl );
935+
//QgsRasterDataProvider* destProvider = ( QgsRasterDataProvider* ) QgsProviderRegistry::instance()->provider( mOutputProviderKey, mOutputUrl );
936+
QgsRasterDataProvider* destProvider = QgsRasterDataProvider::create( mOutputProviderKey, mOutputUrl, mOutputFormat, nBands, type, nCols, nRows, geoTransform, crs, mCreateOptions ) ;
937+
914938
if ( !destProvider )
915939
{
916940
return 0;
917941
}
918942

919-
// TODO enable "use existing", has no effect for now, because using Create() in gdal provider
920-
// should this belong in provider? should also test that source provider is gdal
921-
// if ( mBuildPyramidsFlag == -4 && mOutputProviderKey == "gdal" && mOutputFormat.toLower() == "gtiff" )
922-
// mCreateOptions << "COPY_SRC_OVERVIEWS=YES";
923-
924-
if ( !destProvider->create( mOutputFormat, nBands, type, nCols, nRows, geoTransform,
925-
crs, mCreateOptions ) )
943+
// TODO: return provider and report error
944+
if ( !destProvider->isValid() )
926945
{
927946
delete destProvider;
928947
return 0;
929948
}
949+
950+
/*
951+
if ( !destProvider->create( mOutputFormat, nBands, type, nCols, nRows, geoTransform,
952+
crs, mCreateOptions ) )
953+
{
954+
delete destProvider;
955+
return 0;
956+
}
957+
*/
930958
return destProvider;
931959
}
932960
}

‎src/providers/gdal/qgsgdalprovider.cpp

Lines changed: 29 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,17 @@ int CPL_STDCALL progressCallback( double dfComplete,
9292
return true;
9393
}
9494

95+
QgsGdalProvider::QgsGdalProvider( QString const & uri, QgsError error )
96+
: QgsRasterDataProvider( uri )
97+
, mValid( false )
98+
{
99+
setError( error );
100+
}
95101

96-
QgsGdalProvider::QgsGdalProvider( QString const & uri )
102+
QgsGdalProvider::QgsGdalProvider( QString const & uri, bool update )
97103
: QgsRasterDataProvider( uri )
98104
, QgsGdalProviderBase()
105+
, mUpdate( update )
99106
, mValid( true )
100107
{
101108
QgsDebugMsg( "QgsGdalProvider: constructing with uri '" + uri + "'." );
@@ -126,28 +133,11 @@ QgsGdalProvider::QgsGdalProvider( QString const & uri )
126133
setDataSourceUri( vsiPrefix + uri );
127134
QgsDebugMsg( QString( "Trying %1 syntax, uri= %2" ).arg( vsiPrefix ).arg( dataSourceUri() ) );
128135
}
129-
else
130-
{
131-
// TODO: this constructor is also called for new rasters, in that case GDAL prints error:
132-
// "ERROR 4: `pok.tif' does not exist in the file system, and is not recognised as a supported dataset name."
133-
// To avoid this message, we test first if the file exists at all.
134-
// This should be done better adding static create() method or something like that
135-
// TODO: Cannot test for file existence, for example NetCDF with sublayers
136-
// is using URI: NETCDF:"/path/to/file.cdf":layer1
137-
/*
138-
if ( !QFile::exists( uri ) )
139-
{
140-
QString msg = QString( "File does not exist: %1" ).arg( dataSourceUri() );
141-
appendError( ERR( msg ) );
142-
return;
143-
}
144-
*/
145-
}
146136

147137
QString gdalUri = dataSourceUri();
148138

149139
CPLErrorReset();
150-
mGdalBaseDataset = GDALOpen( TO8F( gdalUri ), GA_ReadOnly );
140+
mGdalBaseDataset = GDALOpen( TO8F( gdalUri ), mUpdate ? GA_Update : GA_ReadOnly );
151141

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

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

2394+
#if 0
24042395
bool QgsGdalProvider::create( const QString& format, int nBands,
24052396
QGis::DataType type,
24062397
int width, int height, double* geoTransform,
24072398
const QgsCoordinateReferenceSystem& crs,
24082399
QStringList createOptions )
2400+
#endif
2401+
QGISEXTERN QgsGdalProvider * create(
2402+
const QString &uri,
2403+
const QString& format, int nBands,
2404+
QGis::DataType type,
2405+
int width, int height, double* geoTransform,
2406+
const QgsCoordinateReferenceSystem& crs,
2407+
QStringList createOptions )
24092408
{
24102409
//get driver
24112410
GDALDriverH driver = GDALGetDriverByName( format.toLocal8Bit().data() );
24122411
if ( !driver )
24132412
{
2414-
return false;
2413+
QgsError error( "Cannot load GDAL driver " + format, "GDAL provider" );
2414+
return new QgsGdalProvider( uri, error );
24152415
}
24162416

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

24222422
//create dataset
2423+
CPLErrorReset();
24232424
char **papszOptions = papszFromStringList( createOptions );
2424-
GDALDatasetH dataset = GDALCreate( driver, dataSourceUri().toLocal8Bit().data(), width, height, nBands, ( GDALDataType )type, papszOptions );
2425+
GDALDatasetH dataset = GDALCreate( driver, uri.toLocal8Bit().data(), width, height, nBands, ( GDALDataType )type, papszOptions );
24252426
CSLDestroy( papszOptions );
24262427
if ( dataset == NULL )
24272428
{
2428-
return false;
2429+
QgsError error( QString( "Cannot create new dataset %1:\n%2" ).arg( uri ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) ), "GDAL provider" );
2430+
return new QgsGdalProvider( uri, error );
24292431
}
24302432

2431-
mGeoTransform[0] = geoTransform[0];
2432-
mGeoTransform[1] = geoTransform[1];
2433-
mGeoTransform[2] = geoTransform[2];
2434-
mGeoTransform[3] = geoTransform[3];
2435-
mGeoTransform[4] = geoTransform[4];
2436-
mGeoTransform[5] = geoTransform[5];
2437-
2438-
GDALSetGeoTransform( dataset, mGeoTransform );
2433+
GDALSetGeoTransform( dataset, geoTransform );
24392434
GDALSetProjection( dataset, crs.toWkt().toLocal8Bit().data() );
2435+
GDALClose( dataset );
24402436

2441-
mGdalBaseDataset = dataset;
2442-
initBaseDataset();
2443-
return mValid;
2437+
return new QgsGdalProvider( uri, true );
24442438
}
24452439

24462440
bool QgsGdalProvider::write( void* data, int band, int width, int height, int xOffset, int yOffset )

‎src/providers/gdal/qgsgdalprovider.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,10 @@ class QgsGdalProvider : public QgsRasterDataProvider, QgsGdalProviderBase
6565
* otherwise we contact the host directly.
6666
*
6767
*/
68-
QgsGdalProvider( QString const & uri = 0 );
68+
QgsGdalProvider( QString const & uri = 0, bool update = false );
69+
70+
/** Create invalid provider with error */
71+
QgsGdalProvider( QString const & uri, QgsError error );
6972

7073
//! Destructor
7174
~QgsGdalProvider();
@@ -234,11 +237,13 @@ class QgsGdalProvider : public QgsRasterDataProvider, QgsGdalProviderBase
234237

235238
/** Creates a new dataset with mDataSourceURI
236239
@return true in case of success*/
240+
/*
237241
bool create( const QString& format, int nBands,
238242
QGis::DataType type,
239243
int width, int height, double* geoTransform,
240244
const QgsCoordinateReferenceSystem& crs,
241245
QStringList createOptions = QStringList() );
246+
*/
242247

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

259264
private:
265+
// update mode
266+
bool mUpdate;
267+
260268
// initialize CRS from wkt
261269
bool crsFromWkt( const char *wkt );
262270

‎src/providers/grass/qgsgrassgislib.cpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -573,12 +573,6 @@ int QgsGrassGisLib::G_open_raster_new( const char *name, RASTER_MAP_TYPE wr_type
573573
raster.name = name;
574574
//raster.writer = new QgsRasterFileWriter( dataSource );
575575

576-
raster.provider = ( QgsRasterDataProvider* )QgsProviderRegistry::instance()->provider( providerKey, dataSource );
577-
if ( !raster.provider )
578-
{
579-
fatal( "Cannot load raster provider with data source: " + dataSource );
580-
}
581-
582576
QString outputFormat = "GTiff";
583577
int nBands = 1;
584578
QGis::DataType type = qgisRasterType( wr_type );
@@ -591,11 +585,13 @@ int QgsGrassGisLib::G_open_raster_new( const char *name, RASTER_MAP_TYPE wr_type
591585
geoTransform[4] = 0.0;
592586
geoTransform[5] = -1. * mExtent.height() / mRows;
593587

594-
if ( !raster.provider->create( outputFormat, nBands, type, mColumns, mRows, geoTransform, mCrs ) )
588+
raster.provider = QgsRasterDataProvider::create( providerKey, dataSource, outputFormat, nBands, type, mColumns, mRows, geoTransform, mCrs );
589+
if ( !raster.provider || !raster.provider->isValid() )
595590
{
596-
delete raster.provider;
591+
if ( raster.provider ) delete raster.provider;
597592
fatal( "Cannot create output data source: " + dataSource );
598593
}
594+
599595
raster.band = 1;
600596
double noDataValue = std::numeric_limits<double>::quiet_NaN();
601597
switch ( wr_type )

0 commit comments

Comments
 (0)
Please sign in to comment.