22#include <QDomDocument>
26using namespace Qt::StringLiterals;
30 , mColorizeColor( QColor::fromRgb( 255, 128, 128 ) )
55 return mInput->bandCount();
70 return mInput->dataType( bandNo );
95 if (
input->bandCount() < 1 )
115 QgsDebugMsgLevel( u
"width = %1 height = %2 extent = %3"_s.arg( width ).arg( height ).arg(
extent.toString() ), 4 );
124 std::unique_ptr< QgsRasterBlock > inputBlock(
mInput->block( bandNumber,
extent, width, height, feedback ) );
125 if ( !inputBlock || inputBlock->isEmpty() )
131 if ( !mInvertColors && mSaturation == 0 && mGrayscaleMode ==
GrayscaleOff && !mColorizeOn )
134 return inputBlock.release();
137 auto outputBlock = std::make_unique<QgsRasterBlock>();
145 const QRgb myNoDataColor = qRgba( 0, 0, 0, 0 );
148 double alphaFactor = 1.0;
150 const QRgb *inputColorData = inputBlock->colorData();
151 const int imageHeight = inputBlock->image().height();
152 const int imageWidth = inputBlock->image().width();
154 QRgb *outputColorData = outputBlock->colorData();
156 for (
int row = 0; row < height; ++row )
161 for (
int col = 0; col < width; ++col )
165 if ( !inputColorData || row >= imageHeight || col >= imageWidth || inputColorData[i] == myNoDataColor )
167 outputColorData[i] = myNoDataColor;
171 const QRgb inputColor = inputColorData[i];
172 QColor myColor = QColor( inputColor );
175 const int alpha = qAlpha( inputColor );
180 outputColorData[i] = inputColor;
185 myColor.getRgb( &r, &g, &b );
187 if ( mInvertColors || alpha != 255 )
193 alphaFactor = alpha / 255.;
204 myColor = QColor::fromRgb( r, g, b );
207 myColor.getHsl( &h, &s, &l );
210 if ( ( mGrayscaleMode !=
GrayscaleOff ) || ( mSaturationScale != 1 ) )
212 processSaturation( r, g, b, h, s, l );
218 processColorization( r, g, b, h, s, l );
230 outputColorData[i] = qRgba( r, g, b, alpha );
234 return outputBlock.release();
238void QgsHueSaturationFilter::processColorization(
int &r,
int &g,
int &b,
int &h,
int &s,
int &l )
const
247 QColor colorizedColor = QColor::fromHsl( h, s, l );
249 if ( mColorizeStrength == 100 )
252 myColor = colorizedColor;
255 myColor.getRgb( &r, &g, &b );
260 int colorizedR, colorizedG, colorizedB;
261 colorizedColor.getRgb( &colorizedR, &colorizedG, &colorizedB );
264 double p = ( double ) mColorizeStrength / 100.;
265 r = p * colorizedR + ( 1 - p ) * r;
266 g = p * colorizedG + ( 1 - p ) * g;
267 b = p * colorizedB + ( 1 - p ) * b;
270 myColor = QColor::fromRgb( r, g, b );
271 myColor.getHsl( &h, &s, &l );
276void QgsHueSaturationFilter::processSaturation(
int &r,
int &g,
int &b,
int &h,
int &s,
int &l )
const
281 switch ( mGrayscaleMode )
289 myColor = QColor::fromHsl( h, s, l );
290 myColor.getRgb( &r, &g, &b );
296 int luminosity = 0.21 * r + 0.72 * g + 0.07 * b;
297 r = g = b = luminosity;
300 myColor = QColor::fromRgb( r, g, b );
301 myColor.getHsl( &h, &s, &l );
307 int average = ( r + g + b ) / 3;
311 myColor = QColor::fromRgb( r, g, b );
312 myColor.getHsl( &h, &s, &l );
318 if ( mSaturationScale < 1 )
321 s = std::min( (
int ) ( s * mSaturationScale ), 255 );
327 s = std::min( (
int ) ( 255. * ( 1 - std::pow( 1 - ( s / 255. ), std::pow( mSaturationScale, 2 ) ) ) ), 255 );
331 myColor = QColor::fromHsl( h, s, l );
332 myColor.getRgb( &r, &g, &b );
340 mSaturation = std::clamp(
saturation, -100, 100 );
343 mSaturationScale = ( ( double ) mSaturation / 100 ) + 1;
351 mColorizeH = mColorizeColor.hue();
352 mColorizeS = mColorizeColor.saturation();
357 if ( parentElem.isNull() )
362 QDomElement filterElem = doc.createElement( u
"huesaturation"_s );
364 filterElem.setAttribute( u
"saturation"_s, QString::number( mSaturation ) );
365 filterElem.setAttribute( u
"grayscaleMode"_s, QString::number( mGrayscaleMode ) );
366 filterElem.setAttribute( u
"invertColors"_s, QString::number( mInvertColors ) );
367 filterElem.setAttribute( u
"colorizeOn"_s, QString::number( mColorizeOn ) );
368 filterElem.setAttribute( u
"colorizeRed"_s, QString::number( mColorizeColor.red() ) );
369 filterElem.setAttribute( u
"colorizeGreen"_s, QString::number( mColorizeColor.green() ) );
370 filterElem.setAttribute( u
"colorizeBlue"_s, QString::number( mColorizeColor.blue() ) );
371 filterElem.setAttribute( u
"colorizeStrength"_s, QString::number( mColorizeStrength ) );
373 parentElem.appendChild( filterElem );
378 if ( filterElem.isNull() )
383 setSaturation( filterElem.attribute( u
"saturation"_s, u
"0"_s ).toInt() );
385 mInvertColors =
static_cast< bool >( filterElem.attribute( u
"invertColors"_s, u
"0"_s ).toInt() );
387 mColorizeOn =
static_cast< bool >( filterElem.attribute( u
"colorizeOn"_s, u
"0"_s ).toInt() );
388 int mColorizeRed = filterElem.attribute( u
"colorizeRed"_s, u
"255"_s ).toInt();
389 int mColorizeGreen = filterElem.attribute( u
"colorizeGreen"_s, u
"128"_s ).toInt();
390 int mColorizeBlue = filterElem.attribute( u
"colorizeBlue"_s, u
"128"_s ).toInt();
391 setColorizeColor( QColor::fromRgb( mColorizeRed, mColorizeGreen, mColorizeBlue ) );
392 mColorizeStrength = filterElem.attribute( u
"colorizeStrength"_s, u
"100"_s ).toInt();
DataType
Raster data types.
@ ARGB32_Premultiplied
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32_Premultiplied.
@ UnknownDataType
Unknown or unspecified type.
@ ARGB32
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32.
bool isCanceled() const
Tells whether the operation has been canceled already.
void setColorizeOn(bool colorizeOn)
void setSaturation(int saturation)
void setGrayscaleMode(QgsHueSaturationFilter::GrayscaleMode grayscaleMode)
QgsHueSaturationFilter(QgsRasterInterface *input=nullptr)
Qgis::DataType dataType(int bandNo) const override
Returns data type for the band specified by number.
QgsRasterBlock * block(int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback *feedback=nullptr) override
Read block of data using given extent and size.
QgsHueSaturationFilter * clone() const override
Clone itself, create deep copy.
void setInvertColors(bool invertColors)
Sets whether the filter will invert colors.
void setColorizeColor(const QColor &colorizeColor)
void setColorizeStrength(int colorizeStrength)
int bandCount() const override
Gets number of bands.
QColor colorizeColor() const
void readXml(const QDomElement &filterElem) override
Sets base class members from xml. Usually called from create() methods of subclasses.
void writeXml(QDomDocument &doc, QDomElement &parentElem) const override
Write base class members to xml.
bool setInput(QgsRasterInterface *input) override
Set input.
Feedback object tailored for raster block reading.
QgsRasterInterface(QgsRasterInterface *input=nullptr)
QgsRasterInterface * mInput
virtual QgsRectangle extent() const
Gets the extent of the interface.
virtual QgsRasterInterface * input() const
Current input.
A rectangle specified with double values.
unsigned long long qgssize
Qgssize is used instead of size_t, because size_t is stdlib type, unknown by SIP, and it would be har...
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)