Skip to content
Permalink
Browse files

Use drawer and iterator to render maps

  • Loading branch information
mhugent committed Jul 7, 2012
1 parent 3f1056a commit c9035294f1ba34b0b56a94cb3331828b85fab7a3
@@ -17,48 +17,31 @@

#include "qgslogger.h"
#include "qgsrasterdrawer.h"
//#include "qgsrasterresampler.h"
#include "qgsrasterprojector.h"
#include "qgsrastertransparency.h"
#include "qgsrasteriterator.h"
#include "qgsrasterviewport.h"
#include "qgsmaptopixel.h"

//resamplers
//#include "qgsbilinearrasterresampler.h"
//#include "qgscubicrasterresampler.h"

#include <QDomDocument>
#include <QDomElement>
#include <QImage>
#include <QPainter>

QgsRasterDrawer::QgsRasterDrawer( QgsRasterInterface* input ): mInput( input )
QgsRasterDrawer::QgsRasterDrawer( QgsRasterIterator* iterator ): mIterator( iterator )
{
}

QgsRasterDrawer::~QgsRasterDrawer()
{
//remove remaining memory in partinfos
/*
QMap<int, RasterPartInfo>::iterator partIt = mRasterPartInfos.begin();
for ( ; partIt != mRasterPartInfos.end(); ++partIt )
{
CPLFree( partIt.value().data );
}
*/
}

