Skip to content

Instantly share code, notes, and snippets.

@Goganoid
Last active October 5, 2021 06:01
Show Gist options
  • Select an option

  • Save Goganoid/c330360e259c5b306601a1b6466a45c1 to your computer and use it in GitHub Desktop.

Select an option

Save Goganoid/c330360e259c5b306601a1b6466a45c1 to your computer and use it in GitHub Desktop.
Doom on Zephyrus G14 Anime Matrix
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(())
}
@Goganoid
Copy link
Author

Goganoid commented Oct 4, 2021

Yeah, I'm a bad programmer

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment