cursive_image/image/compatibility/
jpeg.rs1use super::{
2 super::{format::*, image::*, stream::*},
3 zlib::*,
4};
5
6use {
7 cursive::*,
8 std::{fs::*, io, path::*},
9 zune_jpeg::{
10 zune_core::{colorspace::*, options::*},
11 *,
12 },
13};
14
15impl Image {
16 pub fn new_owned_from_jpeg_file<PathT>(path: PathT, format: ImageFormat, compress: bool) -> io::Result<Self>
20 where
21 PathT: AsRef<Path>,
22 {
23 let (data, size) = read_jpeg(path, format, true)?;
24 let data = if compress { zlib(&data)? } else { data };
25 Ok(Self::new_owned(data, compress, format, size))
26 }
27
28 pub fn new_stream_from_jpeg_file<PathT>(path: PathT, format: ImageFormat) -> io::Result<Self>
32 where
33 PathT: AsRef<Path>,
34 {
35 let path = path.as_ref();
36 let mut decoder = open_jpeg(path, format)?;
37 decoder.decode_headers().map_err(io::Error::other)?; let info = decoder.info().ok_or_else(|| io::Error::other("missing JPEG info"))?;
39 let stream = JpegImageStream::new(path.into(), format);
40 Ok(Self::new_stream(stream, format, (info.width, info.height)))
41 }
42}
43
44struct JpegImageStream {
49 path: PathBuf,
50 format: ImageFormat,
51}
52
53impl JpegImageStream {
54 fn new(path: PathBuf, format: ImageFormat) -> Self {
55 Self { path, format }
56 }
57}
58
59impl ImageStream for JpegImageStream {
60 fn open(&self) -> io::Result<(Box<dyn io::Read>, bool)> {
61 let (data, _size) = read_jpeg(&self.path, self.format, false)?;
63 Ok((Box::new(io::Cursor::new(data)), false))
64 }
65}
66
67fn read_jpeg<PathT>(path: PathT, format: ImageFormat, with_size: bool) -> io::Result<(Vec<u8>, Vec2)>
70where
71 PathT: AsRef<Path>,
72{
73 let mut decoder = open_jpeg(path, format)?;
74 let data = decoder.decode().map_err(io::Error::other)?;
75 let size = if with_size {
76 let info = decoder.info().ok_or_else(|| io::Error::other("missing JPEG info"))?; (info.width, info.height).into()
78 } else {
79 Default::default()
80 };
81 Ok((data, size))
82}
83
84fn open_jpeg<PathT>(path: PathT, format: ImageFormat) -> io::Result<JpegDecoder<io::BufReader<File>>>
85where
86 PathT: AsRef<Path>,
87{
88 let options = DecoderOptions::new_fast().jpeg_set_out_colorspace(match format {
89 ImageFormat::RGB => ColorSpace::RGB,
90 ImageFormat::RGBA => ColorSpace::RGBA,
91 _ => return Err(io::Error::other("unsupported format")),
92 });
93
94 Ok(JpegDecoder::new_with_options(io::BufReader::new(File::open(path)?), options))
95}