Skip to content

Commit

Permalink
Do otf-reprojection directly in raster renderer (much better performa…
Browse files Browse the repository at this point in the history
…nce in case of resampling)
  • Loading branch information
mhugent committed Jan 23, 2012
1 parent f940c5f commit 3f0c486
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 6 deletions.
3 changes: 3 additions & 0 deletions src/core/qgsrasterprojector.h
Expand Up @@ -125,6 +125,9 @@ class QgsRasterProjector
/** get mCPMatrix as string */ /** get mCPMatrix as string */
QString cpToString(); QString cpToString();


int dstRows() const { return mDestRows; }
int dstCols() const { return mDestCols; }

private: private:
/** Source CRS */ /** Source CRS */
QgsCoordinateReferenceSystem mSrcCRS; QgsCoordinateReferenceSystem mSrcCRS;
Expand Down
81 changes: 75 additions & 6 deletions src/core/raster/qgsrasterrenderer.cpp
Expand Up @@ -17,6 +17,7 @@


#include "qgsrasterrenderer.h" #include "qgsrasterrenderer.h"
#include "qgsrasterresampler.h" #include "qgsrasterresampler.h"
#include "qgsrasterprojector.h"
#include "qgsrastertransparency.h" #include "qgsrastertransparency.h"
#include "qgsrasterviewport.h" #include "qgsrasterviewport.h"
#include "qgsmaptopixel.h" #include "qgsmaptopixel.h"
Expand Down Expand Up @@ -101,6 +102,7 @@ void QgsRasterRenderer::startRasterRead( int bandNumber, QgsRasterViewPort* view
pInfo.currentCol = 0; pInfo.currentCol = 0;
pInfo.currentRow = 0; pInfo.currentRow = 0;
pInfo.data = 0; pInfo.data = 0;
pInfo.prj = 0;
mRasterPartInfos.insert( bandNumber, pInfo ); mRasterPartInfos.insert( bandNumber, pInfo );
} }


Expand All @@ -124,6 +126,8 @@ bool QgsRasterRenderer::readNextRasterPart( int bandNumber, double oversamplingX
//remove last data block //remove last data block
CPLFree( pInfo.data ); CPLFree( pInfo.data );
pInfo.data = 0; pInfo.data = 0;
delete pInfo.prj;
pInfo.prj = 0;


//already at end //already at end
if ( pInfo.currentCol == pInfo.nCols && pInfo.currentRow == pInfo.nRows ) if ( pInfo.currentCol == pInfo.nCols && pInfo.currentRow == pInfo.nRows )
Expand All @@ -144,10 +148,25 @@ bool QgsRasterRenderer::readNextRasterPart( int bandNumber, double oversamplingX
double ymax = viewPortExtent.yMaximum() - pInfo.currentRow / ( double )pInfo.nRows * viewPortExtent.height(); double ymax = viewPortExtent.yMaximum() - pInfo.currentRow / ( double )pInfo.nRows * viewPortExtent.height();
QgsRectangle blockRect( xmin, ymin, xmax, ymax ); QgsRectangle blockRect( xmin, ymin, xmax, ymax );


nColsRaster = nCols * oversamplingX; if ( viewPort->mSrcCRS.isValid() && viewPort->mDestCRS.isValid() && viewPort->mSrcCRS != viewPort->mDestCRS )
nRowsRaster = nRows * oversamplingY; {
pInfo.prj = new QgsRasterProjector( viewPort->mSrcCRS,
viewPort->mDestCRS, blockRect, nRows, nCols, 0, 0, mProvider->extent() );
blockRect = pInfo.prj->srcExtent();
}

if ( pInfo.prj )
{
nColsRaster = pInfo.prj->srcCols() * oversamplingX;
nRowsRaster = pInfo.prj->srcRows() * oversamplingY;
}
else
{
nColsRaster = nCols * oversamplingX;
nRowsRaster = nRows * oversamplingY;
}
pInfo.data = VSIMalloc( typeSize * nColsRaster * nRowsRaster ); pInfo.data = VSIMalloc( typeSize * nColsRaster * nRowsRaster );
mProvider->readBlock( bandNumber, blockRect, nColsRaster, nRowsRaster, viewPort->mSrcCRS, viewPort->mDestCRS, pInfo.data ); mProvider->readBlock( bandNumber, blockRect, nColsRaster, nRowsRaster, pInfo.data );
*rasterData = pInfo.data; *rasterData = pInfo.data;
topLeftCol = pInfo.currentCol; topLeftCol = pInfo.currentCol;
topLeftRow = pInfo.currentRow; topLeftRow = pInfo.currentRow;
Expand Down Expand Up @@ -178,6 +197,7 @@ void QgsRasterRenderer::removePartInfo( int bandNumber )
{ {
RasterPartInfo& pInfo = partIt.value(); RasterPartInfo& pInfo = partIt.value();
CPLFree( pInfo.data ); CPLFree( pInfo.data );
delete pInfo.prj;
mRasterPartInfos.remove( bandNumber ); mRasterPartInfos.remove( bandNumber );
} }
} }
Expand All @@ -201,13 +221,29 @@ void QgsRasterRenderer::drawImage( QPainter* p, QgsRasterViewPort* viewPort, con
return; return;
} }


