💿🐜 Antkeeper source code https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

164 lines
4.1 KiB

/*
* Copyright (C) 2021 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_COLOR_SRGB_HPP
#define ANTKEEPER_COLOR_SRGB_HPP
#include "math/math.hpp"
#include <cmath>
namespace color {
/// Functions which operate in the sRGB colorspace.
namespace srgb {
/**
* Performs the sRGB Electro-Optical Transfer Function (EOTF), also known as the sRGB decoding function.
*
* @param v sRGB electrical signal (gamma-encoded sRGB).
* @return Corresponding luminance of the signal (linear sRGB).
*/
/// @{
float eotf(float v);
double eotf(double v);
template <class T>
math::vector3<T> eotf(const math::vector3<T>& v);
/// @}
/**
* Performs the sRGB inverse Electro-Optical Transfer Function (EOTF), also known as the sRGB encoding function.
*
* @param l sRGB luminance (linear sRGB).
* @return Corresponding electrical signal (gamma-encoded sRGB).
*/
/// @{
float eotf_inverse(float v);
double eotf_inverse(double v);
template <class T>
math::vector3<T> eotf_inverse(const math::vector3<T>& l);
/// @}
/**
* Calculates the luminance of a linear sRGB color.
*
* @param x Linear sRGB color.
* @return return Luminance of @p x.
*/
template <class T>
T luminance(const math::vector3<T>& x);
/**
* Transforms a linear sRGB color into the ACEScg colorspace using the Bradford chromatic adaption transform.
*
* @param x Linear sRGB color.
* @return ACEScg color.
*
* @see https://www.colour-science.org/apps/
*/
template <class T>
math::vector3<T> to_acescg(const math::vector3<T>& x);
/**
* Transforms a linear sRGB color into the CIE XYZ colorspace.
*
* @param x Linear sRGB color.
* @return CIE XYZ color.
*/
template <class T>
math::vector3<T> to_xyz(const math::vector3<T>& x);
inline float eotf(float v)
{
return (v < 0.04045f) ? (v / 12.92f) : std::pow((v + 0.055f) / 1.055f, 2.4f);
}
inline double eotf(double v)
{
return (v < 0.04045) ? (v / 12.92) : std::pow((v + 0.055) / 1.055, 2.4);
}
template <class T>
math::vector3<T> eotf(const math::vector3<T>& v)
{
return math::vector3<T>
{
eotf(v[0]),
eotf(v[1]),
eotf(v[2])
};
}
inline float eotf_inverse(float l)
{
return (l <= 0.0031308f) ? (l * 12.92f) : (std::pow(l, 1.0f / 2.4f) * 1.055f - 0.055f);
}
inline double eotf_inverse(double l)
{
return (l <= 0.0031308) ? (l * 12.92) : (std::pow(l, 1.0 / 2.4) * 1.055 - 0.055);
}
template <class T>
math::vector3<T> eotf_inverse(const math::vector3<T>& l)
{
return math::vector3<T>
{
eotf_inverse(l[0]),
eotf_inverse(l[1]),
eotf_inverse(l[2])
};
}
template <class T>
T luminance(const math::vector3<T>& x)
{
static const math::vector3<T> luma = {0.212639005871510, 0.715168678767756, 0.072192315360734};
return math::dot(x, luma);
}
template <class T>
math::vector3<T> to_acescg(const math::vector3<T>& x)
{
static const math::matrix3<T> srgb_to_acescg
{{
{0.613132422390542, 0.070124380833917, 0.020587657528185},
{0.339538015799666, 0.916394011313573, 0.109574571610682},
{0.047416696048269, 0.013451523958235, 0.869785404035327}
}};
return srgb_to_acescg * x;
}
template <class T>
math::vector3<T> to_xyz(const math::vector3<T>& x)
{
static const math::matrix3<T> srgb_to_xyz
{{
{0.412390799265959, 0.212639005871510, 0.019330818715592},
{0.357584339383878, 0.715168678767756, 0.119194779794626},
{0.180480788401834, 0.072192315360734, 0.950532152249661}
}};
return srgb_to_xyz * x;
}
} // namespace srgb
} // namespace color
#endif // ANTKEEPER_COLOR_SRGB_HPP