stitchy_core/files/
mod.rs

1pub mod builder;
2
3#[cfg(unix)]
4pub mod fd;
5
6pub mod image_types;
7pub mod path;
8pub mod raw;
9pub mod util;
10
11use image::{
12    codecs::{jpeg::JpegDecoder, webp::WebPDecoder},
13    metadata::Orientation,
14    DynamicImage, ImageDecoder, ImageError, ImageFormat,
15};
16use std::io::{BufRead, Seek};
17use std::time::SystemTime;
18
19/// Representation of a file's location.
20pub trait FileLocation<P: FileProperties> {
21    fn is_file(&self) -> Result<bool, String>;
22    fn extension(&self) -> Result<String, String>;
23    fn into_properties(self) -> Result<P, String>;
24}
25
26/// Functions to get useful properties of files.
27/// Implementers of this trait are representations of files. The files are not necessarily required to be open, or to
28/// have been opened or read.
29pub trait FileProperties {
30    fn infer_format(&self) -> Option<ImageFormat>;
31    fn into_image_contents(self, print_info: bool) -> Result<DynamicImage, String>;
32    fn file_size(&self) -> u64;
33    fn modify_time(&self) -> SystemTime;
34    fn full_path(&self) -> Option<&String>;
35    fn orientation(&self) -> Result<Orientation, String>;
36
37    fn decode_orientation<R: BufRead + Seek>(&self, source: R) -> Result<Orientation, String> {
38        let format = match self.infer_format() {
39            Some(format) => format,
40            None => {
41                return Ok(Orientation::NoTransforms);
42            }
43        };
44
45        let full_path_label = match self.full_path() {
46            Some(string) => string.as_str(),
47            None => "(path unknown)",
48        };
49
50        match format {
51            ImageFormat::Jpeg => {
52                Self::decode_orientation_from_codec(full_path_label, JpegDecoder::new(source))
53            }
54            ImageFormat::WebP => {
55                Self::decode_orientation_from_codec(full_path_label, WebPDecoder::new(source))
56            }
57            _ => Ok(Orientation::NoTransforms),
58        }
59    }
60
61    fn decode_orientation_from_codec<T: ImageDecoder>(
62        full_path_label: &str,
63        decoder_result: Result<T, ImageError>,
64    ) -> Result<Orientation, String> {
65        let mut decoder =
66            decoder_result.map_err(|e| format!("Error decoding {}: {:?}", full_path_label, e))?;
67        let orientation = decoder
68            .orientation()
69            .map_err(|e| format!("Cannot decode metadata in {}: {:?}", full_path_label, e))?;
70        Ok(orientation)
71    }
72}