cursive_image/image/
jpeg.rs1use super::{format::*, image::*, stream::*};
2
3use {
4 flate2::{read::*, *},
5 std::{
6 fs::*,
7 io::{self, Read},
8 path::*,
9 },
10 zune_jpeg::{
11 zune_core::{colorspace::*, options::*},
12 *,
13 },
14};
15
16impl Image {
17 pub fn new_owned_from_jpeg_file<PathT>(path: PathT, format: ImageFormat, compress: bool) -> io::Result<Self>
19 where
20 PathT: AsRef<Path>,
21 {
22 let mut decoder = open_jpeg(path, format)?;
23 let data = decoder.decode().map_err(io::Error::other)?;
24 let info = decoder.info().ok_or_else(|| io::Error::other("missing JPEG info"))?;
25
26 let data = if compress {
28 let mut compressed = Vec::default();
29 zlib(io::Cursor::new(data)).read_to_end(&mut compressed)?;
30 compressed
31 } else {
32 data
33 };
34
35 Ok(Self::new_owned(data, compress, format, (info.width, info.height)))
36 }
37
38 pub fn new_stream_from_jpeg_file<PathT>(path: PathT, format: ImageFormat) -> io::Result<Self>
40 where
41 PathT: AsRef<Path>,
42 {
43 let mut decoder = open_jpeg(path.as_ref(), format)?;
44 decoder.decode_headers().map_err(io::Error::other)?; let info = decoder.info().ok_or_else(|| io::Error::other("missing JPEG info"))?;
46
47 Ok(Self::new_stream(JpegImageStream::new(path.as_ref().into(), format), format, (info.width, info.height)))
48 }
49}
50
51struct JpegImageStream {
56 path: PathBuf,
57 format: ImageFormat,
58}
59
60impl JpegImageStream {
61 fn new(path: PathBuf, format: ImageFormat) -> Self {
62 Self { path, format }
63 }
64}
65
66impl ImageStream for JpegImageStream {
67 fn open(&self) -> io::Result<(Box<dyn io::Read>, bool)> {
68 let mut decoder = open_jpeg(&self.path, self.format)?;
69
70 let data = decoder.decode().map_err(io::Error::other)?;
72 let reader = io::Cursor::new(data);
73
74 Ok((Box::new(reader), false))
75 }
76}
77
78fn open_jpeg<PathT>(path: PathT, format: ImageFormat) -> io::Result<JpegDecoder<io::BufReader<File>>>
81where
82 PathT: AsRef<Path>,
83{
84 let options = DecoderOptions::new_fast().jpeg_set_out_colorspace(match format {
85 ImageFormat::PNG => return Err(io::Error::other("unsupported format")),
86 ImageFormat::RGB => ColorSpace::RGB,
87 ImageFormat::RGBA => ColorSpace::RGBA,
88 });
89
90 Ok(JpegDecoder::new_with_options(io::BufReader::new(File::open(path)?), options))
91}
92
93fn zlib<ReadT>(reader: ReadT) -> ZlibEncoder<ReadT>
94where
95 ReadT: io::Read,
96{
97 ZlibEncoder::new(reader, Compression::default())
98}