Skip to content

Commit d00efde

Browse files
authoredNov 9, 2017
Merge pull request #5580 from rouault/fix_QgsRasterFileWriter_geopackage
[GDAL provider] in create(), use newly create dataset handle to instanciate the provider (fix #17103)
2 parents 022f6cf + c3e15f5 commit d00efde

File tree

3 files changed

+68
-26
lines changed

3 files changed

+68
-26
lines changed
 

‎src/providers/gdal/qgsgdalprovider.cpp

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ QgsGdalProvider::QgsGdalProvider( const QString &uri, const QgsError &error )
117117
setError( error );
118118
}
119119

120-
QgsGdalProvider::QgsGdalProvider( const QString &uri, bool update )
120+
QgsGdalProvider::QgsGdalProvider( const QString &uri, bool update, GDALDatasetH dataset )
121121
: QgsRasterDataProvider( uri )
122122
, mUpdate( update )
123123
{
@@ -156,29 +156,35 @@ QgsGdalProvider::QgsGdalProvider( const QString &uri, bool update )
156156
}
157157

158158
mGdalDataset = nullptr;
159-
160-
// Try to open using VSIFileHandler (see qgsogrprovider.cpp)
161-
QString vsiPrefix = QgsZipItem::vsiPrefix( uri );
162-
if ( !vsiPrefix.isEmpty() )
159+
if ( dataset )
163160
{
164-
if ( !uri.startsWith( vsiPrefix ) )
165-
setDataSourceUri( vsiPrefix + uri );
166-
QgsDebugMsg( QString( "Trying %1 syntax, uri= %2" ).arg( vsiPrefix, dataSourceUri() ) );
161+
mGdalBaseDataset = dataset;
167162
}
163+
else
164+
{
165+
// Try to open using VSIFileHandler (see qgsogrprovider.cpp)
166+
QString vsiPrefix = QgsZipItem::vsiPrefix( uri );
167+
if ( !vsiPrefix.isEmpty() )
168+
{
169+
if ( !uri.startsWith( vsiPrefix ) )
170+
setDataSourceUri( vsiPrefix + uri );
171+
QgsDebugMsg( QString( "Trying %1 syntax, uri= %2" ).arg( vsiPrefix, dataSourceUri() ) );
172+
}
168173

169-
QString gdalUri = dataSourceUri();
174+
QString gdalUri = dataSourceUri();
170175

171-
CPLErrorReset();
172-
mGdalBaseDataset = gdalOpen( gdalUri.toUtf8().constData(), mUpdate ? GA_Update : GA_ReadOnly );
176+
CPLErrorReset();
177+
mGdalBaseDataset = gdalOpen( gdalUri.toUtf8().constData(), mUpdate ? GA_Update : GA_ReadOnly );
173178

174-
if ( !mGdalBaseDataset )
175-
{
176-
QString msg = QStringLiteral( "Cannot open GDAL dataset %1:\n%2" ).arg( dataSourceUri(), QString::fromUtf8( CPLGetLastErrorMsg() ) );
177-
appendError( ERRMSG( msg ) );
178-
return;
179-
}
179+
if ( !mGdalBaseDataset )
180+
{
181+
QString msg = QStringLiteral( "Cannot open GDAL dataset %1:\n%2" ).arg( dataSourceUri(), QString::fromUtf8( CPLGetLastErrorMsg() ) );
182+
appendError( ERRMSG( msg ) );
183+
return;
184+
}
180185

181-
QgsDebugMsg( "GdalDataset opened" );
186+
QgsDebugMsg( "GdalDataset opened" );
187+
}
182188
initBaseDataset();
183189
}
184190

