diff --git a/src/ImageSharp/Common/Helpers/Numerics.cs b/src/ImageSharp/Common/Helpers/Numerics.cs index 0581993014..e8ba6dde61 100644 --- a/src/ImageSharp/Common/Helpers/Numerics.cs +++ b/src/ImageSharp/Common/Helpers/Numerics.cs @@ -825,5 +825,17 @@ namespace SixLabors.ImageSharp return Sse2.ConvertToInt32(vsum); } #endif + + /// + /// Calculates how many minimum bits needed to store given value. + /// + /// Unsigned integer to store + /// Minimum number of bits needed to store given value + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int MinimumBitsToStore(uint number) + { + const int bitInUnsignedInteger = sizeof(uint) * 8; + return bitInUnsignedInteger - BitOperations.LeadingZeroCount(number); + } } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs b/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs index 8b23211d35..0c1b4dedcf 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs @@ -3,6 +3,7 @@ using System; using System.IO; +using System.Numerics; using System.Runtime.CompilerServices; using System.Threading; using SixLabors.ImageSharp.Memory; @@ -54,29 +55,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder this.target = outputStream; } - /// - /// Gets the counts the number of bits needed to hold an integer. - /// - // The C# compiler emits this as a compile-time constant embedded in the PE file. - // This is effectively compiled down to: return new ReadOnlySpan(&data, length) - // More details can be found: https://github.com/dotnet/roslyn/pull/24621 - private static ReadOnlySpan BitCountLut => new byte[] - { - 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, - }; - /// /// Encodes the image with no subsampling. /// @@ -394,15 +372,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder b = value - 1; } - uint bt; - if (a < 0x100) - { - bt = BitCountLut[a]; - } - else - { - bt = 8 + (uint)BitCountLut[a >> 8]; - } + uint bt = (uint)Numerics.MinimumBitsToStore((uint)a); this.EmitHuff(index, (int)((uint)(runLength << 4) | bt)); if (bt > 0)