103 changes: 4 additions & 99 deletions python/core/raster/qgsrasterinterface.sip
Original file line number Diff line number Diff line change
Expand Up @@ -42,63 +42,20 @@ class QgsRasterInterface

public:

/** Data types.
* This is modified and extended 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 the same as
QImage::Format_ARGB32 */ ARGB32 = 12,
/*! Color, alpha, red, green, blue, 4 bytes the same as
QImage::Format_ARGB32_Premultiplied */ ARGB32_Premultiplied = 13,

TypeCount = 14 /* maximum type # + 1 */
};

struct Range
{
double min;
double max;
bool operator==( const QgsRasterInterface::Range &o ) const;
};

QgsRasterInterface( QgsRasterInterface * input = 0 );

virtual ~QgsRasterInterface();

int typeSize( int dataType ) const;

/** Clone itself, create deep copy */
virtual QgsRasterInterface *clone() const = 0 /Factory/;

int dataTypeSize( int bandNo ) const;

/** Returns true if data type is numeric */
bool typeIsNumeric( QgsRasterInterface::DataType type ) const;

/** Returns true if data type is color */
bool typeIsColor( QgsRasterInterface::DataType type ) const;

/** Returns data type for the band specified by number */
virtual QgsRasterInterface::DataType dataType( int bandNo ) const;
virtual QgsRasterBlock::DataType dataType( int bandNo ) const = 0;

/** For given data type returns wider type and sets no data value */
static QgsRasterInterface::DataType typeWithNoDataValue( DataType dataType, double *noDataValue );
int dataTypeSize ( int bandNo );

/** Get number of bands */
virtual int bandCount() const;
virtual int bandCount() const = 0;

/** Return no data value for specific band. Each band/provider must have
* no data value, if there is no one set in original data, provider decides one
Expand All @@ -113,18 +70,7 @@ class QgsRasterInterface
* @return true if value is nodata */
virtual bool isNoDataValue( int bandNo, double value ) const;

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

/** Read block of data using given extent and size.
* Method to be implemented by subclasses.
* Returns pointer to data.
* Caller is responsible to free the memory returned.
*/
virtual void *readBlock( int bandNo, const QgsRectangle &extent, int width, int height );
virtual QgsRasterBlock *block( int bandNo, const QgsRectangle &extent, int width, int height ) = 0 / Factory /;

/** Set input.
* Returns true if set correctly, false if cannot use that input */
Expand All @@ -144,46 +90,5 @@ class QgsRasterInterface
* resampling etc.
*/
virtual QgsRasterInterface *srcInput();

/** Create a new image with extraneous data, such data may be used
* after the image is destroyed. The memory is not initialized.
*/
QImage * createImage( int width, int height, QImage::Format format ) /Factory/;

/** Switch on (and clear old statistics) or off collection of statistics */
void setStatsOn( bool on );

/** Last total time (for allbands) consumed by this interface for call to block()
* If cumulative is true, the result includes also time spent in all preceding
* interfaces. If cumulative is false, only time consumed by this interface is
* returned. */
double time( bool cumulative = false );

static double readValue( void *data, QgsRasterInterface::DataType type, int index );

static void writeValue( void *data, QgsRasterInterface::DataType type, int index, double value );

/** \brief Print double value with all necessary significant digits.
* It is ensured that conversion back to double gives the same number.
* @param value the value to be printed
* @return string representing the value*/
static QString printValue( double value );

/** \brief Convert block of data from one type to another. Original block memory
* is not release.
* @param srcData source data
* @param srcDataType source data type
* @param destDataType dest data type
* @param size block size (width * height)
* @return block of data in destDataType */
static void * convert( void *srcData, QgsRasterInterface::DataType srcDataType, QgsRasterInterface::DataType destDataType, int size ) /Factory/;

protected:
/** \brief Test if value is within the list of ranges
* @param value value
* @param rangeList list of ranges
* @return true if value is in at least one of ranges
*/
static bool valueInRange( double value, QList<QgsRasterInterface::Range> rangeList );
};

4 changes: 2 additions & 2 deletions python/core/raster/qgsrasteriterator.sip
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ class QgsRasterIterator
@param bandNumber band to read
@param nCols number of columns on output device
@param nRows number of rows on output device
@param rasterData to return the pointer to raster data in
@param block to return the pointer to raster block
@param topLeftCol top left column
@param topLeftRow top left row
@return false if the last part was already returned*/
bool readNextRasterPart( int bandNumber,
int& nCols, int& nRows,
void** rasterData,
QgsRasterBlock** block,
int& topLeftCol, int& topLeftRow );

void stopRasterRead( int bandNumber );
Expand Down
4 changes: 2 additions & 2 deletions python/core/raster/qgsrasterlayer.sip
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ class QgsRasterLayer : QgsMapLayer

/** \brief Wrapper for GDALComputeRasterMinMax with the estimate option
\note added in v1.6 */
void computeMinimumMaximumEstimates( int theBand, double& theMin /Out/, double& theMax /Out/ );
//void computeMinimumMaximumEstimates( int theBand, double& theMin /Out/, double& theMax /Out/ );

/** \brief Compute the actual minimum maximum pixel values based on the current (last) display extent */
// void computeMinimumMaximumFromLastExtent( int theBand, double* theMinMax );
Expand All @@ -260,7 +260,7 @@ class QgsRasterLayer : QgsMapLayer

/** \brief Compute the actual minimum maximum pixel values based on the current (last) display extent
\note added in v1.6 */
void computeMinimumMaximumFromLastExtent( int theBand, double& theMin /Out/, double& theMax /Out/ );
//void computeMinimumMaximumFromLastExtent( int theBand, double& theMin /Out/, double& theMax /Out/ );

/** \brief Get a pointer to the contrast enhancement for the selected band */
QgsContrastEnhancement* contrastEnhancement( unsigned int theBand );
Expand Down
4 changes: 2 additions & 2 deletions python/core/raster/qgsrasternuller.sip
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ class QgsRasterNuller : QgsRasterInterface

int bandCount() const;

QgsRasterInterface::DataType dataType( int bandNo ) const;
QgsRasterBlock::DataType dataType( int bandNo ) const;

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

void setNoData( QList<QgsRasterNuller::NoData> noData );

Expand Down
2 changes: 0 additions & 2 deletions python/core/raster/qgsrasterpipe.sip
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,4 @@ class QgsRasterPipe
QgsRasterProjector * projector() const;
QgsRasterNuller * nuller() const;

/** Set on/off collection of statistics */
void setStatsOn( bool on );
};
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,6 @@ class QgsRasterProjector : QgsRasterInterface
int dstRows() const;
int dstCols() const;

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

4 changes: 2 additions & 2 deletions python/core/raster/qgsrasterrenderer.sip
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ class QgsRasterRenderer : QgsRasterInterface

virtual int bandCount() const;

virtual QgsRasterInterface::DataType dataType( int bandNo ) const;
virtual QgsRasterBlock::DataType dataType( int bandNo ) const;

virtual QString type() const;

virtual bool setInput( QgsRasterInterface* input );

virtual void * readBlock( int bandNo, const QgsRectangle &extent, int width, int height );
virtual QgsRasterBlock * block( int bandNo, const QgsRectangle &extent, int width, int height ) = 0 / Factory /;

bool usesTransparency() const;

Expand Down
4 changes: 2 additions & 2 deletions python/core/raster/qgsrasterresamplefilter.sip
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ class QgsRasterResampleFilter : QgsRasterInterface

int bandCount() const;

QgsRasterInterface::DataType dataType( int bandNo ) const;
QgsRasterBlock::DataType dataType( int bandNo ) const;

bool setInput( QgsRasterInterface* input );

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

/**Set resampler for zoomed in scales. Takes ownership of the object*/
void setZoomedInResampler( QgsRasterResampler* r /Transfer/ );
Expand Down
2 changes: 1 addition & 1 deletion python/core/raster/qgssinglebandcolordatarenderer.sip
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class QgsSingleBandColorDataRenderer: QgsRasterRenderer

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

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

void writeXML( QDomDocument& doc, QDomElement& parentElem ) const;
};
2 changes: 1 addition & 1 deletion python/core/raster/qgssinglebandgrayrenderer.sip
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class QgsSingleBandGrayRenderer: QgsRasterRenderer

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

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

int grayBand() const;
void setGrayBand( int band );
Expand Down
2 changes: 1 addition & 1 deletion python/core/raster/qgssinglebandpseudocolorrenderer.sip
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class QgsSingleBandPseudoColorRenderer: QgsRasterRenderer

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

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

