~ubuntu-branches/ubuntu/wily/qgis/wily

« back to all changes in this revision

Viewing changes to src/core/raster/qgscolorrampshader.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Johan Van de Wauw
  • Date: 2010-07-11 20:23:24 UTC
  • mfrom: (3.1.4 squeeze)
  • Revision ID: james.westby@ubuntu.com-20100711202324-5ktghxa7hracohmr
Tags: 1.4.0+12730-3ubuntu1
* Merge from Debian unstable (LP: #540941).
* Fix compilation issues with QT 4.7
* Add build-depends on libqt4-webkit-dev 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* **************************************************************************
 
2
                qgscolorrampshader.cpp -  description
 
3
                       -------------------
 
4
begin                : Fri Dec 28 2007
 
5
copyright            : (C) 2007 by Peter J. Ersts
 
6
email                : ersts@amnh.org
 
7
 
 
8
This class is based off of code that was originally written by Marco Hugentobler and
 
9
originally part of the larger QgsRasterLayer class
 
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
#define DOUBLE_DIFF_THRESHOLD 0.0000001
 
21
 
 
22
#include "qgslogger.h"
 
23
 
 
24
#include "qgscolorrampshader.h"
 
25
 
 
26
#include <math.h>
 
27
 
 
28
QgsColorRampShader::QgsColorRampShader( double theMinimumValue, double theMaximumValue ) : QgsRasterShaderFunction( theMinimumValue, theMaximumValue )
 
29
{
 
30
  QgsDebugMsg( "called." );
 
31
  mMaximumColorCacheSize = 1024; //good starting value
 
32
  mCurrentColorRampItemIndex = 0;
 
33
}
 
34
 
 
35
QString QgsColorRampShader::colorRampTypeAsQString()
 
36
{
 
37
  switch ( mColorRampType )
 
38
  {
 
39
    case INTERPOLATED:
 
40
      return QString( "INTERPOLATED" );
 
41
      break;
 
42
    case DISCRETE:
 
43
      return QString( "DISCRETE" );
 
44
      break;
 
45
    case EXACT:
 
46
      return QString( "EXACT" );
 
47
      break;
 
48
  }
 
49
  return QString( "Unknown" );
 
50
}
 
51
 
 
52
bool QgsColorRampShader::discreteColor( double theValue, int* theReturnRedValue, int* theReturnGreenValue, int* theReturnBlueValue )
 
53
{
 
54
  int myColorRampItemCount = mColorRampItemList.count();
 
55
  if ( myColorRampItemCount <= 0 )
 
56
  {
 
57
    return false;
 
58
  }
 
59
 
 
60
  double myTinyDiff = 0.0;
 
61
  QgsColorRampShader::ColorRampItem myColorRampItem;
 
62
  while ( mCurrentColorRampItemIndex >= 0 && mCurrentColorRampItemIndex < myColorRampItemCount )
 
63
  {
 
64
    //Start searching from the last index - assumtion is that neighboring pixels tend to be similar values
 
65
    myColorRampItem = mColorRampItemList.value( mCurrentColorRampItemIndex );
 
66
    myTinyDiff = fabs( theValue - myColorRampItem.value );
 
67
    //If the previous entry is less, then search closer to the top of the list (assumes mColorRampItemList is sorted)
 
68
    if ( mCurrentColorRampItemIndex != 0 && theValue <= mColorRampItemList.at( mCurrentColorRampItemIndex - 1 ).value )
 
69
    {
 
70
      mCurrentColorRampItemIndex--;
 
71
    }
 
72
    else if ( theValue <= myColorRampItem.value || myTinyDiff <= DOUBLE_DIFF_THRESHOLD )
 
73
    {
 
74
      *theReturnRedValue = myColorRampItem.color.red();
 
75
      *theReturnGreenValue = myColorRampItem.color.green();
 
76
      *theReturnBlueValue = myColorRampItem.color.blue();
 
77
      //Cache the shaded value
 
78
      if ( mMaximumColorCacheSize >= mColorCache.size() )
 
79
      {
 
80
        mColorCache.insert( theValue, myColorRampItem.color );
 
81
      }
 
82
      return true;
 
83
    }
 
84
    //Search deeper into the color ramp list
 
85
    else
 
86
    {
 
87
      mCurrentColorRampItemIndex++;
 
88
    }
 
89
  }
 
90
 
 
91
  return false; // value not found
 
92
}
 
93
 
 
94
bool QgsColorRampShader::exactColor( double theValue, int* theReturnRedValue, int* theReturnGreenValue, int* theReturnBlueValue )
 
95
{
 
96
  int myColorRampItemCount = mColorRampItemList.count();
 
97
  if ( myColorRampItemCount <= 0 )
 
98
  {
 
99
    return false;
 
100
  }
 
101
 
 
102
  double myTinyDiff = 0.0;
 
103
  QgsColorRampShader::ColorRampItem myColorRampItem;
 
104
  while ( mCurrentColorRampItemIndex >= 0 && mCurrentColorRampItemIndex < myColorRampItemCount )
 
105
  {
 
106
    //Start searching from the last index - assumtion is that neighboring pixels tend to be similar values
 
107
    myColorRampItem = mColorRampItemList.value( mCurrentColorRampItemIndex );
 
108
    myTinyDiff = fabs( theValue - myColorRampItem.value );
 
109
    if ( theValue == myColorRampItem.value || myTinyDiff <= DOUBLE_DIFF_THRESHOLD )
 
110
    {
 
111
      *theReturnRedValue = myColorRampItem.color.red();
 
112
      *theReturnGreenValue = myColorRampItem.color.green();
 
113
      *theReturnBlueValue = myColorRampItem.color.blue();
 
114
      //Cache the shaded value
 
115
      if ( mMaximumColorCacheSize >= mColorCache.size() )
 
116
      {
 
117
        mColorCache.insert( theValue, myColorRampItem.color );
 
118
      }
 
119
      return true;
 
120
    }
 
121
    //pixel value sits between ramp entries so bail
 
122
    else if ( mCurrentColorRampItemIndex != myColorRampItemCount - 1 && theValue > myColorRampItem.value && theValue < mColorRampItemList.at( mCurrentColorRampItemIndex + 1 ).value )
 
123
    {
 
124
      return false;
 
125
    }
 
126
    //Search deeper into the color ramp list
 
127
    else if ( theValue > myColorRampItem.value )
 
128
    {
 
129
      mCurrentColorRampItemIndex++;
 
130
    }
 
131
    //Search back toward the beginning of the list
 
132
    else
 
133
    {
 
134
      mCurrentColorRampItemIndex--;
 
135
    }
 
136
  }
 
137
 
 
138
  return false; // value not found
 
139
}
 
140
 
 
141
bool QgsColorRampShader::interpolatedColor( double theValue, int* theReturnRedValue, int* theReturnGreenValue, int* theReturnBlueValue )
 
142
{
 
143
  int myColorRampItemCount = mColorRampItemList.count();
 
144
  if ( myColorRampItemCount <= 0 )
 
145
  {
 
146
    return false;
 
147
  }
 
148
 
 
149
  double myTinyDiff = 0.0;
 
150
  double myCurrentRampRange; //difference between two consecutive entry values
 
151
  double myOffsetInRange; //difference between the previous entry value and value
 
152
  QgsColorRampShader::ColorRampItem myColorRampItem;
 
153
  while ( mCurrentColorRampItemIndex >= 0 && mCurrentColorRampItemIndex < myColorRampItemCount )
 
154
  {
 
155
    //Start searching from the last index - assumtion is that neighboring pixels tend to be similar values
 
156
    myColorRampItem = mColorRampItemList.value( mCurrentColorRampItemIndex );
 
157
    myTinyDiff = fabs( theValue - myColorRampItem.value );
 
158
    //If the previous entry is less, then search closer to the top of the list (assumes mColorRampItemList is sorted)
 
159
    if ( mCurrentColorRampItemIndex != 0 && theValue <= mColorRampItemList.at( mCurrentColorRampItemIndex - 1 ).value )
 
160
    {
 
161
      mCurrentColorRampItemIndex--;
 
162
    }
 
163
    else if ( mCurrentColorRampItemIndex != 0 && ( theValue <= myColorRampItem.value || myTinyDiff <= DOUBLE_DIFF_THRESHOLD ) )
 
164
    {
 
165
      QgsColorRampShader::ColorRampItem myPreviousColorRampItem = mColorRampItemList.value( mCurrentColorRampItemIndex - 1 );
 
166
      myCurrentRampRange = myColorRampItem.value - myPreviousColorRampItem.value;
 
167
      myOffsetInRange = theValue - myPreviousColorRampItem.value;
 
168
 
 
169
      *theReturnRedValue = ( int )(( double ) myPreviousColorRampItem.color.red() + ((( double )( myColorRampItem.color.red() - myPreviousColorRampItem.color.red() ) / myCurrentRampRange ) * myOffsetInRange ) );
 
170
      *theReturnGreenValue = ( int )(( double ) myPreviousColorRampItem.color.green() + ((( double )( myColorRampItem.color.green() - myPreviousColorRampItem.color.green() ) / myCurrentRampRange ) * myOffsetInRange ) );
 
171
      *theReturnBlueValue = ( int )(( double ) myPreviousColorRampItem.color.blue() + ((( double )( myColorRampItem.color.blue() - myPreviousColorRampItem.color.blue() ) / myCurrentRampRange ) * myOffsetInRange ) );
 
172
      if ( mMaximumColorCacheSize >= mColorCache.size() )
 
173
      {
 
174
        QColor myNewColor( *theReturnRedValue, *theReturnGreenValue, *theReturnBlueValue );
 
175
        mColorCache.insert( theValue, myNewColor );
 
176
      }
 
177
      return true;
 
178
    }
 
179
    else if ( mCurrentColorRampItemIndex == 0 && theValue <= myColorRampItem.value )
 
180
    {
 
181
      QgsColorRampShader::ColorRampItem myPreviousColorRampItem = mColorRampItemList.value( mCurrentColorRampItemIndex - 1 );
 
182
      myCurrentRampRange = myColorRampItem.value - myPreviousColorRampItem.value;
 
183
      myOffsetInRange = theValue - myPreviousColorRampItem.value;
 
184
 
 
185
      *theReturnRedValue = myColorRampItem.color.red();
 
186
      *theReturnGreenValue = myColorRampItem.color.green();
 
187
      *theReturnBlueValue = myColorRampItem.color.blue();
 
188
      if ( mMaximumColorCacheSize >= mColorCache.size() )
 
189
      {
 
190
        QColor myNewColor( *theReturnRedValue, *theReturnGreenValue, *theReturnBlueValue );
 
191
        mColorCache.insert( theValue, myNewColor );
 
192
      }
 
193
      return true;
 
194
    }
 
195
    //Search deeper into the color ramp list
 
196
    else if ( theValue > myColorRampItem.value )
 
197
    {
 
198
      mCurrentColorRampItemIndex++;
 
199
    }
 
200
    else
 
201
    {
 
202
      return false;
 
203
    }
 
204
  }
 
205
 
 
206
  return false;
 
207
}
 
208
 
 
209
void QgsColorRampShader::setColorRampType( QgsColorRampShader::ColorRamp_TYPE theColorRampType )
 
210
{
 
211
  //When the ramp type changes we need to clear out the cache
 
212
  mColorCache.clear();
 
213
  mColorRampType = theColorRampType;
 
214
}
 
215
 
 
216
void QgsColorRampShader::setColorRampType( QString theType )
 
217
{
 
218
  //When the type of the ramp changes we need to clear out the cache
 
219
  mColorCache.clear();
 
220
  if ( theType == "INTERPOLATED" )
 
221
  {
 
222
    mColorRampType = INTERPOLATED;
 
223
  }
 
224
  else if ( theType == "DISCRETE" )
 
225
  {
 
226
    mColorRampType = DISCRETE;
 
227
  }
 
228
  else
 
229
  {
 
230
    mColorRampType = EXACT;
 
231
  }
 
232
}
 
233
 
 
234
bool QgsColorRampShader::shade( double theValue, int* theReturnRedValue, int* theReturnGreenValue, int* theReturnBlueValue )
 
235
{
 
236
 
 
237
  //Get the shaded value from the cache if it exists already
 
238
  QColor myColor = mColorCache.value( theValue );
 
239
  if ( myColor.isValid() )
 
240
  {
 
241
    *theReturnRedValue = myColor.red();
 
242
    *theReturnGreenValue = myColor.green();
 
243
    *theReturnBlueValue = myColor.blue();
 
244
    return true;
 
245
  }
 
246
 
 
247
  //pixel value not in cache so generate new value
 
248
 
 
249
  //Check to be sure mCurrentColorRampItemIndex is within the valid range.
 
250
  if ( mCurrentColorRampItemIndex < 0 )
 
251
  {
 
252
    mCurrentColorRampItemIndex = 0;
 
253
  }
 
254
  else if ( mCurrentColorRampItemIndex >= mColorRampItemList.size() )
 
255
  {
 
256
    mCurrentColorRampItemIndex = mColorRampItemList.size() - 1;
 
257
  }
 
258
 
 
259
  if ( QgsColorRampShader::EXACT == mColorRampType )
 
260
  {
 
261
    return exactColor( theValue, theReturnRedValue, theReturnGreenValue, theReturnBlueValue );
 
262
  }
 
263
  else if ( QgsColorRampShader::INTERPOLATED == mColorRampType )
 
264
  {
 
265
    return interpolatedColor( theValue, theReturnRedValue, theReturnGreenValue, theReturnBlueValue );
 
266
  }
 
267
 
 
268
  return discreteColor( theValue, theReturnRedValue, theReturnGreenValue, theReturnBlueValue );
 
269
}
 
270
 
 
271
bool QgsColorRampShader::shade( double theRedValue, double theGreenValue, double theBlueValue, int* theReturnRedValue, int* theReturnGreenValue, int* theReturnBlueValue )
 
272
{
 
273
  *theReturnRedValue = 0;
 
274
  *theReturnGreenValue = 0;
 
275
  *theReturnBlueValue = 0;
 
276
 
 
277
  return false;
 
278
}