ici_files/
changing.rs

1use crate::prelude::*;
2
3pub trait ChangeColors {
4    /// De/saturate color by percentage
5    /// Negative amount increases saturation
6    /// So `-0.1` is 10% more saturated
7    fn with_saturate(&self, amount: f32) -> Self;
8
9    /// Increase saturation by 10%
10    fn saturate(&self) -> Self
11    where
12        Self: Sized,
13    {
14        self.with_saturate(-0.1)
15    }
16
17    /// Decrease saturation by 10%
18    fn desaturate(&self) -> Self
19    where
20        Self: Sized,
21    {
22        self.with_saturate(0.1)
23    }
24
25    /// Change brightness to `amount`
26    /// So `1.1` is 10% brighter
27    fn with_brightness(&self, amount: f32) -> Self;
28
29    fn lighten(&self) -> Self
30    where
31        Self: Sized,
32    {
33        self.with_brightness(1.1)
34    }
35
36    fn darken(&self) -> Self
37    where
38        Self: Sized,
39    {
40        self.with_brightness(0.9)
41    }
42}
43
44impl ChangeColors for Color {
45    fn with_saturate(&self, amount: f32) -> Self {
46        let mut rgba = [
47            self.r as f32 / 255.0,
48            self.g as f32 / 255.0,
49            self.b as f32 / 255.0,
50        ];
51        let lum = 0.2989 * rgba[0] + 0.5870 * rgba[1] + 0.1140 * rgba[2];
52        rgba[0] = rgba[0] + amount * (lum - rgba[0]);
53        rgba[1] = rgba[1] + amount * (lum - rgba[1]);
54        rgba[2] = rgba[2] + amount * (lum - rgba[2]);
55        Color::new(
56            (rgba[0] * 255.0) as u8,
57            (rgba[1] * 255.0) as u8,
58            (rgba[2] * 255.0) as u8,
59            self.a,
60        )
61    }
62
63    fn with_brightness(&self, amount: f32) -> Self {
64        Color::new(
65            ((((self.r as f32) / 255.0) * amount).clamp(0.0, 1.0) * 255.0) as u8,
66            ((((self.g as f32) / 255.0) * amount).clamp(0.0, 1.0) * 255.0) as u8,
67            ((((self.b as f32) / 255.0) * amount).clamp(0.0, 1.0) * 255.0) as u8,
68            self.a,
69        )
70    }
71}
72
73impl ChangeColors for Vec<Color> {
74    fn with_saturate(&self, amount: f32) -> Self {
75        let mut colors = vec![];
76        for color in self {
77            colors.push(color.with_saturate(amount));
78        }
79        colors
80    }
81
82    fn with_brightness(&self, amount: f32) -> Self {
83        let mut colors = vec![];
84        for color in self {
85            colors.push(color.with_brightness(amount));
86        }
87        colors
88    }
89}
90
91impl ChangeColors for IndexedImage {
92    fn with_saturate(&self, amount: f32) -> Self {
93        let mut image = self.clone();
94        image
95            .set_palette(&image.get_palette().to_vec().with_saturate(amount))
96            .expect("Color disappeared when changing saturation, please raise an issue on GitHub emmabritton/ici-files");
97        image
98    }
99
100    fn with_brightness(&self, amount: f32) -> Self {
101        let mut image = self.clone();
102        image
103            .set_palette(&image.get_palette().to_vec().with_brightness(amount))
104            .expect("Color disappeared when changing saturation, please raise an issue on GitHub emmabritton/ici-files");
105        image
106    }
107}
108
109impl ChangeColors for AnimatedIndexedImage {
110    fn with_saturate(&self, amount: f32) -> Self {
111        let mut image = self.clone();
112        image
113            .set_palette(&image.get_palette().to_vec().with_saturate(amount))
114            .expect("Color disappeared when changing saturation, please raise an issue on GitHub emmabritton/ici-files");
115        image
116    }
117
118    fn with_brightness(&self, amount: f32) -> Self {
119        let mut image = self.clone();
120        image
121            .set_palette(&image.get_palette().to_vec().with_brightness(amount))
122            .expect("Color disappeared when changing saturation, please raise an issue on GitHub emmabritton/ici-files");
123        image
124    }
125}