Skip to content
Permalink
Browse files

Possibility to set resampling modes differently for zoomed-in and zoo…

…med-out
  • Loading branch information
mhugent committed Jan 19, 2012
1 parent 2883fbc commit 66416524c67eaa7d40fe55fed35801c54839297b
@@ -27,6 +27,7 @@
#include "qgscubicrasterresampler.h"
#include "qgscoordinatetransform.h"
#include "qgsrasterlayerproperties.h"
#include "qgsrasterrenderer.h"
#include "qgsgenericprojectionselector.h"
#include "qgsproject.h"
#include "qgsrasterbandstats.h"
@@ -288,20 +289,45 @@ QgsRasterLayerProperties::QgsRasterLayerProperties( QgsMapLayer* lyr, QgsMapCanv
tableTransparency->horizontalHeader()->setResizeMode( 1, QHeaderView::Stretch );

//resampling
const QgsRasterResampler* resampler = mRasterLayer->resampler();
if ( !resampler )
const QgsRasterRenderer* renderer = mRasterLayer->renderer();
mZoomedInResamplingComboBox->insertItem( 0, tr( "Nearest neighbour" ) );
mZoomedInResamplingComboBox->insertItem( 1, tr( "Bilinear" ) );
mZoomedInResamplingComboBox->insertItem( 2, tr( "Cubic" ) );
mZoomedOutResamplingComboBox->insertItem( 0, tr( "Nearest neighbour" ) );
mZoomedOutResamplingComboBox->insertItem( 1, tr( "Average" ) );
//set combo boxes to current resampling types
if ( renderer )
{
mNearestNeighbourRadioButton->setChecked( true );
}
else if ( resampler->type() == "bilinear" )
{
mBilinearRadioButton->setChecked( true );
}
else if ( resampler->type() == "cubic" )
{
mCubicRadioButton->setChecked( true );
}
const QgsRasterResampler* zoomedInResampler = renderer->zoomedInResampler();
if ( zoomedInResampler )
{
if ( zoomedInResampler->type() == "bilinear" )
{
mZoomedInResamplingComboBox->setCurrentIndex( 1 );
}
else if ( zoomedInResampler->type() == "cubic" )
{
mZoomedInResamplingComboBox->setCurrentIndex( 2 );
}
}
else
{
mZoomedInResamplingComboBox->setCurrentIndex( 0 );
}

const QgsRasterResampler* zoomedOutResampler = renderer->zoomedOutResampler();
if ( zoomedOutResampler )
{
if ( zoomedOutResampler->type() == "bilinear" ) //bilinear resampler does averaging when zooming out
{
mZoomedOutResamplingComboBox->setCurrentIndex( 1 );
}
}
else
{
mZoomedOutResamplingComboBox->setCurrentIndex( 0 );
}
}
} // QgsRasterLayerProperties ctor


@@ -1370,20 +1396,6 @@ void QgsRasterLayerProperties::apply()
pixmapLegend->setScaledContents( true );
pixmapLegend->repaint();

//resampling
if ( mNearestNeighbourRadioButton->isChecked() )
{
mRasterLayer->setResampler( 0 );
}
else if ( mBilinearRadioButton->isChecked() )
{
mRasterLayer->setResampler( new QgsBilinearRasterResampler() );
}
else if ( mCubicRadioButton->isChecked() )
{
mRasterLayer->setResampler( new QgsCubicRasterResampler() );
}

