Skip to content

Commit 3f0c486

Browse files
committed
Do otf-reprojection directly in raster renderer (much better performance in case of resampling)
1 parent f940c5f commit 3f0c486

File tree

3 files changed

+81
-6
lines changed

3 files changed

+81
-6
lines changed

src/core/qgsrasterprojector.h

+3
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,9 @@ class QgsRasterProjector
125125
/** get mCPMatrix as string */
126126
QString cpToString();
127127

128+
int dstRows() const { return mDestRows; }
129+
int dstCols() const { return mDestCols; }
130+
128131
private:
129132
/** Source CRS */
130133
QgsCoordinateReferenceSystem mSrcCRS;

src/core/raster/qgsrasterrenderer.cpp

+75-6
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include "qgsrasterrenderer.h"
1919
#include "qgsrasterresampler.h"
20+
#include "qgsrasterprojector.h"
2021
#include "qgsrastertransparency.h"
2122
#include "qgsrasterviewport.h"
2223
#include "qgsmaptopixel.h"
@@ -101,6 +102,7 @@ void QgsRasterRenderer::startRasterRead( int bandNumber, QgsRasterViewPort* view
101102
pInfo.currentCol = 0;
102103
pInfo.currentRow = 0;
103104
pInfo.data = 0;
105+
pInfo.prj = 0;
104106
mRasterPartInfos.insert( bandNumber, pInfo );
105107
}
106108

@@ -124,6 +126,8 @@ bool QgsRasterRenderer::readNextRasterPart( int bandNumber, double oversamplingX
124126
//remove last data block
125127
CPLFree( pInfo.data );
126128
pInfo.data = 0;
129+
delete pInfo.prj;
130+
pInfo.prj = 0;
127131

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

147-
nColsRaster = nCols * oversamplingX;
148-
nRowsRaster = nRows * oversamplingY;
151+
if ( viewPort->mSrcCRS.isValid() && viewPort->mDestCRS.isValid() && viewPort->mSrcCRS != viewPort->mDestCRS )
152+
{
153+
pInfo.prj = new QgsRasterProjector( viewPort->mSrcCRS,
154+
viewPort->mDestCRS, blockRect, nRows, nCols, 0, 0, mProvider->extent() );
155+
blockRect = pInfo.prj->srcExtent();
156+
}
157+
158+
if ( pInfo.prj )
159+
{
160+
nColsRaster = pInfo.prj->srcCols() * oversamplingX;
161+
nRowsRaster = pInfo.prj->srcRows() * oversamplingY;
162+
}
163+
else
164+
{
165+
nColsRaster = nCols * oversamplingX;
166+
nRowsRaster = nRows * oversamplingY;
167+
}
149168
pInfo.data = VSIMalloc( typeSize * nColsRaster * nRowsRaster );
150-
mProvider->readBlock( bandNumber, blockRect, nColsRaster, nRowsRaster, viewPort->mSrcCRS, viewPort->mDestCRS, pInfo.data );
169+
mProvider->readBlock( bandNumber, blockRect, nColsRaster, nRowsRaster, pInfo.data );
151170
*rasterData = pInfo.data;
152171
topLeftCol = pInfo.currentCol;
153172
topLeftRow = pInfo.currentRow;
@@ -178,6 +197,7 @@ void QgsRasterRenderer::removePartInfo( int bandNumber )
178197
{
179198
RasterPartInfo& pInfo = partIt.value();
180199
CPLFree( pInfo.data );
200+
delete pInfo.prj;
181201
mRasterPartInfos.remove( bandNumber );
182202
}
183203
}
@@ -201,13 +221,29 @@ void QgsRasterRenderer::drawImage( QPainter* p, QgsRasterViewPort* viewPort, con
201221
return;
202222
}
203223

224+
//get QgsRasterProjector
225+
QgsRasterProjector* prj;
226+
QMap<int, RasterPartInfo>::const_iterator partInfoIt = mRasterPartInfos.constBegin();
227+
if ( partInfoIt != mRasterPartInfos.constEnd() )
228+
{
229+
prj = partInfoIt->prj;
230+
}
231+
204232
//top left position in device coords
205233
QPoint tlPoint = QPoint( viewPort->topLeftPoint.x() + topLeftCol, viewPort->topLeftPoint.y() + topLeftRow );
206234

207235
//resample and draw image
208236
if (( mZoomedInResampler || mZoomedOutResampler ) && !doubleNear( oversamplingX, 1.0 ) && !doubleNear( oversamplingY, 1.0 ) )
209237
{
210-
QImage dstImg( nCols, nRows, QImage::Format_ARGB32_Premultiplied );
238+
QImage dstImg;
239+
if ( prj )
240+
{
241+
dstImg = QImage( prj->srcCols(), prj->srcRows(), QImage::Format_ARGB32_Premultiplied );
242+
}
243+
else
244+
{
245+
dstImg = QImage( nCols, nRows, QImage::Format_ARGB32_Premultiplied );
246+
}
211247
if ( mZoomedInResampler && oversamplingX < 1.0 )
212248
{
213249
mZoomedInResampler->resample( img, dstImg );
@@ -217,10 +253,43 @@ void QgsRasterRenderer::drawImage( QPainter* p, QgsRasterViewPort* viewPort, con
217253
mZoomedOutResampler->resample( img, dstImg );
218254
}
219255

220-
p->drawImage( tlPoint, dstImg );
256+
if ( prj )
257+
{
258+
QImage projectedImg( nCols, nRows, QImage::Format_ARGB32_Premultiplied );
259+
projectImage( dstImg, projectedImg, prj );
260+
p->drawImage( tlPoint, projectedImg );
261+
}
262+
else
263+
{
264+
p->drawImage( tlPoint, dstImg );
265+
}
221266
}
222267
else //use original image
223268
{
224-
p->drawImage( tlPoint, img );
269+
if ( prj )
270+
{
271+
QImage projectedImg( nCols, nRows, QImage::Format_ARGB32_Premultiplied );
272+
projectImage( img, projectedImg, prj );
273+
p->drawImage( tlPoint, projectedImg );
274+
}
275+
else
276+
{
277+
p->drawImage( tlPoint, img );
278+
}
279+
}
280+
}
281+
282+
void QgsRasterRenderer::projectImage( const QImage& srcImg, QImage& dstImage, QgsRasterProjector* prj ) const
283+
{
284+
int nRows = dstImage.height();
285+
int nCols = dstImage.width();
286+
int srcRow, srcCol;
287+
for ( int i = 0; i < nRows; ++i )
288+
{
289+
for ( int j = 0; j < nCols; ++j )
290+
{
291+
prj->srcRowCol( i, j, &srcRow, &srcCol );
292+
dstImage.setPixel( j, i, srcImg.pixel( srcCol, srcRow ) );
293+
}
225294
}
226295
}

src/core/raster/qgsrasterrenderer.h

+3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
class QPainter;
2424
class QgsMapToPixel;
2525
class QgsRasterResampler;
26+
class QgsRasterProjector;
2627
class QgsRasterTransparency;
2728
class QgsRasterViewPort;
2829

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

4446
QgsRasterRenderer( QgsRasterDataProvider* provider );
@@ -111,6 +113,7 @@ class QgsRasterRenderer
111113
private:
112114
/**Remove part into and release memory*/
113115
void removePartInfo( int bandNumer );
116+
void projectImage( const QImage& srcImg, QImage& dstImage, QgsRasterProjector* prj ) const;
114117
};
115118

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

0 commit comments

Comments
 (0)