Skip to content

Commit

Permalink
Use raster renderer functions to retrieve data parts for multiband co…
Browse files Browse the repository at this point in the history
…lor too
  • Loading branch information
mhugent committed Dec 28, 2011
1 parent 76cc219 commit 172a7c8
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 58 deletions.
152 changes: 97 additions & 55 deletions src/core/raster/qgsmultibandcolorrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@
#include "qgsmultibandcolorrenderer.h"
#include "qgsmaptopixel.h"
#include "qgsrasterresampler.h"
#include "qgsrastertransparency.h"
#include "qgsrasterviewport.h"
#include <QImage>
#include <QPainter>
#include <QSet>

QgsMultiBandColorRenderer::QgsMultiBandColorRenderer( QgsRasterDataProvider* provider, int redBand, int greenBand, int blueBand, QgsRasterResampler* resampler ):
QgsRasterRenderer( provider, resampler ), mRedBand( redBand ), mGreenBand( greenBand ), mBlueBand( blueBand )
Expand All @@ -38,78 +40,118 @@ void QgsMultiBandColorRenderer::draw( QPainter* p, QgsRasterViewPort* viewPort,
return;
}

//read data from provider
int redTypeSize = mProvider->dataTypeSize( mRedBand ) / 8;
int greenTypeSize = mProvider->dataTypeSize( mGreenBand ) / 8;
int blueTypeSize = mProvider->dataTypeSize( mBlueBand ) / 8;

QgsRasterDataProvider::DataType redType = ( QgsRasterDataProvider::DataType )mProvider->dataType( mRedBand );
QgsRasterDataProvider::DataType greenType = ( QgsRasterDataProvider::DataType )mProvider->dataType( mGreenBand );
QgsRasterDataProvider::DataType blueType = ( QgsRasterDataProvider::DataType )mProvider->dataType( mBlueBand );
QgsRasterDataProvider::DataType transparencyType;
if ( mAlphaBand > 0 )
{
transparencyType = ( QgsRasterDataProvider::DataType )mProvider->dataType( mAlphaBand );
}

int nCols, nRows;

if ( mResampler )
double oversampling;
QSet<int> bands;
bands << mRedBand << mGreenBand << mBlueBand;
if ( mAlphaBand > 0 )
{
//read data at source resolution if zoomed in, else do oversampling with factor 2.5
QgsRectangle providerExtent = mProvider->extent();
if ( viewPort->mSrcCRS.isValid() && viewPort->mDestCRS.isValid() && viewPort->mSrcCRS != viewPort->mDestCRS )
{
QgsCoordinateTransform t( viewPort->mSrcCRS, viewPort->mDestCRS );
providerExtent = t.transformBoundingBox( providerExtent );
}
double pixelRatio = theQgsMapToPixel->mapUnitsPerPixel() / ( providerExtent.width() / mProvider->xSize() );
double oversampling = pixelRatio > 1.0 ? 2.5 : pixelRatio;
nCols = viewPort->drawableAreaXDim * oversampling;
nRows = viewPort->drawableAreaYDim * oversampling;
bands << mAlphaBand;
}
else

QMap<int, void*> bandData;
void* defaultPointer;
QSet<int>::const_iterator bandIt = bands.constBegin();
for ( ; bandIt != bands.constEnd(); ++bandIt )
{
nCols = viewPort->drawableAreaXDim;
nRows = viewPort->drawableAreaYDim;
bandData.insert( *bandIt, defaultPointer );
startRasterRead( *bandIt, viewPort, theQgsMapToPixel, oversampling );
}

void* redData = VSIMalloc( redTypeSize * nCols * nRows );
void* greenData = VSIMalloc( greenTypeSize * nCols * nRows );
void* blueData = VSIMalloc( blueTypeSize * nCols * nRows );
void* redData;
void* greenData;
void* blueData;
void* alphaData;
int nCols, nRows, topLeftCol, topLeftRow;

