Last active
October 5, 2021 06:01
-
-
Save Goganoid/c330360e259c5b306601a1b6466a45c1 to your computer and use it in GitHub Desktop.
Doom on Zephyrus G14 Anime Matrix
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| use std::error::Error; | |
| use captrs::*; | |
| use std::time::{Duration, Instant}; | |
| use std::thread::sleep; | |
| use std::sync::mpsc::{Sender, Receiver}; | |
| use std::sync::mpsc; | |
| // clone https://gitlab.com/asus-linux/asusctl into this project, because some crate are not present on crates.io | |
| use rog_anime::{AnimeDataBuffer, {AnimeImage, Vec2}, ANIME_DATA_LEN, Pixel}; | |
| use rog_dbus::RogDbusClient; | |
| const MAX_FRAMERATE:u64=(1000/30) as u64; | |
| const X:u32 = 320; | |
| const Y:u32 = 200; | |
| struct Screen{ | |
| w: u32, | |
| h:u32, | |
| } | |
| impl Screen{ | |
| pub fn new(w:u32,h:u32) -> Self{ | |
| Screen{ | |
| w,h | |
| } | |
| } | |
| // get pixel position in vector | |
| pub fn pixel_pos(&self,x:u32,y:u32) -> usize{ | |
| (y*self.w + x) as usize | |
| } | |
| // get rectangle | |
| pub fn selection<'a>(&self,pixels:&'a Vec<Bgr8>,min_x:u32,min_y:u32,max_x:u32,max_y:u32)->Vec<&'a Bgr8>{ | |
| let mut selection = Vec::<&Bgr8>::new(); | |
| for y in min_y..max_y{ | |
| selection.extend(pixels[self.pixel_pos(min_x,y)..self.pixel_pos(max_x,y)].iter().map(|el|el)); | |
| } | |
| selection | |
| } | |
| } | |
| fn main() ->Result<(), Box<dyn Error>> { | |
| let mut capturer = Capturer::new(0).unwrap(); | |
| let (w, h) = capturer.geometry(); | |
| let screen_size = w*h; | |
| println!("{} | {}",w,h); | |
| let screen = Screen::new(w,h); | |
| // to catch stop signal | |
| let (tx, rx): (Sender<bool>, Receiver<bool>) = mpsc::channel(); | |
| let (client, _) = RogDbusClient::new().unwrap(); | |
| ctrlc::set_handler(move || { | |
| println!("received Ctrl+C!"); | |
| tx.send(true).unwrap(); | |
| }).expect("Could not send signal on channel."); | |
| // for controlling framerate | |
| let mut now = Instant::now(); | |
| let mut finish = Instant::now(); | |
| let mut image:Vec<Pixel> = Vec::new(); | |
| loop { | |
| let frame = capturer.capture_frame().unwrap(); | |
| // that's the weak part. I don't know how to capture the window so just place window at the down left corner of the screen | |
| let selection = screen.selection(&frame, 0, 1080-Y, X, 1080); | |
| let mut avg_bright = 0.0; | |
| for &Bgr8 { r, g, b, .. } in selection.clone().into_iter(){ | |
| let brightness = (0.375*r as f32+0.5*g as f32+0.125*b as f32)/10.0; | |
| avg_bright+=brightness; | |
| } | |
| avg_bright = avg_bright/screen_size as f32; | |
| for &Bgr8 { r, g, b, .. } in selection.into_iter() { | |
| let mut brightness = (0.375*r as f32+0.5*g as f32+0.125*b as f32)/10.0; | |
| let c = (0.299*r as f32+0.587*g as f32+0.114*b as f32).trunc() as u32; | |
| // some magic numbers that create contrast | |
| // if bright location | |
| if avg_bright>0.16 | |
| { | |
| // if very bright | |
| if avg_bright>0.21 { | |
| // make dark pixels even more darker | |
| if brightness < 7.0{ | |
| brightness = brightness / 15.0; | |
| } | |
| } | |
| else{ | |
| if brightness < 5.0 { | |
| brightness = brightness / 10.0; | |
| } | |
| } | |
| } | |
| // if dark location | |
| else if avg_bright<0.9 { | |
| if c<40{ | |
| brightness = brightness/10.0; | |
| } | |
| } | |
| // for every other location | |
| else if c<40{ | |
| brightness = brightness/12.0; | |
| } | |
| // to make bright pixels little less brighter | |
| if brightness>8.0{ | |
| brightness = brightness/4.0; | |
| } | |
| image.push(Pixel{color:c,alpha:brightness}); | |
| } | |
| let mut anime_image = AnimeImage::new( | |
| Vec2::new(0.8, 0.8),0.0,Vec2::new(0.0, 0.0),1.0,image.clone(),285); | |
| anime_image.update(); | |
| client | |
| .proxies() | |
| .anime() | |
| .write(<AnimeDataBuffer>::from(&anime_image)) | |
| .unwrap(); | |
| if let Ok(_) = rx.try_recv(){ | |
| //clear the screen | |
| client.proxies().anime().write(<AnimeDataBuffer>::from_vec(vec![0;ANIME_DATA_LEN])).unwrap(); | |
| break; | |
| } | |
| image.clear(); | |
| now = Instant::now(); | |
| let delta = now - finish; | |
| finish = now; | |
| if delta.as_millis()<MAX_FRAMERATE as u128 { | |
| sleep(Duration::from_millis(MAX_FRAMERATE) - delta); | |
| } | |
| } | |
| Ok(()) | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Yeah, I'm a bad programmer