LCOV - code coverage report
Current view: top level - core/raster - qgscontrastenhancement.cpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 0 211 0.0 %
Date: 2021-03-26 12:19:53 Functions: 0 0 -
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /* **************************************************************************
       2                 :            :                 qgscontrastenhancement.cpp -  description
       3                 :            :                        -------------------
       4                 :            : begin                : Mon Oct 22 2007
       5                 :            : copyright            : (C) 2007 by Peter J. Ersts
       6                 :            : email                : ersts@amnh.org
       7                 :            : 
       8                 :            : This class contains code that was originally part of the larger QgsRasterLayer
       9                 :            : class originally created circa 2004 by T.Sutton, Gary E.Sherman, Steve Halasz
      10                 :            : ****************************************************************************/
      11                 :            : 
      12                 :            : /* **************************************************************************
      13                 :            :  *                                                                         *
      14                 :            :  *   This program is free software; you can redistribute it and/or modify  *
      15                 :            :  *   it under the terms of the GNU General Public License as published by  *
      16                 :            :  *   the Free Software Foundation; either version 2 of the License, or     *
      17                 :            :  *   (at your option) any later version.                                   *
      18                 :            :  *                                                                         *
      19                 :            :  ***************************************************************************/
      20                 :            : 
      21                 :            : #include "qgslogger.h"
      22                 :            : 
      23                 :            : #include "qgscontrastenhancement.h"
      24                 :            : #include "qgscontrastenhancementfunction.h"
      25                 :            : #include "qgslinearminmaxenhancement.h"
      26                 :            : #include "qgslinearminmaxenhancementwithclip.h"
      27                 :            : #include "qgscliptominmaxenhancement.h"
      28                 :            : #include "qgsrasterblock.h"
      29                 :            : #include <QDomDocument>
      30                 :            : #include <QDomElement>
      31                 :            : 
      32                 :          0 : QgsContrastEnhancement::QgsContrastEnhancement( Qgis::DataType dataType )
      33                 :          0 :   : mMinimumValue( minimumValuePossible( dataType ) )
      34                 :          0 :   , mMaximumValue( maximumValuePossible( dataType ) )
      35                 :          0 :   , mRasterDataType( dataType )
      36                 :          0 :   , mRasterDataTypeRange( mMaximumValue - mMinimumValue )
      37                 :          0 :   , mLookupTableOffset( mMinimumValue * -1 )
      38                 :            : {
      39                 :          0 :   mContrastEnhancementFunction.reset( new QgsContrastEnhancementFunction( mRasterDataType, mMinimumValue, mMaximumValue ) );
      40                 :            : 
      41                 :            :   //If the data type is larger than 16-bit do not generate a lookup table
      42                 :          0 :   if ( mRasterDataTypeRange <= 65535.0 )
      43                 :            :   {
      44                 :          0 :     mLookupTable = new int[static_cast <int>( mRasterDataTypeRange + 1 )];
      45                 :          0 :   }
      46                 :          0 : }
      47                 :            : 
      48                 :          0 : QgsContrastEnhancement::QgsContrastEnhancement( const QgsContrastEnhancement &ce )
      49                 :          0 :   : mEnhancementDirty( true )
      50                 :          0 :   , mMinimumValue( ce.mMinimumValue )
      51                 :          0 :   , mMaximumValue( ce.mMaximumValue )
      52                 :          0 :   , mRasterDataType( ce.mRasterDataType )
      53                 :          0 :   , mRasterDataTypeRange( ce.mRasterDataTypeRange )
      54                 :            : {
      55                 :          0 :   mLookupTableOffset = minimumValuePossible( mRasterDataType ) * -1;
      56                 :            : 
      57                 :            :   // setContrastEnhancementAlgorithm sets also QgsContrastEnhancementFunction
      58                 :          0 :   setContrastEnhancementAlgorithm( ce.mContrastEnhancementAlgorithm, false );
      59                 :            : 
      60                 :            :   //If the data type is larger than 16-bit do not generate a lookup table
      61                 :          0 :   if ( mRasterDataTypeRange <= 65535.0 )
      62                 :            :   {
      63                 :          0 :     mLookupTable = new int[static_cast <int>( mRasterDataTypeRange + 1 )];
      64                 :          0 :   }
      65                 :          0 : }
      66                 :            : 
      67                 :          0 : QgsContrastEnhancement::~QgsContrastEnhancement()
      68                 :            : {
      69                 :          0 :   delete [] mLookupTable;
      70                 :          0 : }
      71                 :            : 
      72                 :          0 : int QgsContrastEnhancement::enhanceContrast( double value )
      73                 :            : {
      74                 :          0 :   if ( mEnhancementDirty )
      75                 :            :   {
      76                 :          0 :     generateLookupTable();
      77                 :          0 :   }
      78                 :            : 
      79                 :          0 :   if ( mLookupTable && NoEnhancement != mContrastEnhancementAlgorithm )
      80                 :            :   {
      81                 :          0 :     double shiftedValue = value + mLookupTableOffset;
      82                 :          0 :     if ( shiftedValue >= 0 && shiftedValue < mRasterDataTypeRange + 1 )
      83                 :          0 :       return mLookupTable[static_cast <int>( shiftedValue )];
      84                 :          0 :     return 0;
      85                 :            :   }
      86                 :            :   else
      87                 :            :   {
      88                 :            :     // Even if the contrast enhancement algorithms is set to NoEnhancement
      89                 :            :     // The input values will still have to be scaled for all data types
      90                 :            :     // greater than 1 byte.
      91                 :          0 :     return mContrastEnhancementFunction->enhance( value );
      92                 :            :   }
      93                 :          0 : }
      94                 :            : 
      95                 :          0 : bool QgsContrastEnhancement::generateLookupTable()
      96                 :            : {
      97                 :          0 :   mEnhancementDirty = false;
      98                 :            : 
      99                 :          0 :   if ( !mContrastEnhancementFunction )
     100                 :          0 :     return false;
     101                 :          0 :   if ( NoEnhancement == mContrastEnhancementAlgorithm )
     102                 :          0 :     return false;
     103                 :          0 :   if ( Qgis::Byte != mRasterDataType && Qgis::UInt16 != mRasterDataType && Qgis::Int16 != mRasterDataType )
     104                 :          0 :     return false;
     105                 :          0 :   if ( !mLookupTable )
     106                 :          0 :     return false;
     107                 :            : 
     108                 :          0 :   QgsDebugMsgLevel( QStringLiteral( "building lookup table" ), 4 );
     109                 :          0 :   QgsDebugMsgLevel( QStringLiteral( "***MinimumValue : %1" ).arg( mMinimumValue ), 4 );
     110                 :          0 :   QgsDebugMsgLevel( QStringLiteral( "***MaximumValue : %1" ).arg( mMaximumValue ), 4 );
     111                 :          0 :   QgsDebugMsgLevel( QStringLiteral( "***mLookupTableOffset : %1" ).arg( mLookupTableOffset ), 4 );
     112                 :          0 :   QgsDebugMsgLevel( QStringLiteral( "***mRasterDataTypeRange : %1" ).arg( mRasterDataTypeRange ), 4 );
     113                 :            : 
     114                 :          0 :   for ( int myIterator = 0; myIterator <= mRasterDataTypeRange; myIterator++ )
     115                 :            :   {
     116                 :          0 :     mLookupTable[myIterator] = mContrastEnhancementFunction->enhance( static_cast< double >( myIterator ) - mLookupTableOffset );
     117                 :          0 :   }
     118                 :            : 
     119                 :          0 :   return true;
     120                 :          0 : }
     121                 :            : 
     122                 :          0 : bool QgsContrastEnhancement::isValueInDisplayableRange( double value )
     123                 :            : {
     124                 :          0 :   if ( mContrastEnhancementFunction )
     125                 :            :   {
     126                 :          0 :     return mContrastEnhancementFunction->isValueInDisplayableRange( value );
     127                 :            :   }
     128                 :            : 
     129                 :          0 :   return false;
     130                 :          0 : }
     131                 :            : 
     132                 :          0 : void QgsContrastEnhancement::setContrastEnhancementAlgorithm( ContrastEnhancementAlgorithm algorithm, bool generateTable )
     133                 :            : {
     134                 :          0 :   switch ( algorithm )
     135                 :            :   {
     136                 :            :     case StretchToMinimumMaximum :
     137                 :          0 :       mContrastEnhancementFunction.reset( new QgsLinearMinMaxEnhancement( mRasterDataType, mMinimumValue, mMaximumValue ) );
     138                 :          0 :       break;
     139                 :            :     case StretchAndClipToMinimumMaximum :
     140                 :          0 :       mContrastEnhancementFunction.reset( new QgsLinearMinMaxEnhancementWithClip( mRasterDataType, mMinimumValue, mMaximumValue ) );
     141                 :          0 :       break;
     142                 :            :     case ClipToMinimumMaximum :
     143                 :          0 :       mContrastEnhancementFunction.reset( new QgsClipToMinMaxEnhancement( mRasterDataType, mMinimumValue, mMaximumValue ) );
     144                 :          0 :       break;
     145                 :            :     case UserDefinedEnhancement :
     146                 :            :       //Do nothing
     147                 :          0 :       break;
     148                 :            :     default:
     149                 :          0 :       mContrastEnhancementFunction.reset( new QgsContrastEnhancementFunction( mRasterDataType, mMinimumValue, mMaximumValue ) );
     150                 :          0 :       break;
     151                 :            :   }
     152                 :            : 
     153                 :          0 :   mEnhancementDirty = true;
     154                 :          0 :   mContrastEnhancementAlgorithm = algorithm;
     155                 :            : 
     156                 :          0 :   if ( generateTable )
     157                 :            :   {
     158                 :          0 :     generateLookupTable();
     159                 :          0 :   }
     160                 :          0 : }
     161                 :            : 
     162                 :          0 : void QgsContrastEnhancement::setContrastEnhancementFunction( QgsContrastEnhancementFunction *function )
     163                 :            : {
     164                 :          0 :   QgsDebugMsgLevel( QStringLiteral( "called" ), 4 );
     165                 :            : 
     166                 :          0 :   if ( function )
     167                 :            :   {
     168                 :          0 :     mContrastEnhancementFunction.reset( function );
     169                 :          0 :     mContrastEnhancementAlgorithm = UserDefinedEnhancement;
     170                 :          0 :     generateLookupTable();
     171                 :          0 :   }
     172                 :          0 : }
     173                 :            : 
     174                 :          0 : void QgsContrastEnhancement::setMaximumValue( double value, bool generateTable )
     175                 :            : {
     176                 :          0 :   QgsDebugMsgLevel( "called value: " + QString::number( value ) + " generate lookup table: " + QString::number( static_cast< int >( generateTable ) ), 4 );
     177                 :            : 
     178                 :          0 :   if ( value > maximumValuePossible( mRasterDataType ) )
     179                 :            :   {
     180                 :          0 :     mMaximumValue = maximumValuePossible( mRasterDataType );
     181                 :          0 :   }
     182                 :            :   else
     183                 :            :   {
     184                 :          0 :     mMaximumValue = value;
     185                 :            :   }
     186                 :            : 
     187                 :          0 :   if ( mContrastEnhancementFunction )
     188                 :            :   {
     189                 :          0 :     mContrastEnhancementFunction->setMaximumValue( value );
     190                 :          0 :   }
     191                 :            : 
     192                 :          0 :   mEnhancementDirty = true;
     193                 :            : 
     194                 :          0 :   if ( generateTable )
     195                 :            :   {
     196                 :          0 :     generateLookupTable();
     197                 :          0 :   }
     198                 :          0 : }
     199                 :            : 
     200                 :          0 : void QgsContrastEnhancement::setMinimumValue( double value, bool generateTable )
     201                 :            : {
     202                 :          0 :   QgsDebugMsgLevel( "called value: " + QString::number( value ) + " generate lookup table: " + QString::number( static_cast< int >( generateTable ) ), 4 );
     203                 :            : 
     204                 :          0 :   if ( value < minimumValuePossible( mRasterDataType ) )
     205                 :            :   {
     206                 :          0 :     mMinimumValue = minimumValuePossible( mRasterDataType );
     207                 :          0 :   }
     208                 :            :   else
     209                 :            :   {
     210                 :          0 :     mMinimumValue = value;
     211                 :            :   }
     212                 :            : 
     213                 :          0 :   if ( mContrastEnhancementFunction )
     214                 :            :   {
     215                 :          0 :     mContrastEnhancementFunction->setMinimumValue( value );
     216                 :          0 :   }
     217                 :            : 
     218                 :          0 :   mEnhancementDirty = true;
     219                 :            : 
     220                 :          0 :   if ( generateTable )
     221                 :            :   {
     222                 :          0 :     generateLookupTable();
     223                 :          0 :   }
     224                 :          0 : }
     225                 :            : 
     226                 :          0 : void QgsContrastEnhancement::writeXml( QDomDocument &doc, QDomElement &parentElem ) const
     227                 :            : {
     228                 :            :   //minimum value
     229                 :          0 :   QDomElement minElem = doc.createElement( QStringLiteral( "minValue" ) );
     230                 :          0 :   QDomText minText = doc.createTextNode( QgsRasterBlock::printValue( mMinimumValue ) );
     231                 :          0 :   minElem.appendChild( minText );
     232                 :          0 :   parentElem.appendChild( minElem );
     233                 :            : 
     234                 :            :   //maximum value
     235                 :          0 :   QDomElement maxElem = doc.createElement( QStringLiteral( "maxValue" ) );
     236                 :          0 :   QDomText maxText = doc.createTextNode( QgsRasterBlock::printValue( mMaximumValue ) );
     237                 :          0 :   maxElem.appendChild( maxText );
     238                 :          0 :   parentElem.appendChild( maxElem );
     239                 :            : 
     240                 :            :   //algorithm
     241                 :          0 :   QDomElement algorithmElem = doc.createElement( QStringLiteral( "algorithm" ) );
     242                 :          0 :   QDomText algorithmText = doc.createTextNode( contrastEnhancementAlgorithmString( mContrastEnhancementAlgorithm ) );
     243                 :          0 :   algorithmElem.appendChild( algorithmText );
     244                 :          0 :   parentElem.appendChild( algorithmElem );
     245                 :          0 : }
     246                 :            : 
     247                 :          0 : void QgsContrastEnhancement::readXml( const QDomElement &elem )
     248                 :            : {
     249                 :          0 :   QDomElement minValueElem = elem.firstChildElement( QStringLiteral( "minValue" ) );
     250                 :          0 :   if ( !minValueElem.isNull() )
     251                 :            :   {
     252                 :          0 :     mMinimumValue = minValueElem.text().toDouble();
     253                 :          0 :   }
     254                 :          0 :   QDomElement maxValueElem = elem.firstChildElement( QStringLiteral( "maxValue" ) );
     255                 :          0 :   if ( !maxValueElem.isNull() )
     256                 :            :   {
     257                 :          0 :     mMaximumValue = maxValueElem.text().toDouble();
     258                 :          0 :   }
     259                 :          0 :   QDomElement algorithmElem = elem.firstChildElement( QStringLiteral( "algorithm" ) );
     260                 :          0 :   if ( !algorithmElem.isNull() )
     261                 :            :   {
     262                 :          0 :     QString algorithmString = algorithmElem.text();
     263                 :          0 :     ContrastEnhancementAlgorithm algorithm = NoEnhancement;
     264                 :            :     // old version ( < 19 Apr 2013) was using enum directly -> for backward compatibility
     265                 :          0 :     if ( algorithmString == QLatin1String( "0" ) )
     266                 :            :     {
     267                 :          0 :       algorithm = NoEnhancement;
     268                 :          0 :     }
     269                 :          0 :     else if ( algorithmString == QLatin1String( "1" ) )
     270                 :            :     {
     271                 :          0 :       algorithm = StretchToMinimumMaximum;
     272                 :          0 :     }
     273                 :          0 :     else if ( algorithmString == QLatin1String( "2" ) )
     274                 :            :     {
     275                 :          0 :       algorithm = StretchAndClipToMinimumMaximum;
     276                 :          0 :     }
     277                 :          0 :     else if ( algorithmString == QLatin1String( "3" ) )
     278                 :            :     {
     279                 :          0 :       algorithm = ClipToMinimumMaximum;
     280                 :          0 :     }
     281                 :          0 :     else if ( algorithmString == QLatin1String( "4" ) )
     282                 :            :     {
     283                 :          0 :       algorithm = UserDefinedEnhancement;
     284                 :          0 :     }
     285                 :            :     else
     286                 :            :     {
     287                 :          0 :       algorithm = contrastEnhancementAlgorithmFromString( algorithmString );
     288                 :            :     }
     289                 :            : 
     290                 :          0 :     setContrastEnhancementAlgorithm( algorithm );
     291                 :          0 :   }
     292                 :          0 : }
     293                 :            : 
     294                 :          0 : void QgsContrastEnhancement::toSld( QDomDocument &doc, QDomElement &element ) const
     295                 :            : {
     296                 :          0 :   if ( doc.isNull() || element.isNull() )
     297                 :          0 :     return;
     298                 :            : 
     299                 :          0 :   QString algName;
     300                 :          0 :   switch ( contrastEnhancementAlgorithm() )
     301                 :            :   {
     302                 :            :     case StretchToMinimumMaximum:
     303                 :          0 :       algName = QStringLiteral( "StretchToMinimumMaximum" );
     304                 :          0 :       break;
     305                 :            :     /* TODO: check if ClipToZero => StretchAndClipToMinimumMaximum
     306                 :            :      * because value outside min/max ar considered as NoData instead of 0 */
     307                 :            :     case StretchAndClipToMinimumMaximum:
     308                 :          0 :       algName = QStringLiteral( "ClipToMinimumMaximum" );
     309                 :          0 :       break;
     310                 :            :     case ClipToMinimumMaximum:
     311                 :          0 :       algName = QStringLiteral( "ClipToMinimumMaximum" );
     312                 :          0 :       break;
     313                 :            :     case NoEnhancement:
     314                 :          0 :       return;
     315                 :            :     case UserDefinedEnhancement:
     316                 :          0 :       algName = contrastEnhancementAlgorithmString( contrastEnhancementAlgorithm() );
     317                 :          0 :       QgsDebugMsg( QObject::tr( "No SLD1.0 conversion yet for stretch algorithm %1" ).arg( algName ) );
     318                 :          0 :       return;
     319                 :            :   }
     320                 :            : 
     321                 :            :   // Only <Normalize> is supported
     322                 :            :   // minValue and maxValue are that values as set depending on "Min /Max value settings"
     323                 :            :   // parameters
     324                 :          0 :   QDomElement normalizeElem = doc.createElement( QStringLiteral( "sld:Normalize" ) );
     325                 :          0 :   element.appendChild( normalizeElem );
     326                 :            : 
     327                 :          0 :   QDomElement vendorOptionAlgorithmElem = doc.createElement( QStringLiteral( "sld:VendorOption" ) );
     328                 :          0 :   vendorOptionAlgorithmElem.setAttribute( QStringLiteral( "name" ), QStringLiteral( "algorithm" ) );
     329                 :          0 :   vendorOptionAlgorithmElem.appendChild( doc.createTextNode( algName ) );
     330                 :          0 :   normalizeElem.appendChild( vendorOptionAlgorithmElem );
     331                 :            : 
     332                 :          0 :   QDomElement vendorOptionMinValueElem = doc.createElement( QStringLiteral( "sld:VendorOption" ) );
     333                 :          0 :   vendorOptionMinValueElem.setAttribute( QStringLiteral( "name" ), QStringLiteral( "minValue" ) );
     334                 :          0 :   vendorOptionMinValueElem.appendChild( doc.createTextNode( QString::number( minimumValue() ) ) );
     335                 :          0 :   normalizeElem.appendChild( vendorOptionMinValueElem );
     336                 :            : 
     337                 :          0 :   QDomElement vendorOptionMaxValueElem = doc.createElement( QStringLiteral( "sld:VendorOption" ) );
     338                 :          0 :   vendorOptionMaxValueElem.setAttribute( QStringLiteral( "name" ), QStringLiteral( "maxValue" ) );
     339                 :          0 :   vendorOptionMaxValueElem.appendChild( doc.createTextNode( QString::number( maximumValue() ) ) );
     340                 :          0 :   normalizeElem.appendChild( vendorOptionMaxValueElem );
     341                 :          0 : }
     342                 :            : 
     343                 :          0 : QString QgsContrastEnhancement::contrastEnhancementAlgorithmString( ContrastEnhancementAlgorithm algorithm )
     344                 :            : {
     345                 :          0 :   switch ( algorithm )
     346                 :            :   {
     347                 :            :     case NoEnhancement:
     348                 :          0 :       return QStringLiteral( "NoEnhancement" );
     349                 :            :     case StretchToMinimumMaximum:
     350                 :          0 :       return QStringLiteral( "StretchToMinimumMaximum" );
     351                 :            :     case StretchAndClipToMinimumMaximum:
     352                 :          0 :       return QStringLiteral( "StretchAndClipToMinimumMaximum" );
     353                 :            :     case ClipToMinimumMaximum:
     354                 :          0 :       return QStringLiteral( "ClipToMinimumMaximum" );
     355                 :            :     case UserDefinedEnhancement:
     356                 :          0 :       return QStringLiteral( "UserDefinedEnhancement" );
     357                 :            :   }
     358                 :          0 :   return QStringLiteral( "NoEnhancement" );
     359                 :          0 : }
     360                 :            : 
     361                 :          0 : QgsContrastEnhancement::ContrastEnhancementAlgorithm QgsContrastEnhancement::contrastEnhancementAlgorithmFromString( const QString &contrastEnhancementString )
     362                 :            : {
     363                 :          0 :   if ( contrastEnhancementString == QLatin1String( "StretchToMinimumMaximum" ) )
     364                 :            :   {
     365                 :          0 :     return StretchToMinimumMaximum;
     366                 :            :   }
     367                 :          0 :   else if ( contrastEnhancementString == QLatin1String( "StretchAndClipToMinimumMaximum" ) )
     368                 :            :   {
     369                 :          0 :     return StretchAndClipToMinimumMaximum;
     370                 :            :   }
     371                 :          0 :   else if ( contrastEnhancementString == QLatin1String( "ClipToMinimumMaximum" ) )
     372                 :            :   {
     373                 :          0 :     return ClipToMinimumMaximum;
     374                 :            :   }
     375                 :          0 :   else if ( contrastEnhancementString == QLatin1String( "UserDefinedEnhancement" ) )
     376                 :            :   {
     377                 :          0 :     return UserDefinedEnhancement;
     378                 :            :   }
     379                 :            :   else
     380                 :            :   {
     381                 :          0 :     return NoEnhancement;
     382                 :            :   }
     383                 :          0 : }

Generated by: LCOV version 1.14