@@ -25,32 +25,45 @@ originally part of the larger QgsRasterLayer class
25
25
QgsColorRampShader::QgsColorRampShader ( double theMinimumValue, double theMaximumValue ) : QgsRasterShaderFunction( theMinimumValue, theMaximumValue )
26
26
{
27
27
QgsDebugMsg ( " called." );
28
- mMaximumColorCacheSize = 256 ; // good starting value
28
+ mMaximumColorCacheSize = 1024 ; // good starting value
29
+ mCurrentColorRampItemIndex = 0 ;
29
30
}
30
31
31
32
bool QgsColorRampShader::generateShadedValue ( double theValue, int * theReturnRedValue, int * theReturnGreenValue, int * theReturnBlueValue )
32
33
{
33
- // Get the shaded from the cache if it exists already
34
+
35
+ // Get the shaded value from the cache if it exists already
34
36
QColor myColor = mColorCache .value (theValue);
35
- if ( myColor.isValid ())
37
+ if ( myColor.isValid () )
36
38
{
37
39
*theReturnRedValue = myColor.red ();
38
40
*theReturnGreenValue = myColor.green ();
39
41
*theReturnBlueValue = myColor.blue ();
40
42
return true ;
41
43
}
42
44
43
- // Else we have to generate the shaded value
44
- if ( QgsColorRampShader::INTERPOLATED == mColorRampType )
45
+ // pixel value not in cache so generate new value
46
+
47
+ // Check to be sure mCurrentColorRampItemIndex is within the valid range.
48
+ if ( mCurrentColorRampItemIndex < 0 )
45
49
{
46
- return getInterpolatedColor ( theValue, theReturnRedValue, theReturnGreenValue, theReturnBlueValue ) ;
50
+ mCurrentColorRampItemIndex = 0 ;
47
51
}
48
- else if ( QgsColorRampShader::DISCRETE == mColorRampType )
52
+ else if ( mCurrentColorRampItemIndex >= mColorRampItemList . size () )
49
53
{
50
- return getDiscreteColor ( theValue, theReturnRedValue, theReturnGreenValue, theReturnBlueValue ) ;
54
+ mCurrentColorRampItemIndex = mColorRampItemList . size () - 1 ;
51
55
}
52
-
53
- return getExactColor ( theValue, theReturnRedValue, theReturnGreenValue, theReturnBlueValue );
56
+
57
+ if ( QgsColorRampShader::EXACT == mColorRampType )
58
+ {
59
+ return getExactColor ( theValue, theReturnRedValue, theReturnGreenValue, theReturnBlueValue );
60
+ }
61
+ else if ( QgsColorRampShader::INTERPOLATED == mColorRampType )
62
+ {
63
+ return getInterpolatedColor ( theValue, theReturnRedValue, theReturnGreenValue, theReturnBlueValue );
64
+ }
65
+
66
+ return getDiscreteColor ( theValue, theReturnRedValue, theReturnGreenValue, theReturnBlueValue );
54
67
}
55
68
56
69
bool QgsColorRampShader::generateShadedValue ( double theRedValue, double theGreenValue, double theBlueValue, int * theReturnRedValue, int * theReturnGreenValue, int * theReturnBlueValue )
@@ -81,102 +94,167 @@ QString QgsColorRampShader::getColorRampTypeAsQString()
81
94
82
95
bool QgsColorRampShader::getDiscreteColor ( double theValue, int * theReturnRedValue, int * theReturnGreenValue, int * theReturnBlueValue )
83
96
{
84
- if ( mColorRampItemList .count () <= 0 )
97
+ int myColorRampItemCount = mColorRampItemList .count ();
98
+ if ( myColorRampItemCount <= 0 )
85
99
{
86
100
return false ;
87
101
}
88
- QList<QgsColorRampShader::ColorRampItem>::const_iterator it;
89
- QList<QgsColorRampShader::ColorRampItem>::const_iterator last_it = mColorRampItemList .begin ();
90
- double myCurrentRampValue;
91
- for ( it = mColorRampItemList .begin (); it != mColorRampItemList .end (); ++it )
102
+
103
+ QgsColorRampShader::ColorRampItem myColorRampItem;
104
+ while ( mCurrentColorRampItemIndex >= 0 && mCurrentColorRampItemIndex < myColorRampItemCount )
92
105
{
93
- myCurrentRampValue = it->value ;
94
- if ( theValue <= myCurrentRampValue )
106
+ // Start searching from the last index - assumtion is that neighboring pixels tend to be similar values
107
+ myColorRampItem = mColorRampItemList .value ( mCurrentColorRampItemIndex );
108
+ // If the previous entry is less, then search closer to the top of the list (assumes mColorRampItemList is sorted)
109
+ if ( mCurrentColorRampItemIndex != 0 && theValue <= mColorRampItemList .at ( mCurrentColorRampItemIndex - 1 ).value )
95
110
{
96
- *theReturnRedValue = it->color .red ();
97
- *theReturnGreenValue = it->color .green ();
98
- *theReturnBlueValue = it->color .blue ();
111
+ mCurrentColorRampItemIndex --;
112
+ }
113
+ else if ( theValue <= myColorRampItem.value )
114
+ {
115
+ *theReturnRedValue = myColorRampItem.color .red ();
116
+ *theReturnGreenValue = myColorRampItem.color .green ();
117
+ *theReturnBlueValue = myColorRampItem.color .blue ();
99
118
// Cache the shaded value
100
- if ( mMaximumColorCacheSize < = mColorCache .size ())
119
+ if ( mMaximumColorCacheSize > = mColorCache .size () )
101
120
{
102
- mColorCache .insert (theValue, it-> color );
121
+ mColorCache .insert ( theValue, myColorRampItem. color );
103
122
}
104
123
return true ;
105
124
}
125
+ // Search deeper into the color ramp list
126
+ else
127
+ {
128
+ mCurrentColorRampItemIndex ++;
129
+ }
106
130
}
107
-
131
+
108
132
return false ; // value not found
109
133
}
110
134
111
135
bool QgsColorRampShader::getExactColor ( double theValue, int * theReturnRedValue, int * theReturnGreenValue, int * theReturnBlueValue )
112
136
{
113
- if ( mColorRampItemList .count () <= 0 )
137
+ int myColorRampItemCount = mColorRampItemList .count ();
138
+ if ( myColorRampItemCount <= 0 )
114
139
{
115
140
return false ;
116
141
}
117
- QList<QgsColorRampShader::ColorRampItem>::const_iterator it;
118
- for ( it = mColorRampItemList .begin (); it != mColorRampItemList .end (); ++it )
142
+
143
+ QgsColorRampShader::ColorRampItem myColorRampItem;
144
+ while ( mCurrentColorRampItemIndex >= 0 && mCurrentColorRampItemIndex < myColorRampItemCount )
119
145
{
120
- if ( theValue == it->value )
146
+ // Start searching from the last index - assumtion is that neighboring pixels tend to be similar values
147
+ myColorRampItem = mColorRampItemList .value ( mCurrentColorRampItemIndex );
148
+ if ( theValue == myColorRampItem.value )
121
149
{
122
- *theReturnRedValue = it-> color .red ();
123
- *theReturnGreenValue = it-> color .green ();
124
- *theReturnBlueValue = it-> color .blue ();
150
+ *theReturnRedValue = myColorRampItem. color .red ();
151
+ *theReturnGreenValue = myColorRampItem. color .green ();
152
+ *theReturnBlueValue = myColorRampItem. color .blue ();
125
153
// Cache the shaded value
126
- if ( mMaximumColorCacheSize < = mColorCache .size ())
154
+ if ( mMaximumColorCacheSize > = mColorCache .size () )
127
155
{
128
- mColorCache .insert (theValue, it-> color );
156
+ mColorCache .insert ( theValue, myColorRampItem. color );
129
157
}
130
158
return true ;
131
159
}
160
+ // pixel value sits between ramp entries so bail
161
+ else if ( mCurrentColorRampItemIndex != myColorRampItemCount - 1 && theValue > myColorRampItem.value && theValue < mColorRampItemList .at ( mCurrentColorRampItemIndex + 1 ).value )
162
+ {
163
+ return false ;
164
+ }
165
+ // Search deeper into the color ramp list
166
+ else if ( theValue > myColorRampItem.value )
167
+ {
168
+ mCurrentColorRampItemIndex ++;
169
+ }
170
+ // Search back toward the begining of the list
171
+ else
172
+ {
173
+ mCurrentColorRampItemIndex --;
174
+ }
132
175
}
133
176
134
177
return false ; // value not found
135
178
}
136
179
137
180
bool QgsColorRampShader::getInterpolatedColor ( double theValue, int * theReturnRedValue, int * theReturnGreenValue, int * theReturnBlueValue )
138
181
{
139
- if ( mColorRampItemList .count () <= 0 )
182
+
183
+ int myColorRampItemCount = mColorRampItemList .count ();
184
+ if ( myColorRampItemCount <= 0 )
140
185
{
141
186
return false ;
142
187
}
143
- QList<QgsColorRampShader::ColorRampItem>::const_iterator it;
144
- QList<QgsColorRampShader::ColorRampItem>::const_iterator last_it = mColorRampItemList .end ();
145
- double myCurrentRampValue;
188
+
146
189
double myCurrentRampRange; // difference between two consecutive entry values
147
- double myDiffTheValueLastRampValue; // difference between value and last entry value
148
- double myDiffCurrentRampValueTheValue; // difference between this entry value and value
149
-
150
- for ( it = mColorRampItemList .begin (); it != mColorRampItemList .end (); ++it )
190
+ double myOffsetInRange; // difference between the previous entry value and value
191
+ QgsColorRampShader::ColorRampItem myColorRampItem;
192
+ while ( mCurrentColorRampItemIndex >= 0 && mCurrentColorRampItemIndex < myColorRampItemCount )
151
193
{
152
- myCurrentRampValue = it->value ;
153
- if ( theValue <= myCurrentRampValue )
194
+ // Start searching from the last index - assumtion is that neighboring pixels tend to be similar values
195
+ myColorRampItem = mColorRampItemList .value ( mCurrentColorRampItemIndex );
196
+ // If the previous entry is less, then search closer to the top of the list (assumes mColorRampItemList is sorted)
197
+ if ( mCurrentColorRampItemIndex != 0 && theValue <= mColorRampItemList .at ( mCurrentColorRampItemIndex - 1 ).value )
198
+ {
199
+ mCurrentColorRampItemIndex --;
200
+ }
201
+ else if ( mCurrentColorRampItemIndex != 0 && theValue <= myColorRampItem.value )
202
+ {
203
+ QgsColorRampShader::ColorRampItem myPreviousColorRampItem = mColorRampItemList .value ( mCurrentColorRampItemIndex - 1 );
204
+ myCurrentRampRange = myColorRampItem.value - myPreviousColorRampItem.value ;
205
+ myOffsetInRange = theValue - myPreviousColorRampItem.value ;
206
+
207
+ *theReturnRedValue = ( int )(( double ) myPreviousColorRampItem.color .red () + ((( double ) (myColorRampItem.color .red () - myPreviousColorRampItem.color .red ()) / myCurrentRampRange ) * myOffsetInRange ));
208
+ *theReturnGreenValue = ( int )(( double ) myPreviousColorRampItem.color .green () + ((( double ) (myColorRampItem.color .green () - myPreviousColorRampItem.color .green ()) / myCurrentRampRange) * myOffsetInRange ));
209
+ *theReturnBlueValue = ( int )(( double ) myPreviousColorRampItem.color .blue () + ((( double ) (myColorRampItem.color .blue () - myPreviousColorRampItem.color .blue ()) / myCurrentRampRange ) * myOffsetInRange));
210
+ if ( mMaximumColorCacheSize >= mColorCache .size () )
211
+ {
212
+ QColor myNewColor ( *theReturnRedValue, *theReturnGreenValue, *theReturnBlueValue );
213
+ mColorCache .insert ( theValue, myNewColor );
214
+ }
215
+ return true ;
216
+ }
217
+ else if ( mCurrentColorRampItemIndex == 0 && theValue <= myColorRampItem.value )
154
218
{
155
- if ( last_it != mColorRampItemList .end () )
219
+ QgsColorRampShader::ColorRampItem myPreviousColorRampItem = mColorRampItemList .value ( mCurrentColorRampItemIndex - 1 );
220
+ myCurrentRampRange = myColorRampItem.value - myPreviousColorRampItem.value ;
221
+ myOffsetInRange = theValue - myPreviousColorRampItem.value ;
222
+
223
+ *theReturnRedValue = myColorRampItem.color .red ();
224
+ *theReturnGreenValue = myColorRampItem.color .green ();
225
+ *theReturnBlueValue = myColorRampItem.color .blue ();
226
+ if ( mMaximumColorCacheSize >= mColorCache .size () )
156
227
{
157
- myCurrentRampRange = myCurrentRampValue - last_it->value ;
158
- myDiffTheValueLastRampValue = theValue - last_it->value ;
159
- myDiffCurrentRampValueTheValue = myCurrentRampValue - theValue;
160
-
161
- *theReturnRedValue = ( int )(( it->color .red () * myDiffTheValueLastRampValue + last_it->color .red () * myDiffCurrentRampValueTheValue ) / myCurrentRampRange );
162
- *theReturnGreenValue = ( int )(( it->color .green () * myDiffTheValueLastRampValue + last_it->color .green () * myDiffCurrentRampValueTheValue ) / myCurrentRampRange );
163
- *theReturnBlueValue = ( int )(( it->color .blue () * myDiffTheValueLastRampValue + last_it->color .blue () * myDiffCurrentRampValueTheValue ) / myCurrentRampRange );
164
- // Cache the shaded value
165
- if (mMaximumColorCacheSize <= mColorCache .size ())
166
- {
167
- mColorCache .insert (theValue, it->color );
168
- }
169
- return true ;
228
+ QColor myNewColor ( *theReturnRedValue, *theReturnGreenValue, *theReturnBlueValue );
229
+ mColorCache .insert ( theValue, myNewColor );
170
230
}
231
+ return true ;
232
+ }
233
+ // Search deeper into the color ramp list
234
+ else if ( theValue > myColorRampItem.value )
235
+ {
236
+ mCurrentColorRampItemIndex ++;
237
+ }
238
+ else
239
+ {
240
+ return false ;
171
241
}
172
- last_it = it;
173
242
}
174
243
175
244
return false ;
176
245
}
177
246
247
+ void QgsColorRampShader::setColorRampType ( QgsColorRampShader::COLOR_RAMP_TYPE theColorRampType )
248
+ {
249
+ // When the ramp type changes we need to clear out the cache
250
+ mColorCache .clear ();
251
+ mColorRampType = theColorRampType;
252
+ }
253
+
178
254
void QgsColorRampShader::setColorRampType ( QString theType )
179
255
{
256
+ // When the type of the ramp changes we need to clear out the cache
257
+ mColorCache .clear ();
180
258
if ( theType == " INTERPOLATED" )
181
259
{
182
260
mColorRampType = INTERPOLATED;
0 commit comments