308 changes: 175 additions & 133 deletions src/core/raster/qgsmultibandcolorrenderer.cpp

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions src/core/raster/qgsmultibandcolorrenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,15 @@ class QDomElement;
class CORE_EXPORT QgsMultiBandColorRenderer: public QgsRasterRenderer
{
public:
QgsMultiBandColorRenderer( QgsRasterDataProvider* provider, int redBand, int greenBand, int blueBand,
QgsMultiBandColorRenderer( QgsRasterFace* input, int redBand, int greenBand, int blueBand,
QgsContrastEnhancement* redEnhancement = 0, QgsContrastEnhancement* greenEnhancement = 0,
QgsContrastEnhancement* blueEnhancement = 0 );
~QgsMultiBandColorRenderer();

static QgsRasterRenderer* create( const QDomElement& elem, QgsRasterDataProvider* provider );
static QgsRasterRenderer* create( const QDomElement& elem, QgsRasterFace* input );

void draw( QPainter* p, QgsRasterViewPort* viewPort, const QgsMapToPixel* theQgsMapToPixel );
//void draw( QPainter* p, QgsRasterViewPort* viewPort, const QgsMapToPixel* theQgsMapToPixel );
void * readBlock( int bandNo, QgsRectangle const & extent, int width, int height );

int redBand() const { return mRedBand; }
void setRedBand( int band ) { mRedBand = band; }
Expand Down
166 changes: 80 additions & 86 deletions src/core/raster/qgspalettedrasterrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@
#include <QDomElement>
#include <QImage>

QgsPalettedRasterRenderer::QgsPalettedRasterRenderer( QgsRasterDataProvider* provider, int bandNumber,
QgsPalettedRasterRenderer::QgsPalettedRasterRenderer( QgsRasterFace* input, int bandNumber,
QColor* colorArray, int nColors ):
QgsRasterRenderer( provider, "paletted" ), mBandNumber( bandNumber ), mColors( colorArray ), mNColors( nColors )
QgsRasterRenderer( input, "paletted" ), mBandNumber( bandNumber ), mColors( colorArray ), mNColors( nColors )
{
}

Expand All @@ -34,7 +34,7 @@ QgsPalettedRasterRenderer::~QgsPalettedRasterRenderer()
delete[] mColors;
}

QgsRasterRenderer* QgsPalettedRasterRenderer::create( const QDomElement& elem, QgsRasterDataProvider* provider )
QgsRasterRenderer* QgsPalettedRasterRenderer::create( const QDomElement& elem, QgsRasterFace* input )
{
if ( elem.isNull() )
{
Expand Down Expand Up @@ -62,7 +62,7 @@ QgsRasterRenderer* QgsPalettedRasterRenderer::create( const QDomElement& elem, Q
colors[value] = QColor( entryElem.attribute( "color", "#000000" ) );
}
}
QgsRasterRenderer* r = new QgsPalettedRasterRenderer( provider, bandNumber, colors, nColors );
QgsRasterRenderer* r = new QgsPalettedRasterRenderer( input, bandNumber, colors, nColors );
r->readXML( elem );
return r;
}
Expand All @@ -81,109 +81,103 @@ QColor* QgsPalettedRasterRenderer::colors() const
return colorArray;
}

void QgsPalettedRasterRenderer::draw( QPainter* p, QgsRasterViewPort* viewPort, const QgsMapToPixel* theQgsMapToPixel )
//void QgsPalettedRasterRenderer::draw( QPainter* p, QgsRasterViewPort* viewPort, const QgsMapToPixel* theQgsMapToPixel )
void * QgsPalettedRasterRenderer::readBlock( int bandNo, QgsRectangle const & extent, int width, int height )
{
if ( !p || !mProvider || !viewPort || !theQgsMapToPixel )
if ( !mInput )
{
return;
}

double oversamplingX, oversamplingY;
QgsRasterDataProvider::DataType transparencyType = QgsRasterDataProvider::UnknownDataType;
if ( mAlphaBand > 0 )
{
transparencyType = ( QgsRasterDataProvider::DataType )mProvider->dataType( mAlphaBand );
}
startRasterRead( mBandNumber, viewPort, theQgsMapToPixel, oversamplingX, oversamplingY );

//Read alpha band if necessary
if ( mAlphaBand > 0 && mAlphaBand != mBandNumber )
{
startRasterRead( mAlphaBand, viewPort, theQgsMapToPixel, oversamplingX, oversamplingY );
return 0;
}

//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;
QgsRasterDataProvider::DataType rasterType = ( QgsRasterDataProvider::DataType )mProvider->dataType( mBandNumber );
void* rasterData;
//double oversamplingX, oversamplingY;
//QgsRasterFace::DataType transparencyType = QgsRasterFace::UnknownDataType;
//if ( mAlphaBand > 0 )
//{
//transparencyType = ( QgsRasterFace::DataType )mInput->dataType( mAlphaBand );
//}
//startRasterRead( mBandNumber, viewPort, theQgsMapToPixel, oversamplingX, oversamplingY );

////Read alpha band if necessary
//if ( mAlphaBand > 0 && mAlphaBand != mBandNumber )
//{
//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;
QgsRasterFace::DataType rasterType = ( QgsRasterFace::DataType )mInput->dataType( mBandNumber );
void* rasterData = mInput->readBlock( bandNo, extent, width, height );
double currentOpacity = mOpacity;

//rendering is faster without considering user-defined transparency
bool hasTransparency = usesTransparency( viewPort->mSrcCRS, viewPort->mDestCRS );
// TODO
bool hasTransparency = false;
//bool hasTransparency = usesTransparency( viewPort->mSrcCRS, viewPort->mDestCRS );
void* transparencyData = 0;

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

//create image
QImage img( nRasterCols, nRasterRows, QImage::Format_ARGB32_Premultiplied );
QRgb* imageScanLine = 0;
int val = 0;
currentRasterPos = 0;
//if ( mAlphaBand > 0 && mAlphaBand != mBandNumber )
//{
//readNextRasterPart( mAlphaBand, oversamplingX, oversamplingY, viewPort, nCols, nRows, nRasterCols, nRasterRows,
//&transparencyData, topLeftCol, topLeftRow );
//}
//else if ( mAlphaBand == mBandNumber )
//{
//transparencyData = rasterData;
//}

//create image
QImage img( width, height, QImage::Format_ARGB32_Premultiplied );
QRgb* imageScanLine = 0;
int val = 0;
int currentRasterPos = 0;

for ( int i = 0; i < nRasterRows; ++i )
for ( int i = 0; i < height; ++i )
{
imageScanLine = ( QRgb* )( img.scanLine( i ) );
for ( int j = 0; j < width; ++j )
{
imageScanLine = ( QRgb* )( img.scanLine( i ) );
for ( int j = 0; j < nRasterCols; ++j )
val = readValue( rasterData, rasterType, currentRasterPos );
if ( !hasTransparency )
{
imageScanLine[j] = mColors[ val ].rgba();
}
else
{
val = readValue( rasterData, rasterType, currentRasterPos );
if ( !hasTransparency )
currentOpacity = mOpacity;
if ( mRasterTransparency )
{
imageScanLine[j] = mColors[ val ].rgba();
currentOpacity = mRasterTransparency->alphaValue( val, mOpacity * 255 ) / 255.0;
}
//if ( mAlphaBand > 0 )
//{
//currentOpacity *= ( readValue( transparencyData, transparencyType, currentRasterPos ) / 255.0 );
//}
QColor& currentColor = mColors[val];

if ( mInvertColor )
{
imageScanLine[j] = qRgba( currentOpacity * currentColor.blue(), currentOpacity * currentColor.green(), currentOpacity * currentColor.red(), currentOpacity * 255 );
}
else
{
currentOpacity = mOpacity;
if ( mRasterTransparency )
{
currentOpacity = mRasterTransparency->alphaValue( val, mOpacity * 255 ) / 255.0;
}
if ( mAlphaBand > 0 )
{
currentOpacity *= ( readValue( transparencyData, transparencyType, currentRasterPos ) / 255.0 );
}
QColor& currentColor = mColors[val];

if ( mInvertColor )
{
imageScanLine[j] = qRgba( currentOpacity * currentColor.blue(), currentOpacity * currentColor.green(), currentOpacity * currentColor.red(), currentOpacity * 255 );
}
else
{
imageScanLine[j] = qRgba( currentOpacity * currentColor.red(), currentOpacity * currentColor.green(), currentOpacity * currentColor.blue(), currentOpacity * 255 );
}
imageScanLine[j] = qRgba( currentOpacity * currentColor.red(), currentOpacity * currentColor.green(), currentOpacity * currentColor.blue(), currentOpacity * 255 );
}
++currentRasterPos;
}
++currentRasterPos;
}

drawImage( p, viewPort, img, topLeftCol, topLeftRow, nCols, nRows, oversamplingX, oversamplingY );
}

//stop raster reading
stopRasterRead( mBandNumber );
if ( mAlphaBand > 0 && mAlphaBand != mBandNumber )
{
stopRasterRead( mAlphaBand );
}
VSIFree( rasterData );
void * data = VSIMalloc( img.byteCount() );
return memcpy( data, img.bits(), img.byteCount() );
}

void QgsPalettedRasterRenderer::writeXML( QDomDocument& doc, QDomElement& parentElem ) const
Expand Down
6 changes: 4 additions & 2 deletions src/core/raster/qgspalettedrasterrenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,14 @@ class CORE_EXPORT QgsPalettedRasterRenderer: public QgsRasterRenderer
{
public:
/**Renderer owns color array*/
QgsPalettedRasterRenderer( QgsRasterDataProvider* provider, int bandNumber, QColor* colorArray, int nColors );
QgsPalettedRasterRenderer( QgsRasterFace* input, int bandNumber, QColor* colorArray, int nColors );
~QgsPalettedRasterRenderer();
static QgsRasterRenderer* create( const QDomElement& elem, QgsRasterDataProvider* provider );
static QgsRasterRenderer* create( const QDomElement& elem, QgsRasterFace* input );

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

void * readBlock( int bandNo, QgsRectangle const & extent, int width, int height );

/**Returns number of colors*/
int nColors() const { return mNColors; }
/**Returns copy of color array (caller takes ownership)*/
Expand Down
220 changes: 220 additions & 0 deletions src/core/raster/qgsrasterdrawer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
/***************************************************************************
qgsrasterdrawer.cpp
---------------------
begin : June 2012
copyright : (C) 2012 by Radim Blazek
email : radim dot blazek at gmail.com
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

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

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

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

QgsRasterDrawer::QgsRasterDrawer( QgsRasterFace* input ): mInput( input )
{
}

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 )
{
return;
}

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

//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;

// We know that the output data type of last pipe filter is QImage data
//QgsRasterDataProvider::DataType rasterType = ( QgsRasterDataProvider::DataType )mProvider->dataType( mGrayBand );

void* rasterData;

// readNextRasterPart calcs and resets nCols, nRows, topLeftCol, topLeftRow
while ( readNextRasterPart( bandNumber, viewPort, nCols, nRows,
&rasterData, topLeftCol, topLeftRow ) )
{
//create image
//QImage img( nRasterCols, nRasterRows, QImage::Format_ARGB32_Premultiplied );

// TODO: the exact format should be read from input
QImage img(( uchar * ) rasterData, nCols, nRows, QImage::Format_ARGB32_Premultiplied );
drawImage( p, viewPort, img, topLeftCol, topLeftRow );

// QImage does not delete data block passed to constructor
free( rasterData );
}
}

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->readBlock( 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 )
{
return;
}

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

p->drawImage( tlPoint, img );
}

136 changes: 136 additions & 0 deletions src/core/raster/qgsrasterdrawer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/***************************************************************************
qgsrasterdrawer.h
-------------------
begin : June 2012
copyright : (C) 2012 by Radim Blazek
email : radim dot blazek at gmail.com
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#ifndef QGSRASTERDRAWER_H
#define QGSRASTERDRAWER_H

//#include "qgsrasterdataprovider.h"
#include "qgsrasterface.h"

#include <QMap>

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

class QDomElement;

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( QgsRasterFace* input );
~QgsRasterDrawer();

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

protected:
//inline double readValue( void *data, QgsRasterFace::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 );

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

private:
/**Remove part into and release memory*/
void removePartInfo( int bandNumer );
};
/*
inline double QgsRasterDrawer::readValue( void *data, QgsRasterFace::DataType type, int index )
{
if ( !mProvider )
{
return 0;
}
if ( !data )
{
return mProvider->noDataValue();
}
switch ( type )
{
case QgsRasterFace::Byte:
return ( double )(( GByte * )data )[index];
break;
case QgsRasterFace::UInt16:
return ( double )(( GUInt16 * )data )[index];
break;
case QgsRasterFace::Int16:
return ( double )(( GInt16 * )data )[index];
break;
case QgsRasterFace::UInt32:
return ( double )(( GUInt32 * )data )[index];
break;
case QgsRasterFace::Int32:
return ( double )(( GInt32 * )data )[index];
break;
case QgsRasterFace::Float32:
return ( double )(( float * )data )[index];
break;
case QgsRasterFace::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
29 changes: 29 additions & 0 deletions src/core/raster/qgsrasterface.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/***************************************************************************
qgsrasterface.cpp - Internal raster processing modules interface
--------------------------------------
Date : Jun 21, 2012
Copyright : (C) 2012 by Radim Blazek
email : radim dot blazek at gmail dot com
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgsrasterface.h"
#include "qgslogger.h"

#include <QByteArray>

QgsRasterFace::QgsRasterFace( QgsRasterFace * input ): mInput( input )
{
}

QgsRasterFace::~QgsRasterFace()
{
}
130 changes: 130 additions & 0 deletions src/core/raster/qgsrasterface.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/***************************************************************************
qgsrasterface.h - Internal raster processing modules interface
--------------------------------------
Date : Jun 21, 2012
Copyright : (C) 2012 by Radim Blazek
email : radim dot blazek at gmail dot com
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#ifndef QGSRASTERFACE_H
#define QGSRASTERFACE_H

#include <QObject>

#include "qgsrectangle.h"

/** \ingroup core
* Base class for processing modules.
*/
// TODO: inherit from QObject? QgsRasterDataProvider inherits already from QObject
class CORE_EXPORT QgsRasterFace //: public QObject
{

//Q_OBJECT

public:

// TODO: This is copy of QgsRasterDataProvider::DataType, the QgsRasterDataProvider
// should use this DataType
// This is modified copy of GDALDataType
enum DataType
{
/*! Unknown or unspecified type */ UnknownDataType = 0,
/*! Eight bit unsigned integer */ Byte = 1,
/*! Sixteen bit unsigned integer */ UInt16 = 2,
/*! Sixteen bit signed integer */ Int16 = 3,
/*! Thirty two bit unsigned integer */ UInt32 = 4,
/*! Thirty two bit signed integer */ Int32 = 5,
/*! Thirty two bit floating point */ Float32 = 6,
/*! Sixty four bit floating point */ Float64 = 7,
/*! Complex Int16 */ CInt16 = 8,
/*! Complex Int32 */ CInt32 = 9,
/*! Complex Float32 */ CFloat32 = 10,
/*! Complex Float64 */ CFloat64 = 11,
/*! Color, alpha, red, green, blue, 4 bytes */ ARGBDataType = 12,
TypeCount = 13 /* maximum type # + 1 */
};

int typeSize( int dataType ) const
{
// modified copy from GDAL
switch ( dataType )
{
case Byte:
return 8;

case UInt16:
case Int16:
return 16;

case UInt32:
case Int32:
case Float32:
case CInt16:
return 32;

case Float64:
case CInt32:
case CFloat32:
return 64;

case CFloat64:
return 128;

case ARGBDataType:
return 32;

default:
return 0;
}
}
int dataTypeSize( int bandNo ) const
{
return typeSize( dataType( bandNo ) );
}


QgsRasterFace( QgsRasterFace * input = 0 );

virtual ~QgsRasterFace();

/** Returns data type for the band specified by number */
virtual int dataType( int bandNo ) const
{
return UnknownDataType;
}

// TODO
virtual double noDataValue() const { return 0; }

/** Read block of data using given extent and size.
* Returns pointer to data.
* Caller is responsible to free the memory returned.
*/
virtual void * readBlock( int bandNo, QgsRectangle const & extent, int width, int height )
{
Q_UNUSED( bandNo ); Q_UNUSED( extent ); Q_UNUSED( width ); Q_UNUSED( height );
return 0;
}

void setInput( QgsRasterFace* input ) { mInput = input; }

//protected:
// QgsRasterFace from used as input, data are read from it
QgsRasterFace* mInput;


};

#endif


12 changes: 7 additions & 5 deletions src/core/raster/qgsrasterlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ email : tim at linfiniti.com
#include "qgscolorrampshader.h"

//renderers
#include "qgspalettedrasterrenderer.h"
#include "qgsmultibandcolorrenderer.h"
#include "qgssinglebandcolordatarenderer.h"
#include "qgssinglebandpseudocolorrenderer.h"
//#include "qgspalettedrasterrenderer.h"
//#include "qgsmultibandcolorrenderer.h"
//#include "qgssinglebandcolordatarenderer.h"
//#include "qgssinglebandpseudocolorrenderer.h"
#include "qgssinglebandgrayrenderer.h"

#include <cstdio>
Expand Down Expand Up @@ -823,7 +823,9 @@ void QgsRasterLayer::draw( QPainter * theQPainter,

if ( mRenderer )
{
mRenderer->draw( theQPainter, theRasterViewPort, theQgsMapToPixel );
//mRenderer->draw( theQPainter, theRasterViewPort, theQgsMapToPixel );
QgsRasterDrawer drawer( mRenderer );
drawer.draw( theQPainter, theRasterViewPort, theQgsMapToPixel );
}

QgsDebugMsg( QString( "raster draw time (ms): %1" ).arg( time.elapsed() ) );
Expand Down
2 changes: 2 additions & 0 deletions src/core/raster/qgsrasterlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
#include "qgsrastershader.h"
#include "qgscolorrampshader.h"
#include "qgsrastershaderfunction.h"
#include "qgsrasterface.h"
#include "qgsrasterdrawer.h"
#include "qgsrasterdataprovider.h"

//
Expand Down
39 changes: 23 additions & 16 deletions src/core/raster/qgsrasterrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
#include <QImage>
#include <QPainter>

QgsRasterRenderer::QgsRasterRenderer( QgsRasterDataProvider* provider, const QString& type ): mProvider( provider ),
//QgsRasterRenderer::QgsRasterRenderer( QgsRasterFace* input, const QString& type ): mInput( input ),
QgsRasterRenderer::QgsRasterRenderer( QgsRasterFace* input, const QString& type ): QgsRasterFace( input ),
mType( type ), mZoomedInResampler( 0 ), mZoomedOutResampler( 0 ), mOpacity( 1.0 ), mRasterTransparency( 0 ),
mAlphaBand( -1 ), mInvertColor( false ), mMaxOversampling( 2.0 )
{
Expand All @@ -40,11 +41,11 @@ QgsRasterRenderer::QgsRasterRenderer( QgsRasterDataProvider* provider, const QSt
QgsRasterRenderer::~QgsRasterRenderer()
{
//remove remaining memory in partinfos
QMap<int, RasterPartInfo>::iterator partIt = mRasterPartInfos.begin();
for ( ; partIt != mRasterPartInfos.end(); ++partIt )
{
CPLFree( partIt.value().data );
}
//QMap<int, RasterPartInfo>::iterator partIt = mRasterPartInfos.begin();
//for ( ; partIt != mRasterPartInfos.end(); ++partIt )
//{
//CPLFree( partIt.value().data );
//}

delete mZoomedInResampler;
delete mZoomedOutResampler;
Expand All @@ -63,9 +64,10 @@ void QgsRasterRenderer::setZoomedOutResampler( QgsRasterResampler* r )
mZoomedOutResampler = r;
}

/*
void QgsRasterRenderer::startRasterRead( int bandNumber, QgsRasterViewPort* viewPort, const QgsMapToPixel* mapToPixel, double& oversamplingX, double& oversamplingY )
{
if ( !viewPort || !mapToPixel || !mProvider )
if ( !viewPort || !mapToPixel || !mInput )
{
return;
}
Expand All @@ -78,13 +80,13 @@ void QgsRasterRenderer::startRasterRead( int bandNumber, QgsRasterViewPort* view
if ( mZoomedInResampler || mZoomedOutResampler )
{
QgsRectangle providerExtent = mProvider->extent();
QgsRectangle providerExtent = mInput->extent();
if ( viewPort->mSrcCRS.isValid() && viewPort->mDestCRS.isValid() && viewPort->mSrcCRS != viewPort->mDestCRS )
{
QgsCoordinateTransform t( viewPort->mSrcCRS, viewPort->mDestCRS );
providerExtent = t.transformBoundingBox( providerExtent );
}
double pixelRatio = mapToPixel->mapUnitsPerPixel() / ( providerExtent.width() / mProvider->xSize() );
double pixelRatio = mapToPixel->mapUnitsPerPixel() / ( providerExtent.width() / mInput->xSize() );
oversampling = ( pixelRatio > mMaxOversampling ) ? mMaxOversampling : pixelRatio;
}
Expand All @@ -103,7 +105,7 @@ void QgsRasterRenderer::startRasterRead( int bandNumber, QgsRasterViewPort* view
oversamplingX = (( double )pInfo.nCols * oversampling ) / viewPort->drawableAreaXDim;
oversamplingY = (( double )pInfo.nRows * oversampling ) / viewPort->drawableAreaYDim;
int totalMemoryUsage = pInfo.nCols * oversamplingX * pInfo.nRows * oversamplingY * mProvider->dataTypeSize( bandNumber );
int totalMemoryUsage = pInfo.nCols * oversamplingX * pInfo.nRows * oversamplingY * mInput->dataTypeSize( bandNumber );
int parts = totalMemoryUsage / 100000000 + 1;
int nPartsPerDimension = sqrt(( double ) parts );
pInfo.nColsPerPart = pInfo.nCols / nPartsPerDimension;
Expand Down Expand Up @@ -147,7 +149,7 @@ bool QgsRasterRenderer::readNextRasterPart( int bandNumber, double oversamplingX
//read data block
nCols = qMin( pInfo.nColsPerPart, pInfo.nCols - pInfo.currentCol );
nRows = qMin( pInfo.nRowsPerPart, pInfo.nRows - pInfo.currentRow );
int typeSize = mProvider->dataTypeSize( bandNumber ) / 8;
int typeSize = mInput->dataTypeSize( bandNumber ) / 8;
//get subrectangle
QgsRectangle viewPortExtent = viewPort->mDrawnExtent;
Expand All @@ -160,7 +162,7 @@ bool QgsRasterRenderer::readNextRasterPart( int bandNumber, double oversamplingX
if ( viewPort->mSrcCRS.isValid() && viewPort->mDestCRS.isValid() && viewPort->mSrcCRS != viewPort->mDestCRS )
{
pInfo.prj = new QgsRasterProjector( viewPort->mSrcCRS,
viewPort->mDestCRS, blockRect, nRows, nCols, 0, 0, mProvider->extent() );
viewPort->mDestCRS, blockRect, nRows, nCols, 0, 0, mInput->extent() );
// If we zoom out too much, projector srcRows / srcCols maybe 0, which can cause problems in providers
if ( pInfo.prj->srcRows() <= 0 || pInfo.prj->srcCols() <= 0 )
Expand All @@ -183,8 +185,10 @@ bool QgsRasterRenderer::readNextRasterPart( int bandNumber, double oversamplingX
nColsRaster = nCols * oversamplingX;
nRowsRaster = nRows * oversamplingY;
}
pInfo.data = VSIMalloc( typeSize * nColsRaster * nRowsRaster );
mProvider->readBlock( bandNumber, blockRect, nColsRaster, nRowsRaster, pInfo.data );
//pInfo.data = VSIMalloc( typeSize * nColsRaster * nRowsRaster );
//mInput->readBlock( bandNumber, blockRect, nColsRaster, nRowsRaster, pInfo.data );
pInfo.data = mInput->readBlock( bandNumber, blockRect, nColsRaster, nRowsRaster );
*rasterData = pInfo.data;
topLeftCol = pInfo.currentCol;
topLeftRow = pInfo.currentRow;
Expand Down Expand Up @@ -219,16 +223,17 @@ void QgsRasterRenderer::removePartInfo( int bandNumber )
mRasterPartInfos.remove( bandNumber );
}
}
*/

bool QgsRasterRenderer::usesTransparency( QgsCoordinateReferenceSystem& srcSRS, QgsCoordinateReferenceSystem& dstSRS ) const
{
//transparency is always used if on-the-fly reprojection is enabled
bool reprojectionEnabled = ( srcSRS.isValid() && dstSRS.isValid() && srcSRS != dstSRS );
if ( !mProvider || reprojectionEnabled )
if ( !mInput || reprojectionEnabled )
{
return true;
}
return ( mAlphaBand > 0 || ( mRasterTransparency && !mRasterTransparency->isEmpty( mProvider->noDataValue() ) ) || !doubleNear( mOpacity, 1.0 ) );
return ( mAlphaBand > 0 || ( mRasterTransparency && !mRasterTransparency->isEmpty( mInput->noDataValue() ) ) || !doubleNear( mOpacity, 1.0 ) );
}

void QgsRasterRenderer::setRasterTransparency( QgsRasterTransparency* t )
Expand All @@ -237,6 +242,7 @@ void QgsRasterRenderer::setRasterTransparency( QgsRasterTransparency* t )
mRasterTransparency = t;
}

/*
void QgsRasterRenderer::drawImage( QPainter* p, QgsRasterViewPort* viewPort, const QImage& img, int topLeftCol, int topLeftRow,
int nCols, int nRows, double oversamplingX, double oversamplingY ) const
{
Expand Down Expand Up @@ -317,6 +323,7 @@ void QgsRasterRenderer::projectImage( const QImage& srcImg, QImage& dstImage, Qg
}
}
}
*/

void QgsRasterRenderer::_writeXML( QDomDocument& doc, QDomElement& rasterRendererElem ) const
{
Expand Down
92 changes: 26 additions & 66 deletions src/core/raster/qgsrasterrenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#ifndef QGSRASTERRENDERER_H
#define QGSRASTERRENDERER_H

#include "qgsrasterface.h"
#include "qgsrasterdataprovider.h"
#include <QPair>

Expand All @@ -30,27 +31,20 @@ struct QgsRasterViewPort;

class QDomElement;

class CORE_EXPORT QgsRasterRenderer
class CORE_EXPORT QgsRasterRenderer : public QgsRasterFace
{
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)
};

QgsRasterRenderer( QgsRasterDataProvider* provider, const QString& type );
QgsRasterRenderer( QgsRasterFace* input, const QString& type );
virtual ~QgsRasterRenderer();

virtual QString type() const { return mType; }
virtual void draw( QPainter* p, QgsRasterViewPort* viewPort, const QgsMapToPixel* theQgsMapToPixel ) = 0;
//virtual void draw( QPainter* p, QgsRasterViewPort* viewPort, const QgsMapToPixel* theQgsMapToPixel ) = 0;

virtual void * readBlock( int bandNo, QgsRectangle const & extent, int width, int height )
{
Q_UNUSED( bandNo ); Q_UNUSED( extent ); Q_UNUSED( width ); Q_UNUSED( height );
return 0;
}

bool usesTransparency( QgsCoordinateReferenceSystem& srcSRS, QgsCoordinateReferenceSystem& dstSRS ) const;

Expand Down Expand Up @@ -86,55 +80,19 @@ class CORE_EXPORT QgsRasterRenderer
void readXML( const QDomElement& rendererElem );

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 bandNumber number of raster band to read
@param viewPort describes raster position on screen
@param mapToPixel transform map to pixel
@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 );
/**Fetches next part of raster data
@param bandNumber number of raster band to read
@param oversamplingX oversampling rate in x-direction
@param oversamplingY oversampling rate in y-direction
@param viewPort view port
@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)
@param rasterData raster data
@param topLeftCol Left position relative to left border of viewport
@param topLeftRow Top position relative to top border of viewport*/
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 p the painter
@param viewPort view port
@param img image
@param topLeftCol Left position relative to left border of viewport
@param topLeftRow Top position relative to top border of viewport
@param nCols number of columns
@param nRows number of rows
@param oversamplingX oversampling rate in x-direction
@param oversamplingY oversampling rate in y-direction
*/
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 );
inline double readValue( void *data, QgsRasterFace::DataType type, int index );

/**Write upper class info into rasterrenderer element (called by writeXML method of subclasses)*/
void _writeXML( QDomDocument& doc, QDomElement& rasterRendererElem ) const;


QgsRasterDataProvider* mProvider;
QgsRasterFace* mProvider;
QString mType;
/**Resampler used if screen resolution is higher than raster resolution (zoomed in). 0 means no resampling (nearest neighbour)*/
QgsRasterResampler* mZoomedInResampler;
/**Resampler used if raster resolution is higher than raster resolution (zoomed out). 0 mean no resampling (nearest neighbour)*/
QgsRasterResampler* mZoomedOutResampler;
QMap<int, RasterPartInfo> mRasterPartInfos;
//QMap<int, RasterPartInfo> mRasterPartInfos;

/**Global alpha value (0-1)*/
double mOpacity;
Expand All @@ -155,47 +113,49 @@ class CORE_EXPORT QgsRasterRenderer
void projectImage( const QImage& srcImg, QImage& dstImage, QgsRasterProjector* prj ) const;
};

