Skip to content

Commit

Permalink
Merge branch 'wms_raster_performance'
Browse files Browse the repository at this point in the history
  • Loading branch information
mhugent committed Dec 12, 2012
2 parents 32f0dfd + d9a3c99 commit 4d603b4
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 63 deletions.
5 changes: 3 additions & 2 deletions src/core/qgscoordinatereferencesystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -286,8 +286,9 @@ void QgsCoordinateReferenceSystem::validate()
mCustomSrsValidation( this );

if ( !mIsValidFlag )
// set the default
createFromOgcWmsCrs( GEO_EPSG_CRS_AUTHID );
{
*this = QgsCRSCache::instance()->crsByAuthId( GEO_EPSG_CRS_AUTHID );
}
}

bool QgsCoordinateReferenceSystem::createFromSrid( long id )
Expand Down
6 changes: 3 additions & 3 deletions src/core/qgscoordinatetransform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
* *
***************************************************************************/
#include "qgscoordinatetransform.h"
#include "qgscrscache.h"
#include "qgsmessagelog.h"
#include "qgslogger.h"

Expand Down Expand Up @@ -148,9 +149,8 @@ void QgsCoordinateTransform::initialise()
if ( !mDestCRS.isValid() )
{
//No destination projection is set so we set the default output projection to
//be the same as input proj. This only happens on the first layer loaded
//whatever that may be...
mDestCRS.createFromOgcWmsCrs( mSourceCRS.authid() );
//be the same as input proj.
mDestCRS = QgsCRSCache::instance()->crsByAuthId( mSourceCRS.authid() );
}

// init the projections (destination and source)
Expand Down
60 changes: 41 additions & 19 deletions src/core/raster/qgspalettedrasterrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,17 @@

QgsPalettedRasterRenderer::QgsPalettedRasterRenderer( QgsRasterInterface* input, int bandNumber,
QColor* colorArray, int nColors ):
QgsRasterRenderer( input, "paletted" ), mBand( bandNumber ), mNColors( nColors )
{
mColors = new QRgb[nColors];
for ( int i = 0; i < nColors; ++i )
{
mColors[i] = colorArray[i].rgba();
}
delete[] colorArray;
}

QgsPalettedRasterRenderer::QgsPalettedRasterRenderer( QgsRasterInterface* input, int bandNumber, QRgb* colorArray, int nColors ):
QgsRasterRenderer( input, "paletted" ), mBand( bandNumber ), mColors( colorArray ), mNColors( nColors )
{
}
Expand All @@ -36,7 +47,7 @@ QgsPalettedRasterRenderer::~QgsPalettedRasterRenderer()

