From bf0ea88f01147858545c89d58e9fe78ac0746448 Mon Sep 17 00:00:00 2001 From: Ghoul Date: Thu, 22 Jan 2026 21:29:36 +0500 Subject: [PATCH] feat: add full custom image and gif support for G835L --- rog-anime/src/image.rs | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/rog-anime/src/image.rs b/rog-anime/src/image.rs index da791530..d2ad5517 100644 --- a/rog-anime/src/image.rs +++ b/rog-anime/src/image.rs @@ -276,8 +276,8 @@ impl AnimeImage { // 33.0 = Longest row LED count (physical) plus half-pixel offset AnimeType::GA401 => (33.0 + 0.5) * Self::scale_x(anime_type), AnimeType::GU604 => (38.0 + 0.5) * Self::scale_x(anime_type), - // G835L: max 15 LEDs wide + rectangle shift (~20 pixels) + stagger - AnimeType::G835L => (35.0 + 0.5) * Self::scale_x(anime_type), + // G835L: max X span is 33.5 LEDs (-0.5..33.0) + AnimeType::G835L => (33.0 + 0.5) * Self::scale_x(anime_type), _ => (35.0 + 0.5) * Self::scale_x(anime_type), } } @@ -448,13 +448,35 @@ impl AnimeImage { let transform = Mat3::from_scale_angle_translation(self.scale, self.angle, self.translation); - let pos_in_leds = Mat3::from_translation(Vec2::new(20.0, 20.0)); + let pos_in_leds = Mat3::from_translation(self.led_center()); // Get LED-to-image coords let led_from_px = pos_in_leds * led_from_cm * transform * cm_from_px * center; led_from_px.inverse() } + fn led_center(&self) -> Vec2 { + if self.anime_type != AnimeType::G835L { + return Vec2::new(20.0, 20.0); + } + + let mut min = Vec2::splat(f32::INFINITY); + let mut max = Vec2::splat(f32::NEG_INFINITY); + for led in self.led_pos.iter().flatten() { + let pos = Vec2::new(led.x(), led.y()); + min = min.min(pos); + max = max.max(pos); + } + + if min.x.is_finite() { + let mut center = (min + max) * 0.5; + center.y += 1.0; + center + } else { + Vec2::new(20.0, 20.0) + } + } + /// Generate the base image from inputs. The result can be displayed as is /// or updated via scale, position, or angle then displayed again after /// `update()`.