Skip to main content

doe/
images.rs

1#[allow(warnings)]
2#[cfg(feature = "images")]
3pub mod images {
4    use image::GenericImageView;
5    use image::ImageFormat;
6    use image::{DynamicImage, ImageBuffer, Rgba, RgbaImage};
7    /// # image_add_padding
8    /// padding_color [[r,g,b,a]]
9    /// ```ignore
10    /// use doe::images::image_add_padding;
11    /// image_add_padding(
12    ///     "demo.png",
13    ///     [255,255,255,255], 10,
14    ///     10,
15    ///     "new_demo.png"
16    /// );
17    /// ````
18    ///
19    pub fn image_add_padding(
20        path: &str,
21        padding_color: [u8; 4],
22        padding_vertical: u32,
23        padding_horisontal: u32,
24        new_path: &str,
25    ) -> DynamicImage {
26        let image = image::open(path).unwrap();
27        let (width, height) = (image.width(), image.height());
28        let padded_width = width + 2 * padding_horisontal;
29        let padded_height = height + 2 * padding_vertical;
30        let color = Rgba(padding_color); //color
31        let mut padded_image: RgbaImage =
32            ImageBuffer::from_pixel(padded_width, padded_height, color);
33        for (x, y, pixel) in image.pixels() {
34            padded_image.put_pixel(x + padding_horisontal, y + padding_vertical, pixel);
35        }
36        DynamicImage::ImageRgba8(padded_image)
37    }
38
39    pub fn image_resize(path: &str, size: (u32, u32)) -> DynamicImage {
40        // 打开图像文件
41        let img = image::open(path).expect("无法打开图像文件");
42        // 调整图像大小
43        let resized_img = img.resize_exact(size.0, size.1, image::imageops::FilterType::Lanczos3);
44        resized_img
45    }
46    /// # image_convert
47    /// ```ignore
48    /// let new_format = [
49    ///     "Png",
50    ///     "Jpeg",
51    ///     "Gif",
52    ///     "WebP",
53    ///     "Pnm",
54    ///     "Tiff",
55    ///     "Tga",
56    ///     "Dds",
57    ///     "Bmp",
58    ///     "Ico",
59    ///     "Hdr",
60    ///     "OpenExr",
61    ///     "Farbfeld",
62    ///     "Avif",
63    ///     "Qoi",
64    /// ]
65    /// ```
66    /// ```ignore
67    /// use doe::images::image_convert;
68    /// image_convert("dvwa_23_14.png","Jpeg","demo.jpg");
69    /// ```
70    ///
71    pub fn image_convert(path: &str, new_format: &str, new_path: &str) {
72        // 打开图像文件
73        let img = image::open(path).expect("无法打开图像文件");
74        let format = match new_format.as_ref() {
75            "Png" => (ImageFormat::Png, "png"),
76            "Jpeg" => (ImageFormat::Jpeg, "jpg"),
77            "Gif" => (ImageFormat::Gif, "gif"),
78            "WebP" => (ImageFormat::WebP, "webp"),
79            "Pnm" => (ImageFormat::Pnm, "pnm"),
80            "Tiff" => (ImageFormat::Tiff, "tiff"),
81            "Tga" => (ImageFormat::Tga, "tga"),
82            "Dds" => (ImageFormat::Dds, "dds"),
83            "Bmp" => (ImageFormat::Bmp, "bmp"),
84            "Ico" => (ImageFormat::Ico, "ico"),
85            "Hdr" => (ImageFormat::Hdr, "hdr"),
86            "OpenExr" => (ImageFormat::OpenExr, "exr"),
87            "Farbfeld" => (ImageFormat::Farbfeld, "ff"),
88            "Avif" => (ImageFormat::Avif, "avif"),
89            "Qoi" => (ImageFormat::Qoi, "qoi"),
90            _ => (ImageFormat::Png, "png"),
91        };
92        img.save_with_format(new_path, format.0).unwrap();
93    }
94
95    pub fn convert_to_icns(
96        png_path: &str,
97        icns_path: &str,
98    ) -> Result<(), Box<dyn std::error::Error>> {
99        use icns::{IconFamily, IconType, Image};
100        let file = std::io::BufReader::new(std::fs::File::open(png_path).unwrap());
101        let image = Image::read_png(file).unwrap();
102        let w = image.width();
103        let h = image.height();
104        let new_file = std::io::BufWriter::new(std::fs::File::create(icns_path).unwrap());
105        let mut icon_family = IconFamily::new();
106        icon_family.add_icon(&image).unwrap();
107        icon_family.write(new_file).unwrap();
108        Ok(())
109    }
110    /// # rotate_image
111    /// ```ignore
112    /// let p_name = "demo.png";
113    /// let rotated_img = doe::images::rotate_image(&p_name, 15.0);
114    /// rotated_img.save(p_name).expect("Failed to save rotated image");
115    /// ```
116    /// 
117    /// 
118    pub fn rotate_image(path: &str, degrees: f32) -> RgbaImage {
119        let img = image::open(path).expect("Failed to open image");
120        // Calculate the radians equivalent of the given degrees
121        let radians = degrees.to_radians();
122
123        // Compute the dimensions of the rotated image
124        let (width, height) = img.dimensions();
125        let rotated_width =
126            ((radians.cos() * width as f32).abs() + (radians.sin() * height as f32).abs()) as u32;
127        let rotated_height =
128            ((radians.sin() * width as f32).abs() + (radians.cos() * height as f32).abs()) as u32;
129
130        // Create a new blank image with the rotated dimensions
131        let mut rotated_img = RgbaImage::new(rotated_width, rotated_height);
132
133        // Compute the center coordinates of the rotated image
134        let center_x = rotated_width as f32 / 2.0;
135        let center_y = rotated_height as f32 / 2.0;
136
137        // Iterate over each pixel in the rotated image and copy the corresponding pixel from the original image
138        for (x, y, pixel) in rotated_img.enumerate_pixels_mut() {
139            // Compute the corresponding coordinates in the original image
140            let orig_x = radians.cos() * ((x as f32 - center_x) / center_x)
141                + radians.sin() * ((y as f32 - center_y) / center_y);
142            let orig_y = -radians.sin() * ((x as f32 - center_x) / center_x)
143                + radians.cos() * ((y as f32 - center_y) / center_y);
144
145            // Convert the floating-point coordinates to integer coordinates
146            let orig_x = orig_x * center_x + center_x;
147            let orig_y = orig_y * center_y + center_y;
148
149            // Check if the computed coordinates are within the bounds of the original image
150            if orig_x >= 0.0 && orig_x < width as f32 && orig_y >= 0.0 && orig_y < height as f32 {
151                // Get the pixel value from the original image
152                let orig_pixel = img.get_pixel(orig_x as u32, orig_y as u32);
153
154                // Set the corresponding pixel in the rotated image
155                *pixel = Rgba([orig_pixel[0], orig_pixel[1], orig_pixel[2], orig_pixel[3]]);
156            }
157        }
158
159        rotated_img
160    }
161
162
163    pub fn cut_area(img: ImageBuffer<Rgba<u8>, Vec<u8>>, x: u32, y: u32, width: u32, height: u32) -> Option<RgbaImage> {
164        let sub_image = img.view(x, y, width, height);
165        let mut cut_image = RgbaImage::new(width, height);
166        for (x, y, pixel) in sub_image.pixels() {
167            cut_image.put_pixel(x, y, pixel);
168        }
169        Some(cut_image)
170    }
171    
172    pub fn convert_to_ico(
173        png_path: &str,
174        ico_path: &str,
175    ) -> Result<(), Box<dyn std::error::Error>> {
176        use std::fs::write;
177        use std::fs::File;
178        use std::io::Write;
179        // Create a new, empty icon collection:
180        let mut icon_dir = ico::IconDir::new(ico::ResourceType::Icon);
181        // Read a PNG file from disk and add it to the collection:
182        let file = std::fs::File::open(png_path).unwrap();
183        let image = ico::IconImage::read_png(file).unwrap();
184        icon_dir.add_entry(ico::IconDirEntry::encode(&image).unwrap());
185        let file = std::fs::File::create(ico_path).unwrap();
186        icon_dir.write(file).unwrap();
187        Ok(())
188    }
189}
190#[cfg(feature = "images")]
191pub use images::*;