cursive_image/image/compatibility/
gif.rs1use super::{
2 super::{format::*, image::*, stream::*},
3 zlib::*,
4};
5
6use {
7 cursive::*,
8 gif::*,
9 std::{fs::*, io, path::*},
10};
11
12impl Image {
13 pub fn new_owned_from_gif_file<PathT>(path: PathT, compress: bool) -> io::Result<Self>
17 where
18 PathT: AsRef<Path>,
19 {
20 let (data, size) = read_gif(path, true)?;
21 let data = if compress { zlib(&data)? } else { data };
22 Ok(Self::new_owned(data, compress, ImageFormat::RGBA, size))
23 }
24
25 pub fn new_stream_from_gif_file<PathT>(path: PathT) -> io::Result<Self>
29 where
30 PathT: AsRef<Path>,
31 {
32 let path = path.as_ref();
33 let decoder = open_gif(path)?;
34 let stream = GifImageStream::new(path.into());
35 Ok(Self::new_stream(stream, ImageFormat::RGBA, (decoder.width(), decoder.height())))
36 }
37}
38
39struct GifImageStream {
44 path: PathBuf,
45}
46
47impl GifImageStream {
48 fn new(path: PathBuf) -> Self {
49 Self { path }
50 }
51}
52
53impl ImageStream for GifImageStream {
54 fn open(&self) -> io::Result<(Box<dyn io::Read>, bool)> {
55 let (data, _size) = read_gif(&self.path, false)?;
57 Ok((Box::new(io::Cursor::new(data)), false))
58 }
59}
60
61fn read_gif<PathT>(path: PathT, size: bool) -> io::Result<(Vec<u8>, Vec2)>
64where
65 PathT: AsRef<Path>,
66{
67 let mut decoder = open_gif(path)?;
68 decoder.next_frame_info().map_err(io::Error::other)?.ok_or_else(|| io::Error::other("missing GIF frame"))?;
69 let mut data = vec![0; decoder.buffer_size()];
70 decoder.read_into_buffer(&mut data).map_err(io::Error::other)?;
71 let size = if size { (decoder.width(), decoder.height()).into() } else { Default::default() };
72 Ok((data, size))
73}
74
75fn open_gif<PathT>(path: PathT) -> io::Result<Decoder<File>>
76where
77 PathT: AsRef<Path>,
78{
79 let mut options = DecodeOptions::new();
80 options.set_color_output(ColorOutput::RGBA);
81 Ok(options.read_info(File::open(path)?).map_err(io::Error::other)?)
82}