/**Takes ownership of the shader*/
void setShader( QgsRasterShader* shader /Transfer/ );
Expand Down
6 changes: 3 additions & 3 deletions src/app/qgisapp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4422,7 +4422,7 @@ void QgisApp::deletePrintComposers()
for ( ; it != mPrintComposers.end(); ++it )
{
emit composerWillBeRemoved(( *it )->view() );
delete ( (*it)->composition() );
delete(( *it )->composition() );
delete( *it );
}
mPrintComposers.clear();
Expand Down Expand Up @@ -7113,8 +7113,8 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer* layer )
else if ( layer->type() == QgsMapLayer::RasterLayer )
{
const QgsRasterLayer *rlayer = qobject_cast<const QgsRasterLayer *>( layer );
if ( rlayer->dataProvider()->dataType( 1 ) != QgsRasterDataProvider::ARGB32
&& rlayer->dataProvider()->dataType( 1 ) != QgsRasterDataProvider::ARGB32_Premultiplied )
if ( rlayer->dataProvider()->dataType( 1 ) != QgsRasterBlock::ARGB32
&& rlayer->dataProvider()->dataType( 1 ) != QgsRasterBlock::ARGB32_Premultiplied )
{
if ( rlayer->dataProvider()->capabilities() & QgsRasterDataProvider::Size )
{
Expand Down
30 changes: 15 additions & 15 deletions src/app/qgsrasterlayerproperties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -495,8 +495,8 @@ void QgsRasterLayerProperties::sync()
{
QSettings myQSettings;

if ( mRasterLayer->dataProvider()->dataType( 1 ) == QgsRasterDataProvider::ARGB32
|| mRasterLayer->dataProvider()->dataType( 1 ) == QgsRasterDataProvider::ARGB32_Premultiplied )
if ( mRasterLayer->dataProvider()->dataType( 1 ) == QgsRasterBlock::ARGB32
|| mRasterLayer->dataProvider()->dataType( 1 ) == QgsRasterBlock::ARGB32_Premultiplied )
{
gboxNoDataValue->setEnabled( false );
gboxCustomTransparency->setEnabled( false );
Expand Down Expand Up @@ -553,7 +553,7 @@ void QgsRasterLayerProperties::sync()
// TODO: no data ranges
if ( mRasterLayer->dataProvider()->srcHasNoDataValue( 1 ) )
{
lblSrcNoDataValue->setText( QgsRasterInterface::printValue( mRasterLayer->dataProvider()->srcNoDataValue( 1 ) ) );
lblSrcNoDataValue->setText( QgsRasterBlock::printValue( mRasterLayer->dataProvider()->srcNoDataValue( 1 ) ) );
}
else
{
Expand All @@ -567,11 +567,11 @@ void QgsRasterLayerProperties::sync()
mSrcNoDataValueCheckBox->setEnabled( enableSrcNoData );
lblSrcNoDataValue->setEnabled( enableSrcNoData );

QList<QgsRasterInterface::Range> noDataRangeList = mRasterLayer->dataProvider()->userNoDataValue( 1 );
QList<QgsRasterBlock::Range> noDataRangeList = mRasterLayer->dataProvider()->userNoDataValue( 1 );
QgsDebugMsg( QString( "noDataRangeList.size = %1" ).arg( noDataRangeList.size() ) );
if ( noDataRangeList.size() > 0 )
{
leNoDataValue->insert( QgsRasterInterface::printValue( noDataRangeList.value( 0 ).min ) );
leNoDataValue->insert( QgsRasterBlock::printValue( noDataRangeList.value( 0 ).min ) );
}
else
{
Expand Down Expand Up @@ -607,8 +607,8 @@ void QgsRasterLayerProperties::sync()
lblRows->setText( tr( "Rows: " ) + tr( "n/a" ) );
}

if ( mRasterLayer->dataProvider()->dataType( 1 ) == QgsRasterDataProvider::ARGB32
|| mRasterLayer->dataProvider()->dataType( 1 ) == QgsRasterDataProvider::ARGB32_Premultiplied )
if ( mRasterLayer->dataProvider()->dataType( 1 ) == QgsRasterBlock::ARGB32
|| mRasterLayer->dataProvider()->dataType( 1 ) == QgsRasterBlock::ARGB32_Premultiplied )
{
lblNoData->setText( tr( "No-Data Value: " ) + tr( "n/a" ) );
}
Expand Down Expand Up @@ -675,15 +675,15 @@ void QgsRasterLayerProperties::apply()
*/

//set NoDataValue
QList<QgsRasterInterface::Range> myNoDataRangeList;
QList<QgsRasterBlock::Range> myNoDataRangeList;
if ( "" != leNoDataValue->text() )
{
bool myDoubleOk = false;
double myNoDataValue = leNoDataValue->text().toDouble( &myDoubleOk );
if ( myDoubleOk )
{
//mRasterLayer->setNoDataValue( myNoDataValue );
QgsRasterInterface::Range myNoDataRange;
QgsRasterBlock::Range myNoDataRange;
myNoDataRange.min = myNoDataValue;
myNoDataRange.max = myNoDataValue;

Expand Down Expand Up @@ -1064,12 +1064,12 @@ void QgsRasterLayerProperties::setTransparencyCell( int row, int column, double
QString valueString;
switch ( provider->srcDataType( 1 ) )
{
case QgsRasterInterface::Float32:
case QgsRasterInterface::Float64:
case QgsRasterBlock::Float32:
case QgsRasterBlock::Float64:
lineEdit->setValidator( new QDoubleValidator( 0 ) );
if ( !qIsNaN( value ) )
{
valueString = QgsRasterInterface::printValue( value );
valueString = QgsRasterBlock::printValue( value );
}
break;
default:
Expand All @@ -1096,7 +1096,7 @@ void QgsRasterLayerProperties::setTransparencyCellValue( int row, int column, do
{
QLineEdit *lineEdit = dynamic_cast<QLineEdit *>( tableTransparency->cellWidget( row, column ) );
if ( !lineEdit ) return;
lineEdit->setText( QgsRasterInterface::printValue( value ) );
lineEdit->setText( QgsRasterBlock::printValue( value ) );
lineEdit->adjustSize();
adjustTransparencyCellWidth( row, column );
tableTransparency->resizeColumnsToContents();
Expand Down Expand Up @@ -1629,7 +1629,7 @@ void QgsRasterLayerProperties::updatePipeList()
if ( mPipeTreeWidget->columnCount() <= 1 )
{
QStringList labels;
labels << tr( "Filter" ) << tr( "Bands" ) << tr( "Time" );
labels << tr( "Filter" ) << tr( "Bands" );
mPipeTreeWidget->setHeaderLabels( labels );
connect( mPipeTreeWidget, SIGNAL( itemClicked( QTreeWidgetItem *, int ) ), this, SLOT( pipeItemClicked( QTreeWidgetItem *, int ) ) );
}
Expand All @@ -1653,7 +1653,7 @@ void QgsRasterLayerProperties::updatePipeList()
}

texts << name << QString( "%1" ).arg( interface->bandCount() );
texts << QString( "%1 ms" ).arg( interface->time() );
//texts << QString( "%1 ms" ).arg( interface->time() );
QTreeWidgetItem *item = new QTreeWidgetItem( texts );

#if 0
Expand Down
2 changes: 2 additions & 0 deletions src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ SET(QGIS_CORE_SRCS
pal/rtree.hpp

raster/qgscliptominmaxenhancement.cpp
raster/qgsrasterblock.cpp
raster/qgscolorrampshader.cpp
raster/qgscontrastenhancement.cpp
raster/qgscontrastenhancementfunction.cpp
Expand Down Expand Up @@ -404,6 +405,7 @@ SET(QGIS_CORE_HDRS
composer/qgslegendmodel.h
composer/qgscomposerlegenditem.h

raster/qgsrasterblock.h
raster/qgsrasterdataprovider.h
raster/qgsrasterresamplefilter.h
raster/qgscliptominmaxenhancement.h
Expand Down
260 changes: 108 additions & 152 deletions src/core/raster/qgsmultibandcolorrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,13 @@ QgsRasterRenderer* QgsMultiBandColorRenderer::create( const QDomElement& elem, Q
return r;
}

void * QgsMultiBandColorRenderer::readBlock( int bandNo, QgsRectangle const & extent, int width, int height )
QgsRasterBlock* QgsMultiBandColorRenderer::block( int bandNo, QgsRectangle const & extent, int width, int height )
{
Q_UNUSED( bandNo );
QgsRasterBlock *outputBlock = new QgsRasterBlock();
if ( !mInput )
{
return 0;
return outputBlock;
}

//In some (common) cases, we can simplify the drawing loop considerably and save render time
Expand All @@ -138,28 +139,6 @@ void * QgsMultiBandColorRenderer::readBlock( int bandNo, QgsRectangle const & e
&& mAlphaBand < 1 && !mRedContrastEnhancement && !mGreenContrastEnhancement && !mBlueContrastEnhancement
&& !mInvertColor );

QgsRasterInterface::DataType redType = QgsRasterInterface::UnknownDataType;

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

QSet<int> bands;
if ( mRedBand > 0 )
{
Expand All @@ -175,197 +154,174 @@ void * QgsMultiBandColorRenderer::readBlock( int bandNo, QgsRectangle const & e
}
if ( bands.size() < 1 )
{
return 0; //no need to draw anything if no band is set
// no need to draw anything if no band is set
// TODO:: we should probably return default color block
return outputBlock;
}

if ( mAlphaBand > 0 )
{
bands << mAlphaBand;
}

QMap<int, void*> bandData;
void* defaultPointer = 0;
QMap<int, QgsRasterBlock*> bandBlocks;
QgsRasterBlock* defaultPointer = 0;
QSet<int>::const_iterator bandIt = bands.constBegin();
for ( ; bandIt != bands.constEnd(); ++bandIt )
{
bandData.insert( *bandIt, defaultPointer );
bandBlocks.insert( *bandIt, defaultPointer );
}

void* redData = 0;
void* greenData = 0;
void* blueData = 0;
void* alphaData = 0;
QgsRasterBlock* redBlock = 0;
QgsRasterBlock* greenBlock = 0;
QgsRasterBlock* blueBlock = 0;
QgsRasterBlock* alphaBlock = 0;

bandIt = bands.constBegin();
for ( ; bandIt != bands.constEnd(); ++bandIt )
{
bandData[*bandIt] = mInput->block( *bandIt, extent, width, height );
if ( !bandData[*bandIt] )
bandBlocks[*bandIt] = mInput->block( *bandIt, extent, width, height );
if ( !bandBlocks[*bandIt] )
{
// We should free the alloced mem from block().
QgsDebugMsg( "No input band" );
bandIt--;
for ( ; bandIt != bands.constBegin(); bandIt-- )
{
VSIFree( bandData[*bandIt] );
delete bandBlocks[*bandIt];
}
return 0;
return outputBlock;
}
}

if ( mRedBand > 0 )
{
redData = bandData[mRedBand];
redBlock = bandBlocks[mRedBand];
}
if ( mGreenBand > 0 )
{
greenData = bandData[mGreenBand];
greenBlock = bandBlocks[mGreenBand];
}
if ( mBlueBand > 0 )
{
blueData = bandData[mBlueBand];
blueBlock = bandBlocks[mBlueBand];
}
if ( mAlphaBand > 0 )
{
alphaData = bandData[mAlphaBand];
alphaBlock = bandBlocks[mAlphaBand];
}

QImage img( width, height, QImage::Format_ARGB32_Premultiplied );
if ( img.isNull() )
if ( !outputBlock->reset( QgsRasterBlock::ARGB32_Premultiplied, width, height ) )
{
QgsDebugMsg( "Could not create QImage" );
bandIt = bands.constBegin();
for ( ; bandIt != bands.constEnd(); ++bandIt )
for ( int i = 0; i < bandBlocks.size(); i++ )
{
VSIFree( bandData[*bandIt] );
delete bandBlocks.value( i );
}
return 0;
return outputBlock;
}

QRgb* imageScanLine = 0;
int currentRasterPos = 0;
int redVal = 0;
int greenVal = 0;
int blueVal = 0;
QRgb defaultColor = qRgba( 255, 255, 255, 0 );
double currentOpacity = mOpacity; //opacity (between 0 and 1)
QRgb myDefaultColor = NODATA_COLOR;

for ( int i = 0; i < height; ++i )
for ( size_t i = 0; i < ( size_t )width*height; i++ )
{
imageScanLine = ( QRgb* )( img.scanLine( i ) );
for ( int j = 0; j < width; ++j )
if ( fastDraw ) //fast rendering if no transparency, stretching, color inversion, etc.
{
if ( fastDraw ) //fast rendering if no transparency, stretching, color inversion, etc.
{
redVal = readValue( redData, redType, currentRasterPos );
greenVal = readValue( greenData, greenType, currentRasterPos );
blueVal = readValue( blueData, blueType, currentRasterPos );
if ( mInput->isNoDataValue( mRedBand, redVal ) ||
mInput->isNoDataValue( mGreenBand, greenVal ) ||
mInput->isNoDataValue( mBlueBand, blueVal ) )
{
imageScanLine[j] = defaultColor;
}
else
{
imageScanLine[j] = qRgba( redVal, greenVal, blueVal, 255 );
}

++currentRasterPos;
continue;
}

bool isNoData = false;
if ( mRedBand > 0 )
int redVal = ( int )redBlock->value( i );
int greenVal = ( int )greenBlock->value( i );
int blueVal = ( int )blueBlock->value( i );
if ( redBlock->isNoDataValue( redVal ) ||
greenBlock->isNoDataValue( greenVal ) ||
blueBlock->isNoDataValue( blueVal ) )
{
redVal = readValue( redData, redType, currentRasterPos );
if ( mInput->isNoDataValue( mRedBand, redVal ) ) isNoData = true;
outputBlock->setColor( i, myDefaultColor );
}
if ( mGreenBand > 0 )
{
greenVal = readValue( greenData, greenType, currentRasterPos );
if ( mInput->isNoDataValue( mGreenBand, greenVal ) ) isNoData = true;
}
if ( mBlueBand > 0 )
{
blueVal = readValue( blueData, blueType, currentRasterPos );
if ( mInput->isNoDataValue( mBlueBand, blueVal ) ) isNoData = true;
}
if ( isNoData )
else
{
imageScanLine[j] = defaultColor;
++currentRasterPos;
continue;
outputBlock->setColor( i, qRgba( redVal, greenVal, blueVal, 255 ) );
}
continue;
}

//apply default color if red, green or blue not in displayable range
if (( mRedContrastEnhancement && !mRedContrastEnhancement->isValueInDisplayableRange( redVal ) )
|| ( mGreenContrastEnhancement && !mGreenContrastEnhancement->isValueInDisplayableRange( redVal ) )
|| ( mBlueContrastEnhancement && !mBlueContrastEnhancement->isValueInDisplayableRange( redVal ) ) )
{
imageScanLine[j] = defaultColor;
++currentRasterPos;
continue;
}
bool isNoData = false;
double redVal, greenVal, blueVal;
if ( mRedBand > 0 )
{
redVal = redBlock->value( i );
if ( redBlock->isNoDataValue( redVal ) ) isNoData = true;
}
if ( !isNoData && mGreenBand > 0 )
{
greenVal = greenBlock->value( i );
if ( greenBlock->isNoDataValue( greenVal ) ) isNoData = true;
}
if ( !isNoData && mBlueBand > 0 )
{
blueVal = ( int )blueBlock->value( i );
if ( blueBlock->isNoDataValue( blueVal ) ) isNoData = true;
}
if ( isNoData )
{
outputBlock->setColor( i, myDefaultColor );
continue;
}

//stretch color values
if ( mRedContrastEnhancement )
{
redVal = mRedContrastEnhancement->enhanceContrast( redVal );
}
if ( mGreenContrastEnhancement )
{
greenVal = mGreenContrastEnhancement->enhanceContrast( greenVal );
}
if ( mBlueContrastEnhancement )
{
blueVal = mBlueContrastEnhancement->enhanceContrast( blueVal );
}
//apply default color if red, green or blue not in displayable range
if (( mRedContrastEnhancement && !mRedContrastEnhancement->isValueInDisplayableRange( redVal ) )
|| ( mGreenContrastEnhancement && !mGreenContrastEnhancement->isValueInDisplayableRange( redVal ) )
|| ( mBlueContrastEnhancement && !mBlueContrastEnhancement->isValueInDisplayableRange( redVal ) ) )
{
outputBlock->setColor( i, myDefaultColor );
continue;
}

if ( mInvertColor )
{
redVal = 255 - redVal;
greenVal = 255 - greenVal;
blueVal = 255 - blueVal;
}
//stretch color values
if ( mRedContrastEnhancement )
{
redVal = mRedContrastEnhancement->enhanceContrast( redVal );
}
if ( mGreenContrastEnhancement )
{
greenVal = mGreenContrastEnhancement->enhanceContrast( greenVal );
}
if ( mBlueContrastEnhancement )
{
blueVal = mBlueContrastEnhancement->enhanceContrast( blueVal );
}

//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 ( mInvertColor )
{
redVal = 255 - redVal;
greenVal = 255 - greenVal;
blueVal = 255 - blueVal;
}

if ( doubleNear( currentOpacity, 1.0 ) )
{
imageScanLine[j] = qRgba( redVal, greenVal, blueVal, 255 );
}
else
{
imageScanLine[j] = qRgba( currentOpacity * redVal, currentOpacity * greenVal, currentOpacity * blueVal, currentOpacity * 255 );
}
//opacity
double currentOpacity = mOpacity;
if ( mRasterTransparency )
{
currentOpacity = mRasterTransparency->alphaValue( redVal, greenVal, blueVal, mOpacity * 255 ) / 255.0;
}
if ( mAlphaBand > 0 )
{
currentOpacity *= alphaBlock->value( i ) / 255.0;
}

++currentRasterPos;
if ( doubleNear( currentOpacity, 1.0 ) )
{
outputBlock->setColor( i, qRgba( redVal, greenVal, blueVal, 255 ) );
}
else
{
outputBlock->setColor( i, qRgba( currentOpacity * redVal, currentOpacity * greenVal, currentOpacity * blueVal, currentOpacity * 255 ) );
}
}

bandIt = bands.constBegin();
for ( ; bandIt != bands.constEnd(); ++bandIt )
for ( int i = 0; i < bandBlocks.size(); i++ )
{
VSIFree( bandData[*bandIt] );
delete bandBlocks.value( i );
}

void * data = VSIMalloc( img.byteCount() );
if ( ! data )
{
QgsDebugMsg( QString( "Couldn't allocate output data memory of % bytes" ).arg( img.byteCount() ) );
return 0;
}
return memcpy( data, img.bits(), img.byteCount() );
return outputBlock;
}

void QgsMultiBandColorRenderer::writeXML( QDomDocument& doc, QDomElement& parentElem ) const
Expand Down
2 changes: 1 addition & 1 deletion src/core/raster/qgsmultibandcolorrenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class CORE_EXPORT QgsMultiBandColorRenderer: public QgsRasterRenderer

static QgsRasterRenderer* create( const QDomElement& elem, QgsRasterInterface* input );

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

int redBand() const { return mRedBand; }
void setRedBand( int band ) { mRedBand = band; }
Expand Down
156 changes: 81 additions & 75 deletions src/core/raster/qgspalettedrasterrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

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

Expand All @@ -36,7 +36,7 @@ QgsPalettedRasterRenderer::~QgsPalettedRasterRenderer()

QgsRasterInterface * QgsPalettedRasterRenderer::clone() const
{
QgsPalettedRasterRenderer * renderer = new QgsPalettedRasterRenderer( 0, mBandNumber, colors(), mNColors );
QgsPalettedRasterRenderer * renderer = new QgsPalettedRasterRenderer( 0, mBand, colors(), mNColors );
renderer->setOpacity( mOpacity );
renderer->setAlphaBand( mAlphaBand );
renderer->setInvertColor( mInvertColor );
Expand Down Expand Up @@ -91,114 +91,120 @@ QColor* QgsPalettedRasterRenderer::colors() const
return colorArray;
}

void * QgsPalettedRasterRenderer::readBlock( int bandNo, QgsRectangle const & extent, int width, int height )
QgsRasterBlock * QgsPalettedRasterRenderer::block( int bandNo, QgsRectangle const & extent, int width, int height )
{
QgsRasterBlock *outputBlock = new QgsRasterBlock();
if ( !mInput )
{
return 0;
return outputBlock;
}
QRgb myDefaultColor = qRgba( 0, 0, 0, 0 );
QRgb myDefaultColor = NODATA_COLOR;

QgsRasterInterface::DataType transparencyType = QgsRasterInterface::UnknownDataType;
if ( mAlphaBand > 0 )
{
transparencyType = ( QgsRasterInterface::DataType )mInput->dataType( mAlphaBand );
}
//QgsRasterBlock::DataType transparencyType = QgsRasterBlock::UnknownDataType;
//if ( mAlphaBand > 0 )
//{
// transparencyType = ( QgsRasterBlock::DataType )mInput->dataType( mAlphaBand );
//}

QgsRasterInterface::DataType rasterType = ( QgsRasterInterface::DataType )mInput->dataType( mBandNumber );
void* rasterData = mInput->block( bandNo, extent, width, height );
if ( ! rasterData )
//QgsRasterBlock::DataType rasterType = ( QgsRasterBlock::DataType )mInput->dataType( mBand );
//void* rasterData = mInput->block( bandNo, extent, width, height );
QgsRasterBlock *inputBlock = mInput->block( bandNo, extent, width, height );

if ( !inputBlock || inputBlock->isEmpty() )
{
QgsDebugMsg( "No raster data!" );
return 0;
delete inputBlock;
return outputBlock;
}

double currentOpacity = mOpacity;

//rendering is faster without considering user-defined transparency
bool hasTransparency = usesTransparency();
void* transparencyData = 0;
//void* transparencyData = 0;
QgsRasterBlock *alphaBlock = 0;

if ( mAlphaBand > 0 && mAlphaBand != mBandNumber )
if ( mAlphaBand > 0 && mAlphaBand != mBand )
{
transparencyData = mInput->block( mAlphaBand, extent, width, height );
alphaBlock = mInput->block( mAlphaBand, extent, width, height );
if ( !alphaBlock || alphaBlock->isEmpty() )
{
delete inputBlock;
delete alphaBlock;
return outputBlock;
}
}
else if ( mAlphaBand == mBandNumber )
else if ( mAlphaBand == mBand )
{
transparencyData = rasterData;
//transparencyData = rasterData;
alphaBlock = inputBlock;
}

//create image
QImage img( width, height, QImage::Format_ARGB32_Premultiplied );
if ( img.isNull() )
//QImage img( width, height, QImage::Format_ARGB32_Premultiplied );
//if ( img.isNull() )
//{
//QgsDebugMsg( "Could not create QImage" );
//VSIFree( rasterData );
//return 0;
//}
if ( !outputBlock->reset( QgsRasterBlock::ARGB32_Premultiplied, width, height ) )
{
QgsDebugMsg( "Could not create QImage" );
VSIFree( rasterData );
return 0;
delete inputBlock;
delete alphaBlock;
return outputBlock;
}

QRgb* imageScanLine = 0;
int val = 0;
int currentRasterPos = 0;

for ( int i = 0; i < height; ++i )
for ( size_t i = 0; i < ( size_t )width*height; i++ )
{
imageScanLine = ( QRgb* )( img.scanLine( i ) );
for ( int j = 0; j < width; ++j )
int val = ( int ) inputBlock->value( i );
if ( inputBlock->isNoDataValue( val ) )
{
outputBlock->setColor( i, myDefaultColor );
continue;
}
if ( !hasTransparency )
{
if ( val < 0 || val > mNColors )
{
outputBlock->setColor( i, myDefaultColor );
}
else
{
outputBlock->setColor( i, mColors[ val ].rgba() );
}
}
else
{
val = readValue( rasterData, rasterType, currentRasterPos );
if ( mInput->isNoDataValue( mBandNumber, val ) )
currentOpacity = mOpacity;
if ( mRasterTransparency )
{
imageScanLine[j] = myDefaultColor;
++currentRasterPos;
continue;
currentOpacity = mRasterTransparency->alphaValue( val, mOpacity * 255 ) / 255.0;
}
if ( !hasTransparency )
if ( mAlphaBand > 0 )
{
if ( val < 0 || val > mNColors )
{
imageScanLine[j] = myDefaultColor;
}
else
{
imageScanLine[j] = mColors[ val ].rgba();
}
currentOpacity *= alphaBlock->value( i ) / 255.0;
}
QColor& currentColor = mColors[val];

if ( mInvertColor )
{
outputBlock->setColor( i, 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 );
}
outputBlock->setColor( i, qRgba( currentOpacity * currentColor.red(), currentOpacity * currentColor.green(), currentOpacity * currentColor.blue(), currentOpacity * 255 ) );
}
++currentRasterPos;
}
}

VSIFree( rasterData );

void * data = VSIMalloc( img.byteCount() );
if ( ! data )
delete inputBlock;
if ( mAlphaBand > 0 && mBand != mAlphaBand )
{
QgsDebugMsg( QString( "Couldn't allocate output data memory of % bytes" ).arg( img.byteCount() ) );
return 0;
delete alphaBlock;
}
return memcpy( data, img.bits(), img.byteCount() );

return outputBlock;
}

void QgsPalettedRasterRenderer::writeXML( QDomDocument& doc, QDomElement& parentElem ) const
Expand All @@ -211,7 +217,7 @@ void QgsPalettedRasterRenderer::writeXML( QDomDocument& doc, QDomElement& parent
QDomElement rasterRendererElem = doc.createElement( "rasterrenderer" );
_writeXML( doc, rasterRendererElem );

rasterRendererElem.setAttribute( "band", mBandNumber );
rasterRendererElem.setAttribute( "band", mBand );
QDomElement colorPaletteElem = doc.createElement( "colorPalette" );
for ( int i = 0; i < mNColors; ++i )
{
Expand All @@ -236,9 +242,9 @@ void QgsPalettedRasterRenderer::legendSymbologyItems( QList< QPair< QString, QCo
QList<int> QgsPalettedRasterRenderer::usesBands() const
{
QList<int> bandList;
if ( mBandNumber != -1 )
if ( mBand != -1 )
{
bandList << mBandNumber;
bandList << mBand;
}
return bandList;
}
4 changes: 2 additions & 2 deletions src/core/raster/qgspalettedrasterrenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class CORE_EXPORT QgsPalettedRasterRenderer: public QgsRasterRenderer

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

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

/**Returns number of colors*/
int nColors() const { return mNColors; }
Expand All @@ -51,7 +51,7 @@ class CORE_EXPORT QgsPalettedRasterRenderer: public QgsRasterRenderer
QList<int> usesBands() const;

private:
int mBandNumber;
int mBand;
/**Color array*/
QColor* mColors;
/**Number of colors*/
Expand Down
488 changes: 488 additions & 0 deletions src/core/raster/qgsrasterblock.cpp

Large diffs are not rendered by default.

415 changes: 415 additions & 0 deletions src/core/raster/qgsrasterblock.h

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/core/raster/qgsrasterchecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ bool QgsRasterChecker::runTest( QString theVerifiedKey, QString theVerifiedUri,

int width = expectedProvider->xSize();
int height = expectedProvider->ySize();
int blockSize = width * height * expectedProvider->typeSize( expectedProvider->dataType( band ) ) ;
int blockSize = width * height * QgsRasterBlock::typeSize( expectedProvider->dataType( band ) ) ;
void * expectedData = malloc( blockSize );
void * verifiedData = malloc( blockSize );

Expand Down
76 changes: 41 additions & 35 deletions src/core/raster/qgsrasterdataprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ double QgsRasterDataProvider::noDataValue( int bandNo ) const
return mInternalNoDataValue.value( bandNo -1 );
}

#if 0
void QgsRasterDataProvider::readBlock( int bandNo, QgsRectangle
const & viewExtent, int width,
int height,
Expand Down Expand Up @@ -115,41 +116,45 @@ void QgsRasterDataProvider::readBlock( int bandNo, QgsRectangle

free( mySrcData );
}
#endif

void * QgsRasterDataProvider::readBlock( int bandNo, QgsRectangle const & extent, int width, int height )
//void * QgsRasterDataProvider::readBlock( int bandNo, QgsRectangle const & extent, int width, int height )
QgsRasterBlock * QgsRasterDataProvider::block( int bandNo, QgsRectangle const & extent, int width, int height )
{
QgsDebugMsg( QString( "bandNo = %1 width = %2 height = %3" ).arg( bandNo ).arg( width ).arg( height ) );

// TODO: replace VSIMalloc, it is GDAL function
void * data = VSIMalloc( dataTypeSize( bandNo ) * width * height );
if ( ! data )
//void * data = QgsMalloc( dataTypeSize( bandNo ) * width * height );

QgsRasterBlock *block = new QgsRasterBlock( dataType( bandNo ), width, height, noDataValue( bandNo ) );

if ( block->isEmpty() )
{
QgsDebugMsg( QString( "Couldn't allocate data memory of % bytes" ).arg( dataTypeSize( bandNo ) * width * height ) );
return 0;
QgsDebugMsg( "Couldn't create raster block" );
return block;
}

readBlock( bandNo, extent, width, height, data );
readBlock( bandNo, extent, width, height, block->data() );

// apply user no data values
// TODO: there are other readBlock methods where no data are not applied
QList<QgsRasterInterface::Range> myNoDataRangeList = userNoDataValue( bandNo );
QList<QgsRasterBlock::Range> myNoDataRangeList = userNoDataValue( bandNo );
if ( !myNoDataRangeList.isEmpty() )
{
QgsRasterInterface::DataType type = dataType( bandNo );
//QgsRasterBlock::DataType type = dataType( bandNo );
double myNoDataValue = noDataValue( bandNo );
size_t size = width * height;
for ( size_t i = 0; i < size; i++ )
{
double value = readValue( data, type, i );
double value = block->value( i );

if ( QgsRasterInterface::valueInRange( value, myNoDataRangeList ) )
if ( QgsRasterBlock::valueInRange( value, myNoDataRangeList ) )
{
writeValue( data, type, i, myNoDataValue );
block->setValue( i, myNoDataValue );
}
}
}

return data;
return block;
}

QgsRasterDataProvider::QgsRasterDataProvider()
Expand Down Expand Up @@ -306,7 +311,7 @@ QString QgsRasterDataProvider::lastErrorFormat()
QByteArray QgsRasterDataProvider::noValueBytes( int theBandNo )
{
int type = dataType( theBandNo );
size_t size = dataTypeSize( theBandNo ) / 8;
size_t size = QgsRasterBlock::typeSize( dataType( theBandNo ) ) / 8;
QByteArray ba;
ba.resize(( int )size );
char * data = ba.data();
Expand All @@ -318,33 +323,34 @@ QByteArray QgsRasterDataProvider::noValueBytes( int theBandNo )
int i;
float f;
double d;
// TODO: define correct data types (typedef) like in GDAL
switch ( type )
{
case Byte:
case QgsRasterBlock::Byte:
uc = ( unsigned char )noval;
memcpy( data, &uc, size );
break;
case UInt16:
case QgsRasterBlock::UInt16:
us = ( unsigned short )noval;
memcpy( data, &us, size );
break;
case Int16:
case QgsRasterBlock::Int16:
s = ( short )noval;
memcpy( data, &s, size );
break;
case UInt32:
case QgsRasterBlock::UInt32:
ui = ( unsigned int )noval;
memcpy( data, &ui, size );
break;
case Int32:
case QgsRasterBlock::Int32:
i = ( int )noval;
memcpy( data, &i, size );
break;
case Float32:
case QgsRasterBlock::Float32:
f = ( float )noval;
memcpy( data, &f, size );
break;
case Float64:
case QgsRasterBlock::Float64:
d = ( double )noval;
memcpy( data, &d, size );
break;
Expand Down Expand Up @@ -653,7 +659,7 @@ QgsRasterBandStats QgsRasterDataProvider::bandStatistics( int theBandNo,
int myNXBlocks = ( myWidth + myXBlockSize - 1 ) / myXBlockSize;
int myNYBlocks = ( myHeight + myYBlockSize - 1 ) / myYBlockSize;

void *myData = CPLMalloc( myXBlockSize * myYBlockSize * ( dataTypeSize( theBandNo ) / 8 ) );
void *myData = CPLMalloc( myXBlockSize * myYBlockSize * ( QgsRasterBlock::typeSize( dataType( theBandNo ) ) / 8 ) );

double myXRes = myExtent.width() / myWidth;
double myYRes = myExtent.height() / myHeight;
Expand Down Expand Up @@ -770,7 +776,7 @@ void QgsRasterDataProvider::initHistogram( QgsRasterHistogram &theHistogram,

if ( qIsNaN( theHistogram.minimum ) )
{
if ( mySrcDataType == QgsRasterDataProvider::Byte )
if ( mySrcDataType == QgsRasterBlock::Byte )
{
theHistogram.minimum = 0; // see histogram() for shift for rounding
}
Expand All @@ -785,7 +791,7 @@ void QgsRasterDataProvider::initHistogram( QgsRasterHistogram &theHistogram,
}
if ( qIsNaN( theHistogram.maximum ) )
{
if ( mySrcDataType == QgsRasterDataProvider::Byte )
if ( mySrcDataType == QgsRasterBlock::Byte )
{
theHistogram.maximum = 255;
}
Expand Down Expand Up @@ -844,7 +850,7 @@ void QgsRasterDataProvider::initHistogram( QgsRasterHistogram &theHistogram,
int myBinCount = theBinCount;
if ( myBinCount == 0 )
{
if ( mySrcDataType == QgsRasterDataProvider::Byte )
if ( mySrcDataType == QgsRasterBlock::Byte )
{
myBinCount = 256; // Cannot store more values in byte
}
Expand Down Expand Up @@ -929,7 +935,7 @@ QgsRasterHistogram QgsRasterDataProvider::histogram( int theBandNo,
int myNXBlocks = ( myWidth + myXBlockSize - 1 ) / myXBlockSize;
int myNYBlocks = ( myHeight + myYBlockSize - 1 ) / myYBlockSize;

void *myData = CPLMalloc( myXBlockSize * myYBlockSize * ( dataTypeSize( theBandNo ) / 8 ) );
void *myData = CPLMalloc( myXBlockSize * myYBlockSize * ( QgsRasterBlock::typeSize( dataType( theBandNo ) ) / 8 ) );

double myXRes = myExtent.width() / myWidth;
double myYRes = myExtent.height() / myHeight;
Expand Down Expand Up @@ -1058,25 +1064,25 @@ double QgsRasterDataProvider::readValue( void *data, int type, int index )

switch ( type )
{
case Byte:
case QgsRasterBlock::Byte:
return ( double )(( GByte * )data )[index];
break;
case UInt16:
case QgsRasterBlock::UInt16:
return ( double )(( GUInt16 * )data )[index];
break;
case Int16:
case QgsRasterBlock::Int16:
return ( double )(( GInt16 * )data )[index];
break;
case UInt32:
case QgsRasterBlock::UInt32:
return ( double )(( GUInt32 * )data )[index];
break;
case Int32:
case QgsRasterBlock::Int32:
return ( double )(( GInt32 * )data )[index];
break;
case Float32:
case QgsRasterBlock::Float32:
return ( double )(( float * )data )[index];
break;
case Float64:
case QgsRasterBlock::Float64:
return ( double )(( double * )data )[index];
break;
default:
Expand All @@ -1086,14 +1092,14 @@ double QgsRasterDataProvider::readValue( void *data, int type, int index )
return std::numeric_limits<double>::quiet_NaN();
}

void QgsRasterDataProvider::setUserNoDataValue( int bandNo, QList<QgsRasterInterface::Range> noData )
void QgsRasterDataProvider::setUserNoDataValue( int bandNo, QList<QgsRasterBlock::Range> noData )
{
//if ( bandNo > bandCount() ) return;
if ( bandNo >= mUserNoDataValue.size() )
{
for ( int i = mUserNoDataValue.size(); i < bandNo; i++ )
{
mUserNoDataValue.append( QList<QgsRasterInterface::Range>() );
mUserNoDataValue.append( QList<QgsRasterBlock::Range>() );
}
}
QgsDebugMsg( QString( "set %1 band %1 no data ranges" ).arg( noData.size() ) );
Expand Down
22 changes: 13 additions & 9 deletions src/core/raster/qgsrasterdataprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,18 +179,18 @@ class CORE_EXPORT QgsRasterDataProvider : public QgsDataProvider, public QgsRast
// TODO: Get the file masks supported by this provider, suitable for feeding into the file open dialog box

/** Returns data type for the band specified by number */
virtual QgsRasterInterface::DataType dataType( int bandNo ) const
virtual QgsRasterBlock::DataType dataType( int bandNo ) const
{
return srcDataType( bandNo );
}

/** Returns source data type for the band specified by number,
* source data type may be shorter than dataType
*/
virtual QgsRasterInterface::DataType srcDataType( int bandNo ) const
virtual QgsRasterBlock::DataType srcDataType( int bandNo ) const
{
Q_UNUSED( bandNo );
return QgsRasterDataProvider::UnknownDataType;
return QgsRasterBlock::UnknownDataType;
}

/** Returns data type for the band specified by number */
Expand Down Expand Up @@ -276,6 +276,8 @@ class CORE_EXPORT QgsRasterDataProvider : public QgsDataProvider, public QgsRast
virtual int xSize() const { return 0; }
virtual int ySize() const { return 0; }

// TODO: remove or make protected all readBlock working with void*

/** read block of data */
// TODO clarify what happens on the last block (the part outside raster)
// @note not available in python bindings
Expand All @@ -289,11 +291,13 @@ class CORE_EXPORT QgsRasterDataProvider : public QgsDataProvider, public QgsRast

/** read block of data using give extent and size */
// @note not available in python bindings
virtual void readBlock( int bandNo, QgsRectangle const & viewExtent, int width, int height, QgsCoordinateReferenceSystem theSrcCRS, QgsCoordinateReferenceSystem theDestCRS, void *data );
//virtual void readBlock( int bandNo, QgsRectangle const & viewExtent, int width, int height, QgsCoordinateReferenceSystem theSrcCRS, QgsCoordinateReferenceSystem theDestCRS, void *data );

/** Read block of data using given extent and size. */
// @note not available in python bindings
virtual void *readBlock( int bandNo, QgsRectangle const & extent, int width, int height );
//virtual void *readBlock( int bandNo, QgsRectangle const & extent, int width, int height );

virtual QgsRasterBlock *block( int bandNo, const QgsRectangle &extent, int width, int height );

/* Read a value from a data block at a given index. */
virtual double readValue( void *data, int type, int index );
Expand All @@ -318,10 +322,10 @@ class CORE_EXPORT QgsRasterDataProvider : public QgsDataProvider, public QgsRast
/** Value representing no data value. */
virtual double srcNoDataValue( int bandNo ) const { return mSrcNoDataValue.value( bandNo -1 ); }

virtual void setUserNoDataValue( int bandNo, QList<QgsRasterInterface::Range> noData );
virtual void setUserNoDataValue( int bandNo, QList<QgsRasterBlock::Range> noData );

/** Get list of user no data value ranges */
virtual QList<QgsRasterInterface::Range> userNoDataValue( int bandNo ) const { return mUserNoDataValue.value( bandNo -1 ); }
virtual QList<QgsRasterBlock::Range> userNoDataValue( int bandNo ) const { return mUserNoDataValue.value( bandNo -1 ); }

virtual double minimumValue( int bandNo ) const { Q_UNUSED( bandNo ); return 0; }
virtual double maximumValue( int bandNo ) const { Q_UNUSED( bandNo ); return 0; }
Expand Down Expand Up @@ -549,7 +553,7 @@ class CORE_EXPORT QgsRasterDataProvider : public QgsDataProvider, public QgsRast
/** Creates a new dataset with mDataSourceURI
@return true in case of success*/
virtual bool create( const QString& format, int nBands,
QgsRasterInterface::DataType type,
QgsRasterBlock::DataType type,
int width, int height, double* geoTransform,
const QgsCoordinateReferenceSystem& crs,
QStringList createOptions = QStringList() /*e.v. color table*/ )
Expand Down Expand Up @@ -626,7 +630,7 @@ class CORE_EXPORT QgsRasterDataProvider : public QgsDataProvider, public QgsRast

/** \brief List of lists of user defined additional no data values
* for each band, indexed from 0 */
QList< QList<QgsRasterInterface::Range> > mUserNoDataValue;
QList< QList<QgsRasterBlock::Range> > mUserNoDataValue;

QgsRectangle mExtent;

Expand Down
12 changes: 7 additions & 5 deletions src/core/raster/qgsrasterdrawer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,21 +56,23 @@ void QgsRasterDrawer::draw( QPainter* p, QgsRasterViewPort* viewPort, const QgsM
// We know that the output data type of last pipe filter is QImage data
//QgsRasterDataProvider::DataType rasterType = ( QgsRasterDataProvider::DataType )mProvider->dataType( mGrayBand );

void* rasterData;
//void* rasterData;
QgsRasterBlock *block;

// readNextRasterPart calcs and resets nCols, nRows, topLeftCol, topLeftRow
while ( mIterator->readNextRasterPart( bandNumber, nCols, nRows,
&rasterData, topLeftCol, topLeftRow ) )
&block, 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 );
//QImage img(( uchar * ) rasterData, nCols, nRows, QImage::Format_ARGB32_Premultiplied );
QImage img = block->image();

drawImage( p, viewPort, img, topLeftCol, topLeftRow );

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

Expand Down
90 changes: 46 additions & 44 deletions src/core/raster/qgsrasterfilewriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeRaster( const QgsRast

QgsRasterIterator iter( pipe->last() );

if ( iface->dataType( 1 ) == QgsRasterInterface::ARGB32 ||
iface->dataType( 1 ) == QgsRasterInterface::ARGB32_Premultiplied )
if ( iface->dataType( 1 ) == QgsRasterBlock::ARGB32 ||
iface->dataType( 1 ) == QgsRasterBlock::ARGB32_Premultiplied )
{
WriterError e = writeImageRaster( &iter, nCols, nRows, outputExtent, crs, progressDialog );
mProgressDialog = 0;
Expand Down Expand Up @@ -144,10 +144,10 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster( const Qgs

//check if all the bands have the same data type size, otherwise we cannot write it to the provider
//(at least not with the current interface)
int dataTypeSize = srcProvider->typeSize( srcProvider->srcDataType( 1 ) );
int dataTypeSize = QgsRasterBlock::typeSize( srcProvider->srcDataType( 1 ) );
for ( int i = 2; i <= nBands; ++i )
{
if ( srcProvider->typeSize( srcProvider->srcDataType( 1 ) ) != dataTypeSize )
if ( QgsRasterBlock::typeSize( srcProvider->srcDataType( 1 ) ) != dataTypeSize )
{
return DestProviderError;
}
Expand All @@ -159,16 +159,16 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster( const Qgs
// (not used) value available
QList<bool> destHasNoDataValueList;
QList<double> destNoDataValueList;
QList<QgsRasterInterface::DataType> destDataTypeList;
QList<QgsRasterBlock::DataType> destDataTypeList;
for ( int bandNo = 1; bandNo <= nBands; bandNo++ )
{
QgsRasterNuller *nuller = pipe->nuller();

bool srcHasNoDataValue = srcProvider->srcHasNoDataValue( bandNo );
bool destHasNoDataValue = false;
double destNoDataValue = std::numeric_limits<double>::quiet_NaN();
QgsRasterInterface::DataType destDataType = srcProvider->srcDataType( bandNo );
//QgsRasterInterface::DataType destDataType = srcProvider->dataType( bandNo );
QgsRasterBlock::DataType destDataType = srcProvider->srcDataType( bandNo );
//QgsRasterBlock::DataType destDataType = srcProvider->dataType( bandNo );
// TODO: verify what happens/should happen if srcNoDataValue is disabled by setUseSrcNoDataValue
QgsDebugMsg( QString( "srcHasNoDataValue = %1 srcNoDataValue = %2" ).arg( srcHasNoDataValue ).arg( srcProvider->srcNoDataValue( bandNo ) ) );
if ( srcHasNoDataValue )
Expand Down Expand Up @@ -214,7 +214,7 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster( const Qgs
else
{
// We have to use wider type
destDataType = QgsRasterInterface::typeWithNoDataValue( destDataType, &destNoDataValue );
destDataType = QgsRasterBlock::typeWithNoDataValue( destDataType, &destNoDataValue );
}
destHasNoDataValue = true;
}
Expand All @@ -229,7 +229,7 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster( const Qgs
destNoDataValueList.append( destNoDataValue );
}

QgsRasterInterface::DataType destDataType = destDataTypeList.value( 0 );
QgsRasterBlock::DataType destDataType = destDataTypeList.value( 0 );
// Currently write API supports one output type for dataset only -> find the widest
for ( int i = 1; i < nBands; i++ )
{
Expand All @@ -254,7 +254,7 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster( const Qgs
for ( int i = 0; i < nBands; i++ )
{
double destNoDataValue;
QgsRasterInterface::DataType destDataType = QgsRasterInterface::typeWithNoDataValue( destDataTypeList.value( i ), &destNoDataValue );
QgsRasterBlock::DataType destDataType = QgsRasterBlock::typeWithNoDataValue( destDataTypeList.value( i ), &destNoDataValue );
destDataTypeList.replace( i, destDataType );
destNoDataValueList.replace( i, destNoDataValue );
}
Expand All @@ -274,7 +274,7 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster(
int nCols, int nRows,
const QgsRectangle& outputExtent,
const QgsCoordinateReferenceSystem& crs,
QgsRasterInterface::DataType destDataType,
QgsRasterBlock::DataType destDataType,
QList<bool> destHasNoDataValueList,
QList<double> destNoDataValueList,
QgsRasterDataProvider* destProvider,
Expand All @@ -294,13 +294,13 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster(
int iterCols = 0;
int iterRows = 0;

int dataTypeSize = srcProvider->typeSize( srcProvider->dataType( 1 ) ) / 8;
QList<void*> dataList;
QList<QgsRasterBlock*> blockList;
for ( int i = 1; i <= nBands; ++i )
{
iter->startRasterRead( i, nCols, nRows, outputExtent );
// TODO: no need to alloc memory, change to readBlock() returning the allocated block
dataList.push_back( VSIMalloc( dataTypeSize * mMaxTileWidth * mMaxTileHeight ) );
//blockList.push_back( VSIMalloc( dataTypeSize * mMaxTileWidth * mMaxTileHeight ) );
blockList.push_back( 0 );
// TODO - fix segfault here when using tiles+vrt (reported by Etienne)
destProvider->setNoDataValue( i, destNoDataValueList.value( i - 1 ) );
}
Expand All @@ -323,7 +323,7 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster(
{
for ( int i = 1; i <= nBands; ++i )
{
if ( !iter->readNextRasterPart( i, iterCols, iterRows, &( dataList[i - 1] ), iterLeft, iterTop ) )
if ( !iter->readNextRasterPart( i, iterCols, iterRows, &( blockList[i - 1] ), iterLeft, iterTop ) )
{
delete destProvider;
if ( mTiledMode )
Expand Down Expand Up @@ -354,28 +354,30 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster(
{
for ( int i = 0; i < nBands; ++i )
{
CPLFree( dataList[i] );
delete blockList[i];
}
break;
}
}

// It may happen that internal data type (dataType) is wider than destDataType
QList<void*> destDataList;
QList<QgsRasterBlock*> destBlockList;
for ( int i = 1; i <= nBands; ++i )
{
if ( srcProvider->dataType( i ) == destDataType )
{
destDataList.push_back( dataList[i-1] );
destBlockList.push_back( blockList[i-1] );
}
else
{
// TODO: this conversion should go to QgsRasterDataProvider::write with additional input data type param
void *destData = QgsRasterInterface::convert( dataList[i-1], srcProvider->dataType( i ), destDataType, iterCols * iterRows );
destDataList.push_back( destData );
CPLFree( dataList[i-1] );
//void *destData = QgsRasterBlock::convert( blockList[i-1], srcProvider->dataType( i ), destDataType, iterCols * iterRows );
//destBlockList.push_back( destData );
//CPLFree( blockList[i-1] );
blockList[i-1]->convert( destDataType );
destBlockList.push_back( blockList[i-1] );
}
dataList[i-1] = 0;
blockList[i-1] = 0;
}

if ( mTiledMode ) //write to file
Expand All @@ -387,8 +389,8 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster(
//write data to output file. todo: loop over the data list
for ( int i = 1; i <= nBands; ++i )
{
destProvider->write( destDataList[i - 1], i, iterCols, iterRows, 0, 0 );
CPLFree( destDataList[i - 1] );
destProvider->write( destBlockList[i - 1]->bits( 0 ), i, iterCols, iterRows, 0, 0 );
delete destBlockList[i - 1];
addToVRT( QString::number( fileIndex ), i, iterCols, iterRows, iterLeft, iterTop );
}
}
Expand All @@ -397,8 +399,8 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster(
//loop over data
for ( int i = 1; i <= nBands; ++i )
{
destProvider->write( destDataList[i - 1], i, iterCols, iterRows, iterLeft, iterTop );
CPLFree( destDataList[i - 1] );
destProvider->write( destBlockList[i - 1]->bits( 0 ), i, iterCols, iterRows, iterLeft, iterTop );
delete destBlockList[i - 1];
}
}
++fileIndex;
Expand All @@ -418,9 +420,9 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeImageRaster( QgsRaste
}

const QgsRasterInterface* iface = iter->input();
QgsRasterInterface::DataType inputDataType = iface->dataType( 1 );
if ( !iface || ( inputDataType != QgsRasterInterface::ARGB32 &&
inputDataType != QgsRasterInterface::ARGB32_Premultiplied ) )
QgsRasterBlock::DataType inputDataType = iface->dataType( 1 );
if ( !iface || ( inputDataType != QgsRasterBlock::ARGB32 &&
inputDataType != QgsRasterBlock::ARGB32_Premultiplied ) )
{
return SourceProviderError;
}
Expand All @@ -435,7 +437,7 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeImageRaster( QgsRaste
iter->setMaximumTileWidth( mMaxTileWidth );
iter->setMaximumTileHeight( mMaxTileHeight );

void* data = VSIMalloc( iface->typeSize( inputDataType ) / 8 * mMaxTileWidth * mMaxTileHeight );
//void* data = VSIMalloc( QgsRasterBlock::typeSize( inputDataType ) / 8 * mMaxTileWidth * mMaxTileHeight );
void* redData = VSIMalloc( mMaxTileWidth * mMaxTileHeight );
void* greenData = VSIMalloc( mMaxTileWidth * mMaxTileHeight );
void* blueData = VSIMalloc( mMaxTileWidth * mMaxTileHeight );
Expand All @@ -450,7 +452,7 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeImageRaster( QgsRaste
double geoTransform[6];
globalOutputParameters( outputExtent, nCols, nRows, geoTransform, pixelSize );

destProvider = initOutput( nCols, nRows, crs, geoTransform, 4, QgsRasterInterface::Byte );
destProvider = initOutput( nCols, nRows, crs, geoTransform, 4, QgsRasterBlock::Byte );

//iter->select( outputExtent, outputMapUnitsPerPixel );
iter->startRasterRead( 1, nCols, nRows, outputExtent );
Expand All @@ -466,11 +468,12 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeImageRaster( QgsRaste
progressDialog->setLabelText( QObject::tr( "Reading raster part %1 of %2" ).arg( fileIndex + 1 ).arg( nParts ) );
}

while ( iter->readNextRasterPart( 1, iterCols, iterRows, &data, iterLeft, iterTop ) )
QgsRasterBlock *inputBlock = 0;
while ( iter->readNextRasterPart( 1, iterCols, iterRows, &inputBlock, iterLeft, iterTop ) )
{
if ( iterCols <= 5 || iterRows <= 5 ) //some wms servers don't like small values
{
CPLFree( data );
delete &inputBlock;
continue;
}

Expand All @@ -481,29 +484,28 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeImageRaster( QgsRaste
QCoreApplication::processEvents( QEventLoop::AllEvents, 1000 );
if ( progressDialog->wasCanceled() )
{
CPLFree( data );
delete inputBlock;
break;
}
}

//fill into red/green/blue/alpha channels
uint* p = ( uint* ) data;
int nPixels = iterCols * iterRows;
size_t nPixels = ( size_t )iterCols * iterRows;
// TODO: should be char not int? we are then copying 1 byte
int red = 0;
int green = 0;
int blue = 0;
int alpha = 255;
for ( int i = 0; i < nPixels; ++i )
for ( size_t i = 0; i < nPixels; ++i )
{
QRgb c( *p++ );
QRgb c = inputBlock->color( i );
alpha = qAlpha( c );
red = qRed( c ); green = qGreen( c ); blue = qBlue( c );

if ( inputDataType == QgsRasterInterface::ARGB32_Premultiplied )
if ( inputDataType == QgsRasterBlock::ARGB32_Premultiplied )
{
double a = alpha / 255.;
QgsDebugMsg( QString( "red = %1 green = %2 blue = %3 alpha = %4 p = %5 a = %6" ).arg( red ).arg( green ).arg( blue ).arg( alpha ).arg(( int )*p, 0, 16 ).arg( a ) );
QgsDebugMsgLevel( QString( "red = %1 green = %2 blue = %3 alpha = %4 p = %5 a = %6" ).arg( red ).arg( green ).arg( blue ).arg( alpha ).arg(( int )c, 0, 16 ).arg( a ), 5 );
red /= a;
green /= a;
blue /= a;
Expand All @@ -513,14 +515,14 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeImageRaster( QgsRaste
memcpy(( char* )blueData + i, &blue, 1 );
memcpy(( char* )alphaData + i, &alpha, 1 );
}
CPLFree( data );
delete inputBlock;

//create output file
if ( mTiledMode )
{
delete destProvider;
destProvider = createPartProvider( outputExtent, nCols, iterCols, iterRows,
iterLeft, iterTop, mOutputUrl, fileIndex, 4, QgsRasterInterface::Byte, crs );
iterLeft, iterTop, mOutputUrl, fileIndex, 4, QgsRasterBlock::Byte, crs );

//write data to output file
destProvider->write( redData, 1, iterCols, iterRows, 0, 0 );
Expand Down Expand Up @@ -821,7 +823,7 @@ bool QgsRasterFileWriter::writeVRT( const QString& file )
}

QgsRasterDataProvider* QgsRasterFileWriter::createPartProvider( const QgsRectangle& extent, int nCols, int iterCols,
int iterRows, int iterLeft, int iterTop, const QString& outputUrl, int fileIndex, int nBands, QgsRasterInterface::DataType type,
int iterRows, int iterLeft, int iterTop, const QString& outputUrl, int fileIndex, int nBands, QgsRasterBlock::DataType type,
const QgsCoordinateReferenceSystem& crs )
{
double mup = extent.width() / nCols;
Expand Down Expand Up @@ -858,7 +860,7 @@ QgsRasterDataProvider* QgsRasterFileWriter::createPartProvider( const QgsRectang
}

QgsRasterDataProvider* QgsRasterFileWriter::initOutput( int nCols, int nRows, const QgsCoordinateReferenceSystem& crs,
double* geoTransform, int nBands, QgsRasterInterface::DataType type )
double* geoTransform, int nBands, QgsRasterBlock::DataType type )
{
if ( mTiledMode )
{
Expand Down
6 changes: 3 additions & 3 deletions src/core/raster/qgsrasterfilewriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ class CORE_EXPORT QgsRasterFileWriter
int nCols, int nRows,
const QgsRectangle& outputExtent,
const QgsCoordinateReferenceSystem& crs,
QgsRasterInterface::DataType destDataType,
QgsRasterBlock::DataType destDataType,
QList<bool> destHasNoDataValueList,
QList<double> destNoDataValueList,
QgsRasterDataProvider* destProvider,
Expand All @@ -121,12 +121,12 @@ class CORE_EXPORT QgsRasterFileWriter
/**Create provider and datasource for a part image (vrt mode)*/
QgsRasterDataProvider* createPartProvider( const QgsRectangle& extent, int nCols, int iterCols, int iterRows,
int iterLeft, int iterTop,
const QString& outputUrl, int fileIndex, int nBands, QgsRasterInterface::DataType type,
const QString& outputUrl, int fileIndex, int nBands, QgsRasterBlock::DataType type,
const QgsCoordinateReferenceSystem& crs );

/**Init VRT (for tiled mode) or create global output provider (single-file mode)*/
QgsRasterDataProvider* initOutput( int nCols, int nRows, const QgsCoordinateReferenceSystem& crs, double* geoTransform, int nBands,
QgsRasterInterface::DataType type );
QgsRasterBlock::DataType type );

/**Calculate nRows, geotransform and pixel size for output*/
void globalOutputParameters( const QgsRectangle& extent, int nCols, int& nRows, double* geoTransform, double& pixelSize );
Expand Down
169 changes: 8 additions & 161 deletions src/core/raster/qgsrasterinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,125 +29,21 @@
QgsRasterInterface::QgsRasterInterface( QgsRasterInterface * input )
: mInput( input )
, mOn( true )
, mStatsOn( false )
//, mStatsOn( false )
{
}

QgsRasterInterface::~QgsRasterInterface()
{
}

bool QgsRasterInterface::typeIsNumeric( DataType dataType ) const
bool QgsRasterInterface::isNoDataValue( int bandNo, double value ) const
{
switch ( dataType )
{
case Byte:
case UInt16:
case Int16:
case UInt32:
case Int32:
case Float32:
case CInt16:
case Float64:
case CInt32:
case CFloat32:
case CFloat64:
return true;

case UnknownDataType:
case ARGB32:
case ARGB32_Premultiplied:
case TypeCount:
return false;
}
return false;
}

bool QgsRasterInterface::typeIsColor( DataType dataType ) const
{
switch ( dataType )
{
case ARGB32:
case ARGB32_Premultiplied:
return true;

case UnknownDataType:
case Byte:
case UInt16:
case Int16:
case UInt32:
case Int32:
case Float32:
case CInt16:
case Float64:
case CInt32:
case CFloat32:
case CFloat64:
case TypeCount:
return false;
}
return false;
}

QgsRasterInterface::DataType QgsRasterInterface::typeWithNoDataValue( DataType dataType, double *noDataValue )
{
DataType newDataType;

switch ( dataType )
{
case QgsRasterInterface::Byte:
*noDataValue = -32768.0;
newDataType = QgsRasterInterface::Int16;
break;
case QgsRasterInterface::Int16:
*noDataValue = -2147483648.0;
newDataType = QgsRasterInterface::Int32;
break;
case QgsRasterInterface::UInt16:
*noDataValue = -2147483648.0;
newDataType = QgsRasterInterface::Int32;
break;
case QgsRasterInterface::UInt32:
case QgsRasterInterface::Int32:
case QgsRasterInterface::Float32:
case QgsRasterInterface::Float64:
*noDataValue = std::numeric_limits<double>::max() * -1.0;
newDataType = QgsRasterInterface::Float64;
default:
QgsDebugMsg( QString( "Unknow data type %1" ).arg( dataType ) );
return UnknownDataType;
break;
}
QgsDebugMsg( QString( "newDataType = %1 noDataValue = %2" ).arg( newDataType ).arg( *noDataValue ) );
return newDataType;
}

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

// To give to an image preallocated memory is the only way to avoid memcpy
// when we want to keep data but delete QImage
QImage * QgsRasterInterface::createImage( int width, int height, QImage::Format format )
{
// Qt has its own internal function depthForFormat(), unfortunately it is not public

QImage img( 1, 1, format );

// We ignore QImage::Format_Mono and QImage::Format_MonoLSB ( depth 1)
int size = width * height * img.bytesPerLine();
uchar * data = ( uchar * ) malloc( size );
return new QImage( data, width, height, format );
return QgsRasterBlock::isNoDataValue( value, noDataValue( bandNo ) );
}

#if 0
// version with time counting
void * QgsRasterInterface::block( int bandNo, QgsRectangle const & extent, int width, int height )
{
QTime time;
Expand Down Expand Up @@ -182,7 +78,9 @@ void * QgsRasterInterface::block( int bandNo, QgsRectangle const & extent, int
}
return b;
}
#endif

#if 0
void QgsRasterInterface::setStatsOn( bool on )
{
if ( on )
Expand Down Expand Up @@ -211,56 +109,5 @@ double QgsRasterInterface::time( bool cumulative )
}
return t;
}
#endif

QString QgsRasterInterface::printValue( double value )
{
/*
* IEEE 754 double has 15-17 significant digits. It specifies:
*
* "If a decimal string with at most 15 significant decimal is converted to
* IEEE 754 double precision and then converted back to the same number of
* significant decimal, then the final string should match the original;
* and if an IEEE 754 double precision is converted to a decimal string with at
* least 17 significant decimal and then converted back to double, then the final
* number must match the original."
*
* If printing only 15 digits, some precision could be lost. Printing 17 digits may
* add some confusing digits.
*
* Default 'g' precision on linux is 6 digits, not all significant digits like
* some sprintf manuals say.
*
* We need to ensure that the number printed and used in QLineEdit or XML will
* give the same number when parsed.
*
* Is there a better solution?
*/

QString s;

for ( int i = 15; i <= 17; i++ )
{
s.setNum( value, 'g', i );
if ( s.toDouble() == value )
{
return s;
}
}
// Should not happen
QgsDebugMsg( "Cannot correctly parse printed value" );
return s;
}

void * QgsRasterInterface::convert( void *srcData, QgsRasterInterface::DataType srcDataType, QgsRasterInterface::DataType destDataType, int size )
{
int destDataTypeSize = typeSize( destDataType ) / 8;
void *destData = VSIMalloc( destDataTypeSize * size );
for ( int i = 0; i < size; i++ )
{
double value = readValue( srcData, srcDataType, i );
writeValue( destData, destDataType, i, value );
//double newValue = readValue( destData, destDataType, i );
//QgsDebugMsg( QString("convert type %1 to %2: %3 -> %4").arg(srcDataType).arg(destDataType).arg( value ).arg( newValue ) );
}
return destData;
}
235 changes: 21 additions & 214 deletions src/core/raster/qgsrasterinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <QImage>

#include "qgslogger.h"
#include "qgsrasterblock.h"
#include "qgsrectangle.h"

#include "gdal.h"
Expand All @@ -35,31 +36,7 @@ class CORE_EXPORT QgsRasterInterface
{
public:

/** Data types.
* This is modified and extended 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 the same as
QImage::Format_ARGB32 */ ARGB32 = 12,
/*! Color, alpha, red, green, blue, 4 bytes the same as
QImage::Format_ARGB32_Premultiplied */ ARGB32_Premultiplied = 13,

TypeCount = 14 /* maximum type # + 1 */
};

#if 0
struct Range
{
double min;
Expand All @@ -69,76 +46,29 @@ class CORE_EXPORT QgsRasterInterface
return min == o.min && max == o.max;
}
};
#endif

QgsRasterInterface( QgsRasterInterface * input = 0 );

virtual ~QgsRasterInterface();

static int typeSize( int dataType )
{
// Modified and extended 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 ARGB32:
case ARGB32_Premultiplied:
return 32;

default:
return 0;
}
}

/** Clone itself, create deep copy */
virtual QgsRasterInterface *clone() const = 0;

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

/** Returns true if data type is numeric */
bool typeIsNumeric( DataType type ) const;

/** Returns true if data type is color */
bool typeIsColor( DataType type ) const;

/** Returns data type for the band specified by number */
virtual DataType dataType( int bandNo ) const
virtual QgsRasterBlock::DataType dataType( int bandNo ) const = 0;
#if 0
{
Q_UNUSED( bandNo );
QgsDebugMsg( "Entered" );
return UnknownDataType;
}
#endif

/** For given data type returns wider type and sets no data value */
static DataType typeWithNoDataValue( DataType dataType, double *noDataValue );
int dataTypeSize( int bandNo ) { return QgsRasterBlock::typeSize( dataType( bandNo ) ); }

/** Get number of bands */
virtual int bandCount() const
{
return 1;
}
virtual int bandCount() const = 0;

/** Return no data value for specific band. Each band/provider must have
* no data value, if there is no one set in original data, provider decides one
Expand All @@ -157,18 +87,21 @@ class CORE_EXPORT QgsRasterInterface
* Returns pointer to data.
* Caller is responsible to free the memory returned.
*/
void *block( int bandNo, const QgsRectangle &extent, int width, int height );
//void *block( int bandNo, const QgsRectangle &extent, int width, int height );
virtual QgsRasterBlock *block( int bandNo, const QgsRectangle &extent, int width, int height ) = 0;

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

//{
// Q_UNUSED( bandNo ); Q_UNUSED( extent ); Q_UNUSED( width ); Q_UNUSED( height );
// return new QgsRasterBlock();
//}

/** Set input.
* Returns true if set correctly, false if cannot use that input */
Expand Down Expand Up @@ -198,38 +131,14 @@ class CORE_EXPORT QgsRasterInterface
return mInput ? mInput->srcInput() : this;
}

/** Create a new image with extraneous data, such data may be used
* after the image is destroyed. The memory is not initialized.
*/
QImage * createImage( int width, int height, QImage::Format format );

/** Switch on (and clear old statistics) or off collection of statistics */
void setStatsOn( bool on );
//void setStatsOn( bool on );

/** Last total time (for allbands) consumed by this interface for call to block()
* If cumulative is true, the result includes also time spent in all preceding
* interfaces. If cumulative is false, only time consumed by this interface is
* returned. */
double time( bool cumulative = false );

inline static double readValue( void *data, QgsRasterInterface::DataType type, int index );

inline static void writeValue( void *data, QgsRasterInterface::DataType type, int index, double value );

/** \brief Print double value with all necessary significant digits.
* It is ensured that conversion back to double gives the same number.
* @param value the value to be printed
* @return string representing the value*/
static QString printValue( double value );

/** \brief Convert block of data from one type to another. Original block memory
* is not release.
* @param srcData source data
* @param srcDataType source data type
* @param destDataType dest data type
* @param size block size (width * height)
* @return block of data in destDataType */
static void * convert( void *srcData, QgsRasterInterface::DataType srcDataType, QgsRasterInterface::DataType destDataType, int size );
//double time( bool cumulative = false );

protected:
// QgsRasterInterface used as input
Expand All @@ -238,116 +147,14 @@ class CORE_EXPORT QgsRasterInterface
// On/off state, if off, it does not do anything, replicates input
bool mOn;

/** \brief Test if value is within the list of ranges
* @param value value
* @param rangeList list of ranges
* @return true if value is in at least one of ranges
* @note not available in python bindings
*/
inline static bool valueInRange( double value, QList<QgsRasterInterface::Range> rangeList );

private:
// Last rendering cumulative (this and all preceding interfaces) times, from index 1
QVector<double> mTime;
//QVector<double> mTime;

// Collect statistics
int mStatsOn;
//int mStatsOn;
};

inline double QgsRasterInterface::readValue( void *data, QgsRasterInterface::DataType type, int index )
{
#if 0
if ( !mInput )
{
return 0;
}

if ( !data )
{
return mInput->noDataValue();
}
#endif

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

// TODO: noDataValue is per band
//return mInput->noDataValue();
return std::numeric_limits<double>::quiet_NaN();
}

inline void QgsRasterInterface::writeValue( void *data, QgsRasterInterface::DataType type, int index, double value )
{
if ( !data ) return;

switch ( type )
{
case QgsRasterInterface::Byte:
(( GByte * )data )[index] = ( GByte ) value;
break;
case QgsRasterInterface::UInt16:
(( GUInt16 * )data )[index] = ( GUInt16 ) value;
break;
case QgsRasterInterface::Int16:
(( GInt16 * )data )[index] = ( GInt16 ) value;
break;
case QgsRasterInterface::UInt32:
(( GUInt32 * )data )[index] = ( GUInt32 ) value;
break;
case QgsRasterInterface::Int32:
(( GInt32 * )data )[index] = ( GInt32 ) value;
break;
case QgsRasterInterface::Float32:
(( float * )data )[index] = ( float ) value;
break;
case QgsRasterInterface::Float64:
(( double * )data )[index] = value;
break;
default:
//QgsMessageLog::logMessage( tr( "GDAL data type %1 is not supported" ).arg( type ), tr( "Raster" ) );
break;
}
}

inline bool QgsRasterInterface::valueInRange( double value, QList<QgsRasterInterface::Range> rangeList )
{
foreach ( QgsRasterInterface::Range range, rangeList )
{
if (( value >= range.min && value <= range.max ) ||
doubleNear( value, range.min ) ||
doubleNear( value, range.max ) )
{
return true;
}
}
return false;
}

#endif


12 changes: 8 additions & 4 deletions src/core/raster/qgsrasteriterator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,12 @@ void QgsRasterIterator::startRasterRead( int bandNumber, int nCols, int nRows, c

bool QgsRasterIterator::readNextRasterPart( int bandNumber,
int& nCols, int& nRows,
void** rasterData,
//void** rasterData,
QgsRasterBlock **block,
int& topLeftCol, int& topLeftRow )
{
QgsDebugMsg( "Entered" );
*block = 0;
//get partinfo
QMap<int, RasterPartInfo>::iterator partIt = mRasterPartInfos.find( bandNumber );
if ( partIt == mRasterPartInfos.end() )
Expand All @@ -72,7 +75,7 @@ bool QgsRasterIterator::readNextRasterPart( int bandNumber,
//remove last data block
// TODO: data are released somewhere else (check)
//free( pInfo.data );
pInfo.data = 0;
pInfo.block = 0;
delete pInfo.prj;
pInfo.prj = 0;

Expand All @@ -85,6 +88,7 @@ bool QgsRasterIterator::readNextRasterPart( int bandNumber,
//read data block
nCols = qMin( mMaximumTileWidth, pInfo.nCols - pInfo.currentCol );
nRows = qMin( mMaximumTileHeight, pInfo.nRows - pInfo.currentRow );
QgsDebugMsg( QString( "nCols = %1 nRows = %2" ).arg( nCols ).arg( nRows ) );

//get subrectangle
QgsRectangle viewPortExtent = mExtent;
Expand All @@ -94,9 +98,9 @@ bool QgsRasterIterator::readNextRasterPart( int bandNumber,
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 );
pInfo.block = mInput->block( bandNumber, blockRect, nCols, nRows );

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

Expand Down
5 changes: 4 additions & 1 deletion src/core/raster/qgsrasteriterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <QMap>

class QgsMapToPixel;
class QgsRasterBlock;
class QgsRasterInterface;
class QgsRasterProjector;
struct QgsRasterViewPort;
Expand All @@ -37,6 +38,7 @@ class CORE_EXPORT QgsRasterIterator
int nCols;
int nRows;
void* data; //data (can be in oversampled/undersampled resolution)
QgsRasterBlock *block;
QgsRasterProjector* prj; //raster projector (or 0 if no reprojection is done)
};

Expand All @@ -61,7 +63,8 @@ class CORE_EXPORT QgsRasterIterator
@return false if the last part was already returned*/
bool readNextRasterPart( int bandNumber,
int& nCols, int& nRows,
void** rasterData,
//void** rasterData,
QgsRasterBlock **block,
int& topLeftCol, int& topLeftRow );

void stopRasterRead( int bandNumber );
Expand Down
46 changes: 14 additions & 32 deletions src/core/raster/qgsrasterlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,7 @@ QString QgsRasterLayer::colorShadingAlgorithmAsString() const
return QString( "UndefinedShader" );
}

#if 0
/**
* @param theBand The band (number) for which to estimate the min max values
* @param theMinMax Pointer to a double[2] which hold the estimated min max
Expand Down Expand Up @@ -500,7 +501,7 @@ void QgsRasterLayer::computeMinimumMaximumFromLastExtent( int theBand, double* t
if ( !theMinMax )
return;

QgsRasterInterface::DataType myDataType = mDataProvider->dataType( theBand );
QgsRasterBlock::DataType myDataType = mDataProvider->dataType( theBand );
void* myScanData = readData( theBand, &mLastViewPort );

/* Check for out of memory error */
Expand Down Expand Up @@ -551,6 +552,7 @@ void QgsRasterLayer::computeMinimumMaximumFromLastExtent( int theBand, double& t
theMin = theMinMax[0];
theMax = theMinMax[1];
}
#endif

/**
* @param theBand The band (number) for which to get the contrast enhancement for
Expand Down Expand Up @@ -844,34 +846,12 @@ void QgsRasterLayer::draw( QPainter * theQPainter,
projector->setCRS( theRasterViewPort->mSrcCRS, theRasterViewPort->mDestCRS );
}

#ifdef QGISDEBUG
// Collect stats only for larger sizes to avoid confusion (small time values)
// after thumbnail render e.g. 120 is current thumbnail size
// TODO: consider another way to switch stats on/off or storing of last significant
// stats somehow
if ( theRasterViewPort->drawableAreaXDim > 120 && theRasterViewPort->drawableAreaYDim > 120 )
{
mPipe.setStatsOn( true );
}
#endif

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

#ifdef QGISDEBUG
mPipe.setStatsOn( false );
// Print time stats
QgsDebugMsg( QString( "interface bands time" ) );
for ( int i = 0; i < mPipe.size(); i++ )
{
QgsRasterInterface * interface = mPipe.at( i );
QString name = QString( typeid( *interface ).name() ).replace( QRegExp( ".*Qgs" ), "Qgs" ).left( 30 );
QgsDebugMsg( QString( "%1 %2 %3" ).arg( name, -30 ).arg( interface->bandCount() ).arg( interface->time(), 5 ) );
}
QgsDebugMsg( QString( "total raster draw time (ms): %1" ).arg( time.elapsed(), 5 ) );
#endif
} //end of draw method

QString QgsRasterLayer::drawingStyleAsString() const
Expand Down Expand Up @@ -980,7 +960,7 @@ bool QgsRasterLayer::identify( const QgsPoint & point, QMap<int, QString>& theRe
QMap<int, void *> dataMap = mDataProvider->identify( point );
foreach ( int bandNo, dataMap.keys() )
{
QgsRasterInterface::DataType dataType = mDataProvider->dataType( bandNo );
QgsRasterBlock::DataType dataType = mDataProvider->dataType( bandNo );
void * data = dataMap.value( bandNo );
QString str;
if ( !data )
Expand All @@ -989,7 +969,7 @@ bool QgsRasterLayer::identify( const QgsPoint & point, QMap<int, QString>& theRe
}
else
{
if ( mDataProvider->typeIsNumeric( dataType ) )
if ( QgsRasterBlock::typeIsNumeric( dataType ) )
{
double value = mDataProvider->readValue( data, dataType, 0 );
if ( mDataProvider->isNoDataValue( bandNo, value ) )
Expand Down Expand Up @@ -1788,8 +1768,8 @@ void QgsRasterLayer::setDataProvider( QString const & provider )
{
mRasterType = Multiband;
}
else if ( mDataProvider->dataType( 1 ) == QgsRasterDataProvider::ARGB32
|| mDataProvider->dataType( 1 ) == QgsRasterDataProvider::ARGB32_Premultiplied )
else if ( mDataProvider->dataType( 1 ) == QgsRasterBlock::ARGB32
|| mDataProvider->dataType( 1 ) == QgsRasterBlock::ARGB32_Premultiplied )
{
mRasterType = ColorLayer;
}
Expand Down Expand Up @@ -1943,7 +1923,7 @@ void QgsRasterLayer::setContrastEnhancementAlgorithm( QgsContrastEnhancement::Co
{
if ( myBand != -1 )
{
QgsRasterDataProvider::DataType myType = ( QgsRasterDataProvider::DataType )mDataProvider->dataType( myBand );
QgsRasterBlock::DataType myType = ( QgsRasterBlock::DataType )mDataProvider->dataType( myBand );
QgsContrastEnhancement* myEnhancement = new QgsContrastEnhancement(( QgsContrastEnhancement::QgsRasterDataType )myType );
myEnhancement->setContrastEnhancementAlgorithm( theAlgorithm, theGenerateLookupTableFlag );

Expand Down Expand Up @@ -2057,7 +2037,7 @@ void QgsRasterLayer::setDefaultContrastEnhancement()
}
else if ( mDrawingStyle == MultiBandColor )
{
if ( dataProvider()->typeSize( dataProvider()->srcDataType( 1 ) ) == 8 )
if ( QgsRasterBlock::typeSize( dataProvider()->srcDataType( 1 ) ) == 8 )
{
myKey = "multiBandSingleByte";
myDefault = "NoEnhancement";
Expand Down Expand Up @@ -2679,14 +2659,14 @@ bool QgsRasterLayer::readXml( const QDomNode& layer_node )
if ( ok && ( bandNo > 0 ) && ( bandNo <= mDataProvider->bandCount() ) )
{
mDataProvider->setUseSrcNoDataValue( bandNo, bandElement.attribute( "useSrcNoData" ).toInt() );
QList<QgsRasterInterface::Range> myNoDataRangeList;
QList<QgsRasterBlock::Range> myNoDataRangeList;

QDomNodeList rangeList = bandElement.elementsByTagName( "noDataRange" );

for ( int j = 0; j < rangeList.size(); ++j )
{
QDomElement rangeElement = rangeList.at( j ).toElement();
QgsRasterInterface::Range myNoDataRange;
QgsRasterBlock::Range myNoDataRange;
myNoDataRange.min = rangeElement.attribute( "min" ).toDouble();
myNoDataRange.max = rangeElement.attribute( "max" ).toDouble();
QgsDebugMsg( QString( "min = %1 %2" ).arg( rangeElement.attribute( "min" ) ).arg( myNoDataRange.min ) );
Expand Down Expand Up @@ -2763,7 +2743,7 @@ bool QgsRasterLayer::writeXml( QDomNode & layer_node,
noDataRangeList.setAttribute( "bandNo", bandNo );
noDataRangeList.setAttribute( "useSrcNoData", mDataProvider->useSrcNoDataValue( bandNo ) );

foreach ( QgsRasterInterface::Range range, mDataProvider->userNoDataValue( bandNo ) )
foreach ( QgsRasterBlock::Range range, mDataProvider->userNoDataValue( bandNo ) )
{
QDomElement noDataRange = document.createElement( "noDataRange" );

Expand Down Expand Up @@ -2836,6 +2816,7 @@ QString QgsRasterLayer::projectionWkt()
*data type is the same as raster band. The memory must be released later!
* \return pointer to the memory
*/
#if 0
void *QgsRasterLayer::readData( int bandNo, QgsRasterViewPort *viewPort )
{
int size = mDataProvider->dataTypeSize( bandNo ) / 8;
Expand Down Expand Up @@ -2873,6 +2854,7 @@ void *QgsRasterLayer::readData( int bandNo, QgsRasterViewPort *viewPort )
}
return data;
}
#endif

/*
* @note Called from ctor if a raster image given there
Expand Down
14 changes: 7 additions & 7 deletions src/core/raster/qgsrasterlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -407,30 +407,30 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
/** \brief Wrapper for GDALComputeRasterMinMax with the estimate option
@note python bindings not available
*/
void computeMinimumMaximumEstimates( int theBand, double* theMinMax );
//void computeMinimumMaximumEstimates( int theBand, double* theMinMax );

/** \brief Wrapper for GDALComputeRasterMinMax with the estimate option
@note python bindings not available
*/
void computeMinimumMaximumEstimates( QString theBand, double* theMinMax );
//void computeMinimumMaximumEstimates( QString theBand, double* theMinMax );

/** \brief Wrapper for GDALComputeRasterMinMax with the estimate option
\note added in v1.6 */
void computeMinimumMaximumEstimates( int theBand, double& theMin, double& theMax );
//void computeMinimumMaximumEstimates( int theBand, double& theMin, double& theMax );

/** \brief Compute the actual minimum maximum pixel values based on the current (last) display extent
@note python bindings not available
*/
void computeMinimumMaximumFromLastExtent( int theBand, double* theMinMax );
//void computeMinimumMaximumFromLastExtent( int theBand, double* theMinMax );

/** \brief Compute the actual minimum maximum pixel values based on the current (last) display extent
@note python bindings not available
*/
void computeMinimumMaximumFromLastExtent( QString theBand, double* theMinMax );
//void computeMinimumMaximumFromLastExtent( QString theBand, double* theMinMax );

/** \brief Compute the actual minimum maximum pixel values based on the current (last) display extent
\note added in v1.6 */
void computeMinimumMaximumFromLastExtent( int theBand, double& theMin, double& theMax );
//void computeMinimumMaximumFromLastExtent( int theBand, double& theMin, double& theMax );

/** \brief Get a pointer to the contrast enhancement for the selected band */
QgsContrastEnhancement* contrastEnhancement( unsigned int theBand );
Expand Down Expand Up @@ -788,7 +788,7 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer

/** \brief Allocate memory and load data to that allocated memory */
//void* readData( GDALRasterBandH gdalBand, QgsRasterViewPort *viewPort );
void* readData( int bandNo, QgsRasterViewPort *viewPort );
//void* readData( int bandNo, QgsRasterViewPort *viewPort );

/** \brief Load the given raster file */
bool readFile( const QString & fileName );
Expand Down
28 changes: 15 additions & 13 deletions src/core/raster/qgsrasternuller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,22 +41,23 @@ int QgsRasterNuller::bandCount() const
return 0;
}

QgsRasterInterface::DataType QgsRasterNuller::dataType( int bandNo ) const
QgsRasterBlock::DataType QgsRasterNuller::dataType( int bandNo ) const
{
if ( mInput ) return mInput->dataType( bandNo );
return QgsRasterInterface::UnknownDataType;
return QgsRasterBlock::UnknownDataType;
}

void * QgsRasterNuller::readBlock( int bandNo, QgsRectangle const & extent, int width, int height )
QgsRasterBlock * QgsRasterNuller::block( int bandNo, QgsRectangle const & extent, int width, int height )
{
QgsDebugMsg( "Entered" );
if ( !mInput ) return 0;

//QgsRasterDataProvider *provider = dynamic_cast<QgsRasterDataProvider*>( mInput->srcInput() );

void * rasterData = mInput->block( bandNo, extent, width, height );
QgsRasterBlock *outputBlock = new QgsRasterBlock();
if ( !mInput )
{
return outputBlock;
}

QgsRasterInterface::DataType dataType = mInput->dataType( bandNo );
//void * rasterData = mInput->block( bandNo, extent, width, height );
QgsRasterBlock *inputBlock = mInput->block( bandNo, extent, width, height );

// Input may be without no data value
//double noDataValue = mInput->noDataValue( bandNo );
Expand All @@ -66,22 +67,23 @@ void * QgsRasterNuller::readBlock( int bandNo, QgsRectangle const & extent, int
{
for ( int j = 0; j < width; j++ )
{
int index = i * width + j;
//int index = i * width + j;

double value = readValue( rasterData, dataType, index );
//double value = readValue( rasterData, dataType, index );
double value = inputBlock->value( i, j );

foreach ( NoData noData, mNoData )
{
if (( value >= noData.min && value <= noData.max ) ||
doubleNear( value, noData.min ) ||
doubleNear( value, noData.max ) )
{
writeValue( rasterData, dataType, index, noDataValue );
inputBlock->setValue( i, j, noDataValue );
}
}
}
}

return rasterData;
return inputBlock;
}

4 changes: 2 additions & 2 deletions src/core/raster/qgsrasternuller.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ class CORE_EXPORT QgsRasterNuller : public QgsRasterInterface

int bandCount() const;

QgsRasterInterface::DataType dataType( int bandNo ) const;
QgsRasterBlock::DataType dataType( int bandNo ) const;

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

void setNoData( QList<QgsRasterNuller::NoData> noData ) { mNoData = noData; }

Expand Down
2 changes: 1 addition & 1 deletion src/core/raster/qgsrasterpipe.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ class CORE_EXPORT QgsRasterPipe
QgsRasterNuller * nuller() const;

/** Set on/off collection of statistics */
void setStatsOn( bool on ) { if ( last() ) last()->setStatsOn( on ); }
//void setStatsOn( bool on ) { if ( last() ) last()->setStatsOn( on ); }

private:
/** Get known parent type_info of interface parent */
Expand Down
47 changes: 30 additions & 17 deletions src/core/raster/qgsrasterprojector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,11 @@ int QgsRasterProjector::bandCount() const
return 0;
}

QgsRasterInterface::DataType QgsRasterProjector::dataType( int bandNo ) const
QgsRasterBlock::DataType QgsRasterProjector::dataType( int bandNo ) const
{
if ( mInput ) return mInput->dataType( bandNo );

return QgsRasterInterface::UnknownDataType;
return QgsRasterBlock::UnknownDataType;
}

void QgsRasterProjector::setCRS( const QgsCoordinateReferenceSystem & theSrcCRS, const QgsCoordinateReferenceSystem & theDestCRS )
Expand Down Expand Up @@ -694,11 +694,16 @@ bool QgsRasterProjector::checkRows()
return true;
}

void * QgsRasterProjector::readBlock( int bandNo, QgsRectangle const & extent, int width, int height )
QgsRasterBlock * QgsRasterProjector::block( int bandNo, QgsRectangle const & extent, int width, int height )
{
QgsDebugMsg( QString( "extent:\n%1" ).arg( extent.toString() ) );
QgsDebugMsg( QString( "width = %1 height = %2" ).arg( width ).arg( height ) );
if ( !mInput ) return 0;
QgsRasterBlock *outputBlock = new QgsRasterBlock();
if ( !mInput )
{
return outputBlock;
}


if ( ! mSrcCRS.isValid() || ! mDestCRS.isValid() || mSrcCRS == mDestCRS )
{
Expand All @@ -720,24 +725,28 @@ void * QgsRasterProjector::readBlock( int bandNo, QgsRectangle const & extent,
return 0;
}

void * inputData = mInput->block( bandNo, srcExtent(), srcCols(), srcRows() );

if ( !inputData ) return 0;
//void * inputData = mInput->block( bandNo, srcExtent(), srcCols(), srcRows() );
QgsRasterBlock *inputBlock = mInput->block( bandNo, srcExtent(), srcCols(), srcRows() );
if ( !inputBlock || inputBlock->isEmpty() )
{
QgsDebugMsg( "No raster data!" );
delete inputBlock;
return outputBlock;
}

size_t pixelSize = mInput->typeSize( mInput->dataType( bandNo ) ) / 8;
size_t pixelSize = QgsRasterBlock::typeSize( mInput->dataType( bandNo ) ) / 8;

size_t inputSize = pixelSize * srcCols() * srcRows();

size_t outputSize = width * height * pixelSize;
void * outputData = malloc( outputSize );
//void * outputData = malloc( outputSize );

// Check for allcoation error
if ( ! outputData )
if ( !outputBlock->reset( QgsRasterBlock::ARGB32_Premultiplied, width, height ) )
{
QgsDebugMsg( QString( "Couldn't malloc %1 bytes!" ).arg( outputSize ) );
free( inputData );
return 0;
delete inputBlock;
return outputBlock;
}

// TODO: fill by transparent

int srcRow, srcCol;
Expand All @@ -751,11 +760,15 @@ void * QgsRasterProjector::readBlock( int bandNo, QgsRectangle const & extent,

if ( srcIndex >= inputSize || destIndex >= outputSize ) continue; // should not happen

memcpy(( char* )outputData + destIndex, ( char* )inputData + srcIndex, pixelSize );
//memcpy(( char* )outputData + destIndex, ( char* )inputData + srcIndex, pixelSize );

char *srcBits = inputBlock->bits( srcIndex );
char *destBits = outputBlock->bits( destIndex );
memcpy( destBits, srcBits, pixelSize );
}
}

free( inputData );
delete inputBlock;

return outputData;
return outputBlock;
}
4 changes: 2 additions & 2 deletions src/core/raster/qgsrasterprojector.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ class CORE_EXPORT QgsRasterProjector : public QgsRasterInterface

int bandCount() const;

QgsRasterInterface::DataType dataType( int bandNo ) const;
QgsRasterBlock::DataType dataType( int bandNo ) const;

/** \brief set source and destination CRS */
void setCRS( const QgsCoordinateReferenceSystem & theSrcCRS, const QgsCoordinateReferenceSystem & theDestCRS );
Expand Down Expand Up @@ -101,7 +101,7 @@ class CORE_EXPORT QgsRasterProjector : public QgsRasterInterface
int dstRows() const { return mDestRows; }
int dstCols() const { return mDestCols; }

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


private:
Expand Down
Loading