Skip to main content

rs_img2png/
lib.rs

1use std::io;
2
3use io::Cursor;
4use io::Seek;
5use io::Write;
6
7use io::Read;
8
9use image::DynamicImage;
10use image::ImageFormat;
11
12pub struct Image {
13    pub img: DynamicImage,
14}
15
16impl Image {
17    pub fn to_writer<W>(&self, mut wtr: W) -> Result<W, io::Error>
18    where
19        W: Write + Seek,
20    {
21        let fmt: ImageFormat = ImageFormat::Png;
22        self.img.write_to(&mut wtr, fmt).map_err(io::Error::other)?;
23        wtr.flush()?;
24        Ok(wtr)
25    }
26}
27
28impl Image {
29    pub fn from_bytes(bytes: &[u8], ifmt: Option<ImageFormat>) -> Result<Self, io::Error> {
30        match ifmt {
31            None => image::load_from_memory(bytes),
32            Some(f) => image::load_from_memory_with_format(bytes, f),
33        }
34        .map_err(io::Error::other)
35        .map(|img| Self { img })
36    }
37}
38
39impl Image {
40    pub fn from_reader<R>(rdr: R, limit: u64, ifmt: Option<ImageFormat>) -> Result<Self, io::Error>
41    where
42        R: Read,
43    {
44        let mut taken = rdr.take(limit);
45        let mut buf: Vec<u8> = vec![];
46        taken.read_to_end(&mut buf)?;
47        Self::from_bytes(&buf, ifmt)
48    }
49}
50
51pub const INPUT_BYTES_MAX: u64 = 16777216;
52
53impl Image {
54    pub fn stdin2stdout(limit: u64, ifmt: Option<ImageFormat>) -> Result<(), io::Error> {
55        let img: Self = Self::from_reader(io::stdin().lock(), limit, ifmt)?;
56        let buf: Vec<u8> = vec![];
57        let cur = Cursor::new(buf);
58        let wtr: Cursor<_> = img.to_writer(cur)?;
59        let buf: Vec<u8> = wtr.into_inner();
60        let o = io::stdout();
61        let mut ol = o.lock();
62        ol.write_all(&buf)?;
63        ol.flush()
64    }
65
66    pub fn stdin2stdout_default() -> Result<(), io::Error> {
67        Self::stdin2stdout(INPUT_BYTES_MAX, None)
68    }
69}
70
71pub fn str2image_format(s: &str) -> Option<ImageFormat> {
72    ImageFormat::from_extension(s)
73}
74
75#[cfg(test)]
76mod tests {
77    use super::*;
78
79    #[test]
80    fn test_str2image_format() {
81        assert_eq!(str2image_format("png"), Some(ImageFormat::Png));
82        assert_eq!(str2image_format("jpeg"), Some(ImageFormat::Jpeg));
83        assert_eq!(str2image_format("jpg"), Some(ImageFormat::Jpeg)); // common alias
84        assert_eq!(str2image_format("webp"), Some(ImageFormat::WebP));
85        assert_eq!(str2image_format("xyz"), None); // invalid extension
86        assert_eq!(str2image_format(""), None); // empty string
87    }
88}