|
QGIS API Documentation
master-59fd5e0
|
00001 /*************************************************************************** 00002 qgsbrightnesscontrastfilter.cpp 00003 --------------------- 00004 begin : February 2013 00005 copyright : (C) 2013 by Alexander Bruy 00006 email : alexander dot bruy at gmail dot com 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * * 00011 * This program is free software; you can redistribute it and/or modify * 00012 * it under the terms of the GNU General Public License as published by * 00013 * the Free Software Foundation; either version 2 of the License, or * 00014 * (at your option) any later version. * 00015 * * 00016 ***************************************************************************/ 00017 00018 #include "qgsrasterdataprovider.h" 00019 #include "qgsbrightnesscontrastfilter.h" 00020 00021 #include <qmath.h> 00022 #include <QDomDocument> 00023 #include <QDomElement> 00024 00025 QgsBrightnessContrastFilter::QgsBrightnessContrastFilter( QgsRasterInterface* input ) 00026 : QgsRasterInterface( input ), 00027 mBrightness( 0 ), 00028 mContrast( 0 ) 00029 { 00030 } 00031 00032 QgsBrightnessContrastFilter::~QgsBrightnessContrastFilter() 00033 { 00034 } 00035 00036 QgsRasterInterface * QgsBrightnessContrastFilter::clone() const 00037 { 00038 QgsDebugMsg( "Entered" ); 00039 QgsBrightnessContrastFilter * filter = new QgsBrightnessContrastFilter( 0 ); 00040 filter->setBrightness( mBrightness ); 00041 filter->setContrast( mContrast ); 00042 return filter; 00043 } 00044 00045 int QgsBrightnessContrastFilter::bandCount() const 00046 { 00047 if ( mOn ) 00048 { 00049 return 1; 00050 } 00051 00052 if ( mInput ) 00053 { 00054 return mInput->bandCount(); 00055 } 00056 00057 return 0; 00058 } 00059 00060 QGis::DataType QgsBrightnessContrastFilter::dataType( int bandNo ) const 00061 { 00062 if ( mOn ) 00063 { 00064 return QGis::ARGB32_Premultiplied; 00065 } 00066 00067 if ( mInput ) 00068 { 00069 return mInput->dataType( bandNo ); 00070 } 00071 00072 return QGis::UnknownDataType; 00073 } 00074 00075 bool QgsBrightnessContrastFilter::setInput( QgsRasterInterface* input ) 00076 { 00077 QgsDebugMsg( "Entered" ); 00078 00079 // Brightness filter can only work with single band ARGB32_Premultiplied 00080 if ( !input ) 00081 { 00082 QgsDebugMsg( "No input" ); 00083 return false; 00084 } 00085 00086 if ( !mOn ) 00087 { 00088 // In off mode we can connect to anything 00089 QgsDebugMsg( "OK" ); 00090 mInput = input; 00091 return true; 00092 } 00093 00094 if ( input->bandCount() < 1 ) 00095 { 00096 QgsDebugMsg( "No input band" ); 00097 return false; 00098 } 00099 00100 if ( input->dataType( 1 ) != QGis::ARGB32_Premultiplied && 00101 input->dataType( 1 ) != QGis::ARGB32 ) 00102 { 00103 QgsDebugMsg( "Unknown input data type" ); 00104 return false; 00105 } 00106 00107 mInput = input; 00108 QgsDebugMsg( "OK" ); 00109 return true; 00110 } 00111 00112 QgsRasterBlock * QgsBrightnessContrastFilter::block( int bandNo, QgsRectangle const & extent, int width, int height ) 00113 { 00114 Q_UNUSED( bandNo ); 00115 QgsDebugMsg( QString( "width = %1 height = %2 extent = %3" ).arg( width ).arg( height ).arg( extent.toString() ) ); 00116 00117 QgsRasterBlock *outputBlock = new QgsRasterBlock(); 00118 if ( !mInput ) 00119 { 00120 return outputBlock; 00121 } 00122 00123 // At this moment we know that we read rendered image 00124 int bandNumber = 1; 00125 QgsRasterBlock *inputBlock = mInput->block( bandNumber, extent, width, height ); 00126 if ( !inputBlock || inputBlock->isEmpty() ) 00127 { 00128 QgsDebugMsg( "No raster data!" ); 00129 delete inputBlock; 00130 return outputBlock; 00131 } 00132 00133 if ( mBrightness == 0 && mContrast == 0 ) 00134 { 00135 QgsDebugMsg( "No brightness changes." ); 00136 delete outputBlock; 00137 return inputBlock; 00138 } 00139 00140 if ( !outputBlock->reset( QGis::ARGB32_Premultiplied, width, height ) ) 00141 { 00142 delete inputBlock; 00143 return outputBlock; 00144 } 00145 00146 // adjust image 00147 QRgb myNoDataColor = qRgba( 0, 0, 0, 0 ); 00148 QRgb myColor; 00149 00150 int r, g, b, alpha; 00151 double f = qPow(( mContrast + 100 ) / 100.0, 2 ); 00152 00153 for ( size_t i = 0; i < ( size_t )width*height; i++ ) 00154 { 00155 if ( inputBlock->color( i ) == myNoDataColor ) 00156 { 00157 outputBlock->setColor( i, myNoDataColor ); 00158 continue; 00159 } 00160 00161 myColor = inputBlock->color( i ); 00162 alpha = qAlpha( myColor ); 00163 00164 r = adjustColorComponent( qRed( myColor ), alpha, mBrightness, f ); 00165 g = adjustColorComponent( qGreen( myColor ), alpha, mBrightness, f ); 00166 b = adjustColorComponent( qBlue( myColor ), alpha, mBrightness, f ); 00167 00168 outputBlock->setColor( i, qRgba( r, g, b, alpha ) ); 00169 } 00170 00171 delete inputBlock; 00172 return outputBlock; 00173 } 00174 00175 int QgsBrightnessContrastFilter::adjustColorComponent( int colorComponent, int alpha, int brightness, double contrastFactor ) const 00176 { 00177 if ( alpha == 255 ) 00178 { 00179 // Opaque pixel, do simpler math 00180 return qBound( 0, ( int )(((((( colorComponent / 255.0 ) - 0.5 ) * contrastFactor ) + 0.5 ) * 255 ) + brightness ), 255 ); 00181 } 00182 else 00183 { 00184 // Semi-transparent pixel. We need to adjust the math since we are using QGis::ARGB32_Premultiplied 00185 // and color values have been premultiplied by alpha 00186 double alphaFactor = alpha / 255.; 00187 double adjustedColor = colorComponent / alphaFactor; 00188 00189 // Make sure to return a premultiplied color 00190 return alphaFactor * qBound( 0., (((((( adjustedColor / 255.0 ) - 0.5 ) * contrastFactor ) + 0.5 ) * 255 ) + brightness ), 255. ); 00191 } 00192 } 00193 00194 void QgsBrightnessContrastFilter::writeXML( QDomDocument& doc, QDomElement& parentElem ) const 00195 { 00196 if ( parentElem.isNull() ) 00197 { 00198 return; 00199 } 00200 00201 QDomElement filterElem = doc.createElement( "brightnesscontrast" ); 00202 00203 filterElem.setAttribute( "brightness", QString::number( mBrightness ) ); 00204 filterElem.setAttribute( "contrast", QString::number( mContrast ) ); 00205 parentElem.appendChild( filterElem ); 00206 } 00207 00208 void QgsBrightnessContrastFilter::readXML( const QDomElement& filterElem ) 00209 { 00210 if ( filterElem.isNull() ) 00211 { 00212 return; 00213 } 00214 00215 mBrightness = filterElem.attribute( "brightness", "0" ).toInt(); 00216 mContrast = filterElem.attribute( "contrast", "0" ).toInt(); 00217 }