Skip to content

Commit 09bc1b2

Browse files
committed
building pyramids crash fix
1 parent 5d7b3f2 commit 09bc1b2

File tree

1 file changed

+83
-77
lines changed

1 file changed

+83
-77
lines changed

src/providers/gdal/qgsgdalprovider.cpp

Lines changed: 83 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1368,8 +1368,6 @@ QString QgsGdalProvider::buildPyramids( QList<QgsRasterPyramid> const & theRaste
13681368
// if the dataset couldn't be opened in read / write mode, tell the user
13691369
if ( !mGdalBaseDataset )
13701370
{
1371-
//mGdalBaseDataset = GDALOpen( QFile::encodeName( mDataSource ).constData(), GA_ReadOnly );
1372-
//mGdalBaseDataset = GDALOpen( QFile::encodeName( dataSourceUri()).constData(), GA_ReadOnly );
13731371
mGdalBaseDataset = GDALOpen( TO8F( dataSourceUri() ), GA_ReadOnly );
13741372
//Since we are not a virtual warped dataset, mGdalDataSet and mGdalBaseDataset are supposed to be the same
13751373
mGdalDataset = mGdalBaseDataset;
@@ -1390,7 +1388,8 @@ QString QgsGdalProvider::buildPyramids( QList<QgsRasterPyramid> const & theRaste
13901388
// marked as exists in each RasterPyramid struct.
13911389
//
13921390
CPLErr myError; //in case anything fails
1393-
int myCount = 1;
1391+
1392+
QVector<int> myOverviewLevelsVector;
13941393
QList<QgsRasterPyramid>::const_iterator myRasterPyramidIterator;
13951394
for ( myRasterPyramidIterator = theRasterPyramidList.begin();
13961395
myRasterPyramidIterator != theRasterPyramidList.end();
@@ -1404,89 +1403,96 @@ QString QgsGdalProvider::buildPyramids( QList<QgsRasterPyramid> const & theRaste
14041403
#endif
14051404
if ( myRasterPyramidIterator->build )
14061405
{
1407-
QgsDebugMsg( "Building....." );
1408-
//emit drawingProgress( myCount, myTotal );
1409-
int myOverviewLevelsArray[1] = { myRasterPyramidIterator->level };
1410-
/* From : http://remotesensing.org/gdal/classGDALDataset.html#a23
1411-
* pszResampling : one of "NEAREST", "GAUSS", "CUBIC", "AVERAGE", "MODE", "AVERAGE_MAGPHASE" or "NONE"
1412-
* controlling the downsampling method applied.
1413-
* nOverviews : number of overviews to build.
1414-
* panOverviewList : the list of overview decimation factors to build.
1415-
* nBand : number of bands to build overviews for in panBandList. Build for all bands if this is 0.
1416-
* panBandList : list of band numbers.
1417-
* pfnProgress : a function to call to report progress, or NULL.
1418-
* pProgressData : application data to pass to the progress function.
1419-
*/
1420-
//build the pyramid and show progress to console
1421-
try
1422-
{
1423-
//build the pyramid and show progress to console
1424-
QgsGdalProgress myProg;
1425-
myProg.type = ProgressPyramids;
1426-
myProg.provider = this;
1427-
const char* theMethod;
1428-
if ( theResamplingMethod == tr( "Gauss" ) )
1429-
theMethod = "GAUSS";
1430-
else if ( theResamplingMethod == tr( "Cubic" ) )
1431-
theMethod = "CUBIC";
1432-
else if ( theResamplingMethod == tr( "Average" ) )
1433-
theMethod = "AVERAGE";
1434-
else if ( theResamplingMethod == tr( "Mode" ) )
1435-
theMethod = "MODE";
1436-
//NOTE magphase is disabled in the gui since it tends
1437-
//to create corrupted images. The images can be repaired
1438-
//by running one of the other resampling strategies below.
1439-
//see ticket #284
1440-
// else if ( theResamplingMethod == tr( "Average Magphase" ) )
1441-
// theMethod = "AVERAGE_MAGPHASE";
1442-
else if ( theResamplingMethod == tr( "None" ) )
1443-
theMethod = "NONE";
1444-
else // fall back to nearest neighbor
1445-
theMethod = "NEAREST";
1446-
QgsDebugMsg( QString( "building overview at level %1 using resampling method %2"
1447-
).arg( myRasterPyramidIterator->level ).arg( theMethod ) );
1448-
// TODO - it would be more efficient to do it once instead of for each level
1449-
myError = GDALBuildOverviews( mGdalBaseDataset, theMethod, 1,
1450-
myOverviewLevelsArray, 0, NULL,
1451-
progressCallback, &myProg ); //this is the arg for the gdal progress callback
1452-
1453-
if ( myError == CE_Failure || CPLGetLastErrorNo() == CPLE_NotSupported )
1454-
{
1455-
//something bad happenend
1456-
//QString myString = QString (CPLGetLastError());
1457-
GDALClose( mGdalBaseDataset );
1458-
//mGdalBaseDataset = GDALOpen( QFile::encodeName( mDataSource ).constData(), GA_ReadOnly );
1459-
//mGdalBaseDataset = GDALOpen( QFile::encodeName( dataSourceUri() ).constData(), GA_ReadOnly );
1460-
mGdalBaseDataset = GDALOpen( TO8F( dataSourceUri() ), GA_ReadOnly );
1461-
//Since we are not a virtual warped dataset, mGdalDataSet and mGdalBaseDataset are supposed to be the same
1462-
mGdalDataset = mGdalBaseDataset;
1463-
1464-
//emit drawingProgress( 0, 0 );
1465-
// restore former USE_RRD config (Erdas)
1466-
CPLSetConfigOption( "USE_RRD", myConfigUseRRD );
1467-
return "FAILED_NOT_SUPPORTED";
1468-
}
1469-
else
1470-
{
1471-
//make sure the raster knows it has pyramids
1472-
mHasPyramids = true;
1473-
}
1474-
myCount++;
1406+
QgsDebugMsg( QString( "adding overview at level %1 to list"
1407+
).arg( myRasterPyramidIterator->level ) );
1408+
myOverviewLevelsVector.append( myRasterPyramidIterator->level );
1409+
}
1410+
}
1411+
/* From : http://remotesensing.org/gdal/classGDALDataset.html#a23
1412+
* pszResampling : one of "NEAREST", "GAUSS", "CUBIC", "AVERAGE", "MODE", "AVERAGE_MAGPHASE" or "NONE"
1413+
* controlling the downsampling method applied.
1414+
* nOverviews : number of overviews to build.
1415+
* panOverviewList : the list of overview decimation factors to build.
1416+
* nBand : number of bands to build overviews for in panBandList. Build for all bands if this is 0.
1417+
* panBandList : list of band numbers.
1418+
* pfnProgress : a function to call to report progress, or NULL.
1419+
* pProgressData : application data to pass to the progress function.
1420+
*/
1421+
1422+
const char* theMethod;
1423+
if ( theResamplingMethod == tr( "Gauss" ) )
1424+
theMethod = "GAUSS";
1425+
else if ( theResamplingMethod == tr( "Cubic" ) )
1426+
theMethod = "CUBIC";
1427+
else if ( theResamplingMethod == tr( "Average" ) )
1428+
theMethod = "AVERAGE";
1429+
else if ( theResamplingMethod == tr( "Mode" ) )
1430+
theMethod = "MODE";
1431+
//NOTE magphase is disabled in the gui since it tends
1432+
//to create corrupted images. The images can be repaired
1433+
//by running one of the other resampling strategies below.
1434+
//see ticket #284
1435+
// else if ( theResamplingMethod == tr( "Average Magphase" ) )
1436+
// theMethod = "AVERAGE_MAGPHASE";
1437+
else if ( theResamplingMethod == tr( "None" ) )
1438+
theMethod = "NONE";
1439+
else // fall back to nearest neighbor
1440+
theMethod = "NEAREST";
1441+
1442+
//build the pyramid and show progress to console
1443+
QgsDebugMsg( QString( "Building overviews at %1 levels using resampling method %2"
1444+
).arg( myOverviewLevelsVector.size() ).arg( theMethod ) );
1445+
try
1446+
{
1447+
//build the pyramid and show progress to console
1448+
QgsGdalProgress myProg;
1449+
myProg.type = ProgressPyramids;
1450+
myProg.provider = this;
1451+
// Observed problem: if a *.rrd file exists and GDALBuildOverviews() is called,
1452+
// the *.rrd is deleted and no overviews are created, if GDALBuildOverviews()
1453+
// is called next time, it crashes somewhere in GDAL.
1454+
// Crash can be avoided if dataset is reopened
1455+
myError = GDALBuildOverviews( mGdalBaseDataset, theMethod,
1456+
myOverviewLevelsVector.size(), myOverviewLevelsVector.data(),
1457+
0, NULL,
1458+
progressCallback, &myProg ); //this is the arg for the gdal progress callback
1459+
1460+
if ( myError == CE_Failure || CPLGetLastErrorNo() == CPLE_NotSupported )
1461+
{
1462+
QgsDebugMsg( "Building pyramids failed" );
1463+
//something bad happenend
1464+
//QString myString = QString (CPLGetLastError());
1465+
GDALClose( mGdalBaseDataset );
1466+
mGdalBaseDataset = GDALOpen( TO8F( dataSourceUri() ), GA_ReadOnly );
1467+
//Since we are not a virtual warped dataset, mGdalDataSet and mGdalBaseDataset are supposed to be the same
1468+
mGdalDataset = mGdalBaseDataset;
14751469

1476-
}
1477-
catch ( CPLErr )
1478-
{
1479-
QgsLogger::warning( "Pyramid overview building failed!" );
1480-
}
1470+
//emit drawingProgress( 0, 0 );
1471+
// restore former USE_RRD config (Erdas)
1472+
CPLSetConfigOption( "USE_RRD", myConfigUseRRD );
1473+
return "FAILED_NOT_SUPPORTED";
1474+
}
1475+
else
1476+
{
1477+
QgsDebugMsg( "Building pyramids finished OK" );
1478+
//make sure the raster knows it has pyramids
1479+
mHasPyramids = true;
14811480
}
14821481
}
1482+
catch ( CPLErr )
1483+
{
1484+
QgsLogger::warning( "Pyramid overview building failed!" );
1485+
}
14831486

14841487
// restore former USE_RRD config (Erdas)
14851488
CPLSetConfigOption( "USE_RRD", myConfigUseRRD );
14861489

14871490
QgsDebugMsg( "Pyramid overviews built" );
1488-
if ( theFormat == PyramidsInternal )
1491+
1492+
// For now always reopen to avoid crash described above
1493+
if ( true || theFormat == PyramidsInternal )
14891494
{
1495+
QgsDebugMsg( "Reopening dataset ..." );
14901496
//close the gdal dataset and reopen it in read only mode
14911497
GDALClose( mGdalBaseDataset );
14921498
mGdalBaseDataset = GDALOpen( TO8F( dataSourceUri() ), GA_ReadOnly );

0 commit comments

Comments
 (0)