@@ -147,17 +147,11 @@ QgsRasterBlock * QgsHueSaturationFilter::block( int bandNo, QgsRectangle const
147
147
148
148
// adjust image
149
149
QRgb myNoDataColor = qRgba ( 0 , 0 , 0 , 0 );
150
+ QRgb myRgb;
150
151
QColor myColor;
151
152
int h, s, l;
152
- int r, g, b;
153
-
154
- // Scale saturation value to [0-2], where 0 = desaturated
155
- double saturationScale = (( double ) mSaturation / 100 ) + 1 ;
156
-
157
- // Get hue, saturation for colorized color
158
- int colorizeH, colorizeS;
159
- colorizeH = mColorizeColor .hue ();
160
- colorizeS = mColorizeColor .saturation ();
153
+ int r, g, b, alpha;
154
+ double alphaFactor;
161
155
162
156
for ( size_t i = 0 ; i < ( size_t )width*height; i++ )
163
157
{
@@ -167,93 +161,172 @@ QgsRasterBlock * QgsHueSaturationFilter::block( int bandNo, QgsRectangle const
167
161
continue ;
168
162
}
169
163
170
- // Get hsv and rgb for color
171
- myColor = QColor ( inputBlock->color ( i ) );
172
- myColor.getHsl ( &h, &s, &l );
164
+ myRgb = inputBlock->color ( i );
165
+ myColor = QColor ( myRgb );
166
+
167
+ // Alpha must be taken from QRgb, since conversion from QRgb->QColor loses alpha
168
+ alpha = qAlpha ( myRgb );
169
+
170
+ // Get rgb for color
173
171
myColor.getRgb ( &r, &g, &b );
172
+ if ( alpha != 255 )
173
+ {
174
+ // Semi-transparent pixel. We need to adjust the colors since we are using QGis::ARGB32_Premultiplied
175
+ // and color values have been premultiplied by alpha
176
+ alphaFactor = alpha / 255 .;
177
+ r /= alphaFactor;
178
+ g /= alphaFactor;
179
+ b /= alphaFactor;
180
+ myColor = QColor::fromRgb ( r, g, b );
181
+ }
182
+
183
+ myColor.getHsl ( &h, &s, &l );
174
184
175
- switch ( mGrayscaleMode )
185
+ // Changing saturation?
186
+ if (( mGrayscaleMode != GrayscaleOff ) || ( mSaturationScale != 1 ) )
176
187
{
177
- case GrayscaleLightness:
178
- {
179
- // Lightness mode, set saturation to zero
180
- s = 0 ;
181
- myColor = QColor::fromHsl ( h, s, l );
182
- break ;
183
- }
184
- case GrayscaleLuminosity:
185
- {
186
- // Grayscale by weighted rgb components
187
- int luminosity = 0.21 * r + 0.72 * g + 0.07 * b;
188
- r = g = b = luminosity;
189
- myColor = QColor::fromRgb ( r, g, b );
190
- break ;
191
- }
192
- case GrayscaleAverage:
193
- {
194
- // Grayscale by average of rgb components
195
- int average = ( r + g + b ) / 3 ;
196
- r = g = b = average;
197
- myColor = QColor::fromRgb ( r, g, b );
198
- break ;
199
- }
200
- case GrayscaleOff:
201
- {
202
- // Not being made grayscale, do saturation change
203
- if ( saturationScale < 1 )
204
- {
205
- // Lowering the saturation. Use a simple linear relationship
206
- s = qMin (( int )( s * saturationScale ), 255 );
207
- }
208
- else
209
- {
210
- // Raising the saturation. Use a saturation curve to prevent
211
- // clipping at maximum saturation with ugly results.
212
- s = qMin (( int )( 255 . * ( 1 - pow ( 1 - (( double )s / 255 . ) , saturationScale * 2 ) ) ), 255 );
213
- }
214
- myColor = QColor::fromHsl ( h, s, l );
215
- break ;
216
- }
188
+ processSaturation ( r, g, b, h, s, l );
217
189
}
218
190
219
191
// Colorizing?
220
192
if ( mColorizeOn )
221
193
{
222
- // Update hsl, rgb values (these may have changed with saturation/grayscale adjustments)
223
- myColor.getHsl ( &h, &s, &l );
194
+ processColorization ( r, g, b, h, s, l );
195
+ }
196
+
197
+ // Convert back to rgb
198
+ if ( alpha != 255 )
199
+ {
200
+ // Transparent pixel, need to premultiply color components
201
+ r *= alphaFactor;
202
+ g *= alphaFactor;
203
+ b *= alphaFactor;
204
+ }
205
+
206
+ outputBlock->setColor ( i, qRgba ( r, g, b, alpha ) );
207
+ }
208
+
209
+ delete inputBlock;
210
+ return outputBlock;
211
+ }
212
+
213
+ // Process a colorization and update resultant HSL & RGB values
214
+ void QgsHueSaturationFilter::processColorization ( int &r, int &g, int &b, int &h, int &s, int &l )
215
+ {
216
+ QColor myColor;
217
+
218
+ // Overwrite hue and saturation with values from colorize color
219
+ h = mColorizeH ;
220
+ s = mColorizeS ;
221
+
222
+
223
+ QColor colorizedColor = QColor::fromHsl ( h, s, l );
224
+
225
+ if ( mColorizeStrength == 100 )
226
+ {
227
+ // Full strength
228
+ myColor = colorizedColor;
229
+
230
+ // RGB may have changed, update them
231
+ myColor.getRgb ( &r, &g, &b );
232
+ }
233
+ else
234
+ {
235
+ // Get rgb for colorized color
236
+ int colorizedR, colorizedG, colorizedB;
237
+ colorizedColor.getRgb ( &colorizedR, &colorizedG, &colorizedB );
238
+
239
+ // Now, linearly scale by colorize strength
240
+ double p = ( double ) mColorizeStrength / 100 .;
241
+ r = p * colorizedR + ( 1 - p ) * r;
242
+ g = p * colorizedG + ( 1 - p ) * g;
243
+ b = p * colorizedB + ( 1 - p ) * b;
244
+
245
+ // RGB changed, so update HSL values
246
+ myColor = QColor::fromRgb ( r, g, b );
247
+ myColor.getHsl ( &h, &s, &l );
248
+ }
249
+ }
250
+
251
+ // Process a change in saturation and update resultant HSL & RGB values
252
+ void QgsHueSaturationFilter::processSaturation ( int &r, int &g, int &b, int &h, int &s, int &l )
253
+ {
254
+
255
+ QColor myColor;
256
+
257
+ // Are we converting layer to grayscale?
258
+ switch ( mGrayscaleMode )
259
+ {
260
+ case GrayscaleLightness:
261
+ {
262
+ // Lightness mode, set saturation to zero
263
+ s = 0 ;
264
+
265
+ // Saturation changed, so update rgb values
266
+ myColor = QColor::fromHsl ( h, s, l );
224
267
myColor.getRgb ( &r, &g, &b );
268
+ return ;
269
+ }
270
+ case GrayscaleLuminosity:
271
+ {
272
+ // Grayscale by weighted rgb components
273
+ int luminosity = 0.21 * r + 0.72 * g + 0.07 * b;
274
+ r = g = b = luminosity;
225
275
226
- // Overwrite hue and saturation with values from colorize color
227
- h = colorizeH;
228
- s = colorizeS;
229
- QColor colorizedColor = QColor::fromHsl ( h, s, l );
276
+ // RGB changed, so update HSL values
277
+ myColor = QColor::fromRgb ( r, g, b );
278
+ myColor.getHsl ( &h, &s, &l );
279
+ return ;
280
+ }
281
+ case GrayscaleAverage:
282
+ {
283
+ // Grayscale by average of rgb components
284
+ int average = ( r + g + b ) / 3 ;
285
+ r = g = b = average;
230
286
231
- if ( mColorizeStrength == 100 )
287
+ // RGB changed, so update HSL values
288
+ myColor = QColor::fromRgb ( r, g, b );
289
+ myColor.getHsl ( &h, &s, &l );
290
+ return ;
291
+ }
292
+ case GrayscaleOff:
293
+ {
294
+ // Not being made grayscale, do saturation change
295
+ if ( mSaturationScale < 1 )
232
296
{
233
- // Full strength
234
- myColor = colorizedColor ;
297
+ // Lowering the saturation. Use a simple linear relationship
298
+ s = qMin (( int )( s * mSaturationScale ), 255 ) ;
235
299
}
236
300
else
237
301
{
238
- // Get rgb for colorized color
239
- int colorizedR, colorizedG, colorizedB;
240
- colorizedColor.getRgb ( &colorizedR, &colorizedG, &colorizedB );
241
-
242
- // Now, linearly scale by colorize strength
243
- double p = ( double ) mColorizeStrength / 100 .;
244
- r = p * colorizedR + ( 1 - p ) * r;
245
- g = p * colorizedG + ( 1 - p ) * g;
246
- b = p * colorizedB + ( 1 - p ) * b;
247
- myColor = QColor::fromRgb ( r, g, b );
302
+ // Raising the saturation. Use a saturation curve to prevent
303
+ // clipping at maximum saturation with ugly results.
304
+ s = qMin (( int )( 255 . * ( 1 - pow ( 1 - ( s / 255 . ) , mSaturationScale * 2 ) ) ), 255 );
248
305
}
249
- }
250
306
251
- // Convert back to rgb
252
- outputBlock->setColor ( i, myColor.rgb () );
307
+ // Saturation changed, so update rgb values
308
+ myColor = QColor::fromHsl ( h, s, l );
309
+ myColor.getRgb ( &r, &g, &b );
310
+ return ;
311
+ }
253
312
}
313
+ }
254
314
255
- delete inputBlock;
256
- return outputBlock;
315
+ void QgsHueSaturationFilter::setSaturation ( int saturation )
316
+ {
317
+ mSaturation = qBound ( -100 , saturation, 100 );
318
+
319
+ // Scale saturation value to [0-2], where 0 = desaturated
320
+ mSaturationScale = (( double ) mSaturation / 100 ) + 1 ;
321
+ }
322
+
323
+ void QgsHueSaturationFilter::setColorizeColor ( QColor colorizeColor )
324
+ {
325
+ mColorizeColor = colorizeColor;
326
+
327
+ // Get hue, saturation for colorized color
328
+ mColorizeH = mColorizeColor .hue ();
329
+ mColorizeS = mColorizeColor .saturation ();
257
330
}
258
331
259
332
void QgsHueSaturationFilter::writeXML ( QDomDocument& doc, QDomElement& parentElem )
@@ -283,14 +356,14 @@ void QgsHueSaturationFilter::readXML( const QDomElement& filterElem )
283
356
return ;
284
357
}
285
358
286
- mSaturation = filterElem.attribute ( " saturation" , " 0" ).toInt ();
359
+ setSaturation ( filterElem.attribute ( " saturation" , " 0" ).toInt () );
287
360
mGrayscaleMode = ( QgsHueSaturationFilter::GrayscaleMode )filterElem.attribute ( " grayscaleMode" , " 0" ).toInt ();
288
361
289
362
mColorizeOn = ( bool )filterElem.attribute ( " colorizeOn" , " 0" ).toInt ();
290
363
int mColorizeRed = filterElem.attribute ( " colorizeRed" , " 255" ).toInt ();
291
364
int mColorizeGreen = filterElem.attribute ( " colorizeGreen" , " 0" ).toInt ();
292
365
int mColorizeBlue = filterElem.attribute ( " colorizeBlue" , " 0" ).toInt ();
293
- mColorizeColor = QColor::fromRgb ( mColorizeRed , mColorizeGreen , mColorizeBlue );
366
+ setColorizeColor ( QColor::fromRgb ( mColorizeRed , mColorizeGreen , mColorizeBlue ) );
294
367
mColorizeStrength = filterElem.attribute ( " colorizeStrength" , " 100" ).toInt ();
295
368
296
369
}
0 commit comments