void QgsRasterDrawer::draw( QPainter* p, QgsRasterViewPort* viewPort, const QgsMapToPixel* theQgsMapToPixel )
{
QgsDebugMsg( "Entered" );
if ( !p || !mInput || !viewPort || !theQgsMapToPixel )
if ( !p || !mIterator || !viewPort || !theQgsMapToPixel )
{
return;
}

// last pipe filter has only 1 band
int bandNumber = 1;
startRasterRead( bandNumber, viewPort, theQgsMapToPixel );
mIterator->startRasterRead( bandNumber, viewPort, theQgsMapToPixel );

//number of cols/rows in output pixels
int nCols = 0;
@@ -76,8 +59,8 @@ void QgsRasterDrawer::draw( QPainter* p, QgsRasterViewPort* viewPort, const QgsM
void* rasterData;

// readNextRasterPart calcs and resets nCols, nRows, topLeftCol, topLeftRow
while ( readNextRasterPart( bandNumber, viewPort, nCols, nRows,
&rasterData, topLeftCol, topLeftRow ) )
while ( mIterator->readNextRasterPart( bandNumber, viewPort, nCols, nRows,
&rasterData, topLeftCol, topLeftRow ) )
{
//create image
//QImage img( nRasterCols, nRasterRows, QImage::Format_ARGB32_Premultiplied );
@@ -91,120 +74,6 @@ void QgsRasterDrawer::draw( QPainter* p, QgsRasterViewPort* viewPort, const QgsM
}
}

void QgsRasterDrawer::startRasterRead( int bandNumber, QgsRasterViewPort* viewPort, const QgsMapToPixel* mapToPixel )
{
if ( !viewPort || !mapToPixel || !mInput )
{
return;
}

//remove any previous part on that band
removePartInfo( bandNumber );

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

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

// TODO : we dont know oversampling (grid size) here - how to get totalMemoryUsage ?
//int totalMemoryUsage = pInfo.nCols * oversamplingX * pInfo.nRows * oversamplingY * mInput->dataTypeSize( bandNumber );
int totalMemoryUsage = pInfo.nCols * pInfo.nRows * mInput->dataTypeSize( bandNumber );
int parts = totalMemoryUsage / 100000000 + 1;
int nPartsPerDimension = sqrt( parts );
pInfo.nColsPerPart = pInfo.nCols / nPartsPerDimension;
pInfo.nRowsPerPart = pInfo.nRows / nPartsPerDimension;
pInfo.currentCol = 0;
pInfo.currentRow = 0;
pInfo.data = 0;
pInfo.prj = 0;
mRasterPartInfos.insert( bandNumber, pInfo );
}

bool QgsRasterDrawer::readNextRasterPart( int bandNumber, QgsRasterViewPort* viewPort,
int& nCols, int& nRows, void** rasterData, int& topLeftCol, int& topLeftRow )
{
if ( !viewPort )
{
return false;
}

//get partinfo
QMap<int, RasterPartInfo>::iterator partIt = mRasterPartInfos.find( bandNumber );
if ( partIt == mRasterPartInfos.end() )
{
return false;
}

RasterPartInfo& pInfo = partIt.value();

//remove last data block
// TODO: data are released somewhere else (check)
//free( pInfo.data );
pInfo.data = 0;
delete pInfo.prj;
pInfo.prj = 0;

//already at end
if ( pInfo.currentCol == pInfo.nCols && pInfo.currentRow == pInfo.nRows )
{
return false;
}

//read data block
nCols = qMin( pInfo.nColsPerPart, pInfo.nCols - pInfo.currentCol );
nRows = qMin( pInfo.nRowsPerPart, pInfo.nRows - pInfo.currentRow );
int typeSize = mInput->dataTypeSize( bandNumber ) / 8;

//get subrectangle
QgsRectangle viewPortExtent = viewPort->mDrawnExtent;
double xmin = viewPortExtent.xMinimum() + pInfo.currentCol / ( double )pInfo.nCols * viewPortExtent.width();
double xmax = viewPortExtent.xMinimum() + ( pInfo.currentCol + nCols ) / ( double )pInfo.nCols * viewPortExtent.width();
double ymin = viewPortExtent.yMaximum() - ( pInfo.currentRow + nRows ) / ( double )pInfo.nRows * viewPortExtent.height();
double ymax = viewPortExtent.yMaximum() - pInfo.currentRow / ( double )pInfo.nRows * viewPortExtent.height();
QgsRectangle blockRect( xmin, ymin, xmax, ymax );

pInfo.data = mInput->block( bandNumber, blockRect, nCols, nRows );

*rasterData = pInfo.data;
topLeftCol = pInfo.currentCol;
topLeftRow = pInfo.currentRow;

pInfo.currentCol += nCols;
if ( pInfo.currentCol == pInfo.nCols && pInfo.currentRow + nRows == pInfo.nRows ) //end of raster
{
pInfo.currentRow = pInfo.nRows;
}
else if ( pInfo.currentCol == pInfo.nCols ) //start new row
{
pInfo.currentCol = 0;
pInfo.currentRow += pInfo.nRowsPerPart;
}

return true;
}

void QgsRasterDrawer::stopRasterRead( int bandNumber )
{
removePartInfo( bandNumber );
}

void QgsRasterDrawer::removePartInfo( int bandNumber )
{
QMap<int, RasterPartInfo>::iterator partIt = mRasterPartInfos.find( bandNumber );
if ( partIt != mRasterPartInfos.end() )
{
RasterPartInfo& pInfo = partIt.value();
//CPLFree( pInfo.data );
free( pInfo.data );
delete pInfo.prj;
mRasterPartInfos.remove( bandNumber );
}
}

void QgsRasterDrawer::drawImage( QPainter* p, QgsRasterViewPort* viewPort, const QImage& img, int topLeftCol, int topLeftRow ) const
{
if ( !p || !viewPort )
@@ -18,119 +18,31 @@
#ifndef QGSRASTERDRAWER_H
#define QGSRASTERDRAWER_H

//#include "qgsrasterdataprovider.h"
#include "qgsrasterinterface.h"

#include <QMap>

class QPainter;
class QImage;
class QgsMapToPixel;
class QgsRasterResampler;
class QgsRasterProjector;
class QgsRasterTransparency;
class QgsRasterViewPort;

class QDomElement;
class QgsRasterIterator;

class QgsRasterDrawer
{
public:
//Stores information about reading of a raster band. Columns and rows are in unsampled coordinates
struct RasterPartInfo
{
int currentCol;
int currentRow;
int nCols;
int nRows;
int nColsPerPart;
int nRowsPerPart;
void* data; //data (can be in oversampled/undersampled resolution)
QgsRasterProjector* prj; //raster projector (or 0 if no reprojection is done)
};

QgsRasterDrawer( QgsRasterInterface* input );
QgsRasterDrawer( QgsRasterIterator* iterator );
~QgsRasterDrawer();

void draw( QPainter* p, QgsRasterViewPort* viewPort, const QgsMapToPixel* theQgsMapToPixel );

protected:
//inline double readValue( void *data, QgsRasterInterface::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
*/
void startRasterRead( int bandNumber, QgsRasterViewPort* viewPort, const QgsMapToPixel* mapToPixel );
/**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, QgsRasterViewPort* viewPort,
// int& nCols, int& nRows,
// int& nColsRaster, int& nRowsRaster,
// void** rasterData, int& topLeftCol, int& topLeftRow );
bool readNextRasterPart( int bandNumber, QgsRasterViewPort* viewPort,
int& nCols, int& nRows,
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 ) const;
void stopRasterRead( int bandNumber );

QgsRasterInterface* mInput;
QMap<int, RasterPartInfo> mRasterPartInfos;

private:
/**Remove part into and release memory*/
void removePartInfo( int bandNumer );
QgsRasterIterator* mIterator;
};
/*
inline double QgsRasterDrawer::readValue( void *data, QgsRasterInterface::DataType type, int index )
{
if ( !mProvider )
{
return 0;
}
if ( !data )
{
return mProvider->noDataValue();
}
switch ( type )
{
case QgsRasterInterface::Byte:
return ( double )(( GByte * )data )[index];
break;
case QgsRasterInterface::UInt16:
return ( double )(( GUInt16 * )data )[index];
break;
case QgsRasterInterface::Int16:
return ( double )(( GInt16 * )data )[index];
break;
case QgsRasterInterface::UInt32:
return ( double )(( GUInt32 * )data )[index];
break;
case QgsRasterInterface::Int32:
return ( double )(( GInt32 * )data )[index];
break;
case QgsRasterInterface::Float32:
return ( double )(( float * )data )[index];
break;
case QgsRasterInterface::Float64:
return ( double )(( double * )data )[index];
break;
default:
//QgsMessageLog::logMessage( tr( "GDAL data type %1 is not supported" ).arg( type ), tr( "Raster" ) );
break;
}
return mProvider->noDataValue();
}
*/

#endif // QGSRASTERDRAWER_H
@@ -48,6 +48,9 @@ email : tim at linfiniti.com

#include "qgsrasterprojector.h"

#include "qgsrasteriterator.h"
#include "qgsrasterdrawer.h"

#include <cstdio>
#include <cmath>
#include <limits>
@@ -844,7 +847,8 @@ void QgsRasterLayer::draw( QPainter * theQPainter,
#endif

// Drawer to pipe?
QgsRasterDrawer drawer( mPipe.last() );
QgsRasterIterator iterator( mPipe.last() );
QgsRasterDrawer drawer( &iterator );
drawer.draw( theQPainter, theRasterViewPort, theQgsMapToPixel );

#ifdef QGISDEBUG
@@ -42,7 +42,6 @@
#include "qgscolorrampshader.h"
#include "qgsrastershaderfunction.h"
#include "qgsrasterinterface.h"
#include "qgsrasterdrawer.h"
#include "qgsrasterresamplefilter.h"
#include "qgsrasterdataprovider.h"
#include "qgsrasterpipe.h"

0 comments on commit c903529

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