libeffectengine/effects/
pixelate.rs1use std::io::Cursor;
2#[cfg(not(target_arch = "wasm32"))]
3use std::process::exit;
4use wasm_bindgen::prelude::*;
5
6use image::{DynamicImage, ImageBuffer, ImageFormat, Rgba};
7
8#[cfg(not(target_arch = "wasm32"))]
9use crate::util::subcommand_help_requested;
10use crate::util::{get_paths, read_image};
11
12#[wasm_bindgen(js_name = pixelate)]
15pub fn effect() -> Vec<u8> {
16 #[cfg(not(target_arch = "wasm32"))]
17 {
18 if subcommand_help_requested() {
19 print_help();
20 exit(0);
21 }
22 }
23
24 let paths = get_paths();
25 let image_data = read_image(paths.input_path);
26
27 let img =
28 image::load_from_memory(&image_data.data).expect("Failed to decode image from memory");
29 let image = img.to_rgba8();
30 let image_width = image.width();
31 let image_height = image.height();
32
33 let processed_pixel_size = std::env::args()
35 .nth(4)
36 .or_else(|| Some(String::from("16")))
37 .unwrap()
38 .parse()
39 .unwrap_or_else(|_| 16);
40
41 let mut new_image = ImageBuffer::new(image_width, image_height);
42
43 for i in (0..image_width).step_by(processed_pixel_size as usize) {
44 for j in (0..image_height).step_by(processed_pixel_size as usize) {
45 let mut r_sum: u64 = 0;
46 let mut g_sum: u64 = 0;
47 let mut b_sum: u64 = 0;
48 let mut a_sum: u64 = 0;
49 let mut count: u64 = 0;
50
51 let x_end: u32 = (i + processed_pixel_size).min(image_width);
52 let y_end: u32 = (j + processed_pixel_size).min(image_height);
53
54 for k in i..x_end {
55 for l in j..y_end {
56 let pixel = image.get_pixel(k, l);
57
58 r_sum += pixel.0[0] as u64;
59 g_sum += pixel.0[1] as u64;
60 b_sum += pixel.0[2] as u64;
61 a_sum += pixel.0[3] as u64;
62 count += 1;
63 }
64 }
65
66 if count > 0 {
67 let color = Rgba([
68 (r_sum / count) as u8,
69 (g_sum / count) as u8,
70 (b_sum / count) as u8,
71 (a_sum / count) as u8,
72 ]);
73
74 for k in i..x_end {
75 for l in j..y_end {
76 new_image.put_pixel(k, l, color);
77 }
78 }
79 }
80 }
81 }
82
83 let mut cursor = Cursor::new(Vec::new());
84
85 if image_data.format == ImageFormat::Jpeg {
86 let rgb_image = DynamicImage::ImageRgba8(new_image).into_rgb8();
87 rgb_image
88 .write_to(&mut cursor, image_data.format)
89 .expect("Failed to encode JPEG");
90 } else {
91 new_image
92 .write_to(&mut cursor, image_data.format)
93 .expect("Failed to encode image");
94 }
95
96 return cursor.into_inner();
97}
98
99#[cfg(not(target_arch = "wasm32"))]
101fn print_help() {
102 println!(
103 r#"
104Pixelation Effect
105Applies a pixelation filter to an image by combining multiple pixels into bigger
106ones.
107
108USAGE:
109 effectengine-cli pixelate <INPUT_PATH> <OUTPUT_PATH> [PIXELATION_STRENGTH]
110
111ARGUMENTS:
112 <INPUT_PATH> The path to an input image that should be processed.
113 <OUTPUT_PATH> The path where the resulting image should be saved.
114 Needs to include the filename.
115 [PIXELATION_STRENGTH] Optional. How strong the pixelation effect should be.
116 Specifies the size of each big pixel. (Default: 16)
117 "#
118 );
119}