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