mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
anime: gif-image
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
use std::{env, fs::File, path::Path, thread::sleep, time::Duration};
|
use std::{env, path::Path, thread::sleep};
|
||||||
|
|
||||||
use rog_anime::AniMeSequence;
|
use rog_anime::AniMeSequence;
|
||||||
use rog_dbus::AuraDbusClient;
|
use rog_dbus::AuraDbusClient;
|
||||||
|
|||||||
29
asusctl/examples/animatrix-png-gif.rs
Normal file
29
asusctl/examples/animatrix-png-gif.rs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
use std::{env, path::Path, thread::sleep};
|
||||||
|
|
||||||
|
use rog_anime::AniMeSequence;
|
||||||
|
use rog_dbus::AuraDbusClient;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let (client, _) = AuraDbusClient::new().unwrap();
|
||||||
|
|
||||||
|
let args: Vec<String> = env::args().into_iter().collect();
|
||||||
|
if args.len() != 3 {
|
||||||
|
println!("Please supply filepath and brightness");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let path = Path::new(&args[1]);
|
||||||
|
let brightness = args[2].parse::<f32>().unwrap();
|
||||||
|
let gif = AniMeSequence::png_gif(path, brightness).unwrap();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
for frame in gif.get_animation().unwrap().frames() {
|
||||||
|
client
|
||||||
|
.proxies()
|
||||||
|
.anime()
|
||||||
|
.write(frame.frame().clone())
|
||||||
|
.unwrap();
|
||||||
|
sleep(frame.delay());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use std::{fs::File, path::Path, time::Duration};
|
use std::{fs::File, path::Path, time::Duration};
|
||||||
|
use glam::Vec2;
|
||||||
|
|
||||||
use crate::{error::AnimeError, AniMeDataBuffer, AniMeDiagonal};
|
use crate::{AniMeDataBuffer, AniMeDiagonal, AniMeImage, error::AnimeError, Pixel};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||||
pub struct AniMeFrame {
|
pub struct AniMeFrame {
|
||||||
@@ -25,7 +26,7 @@ impl AniMeFrame {
|
|||||||
pub struct AniMeGif(Vec<AniMeFrame>);
|
pub struct AniMeGif(Vec<AniMeFrame>);
|
||||||
|
|
||||||
impl AniMeGif {
|
impl AniMeGif {
|
||||||
pub fn new(file_name: &Path, brightness: f32) -> Result<Self, AnimeError> {
|
pub fn create_diagonal_gif(file_name: &Path, brightness: f32) -> Result<Self, AnimeError> {
|
||||||
let mut frames = Vec::new();
|
let mut frames = Vec::new();
|
||||||
let mut matrix = AniMeDiagonal::new();
|
let mut matrix = AniMeDiagonal::new();
|
||||||
|
|
||||||
@@ -57,6 +58,47 @@ impl AniMeGif {
|
|||||||
Ok(Self(frames))
|
Ok(Self(frames))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn create_png_gif(file_name: &Path, brightness: f32) -> Result<Self, AnimeError> {
|
||||||
|
let mut frames = Vec::new();
|
||||||
|
|
||||||
|
let mut decoder = gif::DecodeOptions::new();
|
||||||
|
// Configure the decoder such that it will expand the image to RGBA.
|
||||||
|
decoder.set_color_output(gif::ColorOutput::RGBA);
|
||||||
|
// Read the file header
|
||||||
|
let file = File::open(file_name)?;
|
||||||
|
let mut decoder = decoder.read_info(file)?;
|
||||||
|
|
||||||
|
let width = decoder.width();
|
||||||
|
let pixels: Vec<Pixel> = vec![Pixel::default(); (decoder.width() as u32 * decoder.height() as u32) as usize];
|
||||||
|
let mut image = AniMeImage::new(Vec2::new(1.0, 1.0), 0.0, Vec2::new(0.0, 0.0),
|
||||||
|
brightness, pixels, decoder.width() as u32);
|
||||||
|
|
||||||
|
while let Some(frame) = decoder.read_next_frame()? {
|
||||||
|
let wait = frame.delay * 10;
|
||||||
|
for (y, row) in frame.buffer.chunks(frame.width as usize * 4).enumerate() {
|
||||||
|
for (x, px) in row.chunks(4).enumerate() {
|
||||||
|
if px[3] != 255 {
|
||||||
|
// should be t but not in some gifs? What, ASUS, what?
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let pos = (x + frame.left as usize) + ((y + frame.top as usize) * width as usize);
|
||||||
|
image.get_mut()[pos] =
|
||||||
|
Pixel {
|
||||||
|
color: ((px[0] as u32 + px[1] as u32 + px[2] as u32) / 3),
|
||||||
|
alpha: 1.0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
image.update();
|
||||||
|
|
||||||
|
frames.push(AniMeFrame {
|
||||||
|
data: <AniMeDataBuffer>::from(&image),
|
||||||
|
delay: Duration::from_millis(wait as u64),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Ok(Self(frames))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn frames(&self) -> &[AniMeFrame] {
|
pub fn frames(&self) -> &[AniMeFrame] {
|
||||||
&self.0
|
&self.0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ use crate::{
|
|||||||
const LED_PIXEL_LEN: usize = 1244;
|
const LED_PIXEL_LEN: usize = 1244;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Default)]
|
#[derive(Copy, Clone, Debug, Default)]
|
||||||
struct Pixel {
|
pub(crate) struct Pixel {
|
||||||
color: u32,
|
pub color: u32,
|
||||||
alpha: f32,
|
pub alpha: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A single LED position and brightness. The intention of this struct
|
/// A single LED position and brightness. The intention of this struct
|
||||||
@@ -64,7 +64,7 @@ pub struct AniMeImage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AniMeImage {
|
impl AniMeImage {
|
||||||
const fn new(
|
pub(crate) const fn new(
|
||||||
scale: Vec2,
|
scale: Vec2,
|
||||||
angle: f32,
|
angle: f32,
|
||||||
translation: Vec2,
|
translation: Vec2,
|
||||||
@@ -131,6 +131,10 @@ impl AniMeImage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn get_mut(&mut self) -> &mut [Pixel] {
|
||||||
|
&mut self.img_pixels
|
||||||
|
}
|
||||||
|
|
||||||
/// Really only used to generate the output for including as a full const in `LED_IMAGE_POSITIONS`
|
/// Really only used to generate the output for including as a full const in `LED_IMAGE_POSITIONS`
|
||||||
pub fn generate() -> Vec<Option<Led>> {
|
pub fn generate() -> Vec<Option<Led>> {
|
||||||
(0..AniMeImage::height())
|
(0..AniMeImage::height())
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ pub enum AniMeSequence {
|
|||||||
|
|
||||||
impl AniMeSequence {
|
impl AniMeSequence {
|
||||||
pub fn gif(file: &Path, brightness: f32) -> Result<Self, AnimeError> {
|
pub fn gif(file: &Path, brightness: f32) -> Result<Self, AnimeError> {
|
||||||
let frames = AniMeGif::new(file, brightness)?;
|
let frames = AniMeGif::create_diagonal_gif(file, brightness)?;
|
||||||
Ok(Self::Animation(frames))
|
Ok(Self::Animation(frames))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,6 +55,15 @@ impl AniMeSequence {
|
|||||||
Ok(Self::Image(Box::new(data)))
|
Ok(Self::Image(Box::new(data)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn png_gif(file: &Path,
|
||||||
|
// scale: Vec2,
|
||||||
|
// angle: f32,
|
||||||
|
// translation: Vec2,
|
||||||
|
brightness: f32,) -> Result<Self, AnimeError> {
|
||||||
|
let frames = AniMeGif::create_png_gif(file, brightness)?;
|
||||||
|
Ok(Self::Animation(frames))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_animation(&self) -> Option<&AniMeGif> {
|
pub fn get_animation(&self) -> Option<&AniMeGif> {
|
||||||
match self {
|
match self {
|
||||||
AniMeSequence::Animation(anim) => Some(anim),
|
AniMeSequence::Animation(anim) => Some(anim),
|
||||||
|
|||||||
Reference in New Issue
Block a user