mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
Basic fade in/out of gifs
This commit is contained in:
@@ -31,10 +31,12 @@ impl AnimeFrame {
|
||||
pub enum AnimTime {
|
||||
/// Time in milliseconds for animation to run
|
||||
Time(Duration),
|
||||
/// How many full animation loops to run
|
||||
Cycles(u32),
|
||||
/// How many full animation loops to run or how many seconds if image is static
|
||||
Count(u32),
|
||||
/// Run for infinite time
|
||||
Infinite,
|
||||
/// Fade in, play for, fade out
|
||||
Fade(Fade),
|
||||
}
|
||||
|
||||
impl Default for AnimTime {
|
||||
@@ -44,6 +46,40 @@ impl Default for AnimTime {
|
||||
}
|
||||
}
|
||||
|
||||
/// Fancy brightness control: fade in/out, show at brightness for n time
|
||||
#[derive(Debug, Copy, Clone, Deserialize, Serialize)]
|
||||
pub struct Fade {
|
||||
fade_in: Duration,
|
||||
show_for: Option<Duration>,
|
||||
fade_out: Duration,
|
||||
}
|
||||
|
||||
impl Fade {
|
||||
pub fn new(fade_in: Duration, show_for: Option<Duration>, fade_out: Duration) -> Self {
|
||||
Self {
|
||||
fade_in,
|
||||
show_for,
|
||||
fade_out,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fade_in(&self) -> Duration {
|
||||
self.fade_in
|
||||
}
|
||||
|
||||
pub fn show_for(&self) -> Option<Duration> {
|
||||
self.show_for
|
||||
}
|
||||
|
||||
pub fn fade_out(&self) -> Duration {
|
||||
self.fade_out
|
||||
}
|
||||
|
||||
pub fn total_fade_time(&self) -> Duration {
|
||||
self.fade_in + self.fade_out
|
||||
}
|
||||
}
|
||||
|
||||
/// A gif animation. This is a collection of frames from the gif, and a duration
|
||||
/// that the animation should be shown for.
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
@@ -67,6 +103,7 @@ impl AnimeGif {
|
||||
let mut decoder = decoder.read_info(file)?;
|
||||
|
||||
let mut frames = Vec::with_capacity(decoder.buffer_size());
|
||||
|
||||
while let Some(frame) = decoder.read_next_frame()? {
|
||||
let wait = frame.delay * 10;
|
||||
if matches!(frame.dispose, gif::DisposalMethod::Background) {
|
||||
@@ -162,6 +199,39 @@ impl AnimeGif {
|
||||
Ok(Self(frames, duration))
|
||||
}
|
||||
|
||||
/// Make a static gif out of a greyscale png. If no duration is specified then the default
|
||||
/// will be 1 second long. If `AnimTime::Cycles` is specified for `duration` then this can
|
||||
/// be considered how many seconds the image will show for.
|
||||
#[inline]
|
||||
pub fn create_png_static(
|
||||
file_name: &Path,
|
||||
scale: f32,
|
||||
angle: f32,
|
||||
translation: Vec2,
|
||||
duration: AnimTime,
|
||||
brightness: f32,
|
||||
) -> Result<Self, AnimeError> {
|
||||
let image = AnimeImage::from_png(file_name, scale, angle, translation, brightness)?;
|
||||
|
||||
let mut total = Duration::from_millis(1000);
|
||||
if let AnimTime::Fade(fade) = duration {
|
||||
total = fade.total_fade_time();
|
||||
if let Some(middle) = fade.show_for {
|
||||
total += middle;
|
||||
}
|
||||
}
|
||||
// Make frame delay 30ms, and find frame count
|
||||
let frame_count = total.as_millis() / 30;
|
||||
|
||||
let single = AnimeFrame {
|
||||
data: <AnimeDataBuffer>::from(&image),
|
||||
delay: Duration::from_millis(30),
|
||||
};
|
||||
let frames = vec![single; frame_count as usize];
|
||||
|
||||
Ok(Self(frames, duration))
|
||||
}
|
||||
|
||||
/// Get a slice of the frames this gif has
|
||||
#[inline]
|
||||
pub fn frames(&self) -> &[AnimeFrame] {
|
||||
@@ -173,4 +243,16 @@ impl AnimeGif {
|
||||
pub fn duration(&self) -> AnimTime {
|
||||
self.1
|
||||
}
|
||||
|
||||
/// Get the frame count
|
||||
pub fn frame_count(&self) -> usize {
|
||||
self.0.len()
|
||||
}
|
||||
|
||||
/// Get total gif time for one run
|
||||
pub fn total_frame_time(&self) -> Duration {
|
||||
let mut time = 0;
|
||||
self.0.iter().for_each(|f| time += f.delay.as_millis());
|
||||
Duration::from_millis(time as u64)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user