//set the appropriate render style
if ( rbtnSingleBand->isChecked() )
{
@@ -1478,6 +1490,36 @@ void QgsRasterLayerProperties::apply()
//set render style finished


//resampling
QgsRasterRenderer* rasterRenderer = mRasterLayer->renderer();
QgsRasterResampler* zoomedInResampler = 0;
QString zoomedInResamplingMethod = mZoomedInResamplingComboBox->currentText();
if ( zoomedInResamplingMethod == tr( "Bilinear" ) )
{
zoomedInResampler = new QgsBilinearRasterResampler();
}
else if ( zoomedInResamplingMethod == tr( "Cubic" ) )
{
zoomedInResampler = new QgsCubicRasterResampler();
}

if ( rasterRenderer )
{
rasterRenderer->setZoomedInResampler( zoomedInResampler );
}

QgsRasterResampler* zoomedOutResampler = 0;
QString zoomedOutResamplingMethod = mZoomedOutResamplingComboBox->currentText();
if ( zoomedOutResamplingMethod == tr( "Average" ) )
{
zoomedOutResampler = new QgsBilinearRasterResampler();
}

if ( rasterRenderer )
{
rasterRenderer->setZoomedOutResampler( zoomedOutResampler );
}


//get the thumbnail for the layer
QPixmap myQPixmap = QPixmap( pixmapThumbnail->width(), pixmapThumbnail->height() );
@@ -20,8 +20,8 @@
#include <QImage>
#include <QSet>

QgsMultiBandColorRenderer::QgsMultiBandColorRenderer( QgsRasterDataProvider* provider, int redBand, int greenBand, int blueBand, QgsRasterResampler* resampler ):
QgsRasterRenderer( provider, resampler ), mRedBand( redBand ), mGreenBand( greenBand ), mBlueBand( blueBand ), mContrastEnhancement( 0 )
QgsMultiBandColorRenderer::QgsMultiBandColorRenderer( QgsRasterDataProvider* provider, int redBand, int greenBand, int blueBand ):
QgsRasterRenderer( provider ), mRedBand( redBand ), mGreenBand( greenBand ), mBlueBand( blueBand ), mContrastEnhancement( 0 )
{
}

@@ -26,7 +26,7 @@ class QgsContrastEnhancement;
class QgsMultiBandColorRenderer: public QgsRasterRenderer
{
public:
QgsMultiBandColorRenderer( QgsRasterDataProvider* provider, int redBand, int greenBand, int blueBand, QgsRasterResampler* resampler = 0 );
QgsMultiBandColorRenderer( QgsRasterDataProvider* provider, int redBand, int greenBand, int blueBand );
~QgsMultiBandColorRenderer();

void draw( QPainter* p, QgsRasterViewPort* viewPort, const QgsMapToPixel* theQgsMapToPixel );
@@ -22,8 +22,8 @@
#include <QImage>

QgsPalettedRasterRenderer::QgsPalettedRasterRenderer( QgsRasterDataProvider* provider, int bandNumber,
QColor* colorArray, int nColors, QgsRasterResampler* resampler ):
QgsRasterRenderer( provider, resampler ), mBandNumber( bandNumber ), mColors( colorArray ), mNColors( nColors )
QColor* colorArray, int nColors ):
QgsRasterRenderer( provider ), mBandNumber( bandNumber ), mColors( colorArray ), mNColors( nColors )
{
}

@@ -26,7 +26,7 @@ class QgsPalettedRasterRenderer: public QgsRasterRenderer
{
public:
/**Renderer owns color array*/
QgsPalettedRasterRenderer( QgsRasterDataProvider* provider, int bandNumber, QColor* colorArray, int nColors, QgsRasterResampler* resampler = 0 );
QgsPalettedRasterRenderer( QgsRasterDataProvider* provider, int bandNumber, QColor* colorArray, int nColors );
~QgsPalettedRasterRenderer();
void draw( QPainter* p, QgsRasterViewPort* viewPort, const QgsMapToPixel* theQgsMapToPixel );

@@ -38,8 +38,6 @@ email : tim at linfiniti.com

//renderers
#include "qgspalettedrasterrenderer.h"
#include "qgsbilinearrasterresampler.h"
#include "qgscubicrasterresampler.h"
#include "qgsmultibandcolorrenderer.h"
#include "qgssinglebandcolordatarenderer.h"
#include "qgssinglebandpseudocolorrenderer.h"
@@ -103,7 +101,6 @@ QgsRasterLayer::QgsRasterLayer(
, mWidth( std::numeric_limits<int>::max() )
, mHeight( std::numeric_limits<int>::max() )
, mInvertColor( false )
, mResampler( 0 )
, mRenderer( 0 )
{
QgsDebugMsg( "Entered" );
@@ -153,7 +150,6 @@ QgsRasterLayer::QgsRasterLayer( int dummy,
, mStyles( styles )
, mFormat( format )
, mCrs( crs )
, mResampler( 0 )
, mRenderer( 0 )
{
Q_UNUSED( dummy );
@@ -192,7 +188,6 @@ QgsRasterLayer::~QgsRasterLayer()
mValid = false;
delete mRasterShader;
delete mDataProvider;
delete mResampler;
delete mRenderer;
}

@@ -610,15 +605,14 @@ void QgsRasterLayer::setRendererForDrawingStyle( const DrawingStyle & theDrawin
renderer = new QgsPalettedRasterRenderer( mDataProvider,
grayBand,
colorArray,
itemList.size(),
mResampler );
itemList.size() );
break;
}
case MultiBandSingleBandGray:
case SingleBandGray:
{
int grayBand = bandNumber( mGrayBandName );
renderer = new QgsSingleBandGrayRenderer( mDataProvider, grayBand, mResampler );
renderer = new QgsSingleBandGrayRenderer( mDataProvider, grayBand );
if ( QgsContrastEnhancement::NoEnhancement != contrastEnhancementAlgorithm() && !mUserDefinedGrayMinimumMaximum && mStandardDeviations > 0 )
{
mGrayMinimumMaximumEstimated = false;
@@ -656,20 +650,20 @@ void QgsRasterLayer::setRendererForDrawingStyle( const DrawingStyle & theDrawin
mRasterShader->setMinimumValue( myMinimumValue );
mRasterShader->setMaximumValue( myMaximumValue );

renderer = new QgsSingleBandPseudoColorRenderer( mDataProvider, bandNo, mRasterShader, mResampler );
renderer = new QgsSingleBandPseudoColorRenderer( mDataProvider, bandNo, mRasterShader );
break;
}
case MultiBandColor:
{
int red = bandNumber( mRedBandName );
int green = bandNumber( mGreenBandName );
int blue = bandNumber( mBlueBandName );
renderer = new QgsMultiBandColorRenderer( mDataProvider, red, green, blue, mResampler );
renderer = new QgsMultiBandColorRenderer( mDataProvider, red, green, blue );
break;
}
case SingleBandColorDataStyle:
{
renderer = new QgsSingleBandColorDataRenderer( mDataProvider, bandNumber( mGrayBandName ), mResampler );
renderer = new QgsSingleBandColorDataRenderer( mDataProvider, bandNumber( mGrayBandName ) );
break;
}
default:
@@ -2802,12 +2796,6 @@ void QgsRasterLayer::setTransparentBandName( QString const & theBandName )
mTransparencyBandName = validateBandName( theBandName );
}

void QgsRasterLayer::setResampler( QgsRasterResampler* resampler )
{
delete mResampler;
mResampler = resampler;
}

void QgsRasterLayer::setRenderer( QgsRasterRenderer* renderer )
{
delete mRenderer;
@@ -2950,6 +2938,7 @@ bool QgsRasterLayer::readSymbology( const QDomNode& layer_node, QString& errorMe
Q_UNUSED( errorMessage );
QDomNode mnl = layer_node.namedItem( "rasterproperties" );

#if 0
//resampler
QDomElement resamplerElem = mnl.firstChildElement( "resampler" );
if ( !resamplerElem.isNull() )
@@ -2969,6 +2958,7 @@ bool QgsRasterLayer::readSymbology( const QDomNode& layer_node, QString& errorMe
mResampler = 0;
}
}
#endif //0

QDomNode snode = mnl.namedItem( "mDrawingStyle" );
QDomElement myElement = snode.toElement();
@@ -3287,12 +3277,14 @@ bool QgsRasterLayer::writeSymbology( QDomNode & layer_node, QDomDocument & docum
QDomElement rasterPropertiesElement = document.createElement( "rasterproperties" );
layer_node.appendChild( rasterPropertiesElement );

#if 0
// resampler
QString resamplerName = mResampler ? mResampler->type() : "nearest neighbour";
QDomElement resamplerElem = document.createElement( "resampler" );
QDomText resamplerText = document.createTextNode( resamplerName );
resamplerElem.appendChild( resamplerText );
rasterPropertiesElement.appendChild( resamplerElem );
#endif //0

QStringList sl = subLayers();
QStringList sls = mDataProvider->subLayerStyles();
@@ -51,7 +51,6 @@ class QgsRectangle;
class QgsRasterBandStats;
class QgsRasterPyramid;
class QgsRasterRenderer;
class QgsRasterResampler;
class QImage;
class QPixmap;
class QSlider;
@@ -393,14 +392,10 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
/** \brief Mutator for mUserDefinedRGBMinimumMaximum */
void setUserDefinedRGBMinimumMaximum( bool theBool ) { mUserDefinedRGBMinimumMaximum = theBool; }

/** Set raster resampler. Uses nearest neighbour resampling per default. Takes ownership of the resampler object*/
void setResampler( QgsRasterResampler* resampler );
QgsRasterResampler* resampler() { return mResampler; }
const QgsRasterResampler* resampler() const { return mResampler; }

/**Set raster renderer. Takes ownership of the renderer object*/
void setRenderer( QgsRasterRenderer* renderer );
const QgsRasterRenderer* renderer() const { return mRenderer; }
QgsRasterRenderer* renderer() { return mRenderer; }

/** \brief Accessor to find out how many standard deviations are being plotted */
double standardDeviations() const { return mStandardDeviations; }
@@ -940,7 +935,6 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
QString mFormat;
QString mCrs;

QgsRasterResampler* mResampler;
QgsRasterRenderer* mRenderer;
};

@@ -23,7 +23,7 @@
#include <QImage>
#include <QPainter>

QgsRasterRenderer::QgsRasterRenderer( QgsRasterDataProvider* provider, QgsRasterResampler* resampler ): mProvider( provider ), mResampler( resampler ),
QgsRasterRenderer::QgsRasterRenderer( QgsRasterDataProvider* provider ): mProvider( provider ), mZoomedInResampler( 0 ), mZoomedOutResampler( 0 ),
mOpacity( 1.0 ), mRasterTransparency( 0 ), mAlphaBand( -1 ), mInvertColor( false )
{
}
@@ -36,6 +36,21 @@ QgsRasterRenderer::~QgsRasterRenderer()
{
CPLFree( partIt.value().data );
}

delete mZoomedInResampler;
delete mZoomedOutResampler;
}

void QgsRasterRenderer::setZoomedInResampler( QgsRasterResampler* r )
{
delete mZoomedInResampler;
mZoomedInResampler = r;
}

void QgsRasterRenderer::setZoomedOutResampler( QgsRasterResampler* r )
{
delete mZoomedOutResampler;
mZoomedOutResampler = r;
}

void QgsRasterRenderer::startRasterRead( int bandNumber, QgsRasterViewPort* viewPort, const QgsMapToPixel* mapToPixel, double& oversamplingX, double& oversamplingY )
@@ -50,7 +65,8 @@ void QgsRasterRenderer::startRasterRead( int bandNumber, QgsRasterViewPort* view

//calculate oversampling factor
double oversampling = 1.0; //approximate global oversampling factor
if ( mResampler )

if ( mZoomedInResampler || mZoomedOutResampler )
{
QgsRectangle providerExtent = mProvider->extent();
if ( viewPort->mSrcCRS.isValid() && viewPort->mDestCRS.isValid() && viewPort->mSrcCRS != viewPort->mDestCRS )
@@ -62,6 +78,12 @@ void QgsRasterRenderer::startRasterRead( int bandNumber, QgsRasterViewPort* view
oversampling = ( pixelRatio > 4.0 ) ? 4.0 : pixelRatio;
}

//set oversampling back to 1.0 if no resampler for zoomed in / zoomed out (nearest neighbour)
if (( oversampling < 1.0 && !mZoomedInResampler ) || ( oversampling > 1.0 && !mZoomedOutResampler ) )
{
oversampling = 1.0;
}

//split raster into small portions if necessary
RasterPartInfo pInfo;
pInfo.nCols = viewPort->drawableAreaXDim * oversampling;
@@ -178,13 +200,21 @@ void QgsRasterRenderer::drawImage( QPainter* p, QgsRasterViewPort* viewPort, con

//top left position in device coords
QPointF tlPoint = QPointF( viewPort->topLeftPoint.x(), viewPort->topLeftPoint.y() );
tlPoint += QPointF( topLeftCol / oversamplingX, topLeftRow / oversamplingY );

//draw image
if ( mResampler && !( doubleNear( oversamplingX, 1.0 ) && doubleNear( oversamplingY, 1.0 ) ) ) //resampling with factor 1.0 not useful
//resample and draw image
if (( mZoomedInResampler || mZoomedOutResampler ) && !doubleNear( oversamplingX, 1.0 ) && !doubleNear( oversamplingY, 1.0 ) )
{
QImage dstImg( nCols / oversamplingX + 1.0, nRows / oversamplingY + 1.0, QImage::Format_ARGB32_Premultiplied );
mResampler->resample( img, dstImg );
if ( mZoomedInResampler && oversamplingX < 1.0 )
{
mZoomedInResampler->resample( img, dstImg );
}
else if ( mZoomedOutResampler && oversamplingX > 1.0 )
{
mZoomedOutResampler->resample( img, dstImg );
}

tlPoint += QPointF( topLeftCol / oversamplingX, topLeftRow / oversamplingY );
p->drawImage( tlPoint, dstImg );
}
else //use original image

0 comments on commit 6641652

Please sign in to comment.
You can’t perform that action at this time.