@@ -2726,7 +2732,7 @@ QGISEXTERN QgsGdalProvider *create(
27262732
//create dataset
27272733
CPLErrorReset();
27282734
char **papszOptions = papszFromStringList( createOptions );
2729-
gdal::dataset_unique_ptr dataset( GDALCreate( driver, uri.toUtf8().constData(), width, height, nBands, ( GDALDataType )type, papszOptions ) );
2735+
GDALDatasetH dataset = GDALCreate( driver, uri.toUtf8().constData(), width, height, nBands, ( GDALDataType )type, papszOptions );
27302736
CSLDestroy( papszOptions );
27312737
if ( !dataset )
27322738
{
@@ -2735,11 +2741,10 @@ QGISEXTERN QgsGdalProvider *create(
27352741
return new QgsGdalProvider( uri, error );
27362742
}
27372743

2738-
GDALSetGeoTransform( dataset.get(), geoTransform );
2739-
GDALSetProjection( dataset.get(), crs.toWkt().toLocal8Bit().data() );
2740-
dataset.reset();
2744+
GDALSetGeoTransform( dataset, geoTransform );
2745+
GDALSetProjection( dataset, crs.toWkt().toLocal8Bit().data() );
27412746

2742-
return new QgsGdalProvider( uri, true );
2747+
return new QgsGdalProvider( uri, true, dataset );
27432748
}
27442749

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

‎src/providers/gdal/qgsgdalprovider.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,12 @@ class QgsGdalProvider : public QgsRasterDataProvider, QgsGdalProviderBase
6363
/**
6464
* Constructor for the provider.
6565
*
66-
* \param uri HTTP URL of the Web Server. If needed a proxy will be used
67-
* otherwise we contact the host directly.
66+
* \param uri file name
67+
* \param update whether to open in update mode
68+
* \param newDataset handle of newly created dataset.
6869
*
6970
*/
70-
QgsGdalProvider( QString const &uri = QString(), bool update = false );
71+
QgsGdalProvider( QString const &uri = QString(), bool update = false, GDALDatasetH newDataset = nullptr );
7172

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

‎tests/src/python/test_qgsrasterfilewriter.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616

1717
import os
1818
import glob
19+
import tempfile
1920

21+
from osgeo import gdal
2022
from qgis.PyQt.QtCore import QTemporaryFile, QDir
2123
from qgis.core import (QgsRasterLayer,
2224
QgsRasterChecker,
@@ -107,6 +109,40 @@ def testDriverForExtension(self):
107109
self.assertEqual(QgsRasterFileWriter.driverForExtension('not a format'), '')
108110
self.assertEqual(QgsRasterFileWriter.driverForExtension(''), '')
109111

112+
def testImportIntoGpkg(self):
113+
# init target file
114+
test_gpkg = tempfile.mktemp(suffix='.gpkg', dir=self.testDataDir)
115+
gdal.GetDriverByName('GPKG').Create(test_gpkg, 1, 1, 1)
116+
source = QgsRasterLayer(os.path.join(self.testDataDir, 'raster', 'band3_byte_noct_epsg4326.tif'), 'my', 'gdal')
117+
self.assertTrue(source.isValid())
118+
provider = source.dataProvider()
119+
fw = QgsRasterFileWriter(test_gpkg)
120+
fw.setOutputFormat('gpkg')
121+
fw.setCreateOptions(['RASTER_TABLE=imported_table', 'APPEND_SUBDATASET=YES'])
122+
123+
pipe = QgsRasterPipe()
124+
self.assertTrue(pipe.set(provider.clone()))
125+
126+
projector = QgsRasterProjector()
127+
projector.setCrs(provider.crs(), provider.crs())
128+
self.assertTrue(pipe.insert(2, projector))
129+
130+
self.assertEqual(fw.writeRaster(pipe,
131+
provider.xSize(),
132+
provider.ySize(),
133+
provider.extent(),
134+
provider.crs()), 0)
135+
136+
# Check that the test geopackage contains the raster layer and compare
137+
rlayer = QgsRasterLayer('GPKG:%s:imported_table' % test_gpkg)
138+
self.assertTrue(rlayer.isValid())
139+
out_provider = rlayer.dataProvider()
140+
self.assertEqual(provider.block(1, provider.extent(), source.width(), source.height()).data(),
141+
out_provider.block(1, out_provider.extent(), rlayer.width(), rlayer.height()).data())
142+
143+
# remove result file
144+
os.unlink(test_gpkg)
145+
110146

111147
if __name__ == '__main__':
112148
unittest.main()

0 commit comments

Comments
 (0)
Please sign in to comment.