blob: ba2502c4d17b5a5ae9c65a8d262bb926e879cef0 [file] [log] [blame]
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::*;
fn expand_coeffs(y: f32, v: f32) -> [f32; 3] {
[y, 1.0 - y - v, v]
}
impl ColorPrimaries {
pub(crate) fn y_coeffs(&self) -> [f32; 3] {
// These values come from computations in Section 8 of
// https://www.itu.int/rec/T-REC-H.273-201612-S
match self {
ColorPrimaries::Unknown | ColorPrimaries::Srgb | ColorPrimaries::Unspecified => {
expand_coeffs(0.2126, 0.0722)
}
ColorPrimaries::Bt470m => expand_coeffs(0.299, 0.1146),
ColorPrimaries::Bt470bg => expand_coeffs(0.222, 0.0713),
ColorPrimaries::Bt601 | ColorPrimaries::Smpte240 => expand_coeffs(0.212, 0.087),
ColorPrimaries::GenericFilm => expand_coeffs(0.2536, 0.06808),
ColorPrimaries::Bt2020 => expand_coeffs(0.2627, 0.0593),
ColorPrimaries::Xyz => expand_coeffs(0.0, 0.0),
ColorPrimaries::Smpte431 => expand_coeffs(0.2095, 0.0689),
ColorPrimaries::Smpte432 => expand_coeffs(0.229, 0.0793),
ColorPrimaries::Ebu3213 => expand_coeffs(0.2318, 0.096),
}
}
}
fn calculate_yuv_coefficients_from_cicp(
color_primaries: ColorPrimaries,
matrix_coefficients: MatrixCoefficients,
) -> Option<[f32; 3]> {
match matrix_coefficients {
MatrixCoefficients::ChromaDerivedNcl => Some(color_primaries.y_coeffs()),
MatrixCoefficients::Bt709 => Some(expand_coeffs(0.2126, 0.0722)),
MatrixCoefficients::Fcc => Some(expand_coeffs(0.30, 0.11)),
MatrixCoefficients::Bt470bg | MatrixCoefficients::Bt601 => {
Some(expand_coeffs(0.299, 0.114))
}
MatrixCoefficients::Smpte240 => Some(expand_coeffs(0.212, 0.087)),
MatrixCoefficients::Bt2020Ncl => Some(expand_coeffs(0.2627, 0.0593)),
_ => None,
}
}
pub(crate) fn calculate_yuv_coefficients(
color_primaries: ColorPrimaries,
matrix_coefficients: MatrixCoefficients,
) -> [f32; 3] {
// Return known coefficients or fall back to BT.601.
calculate_yuv_coefficients_from_cicp(color_primaries, matrix_coefficients).unwrap_or(
calculate_yuv_coefficients_from_cicp(color_primaries, MatrixCoefficients::Bt601).unwrap(),
)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::internal_utils::assert_eq_f32_array;
#[test]
fn yuv_coefficients() {
assert_eq_f32_array(
&calculate_yuv_coefficients(ColorPrimaries::Unknown, MatrixCoefficients::Bt601),
&[0.299f32, 0.587f32, 0.114f32], // Kr,Kg,Kb as https://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion
);
assert_eq_f32_array(
&calculate_yuv_coefficients(ColorPrimaries::Unknown, MatrixCoefficients::Unspecified),
&[0.299f32, 0.587f32, 0.114f32], // Falls back to Bt601.
);
assert_eq_f32_array(
&calculate_yuv_coefficients(ColorPrimaries::Unknown, MatrixCoefficients::Smpte240),
&[0.212f32, 1f32 - 0.212 - 0.087, 0.087f32], // Kr,Kg,Kb as https://en.wikipedia.org/wiki/YCbCr#SMPTE_240M_conversion
);
}
}