mProvider->readBlock( mRedBand, viewPort->mDrawnExtent, nCols, nRows,
viewPort->mSrcCRS, viewPort->mDestCRS, redData );
mProvider->readBlock( mGreenBand, viewPort->mDrawnExtent, nCols, nRows,
viewPort->mSrcCRS, viewPort->mDestCRS, greenData );
mProvider->readBlock( mBlueBand, viewPort->mDrawnExtent, nCols, nRows,
viewPort->mSrcCRS, viewPort->mDestCRS, blueData );
bool readSuccess;
while ( true )
{
QSet<int>::const_iterator bandIt = bands.constBegin();
for ( ; bandIt != bands.constEnd(); ++bandIt )
{
readSuccess = readNextRasterPart( *bandIt, viewPort, nCols, nRows, &bandData[*bandIt], topLeftCol, topLeftRow );
}

QImage img( nCols, nRows, QImage::Format_ARGB32_Premultiplied );
QRgb* imageScanLine = 0;
int currentRasterPos = 0;
int redVal, greenVal, blueVal;
if ( !readSuccess )
{
break;
}

for ( int i = 0; i < nRows; ++i )
{
imageScanLine = ( QRgb* )( img.scanLine( i ) );
for ( int j = 0; j < nCols; ++j )
redData = bandData[mRedBand];
greenData = bandData[mGreenBand];
blueData = bandData[mBlueBand];
if ( mAlphaBand > 0 )
{
redVal = readValue( redData, redType, currentRasterPos );
greenVal = readValue( greenData, greenType, currentRasterPos );
blueVal = readValue( blueData, blueType, currentRasterPos );
imageScanLine[j] = qRgba( redVal, greenVal, blueVal, 255 );
++currentRasterPos;
alphaData = bandData[mAlphaBand];
}
}

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

if ( mResampler )
{
QImage dstImg( viewPort->drawableAreaXDim, viewPort->drawableAreaYDim, QImage::Format_ARGB32_Premultiplied );
mResampler->resample( img, dstImg );
p->drawImage( QPointF( viewPort->topLeftPoint.x(), viewPort->topLeftPoint.y() ), dstImg );
for ( int i = 0; i < nRows; ++i )
{
imageScanLine = ( QRgb* )( img.scanLine( i ) );
for ( int j = 0; j < nCols; ++j )
{
redVal = readValue( redData, redType, currentRasterPos );
greenVal = readValue( greenData, greenType, currentRasterPos );
blueVal = readValue( blueData, blueType, currentRasterPos );

//opacity
currentOpacity = mOpacity;
if ( mRasterTransparency )
{
currentOpacity = mRasterTransparency->alphaValue( redVal, greenVal, blueVal, mOpacity * 255 ) / 255.0;
}
if ( mAlphaBand > 0 )
{
currentOpacity *= ( readValue( alphaData, transparencyType, currentRasterPos ) / 255.0 );
}

if ( doubleNear( currentOpacity, 255 ) )
{
imageScanLine[j] = qRgba( redVal, greenVal, blueVal, 255 );
}
else
{
imageScanLine[j] = qRgba( currentOpacity * redVal, currentOpacity * greenVal, currentOpacity * blueVal, currentOpacity * 255 );
}
++currentRasterPos;
}
}

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

if ( mResampler ) //resample to output resolution
{
QImage dstImg( nCols / oversampling + 0.5, nRows / oversampling + 0.5, QImage::Format_ARGB32_Premultiplied );
mResampler->resample( img, dstImg );
p->drawImage( tlPoint, dstImg );
}
else //use original image
{
p->drawImage( tlPoint, img );
}
}
else

bandIt = bands.constBegin();
for ( ; bandIt != bands.constEnd(); ++bandIt )
{
p->drawImage( QPointF( viewPort->topLeftPoint.x(), viewPort->topLeftPoint.y() ), img );
stopRasterRead( *bandIt );
}
}
4 changes: 2 additions & 2 deletions src/core/raster/qgspalettedrasterrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ void QgsPalettedRasterRenderer::draw( QPainter* p, QgsRasterViewPort* viewPort,
{
currentOpacity = mRasterTransparency->alphaValue( val, mOpacity * 255 ) / 255.0;
}
if ( mAlphaBand >= 0 )
if ( mAlphaBand > 0 )
{
currentOpacity *= ( readValue( transparencyData, transparencyType, currentRasterPos ) / 255.0 );
}
Expand All @@ -121,7 +121,7 @@ void QgsPalettedRasterRenderer::draw( QPainter* p, QgsRasterViewPort* viewPort,
//draw image
if ( mResampler ) //resample to output resolution
{
QImage dstImg( viewPort->drawableAreaXDim, viewPort->drawableAreaYDim, QImage::Format_ARGB32_Premultiplied );
QImage dstImg( nCols / oversampling + 0.5, nRows / oversampling + 0.5, QImage::Format_ARGB32_Premultiplied );
mResampler->resample( img, dstImg );
p->drawImage( tlPoint, dstImg );
}
Expand Down
2 changes: 1 addition & 1 deletion src/core/raster/qgsrasterrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ void QgsRasterRenderer::startRasterRead( int bandNumber, QgsRasterViewPort* view
pInfo.nCols = viewPort->drawableAreaXDim * oversampling;
pInfo.nRows = viewPort->drawableAreaYDim * oversampling;
int totalMemoryUsage = pInfo.nCols * pInfo.nRows * mProvider->dataTypeSize( bandNumber );
int parts = totalMemoryUsage / 100000000 + 1;
int parts = totalMemoryUsage / /*100000000*/ 100000 + 1;
pInfo.nPartsPerDimension = sqrt( parts );
pInfo.nColsPerPart = pInfo.nCols / pInfo.nPartsPerDimension;
pInfo.nRowsPerPart = pInfo.nRows / pInfo.nPartsPerDimension;
Expand Down

0 comments on commit 172a7c8

Please sign in to comment.