mirror of
https://github.com/qgis/QGIS.git
synced 2025-06-18 00:04:02 -04:00
implement pyramids in raster save dialog ; improve pyramids creation ; remove pyramid-related stuff from qgsrasterlayer
This commit is contained in:
parent
4cfc365477
commit
eda71f5a9c
@ -6,7 +6,7 @@
|
||||
class QgsRasterLayer : QgsMapLayer
|
||||
{
|
||||
%TypeHeaderCode
|
||||
#include <qgsrasterpyramid.h>
|
||||
// #include <qgsrasterpyramid.h>
|
||||
#include <qgsrasterlayer.h>
|
||||
#include <qgscontrastenhancement.h>
|
||||
#include <qgsrastertransparency.h>
|
||||
@ -91,7 +91,7 @@ public:
|
||||
* to be added to the list. Each time a RasterPyramid is created
|
||||
* we will check to see if a pyramid matching these dimensions already exists
|
||||
* in the raster layer, and if so mark the exists flag as true */
|
||||
typedef QList<QgsRasterPyramid> RasterPyramidList;
|
||||
// typedef QList<QgsRasterPyramid> RasterPyramidList;
|
||||
|
||||
/** \brief A list containing one RasterBandStats struct per raster band in this raster layer.
|
||||
* Note that while every RasterBandStats element will have the name and number of its associated
|
||||
@ -151,7 +151,7 @@ public:
|
||||
//QString greenBandName() const; //removed with raster redesign
|
||||
|
||||
/** \brief Accessor for mHasPyramids (READ ONLY) */
|
||||
bool hasPyramids();
|
||||
// bool hasPyramids();
|
||||
|
||||
/** \brief Accessor for mUserDefinedGrayMinimumMaximum */
|
||||
bool hasUserDefinedGrayMinimumMaximum() const;
|
||||
@ -248,7 +248,7 @@ public:
|
||||
* ACTUALLY exists you need to look at the existsFlag member in each struct stored in the
|
||||
* list.
|
||||
*/
|
||||
RasterPyramidList buildPyramidList();
|
||||
// RasterPyramidList buildPyramidList();
|
||||
|
||||
/** \brief Accessor for color shader algorithm */
|
||||
QString colorShadingAlgorithmAsString() const;
|
||||
@ -470,9 +470,9 @@ public:
|
||||
|
||||
public slots:
|
||||
/** \brief Create GDAL pyramid overviews */
|
||||
QString buildPyramids( const RasterPyramidList &,
|
||||
const QString & theResamplingMethod = "NEAREST",
|
||||
bool theTryInternalFlag = false );
|
||||
// QString buildPyramids( const RasterPyramidList &,
|
||||
// const QString & theResamplingMethod = "NEAREST",
|
||||
// bool theTryInternalFlag = false );
|
||||
|
||||
void showStatusMessage( const QString & theMessage );
|
||||
|
||||
|
@ -3997,6 +3997,11 @@ void QgisApp::saveAsRasterFile()
|
||||
}
|
||||
fileWriter.setCreateOptions( d.createOptions() );
|
||||
|
||||
fileWriter.setBuildPyramidsFlag( d.buildPyramidsFlag() );
|
||||
fileWriter.setPyramidsList( d.overviewList() );
|
||||
fileWriter.setPyramidsResampling( d.pyramidsResampling() );
|
||||
fileWriter.setPyramidsFormat( d.pyramidsFormat() );
|
||||
|
||||
fileWriter.writeRaster( pipe, d.nColumns(), d.nRows(), d.outputRectangle(), d.outputCrs(), &pd );
|
||||
delete pipe;
|
||||
}
|
||||
|
@ -117,13 +117,20 @@ QgsRasterLayerProperties::QgsRasterLayerProperties( QgsMapLayer* lyr, QgsMapCanv
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QgsRasterDataProvider* provider = mRasterLayer->dataProvider();
|
||||
|
||||
// Only do pyramids if dealing directly with GDAL.
|
||||
if ( provider->capabilities() & QgsRasterDataProvider::BuildPyramids )
|
||||
{
|
||||
QgsRasterLayer::RasterPyramidList myPyramidList = mRasterLayer->buildPyramidList();
|
||||
QgsRasterLayer::RasterPyramidList::iterator myRasterPyramidIterator;
|
||||
// initialize resampling methods
|
||||
cboResamplingMethod->clear();
|
||||
foreach ( QString method, QgsRasterDataProvider::pyramidResamplingMethods( mRasterLayer->providerType() ) )
|
||||
cboResamplingMethod->addItem( method );
|
||||
|
||||
// build pyramid list
|
||||
QList< QgsRasterPyramid > myPyramidList = provider->buildPyramidList();
|
||||
QList< QgsRasterPyramid >::iterator myRasterPyramidIterator;
|
||||
|
||||
for ( myRasterPyramidIterator = myPyramidList.begin();
|
||||
myRasterPyramidIterator != myPyramidList.end();
|
||||
@ -762,13 +769,14 @@ void QgsRasterLayerProperties::apply()
|
||||
|
||||
void QgsRasterLayerProperties::on_buttonBuildPyramids_clicked()
|
||||
{
|
||||
QgsRasterDataProvider* provider = mRasterLayer->dataProvider();
|
||||
|
||||
connect( mRasterLayer, SIGNAL( progressUpdate( int ) ), mPyramidProgress, SLOT( setValue( int ) ) );
|
||||
connect( provider, SIGNAL( progressUpdate( int ) ), mPyramidProgress, SLOT( setValue( int ) ) );
|
||||
//
|
||||
// Go through the list marking any files that are selected in the listview
|
||||
// as true so that we can generate pyramids for them.
|
||||
//
|
||||
QgsRasterLayer::RasterPyramidList myPyramidList = mRasterLayer->buildPyramidList();
|
||||
QList< QgsRasterPyramid> myPyramidList = provider->buildPyramidList();
|
||||
for ( int myCounterInt = 0; myCounterInt < lbxPyramidResolutions->count(); myCounterInt++ )
|
||||
{
|
||||
QListWidgetItem *myItem = lbxPyramidResolutions->item( myCounterInt );
|
||||
@ -781,15 +789,14 @@ void QgsRasterLayerProperties::on_buttonBuildPyramids_clicked()
|
||||
|
||||
// let the user know we're going to possibly be taking a while
|
||||
QApplication::setOverrideCursor( Qt::WaitCursor );
|
||||
bool myBuildInternalFlag = cbxInternalPyramids->isChecked();
|
||||
QString res = mRasterLayer->buildPyramids(
|
||||
QString res = provider->buildPyramids(
|
||||
myPyramidList,
|
||||
cboResamplingMethod->currentText(),
|
||||
myBuildInternalFlag );
|
||||
( QgsRasterDataProvider::RasterPyramidsFormat ) cbxPyramidsFormat->currentIndex() );
|
||||
QApplication::restoreOverrideCursor();
|
||||
mPyramidProgress->setValue( 0 );
|
||||
buttonBuildPyramids->setEnabled( false );
|
||||
disconnect( mRasterLayer, SIGNAL( progressUpdate( int ) ), mPyramidProgress, SLOT( setValue( int ) ) );
|
||||
disconnect( provider, SIGNAL( progressUpdate( int ) ), mPyramidProgress, SLOT( setValue( int ) ) );
|
||||
if ( !res.isNull() )
|
||||
{
|
||||
if ( res == "ERROR_WRITE_ACCESS" )
|
||||
@ -821,17 +828,16 @@ void QgsRasterLayerProperties::on_buttonBuildPyramids_clicked()
|
||||
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// repopulate the pyramids list
|
||||
//
|
||||
lbxPyramidResolutions->clear();
|
||||
// Need to rebuild list as some or all pyramids may have failed to build
|
||||
myPyramidList = mRasterLayer->buildPyramidList();
|
||||
myPyramidList = provider->buildPyramidList();
|
||||
QIcon myPyramidPixmap( QgsApplication::getThemeIcon( "/mIconPyramid.png" ) );
|
||||
QIcon myNoPyramidPixmap( QgsApplication::getThemeIcon( "/mIconNoPyramid.png" ) );
|
||||
|
||||
QgsRasterLayer::RasterPyramidList::iterator myRasterPyramidIterator;
|
||||
QList< QgsRasterPyramid >::iterator myRasterPyramidIterator;
|
||||
for ( myRasterPyramidIterator = myPyramidList.begin();
|
||||
myRasterPyramidIterator != myPyramidList.end();
|
||||
++myRasterPyramidIterator )
|
||||
|
@ -272,6 +272,26 @@ QByteArray QgsRasterDataProvider::noValueBytes( int theBandNo )
|
||||
return ba;
|
||||
}
|
||||
|
||||
bool QgsRasterDataProvider::hasPyramids()
|
||||
{
|
||||
QList<QgsRasterPyramid> myPyramidList = buildPyramidList();
|
||||
|
||||
if ( myPyramidList.isEmpty() )
|
||||
return false;
|
||||
|
||||
QList<QgsRasterPyramid>::iterator myRasterPyramidIterator;
|
||||
for ( myRasterPyramidIterator = myPyramidList.begin();
|
||||
myRasterPyramidIterator != myPyramidList.end();
|
||||
++myRasterPyramidIterator )
|
||||
{
|
||||
if ( myRasterPyramidIterator->exists )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#if 0
|
||||
QgsRasterBandStats QgsRasterDataProvider::bandStatistics( int theBandNo )
|
||||
{
|
||||
|
@ -102,6 +102,20 @@ class CORE_EXPORT QgsRasterDataProvider : public QgsDataProvider, public QgsRast
|
||||
ProgressStatistics = 2
|
||||
};
|
||||
|
||||
enum RasterBuildPyramids
|
||||
{
|
||||
PyramidsFlagNo = 0,
|
||||
PyramidsFlagYes = 1,
|
||||
CopyExisting = 2
|
||||
};
|
||||
|
||||
enum RasterPyramidsFormat
|
||||
{
|
||||
PyramidsGTiff = 0,
|
||||
PyramidsInternal = 1,
|
||||
PyramidsErdas = 2
|
||||
};
|
||||
|
||||
QgsRasterDataProvider();
|
||||
|
||||
QgsRasterDataProvider( QString const & uri );
|
||||
@ -345,15 +359,24 @@ class CORE_EXPORT QgsRasterDataProvider : public QgsDataProvider, public QgsRast
|
||||
/** \brief Create pyramid overviews */
|
||||
virtual QString buildPyramids( const QList<QgsRasterPyramid> & thePyramidList,
|
||||
const QString & theResamplingMethod = "NEAREST",
|
||||
bool theTryInternalFlag = false )
|
||||
{ Q_UNUSED( thePyramidList ); Q_UNUSED( theResamplingMethod ); Q_UNUSED( theTryInternalFlag ); return "FAILED_NOT_SUPPORTED"; };
|
||||
RasterPyramidsFormat theFormat = PyramidsGTiff )
|
||||
{
|
||||
Q_UNUSED( thePyramidList ); Q_UNUSED( theResamplingMethod ); Q_UNUSED( theFormat );
|
||||
return "FAILED_NOT_SUPPORTED";
|
||||
};
|
||||
|
||||
/** \brief Accessor for ths raster layers pyramid list. A pyramid list defines the
|
||||
/** \brief Accessor for ths raster layers pyramid list.
|
||||
* @param overviewList used to construct the pyramid list (optional), when empty the list is defined by the provider.
|
||||
* A pyramid list defines the
|
||||
* POTENTIAL pyramids that can be in a raster. To know which of the pyramid layers
|
||||
* ACTUALLY exists you need to look at the existsFlag member in each struct stored in the
|
||||
* list.
|
||||
*/
|
||||
virtual QList<QgsRasterPyramid> buildPyramidList() { return QList<QgsRasterPyramid>(); };
|
||||
virtual QList<QgsRasterPyramid> buildPyramidList( QList<int> overviewList = QList<int>() )
|
||||
{ Q_UNUSED( overviewList ); return QList<QgsRasterPyramid>(); };
|
||||
|
||||
/** \brief Returns true if raster has at least one populated histogram. */
|
||||
bool hasPyramids();
|
||||
|
||||
/** If the provider supports it, return band stats for the
|
||||
given band. Default behaviour is to blockwise read the data
|
||||
@ -537,13 +560,21 @@ class CORE_EXPORT QgsRasterDataProvider : public QgsDataProvider, public QgsRast
|
||||
/** Remove dataset*/
|
||||
virtual bool remove() { return false; }
|
||||
|
||||
static QStringList pyramidResamplingMethods( QString providerKey )
|
||||
{
|
||||
return providerKey == "gdal" ?
|
||||
QStringList() << tr( "Average" ) << tr( "Nearest Neighbour" ) << tr( "Gauss" ) <<
|
||||
tr( "Cubic" ) << tr( "Mode" ) << tr( "None" ) : QStringList();
|
||||
}
|
||||
|
||||
signals:
|
||||
/** Emit a signal to notify of the progress event.
|
||||
* Emited theProgress is in percents (0.0-100.0) */
|
||||
void progress( int theType, double theProgress, QString theMessage );
|
||||
void progressUpdate( int theProgress );
|
||||
|
||||
protected:
|
||||
/**Dots per intch. Extended WMS (e.g. QGIS mapserver) support DPI dependent output and therefore
|
||||
/**Dots per inch. Extended WMS (e.g. QGIS mapserver) support DPI dependent output and therefore
|
||||
are suited for printing. A value of -1 means it has not been set
|
||||
@note: this member has been added in version 1.2*/
|
||||
int mDpi;
|
||||
|
@ -18,13 +18,20 @@
|
||||
#include "qgsrasteriterator.h"
|
||||
#include "qgsrasterlayer.h"
|
||||
#include "qgsrasterprojector.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QProgressDialog>
|
||||
#include <QTextStream>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "gdal.h"
|
||||
|
||||
QgsRasterFileWriter::QgsRasterFileWriter( const QString& outputUrl ): mOutputUrl( outputUrl ), mOutputProviderKey( "gdal" ), mOutputFormat( "GTiff" ), mTiledMode( false ),
|
||||
mMaxTileWidth( 500 ), mMaxTileHeight( 500 ), mProgressDialog( 0 )
|
||||
QgsRasterFileWriter::QgsRasterFileWriter( const QString& outputUrl ):
|
||||
mOutputUrl( outputUrl ), mOutputProviderKey( "gdal" ), mOutputFormat( "GTiff" ),
|
||||
mTiledMode( false ), mMaxTileWidth( 500 ), mMaxTileHeight( 500 ),
|
||||
mBuildPyramidsFlag( QgsRasterDataProvider::PyramidsFlagNo ),
|
||||
mPyramidsFormat( QgsRasterDataProvider::PyramidsGTiff ),
|
||||
mProgressDialog( 0 )
|
||||
{
|
||||
|
||||
}
|
||||
@ -210,6 +217,7 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster( const Qgs
|
||||
destNoDataValueList.append( destNoDataValue );
|
||||
}
|
||||
|
||||
// TODO - what is this code doing here in the middle of the file, outside of a function???
|
||||
|
||||
QgsRasterInterface::DataType destDataType = destDataTypeList.value( 0 );
|
||||
// Currently write API supports one output type for dataset only -> find the widest
|
||||
@ -281,6 +289,7 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster(
|
||||
{
|
||||
iter->startRasterRead( i, nCols, nRows, outputExtent );
|
||||
dataList.push_back( VSIMalloc( dataTypeSize * mMaxTileWidth * mMaxTileHeight ) );
|
||||
// TODO - fix segfault here when using tiles+vrt (reported by Etienne)
|
||||
destProvider->setNoDataValue( i, destNoDataValueList.value( i - 1 ) );
|
||||
}
|
||||
|
||||
@ -296,6 +305,8 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster(
|
||||
progressDialog->setLabelText( QObject::tr( "Reading raster part %1 of %2" ).arg( fileIndex + 1 ).arg( nParts ) );
|
||||
}
|
||||
|
||||
// hmm why is there a while( true ) here ..
|
||||
// not good coding practice IMHO, it might be better to use [ for() and break ] or [ while (test) ]
|
||||
while ( true )
|
||||
{
|
||||
for ( int i = 1; i <= nBands; ++i )
|
||||
@ -310,7 +321,13 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster(
|
||||
writeVRT( vrtFilePath );
|
||||
buildPyramids( vrtFilePath );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( mBuildPyramidsFlag == QgsRasterDataProvider::PyramidsFlagYes )
|
||||
buildPyramids( mOutputUrl );
|
||||
}
|
||||
|
||||
QgsDebugMsg( "Done" );
|
||||
return NoError; //reached last tile, bail out
|
||||
}
|
||||
// TODO: verify if NoDataConflict happened, to do that we need the whole pipe or nuller interface
|
||||
@ -356,6 +373,8 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster(
|
||||
}
|
||||
++fileIndex;
|
||||
}
|
||||
|
||||
QgsDebugMsg( "Done" );
|
||||
return NoError;
|
||||
}
|
||||
|
||||
@ -482,6 +501,7 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeImageRaster( QgsRaste
|
||||
|
||||
++fileIndex;
|
||||
}
|
||||
|
||||
delete destProvider;
|
||||
CPLFree( redData ); CPLFree( greenData ); CPLFree( blueData ); CPLFree( alphaData );
|
||||
|
||||
@ -497,6 +517,11 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeImageRaster( QgsRaste
|
||||
writeVRT( vrtFilePath );
|
||||
buildPyramids( vrtFilePath );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( mBuildPyramidsFlag == QgsRasterDataProvider::PyramidsFlagYes )
|
||||
buildPyramids( mOutputUrl );
|
||||
}
|
||||
return NoError;
|
||||
}
|
||||
|
||||
@ -565,6 +590,7 @@ void QgsRasterFileWriter::addToVRT( const QString& filename, int band, int xSize
|
||||
bandElem.appendChild( simpleSourceElem );
|
||||
}
|
||||
|
||||
#if 0
|
||||
void QgsRasterFileWriter::buildPyramids( const QString& filename )
|
||||
{
|
||||
GDALDatasetH dataSet;
|
||||
@ -593,6 +619,67 @@ void QgsRasterFileWriter::buildPyramids( const QString& filename )
|
||||
}*/
|
||||
GDALBuildOverviews( dataSet, "AVERAGE", 6, overviewList, 0, 0, /*pyramidsProgress*/ 0, /*mProgressDialog*/ 0 );
|
||||
}
|
||||
#endif
|
||||
|
||||
void QgsRasterFileWriter::buildPyramids( const QString& filename )
|
||||
{
|
||||
// open new dataProvider so we can build pyramids with it
|
||||
QgsRasterDataProvider* destProvider = QgsRasterLayer::loadProvider( mOutputProviderKey, filename );
|
||||
if ( !destProvider )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO progress report
|
||||
// TODO test mTiledMode - not tested b/c segfault at line # 289
|
||||
// connect( provider, SIGNAL( progressUpdate( int ) ), mPyramidProgress, SLOT( setValue( int ) ) );
|
||||
QList< QgsRasterPyramid> myPyramidList;
|
||||
if ( ! mPyramidsList.isEmpty() )
|
||||
myPyramidList = destProvider->buildPyramidList( mPyramidsList );
|
||||
for ( int myCounterInt = 0; myCounterInt < myPyramidList.count(); myCounterInt++ )
|
||||
{
|
||||
myPyramidList[myCounterInt].build = true;
|
||||
}
|
||||
|
||||
QgsDebugMsg( QString( "building pyramids : %1 pyramids, %2 resampling, %3 format" ).arg( myPyramidList.count() ).arg( mPyramidsResampling ).arg( mPyramidsFormat ) );
|
||||
// QApplication::setOverrideCursor( Qt::WaitCursor );
|
||||
QString res = destProvider->buildPyramids( myPyramidList, mPyramidsResampling, mPyramidsFormat );
|
||||
// QApplication::restoreOverrideCursor();
|
||||
|
||||
// TODO put this in provider or elsewhere
|
||||
if ( !res.isNull() )
|
||||
{
|
||||
QString title, message;
|
||||
if ( res == "ERROR_WRITE_ACCESS" )
|
||||
{
|
||||
title = QObject::tr( "Building pyramids failed - write access denied" );
|
||||
message = QObject::tr( "Write access denied. Adjust the file permissions and try again." );
|
||||
}
|
||||
else if ( res == "ERROR_WRITE_FORMAT" )
|
||||
{
|
||||
title = QObject::tr( "Building pyramids failed." );
|
||||
message = QObject::tr( "The file was not writable. Some formats do not "
|
||||
"support pyramid overviews. Consult the GDAL documentation if in doubt." );
|
||||
}
|
||||
else if ( res == "FAILED_NOT_SUPPORTED" )
|
||||
{
|
||||
title = QObject::tr( "Building pyramids failed." );
|
||||
message = QObject::tr( "Building pyramid overviews is not supported on this type of raster." );
|
||||
}
|
||||
else if ( res == "ERROR_JPEG_COMPRESSION" )
|
||||
{
|
||||
title = QObject::tr( "Building pyramids failed." );
|
||||
message = QObject::tr( "Building internal pyramid overviews is not supported on raster layers with JPEG compression and your current libtiff library." );
|
||||
}
|
||||
else if ( res == "ERROR_VIRTUAL" )
|
||||
{
|
||||
title = QObject::tr( "Building pyramids failed." );
|
||||
message = QObject::tr( "Building pyramid overviews is not supported on this type of raster." );
|
||||
}
|
||||
QMessageBox::warning( 0, title, message );
|
||||
QgsDebugMsg( res + " - " + message );
|
||||
}
|
||||
}
|
||||
|
||||
int QgsRasterFileWriter::pyramidsProgress( double dfComplete, const char *pszMessage, void* pData )
|
||||
{
|
||||
@ -744,6 +831,11 @@ QgsRasterDataProvider* QgsRasterFileWriter::initOutput( int nCols, int nRows, co
|
||||
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 ) )
|
||||
{
|
||||
|
@ -66,6 +66,18 @@ class CORE_EXPORT QgsRasterFileWriter
|
||||
void setMaxTileWidth( int w ) { mMaxTileWidth = w; }
|
||||
int maxTileWidth() const { return mMaxTileWidth; }
|
||||
|
||||
QgsRasterDataProvider::RasterBuildPyramids buildPyramidsFlag() const { return mBuildPyramidsFlag; }
|
||||
void setBuildPyramidsFlag( QgsRasterDataProvider::RasterBuildPyramids f ) { mBuildPyramidsFlag = f; }
|
||||
|
||||
QList< int > pyramidsList() const { return mPyramidsList; }
|
||||
void setPyramidsList( const QList< int > & list ) { mPyramidsList = list; }
|
||||
|
||||
QString pyramidsResampling() const { return mPyramidsResampling; }
|
||||
void setPyramidsResampling( const QString & str ) { mPyramidsResampling = str; }
|
||||
|
||||
QgsRasterDataProvider::RasterPyramidsFormat pyramidsFormat() const { return mPyramidsFormat; }
|
||||
void setPyramidsFormat( QgsRasterDataProvider::RasterPyramidsFormat f ) { mPyramidsFormat = f; }
|
||||
|
||||
void setMaxTileHeight( int h ) { mMaxTileHeight = h; }
|
||||
int maxTileHeight() const { return mMaxTileHeight; }
|
||||
|
||||
@ -128,6 +140,11 @@ class CORE_EXPORT QgsRasterFileWriter
|
||||
double mMaxTileWidth;
|
||||
double mMaxTileHeight;
|
||||
|
||||
QList< int > mPyramidsList;
|
||||
QString mPyramidsResampling;
|
||||
QgsRasterDataProvider::RasterBuildPyramids mBuildPyramidsFlag;
|
||||
QgsRasterDataProvider::RasterPyramidsFormat mPyramidsFormat;
|
||||
|
||||
QDomDocument mVRTDocument;
|
||||
QDomElement mVRTRedBand;
|
||||
QDomElement mVRTGreenBand;
|
||||
|
@ -23,9 +23,7 @@ email : tim at linfiniti.com
|
||||
#include "qgsmaptopixel.h"
|
||||
#include "qgsprojectfiletransform.h"
|
||||
#include "qgsproviderregistry.h"
|
||||
#include "qgsrasterbandstats.h"
|
||||
#include "qgsrasterlayer.h"
|
||||
#include "qgsrasterpyramid.h"
|
||||
#include "qgsrasterrendererregistry.h"
|
||||
#include "qgsrectangle.h"
|
||||
#include "qgsrendercontext.h"
|
||||
@ -423,7 +421,6 @@ const QgsRasterBandStats QgsRasterLayer::bandStatistics( QString const & theBand
|
||||
|
||||
return QgsRasterBandStats(); // return a null one
|
||||
}
|
||||
#endif
|
||||
|
||||
QString QgsRasterLayer::buildPyramids( RasterPyramidList const & theRasterPyramidList,
|
||||
QString const & theResamplingMethod, bool theTryInternalFlag )
|
||||
@ -436,6 +433,7 @@ QgsRasterLayer::RasterPyramidList QgsRasterLayer::buildPyramidList()
|
||||
{
|
||||
return mDataProvider->buildPyramidList();
|
||||
}
|
||||
#endif
|
||||
|
||||
QString QgsRasterLayer::colorShadingAlgorithmAsString() const
|
||||
{
|
||||
@ -1558,7 +1556,6 @@ void QgsRasterLayer::init()
|
||||
setDrawingStyle( QgsRasterLayer::UndefinedDrawingStyle );
|
||||
|
||||
mBandCount = 0;
|
||||
mHasPyramids = false;
|
||||
mNoDataValue = -9999.0;
|
||||
mValidNoDataValue = false;
|
||||
|
||||
@ -1822,12 +1819,7 @@ void QgsRasterLayer::closeDataProvider()
|
||||
mValid = false;
|
||||
mPipe.remove( mDataProvider );
|
||||
mDataProvider = 0;
|
||||
|
||||
//mRasterStatsList.clear();
|
||||
mContrastEnhancementList.clear();
|
||||
|
||||
mHasPyramids = false;
|
||||
mPyramidList.clear();
|
||||
}
|
||||
|
||||
void QgsRasterLayer::setColorShadingAlgorithm( ColorShadingAlgorithm )
|
||||
|
@ -51,8 +51,6 @@
|
||||
//
|
||||
class QgsMapToPixel;
|
||||
class QgsRectangle;
|
||||
class QgsRasterBandStats;
|
||||
class QgsRasterPyramid;
|
||||
class QgsRasterRenderer;
|
||||
class QImage;
|
||||
class QPixmap;
|
||||
@ -273,12 +271,12 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
|
||||
* to be added to the list. Each time a RasterPyramid is created
|
||||
* we will check to see if a pyramid matching these dimensions already exists
|
||||
* in the raster layer, and if so mark the exists flag as true */
|
||||
typedef QList<QgsRasterPyramid> RasterPyramidList;
|
||||
/* typedef QList<QgsRasterPyramid> RasterPyramidList; */
|
||||
|
||||
/** \brief A list containing one RasterBandStats struct per raster band in this raster layer.
|
||||
* Note that while every RasterBandStats element will have the name and number of its associated
|
||||
* band populated, any additional stats are calculated on a need to know basis.*/
|
||||
typedef QList<QgsRasterBandStats> RasterStatsList;
|
||||
/* typedef QList<QgsRasterBandStats> RasterStatsList; */
|
||||
|
||||
//
|
||||
// Static methods:
|
||||
@ -332,7 +330,7 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
|
||||
DrawingStyle drawingStyle() { return mDrawingStyle; }
|
||||
|
||||
/** \brief Accessor for mHasPyramids (READ ONLY) */
|
||||
bool hasPyramids() { return mHasPyramids; }
|
||||
/* bool hasPyramids() { return dataProvider() != NULL ? dataProvider()->hasPyramids() : false ; } */
|
||||
|
||||
/** \brief Accessor for mUserDefinedGrayMinimumMaximum */
|
||||
bool hasUserDefinedGrayMinimumMaximum() const { return mUserDefinedGrayMinimumMaximum; }
|
||||
@ -414,7 +412,7 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
|
||||
* ACTUALLY exists you need to look at the existsFlag member in each struct stored in the
|
||||
* list.
|
||||
*/
|
||||
RasterPyramidList buildPyramidList();
|
||||
// RasterPyramidList buildPyramidList();
|
||||
|
||||
/** \brief Accessor for color shader algorithm */
|
||||
QString colorShadingAlgorithmAsString() const;
|
||||
@ -677,9 +675,9 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
|
||||
|
||||
public slots:
|
||||
/** \brief Create GDAL pyramid overviews */
|
||||
QString buildPyramids( const RasterPyramidList &,
|
||||
const QString & theResamplingMethod = "NEAREST",
|
||||
bool theTryInternalFlag = false );
|
||||
// QString buildPyramids( const RasterPyramidList &,
|
||||
// const QString & theResamplingMethod = "NEAREST",
|
||||
// bool theTryInternalFlag = false );
|
||||
|
||||
void showStatusMessage( const QString & theMessage );
|
||||
|
||||
@ -853,9 +851,6 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
|
||||
/** \brief Values for mapping pixel to world coordinates. Contents of this array are the same as the GDAL adfGeoTransform */
|
||||
double mGeoTransform[6];
|
||||
|
||||
/** \brief Whether this raster has overviews / pyramids or not */
|
||||
bool mHasPyramids;
|
||||
|
||||
/** \brief Raster width */
|
||||
int mWidth;
|
||||
|
||||
@ -880,7 +875,7 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
|
||||
QString mProviderKey;
|
||||
|
||||
/** \brief This list holds a series of RasterPyramid structs which store information for each potential pyramid level */
|
||||
RasterPyramidList mPyramidList;
|
||||
/* RasterPyramidList mPyramidList; */
|
||||
|
||||
/** \brief A collection of stats - one for each band in the layer */
|
||||
//RasterStatsList mRasterStatsList;
|
||||
|
@ -77,10 +77,32 @@ QgsRasterLayerSaveAsDialog::QgsRasterLayerSaveAsDialog( QgsRasterLayer* rasterLa
|
||||
mCreateOptionsWidget->setFormat( myFormats[0] );
|
||||
}
|
||||
mCreateOptionsWidget->update();
|
||||
}
|
||||
|
||||
// Only do pyramids if dealing directly with GDAL.
|
||||
if ( mDataProvider->capabilities() & QgsRasterDataProvider::BuildPyramids )
|
||||
{
|
||||
mPyramidsOptionsWidget->createOptionsWidget()->setType( QgsRasterFormatSaveOptionsWidget::ProfileLineEdit );
|
||||
|
||||
// init. pyramids button group
|
||||
for ( int i = -2, j = 0 ; i >= -4 ; i--, j++ )
|
||||
mPyramidsButtonGroup->setId( mPyramidsButtonGroup->button( i ), j );
|
||||
// TODO enable "use existing", has no effect for now, because using Create() in gdal provider
|
||||
// if ( ! mDataProvider->hasPyramids() )
|
||||
// mPyramidsButtonGroup->button( QgsRasterDataProvider::CopyExisting )->setEnabled( false );
|
||||
mPyramidsButtonGroup->button( QgsRasterDataProvider::CopyExisting )->setEnabled( false );
|
||||
mPyramidsButtonGroup->button( QgsRasterDataProvider::PyramidsFlagNo )->click();
|
||||
mPyramidsButtonGroup->button( QgsRasterDataProvider::PyramidsFlagNo )->setChecked( true );
|
||||
|
||||
populatePyramidsLevels();
|
||||
connect( mPyramidsOptionsWidget, SIGNAL( overviewListChanged() ),
|
||||
this, SLOT( populatePyramidsLevels() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
mPyramidsGroupBox->setEnabled( false );
|
||||
}
|
||||
|
||||
updateCrsGroup();
|
||||
|
||||
QPushButton* okButton = mButtonBox->button( QDialogButtonBox::Ok );
|
||||
@ -627,6 +649,75 @@ void QgsRasterLayerSaveAsDialog::noDataCellTextEdited( const QString & text )
|
||||
}
|
||||
}
|
||||
|
||||
void QgsRasterLayerSaveAsDialog::on_mTileModeCheckBox_toggled( bool toggled )
|
||||
{
|
||||
if ( toggled )
|
||||
{
|
||||
// enable pyramids
|
||||
if ( ! mPyramidsGroupBox->isChecked() )
|
||||
mPyramidsGroupBox->setChecked( true );
|
||||
if ( mPyramidsButtonGroup->checkedId() == QgsRasterDataProvider::PyramidsFlagNo )
|
||||
{
|
||||
mPyramidsButtonGroup->button( QgsRasterDataProvider::PyramidsFlagYes )->click();
|
||||
mPyramidsButtonGroup->button( QgsRasterDataProvider::PyramidsFlagYes )->setChecked( true );
|
||||
}
|
||||
mPyramidsOptionsWidget->checkAllLevels( true );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsRasterLayerSaveAsDialog::on_mPyramidsButtonGroup_buttonClicked( int id )
|
||||
{
|
||||
if ( id == QgsRasterDataProvider::PyramidsFlagNo || id == QgsRasterDataProvider::CopyExisting )
|
||||
{
|
||||
mPyramidsOptionsWidget->setEnabled( false );
|
||||
mPyramidResolutionsLabel->setEnabled( false );
|
||||
mPyramidResolutionsLineEdit->setEnabled( false );
|
||||
}
|
||||
else if ( id == QgsRasterDataProvider::PyramidsFlagYes )
|
||||
{
|
||||
mPyramidsOptionsWidget->setEnabled( true );
|
||||
mPyramidResolutionsLabel->setEnabled( true );
|
||||
mPyramidResolutionsLineEdit->setEnabled( true );
|
||||
}
|
||||
else
|
||||
QgsDebugMsg( QString( "invalid button id %1" ).arg( id ) );
|
||||
populatePyramidsLevels();
|
||||
}
|
||||
|
||||
void QgsRasterLayerSaveAsDialog::populatePyramidsLevels()
|
||||
{
|
||||
// if selection != "Build pyramids", get pyramids from actual layer
|
||||
QString text;
|
||||
|
||||
if ( mPyramidsButtonGroup->checkedId() != QgsRasterDataProvider::PyramidsFlagNo )
|
||||
{
|
||||
QList<QgsRasterPyramid> myPyramidList;
|
||||
if ( mPyramidsButtonGroup->checkedId() == QgsRasterDataProvider::CopyExisting )
|
||||
{
|
||||
myPyramidList = mDataProvider->buildPyramidList();
|
||||
}
|
||||
else if ( mPyramidsButtonGroup->checkedId() == QgsRasterDataProvider::PyramidsFlagYes )
|
||||
{
|
||||
if ( ! mPyramidsOptionsWidget->overviewList().isEmpty() )
|
||||
myPyramidList = mDataProvider->buildPyramidList( mPyramidsOptionsWidget->overviewList() );
|
||||
}
|
||||
QList<QgsRasterPyramid>::iterator myRasterPyramidIterator;
|
||||
for ( myRasterPyramidIterator = myPyramidList.begin();
|
||||
myRasterPyramidIterator != myPyramidList.end();
|
||||
++myRasterPyramidIterator )
|
||||
{
|
||||
if ( mPyramidsButtonGroup->checkedId() == QgsRasterDataProvider::PyramidsFlagYes
|
||||
|| myRasterPyramidIterator->exists )
|
||||
{
|
||||
text += QString::number( myRasterPyramidIterator->xDim ) + QString( "x" ) +
|
||||
QString::number( myRasterPyramidIterator->yDim ) + " ";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mPyramidResolutionsLineEdit->setText( text.trimmed() );
|
||||
}
|
||||
|
||||
void QgsRasterLayerSaveAsDialog::setNoDataToEdited( int row )
|
||||
{
|
||||
if ( row >= mNoDataToEdited.size() )
|
||||
|
@ -58,6 +58,14 @@ class GUI_EXPORT QgsRasterLayerSaveAsDialog: public QDialog, private Ui::QgsRast
|
||||
QgsRectangle outputRectangle() const;
|
||||
QList<QgsRasterNuller::NoData> noData() const;
|
||||
|
||||
QList< int > overviewList() const { return mPyramidsOptionsWidget->overviewList(); }
|
||||
QgsRasterDataProvider::RasterBuildPyramids buildPyramidsFlag() const
|
||||
{ return ( QgsRasterDataProvider::RasterBuildPyramids ) mPyramidsButtonGroup->checkedId(); }
|
||||
QString pyramidsResampling() const { return mPyramidsOptionsWidget->resamplingMethod(); }
|
||||
QgsRasterDataProvider::RasterPyramidsFormat pyramidsFormat() const
|
||||
{ return mPyramidsOptionsWidget->pyramidsFormat(); }
|
||||
|
||||
|
||||
void hideFormat();
|
||||
void hideOutput();
|
||||
|
||||
@ -92,6 +100,9 @@ class GUI_EXPORT QgsRasterLayerSaveAsDialog: public QDialog, private Ui::QgsRast
|
||||
void on_mRemoveSelectedNoDataToolButton_clicked();
|
||||
void on_mRemoveAllNoDataToolButton_clicked();
|
||||
void noDataCellTextEdited( const QString & text );
|
||||
void on_mTileModeCheckBox_toggled( bool toggled );
|
||||
void on_mPyramidsButtonGroup_buttonClicked( int id );
|
||||
void populatePyramidsLevels();
|
||||
|
||||
private:
|
||||
QgsRasterLayer* mRasterLayer;
|
||||
|
@ -34,10 +34,10 @@
|
||||
|
||||
|
||||
QgsRasterPyramidsOptionsWidget::QgsRasterPyramidsOptionsWidget( QWidget* parent, QString provider )
|
||||
: QWidget( parent ), mProvider( provider )
|
||||
: QWidget( parent ), mProvider( provider )
|
||||
{
|
||||
setupUi( this );
|
||||
|
||||
|
||||
mPyramidsOptionsWidget->setProvider( provider );
|
||||
mPyramidsOptionsWidget->setFormat( "_pyramids" );
|
||||
// mPyramidsOptionsWidget->swapOptionsUI( 1 );
|
||||
@ -59,14 +59,23 @@ void QgsRasterPyramidsOptionsWidget::updateUi()
|
||||
// cbxPyramidsInternal->setChecked( mySettings.value( prefix + "internal", false ).toBool() );
|
||||
tmpStr = mySettings.value( prefix + "format", "gtiff" ).toString();
|
||||
if ( tmpStr == "internal" )
|
||||
cboPyramidsFormat->setCurrentIndex( 0 );
|
||||
else if ( tmpStr == "erdas" )
|
||||
cboPyramidsFormat->setCurrentIndex( 2 );
|
||||
cbxPyramidsFormat->setCurrentIndex( 1 );
|
||||
else if ( tmpStr == "external_erdas" )
|
||||
cbxPyramidsFormat->setCurrentIndex( 2 );
|
||||
else
|
||||
cboPyramidsFormat->setCurrentIndex( 1 );
|
||||
cboResamplingMethod->setCurrentIndex( cboResamplingMethod->findText(
|
||||
mySettings.value( prefix + "resampling", "Average" ).toString() ) );
|
||||
lePyramidsLevels->setText( mySettings.value( prefix + "overviewStr", "bla" ).toString() );
|
||||
cbxPyramidsFormat->setCurrentIndex( 0 );
|
||||
|
||||
// initialize resampling methods
|
||||
cboResamplingMethod->clear();
|
||||
foreach ( QString method, QgsRasterDataProvider::pyramidResamplingMethods( mProvider ) )
|
||||
cboResamplingMethod->addItem( method );
|
||||
cboResamplingMethod->setCurrentIndex( cboResamplingMethod->findText(
|
||||
mySettings.value( prefix + "resampling", "Average" ).toString() ) );
|
||||
|
||||
// validate string, only space-separated positive integers are allowed
|
||||
lePyramidsLevels->setValidator( new QRegExpValidator( QRegExp( "(\\d*)(\\s\\d*)*" ), lePyramidsLevels ) );
|
||||
connect( lePyramidsLevels, SIGNAL( editingFinished() ),
|
||||
this, SLOT( setOverviewList() ) );
|
||||
|
||||
// overview list
|
||||
if ( mOverviewCheckBoxes.isEmpty() )
|
||||
@ -74,48 +83,57 @@ void QgsRasterPyramidsOptionsWidget::updateUi()
|
||||
QList<int> overviewList;
|
||||
overviewList << 2 << 4 << 8 << 16 << 32 << 64;
|
||||
mOverviewCheckBoxes.clear();
|
||||
foreach( int i, overviewList )
|
||||
foreach ( int i, overviewList )
|
||||
{
|
||||
mOverviewCheckBoxes[ i ] = new QCheckBox( QString::number( i ), this );
|
||||
layoutPyramidLevels->addWidget( mOverviewCheckBoxes[ i ] );
|
||||
connect( mOverviewCheckBoxes[ i ], SIGNAL( toggled( bool ) ),
|
||||
this, SLOT( setOverviewList() ) );
|
||||
layoutPyramidsLevels->addWidget( mOverviewCheckBoxes[ i ] );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach( int i, mOverviewCheckBoxes.keys() )
|
||||
foreach ( int i, mOverviewCheckBoxes.keys() )
|
||||
mOverviewCheckBoxes[ i ]->setChecked( false );
|
||||
}
|
||||
tmpStr = mySettings.value( prefix + "overviewList", "" ).toString();
|
||||
foreach( QString lev, tmpStr.split( " ", QString::SkipEmptyParts ) )
|
||||
foreach ( QString lev, tmpStr.split( " ", QString::SkipEmptyParts ) )
|
||||
{
|
||||
if( mOverviewCheckBoxes.contains( lev.toInt() ) )
|
||||
mOverviewCheckBoxes[ lev.toInt() ]->setChecked( true );
|
||||
if ( mOverviewCheckBoxes.contains( lev.toInt() ) )
|
||||
mOverviewCheckBoxes[ lev.toInt()]->setChecked( true );
|
||||
}
|
||||
on_lePyramidsLevels_editingFinished();
|
||||
|
||||
setOverviewList();
|
||||
|
||||
mPyramidsOptionsWidget->updateProfiles();
|
||||
}
|
||||
|
||||
|
||||
|
||||
QString QgsRasterPyramidsOptionsWidget::resamplingMethod() const
|
||||
{
|
||||
return cboResamplingMethod->currentText().trimmed();
|
||||
}
|
||||
|
||||
void QgsRasterPyramidsOptionsWidget::apply()
|
||||
{
|
||||
QSettings mySettings;
|
||||
QString prefix = mProvider + "/driverOptions/_pyramids/";
|
||||
QString tmpStr;
|
||||
|
||||
|
||||
// mySettings.setValue( prefix + "internal", cbxPyramidsInternal->isChecked() );
|
||||
if ( cboPyramidsFormat->currentIndex() == 0 )
|
||||
if ( cbxPyramidsFormat->currentIndex() == 1 )
|
||||
tmpStr = "internal";
|
||||
else if ( cboPyramidsFormat->currentIndex() == 2 )
|
||||
tmpStr = "erdas";
|
||||
else
|
||||
tmpStr = "tiff";
|
||||
else if ( cbxPyramidsFormat->currentIndex() == 2 )
|
||||
tmpStr = "external_erdas";
|
||||
else
|
||||
tmpStr = "external";
|
||||
mySettings.setValue( prefix + "format", tmpStr );
|
||||
mySettings.setValue( prefix + "resampling", cboResamplingMethod->currentText().trimmed() );
|
||||
mySettings.setValue( prefix + "overviewStr", lePyramidsLevels->text().trimmed() );
|
||||
|
||||
// overview list
|
||||
tmpStr = "";
|
||||
foreach( int i, mOverviewCheckBoxes.keys() )
|
||||
foreach ( int i, mOverviewCheckBoxes.keys() )
|
||||
{
|
||||
if ( mOverviewCheckBoxes[ i ]->isChecked() )
|
||||
tmpStr += QString::number( i ) + " ";
|
||||
@ -125,29 +143,51 @@ void QgsRasterPyramidsOptionsWidget::apply()
|
||||
mPyramidsOptionsWidget->apply();
|
||||
}
|
||||
|
||||
void QgsRasterPyramidsOptionsWidget::on_lePyramidsLevels_editingFinished()
|
||||
void QgsRasterPyramidsOptionsWidget::checkAllLevels( bool checked )
|
||||
{
|
||||
// validate string, only space-separated positive integers are allowed
|
||||
// should we also validate that numbers are increasing?
|
||||
QString tmpStr;
|
||||
int tmpInt;
|
||||
foreach( QString lev, lePyramidsLevels->text().trimmed().split( " ", QString::SkipEmptyParts ) )
|
||||
{
|
||||
tmpInt = lev.toInt();
|
||||
if ( tmpInt > 0 )
|
||||
tmpStr += QString::number( tmpInt ) + " ";
|
||||
}
|
||||
lePyramidsLevels->setText( tmpStr.trimmed() );
|
||||
foreach ( int i, mOverviewCheckBoxes.keys() )
|
||||
mOverviewCheckBoxes[ i ]->setChecked( checked );
|
||||
}
|
||||
|
||||
// if text is non-empty, disable checkboxes
|
||||
if ( lePyramidsLevels->text() == "" )
|
||||
void QgsRasterPyramidsOptionsWidget::on_cbxPyramidsLevelsCustom_toggled( bool toggled )
|
||||
{
|
||||
// if toggled, disable checkboxes and enable line edit
|
||||
lePyramidsLevels->setEnabled( toggled );
|
||||
foreach ( int i, mOverviewCheckBoxes.keys() )
|
||||
mOverviewCheckBoxes[ i ]->setEnabled( ! toggled );
|
||||
setOverviewList();
|
||||
}
|
||||
|
||||
void QgsRasterPyramidsOptionsWidget::setOverviewList()
|
||||
{
|
||||
QgsDebugMsg( "Entered" );
|
||||
|
||||
mOverviewList.clear();
|
||||
|
||||
// if custum levels is toggled, get selection from line edit
|
||||
if ( cbxPyramidsLevelsCustom->isChecked() )
|
||||
{
|
||||
foreach( int i, mOverviewCheckBoxes.keys() )
|
||||
mOverviewCheckBoxes[ i ]->setEnabled( true );
|
||||
// should we also validate that numbers are increasing?
|
||||
foreach ( QString lev, lePyramidsLevels->text().trimmed().split( " ", QString::SkipEmptyParts ) )
|
||||
{
|
||||
QgsDebugMsg( "lev= " + lev );
|
||||
int tmpInt = lev.toInt();
|
||||
if ( tmpInt > 0 )
|
||||
{
|
||||
QgsDebugMsg( "tmpInt= " + QString::number( tmpInt ) );
|
||||
// if number is valid, add to overview list
|
||||
mOverviewList << tmpInt;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach( int i, mOverviewCheckBoxes.keys() )
|
||||
mOverviewCheckBoxes[ i ]->setEnabled( false );
|
||||
foreach ( int i, mOverviewCheckBoxes.keys() )
|
||||
{
|
||||
if ( mOverviewCheckBoxes[ i ]->isChecked() )
|
||||
mOverviewList << i;
|
||||
}
|
||||
}
|
||||
|
||||
emit overviewListChanged();
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
#define QGSRASTERPYRAMIDSOPTIONSWIDGET_H
|
||||
|
||||
#include "ui_qgsrasterpyramidsoptionswidgetbase.h"
|
||||
#include "qgsrasterdataprovider.h"
|
||||
|
||||
class QCheckBox;
|
||||
|
||||
@ -32,31 +33,38 @@ class GUI_EXPORT QgsRasterPyramidsOptionsWidget: public QWidget,
|
||||
|
||||
public:
|
||||
|
||||
QgsRasterPyramidsOptionsWidget( QWidget* parent = 0, QString provider = "gdal" );
|
||||
QgsRasterPyramidsOptionsWidget( QWidget* parent = 0, QString provider = "gdal" );
|
||||
~QgsRasterPyramidsOptionsWidget();
|
||||
|
||||
void setProvider( QString provider );
|
||||
QStringList createOptions() const { return mPyramidsOptionsWidget->options(); }
|
||||
QgsRasterFormatSaveOptionsWidget* createOptionsWidget() { return mPyramidsOptionsWidget; }
|
||||
const QList<int> overviewList() const { return mOverviewList; }
|
||||
QgsRasterDataProvider::RasterPyramidsFormat pyramidsFormat() const
|
||||
{ return ( QgsRasterDataProvider::RasterPyramidsFormat ) cbxPyramidsFormat->currentIndex(); }
|
||||
QString resamplingMethod() const;
|
||||
|
||||
public slots:
|
||||
|
||||
void apply();
|
||||
void checkAllLevels( bool checked );
|
||||
|
||||
private slots:
|
||||
|
||||
void on_lePyramidsLevels_editingFinished();
|
||||
void on_cboPyramidsFormat_currentIndexChanged( int index )
|
||||
void on_cbxPyramidsLevelsCustom_toggled( bool toggled );
|
||||
void on_cbxPyramidsFormat_currentIndexChanged( int index )
|
||||
{ mPyramidsOptionsWidget->setEnabled( index != 2 ); }
|
||||
void setOverviewList();
|
||||
|
||||
signals:
|
||||
void overviewListChanged();
|
||||
|
||||
private:
|
||||
|
||||
void updateUi();
|
||||
|
||||
|
||||
QString mProvider;
|
||||
bool mInternal;
|
||||
QString mResamplingMethod;
|
||||
QList<int> mOverviewList;
|
||||
QList< int > mOverviewList;
|
||||
QMap< int, QCheckBox* > mOverviewCheckBoxes;
|
||||
};
|
||||
|
||||
|
@ -82,6 +82,7 @@ int CPL_STDCALL progressCallback( double dfComplete,
|
||||
if ( floor( dfLastComplete*10 ) != floor( dfComplete*10 ) )
|
||||
{
|
||||
mypProvider->emitProgress( prog->type, dfComplete * 100, QString( pszMessage ) );
|
||||
mypProvider->emitProgressUpdate( dfComplete * 100 );
|
||||
}
|
||||
dfLastComplete = dfComplete;
|
||||
|
||||
@ -1294,7 +1295,7 @@ QgsRasterHistogram QgsGdalProvider::histogram( int theBandNo,
|
||||
* @return null string on success, otherwise a string specifying error
|
||||
*/
|
||||
QString QgsGdalProvider::buildPyramids( QList<QgsRasterPyramid> const & theRasterPyramidList,
|
||||
QString const & theResamplingMethod, bool theTryInternalFlag )
|
||||
QString const & theResamplingMethod, RasterPyramidsFormat theFormat )
|
||||
{
|
||||
//TODO: Consider making theRasterPyramidList modifyable by this method to indicate if the pyramid exists after build attempt
|
||||
//without requiring the user to rebuild the pyramid list to get the updated infomation
|
||||
@ -1324,7 +1325,8 @@ QString QgsGdalProvider::buildPyramids( QList<QgsRasterPyramid> const & theRaste
|
||||
return "ERROR_VIRTUAL";
|
||||
}
|
||||
|
||||
if ( theTryInternalFlag )
|
||||
// check if building internally
|
||||
if ( theFormat == PyramidsInternal )
|
||||
{
|
||||
// libtiff < 4.0 has a bug that prevents safe building of overviews on JPEG compressed files
|
||||
// we detect libtiff < 4.0 by checking that BIGTIFF is not in the creation options of the GTiff driver
|
||||
@ -1340,26 +1342,37 @@ QString QgsGdalProvider::buildPyramids( QList<QgsRasterPyramid> const & theRaste
|
||||
}
|
||||
}
|
||||
|
||||
//close the gdal dataset and reopen it in read / write mode
|
||||
GDALClose( mGdalDataset );
|
||||
//mGdalBaseDataset = GDALOpen( QFile::encodeName( dataSourceUri() ).constData(), GA_Update );
|
||||
mGdalBaseDataset = GDALOpen( TO8F( dataSourceUri() ), GA_Update );
|
||||
|
||||
// if the dataset couldn't be opened in read / write mode, tell the user
|
||||
if ( !mGdalBaseDataset )
|
||||
//if needed close the gdal dataset and reopen it in read / write mode
|
||||
if ( GDALGetAccess( mGdalDataset ) == GA_ReadOnly )
|
||||
{
|
||||
//mGdalBaseDataset = GDALOpen( QFile::encodeName( mDataSource ).constData(), GA_ReadOnly );
|
||||
//mGdalBaseDataset = GDALOpen( QFile::encodeName( dataSourceUri()).constData(), GA_ReadOnly );
|
||||
mGdalBaseDataset = GDALOpen( TO8F( dataSourceUri() ), GA_ReadOnly );
|
||||
//Since we are not a virtual warped dataset, mGdalDataSet and mGdalBaseDataset are supposed to be the same
|
||||
mGdalDataset = mGdalBaseDataset;
|
||||
return "ERROR_WRITE_FORMAT";
|
||||
GDALClose( mGdalDataset );
|
||||
//mGdalBaseDataset = GDALOpen( QFile::encodeName( dataSourceUri() ).constData(), GA_Update );
|
||||
|
||||
mGdalBaseDataset = GDALOpen( TO8F( dataSourceUri() ), GA_Update );
|
||||
|
||||
// if the dataset couldn't be opened in read / write mode, tell the user
|
||||
if ( !mGdalBaseDataset )
|
||||
{
|
||||
//mGdalBaseDataset = GDALOpen( QFile::encodeName( mDataSource ).constData(), GA_ReadOnly );
|
||||
//mGdalBaseDataset = GDALOpen( QFile::encodeName( dataSourceUri()).constData(), GA_ReadOnly );
|
||||
mGdalBaseDataset = GDALOpen( TO8F( dataSourceUri() ), GA_ReadOnly );
|
||||
//Since we are not a virtual warped dataset, mGdalDataSet and mGdalBaseDataset are supposed to be the same
|
||||
mGdalDataset = mGdalBaseDataset;
|
||||
return "ERROR_WRITE_FORMAT";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// are we using Erdas Imagine external overviews?
|
||||
const char* myConfigUseRRD = CPLGetConfigOption( "USE_RRD", "NO" );
|
||||
if ( theFormat == PyramidsErdas )
|
||||
CPLSetConfigOption( "USE_RRD", "YES" );
|
||||
else
|
||||
CPLSetConfigOption( "USE_RRD", "NO" );
|
||||
|
||||
//
|
||||
// Iterate through the Raster Layer Pyramid Vector, building any pyramid
|
||||
// marked as exists in eaxh RasterPyramid struct.
|
||||
// marked as exists in each RasterPyramid struct.
|
||||
//
|
||||
CPLErr myError; //in case anything fails
|
||||
int myCount = 1;
|
||||
@ -1380,7 +1393,8 @@ QString QgsGdalProvider::buildPyramids( QList<QgsRasterPyramid> const & theRaste
|
||||
//emit drawingProgress( myCount, myTotal );
|
||||
int myOverviewLevelsArray[1] = { myRasterPyramidIterator->level };
|
||||
/* From : http://remotesensing.org/gdal/classGDALDataset.html#a23
|
||||
* pszResampling : one of "NEAREST", "AVERAGE" or "MODE" controlling the downsampling method applied.
|
||||
* pszResampling : one of "NEAREST", "GAUSS", "CUBIC", "AVERAGE", "MODE", "AVERAGE_MAGPHASE" or "NONE"
|
||||
* controlling the downsampling method applied.
|
||||
* nOverviews : number of overviews to build.
|
||||
* panOverviewList : the list of overview decimation factors to build.
|
||||
* nBand : number of bands to build overviews for in panBandList. Build for all bands if this is 0.
|
||||
@ -1391,31 +1405,35 @@ QString QgsGdalProvider::buildPyramids( QList<QgsRasterPyramid> const & theRaste
|
||||
//build the pyramid and show progress to console
|
||||
try
|
||||
{
|
||||
|
||||
//build the pyramid and show progress to console
|
||||
//NOTE this (magphase) is disabled in the gui since it tends
|
||||
//to create corrupted images. The images can be repaired
|
||||
//by running one of the other resampling strategies below.
|
||||
//see ticket #284
|
||||
QgsGdalProgress myProg;
|
||||
myProg.type = ProgressPyramids;
|
||||
myProg.provider = this;
|
||||
if ( theResamplingMethod == tr( "Average Magphase" ) )
|
||||
{
|
||||
myError = GDALBuildOverviews( mGdalBaseDataset, "MODE", 1, myOverviewLevelsArray, 0, NULL,
|
||||
progressCallback, &myProg ); //this is the arg for the gdal progress callback
|
||||
}
|
||||
const char* theMethod;
|
||||
if ( theResamplingMethod == tr( "Gauss" ) )
|
||||
theMethod = "GAUSS";
|
||||
else if ( theResamplingMethod == tr( "Cubic" ) )
|
||||
theMethod = "CUBIC";
|
||||
else if ( theResamplingMethod == tr( "Average" ) )
|
||||
|
||||
{
|
||||
myError = GDALBuildOverviews( mGdalBaseDataset, "AVERAGE", 1, myOverviewLevelsArray, 0, NULL,
|
||||
progressCallback, &myProg ); //this is the arg for the gdal progress callback
|
||||
}
|
||||
theMethod = "AVERAGE";
|
||||
else if ( theResamplingMethod == tr( "Mode" ) )
|
||||
theMethod = "MODE";
|
||||
//NOTE magphase is disabled in the gui since it tends
|
||||
//to create corrupted images. The images can be repaired
|
||||
//by running one of the other resampling strategies below.
|
||||
//see ticket #284
|
||||
// else if ( theResamplingMethod == tr( "Average Magphase" ) )
|
||||
// theMethod = "AVERAGE_MAGPHASE";
|
||||
else if ( theResamplingMethod == tr( "None" ) )
|
||||
theMethod = "NONE";
|
||||
else // fall back to nearest neighbor
|
||||
{
|
||||
myError = GDALBuildOverviews( mGdalBaseDataset, "NEAREST", 1, myOverviewLevelsArray, 0, NULL,
|
||||
progressCallback, &myProg ); //this is the arg for the gdal progress callback
|
||||
}
|
||||
theMethod = "NEAREST";
|
||||
QgsDebugMsg( QString( "building overview at level %1 using resampling method %2"
|
||||
).arg( myRasterPyramidIterator->level ).arg( theMethod ) );
|
||||
// TODO - it would be more efficient to do it once instead of for each level
|
||||
myError = GDALBuildOverviews( mGdalBaseDataset, theMethod, 1,
|
||||
myOverviewLevelsArray, 0, NULL,
|
||||
progressCallback, &myProg ); //this is the arg for the gdal progress callback
|
||||
|
||||
if ( myError == CE_Failure || CPLGetLastErrorNo() == CPLE_NotSupported )
|
||||
{
|
||||
@ -1429,6 +1447,8 @@ QString QgsGdalProvider::buildPyramids( QList<QgsRasterPyramid> const & theRaste
|
||||
mGdalDataset = mGdalBaseDataset;
|
||||
|
||||
//emit drawingProgress( 0, 0 );
|
||||
// restore former USE_RRD config (Erdas)
|
||||
CPLSetConfigOption( "USE_RRD", myConfigUseRRD );
|
||||
return "FAILED_NOT_SUPPORTED";
|
||||
}
|
||||
else
|
||||
@ -1446,8 +1466,11 @@ QString QgsGdalProvider::buildPyramids( QList<QgsRasterPyramid> const & theRaste
|
||||
}
|
||||
}
|
||||
|
||||
// restore former USE_RRD config (Erdas)
|
||||
CPLSetConfigOption( "USE_RRD", myConfigUseRRD );
|
||||
|
||||
QgsDebugMsg( "Pyramid overviews built" );
|
||||
if ( theTryInternalFlag )
|
||||
if ( theFormat == PyramidsInternal )
|
||||
{
|
||||
//close the gdal dataset and reopen it in read only mode
|
||||
GDALClose( mGdalBaseDataset );
|
||||
@ -1460,6 +1483,7 @@ QString QgsGdalProvider::buildPyramids( QList<QgsRasterPyramid> const & theRaste
|
||||
return NULL; // returning null on success
|
||||
}
|
||||
|
||||
#if 0
|
||||
QList<QgsRasterPyramid> QgsGdalProvider::buildPyramidList()
|
||||
{
|
||||
//
|
||||
@ -1535,6 +1559,95 @@ QList<QgsRasterPyramid> QgsGdalProvider::buildPyramidList()
|
||||
|
||||
return mPyramidList;
|
||||
}
|
||||
#endif
|
||||
|
||||
QList<QgsRasterPyramid> QgsGdalProvider::buildPyramidList( QList<int> overviewList )
|
||||
{
|
||||
int myWidth = mWidth;
|
||||
int myHeight = mHeight;
|
||||
GDALRasterBandH myGDALBand = GDALGetRasterBand( mGdalDataset, 1 ); //just use the first band
|
||||
|
||||
mPyramidList.clear();
|
||||
|
||||
// if overviewList is empty (default) build the pyramid list
|
||||
if ( overviewList.isEmpty() )
|
||||
{
|
||||
int myDivisor = 2;
|
||||
|
||||
QgsDebugMsg( "Building initial pyramid list" );
|
||||
|
||||
while (( myWidth / myDivisor > 32 ) && (( myHeight / myDivisor ) > 32 ) )
|
||||
{
|
||||
overviewList.append( myDivisor );
|
||||
//sqare the divisor each step
|
||||
myDivisor = ( myDivisor * 2 );
|
||||
}
|
||||
}
|
||||
|
||||
// loop over pyramid list
|
||||
foreach ( int myDivisor, overviewList )
|
||||
{
|
||||
//
|
||||
// First we build up a list of potential pyramid layers
|
||||
//
|
||||
|
||||
QgsRasterPyramid myRasterPyramid;
|
||||
myRasterPyramid.level = myDivisor;
|
||||
myRasterPyramid.xDim = ( int )( 0.5 + ( myWidth / ( double )myDivisor ) );
|
||||
myRasterPyramid.yDim = ( int )( 0.5 + ( myHeight / ( double )myDivisor ) );
|
||||
myRasterPyramid.exists = false;
|
||||
|
||||
QgsDebugMsg( QString( "Pyramid %1 xDim %2 yDim %3" ).arg( myRasterPyramid.level ).arg( myRasterPyramid.xDim ).arg( myRasterPyramid.yDim ) );
|
||||
|
||||
//
|
||||
// Now we check if it actually exists in the raster layer
|
||||
// and also adjust the dimensions if the dimensions calculated
|
||||
// above are only a near match.
|
||||
//
|
||||
const int myNearMatchLimit = 5;
|
||||
if ( GDALGetOverviewCount( myGDALBand ) > 0 )
|
||||
{
|
||||
int myOverviewCount;
|
||||
for ( myOverviewCount = 0;
|
||||
myOverviewCount < GDALGetOverviewCount( myGDALBand );
|
||||
++myOverviewCount )
|
||||
{
|
||||
GDALRasterBandH myOverview;
|
||||
myOverview = GDALGetOverview( myGDALBand, myOverviewCount );
|
||||
int myOverviewXDim = GDALGetRasterBandXSize( myOverview );
|
||||
int myOverviewYDim = GDALGetRasterBandYSize( myOverview );
|
||||
//
|
||||
// here is where we check if its a near match:
|
||||
// we will see if its within 5 cells either side of
|
||||
//
|
||||
QgsDebugMsg( "Checking whether " + QString::number( myRasterPyramid.xDim ) + " x " +
|
||||
QString::number( myRasterPyramid.yDim ) + " matches " +
|
||||
QString::number( myOverviewXDim ) + " x " + QString::number( myOverviewYDim ) );
|
||||
|
||||
|
||||
if (( myOverviewXDim <= ( myRasterPyramid.xDim + myNearMatchLimit ) ) &&
|
||||
( myOverviewXDim >= ( myRasterPyramid.xDim - myNearMatchLimit ) ) &&
|
||||
( myOverviewYDim <= ( myRasterPyramid.yDim + myNearMatchLimit ) ) &&
|
||||
( myOverviewYDim >= ( myRasterPyramid.yDim - myNearMatchLimit ) ) )
|
||||
{
|
||||
//right we have a match so adjust the a / y before they get added to the list
|
||||
myRasterPyramid.xDim = myOverviewXDim;
|
||||
myRasterPyramid.yDim = myOverviewYDim;
|
||||
myRasterPyramid.exists = true;
|
||||
QgsDebugMsg( ".....YES!" );
|
||||
}
|
||||
else
|
||||
{
|
||||
//no match
|
||||
QgsDebugMsg( ".....no." );
|
||||
}
|
||||
}
|
||||
}
|
||||
mPyramidList.append( myRasterPyramid );
|
||||
}
|
||||
|
||||
return mPyramidList;
|
||||
}
|
||||
|
||||
QStringList QgsGdalProvider::subLayers() const
|
||||
{
|
||||
@ -1546,6 +1659,11 @@ void QgsGdalProvider::emitProgress( int theType, double theProgress, QString the
|
||||
emit progress( theType, theProgress, theMessage );
|
||||
}
|
||||
|
||||
void QgsGdalProvider::emitProgressUpdate( int theProgress )
|
||||
{
|
||||
emit progressUpdate( theProgress );
|
||||
}
|
||||
|
||||
/**
|
||||
* Class factory to return a pointer to a newly created
|
||||
* QgsGdalProvider object
|
||||
@ -2221,6 +2339,11 @@ bool QgsGdalProvider::create( const QString& format, int nBands,
|
||||
return false;
|
||||
}
|
||||
|
||||
QString tmpStr = "create options:";
|
||||
foreach ( QString option, createOptions )
|
||||
tmpStr += " " + option;
|
||||
QgsDebugMsg( tmpStr );
|
||||
|
||||
//create dataset
|
||||
char **papszOptions = papszFromStringList( createOptions );
|
||||
GDALDatasetH dataset = GDALCreate( driver, dataSourceUri().toLocal8Bit().data(), width, height, nBands, ( GDALDataType )type, papszOptions );
|
||||
|
@ -252,14 +252,15 @@ class QgsGdalProvider : public QgsRasterDataProvider, QgsGdalProviderBase
|
||||
|
||||
QString buildPyramids( const QList<QgsRasterPyramid> &,
|
||||
const QString & theResamplingMethod = "NEAREST",
|
||||
bool theTryInternalFlag = false );
|
||||
QList<QgsRasterPyramid> buildPyramidList();
|
||||
RasterPyramidsFormat theFormat = PyramidsGTiff );
|
||||
QList<QgsRasterPyramid> buildPyramidList( QList<int> overviewList = QList<int>() );
|
||||
|
||||
/** \brief Close data set and release related data */
|
||||
void closeDataset();
|
||||
|
||||
/** Emit a signal to notify of the progress event. */
|
||||
void emitProgress( int theType, double theProgress, QString theMessage );
|
||||
void emitProgressUpdate( int theProgress );
|
||||
|
||||
static QMap<QString, QString> supportedMimes();
|
||||
|
||||
|
@ -799,66 +799,6 @@
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Notes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3" colspan="2">
|
||||
<widget class="QLabel" name="textLabel5">
|
||||
<property name="text">
|
||||
<string>Pyramid resolutions</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="3">
|
||||
<widget class="QTextEdit" name="tePyramidDescription">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>5</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="html">
|
||||
<string></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3" colspan="2">
|
||||
<widget class="QListWidget" name="lbxPyramidResolutions">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>32767</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::MultiSelection</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="5">
|
||||
<widget class="QCheckBox" name="cbxInternalPyramids">
|
||||
<property name="text">
|
||||
<string>Build pyramids internally if possible</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="textLabel4_2">
|
||||
<property name="text">
|
||||
<string>Resampling method</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="cboResamplingMethod">
|
||||
<item>
|
||||
@ -890,6 +830,95 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Notes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3" colspan="2">
|
||||
<widget class="QLabel" name="textLabel5">
|
||||
<property name="text">
|
||||
<string>Pyramid resolutions</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="3">
|
||||
<widget class="QTextEdit" name="tePyramidDescription">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>5</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="html">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Cantarell'; font-size:11pt; font-weight:400; font-style:normal;">
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3" colspan="2">
|
||||
<widget class="QListWidget" name="lbxPyramidResolutions">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>32767</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::MultiSelection</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="textLabel4_2">
|
||||
<property name="text">
|
||||
<string>Resampling method</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Overview format</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="cbxPyramidsFormat">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>External</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Internal (if possible)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>External (Erdas Imagine)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tabPageHistogram">
|
||||
@ -919,9 +948,6 @@
|
||||
<attribute name="headerStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="headerStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string notr="true">1</string>
|
||||
|
@ -6,7 +6,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>550</width>
|
||||
<width>575</width>
|
||||
<height>580</height>
|
||||
</rect>
|
||||
</property>
|
||||
@ -29,9 +29,9 @@
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>-239</y>
|
||||
<width>514</width>
|
||||
<height>784</height>
|
||||
<y>-293</y>
|
||||
<width>539</width>
|
||||
<height>831</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
@ -278,7 +278,7 @@
|
||||
<widget class="QPushButton" name="mOriginalExtentButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>140</width>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
@ -307,7 +307,7 @@
|
||||
<widget class="QPushButton" name="mCurrentExtentButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>140</width>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
@ -452,6 +452,9 @@
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="mMaximumSizeXLabel">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Maximum number of columns in one tile.</string>
|
||||
</property>
|
||||
@ -462,6 +465,9 @@
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="mMaximumSizeXLineEdit">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Maximum number of columns in one tile.</string>
|
||||
</property>
|
||||
@ -469,6 +475,9 @@
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="mMaximumSizeYLabel">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Maximum number of rows in one tile.</string>
|
||||
</property>
|
||||
@ -479,6 +488,9 @@
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="mMaximumSizeYLineEdit">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Maximum number of rows in one tile.</string>
|
||||
</property>
|
||||
@ -486,6 +498,9 @@
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="mTileModeCheckBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Create VRT</string>
|
||||
</property>
|
||||
@ -554,7 +569,7 @@
|
||||
<item row="2" column="0">
|
||||
<widget class="QToolButton" name="mLoadTransparentNoDataToolButton">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Load user defined fully transparent (100%) values </string>
|
||||
@ -604,7 +619,7 @@
|
||||
<item>
|
||||
<widget class="QgsCollapsibleGroupBox" name="mPyramidsGroupBox">
|
||||
<property name="title">
|
||||
<string>Pyramids (not yet implemented)</string>
|
||||
<string>Pyramids</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
@ -612,19 +627,100 @@
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="cbxPyramidsBuild">
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="3" column="0">
|
||||
<widget class="QgsRasterPyramidsOptionsWidget" name="mPyramidsOptionsWidget" native="true">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Build pyramids</string>
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QgsRasterPyramidsOptionsWidget" name="mPyramidsOptionsWidget" native="true"/>
|
||||
<item row="0" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButton">
|
||||
<property name="text">
|
||||
<string>No pyramids</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">mPyramidsButtonGroup</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButton_2">
|
||||
<property name="text">
|
||||
<string>Build pyramids</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">mPyramidsButtonGroup</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButton_3">
|
||||
<property name="text">
|
||||
<string>Use existing</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">mPyramidsButtonGroup</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_9">
|
||||
<item>
|
||||
<widget class="QLabel" name="mPyramidResolutionsLabel">
|
||||
<property name="text">
|
||||
<string>Resolutions</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>10</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="mPyramidResolutionsLineEdit">
|
||||
<property name="toolTip">
|
||||
<string>Pyramid resolutions corresponding to levels given</string>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="frame">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
@ -700,4 +796,7 @@
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
<buttongroups>
|
||||
<buttongroup name="mPyramidsButtonGroup"/>
|
||||
</buttongroups>
|
||||
</ui>
|
||||
|
@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>351</width>
|
||||
<height>195</height>
|
||||
<width>366</width>
|
||||
<height>171</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -17,48 +17,15 @@
|
||||
<property name="margin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<item row="3" column="2">
|
||||
<widget class="QLineEdit" name="lePyramidsLevels">
|
||||
<property name="toolTip">
|
||||
<string>Insert positive integer values separated by spaces</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="3">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="cbxPyramidsLevelsCustom">
|
||||
<property name="text">
|
||||
<string>Create Options</string>
|
||||
<string>Custom levels</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0" colspan="3">
|
||||
<widget class="QgsRasterFormatSaveOptionsWidget" name="mPyramidsOptionsWidget" native="true"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Overview format</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>10</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QComboBox" name="cboPyramidsFormat">
|
||||
<widget class="QComboBox" name="cbxPyramidsFormat">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
@ -67,12 +34,12 @@
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Internal (if possible)</string>
|
||||
<string>External</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>External (GTiff)</string>
|
||||
<string>Internal (if possible)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
@ -82,44 +49,10 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QLineEdit" name="lePyramidResolutions">
|
||||
<item row="3" column="2">
|
||||
<widget class="QLineEdit" name="lePyramidsLevels">
|
||||
<property name="toolTip">
|
||||
<string>Pyramid resolutions corresponding to levels given</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>to be done</string>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="3">
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Custom levels</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Resolutions</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="textLabel4_2">
|
||||
<property name="text">
|
||||
<string>Resampling method</string>
|
||||
<string>Insert positive integer values separated by spaces</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -137,6 +70,23 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<layout class="QHBoxLayout" name="layoutPyramidsLevels"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Overview format</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="3">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Create Options</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
@ -144,8 +94,38 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<layout class="QHBoxLayout" name="layoutPyramidLevels"/>
|
||||
<item row="6" column="0" colspan="3">
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="textLabel4_2">
|
||||
<property name="text">
|
||||
<string>Resampling method</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0" colspan="3">
|
||||
<widget class="QgsRasterFormatSaveOptionsWidget" name="mPyramidsOptionsWidget" native="true"/>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>10</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <qgsrasterlayer.h>
|
||||
#include <qgsrasterpyramid.h>
|
||||
#include <qgsrasterbandstats.h>
|
||||
#include <qgsrasterpyramid.h>
|
||||
#include <qgsmaplayerregistry.h>
|
||||
#include <qgsapplication.h>
|
||||
#include <qgsmaprenderer.h>
|
||||
@ -339,24 +340,21 @@ void TestQgsRasterLayer::buildExternalOverviews()
|
||||
// Ok now we can go on to test
|
||||
//
|
||||
|
||||
bool myInternalFlag = false;
|
||||
QgsRasterLayer::RasterPyramidList myPyramidList = mypLayer->buildPyramidList();
|
||||
QgsRasterDataProvider::RasterPyramidsFormat myFormatFlag = QgsRasterDataProvider::PyramidsGTiff;
|
||||
QList< QgsRasterPyramid > myPyramidList = mypLayer->dataProvider()->buildPyramidList();
|
||||
for ( int myCounterInt = 0; myCounterInt < myPyramidList.count(); myCounterInt++ )
|
||||
{
|
||||
//mark to be pyramided
|
||||
myPyramidList[myCounterInt].build = true;
|
||||
}
|
||||
//now actually make the pyramids
|
||||
QString myResult = mypLayer->buildPyramids(
|
||||
myPyramidList,
|
||||
"NEAREST",
|
||||
myInternalFlag
|
||||
);
|
||||
QString myResult =
|
||||
mypLayer->dataProvider()->buildPyramids( myPyramidList, "NEAREST", myFormatFlag );
|
||||
qDebug( "%s", myResult.toLocal8Bit().constData() );
|
||||
//
|
||||
// Lets verify we have pyramids now...
|
||||
//
|
||||
myPyramidList = mypLayer->buildPyramidList();
|
||||
myPyramidList = mypLayer->dataProvider()->buildPyramidList();
|
||||
for ( int myCounterInt = 0; myCounterInt < myPyramidList.count(); myCounterInt++ )
|
||||
{
|
||||
//mark to be pyramided
|
||||
|
Loading…
x
Reference in New Issue
Block a user