colors_transform/
grayscale.rs

1use super::ColorTuple;
2
3pub enum GrayScaleMethod {
4  Average,
5  AverageProminent,
6  Luminance,
7  Rec709,
8  Rec2100
9}
10
11static R_YUV_FACTOR: f32 = 0.299;
12static G_YUV_FACTOR: f32 = 0.587;
13static B_YUV_FACTOR: f32 = 0.114;
14
15static R_REC709_FACTOR: f32 = 0.2126;
16static G_REC709_FACTOR: f32 = 0.7152;
17static B_REC709_FACTOR: f32 = 0.0722;
18
19static R_REC2100_FACTOR: f32 = 0.2627;
20static G_REC2100_FACTOR: f32 = 0.6780;
21static B_REC2100_FACTOR: f32 = 0.0593;
22
23fn rgb_to_grayscale_lum(rgb: &ColorTuple) -> ColorTuple {
24  let (r, g, b) = rgb;
25  (r * R_YUV_FACTOR, g * G_YUV_FACTOR, b * B_YUV_FACTOR)
26}
27
28fn rgb_to_grayscale_rec709(rgb: &ColorTuple) -> ColorTuple {
29  let (r, g, b) = rgb;
30  (r * R_REC709_FACTOR, g * G_REC709_FACTOR, b * B_REC709_FACTOR)
31}
32fn rgb_to_grayscale_rec2100(rgb: &ColorTuple) -> ColorTuple {
33  let (r, g, b) = rgb;
34  (r * R_REC2100_FACTOR, g * G_REC2100_FACTOR, b * B_REC2100_FACTOR)
35}
36
37fn rgb_to_grayscale_avg(rgb: &ColorTuple) -> ColorTuple {
38  let (r, g, b) = rgb;
39  let y = (r + g + b) / 3.0;
40  (y, y, y)
41}
42
43fn rgb_to_grayscale_avg_prom(rgb: &ColorTuple) -> ColorTuple {
44  let (r, g, b) = rgb;
45  let rgb_vec = vec![r, g, b];
46  let max = rgb_vec.iter().fold(std::f32::MIN, |a, &b| a.max(*b));
47  let min = rgb_vec.iter().fold(std::f32::MAX, |a, &b| a.min(*b));
48  let y = (max + min) / 2.0;
49  (y, y, y)
50}
51
52
53pub fn rgb_grayscale(rgb: &ColorTuple, method: GrayScaleMethod) -> ColorTuple {
54  match method {
55    GrayScaleMethod::Average => rgb_to_grayscale_avg(rgb),
56    GrayScaleMethod::AverageProminent => rgb_to_grayscale_avg_prom(rgb),
57    GrayScaleMethod::Luminance => rgb_to_grayscale_lum(rgb),
58    GrayScaleMethod::Rec709 => rgb_to_grayscale_rec709(rgb),
59    GrayScaleMethod::Rec2100 => rgb_to_grayscale_rec2100(rgb),
60  }
61}