2,470 changes: 533 additions & 1,937 deletions src/app/qgsrasterlayerproperties.cpp

Large diffs are not rendered by default.

62 changes: 4 additions & 58 deletions src/app/qgsrasterlayerproperties.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class QgsMapLayer;
class QgsMapCanvas;
class QgsRasterLayer;
class QgsMapToolEmitPoint;
class QgsRasterRendererWidget;

/**Property sheet for a raster map layer
*@author Tim Sutton
Expand Down Expand Up @@ -74,59 +75,15 @@ class QgsRasterLayerProperties : public QDialog, private Ui::QgsRasterLayerPrope
/** \brief slot executed when user presses "Remove Selected Row" button on the transparency page */
void on_pbnRemoveSelectedRow_clicked();
/** \brief slot executed when the single band radio button is pressed. */
void on_rbtnSingleBand_toggled( bool );
/** \brief slot executed when the single band min max radio button is pressed. */
void on_rbtnSingleBandMinMax_toggled( bool );
/** \brief slot executed when the single band standard deviation radio button is pressed. */
void on_rbtnSingleBandStdDev_toggled( bool );
/** \brief slot executed when the three band radio button is pressed. */
void on_rbtnThreeBand_toggled( bool );
/** \brief slot executed when the three band min max radio button is pressed. */
void on_rbtnThreeBandMinMax_toggled( bool );
/** \brief slot executed when the three band standard deviation radio button is pressed. */
void on_rbtnThreeBandStdDev_toggled( bool );
/** \brief slot executed when the reset null value to file default icon is selected */
void on_btnResetNull_clicked( );

void pixelSelected( const QgsPoint& );
/** \brief this slot clears min max values from gui */
void sboxSingleBandStdDev_valueChanged( double );
/** \brief this slot clears min max values from gui */
void sboxThreeBandStdDev_valueChanged( double );
/** \brief slot executed when the transparency level changes. */
void sliderTransparency_valueChanged( int );
/** \brief this slot sets StdDev switch box to 0.00 when user enters min max values */
void userDefinedMinMax_textEdited( QString );

private slots:
/** This slow handles necessary interface modifications (i.e. loading min max values) */
void on_cboBlue_currentIndexChanged( const QString& );
/** This slow handles necessary interface modifications (i.e. loading min max values) */
void on_cboGray_currentIndexChanged( const QString& );
/** This slow handles necessary interface modifications (i.e. loading min max values) */
void on_cboGreen_currentIndexChanged( const QString& );
/** This slow handles necessary interface modifications (i.e. loading min max values) */
void on_cboRed_currentIndexChanged( const QString& );
/** This slot handles necessary interface modifications based when color map selected changes */
void on_cboxColorMap_currentIndexChanged( const QString& );
/** This slot calculates classification values and colors for the tree widget on the colormap tab */
void on_mClassifyButton_clicked();
/** This slot deletes the current class from the tree widget on the colormap tab */
void on_mDeleteEntryButton_clicked();
/** Callback for double clicks on the colormap entry widget */
void handleColormapTreeWidgetDoubleClick( QTreeWidgetItem* item, int column );
/** This slot adds a new row to the color map table */
void on_pbtnAddColorMapEntry_clicked();
/** This slots saves the current color map to a file */
void on_pbtnExportColorMapToFile_clicked();
/** This slots loads the current color map from a band */
void on_pbtnLoadColorMapFromBand_clicked();
/** This slots loads the current color map from a file */
void on_pbtnLoadColorMapFromFile_clicked();
/** This slot loads the minimum and maximum values from the raster band and updates the gui */
void on_pbtnLoadMinMax_clicked();
/** This slot will sort the color map in ascending order */
void on_pbtnSortColorMap_clicked();
void on_mRenderTypeComboBox_currentIndexChanged( int index );
/** Load the default style when appropriate button is pressed. */
void on_pbnLoadDefaultStyle_clicked();
/** Save the default style when appropriate button is pressed. */
Expand Down Expand Up @@ -161,9 +118,6 @@ class QgsRasterLayerProperties : public QDialog, private Ui::QgsRasterLayerPrope
int mDefaultGreenBand;
int mDefaultBlueBand;

/** \brief Internal flag used to short circuit signal loop between min max field and stdDev spin box */
bool ignoreSpinBoxEvent;

/** \brief Flag to indicate if Gray minimum maximum values are actual minimum maximum values */
bool mGrayMinimumMaximumEstimated;

Expand All @@ -180,20 +134,12 @@ class QgsRasterLayerProperties : public QDialog, private Ui::QgsRasterLayerPrope
*/
//bool mRasterLayerIsInternal;

/** \brief Clear current color map table and population with values from new list */
void populateColorMapTable( const QList<QgsColorRampShader::ColorRampItem>& );
QgsRasterRendererWidget* mRendererWidget;

/** \brief Clear the current transparency table and populate the table with the correct types for current drawing mode and data type*/
void populateTransparencyTable();

/** \brief Set the message indicating if any min max values are estimates */
void setMinimumMaximumEstimateWarning();

/**Restores the state of the colormap tab*/
void syncColormapTab();

/** \brief Verify values in custom min max line edits */
bool validUserDefinedMinMax();
void setRendererWidget( const QString& rendererName );

