#pragma once
#include <math.h>
#include <wtf/MathExtras.h>
namespace WebCore {
template<typename> struct ColorComponents;
template<size_t Columns, size_t Rows>
class ColorMatrix {
public:
template<typename ...Ts>
explicit constexpr ColorMatrix(Ts ...input)
: m_matrix {{ input ... }}
{
static_assert(sizeof...(Ts) == Rows * Columns);
}
constexpr ColorComponents<float> transformedColorComponents(const ColorComponents<float>&) const;
constexpr float at(size_t row, size_t column) const
{
return m_matrix[(row * Columns) + column];
}
private:
std::array<float, Rows * Columns> m_matrix;
};
constexpr ColorMatrix<3, 3> grayscaleColorMatrix(float amount)
{
float oneMinusAmount = std::clamp(1.0f - amount, 0.0f, 1.0f);
return ColorMatrix<3, 3> {
0.2126f + 0.7874f * oneMinusAmount, 0.7152f - 0.7152f * oneMinusAmount, 0.0722f - 0.0722f * oneMinusAmount,
0.2126f - 0.2126f * oneMinusAmount, 0.7152f + 0.2848f * oneMinusAmount, 0.0722f - 0.0722f * oneMinusAmount,
0.2126f - 0.2126f * oneMinusAmount, 0.7152f - 0.7152f * oneMinusAmount, 0.0722f + 0.9278f * oneMinusAmount
};
}
constexpr ColorMatrix<3, 3> sepiaColorMatrix(float amount)
{
float oneMinusAmount = std::clamp(1.0f - amount, 0.0f, 1.0f);
return ColorMatrix<3, 3> {
0.393f + 0.607f * oneMinusAmount, 0.769f - 0.769f * oneMinusAmount, 0.189f - 0.189f * oneMinusAmount,
0.349f - 0.349f * oneMinusAmount, 0.686f + 0.314f * oneMinusAmount, 0.168f - 0.168f * oneMinusAmount,
0.272f - 0.272f * oneMinusAmount, 0.534f - 0.534f * oneMinusAmount, 0.131f + 0.869f * oneMinusAmount
};
}
constexpr ColorMatrix<3, 3> saturationColorMatrix(float amount)
{
return ColorMatrix<3, 3> {
0.213f + 0.787f * amount, 0.715f - 0.715f * amount, 0.072f - 0.072f * amount,
0.213f - 0.213f * amount, 0.715f + 0.285f * amount, 0.072f - 0.072f * amount,
0.213f - 0.213f * amount, 0.715f - 0.715f * amount, 0.072f + 0.928f * amount
};
}
inline ColorMatrix<3, 3> hueRotateColorMatrix(float angleInDegrees)
{
float cosHue = cos(deg2rad(angleInDegrees));
float sinHue = sin(deg2rad(angleInDegrees));
return ColorMatrix<3, 3> {
0.213f + cosHue * 0.787f - sinHue * 0.213f, 0.715f - cosHue * 0.715f - sinHue * 0.715f, 0.072f - cosHue * 0.072f + sinHue * 0.928f,
0.213f - cosHue * 0.213f + sinHue * 0.143f, 0.715f + cosHue * 0.285f + sinHue * 0.140f, 0.072f - cosHue * 0.072f - sinHue * 0.283f,
0.213f - cosHue * 0.213f - sinHue * 0.787f, 0.715f - cosHue * 0.715f + sinHue * 0.715f, 0.072f + cosHue * 0.928f + sinHue * 0.072f
};
}
template<size_t Columns, size_t Rows>
constexpr ColorComponents<float> ColorMatrix<Columns, Rows>::transformedColorComponents(const ColorComponents<float>& inputVector) const
{
static_assert(ColorComponents<float>::Size >= Rows);
ColorComponents<float> result;
for (size_t row = 0; row < Rows; ++row) {
if constexpr (Columns <= ColorComponents<float>::Size) {
for (size_t column = 0; column < Columns; ++column)
result[row] += at(row, column) * inputVector[column];
} else if constexpr (Columns > ColorComponents<float>::Size) {
for (size_t column = 0; column < ColorComponents<float>::Size; ++column)
result[row] += at(row, column) * inputVector[column];
for (size_t additionalColumn = ColorComponents<float>::Size; additionalColumn < Columns; ++additionalColumn)
result[row] += at(row, additionalColumn);
}
}
if constexpr (ColorComponents<float>::Size > Rows) {
for (size_t additionalRow = Rows; additionalRow < ColorComponents<float>::Size; ++additionalRow)
result[additionalRow] = inputVector[additionalRow];
}
return result;
}
}