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}