From 081384d8136588fe769e0b4b8bb0e6f3f7004411 Mon Sep 17 00:00:00 2001 From: winscripter <142818255+winscripter@users.noreply.github.com> Date: Tue, 1 Sep 2026 22:48:53 +0400 Subject: [PATCH] Optimize --- .../Modular/Transforms/JxlPalette.cs | 21 +++++++++++-------- .../Modular/Transforms/JxlTransform.cs | 19 +++++++---------- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/src/ImageSharp/Formats/Jxl/Processing/Modular/Transforms/JxlPalette.cs b/src/ImageSharp/Formats/Jxl/Processing/Modular/Transforms/JxlPalette.cs index 4a41bc34c..63d0c0b08 100644 --- a/src/ImageSharp/Formats/Jxl/Processing/Modular/Transforms/JxlPalette.cs +++ b/src/ImageSharp/Formats/Jxl/Processing/Modular/Transforms/JxlPalette.cs @@ -658,6 +658,11 @@ internal static class JxlPalette DebugGuard.MustBeGreaterThanOrEqualTo(beginC, input.MetaChannels, nameof(beginC)); int nb = endC - beginC + 1; // inclusive number of channels + // TODO: if this assert below triggers, increase nb to 6 and update + // the stack allocation for the 'tmp' variable below + // so the size is big enough. + DebugGuard.MustBeLessThanOrEqualTo(nb, 5, nameof(nb)); + JxlModularChannel beginCChannel = input.Channels[beginC]; int w = beginCChannel.Width; int h = beginCChannel.Height; @@ -1036,10 +1041,11 @@ internal static class JxlPalette errorRow[2] = new(nb, w + 4); } - Span bestValue = stackalloc int[nb]; - Span idealResidual = stackalloc int[nb]; - Span quantizedValue = stackalloc int[nb]; - Span predictions = stackalloc int[nb]; + Span tmp = stackalloc int[32]; // Power of 2 + Span bestValue = tmp.Slice(0 * nb, nb); + Span idealResidual = tmp.Slice(1 * nb, nb); + Span quantizedValue = tmp.Slice(2 * nb, nb); + Span predictions = tmp.Slice(30 * nb, nb); // This is a temporary buffer, values are copied here. // It is so we can swap spans. Since spans are just a view @@ -1051,7 +1057,7 @@ internal static class JxlPalette { for (int c = 0; c < nb; c++) { - p_in[c] = input.channel[begin_c + c].Row(y); + p_in[c] = input.channel[beginC + c].Row(y); if (lossy) p_quant[c] = quantized_input.channel[c].Row(y); } @@ -1076,10 +1082,7 @@ internal static class JxlPalette bool best_is_delta = false; float best_distance = float.PositiveInfinity; - bestValue.Clear(); - idealResidual.Clear(); - quantizedValue.Clear(); - predictions.Clear(); + tmp.Clear(); foreach (double diffusion_multiplier in (Span)[0.55, 0.75]) { diff --git a/src/ImageSharp/Formats/Jxl/Processing/Modular/Transforms/JxlTransform.cs b/src/ImageSharp/Formats/Jxl/Processing/Modular/Transforms/JxlTransform.cs index 75ba98608..cf3c2156f 100644 --- a/src/ImageSharp/Formats/Jxl/Processing/Modular/Transforms/JxlTransform.cs +++ b/src/ImageSharp/Formats/Jxl/Processing/Modular/Transforms/JxlTransform.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +using System.Numerics.Tensors; using SixLabors.ImageSharp.Formats.Jxl.Fields; namespace SixLabors.ImageSharp.Formats.Jxl.Processing.Modular.Transforms; @@ -46,19 +47,13 @@ internal sealed class JxlTransform : IJxlFields for (int y = 0; y < channel.Height; y++) { - Span p = channel.GetRow(y); - for (int x = 0; x < channel.Width; x++) - { - if (p[x] < min) - { - min = p[x]; - } + ReadOnlySpan p = channel.GetRow(y); - if (p[x] > max) - { - max = p[x]; - } - } + int minRow = TensorPrimitives.Min(p); + int maxRow = TensorPrimitives.Max(p); + + min = Math.Min(minRow, min); + max = Math.Max(maxRow, max); } } }