//@TODO we should move these gradient generators somewhere more generic
//so they can be used generically throughut the app
Expand Down
10 changes: 10 additions & 0 deletions src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,16 @@ SET(QGIS_CORE_SRCS
raster/qgsrastershader.cpp
raster/qgsrastershaderfunction.cpp

raster/qgsrasterrendererregistry.cpp
raster/qgsrasterrenderer.cpp
raster/qgsbilinearrasterresampler.cpp
raster/qgscubicrasterresampler.cpp
raster/qgspalettedrasterrenderer.cpp
raster/qgsmultibandcolorrenderer.cpp
raster/qgssinglebandcolordatarenderer.cpp
raster/qgssinglebandgrayrenderer.cpp
raster/qgssinglebandpseudocolorrenderer.cpp

renderer/qgscontinuouscolorrenderer.cpp
renderer/qgsgraduatedsymbolrenderer.cpp
renderer/qgsrenderer.cpp
Expand Down
2 changes: 1 addition & 1 deletion src/core/qgsmaplayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ class CORE_EXPORT QgsMapLayer : public QObject
unsigned int getTransparency();

/** Mutator for transparency level. Should be between 0 and 255 */
void setTransparency( unsigned int );
virtual void setTransparency( unsigned int );

/**
* If an operation returns 0 (e.g. draw()), this function
Expand Down
309 changes: 309 additions & 0 deletions src/core/qgsprojectfiletransform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@
#include "qgsprojectfiletransform.h"
#include "qgsprojectversion.h"
#include "qgslogger.h"
#include "qgsrasterlayer.h"
#include "qgsvectordataprovider.h"
#include "qgsvectorlayer.h"
#include <QTextStream>
#include <QDomDocument>
#include <QPrinter> //to find out screen resolution
#include <cstdlib>
#include "qgsproject.h"
#include "qgsprojectproperty.h"

typedef QgsProjectVersion PFV;
Expand All @@ -47,6 +49,8 @@ QgsProjectFileTransform::transform QgsProjectFileTransform::transformers[] =
{PFV( 1, 4, 0 ), PFV( 1, 5, 0 ), &QgsProjectFileTransform::transform1400to1500},
{PFV( 1, 5, 0 ), PFV( 1, 6, 0 ), &QgsProjectFileTransform::transformNull},
{PFV( 1, 6, 0 ), PFV( 1, 7, 0 ), &QgsProjectFileTransform::transformNull},
{PFV( 1, 7, 0 ), PFV( 1, 8, 0 ), &QgsProjectFileTransform::transformNull},
{PFV( 1, 8, 0 ), PFV( 1, 9, 0 ), &QgsProjectFileTransform::transform1800to1900}
};

bool QgsProjectFileTransform::updateRevision( QgsProjectVersion newVersion )
Expand Down Expand Up @@ -451,3 +455,308 @@ void QgsProjectFileTransform::transform1400to1500()
}
}

void QgsProjectFileTransform::transform1800to1900()
{
if ( mDom.isNull() )
{
return;
}

QDomNodeList layerItemList = mDom.elementsByTagName( "rasterproperties" );
for ( int i = 0; i < layerItemList.size(); ++i )
{
QDomElement rasterPropertiesElem = layerItemList.at( i ).toElement();
QDomNode layerNode = rasterPropertiesElem.parentNode();
QDomElement dataSourceElem = layerNode.firstChildElement( "datasource" );
QDomElement layerNameElem = layerNode.firstChildElement( "layername" );
QgsRasterLayer rasterLayer( QgsProject::instance()->readPath( dataSourceElem.text() ), layerNameElem.text() );
convertRasterProperties( mDom, layerNode, rasterPropertiesElem, &rasterLayer );
}
QgsDebugMsg( mDom.toString() );
}

void QgsProjectFileTransform::convertRasterProperties( QDomDocument& doc, QDomNode& parentNode,
QDomElement& rasterPropertiesElem, QgsRasterLayer* rlayer )
{
QDomElement rasterRendererElem = doc.createElement( "rasterrenderer" );
//convert general properties

//invert color
rasterRendererElem.setAttribute( "invertColor", "0" );
QDomElement invertColorElem = rasterPropertiesElem.firstChildElement( "mInvertColor" );
if ( !invertColorElem.isNull() )
{
if ( invertColorElem.text() == "true" )
{
rasterRendererElem.setAttribute( "invertColor", "1" );
}
}

//opacity
rasterRendererElem.setAttribute( "opacity", "1" );
QDomElement transparencyElem = parentNode.firstChildElement( "transparencyLevelInt" );
if ( !transparencyElem.isNull() )
{
double transparency = transparencyElem.text().toInt();
rasterRendererElem.setAttribute( "opacity", transparency / 255.0 );
}

//alphaBand was not saved until now (bug)
rasterRendererElem.setAttribute( "alphaBand", -1 );

//gray band is used for several renderers
int grayBand = rasterBandNumber( rasterPropertiesElem, "mGrayBandName", rlayer );

//convert renderer specific properties
QString drawingStyle = rasterPropertiesElem.firstChildElement( "mDrawingStyle" ).text();
if ( drawingStyle == "SingleBandGray" )
{
rasterRendererElem.setAttribute( "type", "singlebandgray" );
rasterRendererElem.setAttribute( "grayBand", grayBand );
transformContrastEnhancement( doc, rasterPropertiesElem, rasterRendererElem );
}
else if ( drawingStyle == "SingleBandPseudoColor" )
{
rasterRendererElem.setAttribute( "type", "singlebandpseudocolor" );
rasterRendererElem.setAttribute( "band", grayBand );
QDomElement newRasterShaderElem = doc.createElement( "rastershader" );
QDomElement newColorRampShaderElem = doc.createElement( "colorrampshader" );
newRasterShaderElem.appendChild( newColorRampShaderElem );
rasterRendererElem.appendChild( newRasterShaderElem );

//switch depending on mColorShadingAlgorithm
QString colorShadingAlgorithm = rasterPropertiesElem.firstChildElement( "mColorShadingAlgorithm" ).text();
if ( colorShadingAlgorithm == "PseudoColorShader" || colorShadingAlgorithm == "FreakOutShader" )
{
newColorRampShaderElem.setAttribute( "colorRampType", "INTERPOLATED" );

//get minmax from rasterlayer
QgsRasterBandStats rasterBandStats = rlayer->bandStatistics( grayBand );
double minValue = rasterBandStats.minimumValue;
double maxValue = rasterBandStats.maximumValue;
double breakSize = ( maxValue - minValue ) / 3;

QStringList colorList;
if ( colorShadingAlgorithm == "FreakOutShader" )
{
colorList << "#ff00ff" << "#00ffff" << "#ff0000" << "#00ff00";
}
else //pseudocolor
{
colorList << "#0000ff" << "#00ffff" << "#ffff00" << "#ff0000";
}
QStringList::const_iterator colorIt = colorList.constBegin();
double boundValue = minValue;
for ( ; colorIt != colorList.constEnd(); ++colorIt )
{
QDomElement newItemElem = doc.createElement( "item" );
newItemElem.setAttribute( "value", QString::number( boundValue ) );
newItemElem.setAttribute( "label", QString::number( boundValue ) );
newItemElem.setAttribute( "color", *colorIt );
newColorRampShaderElem.appendChild( newItemElem );
boundValue += breakSize;
}
}
else if ( colorShadingAlgorithm == "ColorRampShader" )
{
QDomElement customColorRampElem = rasterPropertiesElem.firstChildElement( "customColorRamp" );
QString type = customColorRampElem.firstChildElement( "colorRampType" ).text();
newColorRampShaderElem.setAttribute( "colorRampType", type );
QDomNodeList colorNodeList = customColorRampElem.elementsByTagName( "colorRampEntry" );

QString value, label;
QColor newColor;
int red, green, blue;
QDomElement currentItemElem;
for ( int i = 0; i < colorNodeList.size(); ++i )
{
currentItemElem = colorNodeList.at( i ).toElement();
value = currentItemElem.attribute( "value" );
label = currentItemElem.attribute( "label" );
red = currentItemElem.attribute( "red" ).toInt();
green = currentItemElem.attribute( "green" ).toInt();
blue = currentItemElem.attribute( "blue" ).toInt();
newColor = QColor( red, green, blue );
QDomElement newItemElem = doc.createElement( "item" );
newItemElem.setAttribute( "value", value );
newItemElem.setAttribute( "label", label );
newItemElem.setAttribute( "color", newColor.name() );
newColorRampShaderElem.appendChild( newItemElem );
}
}
}
else if ( drawingStyle == "PalettedColor" )
{
rasterRendererElem.setAttribute( "type", "paletted" );
rasterRendererElem.setAttribute( "band", grayBand );
QDomElement customColorRampElem = rasterPropertiesElem.firstChildElement( "customColorRamp" );
QDomNodeList colorRampEntryList = customColorRampElem.elementsByTagName( "colorRampEntry" );
QDomElement newColorPaletteElem = doc.createElement( "colorPalette" );

int red = 0;
int green = 0;
int blue = 0;
int value = 0;
QDomElement colorRampEntryElem;
for ( int i = 0; i < colorRampEntryList.size(); ++i )
{
colorRampEntryElem = colorRampEntryList.at( i ).toElement();
QDomElement newPaletteElem = doc.createElement( "paletteEntry" );
value = ( int )( colorRampEntryElem.attribute( "value" ).toDouble() );
newPaletteElem.setAttribute( "value", value );
red = colorRampEntryElem.attribute( "red" ).toInt();
green = colorRampEntryElem.attribute( "green" ).toInt();
blue = colorRampEntryElem.attribute( "blue" ).toInt();
newPaletteElem.setAttribute( "color", QColor( red, green, blue ).name() );
newColorPaletteElem.appendChild( newPaletteElem );
}
rasterRendererElem.appendChild( newColorPaletteElem );
}
else if ( drawingStyle == "MultiBandColor" )
{
rasterRendererElem.setAttribute( "type", "multibandcolor" );

//red band, green band, blue band
int redBand = rasterBandNumber( rasterPropertiesElem, "mRedBandName", rlayer );
int greenBand = rasterBandNumber( rasterPropertiesElem, "mGreenBandName", rlayer );
int blueBand = rasterBandNumber( rasterPropertiesElem, "mBlueBandName", rlayer );
rasterRendererElem.setAttribute( "redBand", redBand );
rasterRendererElem.setAttribute( "greenBand", greenBand );
rasterRendererElem.setAttribute( "blueBand", blueBand );

transformContrastEnhancement( doc, rasterPropertiesElem, rasterRendererElem );
}
else
{
return;
}

//replace rasterproperties element with rasterrenderer element
if ( !parentNode.isNull() )
{
parentNode.replaceChild( rasterRendererElem, rasterPropertiesElem );
}
}

int QgsProjectFileTransform::rasterBandNumber( const QDomElement& rasterPropertiesElem, const QString bandName,
QgsRasterLayer* rlayer )
{
if ( !rlayer )
{
return -1;
}

int band = -1;
QDomElement rasterBandElem = rasterPropertiesElem.firstChildElement( bandName );
if ( !rasterBandElem.isNull() )
{
band = rlayer->bandNumber( rasterBandElem.text() );
if ( band == 0 )
{
band = -1;
}
}
return band;
}

void QgsProjectFileTransform::transformContrastEnhancement( QDomDocument& doc, const QDomElement& rasterproperties, QDomElement& rendererElem )
{
if ( rasterproperties.isNull() || rendererElem.isNull() )
{
return;
}

double minimumValue = 0;
double maximumValue = 0;
QDomElement contrastMinMaxElem = rasterproperties.firstChildElement( "contrastEnhancementMinMaxValues" );
if ( contrastMinMaxElem.isNull() )
{
return;
}

QDomElement contrastEnhancementAlgorithmElem = rasterproperties.firstChildElement( "mContrastEnhancementAlgorithm" );
if ( contrastEnhancementAlgorithmElem.isNull() )
{
return;
}

//convert enhancement name to enumeration
int algorithmEnum = 0;
QString algorithmString = contrastEnhancementAlgorithmElem.text();
if ( algorithmString == "StretchToMinimumMaximum" )
{
algorithmEnum = 1;
}
else if ( algorithmString == "StretchAndClipToMinimumMaximum" )
{
algorithmEnum = 2;
}
else if ( algorithmString == "ClipToMinimumMaximum" )
{
algorithmEnum = 3;
}
else if ( algorithmString == "UserDefinedEnhancement" )
{
algorithmEnum = 4;
}

QDomNodeList minMaxEntryList = contrastMinMaxElem.elementsByTagName( "minMaxEntry" );
QStringList enhancementNameList;
if ( minMaxEntryList.size() == 1 )
{
enhancementNameList << "contrastEnhancement";
}
if ( minMaxEntryList.size() == 3 )
{
enhancementNameList << "redContrastEnhancement" << "greenContrastEnhancement" << "blueContrastEnhancement";
}
if ( minMaxEntryList.size() > enhancementNameList.size() )
{
return;
}

QDomElement minMaxEntryElem;
for ( int i = 0; i < minMaxEntryList.size(); ++i )
{
minMaxEntryElem = minMaxEntryList.at( i ).toElement();
QDomElement minElem = minMaxEntryElem.firstChildElement( "min" );
if ( minElem.isNull() )
{
return;
}
minimumValue = minElem.text().toDouble();

QDomElement maxElem = minMaxEntryElem.firstChildElement( "max" );
if ( maxElem.isNull() )
{
return;
}
maximumValue = maxElem.text().toDouble();

QDomElement newContrastEnhancementElem = doc.createElement( enhancementNameList.at( i ) );
QDomElement newMinValElem = doc.createElement( "minValue" );
QDomText minText = doc.createTextNode( QString::number( minimumValue ) );
newMinValElem.appendChild( minText );
newContrastEnhancementElem.appendChild( newMinValElem );
QDomElement newMaxValElem = doc.createElement( "maxValue" );
QDomText maxText = doc.createTextNode( QString::number( maximumValue ) );
newMaxValElem.appendChild( maxText );
newContrastEnhancementElem.appendChild( newMaxValElem );

QDomElement newAlgorithmElem = doc.createElement( "algorithm" );
QDomText newAlgorithmText = doc.createTextNode( QString::number( algorithmEnum ) );
newAlgorithmElem.appendChild( newAlgorithmText );
newContrastEnhancementElem.appendChild( newAlgorithmElem );

rendererElem.appendChild( newContrastEnhancementElem );
}
}

void QgsProjectFileTransform::transformRasterTransparency( QDomDocument& doc, const QDomElement& orig, QDomElement& rendererElem )
{
//soon...
Q_UNUSED( doc );
Q_UNUSED( orig );
Q_UNUSED( rendererElem );
}

9 changes: 9 additions & 0 deletions src/core/qgsprojectfiletransform.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
#include <vector>
#include "qgsprojectversion.h"

class QgsRasterLayer;

class QgsProjectFileTransform
{
public:
Expand All @@ -56,6 +58,7 @@ class QgsProjectFileTransform
*/
void dump();

static void convertRasterProperties( QDomDocument& doc, QDomNode& parentNode, QDomElement& rasterPropertiesElem, QgsRasterLayer* rlayer );

private:

Expand All @@ -81,6 +84,12 @@ class QgsProjectFileTransform
void transform0110to1000();
void transform1100to1200();
void transform1400to1500();
void transform1800to1900();

//helper functions
static int rasterBandNumber( const QDomElement& rasterPropertiesElem, const QString bandName, QgsRasterLayer* rlayer );
static void transformContrastEnhancement( QDomDocument& doc, const QDomElement& rasterproperties, QDomElement& rendererElem );
static void transformRasterTransparency( QDomDocument& doc, const QDomElement& orig, QDomElement& rendererElem );
};


