Skip to content

Commit

Permalink
Bilinear resampler
Browse files Browse the repository at this point in the history
  • Loading branch information
mhugent committed Dec 18, 2011
1 parent 79b8a76 commit 66ef651
Show file tree
Hide file tree
Showing 9 changed files with 267 additions and 18 deletions.
1 change: 1 addition & 0 deletions src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ SET(QGIS_CORE_SRCS

raster/qgsrasterrenderer.cpp
raster/qgspalettedrasterrenderer.cpp
raster/qgsbilinearrasterresampler.cpp

renderer/qgscontinuouscolorrenderer.cpp
renderer/qgsgraduatedsymbolrenderer.cpp
Expand Down
81 changes: 81 additions & 0 deletions src/core/raster/qgsbilinearrasterresampler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/***************************************************************************
qgsbilinearrasterresampler.cpp
------------------------------
begin : December 2011
copyright : (C) 2011 by Marco Hugentobler
email : marco at sourcepole dot ch
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgsbilinearrasterresampler.h"
#include <QImage>

QgsBilinearRasterResampler::QgsBilinearRasterResampler()
{
}

QgsBilinearRasterResampler::~QgsBilinearRasterResampler()
{
}

void QgsBilinearRasterResampler::resample( const QImage& srcImage, QImage& dstImage ) const
{
double nSrcPerDstX = ( double ) srcImage.width() / ( double ) dstImage.width();
double nSrcPerDstY = ( double ) srcImage.height() / ( double ) dstImage.height();

double currentSrcRow = nSrcPerDstX / 2.0;
double currentSrcCol;

QRgb px1, px2, px3, px4;

for ( int i = 0; i < dstImage.height(); ++i )
{
currentSrcCol = nSrcPerDstY / 2.0;
for ( int j = 0; j < dstImage.width(); ++j )
{
px1 = srcImage.pixel( currentSrcCol, currentSrcRow );
px2 = srcImage.pixel( currentSrcCol + 1, currentSrcRow );
px3 = srcImage.pixel( currentSrcCol + 1, currentSrcRow + 1 );
px4 = srcImage.pixel( currentSrcCol, currentSrcRow + 1 );
double u = currentSrcCol - ( int ) currentSrcCol;
double v = currentSrcRow - ( int ) currentSrcRow;
dstImage.setPixel( j, i, resampleColorValue( u, v, px1, px2, px3, px4 ) );
currentSrcCol += nSrcPerDstX;
}
currentSrcRow += nSrcPerDstY;
}
}

QRgb QgsBilinearRasterResampler::resampleColorValue( double u, double v, QRgb col1, QRgb col2, QRgb col3, QRgb col4 ) const
{
double r1 = qRed( col1 );
double g1 = qGreen( col1 );
double b1 = qBlue( col1 );
double r2 = qRed( col2 );
double g2 = qGreen( col2 );
double b2 = qBlue( col2 );
double r3 = qRed( col3 );
double g3 = qGreen( col3 );
double b3 = qBlue( col3 );
double r4 = qRed( col4 );
double g4 = qGreen( col4 );
double b4 = qBlue( col4 );

double rt1 = u * r2 + ( 1 - u ) * r1;
double gt1 = u * g2 + ( 1 - u ) * g1;
double bt1 = u * b2 + ( 1 - u ) * b1;

double rt2 = u * r3 + ( 1 - u ) * r4;
double gt2 = u * g3 + ( 1 - u ) * g4;
double bt2 = u * b3 + ( 1 - u ) * b4;

return qRgb( v * rt2 + ( 1 - v ) * rt1, v * gt2 + ( 1 - v ) * gt1, v * bt2 + ( 1 - v ) * bt1 );
}
36 changes: 36 additions & 0 deletions src/core/raster/qgsbilinearrasterresampler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/***************************************************************************
qgsbilinearrasterresampler.h
----------------------------
begin : December 2011
copyright : (C) 2011 by Marco Hugentobler
email : marco at sourcepole dot ch
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#ifndef QGSBILINEARRASTERRESAMPLER_H
#define QGSBILINEARRASTERRESAMPLER_H

#include "qgsrasterresampler.h"
#include <QColor>

class QgsBilinearRasterResampler: public QgsRasterResampler
{
public:
QgsBilinearRasterResampler();
~QgsBilinearRasterResampler();

void resample( const QImage& srcImage, QImage& dstImage ) const;

private:
QRgb resampleColorValue( double u, double v, QRgb col1, QRgb col2, QRgb col3, QRgb col4 ) const;
};

#endif // QGSBILINEARRASTERRESAMPLER_H
70 changes: 58 additions & 12 deletions src/core/raster/qgspalettedrasterrenderer.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,32 @@
/***************************************************************************
qgspalettedrasterrenderer.cpp
-----------------------------
begin : December 2011
copyright : (C) 2011 by Marco Hugentobler
email : marco at sourcepole dot ch
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgspalettedrasterrenderer.h"
#include "qgsmaptopixel.h"
#include "qgsrasterviewport.h"
#include <QColor>
#include <QImage>
#include <QPainter>

QgsPalettedRasterRenderer::QgsPalettedRasterRenderer( QgsRasterDataProvider* provider, int bandNumber, QColor* colorArray, int nColors ):
QgsRasterRenderer( provider ), mBandNumber( bandNumber), mColors( colorArray ), mNColors( nColors )
#include "qgsbilinearrasterresampler.h"

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

Expand All @@ -16,33 +37,58 @@ QgsPalettedRasterRenderer::~QgsPalettedRasterRenderer()

void QgsPalettedRasterRenderer::draw( QPainter* p, QgsRasterViewPort* viewPort, const QgsMapToPixel* theQgsMapToPixel )
{
if( !p || !mProvider || !viewPort || !theQgsMapToPixel )
if ( !p || !mProvider || !viewPort || !theQgsMapToPixel )
{
return;
}

int nCols, nRows;
if ( mResampler )
{
//read data at source resolution if zoomed in, else do oversampling with factor 2.5
double pixelRatio = theQgsMapToPixel->mapUnitsPerPixel() / ( mProvider->extent().width() / mProvider->xSize() );
double oversampling = pixelRatio > 1.0 ? 2.5 : pixelRatio;
nCols = viewPort->drawableAreaXDim * oversampling;
nRows = viewPort->drawableAreaYDim * oversampling;
}
else
{
nCols = viewPort->drawableAreaXDim;
nRows = viewPort->drawableAreaYDim;
}

//read data from provider
int typeSize = mProvider->dataTypeSize( mBandNumber ) / 8;
QgsRasterDataProvider::DataType rasterType = (QgsRasterDataProvider::DataType)mProvider->dataType( mBandNumber );
void* rasterData = VSIMalloc( typeSize * viewPort->drawableAreaXDim * viewPort->drawableAreaYDim);
mProvider->readBlock( mBandNumber, viewPort->mDrawnExtent, viewPort->drawableAreaXDim, viewPort->drawableAreaYDim,
viewPort->mSrcCRS, viewPort->mDestCRS, rasterData );
QgsRasterDataProvider::DataType rasterType = ( QgsRasterDataProvider::DataType )mProvider->dataType( mBandNumber );
void* rasterData = VSIMalloc( typeSize * nCols * nRows );
mProvider->readBlock( mBandNumber, viewPort->mDrawnExtent, nCols, nRows,
viewPort->mSrcCRS, viewPort->mDestCRS, rasterData );
int currentRasterPos = 0;

//raster image
QImage img( viewPort->drawableAreaXDim, viewPort->drawableAreaYDim, QImage::Format_ARGB32_Premultiplied );
QImage img( nCols, nRows, QImage::Format_ARGB32_Premultiplied );
QRgb* imageScanLine = 0;

for( int i = 0; i < viewPort->drawableAreaYDim; ++i )
for ( int i = 0; i < nRows; ++i )
{
imageScanLine = ( QRgb* )( img.scanLine( i ) );
for( int j = 0; j < viewPort->drawableAreaXDim; ++j )
for ( int j = 0; j < nCols; ++j )
{
int val = readValue( rasterData, rasterType, currentRasterPos );
imageScanLine[j] = mColors[ val ].rgba();
++currentRasterPos;
}
}
CPLFree( rasterData );
p->drawImage( QPointF( viewPort->topLeftPoint.x(), viewPort->topLeftPoint.y() ), img );

if ( mResampler ) //resample to output resolution
{
QImage dstImg( viewPort->drawableAreaXDim, viewPort->drawableAreaYDim, QImage::Format_ARGB32_Premultiplied );
QgsBilinearRasterResampler rs;
rs.resample( img, dstImg );
p->drawImage( QPointF( viewPort->topLeftPoint.x(), viewPort->topLeftPoint.y() ), dstImg );
}
else //use original image
{
p->drawImage( QPointF( viewPort->topLeftPoint.x(), viewPort->topLeftPoint.y() ), img );
}
}
19 changes: 18 additions & 1 deletion src/core/raster/qgspalettedrasterrenderer.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,20 @@
/***************************************************************************
qgspalettedrasterrenderer.h
---------------------------
begin : December 2011
copyright : (C) 2011 by Marco Hugentobler
email : marco at sourcepole dot ch
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#ifndef QGSPALETTEDRASTERRENDERER_H
#define QGSPALETTEDRASTERRENDERER_H

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

Expand Down
4 changes: 3 additions & 1 deletion src/core/raster/qgsrasterlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ email : tim at linfiniti.com

//renderers
#include "qgspalettedrasterrenderer.h"
#include "qgsbilinearrasterresampler.h"

#include <cstdio>
#include <cmath>
Expand Down Expand Up @@ -846,7 +847,8 @@ void QgsRasterLayer::draw( QPainter * theQPainter,
colorArray[( int )colorIt->value] = colorIt->color;
}

QgsPalettedRasterRenderer renderer( mDataProvider, bNumber, colorArray, itemList.size() );
QgsBilinearRasterResampler resampler;
QgsPalettedRasterRenderer renderer( mDataProvider, bNumber, colorArray, itemList.size(), &resampler );
renderer.draw( theQPainter, theRasterViewPort, theQgsMapToPixel );
#if 0
drawPalettedSingleBandColor( theQPainter, theRasterViewPort,
Expand Down
19 changes: 18 additions & 1 deletion src/core/raster/qgsrasterrenderer.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,23 @@
/***************************************************************************
qgsrasterrenderer.cpp
---------------------
begin : December 2011
copyright : (C) 2011 by Marco Hugentobler
email : marco at sourcepole dot ch
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgsrasterrenderer.h"

QgsRasterRenderer::QgsRasterRenderer( QgsRasterDataProvider* provider ): mProvider( provider )
QgsRasterRenderer::QgsRasterRenderer( QgsRasterDataProvider* provider, QgsRasterResampler* resampler ): mProvider( provider ), mResampler( resampler )
{
}

Expand Down
25 changes: 22 additions & 3 deletions src/core/raster/qgsrasterrenderer.h
Original file line number Diff line number Diff line change
@@ -1,33 +1,52 @@
/***************************************************************************
qgsrasterrenderer.h
-------------------
begin : December 2011
copyright : (C) 2011 by Marco Hugentobler
email : marco at sourcepole dot ch
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#ifndef QGSRASTERRENDERER_H
#define QGSRASTERRENDERER_H

#include "qgsrasterdataprovider.h"

class QPainter;
class QgsMapToPixel;
class QgsRasterResampler;
class QgsRasterViewPort;

class QgsRasterRenderer
{
public:
QgsRasterRenderer( QgsRasterDataProvider* provider );
QgsRasterRenderer( QgsRasterDataProvider* provider, QgsRasterResampler* resampler = 0 );
virtual ~QgsRasterRenderer();
virtual void draw( QPainter* p, QgsRasterViewPort* viewPort, const QgsMapToPixel* theQgsMapToPixel ) = 0;

protected:
inline double readValue( void *data, QgsRasterDataProvider::DataType type, int index );

QgsRasterDataProvider* mProvider;
QgsRasterResampler* mResampler;
};

inline double QgsRasterRenderer::readValue( void *data, QgsRasterDataProvider::DataType type, int index )
{
if( !mProvider )
if ( !mProvider )
{
return 0;
}

if( !data )
if ( !data )
{
return mProvider->noDataValue();
}
Expand Down
30 changes: 30 additions & 0 deletions src/core/raster/qgsrasterresampler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/***************************************************************************
qgsrasterresampler.h
--------------------
begin : December 2011
copyright : (C) 2011 by Marco Hugentobler
email : marco at sourcepole dot ch
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#ifndef QGSRASTERRESAMPLER_H
#define QGSRASTERRESAMPLER_H

class QImage;

/**Interface for resampling rasters (e.g. to have a smoother appearance)*/
class QgsRasterResampler
{
public:
void resample( const QImage& srcImage, QImage& dstImage ) const;
};

#endif // QGSRASTERRESAMPLER_H

0 comments on commit 66ef651

Please sign in to comment.