Skip to content
Permalink
Browse files

Keep raster renderer parts aligned to pixel boundaries of unsampled r…

…asters (to avoid overlaps or white stripes in large prints
  • Loading branch information
mhugent committed Jan 21, 2012
1 parent 15fe4da commit f940c5f4d00f75e25ff753f1c87373a2d694ebe0
@@ -66,15 +66,24 @@ void QgsMultiBandColorRenderer::draw( QPainter* p, QgsRasterViewPort* viewPort,
void* greenData = 0;
void* blueData = 0;
void* alphaData = 0;
int nCols, nRows, topLeftCol, topLeftRow;
//number of cols/rows in output pixels
int nCols = 0;
int nRows = 0;
//number of raster cols/rows with oversampling
int nRasterCols = 0;
int nRasterRows = 0;
//shift to top left point for the raster part
int topLeftCol = 0;
int topLeftRow = 0;

bool readSuccess = true;
while ( true )
{
QSet<int>::const_iterator bandIt = bands.constBegin();
for ( ; bandIt != bands.constEnd(); ++bandIt )
{
readSuccess = readSuccess && readNextRasterPart( *bandIt, viewPort, nCols, nRows, &bandData[*bandIt], topLeftCol, topLeftRow );
readSuccess = readSuccess && readNextRasterPart( *bandIt, oversamplingX, oversamplingY, viewPort, nCols, nRows,
nRasterCols, nRasterRows, &bandData[*bandIt], topLeftCol, topLeftRow );
}

if ( !readSuccess )
@@ -90,16 +99,16 @@ void QgsMultiBandColorRenderer::draw( QPainter* p, QgsRasterViewPort* viewPort,
alphaData = bandData[mAlphaBand];
}

QImage img( nCols, nRows, QImage::Format_ARGB32_Premultiplied );
QImage img( nRasterCols, nRasterRows, QImage::Format_ARGB32_Premultiplied );
QRgb* imageScanLine = 0;
int currentRasterPos = 0;
int redVal, greenVal, blueVal;
double currentOpacity = mOpacity; //opacity (between 0 and 1)

for ( int i = 0; i < nRows; ++i )
for ( int i = 0; i < nRasterRows; ++i )
{
imageScanLine = ( QRgb* )( img.scanLine( i ) );
for ( int j = 0; j < nCols; ++j )
for ( int j = 0; j < nRasterCols; ++j )
{
redVal = readValue( redData, redType, currentRasterPos );
greenVal = readValue( greenData, greenType, currentRasterPos );
@@ -53,8 +53,13 @@ void QgsPalettedRasterRenderer::draw( QPainter* p, QgsRasterViewPort* viewPort,
startRasterRead( mAlphaBand, viewPort, theQgsMapToPixel, oversamplingX, oversamplingY );
}

//number of cols/rows in output pixels
int nCols = 0;
int nRows = 0;
//number of raster cols/rows with oversampling
int nRasterCols = 0;
int nRasterRows = 0;
//shift to top left point for the raster part
int topLeftCol = 0;
int topLeftRow = 0;
int currentRasterPos = 0;
@@ -66,27 +71,29 @@ void QgsPalettedRasterRenderer::draw( QPainter* p, QgsRasterViewPort* viewPort,
bool hasTransparency = usesTransparency( viewPort->mSrcCRS, viewPort->mDestCRS );
void* transparencyData;

while ( readNextRasterPart( mBandNumber, viewPort, nCols, nRows, &rasterData, topLeftCol, topLeftRow ) )
while ( readNextRasterPart( mBandNumber, oversamplingX, oversamplingY, viewPort, nCols, nRows, nRasterCols, nRasterRows,
&rasterData, topLeftCol, topLeftRow ) )
{
if ( mAlphaBand > 0 && mAlphaBand != mBandNumber )
{
readNextRasterPart( mAlphaBand, viewPort, nCols, nRows, &transparencyData, topLeftCol, topLeftRow );
readNextRasterPart( mAlphaBand, oversamplingX, oversamplingY, viewPort, nCols, nRows, nRasterCols, nRasterRows,
&transparencyData, topLeftCol, topLeftRow );
}
else if ( mAlphaBand == mBandNumber )
{
transparencyData = rasterData;
}

//create image
QImage img( nCols, nRows, QImage::Format_ARGB32_Premultiplied );
QImage img( nRasterCols, nRasterRows, QImage::Format_ARGB32_Premultiplied );
QRgb* imageScanLine = 0;
int val = 0;
currentRasterPos = 0;

for ( int i = 0; i < nRows; ++i )
for ( int i = 0; i < nRasterRows; ++i )
{
imageScanLine = ( QRgb* )( img.scanLine( i ) );
for ( int j = 0; j < nCols; ++j )
for ( int j = 0; j < nRasterCols; ++j )
{
val = readValue( rasterData, rasterType, currentRasterPos );
if ( !hasTransparency )
@@ -86,14 +86,14 @@ void QgsRasterRenderer::startRasterRead( int bandNumber, QgsRasterViewPort* view

//split raster into small portions if necessary
RasterPartInfo pInfo;
pInfo.nCols = viewPort->drawableAreaXDim * oversampling;
pInfo.nRows = viewPort->drawableAreaYDim * oversampling;
pInfo.nCols = viewPort->drawableAreaXDim;
pInfo.nRows = viewPort->drawableAreaYDim;

//effective oversampling factors are different to global one because of rounding
oversamplingX = ( double )pInfo.nCols / viewPort->drawableAreaXDim;
oversamplingY = ( double )pInfo.nRows / viewPort->drawableAreaYDim;
oversamplingX = (( double )pInfo.nCols * oversampling ) / viewPort->drawableAreaXDim;
oversamplingY = (( double )pInfo.nRows * oversampling ) / viewPort->drawableAreaYDim;

int totalMemoryUsage = pInfo.nCols * pInfo.nRows * mProvider->dataTypeSize( bandNumber );
int totalMemoryUsage = pInfo.nCols * oversamplingX * pInfo.nRows * oversamplingY * mProvider->dataTypeSize( bandNumber );
int parts = totalMemoryUsage / 100000000 + 1;
int nPartsPerDimension = sqrt( parts );
pInfo.nColsPerPart = pInfo.nCols / nPartsPerDimension;
@@ -104,7 +104,8 @@ void QgsRasterRenderer::startRasterRead( int bandNumber, QgsRasterViewPort* view
mRasterPartInfos.insert( bandNumber, pInfo );
}

bool QgsRasterRenderer::readNextRasterPart( int bandNumber, QgsRasterViewPort* viewPort, int& nCols, int& nRows, void** rasterData, int& topLeftCol, int& topLeftRow )
bool QgsRasterRenderer::readNextRasterPart( int bandNumber, double oversamplingX, double oversamplingY, QgsRasterViewPort* viewPort,
int& nCols, int& nRows, int& nColsRaster, int& nRowsRaster, void** rasterData, int& topLeftCol, int& topLeftRow )
{
if ( !viewPort )
{
@@ -134,7 +135,6 @@ bool QgsRasterRenderer::readNextRasterPart( int bandNumber, QgsRasterViewPort* v
nCols = qMin( pInfo.nColsPerPart, pInfo.nCols - pInfo.currentCol );
nRows = qMin( pInfo.nRowsPerPart, pInfo.nRows - pInfo.currentRow );
int typeSize = mProvider->dataTypeSize( bandNumber ) / 8;
pInfo.data = VSIMalloc( typeSize * nCols * nRows );

//get subrectangle
QgsRectangle viewPortExtent = viewPort->mDrawnExtent;
@@ -144,7 +144,10 @@ bool QgsRasterRenderer::readNextRasterPart( int bandNumber, QgsRasterViewPort* v
double ymax = viewPortExtent.yMaximum() - pInfo.currentRow / ( double )pInfo.nRows * viewPortExtent.height();
QgsRectangle blockRect( xmin, ymin, xmax, ymax );

mProvider->readBlock( bandNumber, blockRect, nCols, nRows, viewPort->mSrcCRS, viewPort->mDestCRS, pInfo.data );
nColsRaster = nCols * oversamplingX;
nRowsRaster = nRows * oversamplingY;
pInfo.data = VSIMalloc( typeSize * nColsRaster * nRowsRaster );
mProvider->readBlock( bandNumber, blockRect, nColsRaster, nRowsRaster, viewPort->mSrcCRS, viewPort->mDestCRS, pInfo.data );
*rasterData = pInfo.data;
topLeftCol = pInfo.currentCol;
topLeftRow = pInfo.currentRow;
@@ -199,12 +202,12 @@ void QgsRasterRenderer::drawImage( QPainter* p, QgsRasterViewPort* viewPort, con
}

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

//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 );
QImage dstImg( nCols, nRows, QImage::Format_ARGB32_Premultiplied );
if ( mZoomedInResampler && oversamplingX < 1.0 )
{
mZoomedInResampler->resample( img, dstImg );
@@ -214,7 +217,6 @@ void QgsRasterRenderer::drawImage( QPainter* p, QgsRasterViewPort* viewPort, con
mZoomedOutResampler->resample( img, dstImg );
}

tlPoint += QPointF( topLeftCol / oversamplingX, topLeftRow / oversamplingY );
p->drawImage( tlPoint, dstImg );
}
else //use original image
@@ -29,7 +29,7 @@ class QgsRasterViewPort;
class QgsRasterRenderer
{
public:

//Stores information about reading of a raster band. Columns and rows are in unsampled coordinates
struct RasterPartInfo
{
int currentCol;
@@ -38,7 +38,7 @@ class QgsRasterRenderer
int nRows;
int nColsPerPart;
int nRowsPerPart;
void* data;
void* data; //data (can be in oversampled/undersampled resolution)
};

QgsRasterRenderer( QgsRasterDataProvider* provider );
@@ -70,8 +70,22 @@ class QgsRasterRenderer
protected:
inline double readValue( void *data, QgsRasterDataProvider::DataType type, int index );

/**Start reading of raster band. Raster data can then be retrieved by calling readNextRasterPart until it returns false.
@param bandNumer number of raster band to read
@param viewPort describes raster position on screen
@param oversamplingX out: oversampling rate in x-direction
@param oversamplingY out: oversampling rate in y-direction*/
void startRasterRead( int bandNumber, QgsRasterViewPort* viewPort, const QgsMapToPixel* mapToPixel, double& oversamplingX, double& oversamplingY );
bool readNextRasterPart( int bandNumber, QgsRasterViewPort* viewPort, int& nCols, int& nRows, void** rasterData, int& topLeftCol, int& topLeftRow );
/**Fetches next part of raster data
@param nCols number of columns on output device
@param nRows number of rows on output device
@param nColsRaster number of raster columns (different to nCols if oversamplingX != 1.0)
@param nRowsRaster number of raster rows (different to nRows if oversamplingY != 0)*/
bool readNextRasterPart( int bandNumber, double oversamplingX, double oversamplingY, QgsRasterViewPort* viewPort, int& nCols, int& nRows,
int& nColsRaster, int& nRowsRaster, void** rasterData, int& topLeftCol, int& topLeftRow );
/**Draws raster part
@param topLeftCol Left position relative to left border of viewport
@param topLeftRow Top position relative to top border of viewport*/
void drawImage( QPainter* p, QgsRasterViewPort* viewPort, const QImage& img, int topLeftCol, int topLeftRow,
int nCols, int nRows, double oversamplingX, double oversamplingY ) const;
void stopRasterRead( int bandNumber );
@@ -39,27 +39,36 @@ void QgsSingleBandColorDataRenderer::draw( QPainter* p, QgsRasterViewPort* viewP
double oversamplingX, oversamplingY;
startRasterRead( mBand, viewPort, theQgsMapToPixel, oversamplingX, oversamplingY );

int topLeftCol, topLeftRow, nCols, nRows, currentRasterPos;
//number of cols/rows in output pixels
int nCols = 0;
int nRows = 0;
//number of raster cols/rows with oversampling
int nRasterCols = 0;
int nRasterRows = 0;
//shift to top left point for the raster part
int topLeftCol = 0;
int topLeftRow = 0;
int currentRasterPos;
void* rasterData;

bool hasTransparency = usesTransparency( viewPort->mSrcCRS, viewPort->mDestCRS );

while ( readNextRasterPart( mBand, viewPort, nCols, nRows, &rasterData, topLeftCol, topLeftRow ) )
while ( readNextRasterPart( mBand, oversamplingX, oversamplingY, viewPort, nCols, nRows, nRasterCols, nRasterRows, &rasterData, topLeftCol, topLeftRow ) )
{
currentRasterPos = 0;
QImage img( nCols, nRows, QImage::Format_ARGB32 );
QImage img( nRasterCols, nRasterRows, QImage::Format_ARGB32 );
uchar* scanLine = 0;
for ( int i = 0; i < nRows; ++i )
for ( int i = 0; i < nRasterRows; ++i )
{
scanLine = img.scanLine( i );
if ( !hasTransparency )
{
memcpy( scanLine, &((( uint* )rasterData )[currentRasterPos] ), nCols * 4 );
currentRasterPos += nCols;
currentRasterPos += nRasterCols;
}
else
{
for ( int j = 0; j < nCols; ++j )
for ( int j = 0; j < nRasterCols; ++j )
{
QRgb c((( uint* )( rasterData ) )[currentRasterPos] );
scanLine[i] = qRgba( qRed( c ), qGreen( c ), qBlue( c ), 255 );
@@ -43,8 +43,13 @@ void QgsSingleBandGrayRenderer::draw( QPainter* p, QgsRasterViewPort* viewPort,
startRasterRead( mAlphaBand, viewPort, theQgsMapToPixel, oversamplingX, oversamplingY );
}

//number of cols/rows in output pixels
int nCols = 0;
int nRows = 0;
//number of raster cols/rows with oversampling
int nRasterCols = 0;
int nRasterRows = 0;
//shift to top left point for the raster part
int topLeftCol = 0;
int topLeftRow = 0;
QgsRasterDataProvider::DataType rasterType = ( QgsRasterDataProvider::DataType )mProvider->dataType( mGrayBand );
@@ -60,11 +65,13 @@ void QgsSingleBandGrayRenderer::draw( QPainter* p, QgsRasterViewPort* viewPort,
QRgb myDefaultColor = qRgba( 0, 0, 0, 0 );


while ( readNextRasterPart( mGrayBand, viewPort, nCols, nRows, &rasterData, topLeftCol, topLeftRow ) )
while ( readNextRasterPart( mGrayBand, oversamplingX, oversamplingY, viewPort, nCols, nRows, nRasterCols, nRasterRows,
&rasterData, topLeftCol, topLeftRow ) )
{
if ( mAlphaBand > 0 && mGrayBand != mAlphaBand )
{
readNextRasterPart( mAlphaBand, viewPort, nCols, nRows, &alphaData, topLeftCol, topLeftRow );
readNextRasterPart( mAlphaBand, oversamplingX, oversamplingY, viewPort, nCols, nRows, nRasterCols, nRasterRows,
&alphaData, topLeftCol, topLeftRow );
}
else if ( mAlphaBand > 0 )
{
@@ -73,14 +80,14 @@ void QgsSingleBandGrayRenderer::draw( QPainter* p, QgsRasterViewPort* viewPort,


//create image
QImage img( nCols, nRows, QImage::Format_ARGB32_Premultiplied );
QImage img( nRasterCols, nRasterRows, QImage::Format_ARGB32_Premultiplied );
QRgb* imageScanLine = 0;
int currentRasterPos = 0;

for ( int i = 0; i < nRows; ++i )
for ( int i = 0; i < nRasterRows; ++i )
{
imageScanLine = ( QRgb* )( img.scanLine( i ) );
for ( int j = 0; j < nCols; ++j )
for ( int j = 0; j < nRasterCols; ++j )
{
grayVal = readValue( rasterData, rasterType, currentRasterPos );

@@ -131,5 +138,4 @@ void QgsSingleBandGrayRenderer::draw( QPainter* p, QgsRasterViewPort* viewPort,
{
stopRasterRead( mAlphaBand );
}

}
@@ -50,8 +50,13 @@ void QgsSingleBandPseudoColorRenderer::draw( QPainter* p, QgsRasterViewPort* vie
startRasterRead( mAlphaBand, viewPort, theQgsMapToPixel, oversamplingX, oversamplingY );
}

//number of cols/rows in output pixels
int nCols = 0;
int nRows = 0;
//number of raster cols/rows with oversampling
int nRasterCols = 0;
int nRasterRows = 0;
//shift to top left point for the raster part
int topLeftCol = 0;
int topLeftRow = 0;
void* rasterData;
@@ -64,27 +69,29 @@ void QgsSingleBandPseudoColorRenderer::draw( QPainter* p, QgsRasterViewPort* vie
//rendering is faster without considering user-defined transparency
bool hasTransparency = usesTransparency( viewPort->mSrcCRS, viewPort->mDestCRS );

while ( readNextRasterPart( mBand, viewPort, nCols, nRows, &rasterData, topLeftCol, topLeftRow ) )
while ( readNextRasterPart( mBand, oversamplingX, oversamplingY, viewPort, nCols, nRows, nRasterCols, nRasterRows,
&rasterData, topLeftCol, topLeftRow ) )
{
if ( mAlphaBand > 0 && mAlphaBand != mBand )
{
readNextRasterPart( mAlphaBand, viewPort, nCols, nRows, &transparencyData, topLeftCol, topLeftRow );
readNextRasterPart( mAlphaBand, oversamplingX, oversamplingY, viewPort, nCols, nRows, nRasterCols, nRasterRows,
&transparencyData, topLeftCol, topLeftRow );
}
else if ( mAlphaBand == mBand )
{
transparencyData = rasterData;
}

//create image
QImage img( nCols, nRows, QImage::Format_ARGB32_Premultiplied );
QImage img( nRasterCols, nRasterRows, QImage::Format_ARGB32_Premultiplied );
QRgb* imageScanLine = 0;
double val = 0;

int currentRasterPos = 0;
for ( int i = 0; i < nRows; ++i )
for ( int i = 0; i < nRasterRows; ++i )
{
imageScanLine = ( QRgb* )( img.scanLine( i ) );
for ( int j = 0; j < nCols; ++j )
for ( int j = 0; j < nRasterCols; ++j )
{
val = readValue( rasterData, rasterType, currentRasterPos );
if ( !mShader->shade( val, &red, &green, &blue ) )

0 comments on commit f940c5f

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