Expand Down
3 changes: 3 additions & 0 deletions src/core/qgsrasterprojector.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ class QgsRasterProjector
/** get mCPMatrix as string */
QString cpToString();

int dstRows() const { return mDestRows; }
int dstCols() const { return mDestCols; }

private:
/** Source CRS */
QgsCoordinateReferenceSystem mSrcCRS;
Expand Down
33 changes: 33 additions & 0 deletions src/core/raster/qgsbilinearrasterresampler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/***************************************************************************
qgsbilinearrasterresampler.cpp
------------------------------
begin : December 2011
copyright : (C) 2011 by Marco Hugentobler
email : marco at sourcepole dot ch
***************************************************************************/

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

#include "qgsbilinearrasterresampler.h"
#include <QImage>
#include <cmath>

QgsBilinearRasterResampler::QgsBilinearRasterResampler()
{
}

QgsBilinearRasterResampler::~QgsBilinearRasterResampler()
{
}

void QgsBilinearRasterResampler::resample( const QImage& srcImage, QImage& dstImage )
{
dstImage = srcImage.scaled( dstImage.width(), dstImage.height(), Qt::KeepAspectRatio, Qt::SmoothTransformation );
}
34 changes: 34 additions & 0 deletions src/core/raster/qgsbilinearrasterresampler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/***************************************************************************
qgsbilinearrasterresampler.h
----------------------------
begin : December 2011
copyright : (C) 2011 by Marco Hugentobler
email : marco at sourcepole dot ch
***************************************************************************/

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

#ifndef QGSBILINEARRASTERRESAMPLER_H
#define QGSBILINEARRASTERRESAMPLER_H

#include "qgsrasterresampler.h"
#include <QColor>

class QgsBilinearRasterResampler: public QgsRasterResampler
{
public:
QgsBilinearRasterResampler();
~QgsBilinearRasterResampler();

void resample( const QImage& srcImage, QImage& dstImage );
QString type() const { return "bilinear"; }
};

#endif // QGSBILINEARRASTERRESAMPLER_H
9 changes: 9 additions & 0 deletions src/core/raster/qgscolorrampshader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,3 +293,12 @@ bool QgsColorRampShader::shade( double theRedValue, double theGreenValue,

return false;
}

void QgsColorRampShader::legendSymbologyItems( QList< QPair< QString, QColor > >& symbolItems ) const
{
QList<QgsColorRampShader::ColorRampItem>::const_iterator colorRampIt = mColorRampItemList.constBegin();
for ( ; colorRampIt != mColorRampItemList.constEnd(); ++colorRampIt )
{
symbolItems.push_back( qMakePair( colorRampIt->label, colorRampIt->color ) );
}
}
4 changes: 3 additions & 1 deletion src/core/raster/qgscolorrampshader.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class CORE_EXPORT QgsColorRampShader : public QgsRasterShaderFunction
QList<QgsColorRampShader::ColorRampItem> colorRampItemList() const {return mColorRampItemList;}

/** \brief Get the color ramp type */
QgsColorRampShader::ColorRamp_TYPE colorRampType() {return mColorRampType;}
QgsColorRampShader::ColorRamp_TYPE colorRampType() const {return mColorRampType;}

/** \brief Get the color ramp type as a string */
QString colorRampTypeAsQString();
Expand All @@ -91,6 +91,8 @@ class CORE_EXPORT QgsColorRampShader : public QgsRasterShaderFunction
/** \brief Generates and new RGB value based on original RGB value */
bool shade( double, double, double, int*, int*, int* );

void legendSymbologyItems( QList< QPair< QString, QColor > >& symbolItems ) const;

private:
/** Current index from which to start searching the color table*/
int mCurrentColorRampItemIndex;
Expand Down
42 changes: 42 additions & 0 deletions src/core/raster/qgscontrastenhancement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ class originally created circa 2004 by T.Sutton, Gary E.Sherman, Steve Halasz
#include "qgslinearminmaxenhancement.h"
#include "qgslinearminmaxenhancementwithclip.h"
#include "qgscliptominmaxenhancement.h"
#include <QDomDocument>
#include <QDomElement>

QgsContrastEnhancement::QgsContrastEnhancement( QgsRasterDataType theDataType )
{
Expand Down Expand Up @@ -353,3 +355,43 @@ void QgsContrastEnhancement::setMinimumValue( double theValue, bool generateTabl
generateLookupTable();
}
}

void QgsContrastEnhancement::writeXML( QDomDocument& doc, QDomElement& parentElem ) const
{
//minimum value
QDomElement minElem = doc.createElement( "minValue" );
QDomText minText = doc.createTextNode( QString::number( mMinimumValue ) );
minElem.appendChild( minText );
parentElem.appendChild( minElem );

//maximum value
QDomElement maxElem = doc.createElement( "maxValue" );
QDomText maxText = doc.createTextNode( QString::number( mMaximumValue ) );
maxElem.appendChild( maxText );
parentElem.appendChild( maxElem );

//algorithm
QDomElement algorithmElem = doc.createElement( "algorithm" );
QDomText algorithmText = doc.createTextNode( QString::number( mContrastEnhancementAlgorithm ) );
algorithmElem.appendChild( algorithmText );
parentElem.appendChild( algorithmElem );
}

void QgsContrastEnhancement::readXML( const QDomElement& elem )
{
QDomElement minValueElem = elem.firstChildElement( "minValue" );
if ( !minValueElem.isNull() )
{
mMinimumValue = minValueElem.text().toDouble();
}
QDomElement maxValueElem = elem.firstChildElement( "maxValue" );
if ( !maxValueElem.isNull() )
{
mMaximumValue = maxValueElem.text().toDouble();
}
QDomElement algorithmElem = elem.firstChildElement( "algorithm" );
if ( !algorithmElem.isNull() )
{
setContrastEnhancementAlgorithm(( ContrastEnhancementAlgorithm )( algorithmElem.text().toInt() ) );
}
}
6 changes: 6 additions & 0 deletions src/core/raster/qgscontrastenhancement.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ class originally created circa 2004 by T.Sutton, Gary E.Sherman, Steve Halasz
#include <limits>

class QgsContrastEnhancementFunction;
class QDomDocument;
class QDomElement;

/** \ingroup core
* Manipulates raster pixel values so that they enhanceContrast or clip into a
Expand Down Expand Up @@ -119,6 +121,10 @@ class CORE_EXPORT QgsContrastEnhancement
/** \brief Return the minimum value for the contrast enhancement range. */
void setMinimumValue( double, bool generateTable = true );

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

void readXML( const QDomElement& elem );

private:
/** \brief Current contrast enhancement algorithm */
ContrastEnhancementAlgorithm mContrastEnhancementAlgorithm;
Expand Down
456 changes: 456 additions & 0 deletions src/core/raster/qgscubicrasterresampler.cpp

Large diffs are not rendered by default.

66 changes: 66 additions & 0 deletions src/core/raster/qgscubicrasterresampler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/***************************************************************************
qgscubicrasterresampler.h
----------------------------
begin : December 2011
copyright : (C) 2011 by Marco Hugentobler
email : marco at sourcepole dot ch
***************************************************************************/

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

#ifndef QGSCUBICRASTERRESAMPLER_H
#define QGSCUBICRASTERRESAMPLER_H

#include "qgsrasterresampler.h"
#include <QColor>

class QgsCubicRasterResampler: public QgsRasterResampler
{
public:
QgsCubicRasterResampler();
~QgsCubicRasterResampler();
void resample( const QImage& srcImage, QImage& dstImage );
QString type() const { return "cubic"; }

private:
static void xDerivativeMatrix( int nCols, int nRows, double* matrix, const int* colorMatrix );
static void yDerivativeMatrix( int nCols, int nRows, double* matrix, const int* colorMatrix );

void calculateControlPoints( int nCols, int nRows, int currentRow, int currentCol, int* redMatrix, int* greenMatrix, int* blueMatrix,
int* alphaMatrix, double* xDerivativeMatrixRed, double* xDerivativeMatrixGreen, double* xDerivativeMatrixBlue,
double* xDerivativeMatrixAlpha, double* yDerivativeMatrixRed, double* yDerivativeMatrixGreen, double* yDerivativeMatrixBlue,
double* yDerivativeMatrixAlpha );

/**Use cubic curve interpoation at the borders of the raster*/
QRgb curveInterpolation( QRgb pt1, QRgb pt2, double t, double d1red, double d1green, double d1blue, double d1alpha, double d2red, double d2green,
double d2blue, double d2alpha );

static double calcBernsteinPoly( int n, int i, double t );
static int lower( int n, int i );
static double power( double a, int b );//calculates a power b
static int faculty( int n );

//control points

//red
double cRed00; double cRed10; double cRed20; double cRed30; double cRed01; double cRed11; double cRed21; double cRed31;
double cRed02; double cRed12; double cRed22; double cRed32; double cRed03; double cRed13; double cRed23; double cRed33;
//green
double cGreen00; double cGreen10; double cGreen20; double cGreen30; double cGreen01; double cGreen11; double cGreen21; double cGreen31;
double cGreen02; double cGreen12; double cGreen22; double cGreen32; double cGreen03; double cGreen13; double cGreen23; double cGreen33;
//blue
double cBlue00; double cBlue10; double cBlue20; double cBlue30; double cBlue01; double cBlue11; double cBlue21; double cBlue31;
double cBlue02; double cBlue12; double cBlue22; double cBlue32; double cBlue03; double cBlue13; double cBlue23; double cBlue33;
//alpha
double cAlpha00; double cAlpha10; double cAlpha20; double cAlpha30; double cAlpha01; double cAlpha11; double cAlpha21; double cAlpha31;
double cAlpha02; double cAlpha12; double cAlpha22; double cAlpha32; double cAlpha03; double cAlpha13; double cAlpha23; double cAlpha33;
};

#endif // QGSCUBICRASTERRESAMPLER_H
353 changes: 353 additions & 0 deletions src/core/raster/qgsmultibandcolorrenderer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,353 @@
/***************************************************************************
qgsmultibandcolorrenderer.cpp
-----------------------------
begin : December 2011
copyright : (C) 2011 by Marco Hugentobler
email : marco at sourcepole dot ch
***************************************************************************/

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

