photon_rs/
filters.rs

1//! Preset color filters.
2
3use crate::channels::alter_channels;
4use crate::colour_spaces;
5use crate::colour_spaces::mix_with_colour;
6use crate::effects::{adjust_contrast, duotone, inc_brightness};
7use crate::monochrome;
8use crate::{PhotonImage, Rgb};
9
10#[cfg(feature = "enable_wasm")]
11use wasm_bindgen::prelude::*;
12
13/// Solarization on the Blue channel.
14///
15/// # Arguments
16/// * `img` - A PhotonImage.
17/// # Example
18///
19/// ```no_run
20/// use photon_rs::filters::neue;
21/// use photon_rs::native::open_image;
22///
23/// let mut img = open_image("img.jpg").expect("File should open");
24/// neue(&mut img);
25/// ```
26#[cfg_attr(feature = "enable_wasm", wasm_bindgen)]
27pub fn neue(photon_image: &mut PhotonImage) {
28    let end = photon_image.get_raw_pixels().len();
29
30    for i in (0..end).step_by(4) {
31        let b_val = photon_image.raw_pixels[i + 2];
32        if 255_i32 - b_val as i32 > 0 {
33            photon_image.raw_pixels[i + 2] = 255 - b_val;
34        }
35    }
36}
37
38/// Solarization on the Red and Green channels.
39///
40/// # Arguments
41/// * `img` - A PhotonImage.
42/// # Example
43///
44/// ```no_run
45/// use photon_rs::filters::lix;
46/// use photon_rs::native::open_image;
47///
48/// let mut img = open_image("img.jpg").expect("File should open");
49/// lix(&mut img);
50/// ```
51#[cfg_attr(feature = "enable_wasm", wasm_bindgen)]
52pub fn lix(photon_image: &mut PhotonImage) {
53    let end = photon_image.get_raw_pixels().len();
54
55    for i in (0..end).step_by(4) {
56        let r_val = photon_image.raw_pixels[i];
57        let g_val = photon_image.raw_pixels[i + 1];
58
59        photon_image.raw_pixels[i] = 255 - r_val;
60        photon_image.raw_pixels[i + 1] = 255 - g_val;
61    }
62}
63
64/// Solarization on the Red and Blue channels.
65///
66/// # Arguments
67/// * `img` - A PhotonImage.
68/// # Example
69///
70/// ```no_run
71/// use photon_rs::filters::ryo;
72/// use photon_rs::native::open_image;
73///
74/// let mut img = open_image("img.jpg").expect("File should open");
75/// ryo(&mut img);
76/// ```
77#[cfg_attr(feature = "enable_wasm", wasm_bindgen)]
78pub fn ryo(photon_image: &mut PhotonImage) {
79    let end = photon_image.get_raw_pixels().len();
80
81    for i in (0..end).step_by(4) {
82        let r_val = photon_image.raw_pixels[i];
83        let b_val = photon_image.raw_pixels[i + 2];
84
85        photon_image.raw_pixels[i] = 255 - r_val;
86        photon_image.raw_pixels[i + 2] = 255 - b_val;
87    }
88}
89
90/// Apply a filter to an image. Over 20 filters are available.
91/// The filters are as follows:
92/// * **oceanic**: Add an aquamarine-tinted hue to an image.
93/// * **islands**: Aquamarine tint.
94/// * **marine**: Add a green/blue mixed hue to an image.
95/// * **seagreen**: Dark green hue, with tones of blue.
96/// * **flagblue**: Royal blue tint
97/// * **liquid**: Blue-inspired tint.
98/// * **diamante**: Custom filter with a blue/turquoise tint.
99/// * **radio**: Fallout-style radio effect.
100/// * **twenties**: Slight-blue tinted historical effect.
101/// * **rosetint**: Rose-tinted filter.
102/// * **mauve**: Purple-infused filter.
103/// * **bluechrome**: Blue monochrome effect.
104/// * **vintage**: Vintage filter with a red tint.
105/// * **perfume**: Increase the blue channel, with moderate increases in the Red and Green channels.
106/// * **serenity**: Custom filter with an increase in the Blue channel's values.
107/// # Arguments
108/// * `img` - A PhotonImage.
109/// * `filter_name` - The filter's name. Choose from the selection above, eg: "oceanic"
110/// # Example
111///
112/// ```no_run
113/// // For example, to add a filter called "vintage" to an image:
114/// use photon_rs::filters::filter;
115/// use photon_rs::native::open_image;
116///
117/// let mut img = open_image("img.jpg").expect("File should open");
118/// filter(&mut img, "vintage");
119/// ```
120#[cfg_attr(feature = "enable_wasm", wasm_bindgen)]
121pub fn filter(img: &mut PhotonImage, filter_name: &str) {
122    let oceanic_rgb = Rgb::new(0, 89, 173);
123    let islands_rgb = Rgb::new(0, 24, 95);
124    let marine_rgb = Rgb::new(0, 14, 119);
125    let seagreen_rgb = Rgb::new(0, 68, 62);
126    let flagblue_rgb = Rgb::new(0, 0, 131);
127    let diamante_rgb = Rgb::new(30, 82, 87);
128    let liquid_rgb = Rgb::new(0, 10, 75);
129    let vintage_rgb = Rgb::new(120, 70, 13);
130    let perfume_rgb = Rgb::new(80, 40, 120);
131    let serenity_rgb = Rgb::new(10, 40, 90);
132
133    match filter_name {
134        // Match filter name to its corresponding function.
135        "oceanic" => mix_with_colour(img, oceanic_rgb, 0.2),
136        "islands" => mix_with_colour(img, islands_rgb, 0.2),
137        "marine" => mix_with_colour(img, marine_rgb, 0.2),
138        "seagreen" => mix_with_colour(img, seagreen_rgb, 0.2),
139        "flagblue" => mix_with_colour(img, flagblue_rgb, 0.2),
140        "diamante" => mix_with_colour(img, diamante_rgb, 0.1),
141        "liquid" => mix_with_colour(img, liquid_rgb, 0.2),
142        "radio" => monochrome::monochrome(img, 5, 40, 20),
143        "twenties" => monochrome::monochrome(img, 18, 12, 20),
144        "rosetint" => monochrome::monochrome(img, 80, 20, 31),
145        "mauve" => monochrome::monochrome(img, 90, 40, 80),
146        "bluechrome" => monochrome::monochrome(img, 20, 30, 60),
147        "vintage" => mix_with_colour(img, vintage_rgb, 0.2),
148        "perfume" => mix_with_colour(img, perfume_rgb, 0.2),
149        "serenity" => mix_with_colour(img, serenity_rgb, 0.2),
150        "golden" => golden(img),
151        "pastel_pink" => pastel_pink(img),
152        "cali" => cali(img),
153        "dramatic" => dramatic(img),
154        "firenze" => firenze(img),
155        "obsidian" => obsidian(img),
156        "lofi" => lofi(img),
157        _ => monochrome::monochrome(img, 90, 40, 80),
158    };
159}
160
161/// Apply a lofi effect to an image.
162///
163/// # Arguments
164/// * `img` - A PhotonImage.
165/// # Example
166///
167/// ```no_run
168/// use photon_rs::filters::lofi;
169/// use photon_rs::native::open_image;
170///
171/// let mut img = open_image("img.jpg").expect("File should open");
172/// lofi(&mut img);
173/// ```
174#[cfg_attr(feature = "enable_wasm", wasm_bindgen)]
175pub fn lofi(img: &mut PhotonImage) {
176    adjust_contrast(img, 30.0);
177    colour_spaces::saturate_hsl(img, 0.2);
178}
179
180/// Apply a rose tint to an image.
181///
182/// # Arguments
183/// * `img` - A PhotonImage.
184/// # Example
185///
186/// ```no_run
187/// use photon_rs::filters::pastel_pink;
188/// use photon_rs::native::open_image;
189///
190/// let mut img = open_image("img.jpg").expect("File should open");
191/// pastel_pink(&mut img);
192/// ```
193#[cfg_attr(feature = "enable_wasm", wasm_bindgen)]
194pub fn pastel_pink(img: &mut PhotonImage) {
195    alter_channels(img, 80, 12, 20);
196    adjust_contrast(img, 30.0);
197}
198
199/// Apply a vintage, golden hue to an image.
200///
201/// # Arguments
202/// * `img` - A PhotonImage.
203/// # Example
204///
205/// ```no_run
206/// use photon_rs::filters::golden;
207/// use photon_rs::native::open_image;
208///
209/// let mut img = open_image("img.jpg").expect("File should open");
210/// golden(&mut img);
211/// ```
212#[cfg_attr(feature = "enable_wasm", wasm_bindgen)]
213pub fn golden(img: &mut PhotonImage) {
214    let vignette_rgb = Rgb::new(235, 145, 50);
215    mix_with_colour(img, vignette_rgb, 0.2);
216    adjust_contrast(img, 30.0);
217}
218
219/// Increased contrast filter effect.
220///
221/// # Arguments
222/// * `img` - A PhotonImage.
223/// # Example
224///
225/// ```no_run
226/// use photon_rs::filters::cali;
227/// use photon_rs::native::open_image;
228///
229/// let mut img = open_image("img.jpg").expect("File should open");
230/// cali(&mut img);
231/// ```
232#[cfg_attr(feature = "enable_wasm", wasm_bindgen)]
233pub fn cali(img: &mut PhotonImage) {
234    let cali_rgb = Rgb::new(255, 45, 75);
235    colour_spaces::mix_with_colour(img, cali_rgb, 0.1);
236    adjust_contrast(img, 50.0);
237}
238
239/// Greyscale effect with increased contrast.
240///
241/// # Arguments
242/// * `img` - A PhotonImage.
243/// # Example
244///
245/// ```no_run
246/// use photon_rs::filters::dramatic;
247/// use photon_rs::native::open_image;
248///
249/// let mut img = open_image("img.jpg").expect("File should open");
250/// dramatic(&mut img);
251/// ```
252#[cfg_attr(feature = "enable_wasm", wasm_bindgen)]
253pub fn dramatic(img: &mut PhotonImage) {
254    monochrome::grayscale(img);
255    adjust_contrast(img, 60.0);
256}
257
258/// Monochrome tint effect with increased contrast
259///
260/// # Arguments
261/// * `img` - A PhotonImage.
262/// * `rgb_color` - RGB color
263/// # Example
264///
265/// ```no_run
266/// use photon_rs::filters::monochrome_tint;
267/// use photon_rs::native::open_image;
268/// use photon_rs::Rgb;
269///
270/// let mut img = open_image("img.jpg").expect("File should open");
271/// let rgb_color = Rgb::new(12, 12, 10);
272/// monochrome_tint(&mut img, rgb_color);
273/// ```
274#[cfg_attr(feature = "enable_wasm", wasm_bindgen)]
275pub fn monochrome_tint(img: &mut PhotonImage, rgb_color: Rgb) {
276    monochrome::grayscale(img);
277    mix_with_colour(img, rgb_color, 0.4);
278    adjust_contrast(img, 60.0);
279}
280
281/// Duotone effect with blue and purple tones.
282///
283/// # Arguments
284/// * `img` - A PhotonImage.
285/// # Example
286///
287/// ```no_run
288/// use photon_rs::filters::duotone_violette;
289/// use photon_rs::native::open_image;
290///
291/// let mut img = open_image("img.jpg").expect("File should open");
292/// duotone_violette(&mut img);
293/// ```
294#[cfg_attr(feature = "enable_wasm", wasm_bindgen)]
295pub fn duotone_violette(img: &mut PhotonImage) {
296    let rgb_color = Rgb::new(16, 228, 248);
297    let rgb_color2 = Rgb::new(116, 54, 221);
298    duotone(img, rgb_color, rgb_color2);
299}
300
301/// Duotone effect with purple tones.
302///
303/// # Arguments
304/// * `img` - A PhotonImage.
305/// # Example
306///
307/// ```no_run
308/// use photon_rs::filters::duotone_horizon;
309/// use photon_rs::native::open_image;
310///
311/// let mut img = open_image("img.jpg").expect("File should open");
312/// duotone_horizon(&mut img);
313/// ```
314#[cfg_attr(feature = "enable_wasm", wasm_bindgen)]
315pub fn duotone_horizon(img: &mut PhotonImage) {
316    let rgb_color = Rgb::new(169, 167, 132);
317    let rgb_color2 = Rgb::new(150, 24, 149);
318    duotone(img, rgb_color, rgb_color2);
319}
320
321/// A duotone filter with a user-specified color and a gray color
322// to create a monochrome tint effect
323///
324/// # Arguments
325/// * `img` - A PhotonImage.
326/// * `rgb_color` - RGB color
327/// # Example
328///
329/// ```no_run
330/// use photon_rs::filters::duotone_tint;
331/// use photon_rs::native::open_image;
332/// use photon_rs::Rgb;
333///
334/// let mut img = open_image("img.jpg").expect("File should open");
335/// let rgb_color = Rgb::new(12, 12, 10);
336/// duotone_tint(&mut img, rgb_color);
337/// ```
338#[cfg_attr(feature = "enable_wasm", wasm_bindgen)]
339pub fn duotone_tint(img: &mut PhotonImage, rgb_color: Rgb) {
340    let rgb_color2 = Rgb::new(68, 61, 76);
341    duotone(img, rgb_color, rgb_color2);
342}
343
344/// Duotone effect with a lilac hue
345///
346/// # Arguments
347/// * `img` - A PhotonImage.
348/// # Example
349///
350/// ```no_run
351/// use photon_rs::filters::duotone_lilac;
352/// use photon_rs::native::open_image;
353///
354/// let mut img = open_image("img.jpg").expect("File should open");
355/// duotone_lilac(&mut img);
356/// ```
357#[cfg_attr(feature = "enable_wasm", wasm_bindgen)]
358pub fn duotone_lilac(img: &mut PhotonImage) {
359    let rgb_color = Rgb::new(45, 3, 3);
360    let rgb_color2 = Rgb::new(163, 134, 224);
361    duotone(img, rgb_color, rgb_color2);
362}
363
364/// A duotone ochre tint effect
365///
366/// # Arguments
367/// * `img` - A PhotonImage.
368/// # Example
369///
370/// ```no_run
371/// use photon_rs::filters::duotone_ochre;
372/// use photon_rs::native::open_image;
373///
374/// let mut img = open_image("img.jpg").expect("File should open");
375/// duotone_ochre(&mut img);
376/// ```
377#[cfg_attr(feature = "enable_wasm", wasm_bindgen)]
378pub fn duotone_ochre(img: &mut PhotonImage) {
379    let rgb_color = Rgb::new(25, 36, 88);
380    let rgb_color2 = Rgb::new(236, 119, 0);
381    duotone(img, rgb_color, rgb_color2);
382}
383
384/// Apply a red hue, with increased contrast and brightness.
385///
386/// # Arguments
387/// * `img` - A PhotonImage.
388/// # Example
389///
390/// ```no_run
391/// use photon_rs::filters::firenze;
392/// use photon_rs::native::open_image;
393///
394/// let mut img = open_image("img.jpg").expect("File should open");
395/// firenze(&mut img);
396/// ```
397#[cfg_attr(feature = "enable_wasm", wasm_bindgen)]
398pub fn firenze(img: &mut PhotonImage) {
399    let cali_rgb = Rgb::new(255, 47, 78);
400    colour_spaces::mix_with_colour(img, cali_rgb, 0.1);
401
402    inc_brightness(img, 30);
403    adjust_contrast(img, 50.0);
404}
405
406/// Apply a greyscale effect with increased contrast.
407///
408/// # Arguments
409/// * `img` - A PhotonImage.
410/// # Example
411///
412/// ```no_run
413/// use photon_rs::filters::obsidian;
414/// use photon_rs::native::open_image;
415///
416/// let mut img = open_image("img.jpg").expect("File should open");
417/// obsidian(&mut img);
418/// ```
419#[cfg_attr(feature = "enable_wasm", wasm_bindgen)]
420pub fn obsidian(img: &mut PhotonImage) {
421    monochrome::grayscale(img);
422    adjust_contrast(img, 25.0);
423}