// Copyright (c) the JPEG XL Project Authors. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. #ifndef LIB_JXL_CMS_OPSIN_PARAMS_H_ #define LIB_JXL_CMS_OPSIN_PARAMS_H_ #include "lib/jxl/base/matrix_ops.h" // Constants that define the XYB color space. namespace jxl { namespace cms { // Parameters for opsin absorbance. constexpr float kM02 = 0.078f; constexpr float kM00 = 0.30f; constexpr float kM01 = 1.0f - kM02 - kM00; constexpr float kM12 = 0.078f; constexpr float kM10 = 0.23f; constexpr float kM11 = 1.0f - kM12 - kM10; constexpr float kM20 = 0.24342268924547819f; constexpr float kM21 = 0.20476744424496821f; constexpr float kM22 = 1.0f - kM20 - kM21; constexpr float kBScale = 1.0f; constexpr float kYToBRatio = 1.0f; // works better with 0.50017729543783418 constexpr float kBToYRatio = 1.0f / kYToBRatio; constexpr float kOpsinAbsorbanceBias0 = 0.0037930732552754493f; constexpr float kOpsinAbsorbanceBias1 = kOpsinAbsorbanceBias0; constexpr float kOpsinAbsorbanceBias2 = kOpsinAbsorbanceBias0; // Opsin absorbance matrix is now frozen. constexpr Matrix3x3 kOpsinAbsorbanceMatrix{ {{kM00, kM01, kM02}, {kM10, kM11, kM12}, {kM20, kM21, kM22}}}; constexpr Matrix3x3 kDefaultInverseOpsinAbsorbanceMatrix{ {{11.031566901960783f, -9.866943921568629f, -0.16462299647058826f}, {-3.254147380392157f, 4.418770392156863f, -0.16462299647058826f}, {-3.6588512862745097f, 2.7129230470588235f, 1.9459282392156863f}}}; // Must be the inverse matrix of kOpsinAbsorbanceMatrix and match the spec. static inline const Matrix3x3& DefaultInverseOpsinAbsorbanceMatrix() { return kDefaultInverseOpsinAbsorbanceMatrix; } constexpr Vector3 kOpsinAbsorbanceBias = { kOpsinAbsorbanceBias0, kOpsinAbsorbanceBias1, kOpsinAbsorbanceBias2, }; constexpr std::array kNegOpsinAbsorbanceBiasRGB = { -kOpsinAbsorbanceBias0, -kOpsinAbsorbanceBias1, -kOpsinAbsorbanceBias2, 1.0f}; constexpr float kScaledXYBOffset0 = 0.015386134f; constexpr float kScaledXYBOffset1 = 0.0f; constexpr float kScaledXYBOffset2 = 0.27770459f; constexpr Vector3 kScaledXYBOffset = {kScaledXYBOffset0, kScaledXYBOffset1, kScaledXYBOffset2}; constexpr float kScaledXYBScale0 = 22.995788804f; constexpr float kScaledXYBScale1 = 1.183000077f; constexpr float kScaledXYBScale2 = 1.502141333f; constexpr Vector3 kScaledXYBScale = { kScaledXYBScale0, kScaledXYBScale1, kScaledXYBScale2, }; // NB(eustas): following function/variable names are just "namos". // More precise calculation of 1 / ((1 / r1) + (1 / r2)) constexpr float ReciprocialSum(float r1, float r2) { return (r1 * r2) / (r1 + r2); } constexpr float kXYBOffset0 = kScaledXYBOffset0 + kScaledXYBOffset1; constexpr float kXYBOffset1 = kScaledXYBOffset1 - kScaledXYBOffset0 + (1.0f / kScaledXYBScale0); constexpr float kXYBOffset2 = kScaledXYBOffset1 + kScaledXYBOffset2; constexpr std::array kXYBOffset = {kXYBOffset0, kXYBOffset1, kXYBOffset2}; constexpr float kXYBScale0 = ReciprocialSum(kScaledXYBScale0, kScaledXYBScale1); constexpr float kXYBScale1 = ReciprocialSum(kScaledXYBScale0, kScaledXYBScale1); constexpr float kXYBScale2 = ReciprocialSum(kScaledXYBScale1, kScaledXYBScale2); constexpr std::array kXYBScale = {kXYBScale0, kXYBScale1, kXYBScale2}; template constexpr float ScaledXYBScale() { return (idx == 0) ? kScaledXYBScale0 : (idx == 1) ? kScaledXYBScale1 : kScaledXYBScale2; } template constexpr float ScaledXYBOffset() { return (idx == 0) ? kScaledXYBOffset0 : (idx == 1) ? kScaledXYBOffset1 : kScaledXYBOffset2; } template constexpr float XYBCorner() { return (((idx == 0) ? x : (idx == 1) ? y : b) / ScaledXYBScale()) - ScaledXYBOffset(); } template constexpr float ScaledA2BCorner() { return (idx == 0) ? (XYBCorner() + XYBCorner()) : (idx == 1) ? (XYBCorner() - XYBCorner()) : (XYBCorner() + XYBCorner()); } typedef std::array ColorCube0D; template constexpr ColorCube0D UnscaledA2BCorner() { return {(ScaledA2BCorner() + kXYBOffset0) * kXYBScale0, (ScaledA2BCorner() + kXYBOffset1) * kXYBScale1, (ScaledA2BCorner() + kXYBOffset2) * kXYBScale2}; } typedef std::array ColorCube1D; template constexpr ColorCube1D UnscaledA2BCubeXY() { return {UnscaledA2BCorner(), UnscaledA2BCorner()}; } typedef std::array ColorCube2D; template constexpr ColorCube2D UnscaledA2BCubeX() { return {UnscaledA2BCubeXY(), UnscaledA2BCubeXY()}; } typedef std::array ColorCube3D; constexpr ColorCube3D UnscaledA2BCube() { return {UnscaledA2BCubeX<0>(), UnscaledA2BCubeX<1>()}; } constexpr ColorCube3D kUnscaledA2BCube = UnscaledA2BCube(); } // namespace cms } // namespace jxl #endif // LIB_JXL_CMS_OPSIN_PARAMS_H_