#include "qgsmultibandcolorrenderer.h"
#include "qgscontrastenhancement.h"
#include "qgsrastertransparency.h"
#include "qgsrasterviewport.h"
#include <QDomDocument>
#include <QDomElement>
#include <QImage>
#include <QSet>

QgsMultiBandColorRenderer::QgsMultiBandColorRenderer( QgsRasterDataProvider* provider, int redBand, int greenBand, int blueBand,
QgsContrastEnhancement* redEnhancement,
QgsContrastEnhancement* greenEnhancement,
QgsContrastEnhancement* blueEnhancement ):
QgsRasterRenderer( provider, "multibandcolor" ), mRedBand( redBand ), mGreenBand( greenBand ), mBlueBand( blueBand ),
mRedContrastEnhancement( redEnhancement ), mGreenContrastEnhancement( greenEnhancement ), mBlueContrastEnhancement( blueEnhancement )
{
}

QgsMultiBandColorRenderer::~QgsMultiBandColorRenderer()
{
delete mRedContrastEnhancement;
delete mGreenContrastEnhancement;
delete mBlueContrastEnhancement;
}

void QgsMultiBandColorRenderer::setRedContrastEnhancement( QgsContrastEnhancement* ce )
{
delete mRedContrastEnhancement; mRedContrastEnhancement = ce;
}

void QgsMultiBandColorRenderer::setGreenContrastEnhancement( QgsContrastEnhancement* ce )
{
delete mGreenContrastEnhancement; mGreenContrastEnhancement = ce;
}

void QgsMultiBandColorRenderer::setBlueContrastEnhancement( QgsContrastEnhancement* ce )
{
delete mBlueContrastEnhancement; mBlueContrastEnhancement = ce;
}

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

//red band, green band, blue band
int redBand = elem.attribute( "redBand", "-1" ).toInt();
int greenBand = elem.attribute( "greenBand", "-1" ).toInt();
int blueBand = elem.attribute( "blueBand", "-1" ).toInt();

//contrast enhancements
QgsContrastEnhancement* redContrastEnhancement = 0;
QDomElement redContrastElem = elem.firstChildElement( "redContrastEnhancement" );
if ( !redContrastElem.isNull() )
{
redContrastEnhancement = new QgsContrastEnhancement(( QgsContrastEnhancement::QgsRasterDataType )(
provider->dataType( redBand ) ) );
redContrastEnhancement->readXML( redContrastElem );
}

QgsContrastEnhancement* greenContrastEnhancement = 0;
QDomElement greenContrastElem = elem.firstChildElement( "greenContrastEnhancement" );
if ( !greenContrastElem.isNull() )
{
greenContrastEnhancement = new QgsContrastEnhancement(( QgsContrastEnhancement::QgsRasterDataType )(
provider->dataType( greenBand ) ) );
greenContrastEnhancement->readXML( greenContrastElem );
}

QgsContrastEnhancement* blueContrastEnhancement = 0;
QDomElement blueContrastElem = elem.firstChildElement( "blueContrastEnhancement" );
if ( !blueContrastElem.isNull() )
{
blueContrastEnhancement = new QgsContrastEnhancement(( QgsContrastEnhancement::QgsRasterDataType )(
provider->dataType( blueBand ) ) );
blueContrastEnhancement->readXML( blueContrastElem );
}

QgsRasterRenderer* r = new QgsMultiBandColorRenderer( provider, redBand, greenBand, blueBand, redContrastEnhancement,
greenContrastEnhancement, blueContrastEnhancement );
r->readXML( elem );
return r;
}

void QgsMultiBandColorRenderer::draw( QPainter* p, QgsRasterViewPort* viewPort, const QgsMapToPixel* theQgsMapToPixel )
{
if ( !p || !mProvider || !viewPort || !theQgsMapToPixel )
{
return;
}

//In some (common) cases, we can simplify the drawing loop considerably and save render time
bool fastDraw = (
!usesTransparency( viewPort->mSrcCRS, viewPort->mDestCRS )
&& mRedBand > 0 && mGreenBand > 0 && mBlueBand > 0
&& mAlphaBand < 1 && !mRedContrastEnhancement && !mGreenContrastEnhancement && !mBlueContrastEnhancement
&& !mInvertColor );

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

double oversamplingX, oversamplingY;
QSet<int> bands;
if ( mRedBand > 0 )
{
bands << mRedBand;
}
if ( mGreenBand > 0 )
{
bands << mGreenBand;
}
if ( mBlueBand > 0 )
{
bands << mBlueBand;
}
if ( bands.size() < 1 )
{
return; //no need to draw anything if no band is set
}

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

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

void* redData = 0;
void* greenData = 0;
void* blueData = 0;
void* alphaData = 0;
//number of cols/rows in output pixels
int nCols = 0;
int nRows = 0;
//number of raster cols/rows with oversampling
int nRasterCols = 0;
int nRasterRows = 0;
//shift to top left point for the raster part
int topLeftCol = 0;
int topLeftRow = 0;

bool readSuccess = true;
while ( true )
{
QSet<int>::const_iterator bandIt = bands.constBegin();
for ( ; bandIt != bands.constEnd(); ++bandIt )
{
readSuccess = readSuccess && readNextRasterPart( *bandIt, oversamplingX, oversamplingY, viewPort, nCols, nRows,
nRasterCols, nRasterRows, &bandData[*bandIt], topLeftCol, topLeftRow );
}

if ( !readSuccess )
{
break;
}

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

QImage img( nRasterCols, nRasterRows, QImage::Format_ARGB32_Premultiplied );
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)

for ( int i = 0; i < nRasterRows; ++i )
{
imageScanLine = ( QRgb* )( img.scanLine( i ) );
for ( int j = 0; j < nRasterCols; ++j )
{

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 );
imageScanLine[j] = qRgba( redVal, greenVal, blueVal, 255 );
++currentRasterPos;
continue;
}

if ( mRedBand > 0 )
{
redVal = readValue( redData, redType, currentRasterPos );
}
if ( mGreenBand > 0 )
{
greenVal = readValue( greenData, greenType, currentRasterPos );
}
if ( mBlueBand > 0 )
{
blueVal = readValue( blueData, blueType, currentRasterPos );
}

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

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

if ( mInvertColor )
{
redVal = 255 - redVal;
greenVal = 255 - greenVal;
blueVal = 255 - 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 ( doubleNear( currentOpacity, 255 ) )
{
imageScanLine[j] = qRgba( redVal, greenVal, blueVal, 255 );
}
else
{
imageScanLine[j] = qRgba( currentOpacity * redVal, currentOpacity * greenVal, currentOpacity * blueVal, currentOpacity * 255 );
}
++currentRasterPos;
}
}

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

bandIt = bands.constBegin();
for ( ; bandIt != bands.constEnd(); ++bandIt )
{
stopRasterRead( *bandIt );
}
}

void QgsMultiBandColorRenderer::writeXML( QDomDocument& doc, QDomElement& parentElem ) const
{
if ( parentElem.isNull() )
{
return;
}

QDomElement rasterRendererElem = doc.createElement( "rasterrenderer" );
_writeXML( doc, rasterRendererElem );
rasterRendererElem.setAttribute( "redBand", mRedBand );
rasterRendererElem.setAttribute( "greenBand", mGreenBand );
rasterRendererElem.setAttribute( "blueBand", mBlueBand );

//contrast enhancement
if ( mRedContrastEnhancement )
{
QDomElement redContrastElem = doc.createElement( "redContrastEnhancement" );
mRedContrastEnhancement->writeXML( doc, redContrastElem );
rasterRendererElem.appendChild( redContrastElem );
}
if ( mGreenContrastEnhancement )
{
QDomElement greenContrastElem = doc.createElement( "greenContrastEnhancement" );
mGreenContrastEnhancement->writeXML( doc, greenContrastElem );
rasterRendererElem.appendChild( greenContrastElem );
}
if ( mBlueContrastEnhancement )
{
QDomElement blueContrastElem = doc.createElement( "blueContrastEnhancement" );
mBlueContrastEnhancement->writeXML( doc, blueContrastElem );
rasterRendererElem.appendChild( blueContrastElem );
}
parentElem.appendChild( rasterRendererElem );
}
70 changes: 70 additions & 0 deletions src/core/raster/qgsmultibandcolorrenderer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/***************************************************************************
qgsmultibandcolorrenderer.h
---------------------------
begin : December 2011
copyright : (C) 2011 by Marco Hugentobler
email : marco at sourcepole dot ch
***************************************************************************/

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

#ifndef QGSMULTIBANDCOLORRENDERER_H
#define QGSMULTIBANDCOLORRENDERER_H

#include "qgsrasterrenderer.h"

class QgsContrastEnhancement;
class QDomElement;

/**Renderer for multiband images with the color components*/
class QgsMultiBandColorRenderer: public QgsRasterRenderer
{
public:
QgsMultiBandColorRenderer( QgsRasterDataProvider* provider, int redBand, int greenBand, int blueBand,
QgsContrastEnhancement* redEnhancement = 0, QgsContrastEnhancement* greenEnhancement = 0,
QgsContrastEnhancement* blueEnhancement = 0 );
~QgsMultiBandColorRenderer();

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

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

int redBand() const { return mRedBand; }
void setRedBand( int band ) { mRedBand = band; }
int greenBand() const { return mGreenBand; }
void setGreenBand( int band ) { mGreenBand = band; }
int blueBand() const { return mBlueBand; }
void setBlueBand( int band ) { mBlueBand = band; }

const QgsContrastEnhancement* redContrastEnhancement() const { return mRedContrastEnhancement; }
/**Takes ownership*/
void setRedContrastEnhancement( QgsContrastEnhancement* ce );

const QgsContrastEnhancement* greenContrastEnhancement() const { return mGreenContrastEnhancement; }
/**Takes ownership*/
void setGreenContrastEnhancement( QgsContrastEnhancement* ce );

const QgsContrastEnhancement* blueContrastEnhancement() const { return mBlueContrastEnhancement; }
/**Takes ownership*/
void setBlueContrastEnhancement( QgsContrastEnhancement* ce );

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

private:
int mRedBand;
int mGreenBand;
int mBlueBand;

QgsContrastEnhancement* mRedContrastEnhancement;
QgsContrastEnhancement* mGreenContrastEnhancement;
QgsContrastEnhancement* mBlueContrastEnhancement;
};

