Skip to content

Commit bd7dcbf

Browse files
authored
Merge pull request #3 from ModMaker101/dev
1.4.0
2 parents fc46881 + c3638a9 commit bd7dcbf

File tree

3 files changed

+83
-80
lines changed

3 files changed

+83
-80
lines changed

KeyLighting/CPUImageProcessor.cs

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
using Newtonsoft.Json;
1010
using OpenRGB.NET;
1111

12-
1312
public class CPUImageProcessor : IDisposable
1413
{
1514
private byte[]? pixelBuffer;
@@ -109,7 +108,6 @@ public OpenRGB.NET.Color[] ProcessImage(Bitmap image, int targetWidth, int targe
109108
{
110109
ProcessColumnsWithEffects(targetWidth, brightness, vibrance, contrast, darkThreshold, darkFactor);
111110

112-
// Apply fading only if fade speed is less than 1.0
113111
if (hasPreviousFrame && fadeSpeed < 1.0)
114112
{
115113
ApplyFading(targetWidth, fadeSpeed);
@@ -134,8 +132,6 @@ public OpenRGB.NET.Color[] ProcessImage(Bitmap image, int targetWidth, int targe
134132
}
135133
}
136134

137-
138-
139135
[MethodImpl(MethodImplOptions.AggressiveInlining)]
140136
private bool AreSettingsCached(double brightness, double contrast)
141137
{
@@ -179,8 +175,6 @@ private bool IsSolidColorFrame()
179175
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
180176
private void ApplyFading(int width, double fadeFactor)
181177
{
182-
// This method should only be called when fadeSpeed < 1.0
183-
// Simply use the provided fade factor without any brightness-based adjustments
184178

185179
Parallel.For(0, width, i => {
186180
resultBuffer[i] = FastBlendColors(previousFrame[i], resultBuffer[i], fadeFactor);
@@ -193,38 +187,33 @@ private OpenRGB.NET.Color FastBlendColors(OpenRGB.NET.Color color1, OpenRGB.NET.
193187
factor = Math.Clamp(factor, 0.0, 1.0);
194188
double inverseFactor = 1.0 - factor;
195189

196-
// Process each channel with adaptive blending
197190
byte r = (byte)(color1.R * inverseFactor + color2.R * factor);
198191
byte g = (byte)(color1.G * inverseFactor + color2.G * factor);
199192
byte b = (byte)(color1.B * inverseFactor + color2.B * factor);
200193

201194
return new OpenRGB.NET.Color(r, g, b);
202195
}
203196

204-
// Also modify ProcessSolidColor method to handle brightness transitions better
205197
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
206198
private void ProcessSolidColor(byte r, byte g, byte b, int width, double brightness, double vibrance, double contrast, int darkThreshold, double darkFactor)
207199
{
208200
OpenRGB.NET.Color processedColor = FastApplyEffects(r, g, b, brightness, vibrance, contrast, darkThreshold, darkFactor);
209201

210-
// Check if we need to apply fading
211202
bool needsFade = hasPreviousFrame &&
212-
fadeSpeed < 1.0 && // Only fade if fade speed is less than 1.0
203+
fadeSpeed < 1.0 &&
213204
!(lastFrameWasSolid &&
214205
lastSolidR == processedColor.R &&
215206
lastSolidG == processedColor.G &&
216207
lastSolidB == processedColor.B);
217208

218209
if (needsFade)
219210
{
220-
// Calculate brightness values for current and previous frame
211+
221212
int prevBrightness = lastSolidR + lastSolidG + lastSolidB;
222213
int newBrightness = processedColor.R + processedColor.G + processedColor.B;
223214

224-
// Determine if we're brightening or darkening
225-
double fadeFactor = fadeSpeed; // Use the configured fade speed
215+
double fadeFactor = fadeSpeed;
226216

227-
// Apply transition
228217
Parallel.For(0, width, i => {
229218
resultBuffer[i] = FastBlendColors(previousFrame[i], processedColor, fadeFactor);
230219
});

KeyLighting/Program.cs

Lines changed: 74 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.IO;
33
using System.Linq;
4+
using System.Text;
45
using System.Threading;
56
using System.Drawing;
67
using System.Drawing.Imaging;
@@ -12,6 +13,7 @@
1213
using System.Runtime.CompilerServices;
1314
using System.Runtime.InteropServices;
1415
using System.Numerics;
16+
using System.Text.Unicode;
1517

1618
namespace KeyboardLighting
1719
{
@@ -20,14 +22,12 @@ namespace KeyboardLighting
2022

2123
class Program
2224
{
23-
25+
static readonly byte[] debugBuffer = new byte[1024];
2426
static readonly object colorsLock = new object();
2527
static ORGBColor[]? prevColors;
2628
static DateTime lastUpdate = DateTime.MinValue;
2729
static DateTime lastDebugImageSave = DateTime.MinValue;
2830

29-
// Remove fade progress tracking
30-
// static float[] fadeProgress;
3131
static ORGBColor[] targetColors;
3232

3333
const int MIN_CAPTURE_INTERVAL_MS = 16;
@@ -75,7 +75,7 @@ static void Main(string[] args)
7575

7676
prevColors = new ORGBColor[ledCount];
7777
ledColorsBuffer = new ORGBColor[ledCount];
78-
// Removed fadeProgress
78+
7979
targetColors = new ORGBColor[ledCount];
8080

8181
var processor = new CPUImageProcessor(config);
@@ -183,7 +183,30 @@ static void ProcessFrame(ScreenCapturer capturer, CPUImageProcessor processor, O
183183

184184
if (config.DebugStringUpdates)
185185
{
186-
Console.WriteLine($"CPU colors: {string.Join(", ", columnColors.Take(5).Select(c => $"R{c.R},G{c.G},B{c.B}"))}");
186+
187+
var span = debugBuffer.AsSpan();
188+
bool success = false;
189+
int written = 0;
190+
191+
if (Utf8.TryWrite(span, $"CPU colors: ", out written))
192+
{
193+
span = span.Slice(written);
194+
for (int i = 0; i < Math.Min(5, columnColors.Length); i++)
195+
{
196+
var c = columnColors[i];
197+
if (i > 0 && Utf8.TryWrite(span, $", ", out int commaWritten))
198+
{
199+
span = span.Slice(commaWritten);
200+
}
201+
if (Utf8.TryWrite(span, $"R{c.R},G{c.G},B{c.B}", out int colorWritten))
202+
{
203+
span = span.Slice(colorWritten);
204+
written += colorWritten;
205+
}
206+
else break;
207+
}
208+
Console.WriteLine(Encoding.UTF8.GetString(debugBuffer, 0, debugBuffer.Length - span.Length));
209+
}
187210
}
188211

189212
UpdateLedColors(columnColors, config, ledCount);
@@ -192,7 +215,12 @@ static void ProcessFrame(ScreenCapturer capturer, CPUImageProcessor processor, O
192215

193216
if (config.DebugStringUpdates)
194217
{
195-
Console.WriteLine($"Updated LEDs, first LED: R{ledColorsBuffer[0].R} G{ledColorsBuffer[0].G} B{ledColorsBuffer[0].B}");
218+
219+
var span = debugBuffer.AsSpan();
220+
if (Utf8.TryWrite(span, $"Updated LEDs, first LED: R{ledColorsBuffer[0].R} G{ledColorsBuffer[0].G} B{ledColorsBuffer[0].B}", out int written))
221+
{
222+
Console.WriteLine(Encoding.UTF8.GetString(debugBuffer, 0, written));
223+
}
196224
}
197225

198226
if (config.SaveDebugImages &&
@@ -217,7 +245,7 @@ static void ProcessFrame(ScreenCapturer capturer, CPUImageProcessor processor, O
217245
[MethodImpl(MethodImplOptions.AggressiveInlining)]
218246
static void UpdateLedColors(ORGBColor[] columnColors, LightingConfig config, int ledCount)
219247
{
220-
// Check if we want instant transitions (fadeSpeed at or very near 1.0)
248+
221249
bool instantTransition = config.FadeFactor >= 0.99;
222250

223251
var wasdEnabled = config.WASDEnabled;
@@ -238,27 +266,26 @@ static void UpdateLedColors(ORGBColor[] columnColors, LightingConfig config, int
238266
{
239267
if (wasdEnabled && Array.IndexOf(wasdKeys, i) >= 0)
240268
{
241-
// Handle WASD keys with special color
269+
242270
ledColorsBuffer[i] = new ORGBColor(wasdR, wasdG, wasdB);
243271
}
244272
else
245273
{
246-
// Apply column colors to the keyboard
274+
247275
int columnIndex = Math.Min(i, columnLength - 1);
248276

249277
if (instantTransition)
250278
{
251-
// With instantTransition, directly apply the column color
279+
252280
ledColorsBuffer[i] = columnColors[columnIndex];
253281
}
254282
else
255283
{
256-
// For backward compatibility, keep some very minimal smoothing
284+
257285
ORGBColor prev = prevColors[i];
258286
ORGBColor target = columnColors[columnIndex];
259287

260-
// Simple lerp with very high weight toward target color
261-
float t = 0.8f; // High value for quick transition but not instant
288+
float t = 0.8f;
262289

263290
byte r = (byte)Math.Round(prev.R * (1 - t) + target.R * t);
264291
byte g = (byte)Math.Round(prev.G * (1 - t) + target.G * t);
@@ -267,57 +294,61 @@ static void UpdateLedColors(ORGBColor[] columnColors, LightingConfig config, int
267294
ledColorsBuffer[i] = new ORGBColor(r, g, b);
268295
}
269296

270-
// Store current color for next frame
271297
prevColors[i] = ledColorsBuffer[i];
272298
}
273299
}
274300
}
301+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
302+
static void WriteFormattedToConsole<T>(T value) where T : IUtf8SpanFormattable
303+
{
304+
Span<byte> buffer = stackalloc byte[512];
305+
if (value.TryFormat(buffer, out int written, default, null))
306+
{
307+
Console.WriteLine(Encoding.UTF8.GetString(buffer.Slice(0, written)));
308+
}
309+
}
310+
static class Utf8BufferPool
311+
{
312+
private static readonly ThreadLocal<byte[]> _threadLocalBuffer =
313+
new ThreadLocal<byte[]>(() => new byte[2048]);
275314

315+
public static byte[] GetBuffer() => _threadLocalBuffer.Value;
316+
}
276317
static void SaveDebugImages(Bitmap frame, ORGBColor[] columnColors, LightingConfig config)
277318
{
278319
try
279320
{
280321
string folder = "images";
281322
Directory.CreateDirectory(folder);
282323

283-
using (var debugBmp = new Bitmap(columnColors.Length, 50))
284-
{
324+
Span<byte> filenameBuffer = stackalloc byte[256];
325+
DateTime now = DateTime.Now;
285326

286-
var bmpData = debugBmp.LockBits(
287-
new Rectangle(0, 0, debugBmp.Width, debugBmp.Height),
288-
ImageLockMode.WriteOnly,
289-
PixelFormat.Format32bppArgb);
290-
291-
IntPtr ptr = bmpData.Scan0;
292-
int bytes = Math.Abs(bmpData.Stride) * debugBmp.Height;
293-
byte[] rgbValues = new byte[bytes];
327+
if (Utf8.TryWrite(filenameBuffer, $"{folder}/debug_frame_{now:yyyyMMdd_HHmmss_fff}.png", out int debugWritten))
328+
{
329+
string debugFilename = Encoding.UTF8.GetString(filenameBuffer.Slice(0, debugWritten));
294330

295-
for (int x = 0; x < columnColors.Length; x++)
331+
using (var debugBmp = new Bitmap(columnColors.Length, 50))
296332
{
297-
var color = columnColors[x];
298-
for (int y = 0; y < 50; y++)
299-
{
300-
int offset = y * bmpData.Stride + x * 4;
301-
rgbValues[offset] = color.B;
302-
rgbValues[offset + 1] = color.G;
303-
rgbValues[offset + 2] = color.R;
304-
rgbValues[offset + 3] = 255;
305-
}
306-
}
307-
308-
Marshal.Copy(rgbValues, 0, ptr, bytes);
309-
debugBmp.UnlockBits(bmpData);
310333

311-
string filename = $"{folder}/debug_frame_{DateTime.Now:yyyyMMdd_HHmmss_fff}.png";
312-
debugBmp.Save(filename, ImageFormat.Png);
334+
debugBmp.Save(debugFilename, ImageFormat.Png);
335+
}
313336
}
314337

315-
string frameFilename = $"{folder}/captured_frame_{DateTime.Now:yyyyMMdd_HHmmss_fff}.png";
316-
frame.Save(frameFilename, ImageFormat.Png);
338+
if (Utf8.TryWrite(filenameBuffer, $"{folder}/captured_frame_{now:yyyyMMdd_HHmmss_fff}.png", out int frameWritten))
339+
{
340+
string frameFilename = Encoding.UTF8.GetString(filenameBuffer.Slice(0, frameWritten));
341+
frame.Save(frameFilename, ImageFormat.Png);
342+
}
317343
}
318344
catch (Exception ex)
319345
{
320-
Console.WriteLine($"Error saving debug images: {ex.Message}");
346+
347+
var span = debugBuffer.AsSpan();
348+
if (Utf8.TryWrite(span, $"Error saving debug images: {ex.Message}", out int written))
349+
{
350+
Console.WriteLine(Encoding.UTF8.GetString(debugBuffer, 0, written));
351+
}
321352
}
322353
}
323354
}

0 commit comments

Comments
 (0)