Skip to content

Commit

Permalink
move gamma correction code inside brightness/contrast filter
Browse files Browse the repository at this point in the history
  • Loading branch information
alexbruy committed Jun 30, 2020
1 parent cfa5c5b commit 0214b4f
Show file tree
Hide file tree
Showing 22 changed files with 68 additions and 493 deletions.
Expand Up @@ -13,7 +13,7 @@
class QgsBrightnessContrastFilter : QgsRasterInterface
{
%Docstring
Brightness/contrast filter pipe for rasters.
Brightness/contrast and gamma correction filter pipe for rasters.
%End

%TypeHeaderCode
Expand Down Expand Up @@ -43,6 +43,9 @@ Brightness/contrast filter pipe for rasters.
void setContrast( int contrast );
int contrast() const;

void setGamma( double gamma );
double gamma() const;

virtual void writeXml( QDomDocument &doc, QDomElement &parentElem ) const;


Expand Down
62 changes: 0 additions & 62 deletions python/core/auto_generated/raster/qgsgammacorrectionfilter.sip.in

This file was deleted.

3 changes: 0 additions & 3 deletions python/core/auto_generated/raster/qgsrasterinterface.sip.in
Expand Up @@ -95,7 +95,6 @@ Base class for processing filters like renderers, reprojector, resampler etc.
#include "qgsrasterinterface.h"
// QgsRasterInterface subclasses
#include <qgsbrightnesscontrastfilter.h>
#include <qgsgammacorrectionfilter.h>
#include <qgshuesaturationfilter.h>
#include <qgsrasterdataprovider.h>
#include <qgsrasternuller.h>
Expand All @@ -116,8 +115,6 @@ Base class for processing filters like renderers, reprojector, resampler etc.
sipType = sipType_QgsBrightnessContrastFilter;
else if ( dynamic_cast<QgsHueSaturationFilter *>( sipCpp ) )
sipType = sipType_QgsHueSaturationFilter;
else if ( dynamic_cast<QgsGammaCorrectionFilter *>( sipCpp ) )
sipType = sipType_QgsGammaCorrectionFilter;
else if ( dynamic_cast<QgsRasterDataProvider *>( sipCpp ) )
{
sipType = sipType_QgsRasterDataProvider;
Expand Down
19 changes: 0 additions & 19 deletions python/core/auto_generated/raster/qgsrasterlayer.sip.in
Expand Up @@ -190,8 +190,6 @@ Returns the raster's resample filter.

.. seealso:: :py:func:`brightnessFilter`

.. seealso:: :py:func:`gammaCorrectionFilter`

.. seealso:: :py:func:`hueSaturationFilter`
%End

Expand All @@ -201,22 +199,7 @@ Returns the raster's brightness/contrast filter.

.. seealso:: :py:func:`resampleFilter`

.. seealso:: :py:func:`gammaCorrectionFilter`

.. seealso:: :py:func:`hueSaturationFilter`
%End

QgsGammaCorrectionFilter *gammaCorrectionFilter() const;
%Docstring
Returns the raster's gamma correction filter.

.. seealso:: :py:func:`resampleFilter`

.. seealso:: :py:func:`brightnessFilter`

.. seealso:: :py:func:`hueSaturationFilter`

.. versionadded:: 3.16
%End

QgsHueSaturationFilter *hueSaturationFilter() const;
Expand All @@ -226,8 +209,6 @@ Returns the raster's hue/saturation filter.
.. seealso:: :py:func:`resampleFilter`

.. seealso:: :py:func:`brightnessFilter`

.. seealso:: :py:func:`gammaCorrectionFilter`
%End

void setResamplingStage( QgsRasterPipe::ResamplingStage stage );
Expand Down
8 changes: 0 additions & 8 deletions python/core/auto_generated/raster/qgsrasterpipe.sip.in
Expand Up @@ -31,7 +31,6 @@ Base class for processing modules.
ProjectorRole,
NullerRole,
HueSaturationRole,
GammaCorrectionRole
};

QgsRasterPipe();
Expand Down Expand Up @@ -103,13 +102,6 @@ Test if interface at index may be switched on/off
QgsRasterRenderer *renderer() const;
QgsRasterResampleFilter *resampleFilter() const;
QgsBrightnessContrastFilter *brightnessFilter() const;

QgsGammaCorrectionFilter *gammaCorrectionFilter() const;
%Docstring
Returns gamma correction filter pipe

.. versionadded:: 3.16
%End
QgsHueSaturationFilter *hueSaturationFilter() const;
QgsRasterProjector *projector() const;
QgsRasterNuller *nuller() const;
Expand Down
1 change: 0 additions & 1 deletion python/core/core_auto.sip
Expand Up @@ -468,7 +468,6 @@
%Include auto_generated/raster/qgscontrastenhancement.sip
%Include auto_generated/raster/qgscontrastenhancementfunction.sip
%Include auto_generated/raster/qgscubicrasterresampler.sip
%Include auto_generated/raster/qgsgammacorrectionfilter.sip
%Include auto_generated/raster/qgshillshaderenderer.sip
%Include auto_generated/raster/qgshuesaturationfilter.sip
%Include auto_generated/raster/qgslinearminmaxenhancement.sip
Expand Down
5 changes: 2 additions & 3 deletions src/app/qgisapp.cpp
Expand Up @@ -315,7 +315,6 @@ Q_GUI_EXPORT extern int qt_defaultDpiX();
#include "qgsrasterlayerproperties.h"
#include "qgsrasternuller.h"
#include "qgsbrightnesscontrastfilter.h"
#include "qgsgammacorrectionfilter.h"
#include "qgsrasterrenderer.h"
#include "qgsrasterlayersaveasdialog.h"
#include "qgsrasterprojector.h"
Expand Down Expand Up @@ -12257,8 +12256,8 @@ void QgisApp::adjustGamma( double delta )
return;
}