#endif // QGSMULTIBANDCOLORRENDERER_H
219 changes: 219 additions & 0 deletions src/core/raster/qgspalettedrasterrenderer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
/***************************************************************************
qgspalettedrasterrenderer.cpp
-----------------------------
begin : December 2011
copyright : (C) 2011 by Marco Hugentobler
email : marco at sourcepole dot ch
***************************************************************************/

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

#include "qgspalettedrasterrenderer.h"
#include "qgsrastertransparency.h"
#include "qgsrasterviewport.h"
#include <QColor>
#include <QDomDocument>
#include <QDomElement>
#include <QImage>

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

QgsPalettedRasterRenderer::~QgsPalettedRasterRenderer()
{
delete[] mColors;
}

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

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

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

int value = 0;
QDomElement entryElem;
for ( int i = 0; i < nColors; ++i )
{
entryElem = paletteEntries.at( i ).toElement();
value = entryElem.attribute( "value", "0" ).toInt();
QgsDebugMsg( entryElem.attribute( "color", "#000000" ) );
colors[value] = QColor( entryElem.attribute( "color", "#000000" ) );
}
}
QgsRasterRenderer* r = new QgsPalettedRasterRenderer( provider, bandNumber, colors, nColors );
r->readXML( elem );
return r;
}

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

void QgsPalettedRasterRenderer::draw( QPainter* p, QgsRasterViewPort* viewPort, const QgsMapToPixel* theQgsMapToPixel )
{
if ( !p || !mProvider || !viewPort || !theQgsMapToPixel )
{
return;
}

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

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

//number of cols/rows in output pixels
int nCols = 0;
int nRows = 0;
//number of raster cols/rows with oversampling
int nRasterCols = 0;
int nRasterRows = 0;
//shift to top left point for the raster part
int topLeftCol = 0;
int topLeftRow = 0;
int currentRasterPos = 0;
QgsRasterDataProvider::DataType rasterType = ( QgsRasterDataProvider::DataType )mProvider->dataType( mBandNumber );
void* rasterData;
double currentOpacity = mOpacity;

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

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

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

for ( int i = 0; i < nRasterRows; ++i )
{
imageScanLine = ( QRgb* )( img.scanLine( i ) );
for ( int j = 0; j < nRasterCols; ++j )
{
val = readValue( rasterData, rasterType, currentRasterPos );
if ( !hasTransparency )
{
imageScanLine[j] = mColors[ val ].rgba();
}
else
{
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 );
}
}
++currentRasterPos;
}
}

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

//stop raster reading
stopRasterRead( mBandNumber );
if ( mAlphaBand > 0 && mAlphaBand != mBandNumber )
{
stopRasterRead( mAlphaBand );
}
}

void QgsPalettedRasterRenderer::writeXML( QDomDocument& doc, QDomElement& parentElem ) const
{
if ( parentElem.isNull() )
{
return;
}

QDomElement rasterRendererElem = doc.createElement( "rasterrenderer" );
_writeXML( doc, rasterRendererElem );

rasterRendererElem.setAttribute( "band", mBandNumber );
QDomElement colorPaletteElem = doc.createElement( "colorPalette" );
for ( int i = 0; i < mNColors; ++i )
{
QDomElement colorElem = doc.createElement( "paletteEntry" );
colorElem.setAttribute( "value", i );
colorElem.setAttribute( "color", mColors[i].name() );
colorPaletteElem.appendChild( colorElem );
}
rasterRendererElem.appendChild( colorPaletteElem );

parentElem.appendChild( rasterRendererElem );
}

void QgsPalettedRasterRenderer::legendSymbologyItems( QList< QPair< QString, QColor > >& symbolItems ) const
{
for ( int i = 0; i < mNColors; ++i )
{
symbolItems.push_back( qMakePair( QString::number( i ), mColors[i] ) );
}
}
53 changes: 53 additions & 0 deletions src/core/raster/qgspalettedrasterrenderer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/***************************************************************************
qgspalettedrasterrenderer.h
---------------------------
begin : December 2011
copyright : (C) 2011 by Marco Hugentobler
email : marco at sourcepole dot ch
***************************************************************************/

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

#ifndef QGSPALETTEDRASTERRENDERER_H
#define QGSPALETTEDRASTERRENDERER_H

#include "qgsrasterrenderer.h"

class QColor;
class QDomElement;

class QgsPalettedRasterRenderer: public QgsRasterRenderer
{
public:
/**Renderer owns color array*/
QgsPalettedRasterRenderer( QgsRasterDataProvider* provider, int bandNumber, QColor* colorArray, int nColors );
~QgsPalettedRasterRenderer();
static QgsRasterRenderer* create( const QDomElement& elem, QgsRasterDataProvider* provider );

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

/**Returns number of colors*/
int nColors() const { return mNColors; }
/**Returns copy of color array (caller takes ownership)*/
QColor* colors() const;

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

void legendSymbologyItems( QList< QPair< QString, QColor > >& symbolItems ) const;

private:
int mBandNumber;
/**Color array*/
QColor* mColors;
/**Number of colors*/
int mNColors;
};

#endif // QGSPALETTEDRASTERRENDERER_H
2,139 changes: 309 additions & 1,830 deletions src/core/raster/qgsrasterlayer.cpp

Large diffs are not rendered by default.

77 changes: 16 additions & 61 deletions src/core/raster/qgsrasterlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class QgsMapToPixel;
class QgsRectangle;
class QgsRasterBandStats;
class QgsRasterPyramid;
class QgsRasterRenderer;
class QImage;
class QPixmap;
class QSlider;
Expand Down Expand Up @@ -228,9 +229,7 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
PalettedSingleBandGray, // a "Palette" layer drawn in gray scale
PalettedSingleBandPseudoColor, // a "Palette" layerdrawn using a pseudocolor algorithm
PalettedMultiBandColor, // currently not supported
MultiBandSingleGandGray, // a layer containing 2 or more bands, but a single band drawn as a range of gray colors
//added in 1.6 to fix naming glitch
MultiBandSingleBandGray = MultiBandSingleGandGray, // a layer containing 2 or more bands, but a single band drawn as a range of gray colors
MultiBandSingleBandGray, // a layer containing 2 or more bands, but a single band drawn as a range of gray colors
MultiBandSingleBandPseudoColor, //a layer containing 2 or more bands, but a single band drawn using a pseudocolor algorithm
MultiBandColor, //a layer containing 2 or more bands, mapped to RGB color space. In the case of a multiband with only two bands, one band will be mapped to more than one color.
SingleBandColorDataStyle // ARGB values rendered directly
Expand Down Expand Up @@ -371,7 +370,9 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer


/** \brief Mutator for drawing style */
void setDrawingStyle( const DrawingStyle & theDrawingStyle ) { mDrawingStyle = theDrawingStyle; }
void setDrawingStyle( const DrawingStyle & theDrawingStyle ) { mDrawingStyle = theDrawingStyle; setRendererForDrawingStyle( theDrawingStyle ); }
/**Sets corresponding renderer for style*/
void setRendererForDrawingStyle( const DrawingStyle & theDrawingStyle );

/** \brief Mutator for mGrayMinimumMaximumEstimated */
void setGrayMinimumMaximumEstimated( bool theBool ) { mGrayMinimumMaximumEstimated = theBool; }
Expand All @@ -391,6 +392,11 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
/** \brief Mutator for mUserDefinedRGBMinimumMaximum */
void setUserDefinedRGBMinimumMaximum( bool theBool ) { mUserDefinedRGBMinimumMaximum = theBool; }

/**Set raster renderer. Takes ownership of the renderer object*/
void setRenderer( QgsRasterRenderer* renderer );
const QgsRasterRenderer* renderer() const { return mRenderer; }
QgsRasterRenderer* renderer() { return mRenderer; }

/** \brief Accessor to find out how many standard deviations are being plotted */
double standardDeviations() const { return mStandardDeviations; }

Expand Down Expand Up @@ -561,6 +567,8 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
/** \brief Returns the number of raster units per each raster pixel. In a world file, this is normally the first row (without the sign) */
double rasterUnitsPerPixel();

const RasterStatsList rasterStatsList() const { return mRasterStatsList; }

/** \brief Read color table from GDAL raster band */
// Keep this for QgsRasterLayerProperties
bool readColorTable( int theBandNumber, QList<QgsColorRampShader::ColorRampItem>* theList );
Expand Down Expand Up @@ -686,6 +694,9 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
/** \brief receive progress signal from provider */
void onProgress( int, double, QString );

/** \brief Overload the setTransparency method from QgsMapLayer */
void setTransparency( unsigned int theInt );

signals:
/** \brief Signal for notifying listeners of long running processes */
void progressUpdate( int theValue );
Expand Down Expand Up @@ -926,64 +937,8 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
QStringList mStyles;
QString mFormat;
QString mCrs;
};

/*#include <QColor>
typedef void* GDALRasterBandH;
class QgsMapToPixel;
struct QgsRasterViewPort;
class QImage;
class QPainter;*/

/**A class encapsulates reading from a raster band and drawing the pixels to a painter.
The class allows sequential reading of the scan lines and setting the image scan line pixels. It automatically decides
on how much of the band / image should stay in virtual memory at a time*/
class CORE_EXPORT QgsRasterImageBuffer
{
public:
QgsRasterImageBuffer( QgsRasterDataProvider *dataProvider, int bandNo, QPainter* p,
QgsRasterViewPort* viewPort, const QgsMapToPixel* mapToPixel, double* mGeoTransform );
~QgsRasterImageBuffer();
void reset( int maxPixelsInVirtualMemory = 5000000 );
/**Returns a pointer to the next scan line (or 0 if end)*/
bool nextScanLine( QRgb** imageScanLine, void** rasterScanLine );

void setWritingEnabled( bool enabled ) { mWritingEnabled = enabled; }

private:
QgsRasterImageBuffer(); //forbidden
/**Creates next part image. Returns false if at end*/
bool createNextPartImage();

/**Peter's fix for zoomed in rasters*/
void drawPixelRectangle();

QgsRasterDataProvider* mDataProvider;
int mBandNo;
QPainter* mPainter;
QgsRasterViewPort* mViewPort;
const QgsMapToPixel* mMapToPixel;
double* mGeoTransform;

bool mValid;
/**True (default), if values are written to an image. If false, the class only reads the values, but does not create an image*/
bool mWritingEnabled;
/**Draws the raster pixels as rectangles. This is only used if the map units per pixel is very, very small*/
bool mDrawPixelRect;
int mCurrentRow;
int mNumPartImages; //number of part images
int mNumRasterRowsPerPart; //number of (raster source) rows per part
int mCurrentPartRasterMin; //minimum (raster source) row of current image
int mCurrentPartRasterMax; //maximum (raster source) row of current image
int mCurrentPartImageRow; //current image row
int mNumCurrentImageRows; //number of image rows for the current part

int mCurrentPart;

//current memory image and gdal scan data
QImage* mCurrentImage;
void* mCurrentGDALData;
QgsRasterRenderer* mRenderer;
};

