mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 20:47:45 +00:00
LibGfx: Implement HueRotateFilter
This implements a simple and fairly efficient hue rotation filter. It is based off the SVG feColorMatrix "hueRotate" matrix operation. https://drafts.fxtf.org/filter-effects-1/#elementdef-fecolormatrix
This commit is contained in:
parent
6b167c8427
commit
df6b7fff90
1 changed files with 84 additions and 0 deletions
84
Userland/Libraries/LibGfx/Filters/HueRotateFilter.h
Normal file
84
Userland/Libraries/LibGfx/Filters/HueRotateFilter.h
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022, MacDue <macdue@dueutil.tech>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/Math.h>
|
||||||
|
#include <LibGfx/Filters/ColorFilter.h>
|
||||||
|
#include <LibGfx/Matrix3x3.h>
|
||||||
|
|
||||||
|
namespace Gfx {
|
||||||
|
|
||||||
|
class HueRotateFilter : public ColorFilter {
|
||||||
|
public:
|
||||||
|
HueRotateFilter(float angle_degrees)
|
||||||
|
: ColorFilter(angle_degrees)
|
||||||
|
, m_operation(calculate_operation_matrix(angle_degrees))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool amount_handled_in_filter() const override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
float angle_degrees() const
|
||||||
|
{
|
||||||
|
return m_amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual StringView class_name() const override { return "HueRotateFilter"sv; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Color convert_color(Color original) override
|
||||||
|
{
|
||||||
|
FloatVector3 rgb = {
|
||||||
|
original.red() / 256.0f,
|
||||||
|
original.green() / 256.0f,
|
||||||
|
original.blue() / 256.0f,
|
||||||
|
};
|
||||||
|
rgb = m_operation * rgb;
|
||||||
|
auto safe_float_to_u8 = [](float value) -> u8 {
|
||||||
|
return static_cast<u8>(AK::clamp(value, 0.0f, 1.0f) * 256);
|
||||||
|
};
|
||||||
|
return Color {
|
||||||
|
safe_float_to_u8(rgb[0]),
|
||||||
|
safe_float_to_u8(rgb[1]),
|
||||||
|
safe_float_to_u8(rgb[2]),
|
||||||
|
original.alpha()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static FloatMatrix3x3 calculate_operation_matrix(float angle)
|
||||||
|
{
|
||||||
|
float angle_rads = angle * (AK::Pi<float> / 180);
|
||||||
|
float cos_angle = 0;
|
||||||
|
float sin_angle = 0;
|
||||||
|
AK::sincos(angle_rads, sin_angle, cos_angle);
|
||||||
|
// The matrices here are taken directly from the SVG filter specification:
|
||||||
|
// https://drafts.fxtf.org/filter-effects-1/#feColorMatrixElement
|
||||||
|
// clang-format off
|
||||||
|
return FloatMatrix3x3 {
|
||||||
|
+0.213, +0.715, +0.072,
|
||||||
|
+0.213, +0.715, +0.072,
|
||||||
|
+0.213, +0.715, +0.072
|
||||||
|
} + cos_angle * FloatMatrix3x3 {
|
||||||
|
+0.787, -0.715, -0.072,
|
||||||
|
-0.213, +0.285, -0.072,
|
||||||
|
-0.213, -0.715, +0.928
|
||||||
|
} + sin_angle * FloatMatrix3x3 {
|
||||||
|
-0.213, -0.715, +0.928,
|
||||||
|
+0.143, +0.140, -0.283,
|
||||||
|
-0.787, +0.715, +0.072
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
}
|
||||||
|
|
||||||
|
FloatMatrix3x3 m_operation;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue