From 321bc2623d197bd11da51c1080c2677c6e0f22c7 Mon Sep 17 00:00:00 2001 From: seerge Date: Sun, 5 Mar 2023 23:14:48 +0100 Subject: [PATCH] Added support for animated GIF in animatrix --- AnimeMatrix/AnimeMatrixDevice.cs | 67 ++++++++++++++++++++++- Aura.cs | 4 +- GHelper.csproj | 2 +- Keyboard.cs | 1 + Program.cs | 3 + Settings.cs | 94 +++++++++++++++++--------------- 6 files changed, 122 insertions(+), 49 deletions(-) diff --git a/AnimeMatrix/AnimeMatrixDevice.cs b/AnimeMatrix/AnimeMatrixDevice.cs index f6f6c6e2..def8fed6 100644 --- a/AnimeMatrix/AnimeMatrixDevice.cs +++ b/AnimeMatrix/AnimeMatrixDevice.cs @@ -1,5 +1,6 @@ // Source thanks to https://github.com/vddCore/Starlight :) +using System.Diagnostics; using System.Text; using Starlight.Communication; @@ -71,13 +72,40 @@ namespace Starlight.AnimeMatrix public int LedCount => 1450; public int Rows => 61; - private readonly byte[] _displayBuffer = new byte[UpdatePageLength * 3]; + private byte[] _displayBuffer = new byte[UpdatePageLength * 3]; + private List frames = new List(); + + private int frameIndex = 0; public AnimeMatrixDevice() : base(0x0B05, 0x193B, 640) { } - + + public byte[] GetBuffer() + { + return _displayBuffer; + } + + public void PresentNextFrame() + { + if (frameIndex >= frames.Count) frameIndex = 0; + _displayBuffer = frames[frameIndex]; + Present(); + frameIndex++; + } + + public void ClearFrames() + { + frames.Clear(); + frameIndex = 0; + } + + public void AddFrame() + { + frames.Add(_displayBuffer.ToArray()); + } + public void SendRaw(params byte[] data) { Set(Packet(data)); @@ -208,6 +236,41 @@ namespace Starlight.AnimeMatrix SetBuiltInAnimation(enable); Set(Packet(0xC5, animation.AsByte)); } + + public void GenerateFrame(Image image) + { + + int width = 34 * 3; + int height = 61; + float scale; + + Bitmap canvas = new Bitmap(width, height); + + scale = Math.Min((float)width / (float)image.Width, (float)height / (float)image.Height); + + var graph = Graphics.FromImage(canvas); + var scaleWidth = (int)(image.Width * scale); + var scaleHeight = (int)(image.Height * scale); + + graph.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High; + graph.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; + graph.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; + + graph.DrawImage(image, ((int)width - scaleWidth), ((int)height - scaleHeight) / 2, scaleWidth, scaleHeight); + + Bitmap bmp = new Bitmap(canvas, 34, 61); + + for (int y = 0; y < bmp.Height; y++) + { + for (int x = 0; x < bmp.Width; x++) + { + var pixel = bmp.GetPixel(x, y); + byte color = (byte)((pixel.R + pixel.G + pixel.B) / 3); + SetLedPlanar(x, y, color); + } + } + + } private void EnsureRowInRange(int row) { diff --git a/Aura.cs b/Aura.cs index 29307663..9cab2214 100644 --- a/Aura.cs +++ b/Aura.cs @@ -3,8 +3,8 @@ public class Aura { - static byte[] MESSAGE_SET = { 0x5d, 0xb5 }; - static byte[] MESSAGE_APPLY = { 0x5d, 0xb4 }; + static byte[] MESSAGE_SET = { 0x5d, 0xb5, 0,0,0 }; + static byte[] MESSAGE_APPLY = { 0x5d, 0xb4}; public const int Static = 0; public const int Breathe = 1; diff --git a/GHelper.csproj b/GHelper.csproj index f76c71d7..bf601842 100644 --- a/GHelper.csproj +++ b/GHelper.csproj @@ -15,7 +15,7 @@ GHelper x64 False - 0.15.1 + 0.16 True diff --git a/Keyboard.cs b/Keyboard.cs index 1b57bab3..02ee24b9 100644 --- a/Keyboard.cs +++ b/Keyboard.cs @@ -10,6 +10,7 @@ {"screenshot", "Screenshot"}, {"play", "Play/Pause"}, {"aura", "Aura"}, + {"ghelper", "Open GHelper"}, {"custom", "Custom"} }; diff --git a/Program.cs b/Program.cs index ca8bb67d..6d661236 100644 --- a/Program.cs +++ b/Program.cs @@ -159,6 +159,9 @@ namespace GHelper case "performance": settingsForm.BeginInvoke(settingsForm.CyclePerformanceMode); break; + case "ghelper": + settingsForm.BeginInvoke(SettingsToggle); + break; case "custom": CustomKey(name); break; diff --git a/Settings.cs b/Settings.cs index 4036b1b8..9c0bcb8a 100644 --- a/Settings.cs +++ b/Settings.cs @@ -5,6 +5,8 @@ using System.Timers; using System.Drawing.Imaging; using System.CodeDom.Compiler; using System.Drawing; +using System; +using System.Globalization; namespace GHelper { @@ -21,11 +23,15 @@ namespace GHelper static System.Timers.Timer aTimer = default!; + static System.Timers.Timer matrixTimer = default!; + public string perfName = "Balanced"; Fans fans; Keyboard keyb; + AnimeMatrixDevice mat = new AnimeMatrixDevice(); + public SettingsForm() { @@ -98,54 +104,54 @@ namespace GHelper void SetMatrixPicture(string fileName) { - int width = 34 * 3; - int height = 61; - float scale; - - Bitmap image; + Image image; try { - using (var bmpTemp = (Bitmap)Image.FromFile(fileName)) + using (var fs = new FileStream(fileName, FileMode.Open)) { - image = new Bitmap(bmpTemp); - - Bitmap canvas = new Bitmap(width, height); - - scale = Math.Min((float)width / (float)image.Width, (float)height / (float)image.Height); - - var graph = Graphics.FromImage(canvas); - var scaleWidth = (int)(image.Width * scale); - var scaleHeight = (int)(image.Height * scale); - - graph.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High; - graph.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; - graph.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; - - graph.DrawImage(image, ((int)width - scaleWidth), ((int)height - scaleHeight) / 2, scaleWidth, scaleHeight); - - Bitmap bmp = new Bitmap(canvas, 34, 61); - - var mat = new AnimeMatrixDevice(); - mat.SetBuiltInAnimation(false); - - for (int y = 0; y < bmp.Height; y++) - { - for (int x = 0; x < bmp.Width; x++) - { - var pixel = bmp.GetPixel(x, y); - byte color = (byte)((pixel.R + pixel.G + pixel.B) / 3); - mat.SetLedPlanar(x, y, color); - } - } - - mat.Present(); - mat.Dispose(); + var ms = new MemoryStream(); + fs.CopyTo(ms); + ms.Position = 0; + image = Image.FromStream(ms); } - } - catch + } catch { Debug.WriteLine("Error loading picture"); + return; + } + + mat.SetBuiltInAnimation(false); + mat.ClearFrames(); + + FrameDimension dimension = new FrameDimension(image.FrameDimensionsList[0]); + int frameCount = image.GetFrameCount(dimension); + + if (frameCount > 1) + { + for (int i = 0; i < frameCount; i++) + { + image.SelectActiveFrame(dimension, i); + mat.GenerateFrame(image); + mat.AddFrame(); + } + + matrixTimer = new System.Timers.Timer(50); + matrixTimer.Enabled = true; + matrixTimer.Elapsed += delegate + { + mat.PresentNextFrame(); + }; + } else + { + if (matrixTimer is not null) + { + matrixTimer.Enabled = false; + matrixTimer.Dispose(); + } + + mat.GenerateFrame(image); + mat.Present(); } @@ -157,7 +163,7 @@ namespace GHelper Thread t = new Thread((ThreadStart)(() => { OpenFileDialog of = new OpenFileDialog(); - of.Filter = "Image Files (*.bmp;*.jpg;*.jpeg,*.png)|*.BMP;*.JPG;*.JPEG;*.PNG"; + of.Filter = "Image Files (*.bmp;*.jpg;*.jpeg,*.png,*.gif)|*.BMP;*.JPG;*.JPEG;*.PNG;*.GIF"; if (of.ShowDialog() == DialogResult.OK) { Program.config.setConfig("matrix_picture", of.FileName); @@ -192,7 +198,7 @@ namespace GHelper int brightness = comboMatrix.SelectedIndex; int running = comboMatrixRunning.SelectedIndex; - var mat = new AnimeMatrixDevice(); + //var mat = new AnimeMatrixDevice(); BuiltInAnimation animation = new BuiltInAnimation( (BuiltInAnimation.Running)running, @@ -222,7 +228,7 @@ namespace GHelper } } - mat.Dispose(); + //mat.Dispose(); Program.config.setConfig("matrix_brightness", comboMatrix.SelectedIndex); Program.config.setConfig("matrix_running", comboMatrixRunning.SelectedIndex);