#endif
385 changes: 385 additions & 0 deletions src/core/raster/qgsrasterrenderer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,385 @@
/***************************************************************************
qgsrasterrenderer.cpp
---------------------
begin : December 2011
copyright : (C) 2011 by Marco Hugentobler
email : marco at sourcepole dot ch
***************************************************************************/

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

#include "qgsrasterrenderer.h"
#include "qgsrasterresampler.h"
#include "qgsrasterprojector.h"
#include "qgsrastertransparency.h"
#include "qgsrasterviewport.h"
#include "qgsmaptopixel.h"

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

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

QgsRasterRenderer::QgsRasterRenderer( QgsRasterDataProvider* provider, const QString& type ): mProvider( provider ),
mType( type ), mZoomedInResampler( 0 ), mZoomedOutResampler( 0 ), mOpacity( 1.0 ), mRasterTransparency( 0 ),
mAlphaBand( -1 ), mInvertColor( false ), mMaxOversampling( 2.0 )
{
}

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

delete mZoomedInResampler;
delete mZoomedOutResampler;
delete mRasterTransparency;
}

void QgsRasterRenderer::setZoomedInResampler( QgsRasterResampler* r )
{
delete mZoomedInResampler;
mZoomedInResampler = r;
}

void QgsRasterRenderer::setZoomedOutResampler( QgsRasterResampler* r )
{
delete mZoomedOutResampler;
mZoomedOutResampler = r;
}

void QgsRasterRenderer::startRasterRead( int bandNumber, QgsRasterViewPort* viewPort, const QgsMapToPixel* mapToPixel, double& oversamplingX, double& oversamplingY )
{
if ( !viewPort || !mapToPixel || !mProvider )
{
return;
}

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

//calculate oversampling factor
double oversampling = 1.0; //approximate global oversampling factor

if ( mZoomedInResampler || mZoomedOutResampler )
{
QgsRectangle providerExtent = mProvider->extent();
if ( viewPort->mSrcCRS.isValid() && viewPort->mDestCRS.isValid() && viewPort->mSrcCRS != viewPort->mDestCRS )
{
QgsCoordinateTransform t( viewPort->mSrcCRS, viewPort->mDestCRS );
providerExtent = t.transformBoundingBox( providerExtent );
}
double pixelRatio = mapToPixel->mapUnitsPerPixel() / ( providerExtent.width() / mProvider->xSize() );
oversampling = ( pixelRatio > mMaxOversampling ) ? mMaxOversampling : pixelRatio;
}

//set oversampling back to 1.0 if no resampler for zoomed in / zoomed out (nearest neighbour)
if (( oversampling < 1.0 && !mZoomedInResampler ) || ( oversampling > 1.0 && !mZoomedOutResampler ) )
{
oversampling = 1.0;
}

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

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

int totalMemoryUsage = pInfo.nCols * oversamplingX * pInfo.nRows * oversamplingY * mProvider->dataTypeSize( bandNumber );
int parts = totalMemoryUsage / 100000000 + 1;
int nPartsPerDimension = sqrt( parts );
pInfo.nColsPerPart = pInfo.nCols / nPartsPerDimension;
pInfo.nRowsPerPart = pInfo.nRows / nPartsPerDimension;
pInfo.currentCol = 0;
pInfo.currentRow = 0;
pInfo.data = 0;
pInfo.prj = 0;
mRasterPartInfos.insert( bandNumber, pInfo );
}

bool QgsRasterRenderer::readNextRasterPart( int bandNumber, double oversamplingX, double oversamplingY, QgsRasterViewPort* viewPort,
int& nCols, int& nRows, int& nColsRaster, int& nRowsRaster, void** rasterData, int& topLeftCol, int& topLeftRow )
{
if ( !viewPort )
{
return false;
}

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

RasterPartInfo& pInfo = partIt.value();

//remove last data block
CPLFree( pInfo.data );
pInfo.data = 0;
delete pInfo.prj;
pInfo.prj = 0;

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

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

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

if ( viewPort->mSrcCRS.isValid() && viewPort->mDestCRS.isValid() && viewPort->mSrcCRS != viewPort->mDestCRS )
{
pInfo.prj = new QgsRasterProjector( viewPort->mSrcCRS,
viewPort->mDestCRS, blockRect, nRows, nCols, 0, 0, mProvider->extent() );

// If we zoom out too much, projector srcRows / srcCols maybe 0, which can cause problems in providers
if ( pInfo.prj->srcRows() <= 0 || pInfo.prj->srcCols() <= 0 )
{
delete pInfo.prj;
pInfo.prj = 0;
return false;
}

blockRect = pInfo.prj->srcExtent();
}

if ( pInfo.prj )
{
nColsRaster = pInfo.prj->srcCols() * oversamplingX;
nRowsRaster = pInfo.prj->srcRows() * oversamplingY;
}
else
{
nColsRaster = nCols * oversamplingX;
nRowsRaster = nRows * oversamplingY;
}
pInfo.data = VSIMalloc( typeSize * nColsRaster * nRowsRaster );
mProvider->readBlock( bandNumber, blockRect, nColsRaster, nRowsRaster, pInfo.data );
*rasterData = pInfo.data;
topLeftCol = pInfo.currentCol;
topLeftRow = pInfo.currentRow;

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

return true;
}

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

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

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

void QgsRasterRenderer::setRasterTransparency( QgsRasterTransparency* t )
{
delete mRasterTransparency;
mRasterTransparency = t;
}

void QgsRasterRenderer::drawImage( QPainter* p, QgsRasterViewPort* viewPort, const QImage& img, int topLeftCol, int topLeftRow,
int nCols, int nRows, double oversamplingX, double oversamplingY ) const
{
if ( !p || !viewPort )
{
return;
}

//get QgsRasterProjector
QgsRasterProjector* prj;
QMap<int, RasterPartInfo>::const_iterator partInfoIt = mRasterPartInfos.constBegin();
if ( partInfoIt != mRasterPartInfos.constEnd() )
{
prj = partInfoIt->prj;
}

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

//resample and draw image
if (( mZoomedInResampler || mZoomedOutResampler ) && !doubleNear( oversamplingX, 1.0 ) && !doubleNear( oversamplingY, 1.0 ) )
{
QImage dstImg;
if ( prj )
{
dstImg = QImage( prj->srcCols(), prj->srcRows(), QImage::Format_ARGB32_Premultiplied );
}
else
{
dstImg = QImage( nCols, nRows, QImage::Format_ARGB32_Premultiplied );
}
if ( mZoomedInResampler && oversamplingX < 1.0 )
{
mZoomedInResampler->resample( img, dstImg );
}
else if ( mZoomedOutResampler && oversamplingX > 1.0 )
{
mZoomedOutResampler->resample( img, dstImg );
}

if ( prj )
{
QImage projectedImg( nCols, nRows, QImage::Format_ARGB32_Premultiplied );
projectImage( dstImg, projectedImg, prj );
p->drawImage( tlPoint, projectedImg );
}
else
{
p->drawImage( tlPoint, dstImg );
}
}
else //use original image
{
if ( prj )
{
QImage projectedImg( nCols, nRows, QImage::Format_ARGB32_Premultiplied );
projectImage( img, projectedImg, prj );
p->drawImage( tlPoint, projectedImg );
}
else
{
p->drawImage( tlPoint, img );
}
}
}

void QgsRasterRenderer::projectImage( const QImage& srcImg, QImage& dstImage, QgsRasterProjector* prj ) const
{
int nRows = dstImage.height();
int nCols = dstImage.width();
int srcRow, srcCol;
for ( int i = 0; i < nRows; ++i )
{
for ( int j = 0; j < nCols; ++j )
{
prj->srcRowCol( i, j, &srcRow, &srcCol );
dstImage.setPixel( j, i, srcImg.pixel( srcCol, srcRow ) );
}
}
}

void QgsRasterRenderer::_writeXML( QDomDocument& doc, QDomElement& rasterRendererElem ) const
{
if ( rasterRendererElem.isNull() )
{
return;
}

rasterRendererElem.setAttribute( "type", mType );
rasterRendererElem.setAttribute( "opacity", mOpacity );
rasterRendererElem.setAttribute( "alphaBand", mAlphaBand );
rasterRendererElem.setAttribute( "maxOversampling", mMaxOversampling );
rasterRendererElem.setAttribute( "invertColor", mInvertColor );
if ( mZoomedInResampler )
{
rasterRendererElem.setAttribute( "zoomedInResampler", mZoomedInResampler->type() );
}
if ( mZoomedOutResampler )
{
rasterRendererElem.setAttribute( "zoomedOutResampler", mZoomedOutResampler->type() );
}

if ( mRasterTransparency )
{
mRasterTransparency->writeXML( doc, rasterRendererElem );
}
}

