From ab2a97a9653a6f3de3705b1892b1fa5b0cc85abb Mon Sep 17 00:00:00 2001 From: Dmitry Pentin Date: Tue, 15 Jun 2021 06:46:11 +0300 Subject: [PATCH] Moved jpeg specific code from Numerics.cs to the jpeg related code --- src/ImageSharp/Common/Helpers/Numerics.cs | 32 +------------------ .../Components/Encoder/HuffmanScanEncoder.cs | 29 +++++++++++++++++ 2 files changed, 30 insertions(+), 31 deletions(-) diff --git a/src/ImageSharp/Common/Helpers/Numerics.cs b/src/ImageSharp/Common/Helpers/Numerics.cs index 83f2a1f7c6..eff1372c17 100644 --- a/src/ImageSharp/Common/Helpers/Numerics.cs +++ b/src/ImageSharp/Common/Helpers/Numerics.cs @@ -836,36 +836,6 @@ namespace SixLabors.ImageSharp } #endif - /// - /// Calculates how many minimum bits needed to store given value for Huffman jpeg encoding. - /// This method does not follow the standard convention - it does not support input value of zero. - /// - /// - /// Passing zero as input value would result in an undefined behaviour. - /// This is done for performance reasons as Huffman encoding code checks for zero value, second identical check could degrade the performance in the hot path. - /// If this method is needed somewhere else apart from jpeg encoding - use explicit if check for zero value case. - /// - /// The value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static int GetHuffmanEncodingLegth(uint value) - { - DebugGuard.IsFalse(value == 0, nameof(value), "Huffman encoding does not encode zero values"); -#if SUPPORTS_BITOPERATIONS - // This should have been implemented as (BitOperations.Log2(value) + 1) as in non-intrinsic implementation - // But internal log2 is implementated like this: (31 - (int)Lzcnt.LeadingZeroCount(value)) - - // BitOperations.Log2 implementation also checks if input value is zero for the convention - // As this is a very specific method for a very specific Huffman encoding code - // We can omit zero check as this should not be invoked with value == 0 and guarded in debug builds - // This is also marked as internal so every use of this would be tracable & testable in tests - return 32 - BitOperations.LeadingZeroCount(value); -#else - // On the contrary to BitOperations implementation this does follow the convention and supports value == 0 case - // Although it's still won't be called with value == 0 - return Log2SoftwareFallback(value) + 1; -#endif - } - /// /// Calculates floored log of the specified value, base 2. /// Note that by convention, input value 0 returns 0 since Log(0) is undefined. @@ -891,7 +861,7 @@ namespace SixLabors.ImageSharp /// https://cstheory.stackexchange.com/questions/19524/using-the-de-bruijn-sequence-to-find-the-lceil-log-2-v-rceil-of-an-integer /// /// The value. - private static int Log2SoftwareFallback(uint value) + internal static int Log2SoftwareFallback(uint value) { // No AggressiveInlining due to large method size // Has conventional contract 0->0 (Log(0) is undefined) by default, no need for if checking diff --git a/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs b/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs index 2a21ae75f8..a8382df2bb 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs @@ -388,5 +388,34 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder this.target.Write(this.emitBuffer, 0, this.emitLen); } } + + /// + /// Calculates how many minimum bits needed to store given value for Huffman jpeg encoding. + /// This method does not follow the standard convention - it does not support input value of zero. + /// + /// + /// Passing zero as input value would result in an undefined behaviour. + /// This is done for performance reasons as Huffman encoding code checks for zero value, second identical check would degrade the performance in the hot path. + /// + /// The value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static int GetHuffmanEncodingLegth(uint value) + { + DebugGuard.IsFalse(value == 0, nameof(value), "Huffman encoding does not encode zero values"); +#if SUPPORTS_BITOPERATIONS + // This should have been implemented as (BitOperations.Log2(value) + 1) as in non-intrinsic implementation + // But internal log2 is implementated like this: (31 - (int)Lzcnt.LeadingZeroCount(value)) + + // BitOperations.Log2 implementation also checks if input value is zero for the convention + // As this is a very specific method for a very specific Huffman encoding code + // We can omit zero check as this should not be invoked with value == 0 and guarded in debug builds + // This is also marked as internal so every use of this would be tracable & testable in tests + return 32 - System.Numerics.BitOperations.LeadingZeroCount(value); +#else + // On the contrary to BitOperations implementation this does follow the convention and supports value == 0 case + // Although it's still won't be called with value == 0 + return Numerics.Log2SoftwareFallback(value) + 1; +#endif + } } }