QgsRasterInterface * QgsPalettedRasterRenderer::clone() const
{
QgsPalettedRasterRenderer * renderer = new QgsPalettedRasterRenderer( 0, mBand, colors(), mNColors );
QgsPalettedRasterRenderer * renderer = new QgsPalettedRasterRenderer( 0, mBand, rgbArray(), mNColors );
renderer->setOpacity( mOpacity );
renderer->setAlphaBand( mAlphaBand );
renderer->setRasterTransparency( mRasterTransparency );
Expand All @@ -52,14 +63,14 @@ QgsRasterRenderer* QgsPalettedRasterRenderer::create( const QDomElement& elem, Q

int bandNumber = elem.attribute( "band", "-1" ).toInt();
int nColors = 0;
QColor* colors = 0;
QRgb* colors = 0;

QDomElement paletteElem = elem.firstChildElement( "colorPalette" );
if ( !paletteElem.isNull() )
{
QDomNodeList paletteEntries = paletteElem.elementsByTagName( "paletteEntry" );
nColors = paletteEntries.size();
colors = new QColor[ nColors ];
colors = new QRgb[ nColors ];

int value = 0;
QDomElement entryElem;
Expand All @@ -68,7 +79,7 @@ QgsRasterRenderer* QgsPalettedRasterRenderer::create( const QDomElement& elem, Q
entryElem = paletteEntries.at( i ).toElement();
value = entryElem.attribute( "value", "0" ).toInt();
QgsDebugMsg( entryElem.attribute( "color", "#000000" ) );
colors[value] = QColor( entryElem.attribute( "color", "#000000" ) );
colors[value] = QColor( entryElem.attribute( "color", "#000000" ) ).rgba();
}
}
QgsRasterRenderer* r = new QgsPalettedRasterRenderer( input, bandNumber, colors, nColors );
Expand All @@ -85,11 +96,25 @@ QColor* QgsPalettedRasterRenderer::colors() const
QColor* colorArray = new QColor[ mNColors ];
for ( int i = 0; i < mNColors; ++i )
{
colorArray[i] = mColors[i];
colorArray[i] = QColor( mColors[i] );
}
return colorArray;
}

QRgb* QgsPalettedRasterRenderer::rgbArray() const
{
if ( mNColors < 1 )
{
return 0;
}
QRgb* rgbValues = new QRgb[mNColors];
for ( int i = 0; i < mNColors; ++i )
{
rgbValues[i] = mColors[i];
}
return rgbValues;
}

QgsRasterBlock * QgsPalettedRasterRenderer::block( int bandNo, QgsRectangle const & extent, int width, int height )
{
QgsRasterBlock *outputBlock = new QgsRasterBlock();
Expand Down Expand Up @@ -146,7 +171,12 @@ QgsRasterBlock * QgsPalettedRasterRenderer::block( int bandNo, QgsRectangle con
return outputBlock;
}

for ( size_t i = 0; i < ( size_t )width*height; i++ )
//use direct data access instead of QgsRasterBlock::setValue
//because of performance
unsigned int* outputData = ( unsigned int* )( outputBlock->data() );

size_t rasterSize = ( size_t )width * height;
for ( size_t i = 0; i < rasterSize; ++i )
{
int val = ( int ) inputBlock->value( i );
if ( inputBlock->isNoDataValue( val ) )
Expand All @@ -156,14 +186,7 @@ QgsRasterBlock * QgsPalettedRasterRenderer::block( int bandNo, QgsRectangle con
}
if ( !hasTransparency )
{
if ( val < 0 || val > mNColors )
{
outputBlock->setColor( i, myDefaultColor );
}
else
{
outputBlock->setColor( i, mColors[ val ].rgba() );
}
outputData[i] = mColors[ val ];
}
else
{
Expand All @@ -176,9 +199,8 @@ QgsRasterBlock * QgsPalettedRasterRenderer::block( int bandNo, QgsRectangle con
{
currentOpacity *= alphaBlock->value( i ) / 255.0;
}
QColor& currentColor = mColors[val];

outputBlock->setColor( i, qRgba( currentOpacity * currentColor.red(), currentOpacity * currentColor.green(), currentOpacity * currentColor.blue(), currentOpacity * 255 ) );
QColor currentColor = QColor( mColors[val] );
outputData[i] = qRgba( currentOpacity * currentColor.red(), currentOpacity * currentColor.green(), currentOpacity * currentColor.blue(), currentOpacity * 255 );
}
}

Expand Down Expand Up @@ -207,7 +229,7 @@ void QgsPalettedRasterRenderer::writeXML( QDomDocument& doc, QDomElement& parent
{
QDomElement colorElem = doc.createElement( "paletteEntry" );
colorElem.setAttribute( "value", i );
colorElem.setAttribute( "color", mColors[i].name() );
colorElem.setAttribute( "color", QColor( mColors[i] ).name() );
colorPaletteElem.appendChild( colorElem );
}
rasterRendererElem.appendChild( colorPaletteElem );
Expand All @@ -219,7 +241,7 @@ void QgsPalettedRasterRenderer::legendSymbologyItems( QList< QPair< QString, QCo
{
for ( int i = 0; i < mNColors; ++i )
{
symbolItems.push_back( qMakePair( QString::number( i ), mColors[i] ) );
symbolItems.push_back( qMakePair( QString::number( i ), QColor( mColors[i] ) ) );
}
}

Expand Down
5 changes: 4 additions & 1 deletion src/core/raster/qgspalettedrasterrenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class CORE_EXPORT QgsPalettedRasterRenderer: public QgsRasterRenderer
public:
/**Renderer owns color array*/
QgsPalettedRasterRenderer( QgsRasterInterface* input, int bandNumber, QColor* colorArray, int nColors );
QgsPalettedRasterRenderer( QgsRasterInterface* input, int bandNumber, QRgb* colorArray, int nColors );
~QgsPalettedRasterRenderer();
QgsRasterInterface * clone() const;
static QgsRasterRenderer* create( const QDomElement& elem, QgsRasterInterface* input );
Expand All @@ -43,6 +44,8 @@ class CORE_EXPORT QgsPalettedRasterRenderer: public QgsRasterRenderer
int nColors() const { return mNColors; }
/**Returns copy of color array (caller takes ownership)*/
QColor* colors() const;
/**Returns copy of rgb array (caller takes ownership)*/
QRgb* rgbArray() const;

void writeXML( QDomDocument& doc, QDomElement& parentElem ) const;

Expand All @@ -53,7 +56,7 @@ class CORE_EXPORT QgsPalettedRasterRenderer: public QgsRasterRenderer
private:
int mBand;
/**Color array*/
QColor* mColors;
QRgb* mColors;
/**Number of colors*/
int mNColors;
};
Expand Down
22 changes: 0 additions & 22 deletions src/core/raster/qgsrasterblock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,28 +239,6 @@ bool QgsRasterBlock::isNoDataValue( double value, double noDataValue )
return false;
}

bool QgsRasterBlock::isNoDataValue( double value ) const
{
// More precise would be qIsNaN(value) && qIsNaN(noDataValue(bandNo)), but probably
// not important and slower
if ( qIsNaN( value ) ||
doubleNear( value, mNoDataValue ) )
{
return true;
}
return false;
}

double QgsRasterBlock::value( size_t index ) const
{
if ( index >= ( size_t )mWidth*mHeight )
{
QgsDebugMsg( QString( "Index %1 out of range (%2 x %3)" ).arg( index ).arg( mWidth ).arg( mHeight ) );
return mNoDataValue;
}
return readValue( mData, mDataType, index );
}

double QgsRasterBlock::value( int row, int column ) const
{
return value(( size_t )row*mWidth + column );
Expand Down
22 changes: 22 additions & 0 deletions src/core/raster/qgsrasterblock.h
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,28 @@ inline bool QgsRasterBlock::valueInRange( double value, const QList<QgsRasterBlo
return false;
}

inline double QgsRasterBlock::value( size_t index ) const
{
/*if ( index >= ( size_t )mWidth*mHeight )
{
QgsDebugMsg( QString( "Index %1 out of range (%2 x %3)" ).arg( index ).arg( mWidth ).arg( mHeight ) );
return mNoDataValue;
}*/
return readValue( mData, mDataType, index );
}

inline bool QgsRasterBlock::isNoDataValue( double value ) const
{
// More precise would be qIsNaN(value) && qIsNaN(noDataValue(bandNo)), but probably
// not important and slower
if ( qIsNaN( value ) ||
doubleNear( value, mNoDataValue ) )
{
return true;
}
return false;
}

#endif


2 changes: 2 additions & 0 deletions src/mapserver/qgis_map_serv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ map service syntax for SOAP/HTTP POST
#include "qgswfsserver.h"
#include "qgsmaprenderer.h"
#include "qgsmapserviceexception.h"
#include "qgspallabeling.h"
#include "qgsprojectparser.h"
#include "qgssldparser.h"
#include <QDomDocument>
Expand Down Expand Up @@ -198,6 +199,7 @@ int main( int argc, char * argv[] )

//creating QgsMapRenderer is expensive (access to srs.db), so we do it here before the fcgi loop
QgsMapRenderer* theMapRenderer = new QgsMapRenderer();
theMapRenderer->setLabelingEngine( new QgsPalLabeling() );

while ( fcgi_accept() >= 0 )
{
Expand Down
2 changes: 0 additions & 2 deletions src/mapserver/qgswmsserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
#include "qgsmaplayerregistry.h"
#include "qgsmaprenderer.h"
#include "qgsmaptopixel.h"
#include "qgspallabeling.h"
#include "qgsproject.h"
#include "qgsrasterlayer.h"
#include "qgsscalecalculator.h"
Expand Down Expand Up @@ -941,7 +940,6 @@ QImage* QgsWMSServer::initializeRendering( QStringList& layersList, QStringList&
delete theImage;
return 0;
}
mMapRenderer->setLabelingEngine( new QgsPalLabeling() );

//find out the current scale denominater and set it to the SLD parser
QgsScaleCalculator scaleCalc(( theImage->logicalDpiX() + theImage->logicalDpiY() ) / 2 , mMapRenderer->destinationCrs().mapUnits() );
Expand Down
36 changes: 22 additions & 14 deletions src/providers/gdal/qgsgdalprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -395,14 +395,17 @@ void QgsGdalProvider::readBlock( int theBandNo, QgsRectangle const & theExtent,

int dataSize = dataTypeSize( theBandNo );

// fill with null values
QByteArray ba = QgsRasterBlock::valueBytes( dataType( theBandNo ), noDataValue( theBandNo ) );
char *nodata = ba.data();
char *block = ( char * ) theBlock;
for ( int i = 0; i < thePixelWidth * thePixelHeight; i++ )
if ( !mExtent.contains( theExtent ) )
{
memcpy( block, nodata, dataSize );
block += dataSize;
// fill with null values
QByteArray ba = QgsRasterBlock::valueBytes( dataType( theBandNo ), noDataValue( theBandNo ) );
char *nodata = ba.data();
char *block = ( char * ) theBlock;
for ( int i = 0; i < thePixelWidth * thePixelHeight; i++ )
{
memcpy( block, nodata, dataSize );
block += dataSize;
}
}

QgsRectangle myRasterExtent = theExtent.intersect( &mExtent );
Expand Down Expand Up @@ -561,23 +564,28 @@ void QgsGdalProvider::readBlock( int theBandNo, QgsRectangle const & theExtent,
double tmpXRes = srcWidth * srcXRes / tmpWidth;
double tmpYRes = srcHeight * srcYRes / tmpHeight; // negative

double y = myRasterExtent.yMaximum() - 0.5 * yRes;
for ( int row = 0; row < height; row++ )
{
double y = myRasterExtent.yMaximum() - ( row + 0.5 ) * yRes;
int tmpRow = static_cast<int>( floor( -1. * ( tmpYMax - y ) / tmpYRes ) );

char *srcRowBlock = tmpBlock + dataSize * tmpRow * tmpWidth;
char *dstRowBlock = ( char * )theBlock + dataSize * ( top + row ) * thePixelWidth;
for ( int col = 0; col < width; col++ )

double x = myRasterExtent.xMinimum() + 0.5 * xRes; // cell center
char* dst = dstRowBlock + dataSize * left;
char* src = 0;
int tmpCol = 0;
for ( int col = 0; col < width; ++col )
{
// cell center
double x = myRasterExtent.xMinimum() + ( col + 0.5 ) * xRes;
// floor() is quite slow! Use just cast to int.
int tmpCol = static_cast<int>(( x - tmpXMin ) / tmpXRes ) ;
char *src = srcRowBlock + dataSize * tmpCol;
char *dst = dstRowBlock + dataSize * ( left + col );
tmpCol = static_cast<int>(( x - tmpXMin ) / tmpXRes ) ;
src = srcRowBlock + dataSize * tmpCol;
memcpy( dst, src, dataSize );
dst += dataSize;
x += xRes;
}
y -= yRes;
}

QgsFree( tmpBlock );
Expand Down

0 comments on commit 4d603b4

Please sign in to comment.