void QgsRasterRenderer::readXML( const QDomElement& rendererElem )
{
if ( rendererElem.isNull() )
{
return;
}

mType = rendererElem.attribute( "type" );
mOpacity = rendererElem.attribute( "opacity", "1.0" ).toDouble();
mAlphaBand = rendererElem.attribute( "alphaBand", "-1" ).toInt();
mMaxOversampling = rendererElem.attribute( "maxOversampling", "2.0" ).toDouble();
mInvertColor = rendererElem.attribute( "invertColor", "0" ).toInt();

QString zoomedInResamplerType = rendererElem.attribute( "zoomedInResampler" );
if ( zoomedInResamplerType == "bilinear" )
{
mZoomedInResampler = new QgsBilinearRasterResampler();
}
else if ( zoomedInResamplerType == "cubic" )
{
mZoomedInResampler = new QgsCubicRasterResampler();
}

QString zoomedOutResamplerType = rendererElem.attribute( "zoomedOutResampler" );
if ( zoomedOutResamplerType == "bilinear" )
{
mZoomedOutResampler = new QgsBilinearRasterResampler();
}

//todo: read mRasterTransparency
QDomElement rasterTransparencyElem = rendererElem.firstChildElement( "rasterTransparency" );
if ( !rasterTransparencyElem.isNull() )
{
delete mRasterTransparency;
mRasterTransparency = new QgsRasterTransparency();
mRasterTransparency->readXML( rasterTransparencyElem );
}
}
185 changes: 185 additions & 0 deletions src/core/raster/qgsrasterrenderer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
/***************************************************************************
qgsrasterrenderer.h
-------------------
begin : December 2011
copyright : (C) 2011 by Marco Hugentobler
email : marco at sourcepole dot ch
***************************************************************************/

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

#ifndef QGSRASTERRENDERER_H
#define QGSRASTERRENDERER_H

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

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

class QDomElement;

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

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

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

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

void setOpacity( double opacity ) { mOpacity = opacity; }
double opacity() const { return mOpacity; }

void setRasterTransparency( QgsRasterTransparency* t );
const QgsRasterTransparency* rasterTransparency() const { return mRasterTransparency; }

void setAlphaBand( int band ) { mAlphaBand = band; }
int alphaBand() const { return mAlphaBand; }

void setInvertColor( bool invert ) { mInvertColor = invert; }
bool invertColor() const { return mInvertColor; }

/**Set resampler for zoomed in scales. Takes ownership of the object*/
void setZoomedInResampler( QgsRasterResampler* r );
const QgsRasterResampler* zoomedInResampler() const { return mZoomedInResampler; }

/**Set resampler for zoomed out scales. Takes ownership of the object*/
void setZoomedOutResampler( QgsRasterResampler* r );
const QgsRasterResampler* zoomedOutResampler() const { return mZoomedOutResampler; }

void setMaxOversampling( double os ) { mMaxOversampling = os; }
double maxOversampling() const { return mMaxOversampling; }

/**Get symbology items if provided by renderer*/
virtual void legendSymbologyItems( QList< QPair< QString, QColor > >& symbolItems ) const { Q_UNUSED( symbolItems ); }

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

/**Sets base class members from xml. Usually called from create() methods of subclasses*/
void readXML( const QDomElement& rendererElem );

protected:
inline double readValue( void *data, QgsRasterDataProvider::DataType type, int index );

/**Start reading of raster band. Raster data can then be retrieved by calling readNextRasterPart until it returns false.
@param bandNumer number of raster band to read
@param viewPort describes raster position on screen
@param oversamplingX out: oversampling rate in x-direction
@param oversamplingY out: oversampling rate in y-direction*/
void startRasterRead( int bandNumber, QgsRasterViewPort* viewPort, const QgsMapToPixel* mapToPixel, double& oversamplingX, double& oversamplingY );
/**Fetches next part of raster data
@param nCols number of columns on output device
@param nRows number of rows on output device
@param nColsRaster number of raster columns (different to nCols if oversamplingX != 1.0)
@param nRowsRaster number of raster rows (different to nRows if oversamplingY != 0)*/
bool readNextRasterPart( int bandNumber, double oversamplingX, double oversamplingY, QgsRasterViewPort* viewPort, int& nCols, int& nRows,
int& nColsRaster, int& nRowsRaster, void** rasterData, int& topLeftCol, int& topLeftRow );
/**Draws raster part
@param topLeftCol Left position relative to left border of viewport
@param topLeftRow Top position relative to top border of viewport*/
void drawImage( QPainter* p, QgsRasterViewPort* viewPort, const QImage& img, int topLeftCol, int topLeftRow,
int nCols, int nRows, double oversamplingX, double oversamplingY ) const;
void stopRasterRead( int bandNumber );

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


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

/**Global alpha value (0-1)*/
double mOpacity;
/**Raster transparency per color or value. Overwrites global alpha value*/
QgsRasterTransparency* mRasterTransparency;
/**Read alpha value from band. Is combined with value from raster transparency / global alpha value.
Default: -1 (not set)*/
int mAlphaBand;

bool mInvertColor;

/**Maximum boundary for oversampling (to avoid too much data traffic). Default: 2.0*/
double mMaxOversampling;

private:
/**Remove part into and release memory*/
void removePartInfo( int bandNumer );
void projectImage( const QImage& srcImg, QImage& dstImage, QgsRasterProjector* prj ) const;
};

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

if ( !data )
{
return mProvider->noDataValue();
}

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

return mProvider->noDataValue();
}

#endif // QGSRASTERRENDERER_H
107 changes: 107 additions & 0 deletions src/core/raster/qgsrasterrendererregistry.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/***************************************************************************
qgsrasterrendererregistry.cpp
-----------------------------
begin : January 2012
copyright : (C) 2012 by Marco Hugentobler
email : marco at sourcepole dot ch
***************************************************************************/

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

#include "qgsrasterrendererregistry.h"
#include "qgsmultibandcolorrenderer.h"
#include "qgspalettedrasterrenderer.h"
#include "qgssinglebandcolordatarenderer.h"
#include "qgssinglebandgrayrenderer.h"
#include "qgssinglebandpseudocolorrenderer.h"

QgsRasterRendererRegistryEntry::QgsRasterRendererRegistryEntry( const QString& theName, const QString& theVisibleName,
QgsRasterRendererCreateFunc rendererFunction,
QgsRasterRendererWidgetCreateFunc widgetFunction ):
name( theName ), visibleName( theVisibleName ), rendererCreateFunction( rendererFunction ),
widgetCreateFunction( widgetFunction )
{
}

QgsRasterRendererRegistryEntry::QgsRasterRendererRegistryEntry(): rendererCreateFunction( 0 ), widgetCreateFunction( 0 )
{
}

QgsRasterRendererRegistry* QgsRasterRendererRegistry::mInstance = 0;

QgsRasterRendererRegistry* QgsRasterRendererRegistry::instance()
{
if ( !mInstance )
{
mInstance = new QgsRasterRendererRegistry();
}
return mInstance;
}

QgsRasterRendererRegistry::QgsRasterRendererRegistry()
{
insert( QgsRasterRendererRegistryEntry( "paletted", QObject::tr( "Paletted" ), QgsPalettedRasterRenderer::create, 0 ) );
insert( QgsRasterRendererRegistryEntry( "multibandcolor", QObject::tr( "Multiband color" ),
QgsMultiBandColorRenderer::create, 0 ) );
insert( QgsRasterRendererRegistryEntry( "singlebandpseudocolor", QObject::tr( "Singleband pseudocolor" ),
QgsSingleBandPseudoColorRenderer::create, 0 ) );
insert( QgsRasterRendererRegistryEntry( "singlebandgray", QObject::tr( "Singleband gray" ),
QgsSingleBandGrayRenderer::create, 0 ) );
insert( QgsRasterRendererRegistryEntry( "singlebandcolordata", QObject::tr( "Singleband color data" ),
QgsSingleBandColorDataRenderer::create, 0 ) );
}

QgsRasterRendererRegistry::~QgsRasterRendererRegistry()
{
}

void QgsRasterRendererRegistry::insert( QgsRasterRendererRegistryEntry entry )
{
mEntries.insert( entry.name, entry );
}

void QgsRasterRendererRegistry::insertWidgetFunction( const QString& rendererName, QgsRasterRendererWidgetCreateFunc func )
{
if ( !mEntries.contains( rendererName ) )
{
return;
}
mEntries[rendererName].widgetCreateFunction = func;
}

bool QgsRasterRendererRegistry::rendererData( const QString& rendererName, QgsRasterRendererRegistryEntry& data ) const
{
QHash< QString, QgsRasterRendererRegistryEntry >::const_iterator it = mEntries.find( rendererName );
if ( it == mEntries.constEnd() )
{
return false;
}
data = it.value();
return true;
}

QStringList QgsRasterRendererRegistry::renderersList() const
{
return QStringList( mEntries.keys() );
}

QList< QgsRasterRendererRegistryEntry > QgsRasterRendererRegistry::entries() const
{
QList< QgsRasterRendererRegistryEntry > result;

QHash< QString, QgsRasterRendererRegistryEntry >::const_iterator it = mEntries.constBegin();
for ( ; it != mEntries.constEnd(); ++it )
{
result.push_back( it.value() );
}
return result;
}


64 changes: 64 additions & 0 deletions src/core/raster/qgsrasterrendererregistry.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/***************************************************************************
qgsrasterrendererregistry.h
---------------------------
begin : January 2012
copyright : (C) 2012 by Marco Hugentobler
email : marco at sourcepole dot ch
***************************************************************************/

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

#ifndef QGSRASTERRENDERERREGISTRY_H
#define QGSRASTERRENDERERREGISTRY_H

#include <QHash>
#include <QString>

class QDomElement;
class QgsRasterDataProvider;
class QgsRasterLayer;
class QgsRasterRenderer;
class QgsRasterRendererWidget;

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

struct QgsRasterRendererRegistryEntry
{
QgsRasterRendererRegistryEntry( const QString& theName, const QString& theVisibleName, QgsRasterRendererCreateFunc rendererFunction,
QgsRasterRendererWidgetCreateFunc widgetFunction );
QgsRasterRendererRegistryEntry();
QString name;
QString visibleName; //visible (and translatable) name
QgsRasterRendererCreateFunc rendererCreateFunction; //pointer to create function
QgsRasterRendererWidgetCreateFunc widgetCreateFunction; //pointer to create function for renderer widget
};

class QgsRasterRendererRegistry
{
public:
static QgsRasterRendererRegistry* instance();
~QgsRasterRendererRegistry();

void insert( QgsRasterRendererRegistryEntry entry );
void insertWidgetFunction( const QString& rendererName, QgsRasterRendererWidgetCreateFunc func );
bool rendererData( const QString& rendererName, QgsRasterRendererRegistryEntry& data ) const;
QStringList renderersList() const;
QList< QgsRasterRendererRegistryEntry > entries() const;

protected:
QgsRasterRendererRegistry();

private:
static QgsRasterRendererRegistry* mInstance;
QHash< QString, QgsRasterRendererRegistryEntry > mEntries;
};