inline double QgsRasterRenderer::readValue( void *data, QgsRasterDataProvider::DataType type, int index )
inline double QgsRasterRenderer::readValue( void *data, QgsRasterFace::DataType type, int index )
{
if ( !mProvider )
if ( !mInput )
{
return 0;
}

if ( !data )
{
return mProvider->noDataValue();
// TODO
//return mInput->noDataValue();
return 0;
}

switch ( type )
{
case QgsRasterDataProvider::Byte:
case QgsRasterFace::Byte:
return ( double )(( GByte * )data )[index];
break;
case QgsRasterDataProvider::UInt16:
case QgsRasterFace::UInt16:
return ( double )(( GUInt16 * )data )[index];
break;
case QgsRasterDataProvider::Int16:
case QgsRasterFace::Int16:
return ( double )(( GInt16 * )data )[index];
break;
case QgsRasterDataProvider::UInt32:
case QgsRasterFace::UInt32:
return ( double )(( GUInt32 * )data )[index];
break;
case QgsRasterDataProvider::Int32:
case QgsRasterFace::Int32:
return ( double )(( GInt32 * )data )[index];
break;
case QgsRasterDataProvider::Float32:
case QgsRasterFace::Float32:
return ( double )(( float * )data )[index];
break;
case QgsRasterDataProvider::Float64:
case QgsRasterFace::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();
return mInput->noDataValue();
}

#endif // QGSRASTERRENDERER_H
5 changes: 3 additions & 2 deletions src/core/raster/qgsrasterrendererregistry.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,13 @@
#include <QString>

class QDomElement;
class QgsRasterDataProvider;
//class QgsRasterDataProvider;
class QgsRasterFace;
class QgsRasterLayer;
class QgsRasterRenderer;
class QgsRasterRendererWidget;

typedef QgsRasterRenderer*( *QgsRasterRendererCreateFunc )( const QDomElement&, QgsRasterDataProvider* provider );
typedef QgsRasterRenderer*( *QgsRasterRendererCreateFunc )( const QDomElement&, QgsRasterFace* input );
typedef QgsRasterRendererWidget*( *QgsRasterRendererWidgetCreateFunc )( QgsRasterLayer* );

struct CORE_EXPORT QgsRasterRendererRegistryEntry
Expand Down
55 changes: 30 additions & 25 deletions src/core/raster/qgssinglebandcolordatarenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
#include <QDomElement>
#include <QImage>

QgsSingleBandColorDataRenderer::QgsSingleBandColorDataRenderer( QgsRasterDataProvider* provider, int band ):
QgsRasterRenderer( provider, "singlebandcolordata" ), mBand( band )
QgsSingleBandColorDataRenderer::QgsSingleBandColorDataRenderer( QgsRasterFace* input, int band ):
QgsRasterRenderer( input, "singlebandcolordata" ), mBand( band )
{

}
Expand All @@ -31,28 +31,28 @@ QgsSingleBandColorDataRenderer::~QgsSingleBandColorDataRenderer()
{
}

QgsRasterRenderer* QgsSingleBandColorDataRenderer::create( const QDomElement& elem, QgsRasterDataProvider* provider )
QgsRasterRenderer* QgsSingleBandColorDataRenderer::create( const QDomElement& elem, QgsRasterFace* input )
{
if ( elem.isNull() )
{
return 0;
}

int band = elem.attribute( "band", "-1" ).toInt();
QgsRasterRenderer* r = new QgsSingleBandColorDataRenderer( provider, band );
QgsRasterRenderer* r = new QgsSingleBandColorDataRenderer( input, band );
r->readXML( elem );
return r;
}

void QgsSingleBandColorDataRenderer::draw( QPainter* p, QgsRasterViewPort* viewPort, const QgsMapToPixel* theQgsMapToPixel )
void * QgsSingleBandColorDataRenderer::readBlock( int bandNo, QgsRectangle const & extent, int width, int height )
{
if ( !p || !mProvider || !viewPort || !theQgsMapToPixel )
if ( !mInput )
{
return;
return 0;
}

double oversamplingX, oversamplingY;
startRasterRead( mBand, viewPort, theQgsMapToPixel, oversamplingX, oversamplingY );
//startRasterRead( mBand, viewPort, theQgsMapToPixel, oversamplingX, oversamplingY );

//number of cols/rows in output pixels
int nCols = 0;
Expand All @@ -64,24 +64,29 @@ void QgsSingleBandColorDataRenderer::draw( QPainter* p, QgsRasterViewPort* viewP
int topLeftCol = 0;
int topLeftRow = 0;
int currentRasterPos;
void* rasterData;

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

QgsRasterFace::DataType rasterType = ( QgsRasterFace::DataType )mInput->dataType( mBand );


void* rasterData = mInput->readBlock( bandNo, extent, width, height );

while ( readNextRasterPart( mBand, oversamplingX, oversamplingY, viewPort, nCols, nRows, nRasterCols, nRasterRows, &rasterData, topLeftCol, topLeftRow ) )
currentRasterPos = 0;
QImage img( width, height, QImage::Format_ARGB32 );
uchar* scanLine = 0;
for ( int i = 0; i < height; ++i )
{
currentRasterPos = 0;
QImage img( nRasterCols, nRasterRows, QImage::Format_ARGB32 );
uchar* scanLine = 0;
for ( int i = 0; i < nRasterRows; ++i )
scanLine = img.scanLine( i );
if ( !hasTransparency )
{
scanLine = img.scanLine( i );
if ( !hasTransparency )
{
memcpy( scanLine, &((( uint* )rasterData )[currentRasterPos] ), nCols * 4 );
currentRasterPos += nRasterCols;
}
else
memcpy( scanLine, &((( uint* )rasterData )[currentRasterPos] ), nCols * 4 );
currentRasterPos += nRasterCols;
}
else
{
for ( int j = 0; j < width; ++j )
{
QRgb pixelColor;
double alpha = 255.0;
Expand All @@ -95,11 +100,11 @@ void QgsSingleBandColorDataRenderer::draw( QPainter* p, QgsRasterViewPort* viewP
}
}
}

drawImage( p, viewPort, img, topLeftCol, topLeftRow, nCols, nRows, oversamplingX, oversamplingY );
}
VSIFree( rasterData );

stopRasterRead( mBand );
void * data = VSIMalloc( img.byteCount() );
return memcpy( data, img.bits(), img.byteCount() );
}

void QgsSingleBandColorDataRenderer::writeXML( QDomDocument& doc, QDomElement& parentElem ) const
Expand Down
8 changes: 5 additions & 3 deletions src/core/raster/qgssinglebandcolordatarenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@ class QDomElement;
class CORE_EXPORT QgsSingleBandColorDataRenderer: public QgsRasterRenderer
{
public:
QgsSingleBandColorDataRenderer( QgsRasterDataProvider* provider, int band );
QgsSingleBandColorDataRenderer( QgsRasterFace* input, int band );
~QgsSingleBandColorDataRenderer();

static QgsRasterRenderer* create( const QDomElement& elem, QgsRasterDataProvider* provider );
static QgsRasterRenderer* create( const QDomElement& elem, QgsRasterFace* input );

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

void * readBlock( int bandNo, QgsRectangle const & extent, int width, int height );

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

Expand Down
180 changes: 89 additions & 91 deletions src/core/raster/qgssinglebandgrayrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
#include <QDomElement>
#include <QImage>

QgsSingleBandGrayRenderer::QgsSingleBandGrayRenderer( QgsRasterDataProvider* provider, int grayBand ):
QgsRasterRenderer( provider, "singlebandgray" ), mGrayBand( grayBand ), mContrastEnhancement( 0 )
QgsSingleBandGrayRenderer::QgsSingleBandGrayRenderer( QgsRasterFace* input, int grayBand ):
QgsRasterRenderer( input, "singlebandgray" ), mGrayBand( grayBand ), mContrastEnhancement( 0 )
{
}

Expand All @@ -32,22 +32,22 @@ QgsSingleBandGrayRenderer::~QgsSingleBandGrayRenderer()
delete mContrastEnhancement;
}

QgsRasterRenderer* QgsSingleBandGrayRenderer::create( const QDomElement& elem, QgsRasterDataProvider* provider )
QgsRasterRenderer* QgsSingleBandGrayRenderer::create( const QDomElement& elem, QgsRasterFace* input )
{
if ( elem.isNull() )
{
return 0;
}

int grayBand = elem.attribute( "grayBand", "-1" ).toInt();
QgsSingleBandGrayRenderer* r = new QgsSingleBandGrayRenderer( provider, grayBand );
QgsSingleBandGrayRenderer* r = new QgsSingleBandGrayRenderer( input, grayBand );
r->readXML( elem );

QDomElement contrastEnhancementElem = elem.firstChildElement( "contrastEnhancement" );
if ( !contrastEnhancementElem.isNull() )
{
QgsContrastEnhancement* ce = new QgsContrastEnhancement(( QgsContrastEnhancement::QgsRasterDataType )(
provider->dataType( grayBand ) ) ) ;
input->dataType( grayBand ) ) ) ;
ce->readXML( contrastEnhancementElem );
r->setContrastEnhancement( ce );
}
Expand All @@ -60,115 +60,113 @@ void QgsSingleBandGrayRenderer::setContrastEnhancement( QgsContrastEnhancement*
mContrastEnhancement = ce;
}

void QgsSingleBandGrayRenderer::draw( QPainter* p, QgsRasterViewPort* viewPort, const QgsMapToPixel* theQgsMapToPixel )
//void QgsSingleBandGrayRenderer::draw( QPainter* p, QgsRasterViewPort* viewPort, const QgsMapToPixel* theQgsMapToPixel )
void * QgsSingleBandGrayRenderer::readBlock( int bandNo, QgsRectangle const & extent, int width, int height )
{
if ( !p || !mProvider || !viewPort || !theQgsMapToPixel )
//if ( !mInput || !viewPort || !theQgsMapToPixel )
if ( !mInput )
{
return;
return 0;
}

double oversamplingX, oversamplingY;
startRasterRead( mGrayBand, viewPort, theQgsMapToPixel, oversamplingX, oversamplingY );
if ( mAlphaBand > 0 && mGrayBand != mAlphaBand )
{
startRasterRead( mAlphaBand, viewPort, theQgsMapToPixel, oversamplingX, oversamplingY );
}
//double oversamplingX, oversamplingY;
//startRasterRead( mGrayBand, viewPort, theQgsMapToPixel, oversamplingX, oversamplingY );
//if ( mAlphaBand > 0 && mGrayBand != mAlphaBand )
//{
//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 );
QgsRasterDataProvider::DataType alphaType = QgsRasterDataProvider::UnknownDataType;
if ( mAlphaBand > 0 )
{
alphaType = ( QgsRasterDataProvider::DataType )mProvider->dataType( mAlphaBand );
}
void* rasterData;
void* alphaData = 0;
//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;

QgsRasterFace::DataType rasterType = ( QgsRasterFace::DataType )mInput->dataType( mGrayBand );
//QgsRasterFace::DataType alphaType = QgsRasterFace::UnknownDataType;
//if ( mAlphaBand > 0 )
//{
//alphaType = ( QgsRasterFace::DataType )mInput->dataType( mAlphaBand );
//}

void* rasterData = mInput->readBlock( mGrayBand, extent, width, height );
//void* alphaData;
double currentAlpha = mOpacity;
int grayVal;
QRgb myDefaultColor = qRgba( 0, 0, 0, 0 );


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

//create image
QImage img( width, height, QImage::Format_ARGB32_Premultiplied );
QRgb* imageScanLine = 0;
int currentRasterPos = 0;

for ( int i = 0; i < height; ++i )
{
if ( mAlphaBand > 0 && mGrayBand != mAlphaBand )
imageScanLine = ( QRgb* )( img.scanLine( i ) );
for ( int j = 0; j < width; ++j )
{
readNextRasterPart( mAlphaBand, oversamplingX, oversamplingY, viewPort, nCols, nRows, nRasterCols, nRasterRows,
&alphaData, topLeftCol, topLeftRow );
}
else if ( mAlphaBand > 0 )
{
alphaData = rasterData;
}
grayVal = readValue( rasterData, rasterType, currentRasterPos );


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

for ( int i = 0; i < nRasterRows; ++i )
{
imageScanLine = ( QRgb* )( img.scanLine( i ) );
for ( int j = 0; j < nRasterCols; ++j )
//alpha
currentAlpha = mOpacity;
if ( mRasterTransparency )
{
grayVal = readValue( rasterData, rasterType, currentRasterPos );

//alpha
currentAlpha = mOpacity;
if ( mRasterTransparency )
{
currentAlpha = mRasterTransparency->alphaValue( grayVal, mOpacity * 255 ) / 255.0;
}
if ( mAlphaBand > 0 )
{
currentAlpha *= ( readValue( alphaData, alphaType, currentRasterPos ) / 255.0 );
}
currentAlpha = mRasterTransparency->alphaValue( grayVal, mOpacity * 255 ) / 255.0;
}
if ( mAlphaBand > 0 )
{
currentAlpha *= ( readValue( alphaData, alphaType, currentRasterPos ) / 255.0 );
}

if ( mContrastEnhancement )
if ( mContrastEnhancement )
{
if ( !mContrastEnhancement->isValueInDisplayableRange( grayVal ) )
{
if ( !mContrastEnhancement->isValueInDisplayableRange( grayVal ) )
{
imageScanLine[ j ] = myDefaultColor;
++currentRasterPos;
continue;
}
grayVal = mContrastEnhancement->enhanceContrast( grayVal );
imageScanLine[ j ] = myDefaultColor;
++currentRasterPos;
continue;
}
grayVal = mContrastEnhancement->enhanceContrast( grayVal );
}

if ( mInvertColor )
{
grayVal = 255 - grayVal;
}
if ( mInvertColor )
{
grayVal = 255 - grayVal;
}

if ( doubleNear( currentAlpha, 1.0 ) )
{
imageScanLine[j] = qRgba( grayVal, grayVal, grayVal, 255 );
}
else
{
imageScanLine[j] = qRgba( currentAlpha * grayVal, currentAlpha * grayVal, currentAlpha * grayVal, currentAlpha * 255 );
}
++currentRasterPos;
if ( doubleNear( currentAlpha, 1.0 ) )
{
imageScanLine[j] = qRgba( grayVal, grayVal, grayVal, 255 );
}
else
{
imageScanLine[j] = qRgba( currentAlpha * grayVal, currentAlpha * grayVal, currentAlpha * grayVal, currentAlpha * 255 );
}
++currentRasterPos;
}

drawImage( p, viewPort, img, topLeftCol, topLeftRow, nCols, nRows, oversamplingX, oversamplingY );
}

stopRasterRead( mGrayBand );
if ( mAlphaBand > 0 && mGrayBand != mAlphaBand )
{
stopRasterRead( mAlphaBand );
}
VSIFree( rasterData );

// TODO: howto get image data without memcpy?
// TODO: byteCount() added in 4.6, QGIS requirement is Qt >= 4.4.0
void * data = VSIMalloc( img.byteCount() );

return memcpy( data, img.bits(), img.byteCount() );
}

void QgsSingleBandGrayRenderer::writeXML( QDomDocument& doc, QDomElement& parentElem ) const
Expand Down
9 changes: 6 additions & 3 deletions src/core/raster/qgssinglebandgrayrenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,15 @@ class QDomElement;
class CORE_EXPORT QgsSingleBandGrayRenderer: public QgsRasterRenderer
{
public:
QgsSingleBandGrayRenderer( QgsRasterDataProvider* provider, int grayBand );
QgsSingleBandGrayRenderer( QgsRasterFace* input, int grayBand );
~QgsSingleBandGrayRenderer();

static QgsRasterRenderer* create( const QDomElement& elem, QgsRasterDataProvider* provider );
//static QgsRasterRenderer* create( const QDomElement& elem, QgsRasterDataProvider* provider );
static QgsRasterRenderer* create( const QDomElement& elem, QgsRasterFace* input );

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

void * readBlock( int bandNo, QgsRectangle const & extent, int width, int height );

int grayBand() const { return mGrayBand; }
void setGrayBand( int band ) { mGrayBand = band; }
Expand Down
146 changes: 71 additions & 75 deletions src/core/raster/qgssinglebandpseudocolorrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
#include <QDomElement>
#include <QImage>

QgsSingleBandPseudoColorRenderer::QgsSingleBandPseudoColorRenderer( QgsRasterDataProvider* provider, int band, QgsRasterShader* shader ):
QgsRasterRenderer( provider, "singlebandpseudocolor" ), mShader( shader ), mBand( band )
QgsSingleBandPseudoColorRenderer::QgsSingleBandPseudoColorRenderer( QgsRasterFace* input, int band, QgsRasterShader* shader ):
QgsRasterRenderer( input, "singlebandpseudocolor" ), mShader( shader ), mBand( band )
{
}

Expand All @@ -39,7 +39,7 @@ void QgsSingleBandPseudoColorRenderer::setShader( QgsRasterShader* shader )
mShader = shader;
}

QgsRasterRenderer* QgsSingleBandPseudoColorRenderer::create( const QDomElement& elem, QgsRasterDataProvider* provider )
QgsRasterRenderer* QgsSingleBandPseudoColorRenderer::create( const QDomElement& elem, QgsRasterFace* input )
{
if ( elem.isNull() )
{
Expand All @@ -54,30 +54,30 @@ QgsRasterRenderer* QgsSingleBandPseudoColorRenderer::create( const QDomElement&
shader = new QgsRasterShader();
shader->readXML( rasterShaderElem );
}
QgsRasterRenderer* r = new QgsSingleBandPseudoColorRenderer( provider, band, shader );
QgsRasterRenderer* r = new QgsSingleBandPseudoColorRenderer( input, band, shader );
r->readXML( elem );
return r;
}

void QgsSingleBandPseudoColorRenderer::draw( QPainter* p, QgsRasterViewPort* viewPort, const QgsMapToPixel* theQgsMapToPixel )
void * QgsSingleBandPseudoColorRenderer::readBlock( int bandNo, QgsRectangle const & extent, int width, int height )
{
if ( !p || !mProvider || !viewPort || !theQgsMapToPixel || !mShader )
if ( !mInput || !mShader )
{
return;
return 0;
}

double oversamplingX, oversamplingY;
QgsRasterDataProvider::DataType transparencyType = QgsRasterDataProvider::UnknownDataType;
if ( mAlphaBand > 0 )
{
transparencyType = ( QgsRasterDataProvider::DataType )mProvider->dataType( mAlphaBand );
}
startRasterRead( mBand, viewPort, theQgsMapToPixel, oversamplingX, oversamplingY );
//Read alpha band if necessary
if ( mAlphaBand > 0 && mAlphaBand != mBand )
{
startRasterRead( mAlphaBand, viewPort, theQgsMapToPixel, oversamplingX, oversamplingY );
}
//double oversamplingX, oversamplingY;
//QgsRasterFace::DataType transparencyType = QgsRasterFace::UnknownDataType;
//if ( mAlphaBand > 0 )
//{
//transparencyType = ( QgsRasterFace::DataType )mInput->dataType( mAlphaBand );
//}
//startRasterRead( mBand, viewPort, theQgsMapToPixel, oversamplingX, oversamplingY );
////Read alpha band if necessary
//if ( mAlphaBand > 0 && mAlphaBand != mBand )
//{
//startRasterRead( mAlphaBand, viewPort, theQgsMapToPixel, oversamplingX, oversamplingY );
//}

//number of cols/rows in output pixels
int nCols = 0;
Expand All @@ -88,79 +88,75 @@ void QgsSingleBandPseudoColorRenderer::draw( QPainter* p, QgsRasterViewPort* vie
//shift to top left point for the raster part
int topLeftCol = 0;
int topLeftRow = 0;
void* rasterData;
void* transparencyData = 0;
double currentOpacity = mOpacity;
QgsRasterDataProvider::DataType rasterType = ( QgsRasterDataProvider::DataType )mProvider->dataType( mBand );
QgsRasterFace::DataType rasterType = ( QgsRasterFace::DataType )mInput->dataType( mBand );

void* rasterData = mInput->readBlock( mBand, extent, width, height );

int red, green, blue;
QRgb myDefaultColor = qRgba( 255, 255, 255, 0 );

//rendering is faster without considering user-defined transparency
bool hasTransparency = usesTransparency( viewPort->mSrcCRS, viewPort->mDestCRS );

while ( readNextRasterPart( mBand, oversamplingX, oversamplingY, viewPort, nCols, nRows, nRasterCols, nRasterRows,
&rasterData, topLeftCol, topLeftRow ) )
//bool hasTransparency = usesTransparency( viewPort->mSrcCRS, viewPort->mDestCRS );
bool hasTransparency = false;

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

//create image
QImage img( width, height, QImage::Format_ARGB32_Premultiplied );
QRgb* imageScanLine = 0;
double val = 0;

int currentRasterPos = 0;
for ( int i = 0; i < height; ++i )
{
if ( mAlphaBand > 0 && mAlphaBand != mBand )
{
readNextRasterPart( mAlphaBand, oversamplingX, oversamplingY, viewPort, nCols, nRows, nRasterCols, nRasterRows,
&transparencyData, topLeftCol, topLeftRow );
}
else if ( mAlphaBand == mBand )
imageScanLine = ( QRgb* )( img.scanLine( i ) );
for ( int j = 0; j < width; ++j )
{
transparencyData = rasterData;
}

//create image
QImage img( nRasterCols, nRasterRows, QImage::Format_ARGB32_Premultiplied );
QRgb* imageScanLine = 0;
double val = 0;
val = readValue( rasterData, rasterType, currentRasterPos );
if ( !mShader->shade( val, &red, &green, &blue ) )
{
imageScanLine[j] = myDefaultColor;
++currentRasterPos;
continue;
}

int currentRasterPos = 0;
for ( int i = 0; i < nRasterRows; ++i )
{
imageScanLine = ( QRgb* )( img.scanLine( i ) );
for ( int j = 0; j < nRasterCols; ++j )
if ( !hasTransparency )
{
val = readValue( rasterData, rasterType, currentRasterPos );
if ( !mShader->shade( val, &red, &green, &blue ) )
imageScanLine[j] = qRgba( red, green, blue, 255 );
}
else
{
//opacity
currentOpacity = mOpacity;
if ( mRasterTransparency )
{
imageScanLine[j] = myDefaultColor;
++currentRasterPos;
continue;
currentOpacity = mRasterTransparency->alphaValue( val, mOpacity * 255 ) / 255.0;
}
//if ( mAlphaBand > 0 )
//{
//currentOpacity *= ( readValue( transparencyData, transparencyType, currentRasterPos ) / 255.0 );
//}

if ( !hasTransparency )
{
imageScanLine[j] = qRgba( red, green, blue, 255 );
}
else
{
//opacity
currentOpacity = mOpacity;
if ( mRasterTransparency )
{
currentOpacity = mRasterTransparency->alphaValue( val, mOpacity * 255 ) / 255.0;
}
if ( mAlphaBand > 0 )
{
currentOpacity *= ( readValue( transparencyData, transparencyType, currentRasterPos ) / 255.0 );
}

imageScanLine[j] = qRgba( currentOpacity * red, currentOpacity * green, currentOpacity * blue, currentOpacity * 255 );
}
++currentRasterPos;
imageScanLine[j] = qRgba( currentOpacity * red, currentOpacity * green, currentOpacity * blue, currentOpacity * 255 );
}
++currentRasterPos;
}

drawImage( p, viewPort, img, topLeftCol, topLeftRow, nCols, nRows, oversamplingX, oversamplingY );
}

stopRasterRead( mBand );
if ( mAlphaBand > 0 && mAlphaBand != mBand )
{
stopRasterRead( mAlphaBand );
}
VSIFree( rasterData );

void * data = VSIMalloc( img.byteCount() );
return memcpy( data, img.bits(), img.byteCount() );
}

void QgsSingleBandPseudoColorRenderer::writeXML( QDomDocument& doc, QDomElement& parentElem ) const
Expand Down
8 changes: 5 additions & 3 deletions src/core/raster/qgssinglebandpseudocolorrenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,14 @@ class CORE_EXPORT QgsSingleBandPseudoColorRenderer: public QgsRasterRenderer
{
public:
/**Note: takes ownership of QgsRasterShader*/
QgsSingleBandPseudoColorRenderer( QgsRasterDataProvider* provider, int band, QgsRasterShader* shader );
QgsSingleBandPseudoColorRenderer( QgsRasterFace* input, int band, QgsRasterShader* shader );
~QgsSingleBandPseudoColorRenderer();

static QgsRasterRenderer* create( const QDomElement& elem, QgsRasterDataProvider* provider );
static QgsRasterRenderer* create( const QDomElement& elem, QgsRasterFace* input );

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

void * readBlock( int bandNo, QgsRectangle const & extent, int width, int height );

/**Takes ownership of the shader*/
void setShader( QgsRasterShader* shader );
Expand Down
5 changes: 5 additions & 0 deletions src/providers/gdal/qgsgdalprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -805,6 +805,11 @@ void QgsGdalProvider::readBlock( int theBandNo, QgsRectangle const & theExtent,
return;
}

//void * QgsGdalProvider::readBlock( int bandNo, QgsRectangle const & extent, int width, int height )
//{
// return 0;
//}

// this is old version which was using GDALWarpOperation, unfortunately
// it may be very slow on large datasets
#if 0
Expand Down
2 changes: 2 additions & 0 deletions src/providers/gdal/qgsgdalprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@ class QgsGdalProvider : public QgsRasterDataProvider
void readBlock( int bandNo, int xBlock, int yBlock, void *data );
void readBlock( int bandNo, QgsRectangle const & viewExtent, int width, int height, void *data );

//void * readBlock( int bandNo, QgsRectangle const & extent, int width, int height );

double noDataValue() const;
void computeMinMax( int bandNo );
double minimumValue( int bandNo ) const;
Expand Down