//get QgsRasterProjector
QgsRasterProjector* prj;
QMap<int, RasterPartInfo>::const_iterator partInfoIt = mRasterPartInfos.constBegin();
if ( partInfoIt != mRasterPartInfos.constEnd() )
{
prj = partInfoIt->prj;
}

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


//resample and draw image //resample and draw image
if (( mZoomedInResampler || mZoomedOutResampler ) && !doubleNear( oversamplingX, 1.0 ) && !doubleNear( oversamplingY, 1.0 ) ) if (( mZoomedInResampler || mZoomedOutResampler ) && !doubleNear( oversamplingX, 1.0 ) && !doubleNear( oversamplingY, 1.0 ) )
{ {
QImage dstImg( nCols, nRows, QImage::Format_ARGB32_Premultiplied ); QImage dstImg;
if ( prj )
{
dstImg = QImage( prj->srcCols(), prj->srcRows(), QImage::Format_ARGB32_Premultiplied );
}
else
{
dstImg = QImage( nCols, nRows, QImage::Format_ARGB32_Premultiplied );
}
if ( mZoomedInResampler && oversamplingX < 1.0 ) if ( mZoomedInResampler && oversamplingX < 1.0 )
{ {
mZoomedInResampler->resample( img, dstImg ); mZoomedInResampler->resample( img, dstImg );
Expand All @@ -217,10 +253,43 @@ void QgsRasterRenderer::drawImage( QPainter* p, QgsRasterViewPort* viewPort, con
mZoomedOutResampler->resample( img, dstImg ); mZoomedOutResampler->resample( img, dstImg );
} }


p->drawImage( tlPoint, dstImg ); if ( prj )
{
QImage projectedImg( nCols, nRows, QImage::Format_ARGB32_Premultiplied );
projectImage( dstImg, projectedImg, prj );
p->drawImage( tlPoint, projectedImg );
}
else
{
p->drawImage( tlPoint, dstImg );
}
} }
else //use original image else //use original image
{ {
p->drawImage( tlPoint, img ); if ( prj )
{
QImage projectedImg( nCols, nRows, QImage::Format_ARGB32_Premultiplied );
projectImage( img, projectedImg, prj );
p->drawImage( tlPoint, projectedImg );
}
else
{
p->drawImage( tlPoint, img );
}
}
}

void QgsRasterRenderer::projectImage( const QImage& srcImg, QImage& dstImage, QgsRasterProjector* prj ) const
{
int nRows = dstImage.height();
int nCols = dstImage.width();
int srcRow, srcCol;
for ( int i = 0; i < nRows; ++i )
{
for ( int j = 0; j < nCols; ++j )
{
prj->srcRowCol( i, j, &srcRow, &srcCol );
dstImage.setPixel( j, i, srcImg.pixel( srcCol, srcRow ) );
}
} }
} }
3 changes: 3 additions & 0 deletions src/core/raster/qgsrasterrenderer.h
Expand Up @@ -23,6 +23,7 @@
class QPainter; class QPainter;
class QgsMapToPixel; class QgsMapToPixel;
class QgsRasterResampler; class QgsRasterResampler;
class QgsRasterProjector;
class QgsRasterTransparency; class QgsRasterTransparency;
class QgsRasterViewPort; class QgsRasterViewPort;


Expand All @@ -39,6 +40,7 @@ class QgsRasterRenderer
int nColsPerPart; int nColsPerPart;
int nRowsPerPart; int nRowsPerPart;
void* data; //data (can be in oversampled/undersampled resolution) void* data; //data (can be in oversampled/undersampled resolution)
QgsRasterProjector* prj; //raster projector (or 0 if no reprojection is done)
}; };


QgsRasterRenderer( QgsRasterDataProvider* provider ); QgsRasterRenderer( QgsRasterDataProvider* provider );
Expand Down Expand Up @@ -111,6 +113,7 @@ class QgsRasterRenderer
private: private:
/**Remove part into and release memory*/ /**Remove part into and release memory*/
void removePartInfo( int bandNumer ); void removePartInfo( int bandNumer );
void projectImage( const QImage& srcImg, QImage& dstImage, QgsRasterProjector* prj ) const;
}; };


inline double QgsRasterRenderer::readValue( void *data, QgsRasterDataProvider::DataType type, int index ) inline double QgsRasterRenderer::readValue( void *data, QgsRasterDataProvider::DataType type, int index )
Expand Down

0 comments on commit 3f0c486

Please sign in to comment.