#endif // QGSRASTERRENDERERREGISTRY_H
33 changes: 33 additions & 0 deletions src/core/raster/qgsrasterresampler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/***************************************************************************
qgsrasterresampler.h
--------------------
begin : December 2011
copyright : (C) 2011 by Marco Hugentobler
email : marco at sourcepole dot ch
***************************************************************************/

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

#ifndef QGSRASTERRESAMPLER_H
#define QGSRASTERRESAMPLER_H

#include <QString>

class QImage;

/**Interface for resampling rasters (e.g. to have a smoother appearance)*/
class QgsRasterResampler
{
public:
virtual void resample( const QImage& srcImage, QImage& dstImage ) = 0;
virtual QString type() const = 0;
};

#endif // QGSRASTERRESAMPLER_H
62 changes: 61 additions & 1 deletion src/core/raster/qgsrastershader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ email : ersts@amnh.org
***************************************************************************/

#include "qgslogger.h"

#include "qgscolorrampshader.h"
#include "qgsrastershader.h"
#include <QDomDocument>
#include <QDomElement>

QgsRasterShader::QgsRasterShader( double theMinimumValue, double theMaximumValue )
{
Expand Down Expand Up @@ -124,3 +126,61 @@ void QgsRasterShader::setMinimumValue( double theValue )
mRasterShaderFunction->setMinimumValue( theValue );
}
}

void QgsRasterShader::writeXML( QDomDocument& doc, QDomElement& parent ) const
{
if ( parent.isNull() || !mRasterShaderFunction )
{
return;
}

QDomElement rasterShaderElem = doc.createElement( "rastershader" );
QgsColorRampShader* colorRampShader = dynamic_cast<QgsColorRampShader*>( mRasterShaderFunction );
if ( colorRampShader )
{
QDomElement colorRampShaderElem = doc.createElement( "colorrampshader" );
colorRampShaderElem.setAttribute( "colorRampType", colorRampShader->colorRampTypeAsQString() );
//items
QList<QgsColorRampShader::ColorRampItem> itemList = colorRampShader->colorRampItemList();
QList<QgsColorRampShader::ColorRampItem>::const_iterator itemIt = itemList.constBegin();
for ( ; itemIt != itemList.constEnd(); ++itemIt )
{
QDomElement itemElem = doc.createElement( "item" );
itemElem.setAttribute( "label", itemIt->label );
itemElem.setAttribute( "value", itemIt->value );
itemElem.setAttribute( "color", itemIt->color.name() );
colorRampShaderElem.appendChild( itemElem );
}
rasterShaderElem.appendChild( colorRampShaderElem );
}
parent.appendChild( rasterShaderElem );
}

void QgsRasterShader::readXML( const QDomElement& elem )
{
//only colorrampshader
QDomElement colorRampShaderElem = elem.firstChildElement( "colorrampshader" );
if ( !colorRampShaderElem.isNull() )
{
QgsColorRampShader* colorRampShader = new QgsColorRampShader();
colorRampShader->setColorRampType( colorRampShaderElem.attribute( "colorRampType", "INTERPOLATED" ) );

QList<QgsColorRampShader::ColorRampItem> itemList;
QDomElement itemElem;
QString itemLabel;
double itemValue;
QColor itemColor;

QDomNodeList itemNodeList = colorRampShaderElem.elementsByTagName( "item" );
for ( int i = 0; i < itemNodeList.size(); ++i )
{
itemElem = itemNodeList.at( i ).toElement();
itemValue = itemElem.attribute( "value" ).toDouble();
itemLabel = itemElem.attribute( "label" );
itemColor.setNamedColor( itemElem.attribute( "color" ) );
itemList.push_back( QgsColorRampShader::ColorRampItem( itemValue, itemColor, itemLabel ) );
}
colorRampShader->setColorRampItemList( itemList );
setRasterShaderFunction( colorRampShader );
}
}
8 changes: 8 additions & 0 deletions src/core/raster/qgsrastershader.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ email : ersts@amnh.org

#include "qgsrastershaderfunction.h"

class QDomDocument;
class QDomElement;

/** \ingroup core
* Interface for all raster shaders.
*/
Expand All @@ -44,6 +47,7 @@ class CORE_EXPORT QgsRasterShader
double minimumValue() { return mMinimumValue; }

QgsRasterShaderFunction* rasterShaderFunction() { return mRasterShaderFunction; }
const QgsRasterShaderFunction* rasterShaderFunction() const { return mRasterShaderFunction; }

/*
*
Expand All @@ -66,6 +70,10 @@ class CORE_EXPORT QgsRasterShader
/** \brief Return the minimum value */
void setMinimumValue( double );

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

void readXML( const QDomElement& elem );

private:
/** \brief User defineable minimum value for the raster shader */
double mMinimumValue;
Expand Down
5 changes: 5 additions & 0 deletions src/core/raster/qgsrastershaderfunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ email : ersts@amnh.org
* typically used to render grayscale images as false color.
*/

#include <QColor>
#include <QPair>

class CORE_EXPORT QgsRasterShaderFunction
{

Expand All @@ -48,6 +51,8 @@ class CORE_EXPORT QgsRasterShaderFunction
double minimumValue() const { return mMinimumValue; }
double maximumValue() const { return mMaximumValue; }

virtual void legendSymbologyItems( QList< QPair< QString, QColor > >& symbolItems ) const { Q_UNUSED( symbolItems ); }

protected:
/** \brief User defineable maximum value for the shading function */
double mMaximumValue;
Expand Down
92 changes: 91 additions & 1 deletion src/core/raster/qgsrastertransparency.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@ email : ersts@amnh.org
* (at your option) any later version. *
* *
***************************************************************************/
#include <QList>

#include "qgsrastertransparency.h"
#include "qgis.h"

#include <QDomDocument>
#include <QDomElement>

QgsRasterTransparency::QgsRasterTransparency()
{
Expand Down Expand Up @@ -168,3 +171,90 @@ int QgsRasterTransparency::alphaValue( double theRedValue, double theGreenValue,

return theGlobalTransparency;
}

bool QgsRasterTransparency::isEmpty( double nodataValue ) const
{
return (
( mTransparentSingleValuePixelList.isEmpty() ||
( mTransparentSingleValuePixelList.size() == 1 && doubleNear( mTransparentSingleValuePixelList.at( 0 ).pixelValue, nodataValue ) ) )
&&
( mTransparentThreeValuePixelList.isEmpty() ||
( mTransparentThreeValuePixelList.size() < 4 && doubleNear( mTransparentThreeValuePixelList.at( 0 ).red, nodataValue ) &&
doubleNear( mTransparentThreeValuePixelList.at( 0 ).green, nodataValue ) && doubleNear( mTransparentThreeValuePixelList.at( 0 ).blue, nodataValue ) ) ) );
}

void QgsRasterTransparency::writeXML( QDomDocument& doc, QDomElement& parentElem ) const
{
QDomElement rasterTransparencyElem = doc.createElement( "rasterTransparency" );
if ( mTransparentSingleValuePixelList.count() > 0 )
{
QDomElement singleValuePixelListElement = doc.createElement( "singleValuePixelList" );
QList<QgsRasterTransparency::TransparentSingleValuePixel>::const_iterator it = mTransparentSingleValuePixelList.constBegin();
for ( ; it != mTransparentSingleValuePixelList.constEnd(); ++it )
{
QDomElement pixelListElement = doc.createElement( "pixelListEntry" );
pixelListElement.setAttribute( "pixelValue", QString::number( it->pixelValue, 'f' ) );
pixelListElement.setAttribute( "percentTransparent", QString::number( it->percentTransparent ) );
singleValuePixelListElement.appendChild( pixelListElement );
}
rasterTransparencyElem.appendChild( singleValuePixelListElement );

}
if ( mTransparentThreeValuePixelList.count() > 0 )
{
QDomElement threeValuePixelListElement = doc.createElement( "threeValuePixelList" );
QList<QgsRasterTransparency::TransparentThreeValuePixel>::const_iterator it = mTransparentThreeValuePixelList.constBegin();
for ( ; it != mTransparentThreeValuePixelList.constEnd(); ++it )
{
QDomElement pixelListElement = doc.createElement( "pixelListEntry" );
pixelListElement.setAttribute( "red", QString::number( it->red, 'f' ) );
pixelListElement.setAttribute( "green", QString::number( it->green, 'f' ) );
pixelListElement.setAttribute( "blue", QString::number( it->blue, 'f' ) );
pixelListElement.setAttribute( "percentTransparent", QString::number( it->percentTransparent ) );
threeValuePixelListElement.appendChild( pixelListElement );
}
rasterTransparencyElem.appendChild( threeValuePixelListElement );
}
parentElem.appendChild( rasterTransparencyElem );
}

void QgsRasterTransparency::readXML( const QDomElement& elem )
{
if ( elem.isNull() )
{
return;
}

mTransparentSingleValuePixelList.clear();
mTransparentThreeValuePixelList.clear();
QDomElement currentEntryElem;

QDomElement singlePixelListElem = elem.firstChildElement( "singleValuePixelList" );
if ( !singlePixelListElem.isNull() )
{
QDomNodeList entryList = singlePixelListElem.elementsByTagName( "pixelListEntry" );
TransparentSingleValuePixel sp;
for ( int i = 0; i < entryList.size(); ++i )
{
currentEntryElem = entryList.at( i ).toElement();
sp.percentTransparent = currentEntryElem.attribute( "percentTransparent" ).toDouble();
sp.pixelValue = currentEntryElem.attribute( "pixelValue" ).toDouble();
mTransparentSingleValuePixelList.append( sp );
}
}
QDomElement threeValuePixelListElem = elem.firstChildElement( "threeValuePixelList" );
if ( !threeValuePixelListElem.isNull() )
{
QDomNodeList entryList = threeValuePixelListElem.elementsByTagName( "pixelListEntry" );
TransparentThreeValuePixel tp;
for ( int i = 0; i < entryList.size(); ++i )
{
currentEntryElem = entryList.at( i ).toElement();
tp.red = currentEntryElem.attribute( "red" ).toDouble();
tp.green = currentEntryElem.attribute( "green" ).toDouble();
tp.blue = currentEntryElem.attribute( "blue" ).toDouble();
tp.percentTransparent = currentEntryElem.attribute( "percentTransparent" ).toDouble();
mTransparentThreeValuePixelList.append( tp );
}
}
}
Loading