1 // Copyright 2024 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 use crate::*;
16 
expand_coeffs(y: f32, v: f32) -> [f32; 3]17 fn expand_coeffs(y: f32, v: f32) -> [f32; 3] {
18     [y, 1.0 - y - v, v]
19 }
20 
21 impl ColorPrimaries {
y_coeffs(&self) -> [f32; 3]22     pub fn y_coeffs(&self) -> [f32; 3] {
23         // These values come from computations in Section 8 of
24         // https://www.itu.int/rec/T-REC-H.273-201612-S
25         match self {
26             ColorPrimaries::Unknown | ColorPrimaries::Srgb | ColorPrimaries::Unspecified => {
27                 expand_coeffs(0.2126, 0.0722)
28             }
29             ColorPrimaries::Bt470m => expand_coeffs(0.299, 0.1146),
30             ColorPrimaries::Bt470bg => expand_coeffs(0.222, 0.0713),
31             ColorPrimaries::Bt601 | ColorPrimaries::Smpte240 => expand_coeffs(0.212, 0.087),
32             ColorPrimaries::GenericFilm => expand_coeffs(0.2536, 0.06808),
33             ColorPrimaries::Bt2020 => expand_coeffs(0.2627, 0.0593),
34             ColorPrimaries::Xyz => expand_coeffs(0.0, 0.0),
35             ColorPrimaries::Smpte431 => expand_coeffs(0.2095, 0.0689),
36             ColorPrimaries::Smpte432 => expand_coeffs(0.229, 0.0793),
37             ColorPrimaries::Ebu3213 => expand_coeffs(0.2318, 0.096),
38         }
39     }
40 }
41 
calculate_yuv_coefficients_from_cicp( color_primaries: ColorPrimaries, matrix_coefficients: MatrixCoefficients, ) -> Option<[f32; 3]>42 fn calculate_yuv_coefficients_from_cicp(
43     color_primaries: ColorPrimaries,
44     matrix_coefficients: MatrixCoefficients,
45 ) -> Option<[f32; 3]> {
46     match matrix_coefficients {
47         MatrixCoefficients::ChromaDerivedNcl => Some(color_primaries.y_coeffs()),
48         MatrixCoefficients::Bt709 => Some(expand_coeffs(0.2126, 0.0722)),
49         MatrixCoefficients::Fcc => Some(expand_coeffs(0.30, 0.11)),
50         MatrixCoefficients::Bt470bg | MatrixCoefficients::Bt601 => {
51             Some(expand_coeffs(0.299, 0.114))
52         }
53         MatrixCoefficients::Smpte240 => Some(expand_coeffs(0.212, 0.087)),
54         MatrixCoefficients::Bt2020Ncl => Some(expand_coeffs(0.2627, 0.0593)),
55         _ => None,
56     }
57 }
58 
calculate_yuv_coefficients( color_primaries: ColorPrimaries, matrix_coefficients: MatrixCoefficients, ) -> [f32; 3]59 pub fn calculate_yuv_coefficients(
60     color_primaries: ColorPrimaries,
61     matrix_coefficients: MatrixCoefficients,
62 ) -> [f32; 3] {
63     // Return known coefficients or fall back to BT.601.
64     calculate_yuv_coefficients_from_cicp(color_primaries, matrix_coefficients).unwrap_or(
65         calculate_yuv_coefficients_from_cicp(color_primaries, MatrixCoefficients::Bt601).unwrap(),
66     )
67 }
68 
69 #[cfg(test)]
70 mod tests {
71     use super::*;
72     use crate::internal_utils::assert_eq_f32_array;
73 
74     #[test]
yuv_coefficients()75     fn yuv_coefficients() {
76         assert_eq_f32_array(
77             &calculate_yuv_coefficients(ColorPrimaries::Unknown, MatrixCoefficients::Bt601),
78             &[0.299f32, 0.587f32, 0.114f32], // Kr,Kg,Kb as https://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion
79         );
80         assert_eq_f32_array(
81             &calculate_yuv_coefficients(ColorPrimaries::Unknown, MatrixCoefficients::Unspecified),
82             &[0.299f32, 0.587f32, 0.114f32], // Falls back to Bt601.
83         );
84         assert_eq_f32_array(
85             &calculate_yuv_coefficients(ColorPrimaries::Unknown, MatrixCoefficients::Smpte240),
86             &[0.212f32, 1f32 - 0.212 - 0.087, 0.087f32], // Kr,Kg,Kb as https://en.wikipedia.org/wiki/YCbCr#SMPTE_240M_conversion
87         );
88     }
89 }
90