QgsGammaCorrectionFilter *gammaFilter = rasterLayer->gammaCorrectionFilter();
gammaFilter->setGamma( gammaFilter->gamma() + delta );
QgsBrightnessContrastFilter *brightnessFilter = rasterLayer->brightnessFilter();
brightnessFilter->setGamma( brightnessFilter->gamma() + delta );

rasterLayer->triggerRepaint();
}
Expand Down
2 changes: 1 addition & 1 deletion src/app/qgisapp.h
Expand Up @@ -2120,7 +2120,7 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
//! Do histogram stretch for singleband gray / multiband color rasters
void histogramStretch( bool visibleAreaOnly = false, QgsRasterMinMaxOrigin::Limits limits = QgsRasterMinMaxOrigin::MinMax );

//! Apply raster brightness
//! Apply raster brightness/contrast
void adjustBrightnessContrast( int delta, bool updateBrightness = true );

/**
Expand Down
2 changes: 0 additions & 2 deletions src/core/CMakeLists.txt
Expand Up @@ -572,7 +572,6 @@ SET(QGIS_CORE_SRCS
raster/qgsbilinearrasterresampler.cpp
raster/qgsbrightnesscontrastfilter.cpp
raster/qgscubicrasterresampler.cpp
raster/qgsgammacorrectionfilter.cpp
raster/qgshuesaturationfilter.cpp
raster/qgsmultibandcolorrenderer.cpp
raster/qgspalettedrasterrenderer.cpp
Expand Down Expand Up @@ -1307,7 +1306,6 @@ SET(QGIS_CORE_HDRS
raster/qgscontrastenhancement.h
raster/qgscontrastenhancementfunction.h
raster/qgscubicrasterresampler.h
raster/qgsgammacorrectionfilter.h
raster/qgshillshaderenderer.h
raster/qgshuesaturationfilter.h
raster/qgslinearminmaxenhancement.h
Expand Down
20 changes: 12 additions & 8 deletions src/core/raster/qgsbrightnesscontrastfilter.cpp
Expand Up @@ -32,6 +32,7 @@ QgsBrightnessContrastFilter *QgsBrightnessContrastFilter::clone() const
QgsBrightnessContrastFilter *filter = new QgsBrightnessContrastFilter( nullptr );
filter->setBrightness( mBrightness );
filter->setContrast( mContrast );
filter->setGamma( mGamma );
return filter;
}

Expand Down Expand Up @@ -122,9 +123,9 @@ QgsRasterBlock *QgsBrightnessContrastFilter::block( int bandNo, QgsRectangle co
return outputBlock.release();
}

if ( mBrightness == 0 && mContrast == 0 )
if ( mBrightness == 0 && mContrast == 0 && mGamma == 1.0 )
{
QgsDebugMsgLevel( QStringLiteral( "No brightness changes." ), 4 );
QgsDebugMsgLevel( QStringLiteral( "No brightness/contrast/gamma changes." ), 4 );
return inputBlock.release();
}

Expand All @@ -139,6 +140,7 @@ QgsRasterBlock *QgsBrightnessContrastFilter::block( int bandNo, QgsRectangle co

int r, g, b, alpha;
double f = std::pow( ( mContrast + 100 ) / 100.0, 2 );
double gammaCorrection = 1.0 / mGamma;

for ( qgssize i = 0; i < ( qgssize )width * height; i++ )
{
Expand All @@ -151,22 +153,22 @@ QgsRasterBlock *QgsBrightnessContrastFilter::block( int bandNo, QgsRectangle co
myColor = inputBlock->color( i );
alpha = qAlpha( myColor );

r = adjustColorComponent( qRed( myColor ), alpha, mBrightness, f );
g = adjustColorComponent( qGreen( myColor ), alpha, mBrightness, f );
b = adjustColorComponent( qBlue( myColor ), alpha, mBrightness, f );
r = adjustColorComponent( qRed( myColor ), alpha, mBrightness, f, gammaCorrection );
g = adjustColorComponent( qGreen( myColor ), alpha, mBrightness, f, gammaCorrection );
b = adjustColorComponent( qBlue( myColor ), alpha, mBrightness, f, gammaCorrection );

outputBlock->setColor( i, qRgba( r, g, b, alpha ) );
}

return outputBlock.release();
}

int QgsBrightnessContrastFilter::adjustColorComponent( int colorComponent, int alpha, int brightness, double contrastFactor ) const
int QgsBrightnessContrastFilter::adjustColorComponent( int colorComponent, int alpha, int brightness, double contrastFactor, double gammaCorrection ) const
{
if ( alpha == 255 )
{
// Opaque pixel, do simpler math
return qBound( 0, ( int )( ( ( ( ( ( colorComponent / 255.0 ) - 0.5 ) * contrastFactor ) + 0.5 ) * 255 ) + brightness ), 255 );
return qBound( 0, ( int )( 255 * std::pow( ( ( ( ( ( ( colorComponent / 255.0 ) - 0.5 ) * contrastFactor ) + 0.5 ) * 255 ) + brightness ) / 255.0, gammaCorrection ) ), 255 );
}
else if ( alpha == 0 )
{
Expand All @@ -181,7 +183,7 @@ int QgsBrightnessContrastFilter::adjustColorComponent( int colorComponent, int a
double adjustedColor = colorComponent / alphaFactor;

// Make sure to return a premultiplied color
return alphaFactor * qBound( 0., ( ( ( ( ( ( adjustedColor / 255.0 ) - 0.5 ) * contrastFactor ) + 0.5 ) * 255 ) + brightness ), 255. );
return alphaFactor * qBound( 0., std::pow( ( ( ( ( ( ( adjustedColor / 255.0 ) - 0.5 ) * contrastFactor ) + 0.5 ) * 255 ) + brightness ) / 255, gammaCorrection ), 255. );
}
}

Expand All @@ -196,6 +198,7 @@ void QgsBrightnessContrastFilter::writeXml( QDomDocument &doc, QDomElement &pare

filterElem.setAttribute( QStringLiteral( "brightness" ), QString::number( mBrightness ) );
filterElem.setAttribute( QStringLiteral( "contrast" ), QString::number( mContrast ) );
filterElem.setAttribute( QStringLiteral( "gamma" ), QString::number( mGamma ) );
parentElem.appendChild( filterElem );
}

Expand All @@ -208,4 +211,5 @@ void QgsBrightnessContrastFilter::readXml( const QDomElement &filterElem )

mBrightness = filterElem.attribute( QStringLiteral( "brightness" ), QStringLiteral( "0" ) ).toInt();
mContrast = filterElem.attribute( QStringLiteral( "contrast" ), QStringLiteral( "0" ) ).toInt();
mGamma = filterElem.attribute( QStringLiteral( "gamma" ), QStringLiteral( "1" ) ).toDouble();
}
15 changes: 11 additions & 4 deletions src/core/raster/qgsbrightnesscontrastfilter.h
Expand Up @@ -26,7 +26,7 @@ class QDomElement;

/**
* \ingroup core
* Brightness/contrast filter pipe for rasters.
* Brightness/contrast and gamma correction filter pipe for rasters.
*/
class CORE_EXPORT QgsBrightnessContrastFilter : public QgsRasterInterface
{
Expand All @@ -49,20 +49,27 @@ class CORE_EXPORT QgsBrightnessContrastFilter : public QgsRasterInterface
void setContrast( int contrast ) { mContrast = qBound( -100, contrast, 100 ); }
int contrast() const { return mContrast; }

void setGamma( double gamma ) { mGamma = qBound( 0.1, gamma, 10.0 ); }
double gamma() const { return mGamma; }

void writeXml( QDomDocument &doc, QDomElement &parentElem ) const override;

//! Sets base class members from xml. Usually called from create() methods of subclasses
void readXml( const QDomElement &filterElem ) override;

private:
//! Adjusts a color component by the specified brightness and contrast factor
int adjustColorComponent( int colorComponent, int alpha, int brightness, double contrastFactor ) const;
//! Adjusts a color component by the specified brightness, contrast factor and gamma correction
int adjustColorComponent( int colorComponent, int alpha, int brightness, double contrastFactor, double gammaCorrection ) const;

//! Current brightness coefficient value. Default: 0. Range: -255...255
int mBrightness = 0;

//! Current contrast coefficient value. Default: 0. Range: -100...100
double mContrast = 0;
int mContrast = 0;

//! Current gamma value. Default: 1. Range: 0.1…10.0
double mGamma = 1.0;

};

#endif // QGSBRIGHTNESSCONTRASTFILTER_H

0 comments on commit 0214b4f

Please sign in to comment.