From eee64f25d63b03a0e4bd08d03a57a0a84fb5880d Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Sun, 24 Jul 2022 00:25:12 +1000 Subject: [PATCH 01/20] Remove SUPPORTS conditions --- shared-infrastructure | 2 +- src/Directory.Build.props | 4 + src/ImageSharp.ruleset | 7 + .../ColorSpaces/Companding/SRgbCompanding.cs | 17 +- .../Common/Extensions/EncoderExtensions.cs | 35 --- .../Common/Extensions/StreamExtensions.cs | 46 ---- .../Common/Helpers/InliningOptions.cs | 6 +- src/ImageSharp/Common/Helpers/Numerics.cs | 128 +--------- .../Helpers/SimdUtils.BasicIntrinsics256.cs | 216 ---------------- .../Helpers/SimdUtils.ExtendedIntrinsics.cs | 35 +-- .../SimdUtils.FallbackIntrinsics128.cs | 20 +- .../Common/Helpers/SimdUtils.HwIntrinsics.cs | 88 +++---- .../Common/Helpers/SimdUtils.Pack.cs | 26 +- .../Common/Helpers/SimdUtils.Shuffle.cs | 18 +- src/ImageSharp/Common/Helpers/SimdUtils.cs | 19 +- src/ImageSharp/Compression/Zlib/Adler32.cs | 22 +- src/ImageSharp/Compression/Zlib/Crc32.cs | 16 +- .../Compression/Zlib/DeflaterEngine.cs | 6 +- .../Jpeg/Components/Block8x8.Intrinsic.cs | 2 - .../Formats/Jpeg/Components/Block8x8.cs | 11 +- .../Jpeg/Components/Block8x8F.Intrinsic.cs | 4 +- .../Formats/Jpeg/Components/Block8x8F.cs | 34 +-- .../JpegColorConverter.FromCmykAvx.cs | 2 - .../JpegColorConverter.FromGrayScaleAvx.cs | 2 - .../JpegColorConverter.FromRgbAvx.cs | 2 - .../JpegColorConverter.FromYCbCrAvx.cs | 2 - .../JpegColorConverter.FromYccKAvx.cs | 2 - .../ColorConverters/JpegColorConverterAvx.cs | 2 - .../ColorConverters/JpegColorConverterBase.cs | 10 - .../Components/Encoder/HuffmanScanEncoder.cs | 15 +- .../LuminanceForwardConverter{TPixel}.cs | 6 +- .../Encoder/RgbForwardConverter{TPixel}.cs | 10 +- .../Encoder/RgbToYCbCrConverterVectorized.cs | 38 +-- .../Components/FloatingPointDCT.Intrinsic.cs | 6 +- .../Jpeg/Components/FloatingPointDCT.cs | 6 - .../Jpeg/Components/ZigZag.Intrinsic.cs | 2 - .../Formats/Png/Filters/AverageFilter.cs | 9 - .../Formats/Png/Filters/PaethFilter.cs | 13 - .../Formats/Png/Filters/SubFilter.cs | 11 +- .../Formats/Png/Filters/UpFilter.cs | 9 - src/ImageSharp/Formats/Webp/AlphaDecoder.cs | 24 +- .../Webp/Lossless/ColorSpaceTransformUtils.cs | 54 ++-- .../Formats/Webp/Lossless/LosslessUtils.cs | 82 +++--- .../Formats/Webp/Lossless/Vp8LHistogram.cs | 4 - .../Formats/Webp/Lossy/LossyUtils.cs | 151 ++++------- src/ImageSharp/Formats/Webp/Lossy/QuantEnc.cs | 42 ++- .../Formats/Webp/Lossy/Vp8Encoding.cs | 124 ++++----- .../Formats/Webp/Lossy/Vp8Histogram.cs | 6 +- .../Formats/Webp/Lossy/Vp8Residual.cs | 25 +- .../Formats/Webp/Lossy/YuvConversion.cs | 80 +++--- .../Formats/Webp/WebpCommonUtils.cs | 28 +- src/ImageSharp/IO/BufferedReadStream.cs | 4 +- src/ImageSharp/IO/ChunkedMemoryStream.cs | 4 - .../DiscontiguousBuffers/MemoryGroup{T}.cs | 16 +- .../PixelOperations/Rgb24.PixelOperations.cs | 4 +- .../PixelOperations/Rgba32.PixelOperations.cs | 8 +- .../Transforms/Resize/ResizeKernel.cs | 8 +- .../BlockOperations/Block8x8F_CopyTo1x1.cs | 10 +- .../Jpeg/BlockOperations/Block8x8F_Round.cs | 4 - .../ColorConversion/CmykColorConversion.cs | 2 - .../GrayscaleColorConversion.cs | 2 - .../ColorConversion/RgbColorConversion.cs | 2 - .../ColorConversion/YCbCrColorConversion.cs | 2 - .../ColorConversion/YccKColorConverter.cs | 2 - .../Color/Bulk/FromVector4.cs | 13 - .../Color/Bulk/ToVector4_Rgba32.cs | 19 +- .../Config.HwIntrinsics.cs | 10 +- .../PixelConversion_PackFromRgbPlanes.cs | 4 - .../ImageSharp.Tests/Common/SimdUtilsTests.cs | 93 +------ .../Formats/Jpg/Block8x8FTests.cs | 4 +- .../Formats/Jpg/JpegColorConverterTests.cs | 22 +- .../Formats/Jpg/JpegDecoderTests.Internal.cs | 14 +- .../Formats/Jpg/RgbToYCbCrConverterTests.cs | 30 +-- .../Formats/Png/Adler32Tests.cs | 2 - .../Formats/Png/PngDecoderFilterTests.cs | 2 - .../BlackIsZeroTiffColorTests.cs | 35 +-- .../WebP/ColorSpaceTransformUtilsTests.cs | 3 - .../Formats/WebP/LosslessUtilsTests.cs | 16 +- .../Formats/WebP/LossyUtilsTests.cs | 2 - .../Formats/WebP/PredictorEncoderTests.cs | 8 +- .../Formats/WebP/QuantEncTests.cs | 2 - .../Formats/WebP/Vp8EncodingTests.cs | 2 - .../Formats/WebP/Vp8HistogramTests.cs | 2 - .../Formats/WebP/Vp8LHistogramTests.cs | 2 - .../Formats/WebP/Vp8ResidualTests.cs | 2 - .../Formats/WebP/WebpCommonUtilsTests.cs | 8 +- .../Formats/WebP/WebpDecoderTests.cs | 240 +++++++----------- .../Formats/WebP/WebpEncoderTests.cs | 2 - .../Formats/WebP/YuvConversionTests.cs | 19 +- .../Processing/Transforms/ResizeTests.cs | 2 - .../Tests/FeatureTestRunnerTests.cs | 17 +- 91 files changed, 555 insertions(+), 1617 deletions(-) create mode 100644 src/ImageSharp.ruleset delete mode 100644 src/ImageSharp/Common/Extensions/EncoderExtensions.cs delete mode 100644 src/ImageSharp/Common/Helpers/SimdUtils.BasicIntrinsics256.cs diff --git a/shared-infrastructure b/shared-infrastructure index c0e0353c1..e12c30b3b 160000 --- a/shared-infrastructure +++ b/shared-infrastructure @@ -1 +1 @@ -Subproject commit c0e0353c1ee89398def0ccdc3e945380034fbea8 +Subproject commit e12c30b3b1427815cffa22ac95c77ba29f65fe5a diff --git a/src/Directory.Build.props b/src/Directory.Build.props index faa29865f..cfc3d8222 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -21,6 +21,10 @@ true + + ..\ImageSharp.ruleset + + diff --git a/src/ImageSharp.ruleset b/src/ImageSharp.ruleset new file mode 100644 index 000000000..e88c43f83 --- /dev/null +++ b/src/ImageSharp.ruleset @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs b/src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs index 1337af702..c15cdf8a8 100644 --- a/src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs +++ b/src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs @@ -5,10 +5,8 @@ using System; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; -#endif namespace SixLabors.ImageSharp.ColorSpaces.Companding { @@ -25,10 +23,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding private const int Length = Scale + 2; // 256kb @ 16bit precision. private const int Scale = (1 << 16) - 1; - private static readonly Lazy LazyCompressTable = new Lazy( + private static readonly Lazy LazyCompressTable = new( () => { - var result = new float[Length]; + float[] result = new float[Length]; for (int i = 0; i < result.Length; i++) { @@ -49,10 +47,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding }, true); - private static readonly Lazy LazyExpandTable = new Lazy( + private static readonly Lazy LazyExpandTable = new( () => { - var result = new float[Length]; + float[] result = new float[Length]; for (int i = 0; i < result.Length; i++) { @@ -84,7 +82,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Expand(Span vectors) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx2.IsSupported && vectors.Length >= 2) { CompandAvx2(vectors, ExpandTable); @@ -96,7 +93,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding } } else -#endif { CompandScalar(vectors, ExpandTable); } @@ -109,7 +105,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe void Compress(Span vectors) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx2.IsSupported && vectors.Length >= 2) { CompandAvx2(vectors, CompressTable); @@ -121,7 +116,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding } } else -#endif { CompandScalar(vectors, CompressTable); } @@ -171,8 +165,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding public static float Compress(float channel) => channel <= 0.0031308F ? 12.92F * channel : (1.055F * MathF.Pow(channel, 0.416666666666667F)) - 0.055F; -#if SUPPORTS_RUNTIME_INTRINSICS - [MethodImpl(MethodImplOptions.AggressiveInlining)] private static unsafe void CompandAvx2(Span vectors, float[] table) { @@ -204,7 +196,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding } } } -#endif [MethodImpl(MethodImplOptions.AggressiveInlining)] private static unsafe void CompandScalar(Span vectors, float[] table) diff --git a/src/ImageSharp/Common/Extensions/EncoderExtensions.cs b/src/ImageSharp/Common/Extensions/EncoderExtensions.cs deleted file mode 100644 index b49e1234f..000000000 --- a/src/ImageSharp/Common/Extensions/EncoderExtensions.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Six Labors Split License. - -#if !SUPPORTS_ENCODING_STRING -using System; -using System.Text; - -namespace SixLabors.ImageSharp -{ - /// - /// Extension methods for the type. - /// - internal static unsafe class EncoderExtensions - { - /// - /// Gets a string from the provided buffer data. - /// - /// The encoding. - /// The buffer. - /// The string. - public static string GetString(this Encoding encoding, ReadOnlySpan buffer) - { - if (buffer.Length == 0) - { - return string.Empty; - } - - fixed (byte* bytes = buffer) - { - return encoding.GetString(bytes, buffer.Length); - } - } - } -} -#endif diff --git a/src/ImageSharp/Common/Extensions/StreamExtensions.cs b/src/ImageSharp/Common/Extensions/StreamExtensions.cs index e21d9e96b..3018b2d0e 100644 --- a/src/ImageSharp/Common/Extensions/StreamExtensions.cs +++ b/src/ImageSharp/Common/Extensions/StreamExtensions.cs @@ -70,51 +70,5 @@ namespace SixLabors.ImageSharp ArrayPool.Shared.Return(buffer); } } - -#if !SUPPORTS_SPAN_STREAM - // This is a port of the CoreFX implementation and is MIT Licensed: - // https://github.com/dotnet/corefx/blob/17300169760c61a90cab8d913636c1058a30a8c1/src/Common/src/CoreLib/System/IO/Stream.cs#L742 - public static int Read(this Stream stream, Span buffer) - { - // This uses ArrayPool.Shared, rather than taking a MemoryAllocator, - // in order to match the signature of the framework method that exists in - // .NET Core. - byte[] sharedBuffer = ArrayPool.Shared.Rent(buffer.Length); - try - { - int numRead = stream.Read(sharedBuffer, 0, buffer.Length); - if ((uint)numRead > (uint)buffer.Length) - { - throw new IOException("Stream was too long."); - } - - new Span(sharedBuffer, 0, numRead).CopyTo(buffer); - return numRead; - } - finally - { - ArrayPool.Shared.Return(sharedBuffer); - } - } - - // This is a port of the CoreFX implementation and is MIT Licensed: - // https://github.com/dotnet/corefx/blob/17300169760c61a90cab8d913636c1058a30a8c1/src/Common/src/CoreLib/System/IO/Stream.cs#L775 - public static void Write(this Stream stream, ReadOnlySpan buffer) - { - // This uses ArrayPool.Shared, rather than taking a MemoryAllocator, - // in order to match the signature of the framework method that exists in - // .NET Core. - byte[] sharedBuffer = ArrayPool.Shared.Rent(buffer.Length); - try - { - buffer.CopyTo(sharedBuffer); - stream.Write(sharedBuffer, 0, buffer.Length); - } - finally - { - ArrayPool.Shared.Return(sharedBuffer); - } - } -#endif } } diff --git a/src/ImageSharp/Common/Helpers/InliningOptions.cs b/src/ImageSharp/Common/Helpers/InliningOptions.cs index a6c6d021c..520c19201 100644 --- a/src/ImageSharp/Common/Helpers/InliningOptions.cs +++ b/src/ImageSharp/Common/Helpers/InliningOptions.cs @@ -18,13 +18,11 @@ namespace SixLabors.ImageSharp public const MethodImplOptions AlwaysInline = MethodImplOptions.AggressiveInlining; #if PROFILING public const MethodImplOptions HotPath = MethodImplOptions.NoInlining; + public const MethodImplOptions ShortMethod = MethodImplOptions.NoInlining; #else -#if SUPPORTS_HOTPATH public const MethodImplOptions HotPath = MethodImplOptions.AggressiveOptimization; -#else - public const MethodImplOptions HotPath = MethodImplOptions.AggressiveInlining; -#endif + public const MethodImplOptions ShortMethod = MethodImplOptions.AggressiveInlining; #endif public const MethodImplOptions ColdPath = MethodImplOptions.NoInlining; diff --git a/src/ImageSharp/Common/Helpers/Numerics.cs b/src/ImageSharp/Common/Helpers/Numerics.cs index c149cc7b6..9f81de1c2 100644 --- a/src/ImageSharp/Common/Helpers/Numerics.cs +++ b/src/ImageSharp/Common/Helpers/Numerics.cs @@ -5,10 +5,8 @@ using System; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; -#endif namespace SixLabors.ImageSharp { @@ -18,20 +16,8 @@ namespace SixLabors.ImageSharp /// internal static class Numerics { -#if SUPPORTS_RUNTIME_INTRINSICS public const int BlendAlphaControl = 0b_10_00_10_00; private const int ShuffleAlphaControl = 0b_11_11_11_11; -#endif - -#if !SUPPORTS_BITOPERATIONS - private static ReadOnlySpan Log2DeBruijn => new byte[32] - { - 00, 09, 01, 10, 13, 21, 02, 29, - 11, 14, 16, 18, 22, 25, 03, 30, - 08, 12, 20, 28, 15, 17, 24, 07, - 19, 27, 23, 06, 26, 05, 04, 31 - }; -#endif /// /// Determine the Greatest CommonDivisor (GCD) of two numbers. @@ -129,13 +115,13 @@ namespace SixLabors.ImageSharp [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float Gaussian(float x, float sigma) { - const float Numerator = 1.0f; + const float numerator = 1.0f; float denominator = MathF.Sqrt(2 * MathF.PI) * sigma; float exponentNumerator = -x * x; float exponentDenominator = 2 * Pow2(sigma); - float left = Numerator / denominator; + float left = numerator / denominator; float right = MathF.Exp(exponentNumerator / exponentDenominator); return left * right; @@ -300,7 +286,7 @@ namespace SixLabors.ImageSharp [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Clamp(Span span, byte min, byte max) { - Span remainder = span.Slice(ClampReduce(span, min, max)); + Span remainder = span[ClampReduce(span, min, max)..]; if (remainder.Length > 0) { @@ -325,7 +311,7 @@ namespace SixLabors.ImageSharp [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Clamp(Span span, uint min, uint max) { - Span remainder = span.Slice(ClampReduce(span, min, max)); + Span remainder = span[ClampReduce(span, min, max)..]; if (remainder.Length > 0) { @@ -350,7 +336,7 @@ namespace SixLabors.ImageSharp [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Clamp(Span span, int min, int max) { - Span remainder = span.Slice(ClampReduce(span, min, max)); + Span remainder = span[ClampReduce(span, min, max)..]; if (remainder.Length > 0) { @@ -375,7 +361,7 @@ namespace SixLabors.ImageSharp [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Clamp(Span span, float min, float max) { - Span remainder = span.Slice(ClampReduce(span, min, max)); + Span remainder = span[ClampReduce(span, min, max)..]; if (remainder.Length > 0) { @@ -400,7 +386,7 @@ namespace SixLabors.ImageSharp [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Clamp(Span span, double min, double max) { - Span remainder = span.Slice(ClampReduce(span, min, max)); + Span remainder = span[ClampReduce(span, min, max)..]; if (remainder.Length > 0) { @@ -427,7 +413,7 @@ namespace SixLabors.ImageSharp if (adjustedCount > 0) { - ClampImpl(span.Slice(0, adjustedCount), min, max); + ClampImpl(span[..adjustedCount], min, max); } return adjustedCount; @@ -512,7 +498,6 @@ namespace SixLabors.ImageSharp [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Premultiply(Span vectors) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx2.IsSupported && vectors.Length >= 2) { // Divide by 2 as 4 elements per Vector4 and 8 per Vector256 @@ -530,11 +515,10 @@ namespace SixLabors.ImageSharp if (Modulo2(vectors.Length) != 0) { // Vector4 fits neatly in pairs. Any overlap has to be equal to 1. - Premultiply(ref MemoryMarshal.GetReference(vectors.Slice(vectors.Length - 1))); + Premultiply(ref MemoryMarshal.GetReference(vectors[^1..])); } } else -#endif { ref Vector4 vectorsStart = ref MemoryMarshal.GetReference(vectors); ref Vector4 vectorsEnd = ref Unsafe.Add(ref vectorsStart, vectors.Length); @@ -555,7 +539,6 @@ namespace SixLabors.ImageSharp [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void UnPremultiply(Span vectors) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx2.IsSupported && vectors.Length >= 2) { // Divide by 2 as 4 elements per Vector4 and 8 per Vector256 @@ -573,11 +556,10 @@ namespace SixLabors.ImageSharp if (Modulo2(vectors.Length) != 0) { // Vector4 fits neatly in pairs. Any overlap has to be equal to 1. - UnPremultiply(ref MemoryMarshal.GetReference(vectors.Slice(vectors.Length - 1))); + UnPremultiply(ref MemoryMarshal.GetReference(vectors[^1..])); } } else -#endif { ref Vector4 vectorsStart = ref MemoryMarshal.GetReference(vectors); ref Vector4 vectorsEnd = ref Unsafe.Add(ref vectorsStart, vectors.Length); @@ -627,7 +609,6 @@ namespace SixLabors.ImageSharp [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe void CubeRootOnXYZ(Span vectors) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Sse41.IsSupported) { ref Vector128 vectors128Ref = ref Unsafe.As>(ref MemoryMarshal.GetReference(vectors)); @@ -678,7 +659,6 @@ namespace SixLabors.ImageSharp } } else -#endif { ref Vector4 vectorsRef = ref MemoryMarshal.GetReference(vectors); ref Vector4 vectorsEnd = ref Unsafe.Add(ref vectorsRef, vectors.Length); @@ -727,8 +707,6 @@ namespace SixLabors.ImageSharp } } -#if SUPPORTS_RUNTIME_INTRINSICS - /// /// Performs a linear interpolation between two values based on the given weighting. /// @@ -752,7 +730,6 @@ namespace SixLabors.ImageSharp return Avx.Add(Avx.Multiply(diff, amount), value1); } } -#endif /// /// Performs a linear interpolation between two values based on the given weighting. @@ -765,8 +742,6 @@ namespace SixLabors.ImageSharp public static float Lerp(float value1, float value2, float amount) => ((value2 - value1) * amount) + value1; -#if SUPPORTS_RUNTIME_INTRINSICS - /// /// Accumulates 8-bit integers into by /// widening them to 32-bit integers and performing four additions. @@ -860,51 +835,14 @@ namespace SixLabors.ImageSharp // Vector128.ToScalar() isn't optimized pre-net5.0 https://github.com/dotnet/runtime/pull/37882 return Sse2.ConvertToInt32(vsum); } -#endif /// /// Calculates floored log of the specified value, base 2. /// Note that by convention, input value 0 returns 0 since Log(0) is undefined. /// /// The value. - public static int Log2(uint value) - { -#if SUPPORTS_BITOPERATIONS - return BitOperations.Log2(value); -#else - return Log2SoftwareFallback(value); -#endif - } - -#if !SUPPORTS_BITOPERATIONS - /// - /// Calculates floored log of the specified value, base 2. - /// Note that by convention, input value 0 returns 0 since Log(0) is undefined. - /// Bit hacking with deBruijn sequence, extremely fast yet does not use any intrinsics so will work on every platform/runtime. - /// - /// - /// Description of this bit hacking can be found here: - /// 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) - { - // No AggressiveInlining due to large method size - // Has conventional contract 0->0 (Log(0) is undefined) by default, no need for if checking - - // Fill trailing zeros with ones, eg 00010010 becomes 00011111 - value |= value >> 01; - value |= value >> 02; - value |= value >> 04; - value |= value >> 08; - value |= value >> 16; - - // uint.MaxValue >> 27 is always in range [0 - 31] so we use Unsafe.AddByteOffset to avoid bounds check - return Unsafe.AddByteOffset( - ref MemoryMarshal.GetReference(Log2DeBruijn), - (IntPtr)(int)((value * 0x07C4ACDDu) >> 27)); // uint|long -> IntPtr cast on 32-bit platforms does expensive overflow checks not needed here - } -#endif + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Log2(uint value) => BitOperations.Log2(value); /// /// Fast division with ceiling for numbers. @@ -921,44 +859,8 @@ namespace SixLabors.ImageSharp /// The number of bits to rotate with. /// The rotated value. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static uint RotateLeft(uint value, int offset) - { -#if SUPPORTS_BITOPERATIONS - return BitOperations.RotateLeft(value, offset); -#else - return RotateLeftSoftwareFallback(value, offset); -#endif - } - -#if !SUPPORTS_BITOPERATIONS - /// - /// Rotates the specified value left by the specified number of bits. - /// - /// The value to rotate. - /// The number of bits to rotate with. - /// The rotated value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static uint RotateLeftSoftwareFallback(uint value, int offset) - => (value << offset) | (value >> (32 - offset)); -#endif - - /// - /// Rotates the specified value right by the specified number of bits. - /// - /// The value to rotate. - /// The number of bits to rotate with. - /// The rotated value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static uint RotateRight(uint value, int offset) - { -#if SUPPORTS_BITOPERATIONS - return BitOperations.RotateRight(value, offset); -#else - return RotateRightSoftwareFallback(value, offset); -#endif - } + public static uint RotateLeft(uint value, int offset) => BitOperations.RotateLeft(value, offset); -#if !SUPPORTS_BITOPERATIONS /// /// Rotates the specified value right by the specified number of bits. /// @@ -966,9 +868,7 @@ namespace SixLabors.ImageSharp /// The number of bits to rotate with. /// The rotated value. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static uint RotateRightSoftwareFallback(uint value, int offset) - => (value >> offset) | (value << (32 - offset)); -#endif + public static uint RotateRight(uint value, int offset) => BitOperations.RotateRight(value, offset); /// /// Tells whether input value is outside of the given range. diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.BasicIntrinsics256.cs b/src/ImageSharp/Common/Helpers/SimdUtils.BasicIntrinsics256.cs deleted file mode 100644 index 7e878677f..000000000 --- a/src/ImageSharp/Common/Helpers/SimdUtils.BasicIntrinsics256.cs +++ /dev/null @@ -1,216 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Six Labors Split License. - -using System; -using System.Numerics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using SixLabors.ImageSharp.Tuples; - -// ReSharper disable MemberHidesStaticFromOuterClass -namespace SixLabors.ImageSharp -{ - internal static partial class SimdUtils - { - /// - /// Implementation with 256bit / AVX2 intrinsics NOT depending on newer API-s (Vector.Widen etc.) - /// - public static class BasicIntrinsics256 - { - public static bool IsAvailable { get; } = HasVector8; - -#if !SUPPORTS_EXTENDED_INTRINSICS - /// - /// as many elements as possible, slicing them down (keeping the remainder). - /// - [MethodImpl(InliningOptions.ShortMethod)] - internal static void ByteToNormalizedFloatReduce( - ref ReadOnlySpan source, - ref Span dest) - { - DebugGuard.IsTrue(source.Length == dest.Length, nameof(source), "Input spans must be of same length!"); - - if (!IsAvailable) - { - return; - } - - int remainder = Numerics.Modulo8(source.Length); - int adjustedCount = source.Length - remainder; - - if (adjustedCount > 0) - { - ByteToNormalizedFloat( - source.Slice(0, adjustedCount), - dest.Slice(0, adjustedCount)); - - source = source.Slice(adjustedCount); - dest = dest.Slice(adjustedCount); - } - } - - /// - /// as many elements as possible, slicing them down (keeping the remainder). - /// - [MethodImpl(InliningOptions.ShortMethod)] - internal static void NormalizedFloatToByteSaturateReduce( - ref ReadOnlySpan source, - ref Span dest) - { - DebugGuard.IsTrue(source.Length == dest.Length, nameof(source), "Input spans must be of same length!"); - - if (!IsAvailable) - { - return; - } - - int remainder = Numerics.Modulo8(source.Length); - int adjustedCount = source.Length - remainder; - - if (adjustedCount > 0) - { - NormalizedFloatToByteSaturate(source.Slice(0, adjustedCount), dest.Slice(0, adjustedCount)); - - source = source.Slice(adjustedCount); - dest = dest.Slice(adjustedCount); - } - } -#endif - - /// - /// SIMD optimized implementation for . - /// Works only with span Length divisible by 8. - /// Implementation adapted from: - /// http://lolengine.net/blog/2011/3/20/understanding-fast-float-integer-conversions - /// http://stackoverflow.com/a/536278 - /// - internal static void ByteToNormalizedFloat(ReadOnlySpan source, Span dest) - { - VerifyHasVector8(nameof(ByteToNormalizedFloat)); - VerifySpanInput(source, dest, 8); - - var bVec = new Vector(256.0f / 255.0f); - var magicFloat = new Vector(32768.0f); - var magicInt = new Vector(1191182336); // reinterpreted value of 32768.0f - var mask = new Vector(255); - - ref Octet sourceBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(source)); - ref Octet destBaseAsWideOctet = ref Unsafe.As>(ref MemoryMarshal.GetReference(dest)); - - ref Vector destBaseAsFloat = ref Unsafe.As, Vector>(ref destBaseAsWideOctet); - - int n = dest.Length / 8; - - for (int i = 0; i < n; i++) - { - ref Octet s = ref Unsafe.Add(ref sourceBase, i); - ref Octet d = ref Unsafe.Add(ref destBaseAsWideOctet, i); - d.LoadFrom(ref s); - } - - for (int i = 0; i < n; i++) - { - ref Vector df = ref Unsafe.Add(ref destBaseAsFloat, i); - - var vi = Vector.AsVectorUInt32(df); - vi &= mask; - vi |= magicInt; - - var vf = Vector.AsVectorSingle(vi); - vf = (vf - magicFloat) * bVec; - - df = vf; - } - } - - /// - /// Implementation of which is faster on older runtimes. - /// - internal static void NormalizedFloatToByteSaturate(ReadOnlySpan source, Span dest) - { - VerifyHasVector8(nameof(NormalizedFloatToByteSaturate)); - VerifySpanInput(source, dest, 8); - - if (source.Length == 0) - { - return; - } - - ref Vector srcBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(source)); - ref Octet destBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(dest)); - int n = source.Length / 8; - - var magick = new Vector(32768.0f); - var scale = new Vector(255f) / new Vector(256f); - - // need to copy to a temporary struct, because - // SimdUtils.Octet temp = Unsafe.As, SimdUtils.Octet>(ref x) - // does not work. TODO: This might be a CoreClr bug, need to ask/report - var temp = default(Octet); - ref Vector tempRef = ref Unsafe.As, Vector>(ref temp); - - for (int i = 0; i < n; i++) - { - // union { float f; uint32_t i; } u; - // u.f = 32768.0f + x * (255.0f / 256.0f); - // return (uint8_t)u.i; - Vector x = Unsafe.Add(ref srcBase, i); - x = Vector.Max(x, Vector.Zero); - x = Vector.Min(x, Vector.One); - - x = (x * scale) + magick; - tempRef = x; - - ref Octet d = ref Unsafe.Add(ref destBase, i); - d.LoadFrom(ref temp); - } - } - - /// - /// Convert all values normalized into [0..1] from 'source' - /// into 'dest' buffer of . The values are scaled up into [0-255] and rounded. - /// This implementation is SIMD optimized and works only when span Length is divisible by 8. - /// Based on: - /// - /// http://lolengine.net/blog/2011/3/20/understanding-fast-float-integer-conversions - /// - /// - internal static void BulkConvertNormalizedFloatToByte(ReadOnlySpan source, Span dest) - { - VerifyHasVector8(nameof(BulkConvertNormalizedFloatToByte)); - VerifySpanInput(source, dest, 8); - - if (source.Length == 0) - { - return; - } - - ref Vector srcBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(source)); - ref Octet destBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(dest)); - int n = source.Length / 8; - - var magick = new Vector(32768.0f); - var scale = new Vector(255f) / new Vector(256f); - - // need to copy to a temporary struct, because - // SimdUtils.Octet temp = Unsafe.As, SimdUtils.Octet>(ref x) - // does not work. TODO: This might be a CoreClr bug, need to ask/report - var temp = default(Octet); - ref Vector tempRef = ref Unsafe.As, Vector>(ref temp); - - for (int i = 0; i < n; i++) - { - // union { float f; uint32_t i; } u; - // u.f = 32768.0f + x * (255.0f / 256.0f); - // return (uint8_t)u.i; - Vector x = Unsafe.Add(ref srcBase, i); - x = (x * scale) + magick; - tempRef = x; - - ref Octet d = ref Unsafe.Add(ref destBase, i); - d.LoadFrom(ref temp); - } - } - } - } -} diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.ExtendedIntrinsics.cs b/src/ImageSharp/Common/Helpers/SimdUtils.ExtendedIntrinsics.cs index 336ff3abc..3a143cda2 100644 --- a/src/ImageSharp/Common/Helpers/SimdUtils.ExtendedIntrinsics.cs +++ b/src/ImageSharp/Common/Helpers/SimdUtils.ExtendedIntrinsics.cs @@ -21,12 +21,7 @@ namespace SixLabors.ImageSharp /// public static class ExtendedIntrinsics { - public static bool IsAvailable { get; } = -#if SUPPORTS_EXTENDED_INTRINSICS - Vector.IsHardwareAccelerated; -#else - false; -#endif + public static bool IsAvailable { get; } = Vector.IsHardwareAccelerated; /// /// Widen and convert a vector of values into 2 vectors of -s. @@ -62,10 +57,10 @@ namespace SixLabors.ImageSharp if (adjustedCount > 0) { - ByteToNormalizedFloat(source.Slice(0, adjustedCount), dest.Slice(0, adjustedCount)); + ByteToNormalizedFloat(source[..adjustedCount], dest[..adjustedCount]); - source = source.Slice(adjustedCount); - dest = dest.Slice(adjustedCount); + source = source[adjustedCount..]; + dest = dest[adjustedCount..]; } } @@ -89,12 +84,10 @@ namespace SixLabors.ImageSharp if (adjustedCount > 0) { - NormalizedFloatToByteSaturate( - source.Slice(0, adjustedCount), - dest.Slice(0, adjustedCount)); + NormalizedFloatToByteSaturate(source[..adjustedCount], dest[..adjustedCount]); - source = source.Slice(adjustedCount); - dest = dest.Slice(adjustedCount); + source = source[adjustedCount..]; + dest = dest[adjustedCount..]; } } @@ -160,12 +153,10 @@ namespace SixLabors.ImageSharp Vector w2 = ConvertToUInt32(f2); Vector w3 = ConvertToUInt32(f3); - Vector u0 = Vector.Narrow(w0, w1); - Vector u1 = Vector.Narrow(w2, w3); + var u0 = Vector.Narrow(w0, w1); + var u1 = Vector.Narrow(w2, w3); - Vector b = Vector.Narrow(u0, u1); - - Unsafe.Add(ref destBase, i) = b; + Unsafe.Add(ref destBase, i) = Vector.Narrow(u0, u1); } } @@ -176,15 +167,15 @@ namespace SixLabors.ImageSharp vf *= maxBytes; vf += new Vector(0.5f); vf = Vector.Min(Vector.Max(vf, Vector.Zero), maxBytes); - Vector vi = Vector.ConvertToInt32(vf); + var vi = Vector.ConvertToInt32(vf); return Vector.AsVectorUInt32(vi); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static Vector ConvertToSingle(Vector u) { - Vector vi = Vector.AsVectorInt32(u); - Vector v = Vector.ConvertToSingle(vi); + var vi = Vector.AsVectorInt32(u); + var v = Vector.ConvertToSingle(vi); v *= new Vector(1f / 255f); return v; } diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.FallbackIntrinsics128.cs b/src/ImageSharp/Common/Helpers/SimdUtils.FallbackIntrinsics128.cs index c035ac72f..92c5bf5fb 100644 --- a/src/ImageSharp/Common/Helpers/SimdUtils.FallbackIntrinsics128.cs +++ b/src/ImageSharp/Common/Helpers/SimdUtils.FallbackIntrinsics128.cs @@ -33,12 +33,10 @@ namespace SixLabors.ImageSharp if (adjustedCount > 0) { - ByteToNormalizedFloat( - source.Slice(0, adjustedCount), - dest.Slice(0, adjustedCount)); + ByteToNormalizedFloat(source[..adjustedCount], dest[..adjustedCount]); - source = source.Slice(adjustedCount); - dest = dest.Slice(adjustedCount); + source = source[adjustedCount..]; + dest = dest[adjustedCount..]; } } @@ -58,11 +56,11 @@ namespace SixLabors.ImageSharp if (adjustedCount > 0) { NormalizedFloatToByteSaturate( - source.Slice(0, adjustedCount), - dest.Slice(0, adjustedCount)); + source[..adjustedCount], + dest[..adjustedCount]); - source = source.Slice(adjustedCount); - dest = dest.Slice(adjustedCount); + source = source[adjustedCount..]; + dest = dest[adjustedCount..]; } } @@ -83,7 +81,7 @@ namespace SixLabors.ImageSharp ref ByteVector4 sBase = ref Unsafe.As(ref MemoryMarshal.GetReference(source)); ref Vector4 dBase = ref Unsafe.As(ref MemoryMarshal.GetReference(dest)); - const float Scale = 1f / 255f; + const float scale = 1f / 255f; Vector4 d = default; for (int i = 0; i < count; i++) @@ -93,7 +91,7 @@ namespace SixLabors.ImageSharp d.Y = s.Y; d.Z = s.Z; d.W = s.W; - d *= Scale; + d *= scale; Unsafe.Add(ref dBase, i) = d; } } diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs b/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs index 01b68f9fa..54f511bf3 100644 --- a/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs +++ b/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#if SUPPORTS_RUNTIME_INTRINSICS using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -63,12 +62,12 @@ namespace SixLabors.ImageSharp if (adjustedCount > 0) { Shuffle4( - source.Slice(0, adjustedCount), - dest.Slice(0, adjustedCount), + source[..adjustedCount], + dest[..adjustedCount], control); - source = source.Slice(adjustedCount); - dest = dest.Slice(adjustedCount); + source = source[adjustedCount..]; + dest = dest[adjustedCount..]; } } } @@ -97,12 +96,12 @@ namespace SixLabors.ImageSharp if (adjustedCount > 0) { Shuffle4( - source.Slice(0, adjustedCount), - dest.Slice(0, adjustedCount), + source[..adjustedCount], + dest[..adjustedCount], control); - source = source.Slice(adjustedCount); - dest = dest.Slice(adjustedCount); + source = source[adjustedCount..]; + dest = dest[adjustedCount..]; } } } @@ -129,12 +128,12 @@ namespace SixLabors.ImageSharp if (adjustedCount > 0) { Shuffle3( - source.Slice(0, adjustedCount), - dest.Slice(0, adjustedCount), + source[..adjustedCount], + dest[..adjustedCount], control); - source = source.Slice(adjustedCount); - dest = dest.Slice(adjustedCount); + source = source[adjustedCount..]; + dest = dest[adjustedCount..]; } } } @@ -162,12 +161,12 @@ namespace SixLabors.ImageSharp if (sourceCount > 0) { Pad3Shuffle4( - source.Slice(0, sourceCount), - dest.Slice(0, destCount), + source[..sourceCount], + dest[..destCount], control); - source = source.Slice(sourceCount); - dest = dest.Slice(destCount); + source = source[sourceCount..]; + dest = dest[destCount..]; } } } @@ -195,12 +194,12 @@ namespace SixLabors.ImageSharp if (sourceCount > 0) { Shuffle4Slice3( - source.Slice(0, sourceCount), - dest.Slice(0, destCount), + source[..sourceCount], + dest[..destCount], control); - source = source.Slice(sourceCount); - dest = dest.Slice(destCount); + source = source[sourceCount..]; + dest = dest[destCount..]; } } } @@ -603,10 +602,10 @@ namespace SixLabors.ImageSharp if (adjustedCount > 0) { - ByteToNormalizedFloat(source.Slice(0, adjustedCount), dest.Slice(0, adjustedCount)); + ByteToNormalizedFloat(source[..adjustedCount], dest[..adjustedCount]); - source = source.Slice(adjustedCount); - dest = dest.Slice(adjustedCount); + source = source[adjustedCount..]; + dest = dest[adjustedCount..]; } } } @@ -736,11 +735,11 @@ namespace SixLabors.ImageSharp if (adjustedCount > 0) { NormalizedFloatToByteSaturate( - source.Slice(0, adjustedCount), - dest.Slice(0, adjustedCount)); + source[..adjustedCount], + dest[..adjustedCount]); - source = source.Slice(adjustedCount); - dest = dest.Slice(adjustedCount); + source = source[adjustedCount..]; + dest = dest[adjustedCount..]; } } } @@ -844,13 +843,12 @@ namespace SixLabors.ImageSharp int count = redChannel.Length / Vector256.Count; - ref byte control1Bytes = ref MemoryMarshal.GetReference(SimdUtils.HwIntrinsics.PermuteMaskEvenOdd8x32); + ref byte control1Bytes = ref MemoryMarshal.GetReference(PermuteMaskEvenOdd8x32); Vector256 control1 = Unsafe.As>(ref control1Bytes); ref byte control2Bytes = ref MemoryMarshal.GetReference(PermuteMaskShiftAlpha8x32); Vector256 control2 = Unsafe.As>(ref control2Bytes); - - Vector256 a = Vector256.Create((byte)255); + var a = Vector256.Create((byte)255); Vector256 shuffleAlpha = Unsafe.As>(ref MemoryMarshal.GetReference(ShuffleMaskShiftAlpha)); @@ -898,10 +896,10 @@ namespace SixLabors.ImageSharp } int slice = count * Vector256.Count; - redChannel = redChannel.Slice(slice); - greenChannel = greenChannel.Slice(slice); - blueChannel = blueChannel.Slice(slice); - destination = destination.Slice(slice); + redChannel = redChannel[slice..]; + greenChannel = greenChannel[slice..]; + blueChannel = blueChannel[slice..]; + destination = destination[slice..]; } internal static void PackFromRgbPlanesAvx2Reduce( @@ -916,16 +914,9 @@ namespace SixLabors.ImageSharp ref Vector256 dBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(destination)); int count = redChannel.Length / Vector256.Count; - - ref byte control1Bytes = ref MemoryMarshal.GetReference(SimdUtils.HwIntrinsics.PermuteMaskEvenOdd8x32); + ref byte control1Bytes = ref MemoryMarshal.GetReference(PermuteMaskEvenOdd8x32); Vector256 control1 = Unsafe.As>(ref control1Bytes); - - ref byte control2Bytes = ref MemoryMarshal.GetReference(PermuteMaskShiftAlpha8x32); - Vector256 control2 = Unsafe.As>(ref control2Bytes); - - Vector256 a = Vector256.Create((byte)255); - - Vector256 shuffleAlpha = Unsafe.As>(ref MemoryMarshal.GetReference(ShuffleMaskShiftAlpha)); + var a = Vector256.Create((byte)255); for (int i = 0; i < count; i++) { @@ -957,12 +948,11 @@ namespace SixLabors.ImageSharp } int slice = count * Vector256.Count; - redChannel = redChannel.Slice(slice); - greenChannel = greenChannel.Slice(slice); - blueChannel = blueChannel.Slice(slice); - destination = destination.Slice(slice); + redChannel = redChannel[slice..]; + greenChannel = greenChannel[slice..]; + blueChannel = blueChannel[slice..]; + destination = destination[slice..]; } } } } -#endif diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.Pack.cs b/src/ImageSharp/Common/Helpers/SimdUtils.Pack.cs index 3ee2086cf..0c33ffe0b 100644 --- a/src/ImageSharp/Common/Helpers/SimdUtils.Pack.cs +++ b/src/ImageSharp/Common/Helpers/SimdUtils.Pack.cs @@ -4,10 +4,8 @@ using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using SixLabors.ImageSharp.PixelFormats; -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.Intrinsics.X86; -#endif +using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp { @@ -15,7 +13,6 @@ namespace SixLabors.ImageSharp { [MethodImpl(InliningOptions.ShortMethod)] internal static void PackFromRgbPlanes( - Configuration configuration, ReadOnlySpan redChannel, ReadOnlySpan greenChannel, ReadOnlySpan blueChannel, @@ -25,13 +22,11 @@ namespace SixLabors.ImageSharp DebugGuard.IsTrue(blueChannel.Length == redChannel.Length, nameof(blueChannel), "Channels must be of same size!"); DebugGuard.IsTrue(destination.Length > redChannel.Length + 2, nameof(destination), "'destination' must contain a padding of 3 elements!"); -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx2.IsSupported) { HwIntrinsics.PackFromRgbPlanesAvx2Reduce(ref redChannel, ref greenChannel, ref blueChannel, ref destination); } else -#endif { PackFromRgbPlanesScalarBatchedReduce(ref redChannel, ref greenChannel, ref blueChannel, ref destination); } @@ -41,7 +36,6 @@ namespace SixLabors.ImageSharp [MethodImpl(InliningOptions.ShortMethod)] internal static void PackFromRgbPlanes( - Configuration configuration, ReadOnlySpan redChannel, ReadOnlySpan greenChannel, ReadOnlySpan blueChannel, @@ -51,13 +45,11 @@ namespace SixLabors.ImageSharp DebugGuard.IsTrue(blueChannel.Length == redChannel.Length, nameof(blueChannel), "Channels must be of same size!"); DebugGuard.IsTrue(destination.Length > redChannel.Length, nameof(destination), "'destination' span should not be shorter than the source channels!"); -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx2.IsSupported) { HwIntrinsics.PackFromRgbPlanesAvx2Reduce(ref redChannel, ref greenChannel, ref blueChannel, ref destination); } else -#endif { PackFromRgbPlanesScalarBatchedReduce(ref redChannel, ref greenChannel, ref blueChannel, ref destination); } @@ -106,10 +98,10 @@ namespace SixLabors.ImageSharp } int finished = count * 4; - redChannel = redChannel.Slice(finished); - greenChannel = greenChannel.Slice(finished); - blueChannel = blueChannel.Slice(finished); - destination = destination.Slice(finished); + redChannel = redChannel[finished..]; + greenChannel = greenChannel[finished..]; + blueChannel = blueChannel[finished..]; + destination = destination[finished..]; } private static void PackFromRgbPlanesScalarBatchedReduce( @@ -154,10 +146,10 @@ namespace SixLabors.ImageSharp } int finished = count * 4; - redChannel = redChannel.Slice(finished); - greenChannel = greenChannel.Slice(finished); - blueChannel = blueChannel.Slice(finished); - destination = destination.Slice(finished); + redChannel = redChannel[finished..]; + greenChannel = greenChannel[finished..]; + blueChannel = blueChannel[finished..]; + destination = destination[finished..]; } private static void PackFromRgbPlanesRemainder( diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.Shuffle.cs b/src/ImageSharp/Common/Helpers/SimdUtils.Shuffle.cs index db86afd64..1459601ea 100644 --- a/src/ImageSharp/Common/Helpers/SimdUtils.Shuffle.cs +++ b/src/ImageSharp/Common/Helpers/SimdUtils.Shuffle.cs @@ -25,9 +25,7 @@ namespace SixLabors.ImageSharp { VerifyShuffle4SpanInput(source, dest); -#if SUPPORTS_RUNTIME_INTRINSICS HwIntrinsics.Shuffle4Reduce(ref source, ref dest, control); -#endif // Deal with the remainder: if (source.Length > 0) @@ -52,9 +50,7 @@ namespace SixLabors.ImageSharp { VerifyShuffle4SpanInput(source, dest); -#if SUPPORTS_RUNTIME_INTRINSICS HwIntrinsics.Shuffle4Reduce(ref source, ref dest, shuffle.Control); -#endif // Deal with the remainder: if (source.Length > 0) @@ -80,9 +76,7 @@ namespace SixLabors.ImageSharp // Source length should be smaller than dest length, and divisible by 3. VerifyShuffle3SpanInput(source, dest); -#if SUPPORTS_RUNTIME_INTRINSICS HwIntrinsics.Shuffle3Reduce(ref source, ref dest, shuffle.Control); -#endif // Deal with the remainder: if (source.Length > 0) @@ -107,9 +101,7 @@ namespace SixLabors.ImageSharp { VerifyPad3Shuffle4SpanInput(source, dest); -#if SUPPORTS_RUNTIME_INTRINSICS HwIntrinsics.Pad3Shuffle4Reduce(ref source, ref dest, shuffle.Control); -#endif // Deal with the remainder: if (source.Length > 0) @@ -134,9 +126,7 @@ namespace SixLabors.ImageSharp { VerifyShuffle4Slice3SpanInput(source, dest); -#if SUPPORTS_RUNTIME_INTRINSICS HwIntrinsics.Shuffle4Slice3Reduce(ref source, ref dest, shuffle.Control); -#endif // Deal with the remainder: if (source.Length > 0) @@ -266,10 +256,10 @@ namespace SixLabors.ImageSharp out int p1, out int p0) { - p3 = control >> 6 & 0x3; - p2 = control >> 4 & 0x3; - p1 = control >> 2 & 0x3; - p0 = control >> 0 & 0x3; + p3 = (control >> 6) & 0x3; + p2 = (control >> 4) & 0x3; + p1 = (control >> 2) & 0x3; + p0 = (control >> 0) & 0x3; } } } diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.cs b/src/ImageSharp/Common/Helpers/SimdUtils.cs index 0384cc4ed..1a8d50a5d 100644 --- a/src/ImageSharp/Common/Helpers/SimdUtils.cs +++ b/src/ImageSharp/Common/Helpers/SimdUtils.cs @@ -6,11 +6,8 @@ using System.Diagnostics; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using SixLabors.ImageSharp.PixelFormats; -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; -#endif namespace SixLabors.ImageSharp { @@ -56,8 +53,6 @@ namespace SixLabors.ImageSharp [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static Vector FastRound(this Vector v) { -#if SUPPORTS_RUNTIME_INTRINSICS - if (Avx2.IsSupported) { ref Vector256 v256 = ref Unsafe.As, Vector256>(ref v); @@ -65,7 +60,6 @@ namespace SixLabors.ImageSharp return Unsafe.As, Vector>(ref vRound); } else -#endif { var magic0 = new Vector(int.MinValue); // 0x80000000 var sgn0 = Vector.AsVectorSingle(magic0); @@ -87,13 +81,8 @@ namespace SixLabors.ImageSharp internal static void ByteToNormalizedFloat(ReadOnlySpan source, Span dest) { DebugGuard.IsTrue(source.Length == dest.Length, nameof(source), "Input spans must be of same length!"); -#if SUPPORTS_RUNTIME_INTRINSICS + HwIntrinsics.ByteToNormalizedFloatReduce(ref source, ref dest); -#elif SUPPORTS_EXTENDED_INTRINSICS - ExtendedIntrinsics.ByteToNormalizedFloatReduce(ref source, ref dest); -#else - BasicIntrinsics256.ByteToNormalizedFloatReduce(ref source, ref dest); -#endif // Also deals with the remainder from previous conversions: FallbackIntrinsics128.ByteToNormalizedFloatReduce(ref source, ref dest); @@ -118,13 +107,7 @@ namespace SixLabors.ImageSharp { DebugGuard.IsTrue(source.Length == dest.Length, nameof(source), "Input spans must be of same length!"); -#if SUPPORTS_RUNTIME_INTRINSICS HwIntrinsics.NormalizedFloatToByteSaturateReduce(ref source, ref dest); -#elif SUPPORTS_EXTENDED_INTRINSICS - ExtendedIntrinsics.NormalizedFloatToByteSaturateReduce(ref source, ref dest); -#else - BasicIntrinsics256.NormalizedFloatToByteSaturateReduce(ref source, ref dest); -#endif // Also deals with the remainder from previous conversions: FallbackIntrinsics128.NormalizedFloatToByteSaturateReduce(ref source, ref dest); diff --git a/src/ImageSharp/Compression/Zlib/Adler32.cs b/src/ImageSharp/Compression/Zlib/Adler32.cs index 7c3b4ae18..d8234e1b8 100644 --- a/src/ImageSharp/Compression/Zlib/Adler32.cs +++ b/src/ImageSharp/Compression/Zlib/Adler32.cs @@ -4,10 +4,8 @@ using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; -#endif #pragma warning disable IDE0007 // Use implicit type namespace SixLabors.ImageSharp.Compression.Zlib @@ -29,7 +27,6 @@ namespace SixLabors.ImageSharp.Compression.Zlib // NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 private const uint NMAX = 5552; -#if SUPPORTS_RUNTIME_INTRINSICS private const int MinBufferSize = 64; private const int BlockSize = 1 << 5; @@ -40,7 +37,6 @@ namespace SixLabors.ImageSharp.Compression.Zlib 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, // tap1 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 // tap2 }; -#endif /// /// Calculates the Adler32 checksum with the bytes taken from the span. @@ -65,7 +61,6 @@ namespace SixLabors.ImageSharp.Compression.Zlib return adler; } -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx2.IsSupported && buffer.Length >= MinBufferSize) { return CalculateAvx2(adler, buffer); @@ -77,13 +72,9 @@ namespace SixLabors.ImageSharp.Compression.Zlib } return CalculateScalar(adler, buffer); -#else - return CalculateScalar(adler, buffer); -#endif } // Based on https://github.com/chromium/chromium/blob/master/third_party/zlib/adler32_simd.c -#if SUPPORTS_RUNTIME_INTRINSICS [MethodImpl(InliningOptions.HotPath | InliningOptions.ShortMethod)] private static unsafe uint CalculateSse(uint adler, ReadOnlySpan buffer) { @@ -149,15 +140,15 @@ namespace SixLabors.ImageSharp.Compression.Zlib v_s2 = Sse2.Add(v_s2, Sse2.ShiftLeftLogical(v_ps, 5)); // Sum epi32 ints v_s1(s2) and accumulate in s1(s2). - const byte S2301 = 0b1011_0001; // A B C D -> B A D C - const byte S1032 = 0b0100_1110; // A B C D -> C D A B + const byte s2301 = 0b1011_0001; // A B C D -> B A D C + const byte s1032 = 0b0100_1110; // A B C D -> C D A B - v_s1 = Sse2.Add(v_s1, Sse2.Shuffle(v_s1, S1032)); + v_s1 = Sse2.Add(v_s1, Sse2.Shuffle(v_s1, s1032)); s1 += v_s1.ToScalar(); - v_s2 = Sse2.Add(v_s2, Sse2.Shuffle(v_s2, S2301)); - v_s2 = Sse2.Add(v_s2, Sse2.Shuffle(v_s2, S1032)); + v_s2 = Sse2.Add(v_s2, Sse2.Shuffle(v_s2, s2301)); + v_s2 = Sse2.Add(v_s2, Sse2.Shuffle(v_s2, s1032)); s2 = v_s2.ToScalar(); @@ -290,7 +281,6 @@ namespace SixLabors.ImageSharp.Compression.Zlib s2 %= BASE; } -#endif [MethodImpl(InliningOptions.HotPath | InliningOptions.ShortMethod)] private static unsafe uint CalculateScalar(uint adler, ReadOnlySpan buffer) @@ -301,7 +291,7 @@ namespace SixLabors.ImageSharp.Compression.Zlib fixed (byte* bufferPtr = buffer) { - var localBufferPtr = bufferPtr; + byte* localBufferPtr = bufferPtr; uint length = (uint)buffer.Length; while (length > 0) diff --git a/src/ImageSharp/Compression/Zlib/Crc32.cs b/src/ImageSharp/Compression/Zlib/Crc32.cs index 0d900cc17..757682a3f 100644 --- a/src/ImageSharp/Compression/Zlib/Crc32.cs +++ b/src/ImageSharp/Compression/Zlib/Crc32.cs @@ -4,10 +4,8 @@ using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; -#endif namespace SixLabors.ImageSharp.Compression.Zlib { @@ -22,7 +20,6 @@ namespace SixLabors.ImageSharp.Compression.Zlib /// public const uint SeedValue = 0U; -#if SUPPORTS_RUNTIME_INTRINSICS private const int MinBufferSize = 64; private const int ChunksizeMask = 15; @@ -35,7 +32,6 @@ namespace SixLabors.ImageSharp.Compression.Zlib 0x0163cd6124, 0x0000000000, // k5, k0 0x01db710641, 0x01f7011641 // polynomial }; -#endif /// /// Calculates the CRC checksum with the bytes taken from the span. @@ -60,21 +56,14 @@ namespace SixLabors.ImageSharp.Compression.Zlib return crc; } -#if SUPPORTS_RUNTIME_INTRINSICS if (Sse41.IsSupported && Pclmulqdq.IsSupported && buffer.Length >= MinBufferSize) { return ~CalculateSse(~crc, buffer); } - else - { - return ~CalculateScalar(~crc, buffer); - } -#else + return ~CalculateScalar(~crc, buffer); -#endif } -#if SUPPORTS_RUNTIME_INTRINSICS // Based on https://github.com/chromium/chromium/blob/master/third_party/zlib/crc32_simd.c [MethodImpl(InliningOptions.HotPath | InliningOptions.ShortMethod)] private static unsafe uint CalculateSse(uint crc, ReadOnlySpan buffer) @@ -194,11 +183,10 @@ namespace SixLabors.ImageSharp.Compression.Zlib x1 = Sse2.Xor(x1, x2); crc = (uint)Sse41.Extract(x1.AsInt32(), 1); - return buffer.Length - chunksize == 0 ? crc : CalculateScalar(crc, buffer.Slice(chunksize)); + return buffer.Length - chunksize == 0 ? crc : CalculateScalar(crc, buffer[chunksize..]); } } } -#endif [MethodImpl(InliningOptions.HotPath | InliningOptions.ShortMethod)] private static uint CalculateScalar(uint crc, ReadOnlySpan buffer) diff --git a/src/ImageSharp/Compression/Zlib/DeflaterEngine.cs b/src/ImageSharp/Compression/Zlib/DeflaterEngine.cs index a77c22bf8..2d19aabb5 100644 --- a/src/ImageSharp/Compression/Zlib/DeflaterEngine.cs +++ b/src/ImageSharp/Compression/Zlib/DeflaterEngine.cs @@ -276,8 +276,8 @@ namespace SixLabors.ImageSharp.Compression.Zlib this.lookahead = 0; this.prevAvailable = false; this.matchLen = DeflaterConstants.MIN_MATCH - 1; - this.head.Span.Slice(0, DeflaterConstants.HASH_SIZE).Clear(); - this.prev.Span.Slice(0, DeflaterConstants.WSIZE).Clear(); + this.head.Span[..DeflaterConstants.HASH_SIZE].Clear(); + this.prev.Span[..DeflaterConstants.WSIZE].Clear(); } /// @@ -286,7 +286,7 @@ namespace SixLabors.ImageSharp.Compression.Zlib /// The value to set the level to. public void SetLevel(int level) { - if ((level < 0) || (level > 9)) + if (level is < 0 or > 9) { DeflateThrowHelper.ThrowOutOfRange(nameof(level)); } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8.Intrinsic.cs b/src/ImageSharp/Formats/Jpeg/Components/Block8x8.Intrinsic.cs index 8eba118fd..82eb8324a 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8.Intrinsic.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8.Intrinsic.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.InteropServices; using System.Runtime.Intrinsics; @@ -36,4 +35,3 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components public Vector256 V67; } } -#endif diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8.cs b/src/ImageSharp/Formats/Jpeg/Components/Block8x8.cs index d83edbd5b..86c69a8be 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8.cs @@ -5,10 +5,8 @@ using System; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; -#endif using System.Text; namespace SixLabors.ImageSharp.Formats.Jpeg.Components @@ -173,7 +171,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components [MethodImpl(InliningOptions.ShortMethod)] public nint GetLastNonZeroIndex() { -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx2.IsSupported) { const int equalityMask = unchecked((int)0b1111_1111_1111_1111_1111_1111_1111_1111); @@ -207,7 +204,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components return -1; } else -#endif { nint index = Size - 1; ref short elemRef = ref Unsafe.As(ref this); @@ -271,12 +267,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components // row #6 Swap(ref Unsafe.Add(ref elemRef, 55), ref Unsafe.Add(ref elemRef, 62)); - static void Swap(ref short a, ref short b) - { - short tmp = a; - a = b; - b = tmp; - } + static void Swap(ref short a, ref short b) => (b, a) = (a, b); } /// diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Intrinsic.cs b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Intrinsic.cs index 2a03f911b..4c19510b7 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Intrinsic.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Intrinsic.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#if SUPPORTS_RUNTIME_INTRINSICS using System; using System.Numerics; using System.Runtime.CompilerServices; @@ -43,7 +42,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components ref Vector256 bBase = ref b.V0; ref Vector256 destRef = ref dest.V01; - Vector256 multiplyIntoInt16ShuffleMask = Vector256.Create(0, 1, 4, 5, 2, 3, 6, 7); + var multiplyIntoInt16ShuffleMask = Vector256.Create(0, 1, 4, 5, 2, 3, 6, 7); for (nint i = 0; i < 8; i += 2) { @@ -145,4 +144,3 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components } } } -#endif diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs index 6faaadac7..7466d74f4 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs @@ -5,10 +5,8 @@ using System; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; -#endif using System.Text; // ReSharper disable InconsistentNaming @@ -160,7 +158,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components [MethodImpl(InliningOptions.ShortMethod)] public void MultiplyInPlace(float value) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx.IsSupported) { var valueVec = Vector256.Create(value); @@ -174,7 +171,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components this.V7 = Avx.Multiply(this.V7, valueVec); } else -#endif { var valueVec = new Vector4(value); this.V0L *= valueVec; @@ -202,7 +198,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components [MethodImpl(InliningOptions.ShortMethod)] public unsafe void MultiplyInPlace(ref Block8x8F other) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx.IsSupported) { this.V0 = Avx.Multiply(this.V0, other.V0); @@ -215,7 +210,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components this.V7 = Avx.Multiply(this.V7, other.V7); } else -#endif { this.V0L *= other.V0L; this.V0R *= other.V0R; @@ -243,7 +237,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components [MethodImpl(InliningOptions.ShortMethod)] public void AddInPlace(float value) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx.IsSupported) { var valueVec = Vector256.Create(value); @@ -257,7 +250,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components this.V7 = Avx.Add(this.V7, valueVec); } else -#endif { var valueVec = new Vector4(value); this.V0L += valueVec; @@ -287,7 +279,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components /// The quantization table. public static void Quantize(ref Block8x8F block, ref Block8x8 dest, ref Block8x8F qt) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx2.IsSupported) { MultiplyIntoInt16_Avx2(ref block, ref qt, ref dest); @@ -299,7 +290,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components ZigZag.ApplyTransposingZigZagOrderingSsse3(ref dest); } else -#endif { for (int i = 0; i < Size; i++) { @@ -366,13 +356,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components [MethodImpl(InliningOptions.ShortMethod)] public void LoadFrom(ref Block8x8 source) { -#if SUPPORTS_EXTENDED_INTRINSICS if (SimdUtils.HasVector8) { this.LoadFromInt16ExtendedAvx2(ref source); return; } -#endif + this.LoadFromInt16Scalar(ref source); } @@ -414,7 +403,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components /// Value to compare to. public bool EqualsToScalar(int value) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx2.IsSupported) { const int equalityMask = unchecked((int)0b1111_1111_1111_1111_1111_1111_1111_1111); @@ -433,20 +421,18 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components return true; } -#endif - { - ref float scalars = ref Unsafe.As(ref this); - for (int i = 0; i < Size; i++) + ref float scalars = ref Unsafe.As(ref this); + + for (int i = 0; i < Size; i++) + { + if ((int)Unsafe.Add(ref scalars, i) != value) { - if ((int)Unsafe.Add(ref scalars, i) != value) - { - return false; - } + return false; } - - return true; } + + return true; } /// @@ -491,13 +477,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components [MethodImpl(InliningOptions.ShortMethod)] public void TransposeInplace() { -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx.IsSupported) { this.TransposeInplace_Avx(); } else -#endif { this.TransposeInplace_Scalar(); } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykAvx.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykAvx.cs index 7955600b5..718f45e57 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykAvx.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykAvx.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Intrinsics; @@ -49,4 +48,3 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters } } } -#endif diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleAvx.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleAvx.cs index 261d76a31..019e02209 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleAvx.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleAvx.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Intrinsics; @@ -36,4 +35,3 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters } } } -#endif diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbAvx.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbAvx.cs index 93dfe4688..39b043b4c 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbAvx.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbAvx.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Intrinsics; @@ -43,4 +42,3 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters } } } -#endif diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrAvx.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrAvx.cs index 2167c8686..fb8808136 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrAvx.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrAvx.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Intrinsics; @@ -71,4 +70,3 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters } } } -#endif diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKAvx.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKAvx.cs index 8b5f8463d..04465b82b 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKAvx.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKAvx.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Intrinsics; @@ -79,4 +78,3 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters } } } -#endif diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverterAvx.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverterAvx.cs index b333d3268..8c0db38d7 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverterAvx.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverterAvx.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; @@ -32,4 +31,3 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters } } } -#endif diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverterBase.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverterBase.cs index 8339206b4..fb1ac1b74 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverterBase.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverterBase.cs @@ -117,9 +117,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters /// private static IEnumerable GetYCbCrConverters(int precision) { -#if SUPPORTS_RUNTIME_INTRINSICS yield return new FromYCbCrAvx(precision); -#endif yield return new FromYCbCrVector(precision); yield return new FromYCbCrScalar(precision); } @@ -129,9 +127,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters /// private static IEnumerable GetYccKConverters(int precision) { -#if SUPPORTS_RUNTIME_INTRINSICS yield return new FromYccKAvx(precision); -#endif yield return new FromYccKVector(precision); yield return new FromYccKScalar(precision); } @@ -141,9 +137,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters /// private static IEnumerable GetCmykConverters(int precision) { -#if SUPPORTS_RUNTIME_INTRINSICS yield return new FromCmykAvx(precision); -#endif yield return new FromCmykVector(precision); yield return new FromCmykScalar(precision); } @@ -153,9 +147,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters /// private static IEnumerable GetGrayScaleConverters(int precision) { -#if SUPPORTS_RUNTIME_INTRINSICS yield return new FromGrayscaleAvx(precision); -#endif yield return new FromGrayScaleVector(precision); yield return new FromGrayscaleScalar(precision); } @@ -165,9 +157,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters /// private static IEnumerable GetRgbConverters(int precision) { -#if SUPPORTS_RUNTIME_INTRINSICS yield return new FromRgbAvx(precision); -#endif yield return new FromRgbVector(precision); yield return new FromRgbScalar(precision); } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs b/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs index 24ab9f8d1..7d4d95a01 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs @@ -558,7 +558,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder internal static int GetHuffmanEncodingLength(uint value) { DebugGuard.IsTrue(value <= (1 << 16), "Huffman encoder is supposed to encode a value of 16bit size max"); -#if SUPPORTS_BITOPERATIONS + // This should have been implemented as (BitOperations.Log2(value) + 1) as in non-intrinsic implementation // But internal log2 is implemented like this: (31 - (int)Lzcnt.LeadingZeroCount(value)) @@ -567,19 +567,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder // Fallback code if Lzcnt is not supported still use if-check // But most modern CPUs support this instruction so this should not be a problem return 32 - BitOperations.LeadingZeroCount(value); -#else - // Ideally: - // if 0 - return 0 in this case - // else - return log2(value) + 1 - // - // Hack based on input value constraint: - // We know that input values are guaranteed to be maximum 16 bit large for huffman encoding - // We can safely shift input value for one bit -> log2(value << 1) - // Because of the 16 bit value constraint it won't overflow - // With that input value change we no longer need to add 1 before returning - // And this eliminates need to check if input value is zero - it is a standard convention which Log2SoftwareFallback adheres to - return Numerics.Log2(value << 1); -#endif } /// diff --git a/src/ImageSharp/Formats/Jpeg/Components/Encoder/LuminanceForwardConverter{TPixel}.cs b/src/ImageSharp/Formats/Jpeg/Components/Encoder/LuminanceForwardConverter{TPixel}.cs index 29a13d201..0291569d0 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Encoder/LuminanceForwardConverter{TPixel}.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Encoder/LuminanceForwardConverter{TPixel}.cs @@ -5,10 +5,8 @@ using System; using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; -#endif using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.PixelFormats; @@ -98,16 +96,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder { Debug.Assert(RgbToYCbCrConverterVectorized.IsSupported, "AVX2 is required to run this converter"); -#if SUPPORTS_RUNTIME_INTRINSICS ref Vector128 l8ByteSpan = ref Unsafe.As>(ref l8Start); ref Vector256 destRef = ref yBlock.V0; const int bytesPerL8Stride = 8; for (nint i = 0; i < 8; i++) { - Unsafe.Add(ref destRef, i) = Avx2.ConvertToVector256Single(Avx2.ConvertToVector256Int32(Unsafe.AddByteOffset(ref l8ByteSpan, bytesPerL8Stride * i))); + Unsafe.Add(ref destRef, i) = Avx.ConvertToVector256Single(Avx2.ConvertToVector256Int32(Unsafe.AddByteOffset(ref l8ByteSpan, bytesPerL8Stride * i))); } -#endif } /// diff --git a/src/ImageSharp/Formats/Jpeg/Components/Encoder/RgbForwardConverter{TPixel}.cs b/src/ImageSharp/Formats/Jpeg/Components/Encoder/RgbForwardConverter{TPixel}.cs index 3c1daadb0..7b7c6196c 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Encoder/RgbForwardConverter{TPixel}.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Encoder/RgbForwardConverter{TPixel}.cs @@ -5,10 +5,8 @@ using System; using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; -#endif using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.PixelFormats; @@ -120,15 +118,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder { Debug.Assert(RgbToYCbCrConverterVectorized.IsSupported, "AVX2 is required to run this converter"); -#if SUPPORTS_RUNTIME_INTRINSICS ref Vector256 rgbByteSpan = ref Unsafe.As>(ref MemoryMarshal.GetReference(rgbSpan)); ref Vector256 redRef = ref rBlock.V0; ref Vector256 greenRef = ref gBlock.V0; ref Vector256 blueRef = ref bBlock.V0; - var zero = Vector256.Create(0).AsByte(); + Vector256 zero = Vector256.Create(0).AsByte(); - var extractToLanesMask = Unsafe.As>(ref MemoryMarshal.GetReference(RgbToYCbCrConverterVectorized.MoveFirst24BytesToSeparateLanes)); - var extractRgbMask = Unsafe.As>(ref MemoryMarshal.GetReference(RgbToYCbCrConverterVectorized.ExtractRgb)); + Vector256 extractToLanesMask = Unsafe.As>(ref MemoryMarshal.GetReference(RgbToYCbCrConverterVectorized.MoveFirst24BytesToSeparateLanes)); + Vector256 extractRgbMask = Unsafe.As>(ref MemoryMarshal.GetReference(RgbToYCbCrConverterVectorized.ExtractRgb)); Vector256 rgb, rg, bx; const int bytesPerRgbStride = 24; @@ -145,7 +142,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder Unsafe.Add(ref greenRef, i) = Avx.ConvertToVector256Single(Avx2.UnpackHigh(rg, zero).AsInt32()); Unsafe.Add(ref blueRef, i) = Avx.ConvertToVector256Single(Avx2.UnpackLow(bx, zero).AsInt32()); } -#endif } private static void ConvertScalar(Span rgbSpan, ref Block8x8F redBlock, ref Block8x8F greenBlock, ref Block8x8F blueBlock) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Encoder/RgbToYCbCrConverterVectorized.cs b/src/ImageSharp/Formats/Jpeg/Components/Encoder/RgbToYCbCrConverterVectorized.cs index c2bc8cfb8..71de4f75a 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Encoder/RgbToYCbCrConverterVectorized.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Encoder/RgbToYCbCrConverterVectorized.cs @@ -3,29 +3,17 @@ using System; using System.Diagnostics; -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; -#endif using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder { internal static class RgbToYCbCrConverterVectorized { - public static bool IsSupported - { - get - { -#if SUPPORTS_RUNTIME_INTRINSICS - return Avx2.IsSupported; -#else - return false; -#endif - } - } + public static bool IsSupported => Avx2.IsSupported; public static int AvxCompatibilityPadding { @@ -48,18 +36,15 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder // 8 byte padding to rgb byte span will solve this problem without extra code in converters get { -#if SUPPORTS_RUNTIME_INTRINSICS if (IsSupported) { return 8; } -#endif + return 0; } } -#if SUPPORTS_RUNTIME_INTRINSICS - internal static ReadOnlySpan MoveFirst24BytesToSeparateLanes => new byte[] { 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 6, 0, 0, 0, @@ -71,7 +56,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder 0, 3, 6, 9, 1, 4, 7, 10, 2, 5, 8, 11, 0xFF, 0xFF, 0xFF, 0xFF, 0, 3, 6, 9, 1, 4, 7, 10, 2, 5, 8, 11, 0xFF, 0xFF, 0xFF, 0xFF }; -#endif /// /// Converts 8x8 Rgb24 pixel matrix to YCbCr pixel matrices with 4:4:4 subsampling @@ -85,7 +69,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder { Debug.Assert(IsSupported, "AVX2 is required to run this converter"); -#if SUPPORTS_RUNTIME_INTRINSICS var f0299 = Vector256.Create(0.299f); var f0587 = Vector256.Create(0.587f); var f0114 = Vector256.Create(0.114f); @@ -95,15 +78,15 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder var fn0418688 = Vector256.Create(-0.418688f); var fn0081312F = Vector256.Create(-0.081312F); var f05 = Vector256.Create(0.5f); - var zero = Vector256.Create(0).AsByte(); + Vector256 zero = Vector256.Create(0).AsByte(); ref Vector256 rgbByteSpan = ref Unsafe.As>(ref MemoryMarshal.GetReference(rgbSpan)); ref Vector256 destYRef = ref yBlock.V0; ref Vector256 destCbRef = ref cbBlock.V0; ref Vector256 destCrRef = ref crBlock.V0; - var extractToLanesMask = Unsafe.As>(ref MemoryMarshal.GetReference(MoveFirst24BytesToSeparateLanes)); - var extractRgbMask = Unsafe.As>(ref MemoryMarshal.GetReference(ExtractRgb)); + Vector256 extractToLanesMask = Unsafe.As>(ref MemoryMarshal.GetReference(MoveFirst24BytesToSeparateLanes)); + Vector256 extractRgbMask = Unsafe.As>(ref MemoryMarshal.GetReference(ExtractRgb)); Vector256 rgb, rg, bx; Vector256 r, g, b; @@ -130,7 +113,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder // 128F + ((0.5F * r) - (0.418688F * g) - (0.081312F * b)) Unsafe.Add(ref destCrRef, i) = Avx.Add(f128, SimdUtils.HwIntrinsics.MultiplyAdd(SimdUtils.HwIntrinsics.MultiplyAdd(Avx.Multiply(fn0081312F, b), fn0418688, g), f05, r)); } -#endif } /// @@ -140,7 +122,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder { Debug.Assert(IsSupported, "AVX2 is required to run this converter"); -#if SUPPORTS_RUNTIME_INTRINSICS var f0299 = Vector256.Create(0.299f); var f0587 = Vector256.Create(0.587f); var f0114 = Vector256.Create(0.114f); @@ -150,7 +131,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder var fn0418688 = Vector256.Create(-0.418688f); var fn0081312F = Vector256.Create(-0.081312F); var f05 = Vector256.Create(0.5f); - var zero = Vector256.Create(0).AsByte(); + Vector256 zero = Vector256.Create(0).AsByte(); ref Vector256 rgbByteSpan = ref Unsafe.As>(ref MemoryMarshal.GetReference(rgbSpan)); @@ -159,8 +140,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder ref Vector256 destCbRef = ref Unsafe.Add(ref Unsafe.As>(ref cbBlock), destOffset); ref Vector256 destCrRef = ref Unsafe.Add(ref Unsafe.As>(ref crBlock), destOffset); - var extractToLanesMask = Unsafe.As>(ref MemoryMarshal.GetReference(MoveFirst24BytesToSeparateLanes)); - var extractRgbMask = Unsafe.As>(ref MemoryMarshal.GetReference(ExtractRgb)); + Vector256 extractToLanesMask = Unsafe.As>(ref MemoryMarshal.GetReference(MoveFirst24BytesToSeparateLanes)); + Vector256 extractRgbMask = Unsafe.As>(ref MemoryMarshal.GetReference(ExtractRgb)); Vector256 rgb, rg, bx; Vector256 r, g, b; @@ -231,10 +212,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder // 128F + ((0.5F * r) - (0.418688F * g) - (0.081312F * b)) Unsafe.Add(ref destCrRef, i) = Avx.Add(f128, SimdUtils.HwIntrinsics.MultiplyAdd(SimdUtils.HwIntrinsics.MultiplyAdd(Avx.Multiply(fn0081312F, b), fn0418688, g), f05, r)); } -#endif } -#if SUPPORTS_RUNTIME_INTRINSICS /// /// Scales 16x2 matrix to 8x1 using 2x2 average /// @@ -254,6 +233,5 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder return Avx2.Permute4x64(avg2x2.AsDouble(), 0b11_01_10_00).AsSingle(); } -#endif } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/FloatingPointDCT.Intrinsic.cs b/src/ImageSharp/Formats/Jpeg/Components/FloatingPointDCT.Intrinsic.cs index 19349e454..4bc4181ff 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/FloatingPointDCT.Intrinsic.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/FloatingPointDCT.Intrinsic.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; @@ -45,7 +44,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components block.V0 = Avx.Add(tmp10, tmp11); block.V4 = Avx.Subtract(tmp10, tmp11); - Vector256 mm256_F_0_7071 = Vector256.Create(0.707106781f); + var mm256_F_0_7071 = Vector256.Create(0.707106781f); Vector256 z1 = Avx.Multiply(Avx.Add(tmp12, tmp13), mm256_F_0_7071); block.V2 = Avx.Add(tmp13, z1); block.V6 = Avx.Subtract(tmp13, z1); @@ -98,7 +97,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components Vector256 tmp10 = Avx.Add(z5, tmp2); Vector256 tmp11 = Avx.Subtract(z5, tmp2); - Vector256 mm256_F_1_4142 = Vector256.Create(1.414213562f); + var mm256_F_1_4142 = Vector256.Create(1.414213562f); Vector256 tmp13 = Avx.Add(tmp1, tmp3); Vector256 tmp12 = SimdUtils.HwIntrinsics.MultiplySubstract(tmp13, Avx.Subtract(tmp1, tmp3), mm256_F_1_4142); @@ -142,4 +141,3 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components } } } -#endif diff --git a/src/ImageSharp/Formats/Jpeg/Components/FloatingPointDCT.cs b/src/ImageSharp/Formats/Jpeg/Components/FloatingPointDCT.cs index 37ec6e190..cf0d69ef4 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/FloatingPointDCT.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/FloatingPointDCT.cs @@ -4,9 +4,7 @@ using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.Intrinsics.X86; -#endif // ReSharper disable InconsistentNaming namespace SixLabors.ImageSharp.Formats.Jpeg.Components @@ -112,13 +110,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components /// Input block. public static void TransformIDCT(ref Block8x8F block) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx.IsSupported) { IDCT8x8_Avx(ref block); } else -#endif { IDCT_Vector4(ref block); } @@ -134,13 +130,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components /// Input block. public static void TransformFDCT(ref Block8x8F block) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx.IsSupported) { FDCT8x8_Avx(ref block); } else -#endif { FDCT_Vector4(ref block); } diff --git a/src/ImageSharp/Formats/Jpeg/Components/ZigZag.Intrinsic.cs b/src/ImageSharp/Formats/Jpeg/Components/ZigZag.Intrinsic.cs index ee1ec501b..2fa1d835e 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/ZigZag.Intrinsic.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/ZigZag.Intrinsic.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#if SUPPORTS_RUNTIME_INTRINSICS using System; using System.Runtime.InteropServices; using System.Runtime.Intrinsics; @@ -304,4 +303,3 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components } } } -#endif diff --git a/src/ImageSharp/Formats/Png/Filters/AverageFilter.cs b/src/ImageSharp/Formats/Png/Filters/AverageFilter.cs index b381442bd..4471b355e 100644 --- a/src/ImageSharp/Formats/Png/Filters/AverageFilter.cs +++ b/src/ImageSharp/Formats/Png/Filters/AverageFilter.cs @@ -4,11 +4,8 @@ using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; - -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; -#endif namespace SixLabors.ImageSharp.Formats.Png.Filters { @@ -35,19 +32,16 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters // With pixels positioned like this: // prev: c b // row: a d -#if SUPPORTS_RUNTIME_INTRINSICS if (Sse2.IsSupported && bytesPerPixel is 4) { DecodeSse2(scanline, previousScanline); } else -#endif { DecodeScalar(scanline, previousScanline, bytesPerPixel); } } -#if SUPPORTS_RUNTIME_INTRINSICS [MethodImpl(MethodImplOptions.AggressiveInlining)] private static void DecodeSse2(Span scanline, Span previousScanline) { @@ -81,7 +75,6 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters offset += 4; } } -#endif [MethodImpl(MethodImplOptions.AggressiveInlining)] private static void DecodeScalar(Span scanline, Span previousScanline, int bytesPerPixel) @@ -139,7 +132,6 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters sum += Numerics.Abs(unchecked((sbyte)res)); } -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx2.IsSupported) { Vector256 zero = Vector256.Zero; @@ -210,7 +202,6 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters sum += Numerics.ReduceSum(sumAccumulator); } -#endif for (int xLeft = x - bytesPerPixel; x < scanline.Length; ++xLeft /* Note: ++x happens in the body to avoid one add operation */) { diff --git a/src/ImageSharp/Formats/Png/Filters/PaethFilter.cs b/src/ImageSharp/Formats/Png/Filters/PaethFilter.cs index 03d883454..0676f618b 100644 --- a/src/ImageSharp/Formats/Png/Filters/PaethFilter.cs +++ b/src/ImageSharp/Formats/Png/Filters/PaethFilter.cs @@ -5,11 +5,8 @@ using System; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; - -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; -#endif namespace SixLabors.ImageSharp.Formats.Png.Filters { @@ -38,20 +35,16 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters // row: a d // The Paeth function predicts d to be whichever of a, b, or c is nearest to // p = a + b - c. -#if SUPPORTS_RUNTIME_INTRINSICS if (Sse41.IsSupported && bytesPerPixel is 4) { DecodeSse41(scanline, previousScanline); } else -#endif { DecodeScalar(scanline, previousScanline, bytesPerPixel); } } -#if SUPPORTS_RUNTIME_INTRINSICS - [MethodImpl(MethodImplOptions.AggressiveInlining)] private static void DecodeSse41(Span scanline, Span previousScanline) { @@ -107,8 +100,6 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters } } -#endif - [MethodImpl(MethodImplOptions.AggressiveInlining)] private static void DecodeScalar(Span scanline, Span previousScanline, int bytesPerPixel) { @@ -168,7 +159,6 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters sum += Numerics.Abs(unchecked((sbyte)res)); } -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx2.IsSupported) { Vector256 zero = Vector256.Zero; @@ -213,7 +203,6 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters sum += (int)sumAccumulator[i]; } } -#endif for (int xLeft = x - bytesPerPixel; x < scanline.Length; ++xLeft /* Note: ++x happens in the body to avoid one add operation */) { @@ -261,7 +250,6 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters return upperLeft; } -#if SUPPORTS_RUNTIME_INTRINSICS private static Vector256 PaethPredictor(Vector256 left, Vector256 above, Vector256 upleft) { Vector256 zero = Vector256.Zero; @@ -324,6 +312,5 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters left: above, right: upperLeft)); } -#endif } } diff --git a/src/ImageSharp/Formats/Png/Filters/SubFilter.cs b/src/ImageSharp/Formats/Png/Filters/SubFilter.cs index a7044837e..063cc11c3 100644 --- a/src/ImageSharp/Formats/Png/Filters/SubFilter.cs +++ b/src/ImageSharp/Formats/Png/Filters/SubFilter.cs @@ -5,11 +5,8 @@ using System; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; - -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; -#endif namespace SixLabors.ImageSharp.Formats.Png.Filters { @@ -29,19 +26,16 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters public static void Decode(Span scanline, int bytesPerPixel) { // The Sub filter predicts each pixel as the previous pixel. -#if SUPPORTS_RUNTIME_INTRINSICS if (Sse2.IsSupported && bytesPerPixel is 4) { DecodeSse2(scanline); } else -#endif { DecodeScalar(scanline, bytesPerPixel); } } -#if SUPPORTS_RUNTIME_INTRINSICS private static void DecodeSse2(Span scanline) { ref byte scanBaseRef = ref MemoryMarshal.GetReference(scanline); @@ -64,7 +58,6 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters offset += 4; } } -#endif private static void DecodeScalar(Span scanline, int bytesPerPixel) { @@ -110,7 +103,6 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters sum += Numerics.Abs(unchecked((sbyte)res)); } -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx2.IsSupported) { Vector256 zero = Vector256.Zero; @@ -151,7 +143,6 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters sum += (int)sumAccumulator[i]; } } -#endif for (int xLeft = x - bytesPerPixel; x < scanline.Length; ++xLeft /* Note: ++x happens in the body to avoid one add operation */) { @@ -163,7 +154,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters sum += Numerics.Abs(unchecked((sbyte)res)); } - sum -= 1; + sum--; } } } diff --git a/src/ImageSharp/Formats/Png/Filters/UpFilter.cs b/src/ImageSharp/Formats/Png/Filters/UpFilter.cs index c5003d111..e80c5d22b 100644 --- a/src/ImageSharp/Formats/Png/Filters/UpFilter.cs +++ b/src/ImageSharp/Formats/Png/Filters/UpFilter.cs @@ -5,11 +5,8 @@ using System; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; - -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; -#endif namespace SixLabors.ImageSharp.Formats.Png.Filters { @@ -30,7 +27,6 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters { DebugGuard.MustBeSameSized(scanline, previousScanline, nameof(scanline)); -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx2.IsSupported) { DecodeAvx2(scanline, previousScanline); @@ -40,13 +36,11 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters DecodeSse2(scanline, previousScanline); } else -#endif { DecodeScalar(scanline, previousScanline); } } -#if SUPPORTS_RUNTIME_INTRINSICS private static void DecodeAvx2(Span scanline, Span previousScanline) { ref byte scanBaseRef = ref MemoryMarshal.GetReference(scanline); @@ -110,7 +104,6 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters offset++; } } -#endif [MethodImpl(MethodImplOptions.AggressiveInlining)] private static void DecodeScalar(Span scanline, Span previousScanline) @@ -150,7 +143,6 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters int x = 0; -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx2.IsSupported) { Vector256 zero = Vector256.Zero; @@ -191,7 +183,6 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters sum += (int)sumAccumulator[i]; } } -#endif for (; x < scanline.Length; /* Note: ++x happens in the body to avoid one add operation */) { diff --git a/src/ImageSharp/Formats/Webp/AlphaDecoder.cs b/src/ImageSharp/Formats/Webp/AlphaDecoder.cs index 3a118fc0e..a2628a1db 100644 --- a/src/ImageSharp/Formats/Webp/AlphaDecoder.cs +++ b/src/ImageSharp/Formats/Webp/AlphaDecoder.cs @@ -6,13 +6,11 @@ using System.Buffers; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; using SixLabors.ImageSharp.Formats.Webp.BitReader; using SixLabors.ImageSharp.Formats.Webp.Lossless; using SixLabors.ImageSharp.Memory; -#if SUPPORTS_RUNTIME_INTRINSICS -using System.Runtime.Intrinsics; -using System.Runtime.Intrinsics.X86; -#endif namespace SixLabors.ImageSharp.Formats.Webp { @@ -143,7 +141,7 @@ namespace SixLabors.ImageSharp.Formats.Webp Span alphaSpan = this.Alpha.Memory.Span; if (this.AlphaFilterType == WebpAlphaFilterType.None) { - dataSpan.Slice(0, pixelCount).CopyTo(alphaSpan); + dataSpan[..pixelCount].CopyTo(alphaSpan); return; } @@ -166,8 +164,8 @@ namespace SixLabors.ImageSharp.Formats.Webp } prev = dst; - deltas = deltas.Slice(this.Width); - dst = dst.Slice(this.Width); + deltas = deltas[this.Width..]; + dst = dst[this.Width..]; } } else @@ -199,7 +197,7 @@ namespace SixLabors.ImageSharp.Formats.Webp } Span alphaSpan = this.Alpha.Memory.Span; - Span prev = this.PrevRow == 0 ? null : alphaSpan.Slice(this.Width * this.PrevRow); + Span prev = this.PrevRow == 0 ? null : alphaSpan[(this.Width * this.PrevRow)..]; for (int y = firstRow; y < lastRow; y++) { switch (this.AlphaFilterType) @@ -216,7 +214,7 @@ namespace SixLabors.ImageSharp.Formats.Webp } prev = dst; - dst = dst.Slice(stride); + dst = dst[stride..]; } this.PrevRow = lastRow - 1; @@ -234,8 +232,8 @@ namespace SixLabors.ImageSharp.Formats.Webp Span output = this.Alpha.Memory.Span; Span pixelData = this.Vp8LDec.Pixels.Memory.Span; Span pixelDataAsBytes = MemoryMarshal.Cast(pixelData); - Span dst = output.Slice(this.Width * firstRow); - Span input = pixelDataAsBytes.Slice(this.Vp8LDec.Width * firstRow); + Span dst = output[(this.Width * firstRow)..]; + Span input = pixelDataAsBytes[(this.Vp8LDec.Width * firstRow)..]; if (this.Vp8LDec.Transforms.Count == 0 || this.Vp8LDec.Transforms[0].TransformType != Vp8LTransformType.ColorIndexingTransform) { @@ -311,7 +309,6 @@ namespace SixLabors.ImageSharp.Formats.Webp private static void HorizontalUnfilter(Span prev, Span input, Span dst, int width) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Sse2.IsSupported) { dst[0] = (byte)(input[0] + (prev.IsEmpty ? 0 : prev[0])); @@ -345,7 +342,6 @@ namespace SixLabors.ImageSharp.Formats.Webp } } else -#endif { byte pred = (byte)(prev.IsEmpty ? 0 : prev[0]); @@ -366,7 +362,6 @@ namespace SixLabors.ImageSharp.Formats.Webp } else { -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx2.IsSupported) { nint i; @@ -386,7 +381,6 @@ namespace SixLabors.ImageSharp.Formats.Webp } } else -#endif { for (int i = 0; i < width; i++) { diff --git a/src/ImageSharp/Formats/Webp/Lossless/ColorSpaceTransformUtils.cs b/src/ImageSharp/Formats/Webp/Lossless/ColorSpaceTransformUtils.cs index 06e3c88fc..d80cdc275 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/ColorSpaceTransformUtils.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/ColorSpaceTransformUtils.cs @@ -4,10 +4,8 @@ using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; -#endif namespace SixLabors.ImageSharp.Formats.Webp.Lossless { @@ -15,21 +13,20 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless { public static void CollectColorBlueTransforms(Span bgra, int stride, int tileWidth, int tileHeight, int greenToBlue, int redToBlue, Span histo) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx2.IsSupported && tileWidth >= 16) { const int span = 16; Span values = stackalloc ushort[span]; - Vector256 collectColorBlueTransformsShuffleLowMask256 = Vector256.Create(255, 2, 255, 6, 255, 10, 255, 14, 255, 255, 255, 255, 255, 255, 255, 255, 255, 18, 255, 22, 255, 26, 255, 30, 255, 255, 255, 255, 255, 255, 255, 255); - Vector256 collectColorBlueTransformsShuffleHighMask256 = Vector256.Create(255, 255, 255, 255, 255, 255, 255, 255, 255, 2, 255, 6, 255, 10, 255, 14, 255, 255, 255, 255, 255, 255, 255, 255, 255, 18, 255, 22, 255, 26, 255, 30); - Vector256 collectColorBlueTransformsGreenBlueMask256 = Vector256.Create(255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0); - Vector256 collectColorBlueTransformsGreenMask256 = Vector256.Create(0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255); - Vector256 collectColorBlueTransformsBlueMask256 = Vector256.Create(255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0); - Vector256 multsr = Vector256.Create(LosslessUtils.Cst5b(redToBlue)); - Vector256 multsg = Vector256.Create(LosslessUtils.Cst5b(greenToBlue)); + var collectColorBlueTransformsShuffleLowMask256 = Vector256.Create(255, 2, 255, 6, 255, 10, 255, 14, 255, 255, 255, 255, 255, 255, 255, 255, 255, 18, 255, 22, 255, 26, 255, 30, 255, 255, 255, 255, 255, 255, 255, 255); + var collectColorBlueTransformsShuffleHighMask256 = Vector256.Create(255, 255, 255, 255, 255, 255, 255, 255, 255, 2, 255, 6, 255, 10, 255, 14, 255, 255, 255, 255, 255, 255, 255, 255, 255, 18, 255, 22, 255, 26, 255, 30); + var collectColorBlueTransformsGreenBlueMask256 = Vector256.Create(255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0); + var collectColorBlueTransformsGreenMask256 = Vector256.Create(0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255); + var collectColorBlueTransformsBlueMask256 = Vector256.Create(255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0); + var multsr = Vector256.Create(LosslessUtils.Cst5b(redToBlue)); + var multsg = Vector256.Create(LosslessUtils.Cst5b(greenToBlue)); for (int y = 0; y < tileHeight; y++) { - Span srcSpan = bgra.Slice(y * stride); + Span srcSpan = bgra[(y * stride)..]; ref uint inputRef = ref MemoryMarshal.GetReference(srcSpan); for (nint x = 0; x <= tileWidth - span; x += span) { @@ -63,23 +60,23 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless int leftOver = tileWidth & (span - 1); if (leftOver > 0) { - CollectColorBlueTransformsNoneVectorized(bgra.Slice(tileWidth - leftOver), stride, leftOver, tileHeight, greenToBlue, redToBlue, histo); + CollectColorBlueTransformsNoneVectorized(bgra[(tileWidth - leftOver)..], stride, leftOver, tileHeight, greenToBlue, redToBlue, histo); } } else if (Sse41.IsSupported) { const int span = 8; Span values = stackalloc ushort[span]; - Vector128 collectColorBlueTransformsShuffleLowMask = Vector128.Create(255, 2, 255, 6, 255, 10, 255, 14, 255, 255, 255, 255, 255, 255, 255, 255); - Vector128 collectColorBlueTransformsShuffleHighMask = Vector128.Create(255, 255, 255, 255, 255, 255, 255, 255, 255, 2, 255, 6, 255, 10, 255, 14); - Vector128 collectColorBlueTransformsGreenBlueMask = Vector128.Create(255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0); - Vector128 collectColorBlueTransformsGreenMask = Vector128.Create(0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255); - Vector128 collectColorBlueTransformsBlueMask = Vector128.Create(255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0); - Vector128 multsr = Vector128.Create(LosslessUtils.Cst5b(redToBlue)); - Vector128 multsg = Vector128.Create(LosslessUtils.Cst5b(greenToBlue)); + var collectColorBlueTransformsShuffleLowMask = Vector128.Create(255, 2, 255, 6, 255, 10, 255, 14, 255, 255, 255, 255, 255, 255, 255, 255); + var collectColorBlueTransformsShuffleHighMask = Vector128.Create(255, 255, 255, 255, 255, 255, 255, 255, 255, 2, 255, 6, 255, 10, 255, 14); + var collectColorBlueTransformsGreenBlueMask = Vector128.Create(255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0); + var collectColorBlueTransformsGreenMask = Vector128.Create(0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255); + var collectColorBlueTransformsBlueMask = Vector128.Create(255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0); + var multsr = Vector128.Create(LosslessUtils.Cst5b(redToBlue)); + var multsg = Vector128.Create(LosslessUtils.Cst5b(greenToBlue)); for (int y = 0; y < tileHeight; y++) { - Span srcSpan = bgra.Slice(y * stride); + Span srcSpan = bgra[(y * stride)..]; ref uint inputRef = ref MemoryMarshal.GetReference(srcSpan); for (nint x = 0; x <= tileWidth - span; x += span) { @@ -113,11 +110,10 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless int leftOver = tileWidth & (span - 1); if (leftOver > 0) { - CollectColorBlueTransformsNoneVectorized(bgra.Slice(tileWidth - leftOver), stride, leftOver, tileHeight, greenToBlue, redToBlue, histo); + CollectColorBlueTransformsNoneVectorized(bgra[(tileWidth - leftOver)..], stride, leftOver, tileHeight, greenToBlue, redToBlue, histo); } } else -#endif { CollectColorBlueTransformsNoneVectorized(bgra, stride, tileWidth, tileHeight, greenToBlue, redToBlue, histo); } @@ -140,17 +136,16 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless public static void CollectColorRedTransforms(Span bgra, int stride, int tileWidth, int tileHeight, int greenToRed, Span histo) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx2.IsSupported && tileWidth >= 16) { Vector256 collectColorRedTransformsGreenMask256 = Vector256.Create(0x00ff00).AsByte(); Vector256 collectColorRedTransformsAndMask256 = Vector256.Create((short)0xff).AsByte(); - Vector256 multsg = Vector256.Create(LosslessUtils.Cst5b(greenToRed)); + var multsg = Vector256.Create(LosslessUtils.Cst5b(greenToRed)); const int span = 16; Span values = stackalloc ushort[span]; for (int y = 0; y < tileHeight; y++) { - Span srcSpan = bgra.Slice(y * stride); + Span srcSpan = bgra[(y * stride)..]; ref uint inputRef = ref MemoryMarshal.GetReference(srcSpan); for (nint x = 0; x <= tileWidth - span; x += span) { @@ -181,19 +176,19 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless int leftOver = tileWidth & (span - 1); if (leftOver > 0) { - CollectColorRedTransformsNoneVectorized(bgra.Slice(tileWidth - leftOver), stride, leftOver, tileHeight, greenToRed, histo); + CollectColorRedTransformsNoneVectorized(bgra[(tileWidth - leftOver)..], stride, leftOver, tileHeight, greenToRed, histo); } } else if (Sse41.IsSupported) { Vector128 collectColorRedTransformsGreenMask = Vector128.Create(0x00ff00).AsByte(); Vector128 collectColorRedTransformsAndMask = Vector128.Create((short)0xff).AsByte(); - Vector128 multsg = Vector128.Create(LosslessUtils.Cst5b(greenToRed)); + var multsg = Vector128.Create(LosslessUtils.Cst5b(greenToRed)); const int span = 8; Span values = stackalloc ushort[span]; for (int y = 0; y < tileHeight; y++) { - Span srcSpan = bgra.Slice(y * stride); + Span srcSpan = bgra[(y * stride)..]; ref uint inputRef = ref MemoryMarshal.GetReference(srcSpan); for (nint x = 0; x <= tileWidth - span; x += span) { @@ -224,11 +219,10 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless int leftOver = tileWidth & (span - 1); if (leftOver > 0) { - CollectColorRedTransformsNoneVectorized(bgra.Slice(tileWidth - leftOver), stride, leftOver, tileHeight, greenToRed, histo); + CollectColorRedTransformsNoneVectorized(bgra[(tileWidth - leftOver)..], stride, leftOver, tileHeight, greenToRed, histo); } } else -#endif { CollectColorRedTransformsNoneVectorized(bgra, stride, tileWidth, tileHeight, greenToRed, histo); } diff --git a/src/ImageSharp/Formats/Webp/Lossless/LosslessUtils.cs b/src/ImageSharp/Formats/Webp/Lossless/LosslessUtils.cs index 23b355ca4..c6d0d1cfa 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/LosslessUtils.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/LosslessUtils.cs @@ -4,11 +4,9 @@ using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using SixLabors.ImageSharp.Memory; -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; -#endif +using SixLabors.ImageSharp.Memory; namespace SixLabors.ImageSharp.Formats.Webp.Lossless { @@ -68,9 +66,9 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless { if (distance < PrefixLookupIdxMax) { - (int Code, int ExtraBits) prefixCode = WebpLookupTables.PrefixEncodeCode[distance]; - extraBits = prefixCode.ExtraBits; - return prefixCode.Code; + (int code, int bits) = WebpLookupTables.PrefixEncodeCode[distance]; + extraBits = bits; + return code; } return PrefixEncodeBitsNoLut(distance, ref extraBits); @@ -80,11 +78,11 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless { if (distance < PrefixLookupIdxMax) { - (int Code, int ExtraBits) prefixCode = WebpLookupTables.PrefixEncodeCode[distance]; - extraBits = prefixCode.ExtraBits; + (int code, int bits) = WebpLookupTables.PrefixEncodeCode[distance]; + extraBits = bits; extraBitsValue = WebpLookupTables.PrefixEncodeExtraBitsValue[distance]; - return prefixCode.Code; + return code; } return PrefixEncodeNoLut(distance, ref extraBits, ref extraBitsValue); @@ -96,10 +94,9 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless /// The pixel data to apply the transformation. public static void AddGreenToBlueAndRed(Span pixelData) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx2.IsSupported) { - Vector256 addGreenToBlueAndRedMaskAvx2 = Vector256.Create(1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13, 255, 17, 255, 17, 255, 21, 255, 21, 255, 25, 255, 25, 255, 29, 255, 29, 255); + var addGreenToBlueAndRedMaskAvx2 = Vector256.Create(1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13, 255, 17, 255, 17, 255, 21, 255, 21, 255, 25, 255, 25, 255, 29, 255, 29, 255); int numPixels = pixelData.Length; nint i; for (i = 0; i <= numPixels - 8; i += 8) @@ -113,12 +110,12 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless if (i != numPixels) { - AddGreenToBlueAndRedScalar(pixelData.Slice((int)i)); + AddGreenToBlueAndRedScalar(pixelData[(int)i..]); } } else if (Ssse3.IsSupported) { - Vector128 addGreenToBlueAndRedMaskSsse3 = Vector128.Create(1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13, 255); + var addGreenToBlueAndRedMaskSsse3 = Vector128.Create(1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13, 255); int numPixels = pixelData.Length; nint i; for (i = 0; i <= numPixels - 4; i += 4) @@ -132,7 +129,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless if (i != numPixels) { - AddGreenToBlueAndRedScalar(pixelData.Slice((int)i)); + AddGreenToBlueAndRedScalar(pixelData[(int)i..]); } } else if (Sse2.IsSupported) @@ -154,11 +151,10 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless if (i != numPixels) { - AddGreenToBlueAndRedScalar(pixelData.Slice((int)i)); + AddGreenToBlueAndRedScalar(pixelData[(int)i..]); } } else -#endif { AddGreenToBlueAndRedScalar(pixelData); } @@ -180,10 +176,9 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless public static void SubtractGreenFromBlueAndRed(Span pixelData) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx2.IsSupported) { - Vector256 subtractGreenFromBlueAndRedMaskAvx2 = Vector256.Create(1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13, 255, 17, 255, 17, 255, 21, 255, 21, 255, 25, 255, 25, 255, 29, 255, 29, 255); + var subtractGreenFromBlueAndRedMaskAvx2 = Vector256.Create(1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13, 255, 17, 255, 17, 255, 21, 255, 21, 255, 25, 255, 25, 255, 29, 255, 29, 255); int numPixels = pixelData.Length; nint i; for (i = 0; i <= numPixels - 8; i += 8) @@ -197,12 +192,12 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless if (i != numPixels) { - SubtractGreenFromBlueAndRedScalar(pixelData.Slice((int)i)); + SubtractGreenFromBlueAndRedScalar(pixelData[(int)i..]); } } else if (Ssse3.IsSupported) { - Vector128 subtractGreenFromBlueAndRedMaskSsse3 = Vector128.Create(1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13, 255); + var subtractGreenFromBlueAndRedMaskSsse3 = Vector128.Create(1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13, 255); int numPixels = pixelData.Length; nint i; for (i = 0; i <= numPixels - 4; i += 4) @@ -216,7 +211,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless if (i != numPixels) { - SubtractGreenFromBlueAndRedScalar(pixelData.Slice((int)i)); + SubtractGreenFromBlueAndRedScalar(pixelData[(int)i..]); } } else if (Sse2.IsSupported) @@ -238,11 +233,10 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless if (i != numPixels) { - SubtractGreenFromBlueAndRedScalar(pixelData.Slice((int)i)); + SubtractGreenFromBlueAndRedScalar(pixelData[(int)i..]); } } else -#endif { SubtractGreenFromBlueAndRedScalar(pixelData); } @@ -375,11 +369,10 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless /// The number of pixels to process. public static void TransformColor(Vp8LMultipliers m, Span pixelData, int numPixels) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx2.IsSupported && numPixels >= 8) { - Vector256 transformColorAlphaGreenMask256 = Vector256.Create(0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255); - Vector256 transformColorRedBlueMask256 = Vector256.Create(255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0); + var transformColorAlphaGreenMask256 = Vector256.Create(0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255); + var transformColorRedBlueMask256 = Vector256.Create(255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0); Vector256 multsrb = MkCst32(Cst5b(m.GreenToRed), Cst5b(m.GreenToBlue)); Vector256 multsb2 = MkCst32(Cst5b(m.RedToBlue), 0); @@ -405,13 +398,13 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless if (idx != numPixels) { - TransformColorScalar(m, pixelData.Slice((int)idx), numPixels - (int)idx); + TransformColorScalar(m, pixelData[(int)idx..], numPixels - (int)idx); } } else if (Sse2.IsSupported) { - Vector128 transformColorAlphaGreenMask = Vector128.Create(0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255); - Vector128 transformColorRedBlueMask = Vector128.Create(255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0); + var transformColorAlphaGreenMask = Vector128.Create(0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255); + var transformColorRedBlueMask = Vector128.Create(255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0); Vector128 multsrb = MkCst16(Cst5b(m.GreenToRed), Cst5b(m.GreenToBlue)); Vector128 multsb2 = MkCst16(Cst5b(m.RedToBlue), 0); nint idx; @@ -436,11 +429,10 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless if (idx != numPixels) { - TransformColorScalar(m, pixelData.Slice((int)idx), numPixels - (int)idx); + TransformColorScalar(m, pixelData[(int)idx..], numPixels - (int)idx); } } else -#endif { TransformColorScalar(m, pixelData, numPixels); } @@ -471,10 +463,9 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless /// The pixel data to apply the inverse transform on. public static void TransformColorInverse(Vp8LMultipliers m, Span pixelData) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx2.IsSupported && pixelData.Length >= 8) { - Vector256 transformColorInverseAlphaGreenMask256 = Vector256.Create(0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255); + var transformColorInverseAlphaGreenMask256 = Vector256.Create(0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255); Vector256 multsrb = MkCst32(Cst5b(m.GreenToRed), Cst5b(m.GreenToBlue)); Vector256 multsb2 = MkCst32(Cst5b(m.RedToBlue), 0); nint idx; @@ -500,12 +491,12 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless if (idx != pixelData.Length) { - TransformColorInverseScalar(m, pixelData.Slice((int)idx)); + TransformColorInverseScalar(m, pixelData[(int)idx..]); } } else if (Sse2.IsSupported) { - Vector128 transformColorInverseAlphaGreenMask = Vector128.Create(0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255); + var transformColorInverseAlphaGreenMask = Vector128.Create(0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255); Vector128 multsrb = MkCst16(Cst5b(m.GreenToRed), Cst5b(m.GreenToBlue)); Vector128 multsb2 = MkCst16(Cst5b(m.RedToBlue), 0); @@ -532,11 +523,10 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless if (idx != pixelData.Length) { - TransformColorInverseScalar(m, pixelData.Slice((int)idx)); + TransformColorInverseScalar(m, pixelData[(int)idx..]); } } else -#endif { TransformColorInverseScalar(m, pixelData); } @@ -753,7 +743,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless /// Shanon entropy. public static float CombinedShannonEntropy(Span x, Span y) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx2.IsSupported) { double retVal = 0.0d; @@ -906,7 +895,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless return (float)retVal; } else -#endif { double retVal = 0.0d; uint sumX = 0, sumXY = 0; @@ -1406,7 +1394,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless private static uint ClampedAddSubtractFull(uint c0, uint c1, uint c2) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Sse2.IsSupported) { Vector128 c0Vec = Sse2.UnpackLow(Sse2.ConvertScalarToVector128UInt32(c0).AsByte(), Vector128.Zero); @@ -1415,10 +1402,9 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless Vector128 v1 = Sse2.Add(c0Vec.AsInt16(), c1Vec.AsInt16()); Vector128 v2 = Sse2.Subtract(v1, c2Vec.AsInt16()); Vector128 b = Sse2.PackUnsignedSaturate(v2, v2); - uint output = Sse2.ConvertToUInt32(b.AsUInt32()); - return output; + return Sse2.ConvertToUInt32(b.AsUInt32()); } -#endif + { int a = AddSubtractComponentFull( (int)(c0 >> 24), @@ -1439,7 +1425,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless private static uint ClampedAddSubtractHalf(uint c0, uint c1, uint c2) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Sse2.IsSupported) { Vector128 c0Vec = Sse2.UnpackLow(Sse2.ConvertScalarToVector128UInt32(c0).AsByte(), Vector128.Zero); @@ -1453,10 +1438,9 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless Vector128 a3 = Sse2.ShiftRightArithmetic(a2, 1); Vector128 a4 = Sse2.Add(a0, a3).AsInt16(); Vector128 a5 = Sse2.PackUnsignedSaturate(a4, a4); - uint output = Sse2.ConvertToUInt32(a5.AsUInt32()); - return output; + return Sse2.ConvertToUInt32(a5.AsUInt32()); } -#endif + { uint ave = Average2(c0, c1); int a = AddSubtractComponentHalf((int)(ave >> 24), (int)(c2 >> 24)); @@ -1476,17 +1460,14 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless [MethodImpl(InliningOptions.ShortMethod)] private static uint Clip255(uint a) => a < 256 ? a : ~a >> 24; -#if SUPPORTS_RUNTIME_INTRINSICS [MethodImpl(InliningOptions.ShortMethod)] private static Vector128 MkCst16(int hi, int lo) => Vector128.Create((hi << 16) | (lo & 0xffff)); [MethodImpl(InliningOptions.ShortMethod)] private static Vector256 MkCst32(int hi, int lo) => Vector256.Create((hi << 16) | (lo & 0xffff)); -#endif private static uint Select(uint a, uint b, uint c, Span scratch) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Sse2.IsSupported) { Span output = scratch; @@ -1510,7 +1491,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless } } else -#endif { int paMinusPb = Sub3((int)(a >> 24), (int)(b >> 24), (int)(c >> 24)) + diff --git a/src/ImageSharp/Formats/Webp/Lossless/Vp8LHistogram.cs b/src/ImageSharp/Formats/Webp/Lossless/Vp8LHistogram.cs index 0c9bed366..dca239e85 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/Vp8LHistogram.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/Vp8LHistogram.cs @@ -5,10 +5,8 @@ using System; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; -#endif namespace SixLabors.ImageSharp.Formats.Webp.Lossless { @@ -517,7 +515,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless DebugGuard.MustBeGreaterThanOrEqualTo(b.Length, count, nameof(b.Length)); DebugGuard.MustBeGreaterThanOrEqualTo(output.Length, count, nameof(output.Length)); -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx2.IsSupported) { ref uint aRef = ref MemoryMarshal.GetReference(a); @@ -551,7 +548,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless } } else -#endif { for (int i = 0; i < count; i++) { diff --git a/src/ImageSharp/Formats/Webp/Lossy/LossyUtils.cs b/src/ImageSharp/Formats/Webp/Lossy/LossyUtils.cs index e19a813a4..210125790 100644 --- a/src/ImageSharp/Formats/Webp/Lossy/LossyUtils.cs +++ b/src/ImageSharp/Formats/Webp/Lossy/LossyUtils.cs @@ -5,10 +5,8 @@ using System; using System.Buffers.Binary; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; -#endif // ReSharper disable InconsistentNaming namespace SixLabors.ImageSharp.Formats.Webp.Lossy @@ -19,7 +17,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy [MethodImpl(InliningOptions.ShortMethod)] public static int Vp8_Sse16X16(Span a, Span b) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx2.IsSupported) { return Vp8_Sse16xN_Avx2(a, b, 4); @@ -29,17 +26,14 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy { return Vp8_Sse16xN_Sse2(a, b, 8); } -#endif - { - return Vp8_SseNxN(a, b, 16, 16); - } + + return Vp8_SseNxN(a, b, 16, 16); } // Note: method name in libwebp reference implementation is called VP8SSE16x8. [MethodImpl(InliningOptions.ShortMethod)] public static int Vp8_Sse16X8(Span a, Span b) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx2.IsSupported) { return Vp8_Sse16xN_Avx2(a, b, 2); @@ -49,17 +43,14 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy { return Vp8_Sse16xN_Sse2(a, b, 4); } -#endif - { - return Vp8_SseNxN(a, b, 16, 8); - } + + return Vp8_SseNxN(a, b, 16, 8); } // Note: method name in libwebp reference implementation is called VP8SSE4x4. [MethodImpl(InliningOptions.ShortMethod)] public static int Vp8_Sse4X4(Span a, Span b) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx2.IsSupported) { // Load values. @@ -128,10 +119,8 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy return Numerics.ReduceSum(sum); } -#endif - { - return Vp8_SseNxN(a, b, 4, 4); - } + + return Vp8_SseNxN(a, b, 4, 4); } [MethodImpl(InliningOptions.ShortMethod)] @@ -155,7 +144,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy return count; } -#if SUPPORTS_RUNTIME_INTRINSICS [MethodImpl(InliningOptions.ShortMethod)] private static int Vp8_Sse16xN_Sse2(Span a, Span b, int numPairs) { @@ -251,7 +239,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy return Avx2.Add(sum1, sum2); } -#endif [MethodImpl(InliningOptions.ShortMethod)] public static void Vp8Copy4X4(Span src, Span dst) => Copy(src, dst, 4, 4); @@ -274,7 +261,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy public static int Vp8Disto16X16(Span a, Span b, Span w, Span scratch) { int d = 0; - int dataSize = (4 * WebpConstants.Bps) - 16; + const int dataSize = (4 * WebpConstants.Bps) - 16; for (int y = 0; y < 16 * WebpConstants.Bps; y += 4 * WebpConstants.Bps) { for (int x = 0; x < 16; x += 4) @@ -289,14 +276,12 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy [MethodImpl(InliningOptions.ShortMethod)] public static int Vp8Disto4X4(Span a, Span b, Span w, Span scratch) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Sse41.IsSupported) { int diffSum = TTransformSse41(a, b, w); return Math.Abs(diffSum) >> 5; } else -#endif { int sum1 = TTransform(a, w, scratch); int sum2 = TTransform(b, w, scratch); @@ -328,7 +313,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy for (int j = 0; j < 16; j++) { // memcpy(dst + j * BPS, dst - BPS, 16); - src.CopyTo(dst.Slice(j * WebpConstants.Bps)); + src.CopyTo(dst[(j * WebpConstants.Bps)..]); } } @@ -342,7 +327,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy byte v = yuv[offset]; Memset(dst, v, 0, 16); offset += WebpConstants.Bps; - dst = dst.Slice(WebpConstants.Bps); + dst = dst[WebpConstants.Bps..]; } } @@ -399,11 +384,11 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy // vertical Span src = yuv.Slice(offset - WebpConstants.Bps, 8); - int endIdx = 8 * WebpConstants.Bps; + const int endIdx = 8 * WebpConstants.Bps; for (int j = 0; j < endIdx; j += WebpConstants.Bps) { // memcpy(dst + j * BPS, dst - BPS, 8); - src.CopyTo(dst.Slice(j)); + src.CopyTo(dst[j..]); } } @@ -417,7 +402,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy // dst += BPS; byte v = yuv[offset]; Memset(dst, v, 0, 8); - dst = dst.Slice(WebpConstants.Bps); + dst = dst[WebpConstants.Bps..]; offset += WebpConstants.Bps; } } @@ -427,7 +412,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy // DC with no top samples. int dc0 = 4; int offsetMinusOne = offset - 1; - int endIdx = 8 * WebpConstants.Bps; + const int endIdx = 8 * WebpConstants.Bps; for (int i = 0; i < endIdx; i += WebpConstants.Bps) { // dc0 += dst[-1 + i * BPS]; @@ -466,7 +451,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy } dc >>= 3; - int endIndx = 4 * WebpConstants.Bps; + const int endIndx = 4 * WebpConstants.Bps; for (int i = 0; i < endIndx; i += WebpConstants.Bps) { Memset(dst, (byte)dc, i, 4); @@ -484,10 +469,10 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy vals[1] = Avg3(yuv[topOffset], yuv[topOffset + 1], yuv[topOffset + 2]); vals[2] = Avg3(yuv[topOffset + 1], yuv[topOffset + 2], yuv[topOffset + 3]); vals[3] = Avg3(yuv[topOffset + 2], yuv[topOffset + 3], yuv[topOffset + 4]); - int endIdx = 4 * WebpConstants.Bps; + const int endIdx = 4 * WebpConstants.Bps; for (int i = 0; i < endIdx; i += WebpConstants.Bps) { - vals.CopyTo(dst.Slice(i)); + vals.CopyTo(dst[i..]); } } @@ -503,11 +488,11 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy uint val = 0x01010101U * Avg3(a, b, c); BinaryPrimitives.WriteUInt32BigEndian(dst, val); val = 0x01010101U * Avg3(b, c, d); - BinaryPrimitives.WriteUInt32BigEndian(dst.Slice(WebpConstants.Bps), val); + BinaryPrimitives.WriteUInt32BigEndian(dst[WebpConstants.Bps..], val); val = 0x01010101U * Avg3(c, d, e); - BinaryPrimitives.WriteUInt32BigEndian(dst.Slice(2 * WebpConstants.Bps), val); + BinaryPrimitives.WriteUInt32BigEndian(dst[(2 * WebpConstants.Bps)..], val); val = 0x01010101U * Avg3(d, e, e); - BinaryPrimitives.WriteUInt32BigEndian(dst.Slice(3 * WebpConstants.Bps), val); + BinaryPrimitives.WriteUInt32BigEndian(dst[(3 * WebpConstants.Bps)..], val); } public static void RD4(Span dst, Span yuv, int offset) @@ -726,7 +711,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy /// public static void TransformWht(Span input, Span output, Span scratch) { - Span tmp = scratch.Slice(0, 16); + Span tmp = scratch[..16]; tmp.Clear(); for (int i = 0; i < 4; i++) { @@ -768,7 +753,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy public static int TTransform(Span input, Span w, Span scratch) { int sum = 0; - Span tmp = scratch.Slice(0, 16); + Span tmp = scratch[..16]; tmp.Clear(); // horizontal pass. @@ -807,13 +792,12 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy sum += w[8] * Math.Abs(b2); sum += w[12] * Math.Abs(b3); - w = w.Slice(1); + w = w[1..]; } return sum; } -#if SUPPORTS_RUNTIME_INTRINSICS /// /// Hadamard transform /// Returns the weighted sum of the absolute value of transformed coefficients. @@ -944,13 +928,11 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy // a02 a12 a22 a32 b02 b12 b22 b32 // a03 a13 a23 a33 b03 b13 b23 b33 } -#endif // Transforms (Paragraph 14.4). // Does two transforms. public static void TransformTwo(Span src, Span dst, Span scratch) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Sse2.IsSupported) { // This implementation makes use of 16-bit fixed point versions of two @@ -1002,8 +984,8 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy Vector128 a = Sse2.Add(in0.AsInt16(), in2.AsInt16()); Vector128 b = Sse2.Subtract(in0.AsInt16(), in2.AsInt16()); - Vector128 k1 = Vector128.Create((short)20091); - Vector128 k2 = Vector128.Create((short)-30068); + var k1 = Vector128.Create((short)20091); + var k2 = Vector128.Create((short)-30068); // c = MUL(in1, K2) - MUL(in3, K1) = MUL(in1, k2) - MUL(in3, k1) + in1 - in3 Vector128 c1 = Sse2.MultiplyHigh(in1.AsInt16(), k2); @@ -1097,16 +1079,14 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy Unsafe.As>(ref Unsafe.Add(ref outputRef, WebpConstants.Bps * 3)) = dst3.GetLower(); } else -#endif { TransformOne(src, dst, scratch); - TransformOne(src.Slice(16), dst.Slice(4), scratch); + TransformOne(src[16..], dst[4..], scratch); } } public static void TransformOne(Span src, Span dst, Span scratch) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Sse2.IsSupported) { // Load and concatenate the transform coefficients. @@ -1126,8 +1106,8 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy Vector128 a = Sse2.Add(in0.AsInt16(), in2.AsInt16()); Vector128 b = Sse2.Subtract(in0.AsInt16(), in2.AsInt16()); - Vector128 k1 = Vector128.Create((short)20091); - Vector128 k2 = Vector128.Create((short)-30068); + var k1 = Vector128.Create((short)20091); + var k2 = Vector128.Create((short)-30068); // c = MUL(in1, K2) - MUL(in3, K1) = MUL(in1, k2) - MUL(in3, k1) + in1 - in3 Vector128 c1 = Sse2.MultiplyHigh(in1.AsInt16(), k2); @@ -1225,9 +1205,8 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy Unsafe.As(ref Unsafe.Add(ref outputRef, WebpConstants.Bps * 3)) = output3; } else -#endif { - Span tmp = scratch.Slice(0, 16); + Span tmp = scratch[..16]; int tmpOffset = 0; for (int srcOffset = 0; srcOffset < 4; srcOffset++) { @@ -1263,10 +1242,10 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy int b = dc - tmp[tmpOffsetPlus8]; int c = Mul2(tmp[tmpOffsetPlus4]) - Mul1(tmp[tmpOffsetPlus12]); int d = Mul1(tmp[tmpOffsetPlus4]) + Mul2(tmp[tmpOffsetPlus12]); - Store(dst.Slice(dstOffset), 0, 0, a + d); - Store(dst.Slice(dstOffset), 1, 0, b + c); - Store(dst.Slice(dstOffset), 2, 0, b - c); - Store(dst.Slice(dstOffset), 3, 0, a - d); + Store(dst[dstOffset..], 0, 0, a + d); + Store(dst[dstOffset..], 1, 0, b + c); + Store(dst[dstOffset..], 2, 0, b - c); + Store(dst[dstOffset..], 3, 0, a - d); tmpOffset++; dstOffset += WebpConstants.Bps; @@ -1302,37 +1281,36 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy public static void TransformUv(Span src, Span dst, Span scratch) { - TransformTwo(src.Slice(0 * 16), dst, scratch); - TransformTwo(src.Slice(2 * 16), dst.Slice(4 * WebpConstants.Bps), scratch); + TransformTwo(src[..], dst, scratch); + TransformTwo(src[(2 * 16)..], dst[(4 * WebpConstants.Bps)..], scratch); } public static void TransformDcuv(Span src, Span dst) { if (src[0 * 16] != 0) { - TransformDc(src.Slice(0 * 16), dst); + TransformDc(src[..], dst); } if (src[1 * 16] != 0) { - TransformDc(src.Slice(1 * 16), dst.Slice(4)); + TransformDc(src[(1 * 16)..], dst[4..]); } if (src[2 * 16] != 0) { - TransformDc(src.Slice(2 * 16), dst.Slice(4 * WebpConstants.Bps)); + TransformDc(src[(2 * 16)..], dst[(4 * WebpConstants.Bps)..]); } if (src[3 * 16] != 0) { - TransformDc(src.Slice(3 * 16), dst.Slice((4 * WebpConstants.Bps) + 4)); + TransformDc(src[(3 * 16)..], dst[((4 * WebpConstants.Bps) + 4)..]); } } // Simple In-loop filtering (Paragraph 15.2) public static void SimpleVFilter16(Span p, int offset, int stride, int thresh) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Sse2.IsSupported) { // Load. @@ -1351,7 +1329,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy Unsafe.As>(ref outputRef) = q0.AsSByte(); } else -#endif { int thresh2 = (2 * thresh) + 1; int end = 16 + offset; @@ -1367,7 +1344,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy public static void SimpleHFilter16(Span p, int offset, int stride, int thresh) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Sse2.IsSupported) { // Beginning of p1 @@ -1378,7 +1354,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy Store16x4(p1, p0, q0, q1, ref pRef, ref Unsafe.Add(ref pRef, 8 * stride), stride); } else -#endif { int thresh2 = (2 * thresh) + 1; int end = offset + (16 * stride); @@ -1394,7 +1369,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy public static void SimpleVFilter16i(Span p, int offset, int stride, int thresh) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Sse2.IsSupported) { for (int k = 3; k > 0; k--) @@ -1404,7 +1378,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy } } else -#endif { for (int k = 3; k > 0; k--) { @@ -1416,7 +1389,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy public static void SimpleHFilter16i(Span p, int offset, int stride, int thresh) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Sse2.IsSupported) { for (int k = 3; k > 0; k--) @@ -1426,7 +1398,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy } } else -#endif { for (int k = 3; k > 0; k--) { @@ -1440,7 +1411,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy [MethodImpl(InliningOptions.ShortMethod)] public static void VFilter16(Span p, int offset, int stride, int thresh, int ithresh, int hevThresh) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Sse2.IsSupported) { ref byte pRef = ref MemoryMarshal.GetReference(p); @@ -1475,7 +1445,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy Unsafe.As>(ref Unsafe.Add(ref outputRef, offset + (2 * stride))) = q2.AsInt32(); } else -#endif { FilterLoop26(p, offset, stride, 1, 16, thresh, ithresh, hevThresh); } @@ -1484,7 +1453,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy [MethodImpl(InliningOptions.ShortMethod)] public static void HFilter16(Span p, int offset, int stride, int thresh, int ithresh, int hevThresh) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Sse2.IsSupported) { ref byte pRef = ref MemoryMarshal.GetReference(p); @@ -1508,7 +1476,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy Store16x4(q0, q1, q2, q3, ref Unsafe.Add(ref pRef, offset), ref Unsafe.Add(ref pRef, offset + (8 * stride)), stride); } else -#endif { FilterLoop26(p, offset, 1, stride, 16, thresh, ithresh, hevThresh); } @@ -1516,7 +1483,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy public static void VFilter16i(Span p, int offset, int stride, int thresh, int ithresh, int hevThresh) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Sse2.IsSupported) { ref byte pRef = ref MemoryMarshal.GetReference(p); @@ -1528,7 +1494,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy for (int k = 3; k > 0; k--) { // Beginning of p1. - Span b = p.Slice(offset + (2 * stride)); + Span b = p[(offset + (2 * stride))..]; offset += 4 * stride; Vector128 mask = Abs(p0, p1); @@ -1562,7 +1528,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy } } else -#endif { for (int k = 3; k > 0; k--) { @@ -1574,7 +1539,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy public static void HFilter16i(Span p, int offset, int stride, int thresh, int ithresh, int hevThresh) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Sse2.IsSupported) { ref byte pRef = ref MemoryMarshal.GetReference(p); @@ -1611,7 +1575,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy } } else -#endif { for (int k = 3; k > 0; k--) { @@ -1625,7 +1588,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy [MethodImpl(InliningOptions.ShortMethod)] public static void VFilter8(Span u, Span v, int offset, int stride, int thresh, int ithresh, int hevThresh) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Sse2.IsSupported) { // Load uv h-edges. @@ -1661,7 +1623,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy StoreUv(q2, ref uRef, ref vRef, offset + (2 * stride)); } else -#endif { FilterLoop26(u, offset, stride, 1, 8, thresh, ithresh, hevThresh); FilterLoop26(v, offset, stride, 1, 8, thresh, ithresh, hevThresh); @@ -1671,7 +1632,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy [MethodImpl(InliningOptions.ShortMethod)] public static void HFilter8(Span u, Span v, int offset, int stride, int thresh, int ithresh, int hevThresh) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Sse2.IsSupported) { ref byte uRef = ref MemoryMarshal.GetReference(u); @@ -1695,7 +1655,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy Store16x4(q0, q1, q2, q3, ref Unsafe.Add(ref uRef, offset), ref Unsafe.Add(ref vRef, offset), stride); } else -#endif { FilterLoop26(u, offset, 1, stride, 8, thresh, ithresh, hevThresh); FilterLoop26(v, offset, 1, stride, 8, thresh, ithresh, hevThresh); @@ -1705,7 +1664,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy [MethodImpl(InliningOptions.ShortMethod)] public static void VFilter8i(Span u, Span v, int offset, int stride, int thresh, int ithresh, int hevThresh) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Sse2.IsSupported) { // Load uv h-edges. @@ -1741,7 +1699,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy StoreUv(q1, ref uRef, ref vRef, offset + stride); } else -#endif { int offset4mulstride = offset + (4 * stride); FilterLoop24(u, offset4mulstride, stride, 1, 8, thresh, ithresh, hevThresh); @@ -1752,7 +1709,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy [MethodImpl(InliningOptions.ShortMethod)] public static void HFilter8i(Span u, Span v, int offset, int stride, int thresh, int ithresh, int hevThresh) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Sse2.IsSupported) { ref byte uRef = ref MemoryMarshal.GetReference(u); @@ -1780,7 +1736,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy Store16x4(p1, p0, q0, q1, ref Unsafe.Add(ref uRef, offset), ref Unsafe.Add(ref vRef, offset), stride); } else -#endif { int offsetPlus4 = offset + 4; FilterLoop24(u, offsetPlus4, 1, stride, 8, thresh, ithresh, hevThresh); @@ -1790,7 +1745,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy public static void Mean16x4(Span input, Span dc) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Ssse3.IsSupported) { Vector128 mean16x4Mask = Vector128.Create((short)0x00ff).AsByte(); @@ -1821,7 +1775,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy Unsafe.As>(ref outputRef) = wide; } else -#endif { for (int k = 0; k < 4; k++) { @@ -1835,7 +1788,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy } dc[k] = avg; - input = input.Slice(4); // go to next 4x4 block. + input = input[4..]; // go to next 4x4 block. } } } @@ -1860,7 +1813,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy { for (int j = 0; j < 16; j++) { - Memset(dst.Slice(j * WebpConstants.Bps), (byte)v, 0, 16); + Memset(dst[(j * WebpConstants.Bps)..], (byte)v, 0, 16); } } @@ -1868,7 +1821,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy { // For information about how true motion works, see rfc6386, page 52. ff and section 20.14. int topOffset = offset - WebpConstants.Bps; - Span top = yuv.Slice(topOffset); + Span top = yuv[topOffset..]; byte p = yuv[topOffset - 1]; int leftOffset = offset - 1; byte left = yuv[leftOffset]; @@ -1881,7 +1834,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy leftOffset += WebpConstants.Bps; left = yuv[leftOffset]; - dst = dst.Slice(WebpConstants.Bps); + dst = dst[WebpConstants.Bps..]; } } @@ -1959,11 +1912,10 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy p[offset] = WebpLookupTables.Clip1(q0 - a1); } -#if SUPPORTS_RUNTIME_INTRINSICS // Applies filter on 2 pixels (p0 and q0) private static void DoFilter2Sse2(ref Vector128 p1, ref Vector128 p0, ref Vector128 q0, ref Vector128 q1, int thresh) { - Vector128 signBit = Vector128.Create((byte)0x80); + var signBit = Vector128.Create((byte)0x80); // Convert p1/q1 to byte (for GetBaseDelta). Vector128 p1s = Sse2.Xor(p1, signBit); @@ -1992,7 +1944,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy // Compute hev mask. Vector128 notHev = GetNotHev(ref p1, ref p0, ref q0, ref q1, tresh); - Vector128 signBit = Vector128.Create((byte)0x80); + var signBit = Vector128.Create((byte)0x80); // Convert to signed values. p1 = Sse2.Xor(p1, signBit); @@ -2036,7 +1988,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy Vector128 notHev = GetNotHev(ref p1, ref p0, ref q0, ref q1, tresh); // Convert to signed values. - Vector128 signBit = Vector128.Create((byte)0x80); + var signBit = Vector128.Create((byte)0x80); p1 = Sse2.Xor(p1, signBit); p0 = Sse2.Xor(p0, signBit); q0 = Sse2.Xor(q0, signBit); @@ -2057,11 +2009,11 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy Vector128 flow = Sse2.UnpackLow(Vector128.Zero, f); Vector128 fhigh = Sse2.UnpackHigh(Vector128.Zero, f); - Vector128 nine = Vector128.Create((short)0x0900); + var nine = Vector128.Create((short)0x0900); Vector128 f9Low = Sse2.MultiplyHigh(flow.AsInt16(), nine); // Filter (lo) * 9 Vector128 f9High = Sse2.MultiplyHigh(fhigh.AsInt16(), nine); // Filter (hi) * 9 - Vector128 sixtyThree = Vector128.Create((short)63); + var sixtyThree = Vector128.Create((short)63); Vector128 a2Low = Sse2.Add(f9Low, sixtyThree); // Filter * 9 + 63 Vector128 a2High = Sse2.Add(f9High, sixtyThree); // Filter * 9 + 63 @@ -2100,7 +2052,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy // not_hev <= t1 && not_hev <= t2 return Sse2.CompareEqual(tMaxH, Vector128.Zero); } -#endif // Applies filter on 4 pixels (p1, p0, q0 and q1) private static void DoFilter4(Span p, int offset, int step) @@ -2180,7 +2131,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy WebpLookupTables.Abs0(q2 - q1) <= it && WebpLookupTables.Abs0(q1 - q0) <= it; } -#if SUPPORTS_RUNTIME_INTRINSICS private static Vector128 NeedsFilter(Vector128 p1, Vector128 p0, Vector128 q0, Vector128 q1, int thresh) { var mthresh = Vector128.Create((byte)thresh); @@ -2345,7 +2295,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy // Pixels 'pi' and 'qi' are int8_t on input, uint8_t on output (sign flip). private static void Update2Pixels(ref Vector128 pi, ref Vector128 qi, Vector128 a0Low, Vector128 a0High) { - Vector128 signBit = Vector128.Create((byte)0x80); + var signBit = Vector128.Create((byte)0x80); Vector128 a1Low = Sse2.ShiftRightArithmetic(a0Low, 7); Vector128 a1High = Sse2.ShiftRightArithmetic(a0High, 7); Vector128 delta = Sse2.PackSignedSaturate(a1Low, a1High); @@ -2374,7 +2324,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy [MethodImpl(InliningOptions.ShortMethod)] private static Vector128 Abs(Vector128 p, Vector128 q) => Sse2.Or(Sse2.SubtractSaturate(q, p), Sse2.SubtractSaturate(p, q)); -#endif [MethodImpl(InliningOptions.ShortMethod)] private static bool Hev(Span p, int offset, int step, int thresh) @@ -2411,7 +2360,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy [MethodImpl(InliningOptions.ShortMethod)] private static void Put8x8uv(byte value, Span dst) { - int end = 8 * WebpConstants.Bps; + const int end = 8 * WebpConstants.Bps; for (int j = 0; j < end; j += WebpConstants.Bps) { // memset(dst + j * BPS, value, 8); diff --git a/src/ImageSharp/Formats/Webp/Lossy/QuantEnc.cs b/src/ImageSharp/Formats/Webp/Lossy/QuantEnc.cs index a191cbcf8..4d60f0ae3 100644 --- a/src/ImageSharp/Formats/Webp/Lossy/QuantEnc.cs +++ b/src/ImageSharp/Formats/Webp/Lossy/QuantEnc.cs @@ -4,10 +4,8 @@ using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; -#endif namespace SixLabors.ImageSharp.Formats.Webp.Lossy { @@ -77,9 +75,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy if (mode == 0 || rdCur.Score < rdBest.Score) { - Vp8ModeScore tmp = rdCur; - rdCur = rdBest; - rdBest = tmp; + (rdBest, rdCur) = (rdCur, rdBest); it.SwapOut(); } } @@ -132,9 +128,9 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy rdi4.Clear(); int mode; int bestMode = -1; - Span src = src0.Slice(WebpLookupTables.Vp8Scan[it.I4]); + Span src = src0[WebpLookupTables.Vp8Scan[it.I4]..]; short[] modeCosts = it.GetCostModeI4(rd.ModesI4); - Span bestBlock = bestBlocks.Slice(WebpLookupTables.Vp8Scan[it.I4]); + Span bestBlock = bestBlocks[WebpLookupTables.Vp8Scan[it.I4]..]; Span tmpDst = it.Scratch.AsSpan(); tmpDst.Clear(); @@ -199,7 +195,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy } // Copy selected samples to the right place. - LossyUtils.Vp8Copy4X4(bestBlock, bestBlocks.Slice(WebpLookupTables.Vp8Scan[it.I4])); + LossyUtils.Vp8Copy4X4(bestBlock, bestBlocks[WebpLookupTables.Vp8Scan[it.I4]..]); rd.ModesI4[it.I4] = (byte)bestMode; it.TopNz[it.I4 & 3] = it.LeftNz[it.I4 >> 2] = rdi4.Nz != 0 ? 1 : 0; @@ -290,14 +286,14 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy Span scratch = it.Scratch3.AsSpan(0, 16); shortScratchSpan.Clear(); scratch.Clear(); - Span dcTmp = shortScratchSpan.Slice(0, 16); + Span dcTmp = shortScratchSpan[..16]; Span tmp = shortScratchSpan.Slice(16, 16 * 16); for (n = 0; n < 16; n += 2) { Vp8Encoding.FTransform2( - src.Slice(WebpLookupTables.Vp8Scan[n]), - reference.Slice(WebpLookupTables.Vp8Scan[n]), + src[WebpLookupTables.Vp8Scan[n]..], + reference[WebpLookupTables.Vp8Scan[n]..], tmp.Slice(n * 16, 16), tmp.Slice((n + 1) * 16, 16), scratch); @@ -318,7 +314,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy LossyUtils.TransformWht(dcTmp, tmp, scratch); for (n = 0; n < 16; n += 2) { - Vp8Encoding.ITransformTwo(reference.Slice(WebpLookupTables.Vp8Scan[n]), tmp.Slice(n * 16, 32), yuvOut.Slice(WebpLookupTables.Vp8Scan[n]), scratch); + Vp8Encoding.ITransformTwo(reference[WebpLookupTables.Vp8Scan[n]..], tmp.Slice(n * 16, 32), yuvOut[WebpLookupTables.Vp8Scan[n]..], scratch); } return nz; @@ -348,8 +344,8 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy for (n = 0; n < 8; n += 2) { Vp8Encoding.FTransform2( - src.Slice(WebpLookupTables.Vp8ScanUv[n]), - reference.Slice(WebpLookupTables.Vp8ScanUv[n]), + src[WebpLookupTables.Vp8ScanUv[n]..], + reference[WebpLookupTables.Vp8ScanUv[n]..], tmp.Slice(n * 16, 16), tmp.Slice((n + 1) * 16, 16), scratch); @@ -364,7 +360,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy for (n = 0; n < 8; n += 2) { - Vp8Encoding.ITransformTwo(reference.Slice(WebpLookupTables.Vp8ScanUv[n]), tmp.Slice(n * 16, 32), yuvOut.Slice(WebpLookupTables.Vp8ScanUv[n]), scratch); + Vp8Encoding.ITransformTwo(reference[WebpLookupTables.Vp8ScanUv[n]..], tmp.Slice(n * 16, 32), yuvOut[WebpLookupTables.Vp8ScanUv[n]..], scratch); } return nz << 16; @@ -512,14 +508,13 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy [MethodImpl(InliningOptions.ShortMethod)] public static int Quantize2Blocks(Span input, Span output, ref Vp8Matrix mtx) { - int nz = QuantizeBlock(input.Slice(0, 16), output.Slice(0, 16), ref mtx) << 0; + int nz = QuantizeBlock(input[..16], output[..16], ref mtx) << 0; nz |= QuantizeBlock(input.Slice(1 * 16, 16), output.Slice(1 * 16, 16), ref mtx) << 1; return nz; } public static int QuantizeBlock(Span input, Span output, ref Vp8Matrix mtx) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx2.IsSupported) { // Load all inputs. @@ -636,7 +631,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy Vector128 out8 = Sse2.PackSignedSaturate(out08.AsInt32(), out12.AsInt32()); // if (coeff > 2047) coeff = 2047 - Vector128 maxCoeff2047 = Vector128.Create((short)MaxLevel); + var maxCoeff2047 = Vector128.Create((short)MaxLevel); out0 = Sse2.Min(out0, maxCoeff2047); out8 = Sse2.Min(out8, maxCoeff2047); @@ -677,7 +672,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy return Sse2.MoveMask(cmpeq) != 0xffff ? 1 : 0; } else -#endif { int last = -1; int n; @@ -762,11 +756,11 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy c[0] += (short)(((C1 * top[0]) + (C2 * left[0])) >> (DSHIFT - DSCALE)); int err0 = QuantizeSingle(c, ref mtx); c[1 * 16] += (short)(((C1 * top[1]) + (C2 * err0)) >> (DSHIFT - DSCALE)); - int err1 = QuantizeSingle(c.Slice(1 * 16), ref mtx); + int err1 = QuantizeSingle(c[(1 * 16)..], ref mtx); c[2 * 16] += (short)(((C1 * err0) + (C2 * left[1])) >> (DSHIFT - DSCALE)); - int err2 = QuantizeSingle(c.Slice(2 * 16), ref mtx); + int err2 = QuantizeSingle(c[(2 * 16)..], ref mtx); c[3 * 16] += (short)(((C1 * err1) + (C2 * err2)) >> (DSHIFT - DSCALE)); - int err3 = QuantizeSingle(c.Slice(3 * 16), ref mtx); + int err3 = QuantizeSingle(c[(3 * 16)..], ref mtx); rd.Derr[ch, 0] = err1; rd.Derr[ch, 1] = err2; @@ -781,13 +775,13 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy Span vSpan = BitConverter.GetBytes(v).AsSpan(); for (nint i = 0; i < 16; i++) { - if (!src.Slice(0, 4).SequenceEqual(vSpan) || !src.Slice(4, 4).SequenceEqual(vSpan) || + if (!src[..4].SequenceEqual(vSpan) || !src.Slice(4, 4).SequenceEqual(vSpan) || !src.Slice(8, 4).SequenceEqual(vSpan) || !src.Slice(12, 4).SequenceEqual(vSpan)) { return false; } - src = src.Slice(WebpConstants.Bps); + src = src[WebpConstants.Bps..]; } return true; diff --git a/src/ImageSharp/Formats/Webp/Lossy/Vp8Encoding.cs b/src/ImageSharp/Formats/Webp/Lossy/Vp8Encoding.cs index b98eea415..4b94c840d 100644 --- a/src/ImageSharp/Formats/Webp/Lossy/Vp8Encoding.cs +++ b/src/ImageSharp/Formats/Webp/Lossy/Vp8Encoding.cs @@ -5,10 +5,8 @@ using System; using System.Buffers.Binary; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; -#endif namespace SixLabors.ImageSharp.Formats.Webp.Lossy { @@ -81,7 +79,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy // Does two inverse transforms. public static void ITransformTwo(Span reference, Span input, Span dst, Span scratch) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Sse2.IsSupported) { // This implementation makes use of 16-bit fixed point versions of two @@ -184,16 +181,14 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy Unsafe.As>(ref Unsafe.Add(ref outputRef, WebpConstants.Bps * 3)) = ref3.GetLower(); } else -#endif { ITransformOne(reference, input, dst, scratch); - ITransformOne(reference.Slice(4), input.Slice(16), dst.Slice(4), scratch); + ITransformOne(reference[4..], input[16..], dst[4..], scratch); } } public static void ITransformOne(Span reference, Span input, Span dst, Span scratch) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Sse2.IsSupported) { // Load and concatenate the transform coefficients (we'll do two inverse @@ -272,10 +267,9 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy Unsafe.As(ref Unsafe.Add(ref outputRef, WebpConstants.Bps * 3)) = output3; } else -#endif { int i; - Span tmp = scratch.Slice(0, 16); + Span tmp = scratch[..16]; for (i = 0; i < 4; i++) { // vertical pass. @@ -287,8 +281,8 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy tmp[1] = b + c; tmp[2] = b - c; tmp[3] = a - d; - tmp = tmp.Slice(4); - input = input.Slice(1); + tmp = tmp[4..]; + input = input[1..]; } tmp = scratch; @@ -304,12 +298,11 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy Store(dst, reference, 1, i, b + c); Store(dst, reference, 2, i, b - c); Store(dst, reference, 3, i, a - d); - tmp = tmp.Slice(1); + tmp = tmp[1..]; } } } -#if SUPPORTS_RUNTIME_INTRINSICS private static void InverseTransformVerticalPass(Vector128 in0, Vector128 in2, Vector128 in1, Vector128 in3, out Vector128 tmp0, out Vector128 tmp1, out Vector128 tmp2, out Vector128 tmp3) { Vector128 a = Sse2.Add(in0.AsInt16(), in2.AsInt16()); @@ -372,11 +365,9 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy shifted2 = Sse2.ShiftRightArithmetic(tmp2, 3); shifted3 = Sse2.ShiftRightArithmetic(tmp3, 3); } -#endif public static void FTransform2(Span src, Span reference, Span output, Span output2, Span scratch) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Sse2.IsSupported) { ref byte srcRef = ref MemoryMarshal.GetReference(src); @@ -429,16 +420,14 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy FTransformPass2SSE2(v01h, v32h, output2); } else -#endif { FTransform(src, reference, output, scratch); - FTransform(src.Slice(4), reference.Slice(4), output2, scratch); + FTransform(src[4..], reference[4..], output2, scratch); } } public static void FTransform(Span src, Span reference, Span output, Span scratch) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Sse2.IsSupported) { ref byte srcRef = ref MemoryMarshal.GetReference(src); @@ -486,10 +475,9 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy FTransformPass2SSE2(v01, v32, output); } else -#endif { int i; - Span tmp = scratch.Slice(0, 16); + Span tmp = scratch[..16]; int srcIdx = 0; int refIdx = 0; @@ -530,7 +518,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy } } -#if SUPPORTS_RUNTIME_INTRINSICS public static void FTransformPass1SSE2(Vector128 row01, Vector128 row23, out Vector128 out01, out Vector128 out32) { // *in01 = 00 01 10 11 02 03 12 13 @@ -621,11 +608,10 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy Unsafe.As>(ref outputRef) = d0g1.AsInt16(); Unsafe.As>(ref Unsafe.Add(ref outputRef, 8)) = d2f3.AsInt16(); } -#endif public static void FTransformWht(Span input, Span output, Span scratch) { - Span tmp = scratch.Slice(0, 16); + Span tmp = scratch[..16]; int i; int inputIdx = 0; @@ -668,62 +654,62 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy // luma 16x16 prediction (paragraph 12.3). public static void EncPredLuma16(Span dst, Span left, Span top) { - DcMode(dst.Slice(I16DC16), left, top, 16, 16, 5); - VerticalPred(dst.Slice(I16VE16), top, 16); - HorizontalPred(dst.Slice(I16HE16), left, 16); - TrueMotion(dst.Slice(I16TM16), left, top, 16); + DcMode(dst[..], left, top, 16, 16, 5); + VerticalPred(dst[I16VE16..], top, 16); + HorizontalPred(dst[I16HE16..], left, 16); + TrueMotion(dst[I16TM16..], left, top, 16); } // Chroma 8x8 prediction (paragraph 12.2). public static void EncPredChroma8(Span dst, Span left, Span top) { // U block. - DcMode(dst.Slice(C8DC8), left, top, 8, 8, 4); - VerticalPred(dst.Slice(C8VE8), top, 8); - HorizontalPred(dst.Slice(C8HE8), left, 8); - TrueMotion(dst.Slice(C8TM8), left, top, 8); + DcMode(dst[C8DC8..], left, top, 8, 8, 4); + VerticalPred(dst[C8VE8..], top, 8); + HorizontalPred(dst[C8HE8..], left, 8); + TrueMotion(dst[C8TM8..], left, top, 8); // V block. - dst = dst.Slice(8); - if (top != null) + dst = dst[8..]; + if (top != default) { - top = top.Slice(8); + top = top[8..]; } - if (left != null) + if (left != default) { - left = left.Slice(16); + left = left[16..]; } - DcMode(dst.Slice(C8DC8), left, top, 8, 8, 4); - VerticalPred(dst.Slice(C8VE8), top, 8); - HorizontalPred(dst.Slice(C8HE8), left, 8); - TrueMotion(dst.Slice(C8TM8), left, top, 8); + DcMode(dst[C8DC8..], left, top, 8, 8, 4); + VerticalPred(dst[C8VE8..], top, 8); + HorizontalPred(dst[C8HE8..], left, 8); + TrueMotion(dst[C8TM8..], left, top, 8); } // Left samples are top[-5 .. -2], top_left is top[-1], top are // located at top[0..3], and top right is top[4..7] public static void EncPredLuma4(Span dst, Span top, int topOffset, Span vals) { - Dc4(dst.Slice(I4DC4), top, topOffset); - Tm4(dst.Slice(I4TM4), top, topOffset); - Ve4(dst.Slice(I4VE4), top, topOffset, vals); - He4(dst.Slice(I4HE4), top, topOffset); - Rd4(dst.Slice(I4RD4), top, topOffset); - Vr4(dst.Slice(I4VR4), top, topOffset); - Ld4(dst.Slice(I4LD4), top, topOffset); - Vl4(dst.Slice(I4VL4), top, topOffset); - Hd4(dst.Slice(I4HD4), top, topOffset); - Hu4(dst.Slice(I4HU4), top, topOffset); + Dc4(dst[I4DC4..], top, topOffset); + Tm4(dst[I4TM4..], top, topOffset); + Ve4(dst[I4VE4..], top, topOffset, vals); + He4(dst[I4HE4..], top, topOffset); + Rd4(dst[I4RD4..], top, topOffset); + Vr4(dst[I4VR4..], top, topOffset); + Ld4(dst[I4LD4..], top, topOffset); + Vl4(dst[I4VL4..], top, topOffset); + Hd4(dst[I4HD4..], top, topOffset); + Hu4(dst[I4HU4..], top, topOffset); } private static void VerticalPred(Span dst, Span top, int size) { - if (top != null) + if (top != default) { for (int j = 0; j < size; j++) { - top.Slice(0, size).CopyTo(dst.Slice(j * WebpConstants.Bps)); + top[..size].CopyTo(dst[(j * WebpConstants.Bps)..]); } } else @@ -734,9 +720,9 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy public static void HorizontalPred(Span dst, Span left, int size) { - if (left != null) + if (left != default) { - left = left.Slice(1); // in the reference implementation, left starts at - 1. + left = left[1..]; // in the reference implementation, left starts at - 1. for (int j = 0; j < size; j++) { dst.Slice(j * WebpConstants.Bps, size).Fill(left[j]); @@ -750,20 +736,20 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy public static void TrueMotion(Span dst, Span left, Span top, int size) { - if (left != null) + if (left != default) { - if (top != null) + if (top != default) { Span clip = Clip1.AsSpan(255 - left[0]); // left [0] instead of left[-1], original left starts at -1 for (int y = 0; y < size; y++) { - Span clipTable = clip.Slice(left[y + 1]); // left[y] + Span clipTable = clip[left[y + 1]..]; // left[y] for (int x = 0; x < size; x++) { dst[x] = clipTable[top[x]]; } - dst = dst.Slice(WebpConstants.Bps); + dst = dst[WebpConstants.Bps..]; } } else @@ -777,7 +763,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy // is equivalent to VE prediction where you just copy the top samples. // Note that if top samples are not available, the default value is // then 129, and not 127 as in the VerticalPred case. - if (top != null) + if (top != default) { VerticalPred(dst, top, size); } @@ -792,17 +778,17 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy { int dc = 0; int j; - if (top != null) + if (top != default) { for (j = 0; j < size; j++) { dc += top[j]; } - if (left != null) + if (left != default) { // top and left present. - left = left.Slice(1); // in the reference implementation, left starts at -1. + left = left[1..]; // in the reference implementation, left starts at -1. for (j = 0; j < size; j++) { dc += left[j]; @@ -816,10 +802,10 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy dc = (dc + round) >> shift; } - else if (left != null) + else if (left != default) { // left but no top. - left = left.Slice(1); // in the reference implementation, left starts at -1. + left = left[1..]; // in the reference implementation, left starts at -1. for (j = 0; j < size; j++) { dc += left[j]; @@ -854,13 +840,13 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy Span clip = Clip1.AsSpan(255 - top[topOffset - 1]); for (int y = 0; y < 4; y++) { - Span clipTable = clip.Slice(top[topOffset - 2 - y]); + Span clipTable = clip[top[topOffset - 2 - y]..]; for (int x = 0; x < 4; x++) { dst[x] = clipTable[top[topOffset + x]]; } - dst = dst.Slice(WebpConstants.Bps); + dst = dst[WebpConstants.Bps..]; } } @@ -873,7 +859,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy vals[3] = LossyUtils.Avg3(top[topOffset + 2], top[topOffset + 3], top[topOffset + 4]); for (int i = 0; i < 4; i++) { - vals.CopyTo(dst.Slice(i * WebpConstants.Bps)); + vals.CopyTo(dst[(i * WebpConstants.Bps)..]); } } @@ -889,11 +875,11 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy uint val = 0x01010101U * LossyUtils.Avg3(x, i, j); BinaryPrimitives.WriteUInt32BigEndian(dst, val); val = 0x01010101U * LossyUtils.Avg3(i, j, k); - BinaryPrimitives.WriteUInt32BigEndian(dst.Slice(1 * WebpConstants.Bps), val); + BinaryPrimitives.WriteUInt32BigEndian(dst[(1 * WebpConstants.Bps)..], val); val = 0x01010101U * LossyUtils.Avg3(j, k, l); - BinaryPrimitives.WriteUInt32BigEndian(dst.Slice(2 * WebpConstants.Bps), val); + BinaryPrimitives.WriteUInt32BigEndian(dst[(2 * WebpConstants.Bps)..], val); val = 0x01010101U * LossyUtils.Avg3(k, l, l); - BinaryPrimitives.WriteUInt32BigEndian(dst.Slice(3 * WebpConstants.Bps), val); + BinaryPrimitives.WriteUInt32BigEndian(dst[(3 * WebpConstants.Bps)..], val); } private static void Rd4(Span dst, Span top, int topOffset) diff --git a/src/ImageSharp/Formats/Webp/Lossy/Vp8Histogram.cs b/src/ImageSharp/Formats/Webp/Lossy/Vp8Histogram.cs index a52d9e90a..1ba359d85 100644 --- a/src/ImageSharp/Formats/Webp/Lossy/Vp8Histogram.cs +++ b/src/ImageSharp/Formats/Webp/Lossy/Vp8Histogram.cs @@ -4,10 +4,8 @@ using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; -#endif namespace SixLabors.ImageSharp.Formats.Webp.Lossy { @@ -54,10 +52,9 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy this.distribution.AsSpan().Clear(); for (j = startBlock; j < endBlock; j++) { - Vp8Encoding.FTransform(reference.Slice(WebpLookupTables.Vp8DspScan[j]), pred.Slice(WebpLookupTables.Vp8DspScan[j]), this.output, this.scratch); + Vp8Encoding.FTransform(reference[WebpLookupTables.Vp8DspScan[j]..], pred[WebpLookupTables.Vp8DspScan[j]..], this.output, this.scratch); // Convert coefficients to bin. -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx2.IsSupported) { // Load. @@ -81,7 +78,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy } } else -#endif { for (int k = 0; k < 16; ++k) { diff --git a/src/ImageSharp/Formats/Webp/Lossy/Vp8Residual.cs b/src/ImageSharp/Formats/Webp/Lossy/Vp8Residual.cs index e3a5696e3..42116932a 100644 --- a/src/ImageSharp/Formats/Webp/Lossy/Vp8Residual.cs +++ b/src/ImageSharp/Formats/Webp/Lossy/Vp8Residual.cs @@ -4,10 +4,8 @@ using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; -#endif namespace SixLabors.ImageSharp.Formats.Webp.Lossy { @@ -46,7 +44,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy public void SetCoeffs(Span coeffs) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Sse2.IsSupported) { ref short coeffsRef = ref MemoryMarshal.GetReference(coeffs); @@ -68,7 +65,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy this.Last = mask != 0 ? Numerics.Log2(mask) : -1; } else -#endif { int n; this.Last = -1; @@ -82,7 +78,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy } } - coeffs.Slice(0, 16).CopyTo(this.Coeffs); + coeffs[..16].CopyTo(this.Coeffs); } // Simulate block coding, but only record statistics. @@ -93,23 +89,23 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy Vp8StatsArray s = this.Stats[n].Stats[ctx]; if (this.Last < 0) { - this.RecordStats(0, s, 0); + RecordStats(0, s, 0); return 0; } while (n <= this.Last) { int v; - this.RecordStats(1, s, 0); // order of record doesn't matter + RecordStats(1, s, 0); // order of record doesn't matter while ((v = this.Coeffs[n++]) == 0) { - this.RecordStats(0, s, 1); + RecordStats(0, s, 1); s = this.Stats[WebpConstants.Vp8EncBands[n]].Stats[0]; } - this.RecordStats(1, s, 1); + RecordStats(1, s, 1); bool bit = (uint)(v + 1) > 2u; - if (this.RecordStats(bit ? 1 : 0, s, 2) == 0) + if (RecordStats(bit ? 1 : 0, s, 2) == 0) { // v = -1 or 1 s = this.Stats[WebpConstants.Vp8EncBands[n]].Stats[1]; @@ -130,7 +126,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy int mask = 2 << i; if ((pattern & 1) != 0) { - this.RecordStats((bits & mask) != 0 ? 1 : 0, s, 3 + i); + RecordStats((bits & mask) != 0 ? 1 : 0, s, 3 + i); } } @@ -140,7 +136,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy if (n < 16) { - this.RecordStats(0, s, 0); + RecordStats(0, s, 0); } return 1; @@ -163,7 +159,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy return LossyUtils.Vp8BitCost(0, (byte)p0); } -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx2.IsSupported) { Span ctxs = this.scratch.AsSpan(0, 16); @@ -211,7 +206,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy return cost; } -#endif + { int v; for (; n < this.Last; ++n) @@ -241,7 +236,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy private static int LevelCost(Span table, int level) => WebpLookupTables.Vp8LevelFixedCosts[level] + table[level > WebpConstants.MaxVariableLevel ? WebpConstants.MaxVariableLevel : level]; - private int RecordStats(int bit, Vp8StatsArray statsArr, int idx) + private static int RecordStats(int bit, Vp8StatsArray statsArr, int idx) { // An overflow is inbound. Note we handle this at 0xfffe0000u instead of // 0xffff0000u to make sure p + 1u does not overflow. diff --git a/src/ImageSharp/Formats/Webp/Lossy/YuvConversion.cs b/src/ImageSharp/Formats/Webp/Lossy/YuvConversion.cs index 6e350e7dc..ea2b82c2c 100644 --- a/src/ImageSharp/Formats/Webp/Lossy/YuvConversion.cs +++ b/src/ImageSharp/Formats/Webp/Lossy/YuvConversion.cs @@ -5,10 +5,8 @@ using System; using System.Buffers; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; -#endif using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; @@ -32,13 +30,11 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy // ([3*a + b + 9*c + 3*d a + 3*b + 3*c + 9*d] [8 8]) / 16 public static void UpSample(Span topY, Span bottomY, Span topU, Span topV, Span curU, Span curV, Span topDst, Span bottomDst, int len, byte[] uvBuffer) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Sse41.IsSupported) { UpSampleSse41(topY, bottomY, topU, topV, curU, curV, topDst, bottomDst, len, uvBuffer); } else -#endif { UpSampleScalar(topY, bottomY, topU, topV, curU, curV, topDst, bottomDst, len); } @@ -46,7 +42,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy private static void UpSampleScalar(Span topY, Span bottomY, Span topU, Span topV, Span curU, Span curV, Span topDst, Span bottomDst, int len) { - int xStep = 3; + const int xStep = 3; int lastPixelPair = (len - 1) >> 1; uint tluv = LoadUv(topU[0], topV[0]); // top-left sample uint luv = LoadUv(curU[0], curV[0]); // left-sample @@ -71,15 +67,15 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy uv0 = (diag12 + tluv) >> 1; uint uv1 = (diag03 + tuv) >> 1; int xMul2 = x * 2; - YuvToBgr(topY[xMul2 - 1], (int)(uv0 & 0xff), (int)(uv0 >> 16), topDst.Slice((xMul2 - 1) * xStep)); - YuvToBgr(topY[xMul2 - 0], (int)(uv1 & 0xff), (int)(uv1 >> 16), topDst.Slice((xMul2 - 0) * xStep)); + YuvToBgr(topY[xMul2 - 1], (int)(uv0 & 0xff), (int)(uv0 >> 16), topDst[((xMul2 - 1) * xStep)..]); + YuvToBgr(topY[xMul2 - 0], (int)(uv1 & 0xff), (int)(uv1 >> 16), topDst[((xMul2 - 0) * xStep)..]); if (bottomY != default) { uv0 = (diag03 + luv) >> 1; uv1 = (diag12 + uv) >> 1; - YuvToBgr(bottomY[xMul2 - 1], (int)(uv0 & 0xff), (int)(uv0 >> 16), bottomDst.Slice((xMul2 - 1) * xStep)); - YuvToBgr(bottomY[xMul2 + 0], (int)(uv1 & 0xff), (int)(uv1 >> 16), bottomDst.Slice((xMul2 + 0) * xStep)); + YuvToBgr(bottomY[xMul2 - 1], (int)(uv0 & 0xff), (int)(uv0 >> 16), bottomDst[((xMul2 - 1) * xStep)..]); + YuvToBgr(bottomY[xMul2 + 0], (int)(uv1 & 0xff), (int)(uv1 >> 16), bottomDst[((xMul2 + 0) * xStep)..]); } tluv = tuv; @@ -89,16 +85,15 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy if ((len & 1) == 0) { uv0 = ((3 * tluv) + luv + 0x00020002u) >> 2; - YuvToBgr(topY[len - 1], (int)(uv0 & 0xff), (int)(uv0 >> 16), topDst.Slice((len - 1) * xStep)); + YuvToBgr(topY[len - 1], (int)(uv0 & 0xff), (int)(uv0 >> 16), topDst[((len - 1) * xStep)..]); if (bottomY != default) { uv0 = ((3 * luv) + tluv + 0x00020002u) >> 2; - YuvToBgr(bottomY[len - 1], (int)(uv0 & 0xff), (int)(uv0 >> 16), bottomDst.Slice((len - 1) * xStep)); + YuvToBgr(bottomY[len - 1], (int)(uv0 & 0xff), (int)(uv0 >> 16), bottomDst[((len - 1) * xStep)..]); } } } -#if SUPPORTS_RUNTIME_INTRINSICS // We compute (9*a + 3*b + 3*c + d + 8) / 16 as follows // u = (9*a + 3*b + 3*c + d + 8) / 16 // = (a + (a + 3*b + 3*c + d) / 8 + 1) / 2 @@ -118,7 +113,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy const int xStep = 3; Array.Clear(uvBuffer); Span ru = uvBuffer.AsSpan(15); - Span rv = ru.Slice(32); + Span rv = ru[32..]; // Treat the first pixel in regular way. int uDiag = ((topU[0] + curU[0]) >> 1) + 1; @@ -140,7 +135,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy ref byte topVRef = ref MemoryMarshal.GetReference(topV); ref byte curURef = ref MemoryMarshal.GetReference(curU); ref byte curVRef = ref MemoryMarshal.GetReference(curV); - if (bottomY != null) + if (bottomY != default) { for (pos = 1, uvPos = 0; pos + 32 + 1 <= len; pos += 32, uvPos += 16) { @@ -163,17 +158,17 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy if (len > 1) { int leftOver = ((len + 1) >> 1) - (pos >> 1); - Span tmpTopDst = ru.Slice(4 * 32); - Span tmpBottomDst = tmpTopDst.Slice(4 * 32); - Span tmpTop = tmpBottomDst.Slice(4 * 32); - Span tmpBottom = (bottomY == null) ? null : tmpTop.Slice(32); - UpSampleLastBlock(topU.Slice(uvPos), curU.Slice(uvPos), leftOver, ru); - UpSampleLastBlock(topV.Slice(uvPos), curV.Slice(uvPos), leftOver, rv); - - topY.Slice(pos, len - pos).CopyTo(tmpTop); + Span tmpTopDst = ru[(4 * 32)..]; + Span tmpBottomDst = tmpTopDst[(4 * 32)..]; + Span tmpTop = tmpBottomDst[(4 * 32)..]; + Span tmpBottom = (bottomY == default) ? null : tmpTop[32..]; + UpSampleLastBlock(topU[uvPos..], curU[uvPos..], leftOver, ru); + UpSampleLastBlock(topV[uvPos..], curV[uvPos..], leftOver, rv); + + topY[pos..len].CopyTo(tmpTop); if (bottomY != default) { - bottomY.Slice(pos, len - pos).CopyTo(tmpBottom); + bottomY[pos..len].CopyTo(tmpBottom); ConvertYuvToBgrWithBottomYSse41(tmpTop, tmpBottom, tmpTopDst, tmpBottomDst, ru, rv, 0, xStep); } else @@ -181,10 +176,10 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy ConvertYuvToBgrSse41(tmpTop, tmpTopDst, ru, rv, 0, xStep); } - tmpTopDst.Slice(0, (len - pos) * xStep).CopyTo(topDst.Slice(pos * xStep)); + tmpTopDst[..((len - pos) * xStep)].CopyTo(topDst[(pos * xStep)..]); if (bottomY != default) { - tmpBottomDst.Slice(0, (len - pos) * xStep).CopyTo(bottomDst.Slice(pos * xStep)); + tmpBottomDst[..((len - pos) * xStep)].CopyTo(bottomDst[(pos * xStep)..]); } } } @@ -216,15 +211,15 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy // Pack the alternate pixels. PackAndStore(a, b, diag1, diag2, output); // store top. - PackAndStore(c, d, diag2, diag1, output.Slice(2 * 32)); + PackAndStore(c, d, diag2, diag1, output[(2 * 32)..]); } private static void UpSampleLastBlock(Span tb, Span bb, int numPixels, Span output) { Span r1 = stackalloc byte[17]; Span r2 = stackalloc byte[17]; - tb.Slice(0, numPixels).CopyTo(r1); - bb.Slice(0, numPixels).CopyTo(r2); + tb[..numPixels].CopyTo(r1); + bb[..numPixels].CopyTo(r2); // Replicate last byte. int length = 17 - numPixels; @@ -263,7 +258,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy Unsafe.As>(ref output0Ref) = t1; Unsafe.As>(ref output1Ref) = t2; } -#endif /// /// Converts the RGB values of the image to YUV. @@ -317,11 +311,11 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy AccumulateRgba(bgraRow0, bgraRow1, tmpRgbSpan, width); } - ConvertRgbaToUv(tmpRgbSpan, u.Slice(uvRowIndex * uvWidth), v.Slice(uvRowIndex * uvWidth), uvWidth); + ConvertRgbaToUv(tmpRgbSpan, u[(uvRowIndex * uvWidth)..], v[(uvRowIndex * uvWidth)..], uvWidth); uvRowIndex++; - ConvertRgbaToY(bgraRow0, y.Slice(rowIndex * width), width); - ConvertRgbaToY(bgraRow1, y.Slice((rowIndex + 1) * width), width); + ConvertRgbaToY(bgraRow0, y[(rowIndex * width)..], width); + ConvertRgbaToY(bgraRow1, y[((rowIndex + 1) * width)..], width); } // Extra last row. @@ -329,7 +323,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy { Span rowSpan = imageBuffer.DangerousGetRowSpan(rowIndex); PixelOperations.Instance.ToBgra32(configuration, rowSpan, bgraRow0); - ConvertRgbaToY(bgraRow0, y.Slice(rowIndex * width), width); + ConvertRgbaToY(bgraRow0, y[(rowIndex * width)..], width); if (!WebpCommonUtils.CheckNonOpaque(bgraRow0)) { @@ -341,7 +335,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy hasAlpha = true; } - ConvertRgbaToUv(tmpRgbSpan, u.Slice(uvRowIndex * uvWidth), v.Slice(uvRowIndex * uvWidth), uvWidth); + ConvertRgbaToUv(tmpRgbSpan, u[(uvRowIndex * uvWidth)..], v[(uvRowIndex * uvWidth)..], uvWidth); } return hasAlpha; @@ -569,16 +563,14 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy bgr[0] = (byte)YuvToB(y, u); } -#if SUPPORTS_RUNTIME_INTRINSICS - [MethodImpl(InliningOptions.ShortMethod)] - private static void ConvertYuvToBgrSse41(Span topY, Span topDst, Span ru, Span rv, int curX, int step) => YuvToBgrSse41(topY.Slice(curX), ru, rv, topDst.Slice(curX * step)); + private static void ConvertYuvToBgrSse41(Span topY, Span topDst, Span ru, Span rv, int curX, int step) => YuvToBgrSse41(topY[curX..], ru, rv, topDst[(curX * step)..]); [MethodImpl(InliningOptions.ShortMethod)] private static void ConvertYuvToBgrWithBottomYSse41(Span topY, Span bottomY, Span topDst, Span bottomDst, Span ru, Span rv, int curX, int step) { - YuvToBgrSse41(topY.Slice(curX), ru, rv, topDst.Slice(curX * step)); - YuvToBgrSse41(bottomY.Slice(curX), ru.Slice(64), rv.Slice(64), bottomDst.Slice(curX * step)); + YuvToBgrSse41(topY[curX..], ru, rv, topDst[(curX * step)..]); + YuvToBgrSse41(bottomY[curX..], ru[64..], rv[64..], bottomDst[(curX * step)..]); } private static void YuvToBgrSse41(Span y, Span u, Span v, Span dst) @@ -718,9 +710,9 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy // R = (19077 * y + 26149 * v - 14234) >> 6 // G = (19077 * y - 6419 * u - 13320 * v + 8708) >> 6 // B = (19077 * y + 33050 * u - 17685) >> 6 - Vector128 k19077 = Vector128.Create((ushort)19077); - Vector128 k26149 = Vector128.Create((ushort)26149); - Vector128 k14234 = Vector128.Create((ushort)14234); + var k19077 = Vector128.Create((ushort)19077); + var k26149 = Vector128.Create((ushort)26149); + var k14234 = Vector128.Create((ushort)14234); Vector128 y1 = Sse2.MultiplyHigh(y0.AsUInt16(), k19077); Vector128 r0 = Sse2.MultiplyHigh(v0.AsUInt16(), k26149); @@ -744,8 +736,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy b = Sse2.ShiftRightLogical(b2.AsInt16(), 6); // range: [0, 34238] } -#endif - [MethodImpl(InliningOptions.ShortMethod)] public static int YuvToB(int y, int u) => Clip8(MultHi(y, 19077) + MultHi(u, 33050) - 17685); @@ -761,7 +751,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy [MethodImpl(InliningOptions.ShortMethod)] private static byte Clip8(int v) { - int yuvMask = (256 << 6) - 1; + const int yuvMask = (256 << 6) - 1; return (byte)((v & ~yuvMask) == 0 ? v >> 6 : v < 0 ? 0 : 255); } } diff --git a/src/ImageSharp/Formats/Webp/WebpCommonUtils.cs b/src/ImageSharp/Formats/Webp/WebpCommonUtils.cs index bd862c41c..c5d8c30ed 100644 --- a/src/ImageSharp/Formats/Webp/WebpCommonUtils.cs +++ b/src/ImageSharp/Formats/Webp/WebpCommonUtils.cs @@ -3,11 +3,9 @@ using System; using System.Runtime.InteropServices; -using SixLabors.ImageSharp.PixelFormats; -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; -#endif +using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Formats.Webp { @@ -23,7 +21,6 @@ namespace SixLabors.ImageSharp.Formats.Webp /// Returns true if alpha has non-0xff values. public static unsafe bool CheckNonOpaque(Span row) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx2.IsSupported) { ReadOnlySpan rowBytes = MemoryMarshal.AsBytes(row); @@ -31,7 +28,7 @@ namespace SixLabors.ImageSharp.Formats.Webp int length = (row.Length * 4) - 3; fixed (byte* src = rowBytes) { - Vector256 alphaMaskVector256 = Vector256.Create(0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255); + var alphaMaskVector256 = Vector256.Create(0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255); Vector256 all0x80Vector256 = Vector256.Create((byte)0x80).AsByte(); for (; i + 128 <= length; i += 128) @@ -113,7 +110,6 @@ namespace SixLabors.ImageSharp.Formats.Webp } } else -#endif { for (int x = 0; x < row.Length; x++) { @@ -127,10 +123,9 @@ namespace SixLabors.ImageSharp.Formats.Webp return false; } -#if SUPPORTS_RUNTIME_INTRINSICS private static unsafe bool IsNoneOpaque64Bytes(byte* src, int i) { - Vector128 alphaMask = Vector128.Create(0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255); + var alphaMask = Vector128.Create(0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255); Vector128 a0 = Sse2.LoadVector128(src + i).AsByte(); Vector128 a1 = Sse2.LoadVector128(src + i + 16).AsByte(); @@ -145,17 +140,12 @@ namespace SixLabors.ImageSharp.Formats.Webp Vector128 d = Sse2.PackSignedSaturate(c0, c1).AsByte(); Vector128 bits = Sse2.CompareEqual(d, Vector128.Create((byte)0x80).AsByte()); int mask = Sse2.MoveMask(bits); - if (mask != 0xFFFF) - { - return true; - } - - return false; + return mask != 0xFFFF; } private static unsafe bool IsNoneOpaque32Bytes(byte* src, int i) { - Vector128 alphaMask = Vector128.Create(0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255); + var alphaMask = Vector128.Create(0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255); Vector128 a0 = Sse2.LoadVector128(src + i).AsByte(); Vector128 a1 = Sse2.LoadVector128(src + i + 16).AsByte(); @@ -165,13 +155,7 @@ namespace SixLabors.ImageSharp.Formats.Webp Vector128 d = Sse2.PackSignedSaturate(c, c).AsByte(); Vector128 bits = Sse2.CompareEqual(d, Vector128.Create((byte)0x80).AsByte()); int mask = Sse2.MoveMask(bits); - if (mask != 0xFFFF) - { - return true; - } - - return false; + return mask != 0xFFFF; } -#endif } } diff --git a/src/ImageSharp/IO/BufferedReadStream.cs b/src/ImageSharp/IO/BufferedReadStream.cs index a117b7d11..572563ef3 100644 --- a/src/ImageSharp/IO/BufferedReadStream.cs +++ b/src/ImageSharp/IO/BufferedReadStream.cs @@ -175,7 +175,6 @@ namespace SixLabors.ImageSharp.IO return this.ReadToBufferViaCopyFast(buffer, offset, count); } -#if SUPPORTS_SPAN_STREAM /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public override int Read(Span buffer) @@ -196,7 +195,6 @@ namespace SixLabors.ImageSharp.IO return this.ReadToBufferViaCopyFast(buffer); } -#endif /// public override void Flush() @@ -354,7 +352,7 @@ namespace SixLabors.ImageSharp.IO int i; do { - i = baseStream.Read(buffer.Slice(n, count - n)); + i = baseStream.Read(buffer[n..count]); n += i; } while (n < count && i > 0); diff --git a/src/ImageSharp/IO/ChunkedMemoryStream.cs b/src/ImageSharp/IO/ChunkedMemoryStream.cs index 2bd8563ab..44ec7aa29 100644 --- a/src/ImageSharp/IO/ChunkedMemoryStream.cs +++ b/src/ImageSharp/IO/ChunkedMemoryStream.cs @@ -236,11 +236,9 @@ namespace SixLabors.ImageSharp.IO return this.ReadImpl(buffer.AsSpan(offset, count)); } -#if SUPPORTS_SPAN_STREAM /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public override int Read(Span buffer) => this.ReadImpl(buffer); -#endif private int ReadImpl(Span buffer) { @@ -352,11 +350,9 @@ namespace SixLabors.ImageSharp.IO this.WriteImpl(buffer.AsSpan(offset, count)); } -#if SUPPORTS_SPAN_STREAM /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public override void Write(ReadOnlySpan buffer) => this.WriteImpl(buffer); -#endif private void WriteImpl(ReadOnlySpan buffer) { diff --git a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.cs b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.cs index 18d80dd51..ace02c8fa 100644 --- a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.cs +++ b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.cs @@ -7,7 +7,6 @@ using System.Collections; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using System.Threading; using SixLabors.ImageSharp.Memory.Internals; namespace SixLabors.ImageSharp.Memory @@ -129,7 +128,7 @@ namespace SixLabors.ImageSharp.Memory if (bufferCount > 0) { - buffers[buffers.Length - 1] = allocator.Allocate(sizeOfLastBuffer, options); + buffers[^1] = allocator.Allocate(sizeOfLastBuffer, options); } return new Owned(buffers, bufferLength, totalLengthInElements, true); @@ -214,12 +213,12 @@ namespace SixLabors.ImageSharp.Memory } } - if (source.Length > 0 && source[source.Length - 1].Length > bufferLength) + if (source.Length > 0 && source[^1].Length > bufferLength) { throw new InvalidMemoryOperationException("Wrap: the last buffer is too large!"); } - long totalLength = bufferLength > 0 ? ((long)bufferLength * (source.Length - 1)) + source[source.Length - 1].Length : 0; + long totalLength = bufferLength > 0 ? ((long)bufferLength * (source.Length - 1)) + source[^1].Length : 0; return new Consumed(source, bufferLength, totalLength); } @@ -235,12 +234,12 @@ namespace SixLabors.ImageSharp.Memory } } - if (source.Length > 0 && source[source.Length - 1].Memory.Length > bufferLength) + if (source.Length > 0 && source[^1].Memory.Length > bufferLength) { throw new InvalidMemoryOperationException("Wrap: the last buffer is too large!"); } - long totalLength = bufferLength > 0 ? ((long)bufferLength * (source.Length - 1)) + source[source.Length - 1].Memory.Length : 0; + long totalLength = bufferLength > 0 ? ((long)bufferLength * (source.Length - 1)) + source[^1].Memory.Length : 0; return new Owned(source, bufferLength, totalLength, false); } @@ -252,15 +251,10 @@ namespace SixLabors.ImageSharp.Memory { case SpanCacheMode.SingleArray: { -#if SUPPORTS_CREATESPAN ref byte b0 = ref MemoryMarshal.GetReference(this.memoryGroupSpanCache.SingleArray); ref T e0 = ref Unsafe.As(ref b0); e0 = ref Unsafe.Add(ref e0, y * width); return MemoryMarshal.CreateSpan(ref e0, width); -#else - return MemoryMarshal.Cast(this.memoryGroupSpanCache.SingleArray).Slice(y * width, width); -#endif - } case SpanCacheMode.SinglePointer: diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgb24.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgb24.PixelOperations.cs index 07923c8ae..310a479f5 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgb24.PixelOperations.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgb24.PixelOperations.cs @@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.PixelFormats internal partial class PixelOperations : PixelOperations { private static readonly Lazy LazyInfo = - new Lazy(() => PixelTypeInfo.Create(PixelAlphaRepresentation.None), true); + new(() => PixelTypeInfo.Create(PixelAlphaRepresentation.None), true); /// public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; @@ -34,7 +34,7 @@ namespace SixLabors.ImageSharp.PixelFormats int count = redChannel.Length; GuardPackFromRgbPlanes(greenChannel, blueChannel, destination, count); - SimdUtils.PackFromRgbPlanes(configuration, redChannel, greenChannel, blueChannel, destination); + SimdUtils.PackFromRgbPlanes(redChannel, greenChannel, blueChannel, destination); } } } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgba32.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgba32.PixelOperations.cs index e55332228..98d9177a9 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgba32.PixelOperations.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgba32.PixelOperations.cs @@ -20,7 +20,7 @@ namespace SixLabors.ImageSharp.PixelFormats internal partial class PixelOperations : PixelOperations { private static readonly Lazy LazyInfo = - new Lazy(() => PixelTypeInfo.Create(PixelAlphaRepresentation.Unassociated), true); + new(() => PixelTypeInfo.Create(PixelAlphaRepresentation.Unassociated), true); /// public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; @@ -34,7 +34,7 @@ namespace SixLabors.ImageSharp.PixelFormats { Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationVectors, nameof(destinationVectors)); - destinationVectors = destinationVectors.Slice(0, sourcePixels.Length); + destinationVectors = destinationVectors[..sourcePixels.Length]; SimdUtils.ByteToNormalizedFloat( MemoryMarshal.Cast(sourcePixels), MemoryMarshal.Cast(destinationVectors)); @@ -50,7 +50,7 @@ namespace SixLabors.ImageSharp.PixelFormats { Guard.DestinationShouldNotBeTooShort(sourceVectors, destinationPixels, nameof(destinationPixels)); - destinationPixels = destinationPixels.Slice(0, sourceVectors.Length); + destinationPixels = destinationPixels[..sourceVectors.Length]; Vector4Converters.ApplyBackwardConversionModifiers(sourceVectors, modifiers); SimdUtils.NormalizedFloatToByteSaturate( MemoryMarshal.Cast(sourceVectors), @@ -69,7 +69,7 @@ namespace SixLabors.ImageSharp.PixelFormats int count = redChannel.Length; GuardPackFromRgbPlanes(greenChannel, blueChannel, destination, count); - SimdUtils.PackFromRgbPlanes(configuration, redChannel, greenChannel, blueChannel, destination); + SimdUtils.PackFromRgbPlanes(redChannel, greenChannel, blueChannel, destination); } } } diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs index d6cfbc4cc..73a75bf66 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs @@ -4,11 +4,9 @@ using System; using System.Numerics; using System.Runtime.CompilerServices; -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.InteropServices; using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; -#endif namespace SixLabors.ImageSharp.Processing.Processors.Transforms { @@ -56,7 +54,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms public Span Values { [MethodImpl(InliningOptions.ShortMethod)] - get => new Span(this.bufferPtr, this.Length); + get => new(this.bufferPtr, this.Length); } /// @@ -71,7 +69,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms [MethodImpl(InliningOptions.ShortMethod)] public Vector4 ConvolveCore(ref Vector4 rowStartRef) { -#if SUPPORTS_RUNTIME_INTRINSICS if (Avx2.IsSupported && Fma.IsSupported) { float* bufferStart = this.bufferPtr; @@ -141,7 +138,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms return *(Vector4*)&result128; } else -#endif { // Destination color components Vector4 result = Vector4.Zero; @@ -167,7 +163,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// [MethodImpl(InliningOptions.ShortMethod)] internal ResizeKernel AlterLeftValue(int left) - => new ResizeKernel(left, this.bufferPtr, this.Length); + => new(left, this.bufferPtr, this.Length); internal void Fill(Span values) { diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_CopyTo1x1.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_CopyTo1x1.cs index 5b2c8c05e..ee196cbea 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_CopyTo1x1.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_CopyTo1x1.cs @@ -5,10 +5,8 @@ using System; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; -#endif using BenchmarkDotNet.Attributes; using SixLabors.ImageSharp.Formats.Jpeg.Components; @@ -169,7 +167,6 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg.BlockOperations Unsafe.As>(ref Unsafe.AddByteOffset(ref d, (IntPtr)(stride * 7))) = v3; } -#if SUPPORTS_RUNTIME_INTRINSICS [Benchmark] public void UseVector256_Avx2_Variant1() { @@ -319,7 +316,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg.BlockOperations { fixed (Block8x8F* ss = &this.block) { - var s = (float*)ss; + float* s = (float*)ss; Vector256 v0 = Avx.LoadVector256(s); Vector256 v1 = Avx.LoadVector256(s + 8); Vector256 v2 = Avx.LoadVector256(s + (8 * 2)); @@ -345,8 +342,8 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg.BlockOperations public void UseVector256_Avx2_Variant3_sbyte() { int stride = Width * 4; - var d = (sbyte*)this.bufferPtr; - var s = (sbyte*)this.blockPtr; + sbyte* d = (sbyte*)this.bufferPtr; + sbyte* s = (sbyte*)this.blockPtr; Vector256 v0 = Avx.LoadVector256(s); Vector256 v1 = Avx.LoadVector256(s + 32); @@ -366,7 +363,6 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg.BlockOperations Avx.Store(d + (stride * 6), v2); Avx.Store(d + (stride * 7), v3); } -#endif // *** RESULTS 02/2020 *** // BenchmarkDotNet=v0.12.0, OS=Windows 10.0.18363 diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_Round.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_Round.cs index 6dc5702fa..1ff81d677 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_Round.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_Round.cs @@ -5,10 +5,8 @@ using System; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; -#endif using BenchmarkDotNet.Attributes; using SixLabors.ImageSharp.Formats.Jpeg.Components; @@ -136,7 +134,6 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg.BlockOperations row3 = SimdUtils.FastRound(row3); } -#if SUPPORTS_RUNTIME_INTRINSICS [Benchmark] public void Sse41_V1() { @@ -491,6 +488,5 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg.BlockOperations Sse.StoreAligned(p6, v6); Sse.StoreAligned(p7, v7); } -#endif } } diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/CmykColorConversion.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/CmykColorConversion.cs index b838453cc..e44eeb777 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/CmykColorConversion.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/CmykColorConversion.cs @@ -30,7 +30,6 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg new JpegColorConverterBase.FromCmykVector(8).ConvertToRgbInplace(values); } -#if SUPPORTS_RUNTIME_INTRINSICS [Benchmark] public void SimdVectorAvx() { @@ -38,6 +37,5 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg new JpegColorConverterBase.FromCmykAvx(8).ConvertToRgbInplace(values); } -#endif } } diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/GrayscaleColorConversion.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/GrayscaleColorConversion.cs index 00550ccae..e69b509de 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/GrayscaleColorConversion.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/GrayscaleColorConversion.cs @@ -22,7 +22,6 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg new JpegColorConverterBase.FromGrayscaleScalar(8).ConvertToRgbInplace(values); } -#if SUPPORTS_RUNTIME_INTRINSICS [Benchmark] public void SimdVectorAvx() { @@ -30,6 +29,5 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg new JpegColorConverterBase.FromGrayscaleAvx(8).ConvertToRgbInplace(values); } -#endif } } diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/RgbColorConversion.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/RgbColorConversion.cs index 4d2bf1d8f..a34489d7e 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/RgbColorConversion.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/RgbColorConversion.cs @@ -30,7 +30,6 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg new JpegColorConverterBase.FromRgbVector(8).ConvertToRgbInplace(values); } -#if SUPPORTS_RUNTIME_INTRINSICS [Benchmark] public void SimdVectorAvx() { @@ -38,6 +37,5 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg new JpegColorConverterBase.FromRgbAvx(8).ConvertToRgbInplace(values); } -#endif } } diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/YCbCrColorConversion.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/YCbCrColorConversion.cs index e8144bf5a..22697a21c 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/YCbCrColorConversion.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/YCbCrColorConversion.cs @@ -30,7 +30,6 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg new JpegColorConverterBase.FromYCbCrVector(8).ConvertToRgbInplace(values); } -#if SUPPORTS_RUNTIME_INTRINSICS [Benchmark] public void SimdVectorAvx() { @@ -38,6 +37,5 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg new JpegColorConverterBase.FromYCbCrAvx(8).ConvertToRgbInplace(values); } -#endif } } diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/YccKColorConverter.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/YccKColorConverter.cs index 19cbfc1f5..471f9be72 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/YccKColorConverter.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/YccKColorConverter.cs @@ -30,7 +30,6 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg new JpegColorConverterBase.FromYccKVector(8).ConvertToRgbInplace(values); } -#if SUPPORTS_RUNTIME_INTRINSICS [Benchmark] public void SimdVectorAvx2() { @@ -38,6 +37,5 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg new JpegColorConverterBase.FromYccKAvx(8).ConvertToRgbInplace(values); } -#endif } } diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/FromVector4.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/FromVector4.cs index 9f7a988e1..bb2985ab7 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/FromVector4.cs +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/FromVector4.cs @@ -6,10 +6,8 @@ using System.Buffers; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; -#endif using BenchmarkDotNet.Attributes; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; @@ -80,15 +78,6 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk SimdUtils.FallbackIntrinsics128.NormalizedFloatToByteSaturate(sBytes, dFloats); } - [Benchmark] - public void BasicIntrinsics256() - { - Span sBytes = MemoryMarshal.Cast(this.source.GetSpan()); - Span dFloats = MemoryMarshal.Cast(this.destination.GetSpan()); - - SimdUtils.BasicIntrinsics256.NormalizedFloatToByteSaturate(sBytes, dFloats); - } - [Benchmark] public void ExtendedIntrinsic() { @@ -98,7 +87,6 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk SimdUtils.ExtendedIntrinsics.NormalizedFloatToByteSaturate(sBytes, dFloats); } -#if SUPPORTS_RUNTIME_INTRINSICS [Benchmark] public void UseHwIntrinsics() { @@ -161,7 +149,6 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk vf = Avx.Multiply(scale, vf); return Avx.ConvertToVector256Int32(vf); } -#endif // *** RESULTS 2020 March: *** // Intel Core i7-8650U CPU 1.90GHz (Kaby Lake R), 1 CPU, 8 logical and 4 physical cores diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Rgba32.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Rgba32.cs index 88b4c200e..ec51e104e 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Rgba32.cs +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Rgba32.cs @@ -26,21 +26,10 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk [Benchmark] public void PixelOperations_Base() - { - new PixelOperations().ToVector4( + => new PixelOperations().ToVector4( this.Configuration, this.source.GetSpan(), this.destination.GetSpan()); - } - - [Benchmark(Baseline = true)] - public void BasicIntrinsics256() - { - Span sBytes = MemoryMarshal.Cast(this.source.GetSpan()); - Span dFloats = MemoryMarshal.Cast(this.destination.GetSpan()); - - SimdUtils.BasicIntrinsics256.ByteToNormalizedFloat(sBytes, dFloats); - } [Benchmark] public void ExtendedIntrinsics() @@ -51,7 +40,6 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk SimdUtils.ExtendedIntrinsics.ByteToNormalizedFloat(sBytes, dFloats); } -#if SUPPORTS_RUNTIME_INTRINSICS [Benchmark] public void HwIntrinsics() { @@ -60,7 +48,6 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk SimdUtils.HwIntrinsics.ByteToNormalizedFloat(sBytes, dFloats); } -#endif // [Benchmark] public void ExtendedIntrinsics_BulkConvertByteToNormalizedFloat_2Loops() @@ -96,8 +83,8 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk { ref Vector dRef = ref Unsafe.Add(ref destBase, i); - Vector du = Vector.AsVectorInt32(dRef); - Vector v = Vector.ConvertToSingle(du); + var du = Vector.AsVectorInt32(dRef); + var v = Vector.ConvertToSingle(du); v *= scale; dRef = v; diff --git a/tests/ImageSharp.Benchmarks/Config.HwIntrinsics.cs b/tests/ImageSharp.Benchmarks/Config.HwIntrinsics.cs index 16b016a7c..4de745005 100644 --- a/tests/ImageSharp.Benchmarks/Config.HwIntrinsics.cs +++ b/tests/ImageSharp.Benchmarks/Config.HwIntrinsics.cs @@ -1,9 +1,7 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.Intrinsics.X86; -#endif using BenchmarkDotNet.Environments; using BenchmarkDotNet.Jobs; @@ -58,26 +56,24 @@ namespace SixLabors.ImageSharp.Benchmarks { public HwIntrinsics_SSE_AVX() { - this.AddJob(Job.Default.WithRuntime(CoreRuntime.Core31) + this.AddJob(Job.Default.WithRuntime(CoreRuntime.Core60) .WithEnvironmentVariables( new EnvironmentVariable(EnableHWIntrinsic, Off), new EnvironmentVariable(FeatureSIMD, Off)) .WithId("1. No HwIntrinsics").AsBaseline()); -#if SUPPORTS_RUNTIME_INTRINSICS if (Sse.IsSupported) { - this.AddJob(Job.Default.WithRuntime(CoreRuntime.Core31) + this.AddJob(Job.Default.WithRuntime(CoreRuntime.Core60) .WithEnvironmentVariables(new EnvironmentVariable(EnableAVX, Off)) .WithId("2. SSE")); } if (Avx.IsSupported) { - this.AddJob(Job.Default.WithRuntime(CoreRuntime.Core31) + this.AddJob(Job.Default.WithRuntime(CoreRuntime.Core60) .WithId("3. AVX")); } -#endif } } } diff --git a/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_PackFromRgbPlanes.cs b/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_PackFromRgbPlanes.cs index d0300b057..252ff9058 100644 --- a/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_PackFromRgbPlanes.cs +++ b/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_PackFromRgbPlanes.cs @@ -4,10 +4,8 @@ using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; -#endif using BenchmarkDotNet.Attributes; using SixLabors.ImageSharp.PixelFormats; @@ -200,7 +198,6 @@ namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion } } -#if SUPPORTS_RUNTIME_INTRINSICS [Benchmark(Baseline = true)] public void Rgba32_Avx2_Float() { @@ -261,7 +258,6 @@ namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion Span rgb = this.rgbaBuf; SimdUtils.HwIntrinsics.PackFromRgbPlanesAvx2Reduce(ref r, ref g, ref b, ref rgb); } -#endif #pragma warning disable SA1132 private struct Byte8 diff --git a/tests/ImageSharp.Tests/Common/SimdUtilsTests.cs b/tests/ImageSharp.Tests/Common/SimdUtilsTests.cs index 028cc56cd..1ba3c64de 100644 --- a/tests/ImageSharp.Tests/Common/SimdUtilsTests.cs +++ b/tests/ImageSharp.Tests/Common/SimdUtilsTests.cs @@ -5,9 +5,7 @@ using System; using System.Linq; using System.Numerics; using System.Runtime.CompilerServices; -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.Intrinsics.X86; -#endif using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Tests.TestUtilities; using Xunit; @@ -43,7 +41,7 @@ namespace SixLabors.ImageSharp.Tests.Common private static Vector CreateExactTestVector1() { - var data = new float[Vector.Count]; + float[] data = new float[Vector.Count]; data[0] = 0.1f; data[1] = 0.4f; @@ -113,53 +111,6 @@ namespace SixLabors.ImageSharp.Tests.Common return false; } - [Theory] - [InlineData(1, 0)] - [InlineData(1, 8)] - [InlineData(2, 16)] - [InlineData(3, 128)] - public void BasicIntrinsics256_BulkConvertNormalizedFloatToByte_WithRoundedData(int seed, int count) - { - if (this.SkipOnNonAvx2()) - { - return; - } - - float[] orig = new Random(seed).GenerateRandomRoundedFloatArray(count, 0, 256); - float[] normalized = orig.Select(f => f / 255f).ToArray(); - - var dest = new byte[count]; - - SimdUtils.BasicIntrinsics256.BulkConvertNormalizedFloatToByte(normalized, dest); - - byte[] expected = orig.Select(f => (byte)f).ToArray(); - - Assert.Equal(expected, dest); - } - - [Theory] - [InlineData(1, 0)] - [InlineData(1, 8)] - [InlineData(2, 16)] - [InlineData(3, 128)] - public void BasicIntrinsics256_BulkConvertNormalizedFloatToByte_WithNonRoundedData(int seed, int count) - { - if (this.SkipOnNonAvx2()) - { - return; - } - - float[] source = new Random(seed).GenerateRandomFloatArray(count, 0, 1f); - - byte[] dest = new byte[count]; - - SimdUtils.BasicIntrinsics256.BulkConvertNormalizedFloatToByte(source, dest); - - byte[] expected = source.Select(f => (byte)Math.Round(f * 255f)).ToArray(); - - Assert.Equal(expected, dest); - } - public static readonly TheoryData ArraySizesDivisibleBy8 = new() { 0, 8, 16, 1024 }; public static readonly TheoryData ArraySizesDivisibleBy4 = new() { 0, 4, 8, 28, 1020 }; public static readonly TheoryData ArraySizesDivisibleBy3 = new() { 0, 3, 9, 36, 957 }; @@ -173,27 +124,12 @@ namespace SixLabors.ImageSharp.Tests.Common count, (s, d) => SimdUtils.FallbackIntrinsics128.ByteToNormalizedFloat(s.Span, d.Span)); - [Theory] - [MemberData(nameof(ArraySizesDivisibleBy8))] - public void BasicIntrinsics256_BulkConvertByteToNormalizedFloat(int count) - { - if (this.SkipOnNonAvx2()) - { - return; - } - - TestImpl_BulkConvertByteToNormalizedFloat( - count, - (s, d) => SimdUtils.BasicIntrinsics256.ByteToNormalizedFloat(s.Span, d.Span)); - } - [Theory] [MemberData(nameof(ArraySizesDivisibleBy32))] public void ExtendedIntrinsics_BulkConvertByteToNormalizedFloat(int count) => TestImpl_BulkConvertByteToNormalizedFloat( count, (s, d) => SimdUtils.ExtendedIntrinsics.ByteToNormalizedFloat(s.Span, d.Span)); -#if SUPPORTS_RUNTIME_INTRINSICS [Theory] [MemberData(nameof(ArraySizesDivisibleBy32))] public void HwIntrinsics_BulkConvertByteToNormalizedFloat(int count) @@ -212,7 +148,6 @@ namespace SixLabors.ImageSharp.Tests.Common count, HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX2 | HwIntrinsics.DisableSSE41); } -#endif [Theory] [MemberData(nameof(ArbitraryArraySizes))] @@ -239,18 +174,6 @@ namespace SixLabors.ImageSharp.Tests.Common count, (s, d) => SimdUtils.FallbackIntrinsics128.NormalizedFloatToByteSaturate(s.Span, d.Span)); - [Theory] - [MemberData(nameof(ArraySizesDivisibleBy8))] - public void BasicIntrinsics256_BulkConvertNormalizedFloatToByteClampOverflows(int count) - { - if (this.SkipOnNonAvx2()) - { - return; - } - - TestImpl_BulkConvertNormalizedFloatToByteClampOverflows(count, (s, d) => SimdUtils.BasicIntrinsics256.NormalizedFloatToByteSaturate(s.Span, d.Span)); - } - [Theory] [MemberData(nameof(ArraySizesDivisibleBy32))] public void ExtendedIntrinsics_BulkConvertNormalizedFloatToByteClampOverflows(int count) => TestImpl_BulkConvertNormalizedFloatToByteClampOverflows( @@ -278,8 +201,6 @@ namespace SixLabors.ImageSharp.Tests.Common Assert.Equal(expected2, actual2); } -#if SUPPORTS_RUNTIME_INTRINSICS - [Theory] [MemberData(nameof(ArraySizesDivisibleBy32))] public void HwIntrinsics_BulkConvertNormalizedFloatToByteClampOverflows(int count) @@ -299,8 +220,6 @@ namespace SixLabors.ImageSharp.Tests.Common HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX2); } -#endif - [Theory] [MemberData(nameof(ArbitraryArraySizes))] public void BulkConvertNormalizedFloatToByteClampOverflows(int count) @@ -325,16 +244,15 @@ namespace SixLabors.ImageSharp.Tests.Common public void PackFromRgbPlanes_Rgb24(int count) => TestPackFromRgbPlanes( count, (r, g, b, actual) => - SimdUtils.PackFromRgbPlanes(Configuration.Default, r, g, b, actual)); + SimdUtils.PackFromRgbPlanes(r, g, b, actual)); [Theory] [MemberData(nameof(ArbitraryArraySizes))] public void PackFromRgbPlanes_Rgba32(int count) => TestPackFromRgbPlanes( count, (r, g, b, actual) => - SimdUtils.PackFromRgbPlanes(Configuration.Default, r, g, b, actual)); + SimdUtils.PackFromRgbPlanes(r, g, b, actual)); -#if SUPPORTS_RUNTIME_INTRINSICS [Fact] public void PackFromRgbPlanesAvx2Reduce_Rgb24() { @@ -403,7 +321,6 @@ namespace SixLabors.ImageSharp.Tests.Common Assert.Equal(0, bb.Length); Assert.Equal(0, dd.Length); } -#endif internal static void TestPackFromRgbPlanes(int count, Action packMethod) where TPixel : unmanaged, IPixel @@ -422,7 +339,7 @@ namespace SixLabors.ImageSharp.Tests.Common var actual = new TPixel[count + 3]; // padding for Rgb24 AVX2 packMethod(r, g, b, actual); - Assert.True(expected.AsSpan().SequenceEqual(actual.AsSpan().Slice(0, count))); + Assert.True(expected.AsSpan().SequenceEqual(actual.AsSpan()[..count])); } private static void TestImpl_BulkConvertNormalizedFloatToByteClampOverflows( @@ -434,7 +351,7 @@ namespace SixLabors.ImageSharp.Tests.Common seed = seed > 0 ? seed : count; float[] source = new Random(seed).GenerateRandomFloatArray(count, -0.2f, 1.2f); byte[] expected = source.Select(NormalizedFloatToByte).ToArray(); - var actual = new byte[count]; + byte[] actual = new byte[count]; convert(source, actual); diff --git a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs index 28cf92d10..3d75d3448 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs @@ -4,9 +4,7 @@ // Uncomment this to turn unit tests into benchmarks: // #define BENCHMARKING using System; -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.Intrinsics.X86; -#endif using SixLabors.ImageSharp.Formats.Jpeg.Components; using SixLabors.ImageSharp.Tests.Formats.Jpg.Utils; using SixLabors.ImageSharp.Tests.TestUtilities; @@ -424,7 +422,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg static void RunTest(string serializedEqualsTo) { int equalsTo = FeatureTestRunner.Deserialize(serializedEqualsTo); - int offValue = 0; + const int offValue = 0; // Fill matrix with valid value Block8x8F block = default; diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs index ce8482b79..5e6b999f9 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs @@ -2,7 +2,6 @@ // Licensed under the Six Labors Split License. using System; -using System.Numerics; using SixLabors.ImageSharp.ColorSpaces; using SixLabors.ImageSharp.ColorSpaces.Conversion; using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder; @@ -24,11 +23,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg private const int TestBufferLength = 40; -#if SUPPORTS_RUNTIME_INTRINSICS - private static readonly HwIntrinsics IntrinsicsConfig = HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX; -#else - private static readonly HwIntrinsics IntrinsicsConfig = HwIntrinsics.AllowAll; -#endif + private const HwIntrinsics IntrinsicsConfig = HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX; private static readonly ApproximateColorSpaceComparer ColorSpaceComparer = new(epsilon: Precision); @@ -37,24 +32,19 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg public static readonly TheoryData Seeds = new() { 1, 2, 3 }; public JpegColorConverterTests(ITestOutputHelper output) - { - this.Output = output; - } + => this.Output = output; private ITestOutputHelper Output { get; } [Fact] public void GetConverterThrowsExceptionOnInvalidColorSpace() - { - Assert.Throws(() => JpegColorConverterBase.GetConverter(JpegColorSpace.Undefined, 8)); - } + => Assert.Throws(() => JpegColorConverterBase.GetConverter(JpegColorSpace.Undefined, 8)); [Fact] public void GetConverterThrowsExceptionOnInvalidPrecision() - { + // Valid precisions: 8 & 12 bit - Assert.Throws(() => JpegColorConverterBase.GetConverter(JpegColorSpace.YCbCr, 9)); - } + => Assert.Throws(() => JpegColorConverterBase.GetConverter(JpegColorSpace.YCbCr, 9)); [Theory] [InlineData(JpegColorSpace.Grayscale, 8)] @@ -242,7 +232,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg FeatureTestRunner.Deserialize(arg)); } -#if SUPPORTS_RUNTIME_INTRINSICS [Theory] [MemberData(nameof(Seeds))] public void FromYCbCrAvx2(int seed) => @@ -267,7 +256,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg [MemberData(nameof(Seeds))] public void FromYccKAvx2(int seed) => this.TestConverter(new JpegColorConverterBase.FromYccKAvx(8), 4, seed); -#endif private void TestConverter( JpegColorConverterBase converter, diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Internal.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Internal.cs index 6bf7ae88f..537545285 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Internal.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Internal.cs @@ -1,22 +1,10 @@ // Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. +// Licensed under the Six Labors Split License. using System; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; using SixLabors.ImageSharp.Formats.Jpeg; using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder; -using SixLabors.ImageSharp.IO; -using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Tests.Formats.Jpg.Utils; -using SixLabors.ImageSharp.Tests.TestUtilities; -using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; -using SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs; using Xunit; -using Xunit.Abstractions; // ReSharper disable InconsistentNaming namespace SixLabors.ImageSharp.Tests.Formats.Jpg diff --git a/tests/ImageSharp.Tests/Formats/Jpg/RgbToYCbCrConverterTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/RgbToYCbCrConverterTests.cs index 0f24e6c12..55b9dbb29 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/RgbToYCbCrConverterTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/RgbToYCbCrConverterTests.cs @@ -4,10 +4,8 @@ using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; -#endif using SixLabors.ImageSharp.ColorSpaces; using SixLabors.ImageSharp.Formats.Jpeg.Components; using SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder; @@ -22,16 +20,14 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg public class RgbToYCbCrConverterTests { public RgbToYCbCrConverterTests(ITestOutputHelper output) - { - this.Output = output; - } + => this.Output = output; private ITestOutputHelper Output { get; } [Fact] public void TestConverterLut444() { - int dataSize = 8 * 8; + const int dataSize = 8 * 8; Rgb24[] data = CreateTestData(dataSize); var target = RgbToYCbCrConverterLut.Create(); @@ -53,7 +49,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg return; } - int dataSize = 8 * 8; + const int dataSize = 8 * 8; Rgb24[] data = CreateTestData(dataSize); Block8x8F y = default; @@ -68,7 +64,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg [Fact] public void TestConverterLut420() { - int dataSize = 16 * 16; + const int dataSize = 16 * 16; Span data = CreateTestData(dataSize).AsSpan(); var target = RgbToYCbCrConverterLut.Create(); @@ -77,7 +73,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg var cr = default(Block8x8F); target.Convert420(data, ref yBlocks[0], ref yBlocks[1], ref cb, ref cr, 0); - target.Convert420(data.Slice(16 * 8), ref yBlocks[2], ref yBlocks[3], ref cb, ref cr, 1); + target.Convert420(data[(16 * 8)..], ref yBlocks[2], ref yBlocks[3], ref cb, ref cr, 1); Verify420(data, yBlocks, ref cb, ref cr, new ApproximateFloatComparer(1F)); } @@ -91,7 +87,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg return; } - int dataSize = 16 * 16; + const int dataSize = 16 * 16; Span data = CreateTestData(dataSize).AsSpan(); var yBlocks = new Block8x8F[4]; @@ -99,12 +95,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg var cr = default(Block8x8F); RgbToYCbCrConverterVectorized.Convert420(data, ref yBlocks[0], ref yBlocks[1], ref cb, ref cr, 0); - RgbToYCbCrConverterVectorized.Convert420(data.Slice(16 * 8), ref yBlocks[2], ref yBlocks[3], ref cb, ref cr, 1); + RgbToYCbCrConverterVectorized.Convert420(data[(16 * 8)..], ref yBlocks[2], ref yBlocks[3], ref cb, ref cr, 1); Verify420(data, yBlocks, ref cb, ref cr, new ApproximateFloatComparer(1F)); } -#if SUPPORTS_RUNTIME_INTRINSICS [Theory] [InlineData(1)] [InlineData(2)] @@ -140,7 +135,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg return 0.25f * (data[upIdx] + data[upIdx + 1] + data[lowIdx] + data[lowIdx + 1]); } } -#endif private static void Verify444( ReadOnlySpan data, @@ -180,17 +174,17 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg VerifyBlock(ref yResult[0], ref trueBlock, comparer); // top right - Copy8x8(data.Slice(8), tempData); + Copy8x8(data[8..], tempData); RgbToYCbCr(tempData, ref trueBlock, ref cbTrue[1], ref crTrue[1]); VerifyBlock(ref yResult[1], ref trueBlock, comparer); // bottom left - Copy8x8(data.Slice(8 * 16), tempData); + Copy8x8(data[(8 * 16)..], tempData); RgbToYCbCr(tempData, ref trueBlock, ref cbTrue[2], ref crTrue[2]); VerifyBlock(ref yResult[2], ref trueBlock, comparer); // bottom right - Copy8x8(data.Slice((8 * 16) + 8), tempData); + Copy8x8(data[((8 * 16) + 8)..], tempData); RgbToYCbCr(tempData, ref trueBlock, ref cbTrue[3], ref crTrue[3]); VerifyBlock(ref yResult[3], ref trueBlock, comparer); @@ -207,7 +201,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg { for (int i = 0; i < 8; i++) { - source.Slice(i * 16, 8).CopyTo(dest.Slice(i * 8)); + source.Slice(i * 16, 8).CopyTo(dest[(i * 8)..]); } } @@ -259,7 +253,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg var data = new Rgb24[size]; var r = new Random(); - var random = new byte[3]; + byte[] random = new byte[3]; for (int i = 0; i < data.Length; i++) { r.NextBytes(random); diff --git a/tests/ImageSharp.Tests/Formats/Png/Adler32Tests.cs b/tests/ImageSharp.Tests/Formats/Png/Adler32Tests.cs index 0c91c9098..9e13edeba 100644 --- a/tests/ImageSharp.Tests/Formats/Png/Adler32Tests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/Adler32Tests.cs @@ -51,7 +51,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png return data; } -#if SUPPORTS_RUNTIME_INTRINSICS [Fact] public void RunCalculateAdlerTest_WithHardwareIntrinsics_Works() => FeatureTestRunner.RunWithHwIntrinsicsFeature(RunCalculateAdlerTest, HwIntrinsics.AllowAll); @@ -69,6 +68,5 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png CalculateAdlerAndCompareToReference(testData[i]); } } -#endif } } diff --git a/tests/ImageSharp.Tests/Formats/Png/PngDecoderFilterTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngDecoderFilterTests.cs index a0f93ba29..df364ee50 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngDecoderFilterTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngDecoderFilterTests.cs @@ -147,7 +147,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png [Fact] public void PaethFilter_Works() => RunPaethFilterTest(); -#if SUPPORTS_RUNTIME_INTRINSICS [Fact] public void AverageFilter_WithHardwareIntrinsics_Works() => FeatureTestRunner.RunWithHwIntrinsicsFeature(RunAverageFilterTest, HwIntrinsics.AllowAll); @@ -174,6 +173,5 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png [Fact] public void PaethFilter_WithoutHardwareIntrinsics_Works() => FeatureTestRunner.RunWithHwIntrinsicsFeature(RunPaethFilterTest, HwIntrinsics.DisableHWIntrinsic); -#endif } } diff --git a/tests/ImageSharp.Tests/Formats/Tiff/PhotometricInterpretation/BlackIsZeroTiffColorTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/PhotometricInterpretation/BlackIsZeroTiffColorTests.cs index 9e1004cec..c9854c022 100644 --- a/tests/ImageSharp.Tests/Formats/Tiff/PhotometricInterpretation/BlackIsZeroTiffColorTests.cs +++ b/tests/ImageSharp.Tests/Formats/Tiff/PhotometricInterpretation/BlackIsZeroTiffColorTests.cs @@ -30,7 +30,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff.PhotometricInterpretation 0b10010000 }; - private static readonly Rgba32[][] BilevelResult4X4 = { + private static readonly Rgba32[][] BilevelResult4X4 = + { new[] { Bit0, Bit1, Bit0, Bit1 }, new[] { Bit1, Bit1, Bit1, Bit1 }, new[] { Bit0, Bit1, Bit1, Bit1 }, @@ -154,41 +155,25 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff.PhotometricInterpretation [MemberData(nameof(Grayscale4_Data))] [MemberData(nameof(Grayscale8_Data))] public void Decode_WritesPixelData(byte[] inputData, ushort bitsPerSample, int left, int top, int width, int height, Rgba32[][] expectedResult) - { - AssertDecode(expectedResult, pixels => - { - new BlackIsZeroTiffColor(new TiffBitsPerSample(bitsPerSample, 0, 0)).Decode(inputData, pixels, left, top, width, height); - }); - } + => AssertDecode( + expectedResult, + pixels => new BlackIsZeroTiffColor(new TiffBitsPerSample(bitsPerSample, 0, 0)).Decode(inputData, pixels, left, top, width, height)); [Theory] [MemberData(nameof(BilevelData))] public void Decode_WritesPixelData_Bilevel(byte[] inputData, int bitsPerSample, int left, int top, int width, int height, Rgba32[][] expectedResult) - { - AssertDecode(expectedResult, pixels => - { - new BlackIsZero1TiffColor().Decode(inputData, pixels, left, top, width, height); - }); - } + => AssertDecode(expectedResult, pixels => new BlackIsZero1TiffColor().Decode(inputData, pixels, left, top, width, height)); [Theory] [MemberData(nameof(Grayscale4_Data))] public void Decode_WritesPixelData_4Bit(byte[] inputData, int bitsPerSample, int left, int top, int width, int height, Rgba32[][] expectedResult) - { - AssertDecode(expectedResult, pixels => - { - new BlackIsZero4TiffColor().Decode(inputData, pixels, left, top, width, height); - }); - } + => AssertDecode( + expectedResult, + pixels => new BlackIsZero4TiffColor().Decode(inputData, pixels, left, top, width, height)); [Theory] [MemberData(nameof(Grayscale8_Data))] public void Decode_WritesPixelData_8Bit(byte[] inputData, int bitsPerSample, int left, int top, int width, int height, Rgba32[][] expectedResult) - { - AssertDecode(expectedResult, pixels => - { - new BlackIsZero8TiffColor(Configuration.Default).Decode(inputData, pixels, left, top, width, height); - }); - } + => AssertDecode(expectedResult, pixels => new BlackIsZero8TiffColor(Configuration.Default).Decode(inputData, pixels, left, top, width, height)); } } diff --git a/tests/ImageSharp.Tests/Formats/WebP/ColorSpaceTransformUtilsTests.cs b/tests/ImageSharp.Tests/Formats/WebP/ColorSpaceTransformUtilsTests.cs index c06936c09..013674cfe 100644 --- a/tests/ImageSharp.Tests/Formats/WebP/ColorSpaceTransformUtilsTests.cs +++ b/tests/ImageSharp.Tests/Formats/WebP/ColorSpaceTransformUtilsTests.cs @@ -68,7 +68,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp [Fact] public void CollectColorRedTransforms_Works() => RunCollectColorRedTransformsTest(); -#if SUPPORTS_RUNTIME_INTRINSICS [Fact] public void CollectColorBlueTransforms_WithHardwareIntrinsics_Works() => FeatureTestRunner.RunWithHwIntrinsicsFeature(RunCollectColorBlueTransformsTest, HwIntrinsics.AllowAll); @@ -86,7 +85,5 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp [Fact] public void CollectColorRedTransforms_WithoutAvx2_Works() => FeatureTestRunner.RunWithHwIntrinsicsFeature(RunCollectColorRedTransformsTest, HwIntrinsics.DisableAVX2); -#endif - } } diff --git a/tests/ImageSharp.Tests/Formats/WebP/LosslessUtilsTests.cs b/tests/ImageSharp.Tests/Formats/WebP/LosslessUtilsTests.cs index c9c3ba5de..eb7b4dc64 100644 --- a/tests/ImageSharp.Tests/Formats/WebP/LosslessUtilsTests.cs +++ b/tests/ImageSharp.Tests/Formats/WebP/LosslessUtilsTests.cs @@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp { int[] x = { 3, 5, 2, 5, 3, 1, 2, 2, 3, 3, 1, 2, 1, 2, 1, 1, 0, 0, 0, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 1, 1, 0, 0, 2, 1, 1, 0, 3, 1, 2, 3, 2, 3 }; int[] y = { 11, 12, 8, 3, 4, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 2, 1, 1, 2, 4, 6, 4 }; - float expected = 884.7585f; + const float expected = 884.7585f; float actual = LosslessUtils.CombinedShannonEntropy(x, y); @@ -147,9 +147,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp { // arrange uint[] topData = { 4278258949, 4278258949 }; - uint left = 4294839812; + const uint left = 4294839812; short[] scratch = new short[8]; - uint expectedResult = 4294839812; + const uint expectedResult = 4294839812; // act unsafe @@ -168,8 +168,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp { // arrange uint[] topData = { 4294844413, 4294779388 }; - uint left = 4294844413; - uint expectedResult = 4294779388; + const uint left = 4294844413; + const uint expectedResult = 4294779388; // act unsafe @@ -188,8 +188,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp { // arrange uint[] topData = { 4278193922, 4278193666 }; - uint left = 4278193410; - uint expectedResult = 4278193154; + const uint left = 4278193410; + const uint expectedResult = 4278193154; // act unsafe @@ -228,7 +228,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp [Fact] public void TransformColorInverse_Works() => RunTransformColorInverseTest(); -#if SUPPORTS_RUNTIME_INTRINSICS [Fact] public void CombinedShannonEntropy_WithHardwareIntrinsics_Works() => FeatureTestRunner.RunWithHwIntrinsicsFeature(RunCombinedShannonEntropyTest, HwIntrinsics.AllowAll); @@ -288,6 +287,5 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp [Fact] public void TransformColorInverse_WithoutAVX2_Works() => FeatureTestRunner.RunWithHwIntrinsicsFeature(RunTransformColorInverseTest, HwIntrinsics.DisableAVX2); -#endif } } diff --git a/tests/ImageSharp.Tests/Formats/WebP/LossyUtilsTests.cs b/tests/ImageSharp.Tests/Formats/WebP/LossyUtilsTests.cs index 9248f37c6..419d6e266 100644 --- a/tests/ImageSharp.Tests/Formats/WebP/LossyUtilsTests.cs +++ b/tests/ImageSharp.Tests/Formats/WebP/LossyUtilsTests.cs @@ -301,7 +301,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp [Fact] public void HadamardTransform_Works() => RunHadamardTransformTest(); -#if SUPPORTS_RUNTIME_INTRINSICS [Fact] public void TransformTwo_WithHardwareIntrinsics_Works() => FeatureTestRunner.RunWithHwIntrinsicsFeature(RunTransformTwoTest, HwIntrinsics.AllowAll); @@ -352,6 +351,5 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp [Fact] public void HadamardTransform_WithoutHardwareIntrinsics_Works() => FeatureTestRunner.RunWithHwIntrinsicsFeature(RunHadamardTransformTest, HwIntrinsics.DisableHWIntrinsic); -#endif } } diff --git a/tests/ImageSharp.Tests/Formats/WebP/PredictorEncoderTests.cs b/tests/ImageSharp.Tests/Formats/WebP/PredictorEncoderTests.cs index f9b949e21..a9427b5ef 100644 --- a/tests/ImageSharp.Tests/Formats/WebP/PredictorEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/WebP/PredictorEncoderTests.cs @@ -6,9 +6,7 @@ using System.IO; using SixLabors.ImageSharp.Formats.Webp; using SixLabors.ImageSharp.Formats.Webp.Lossless; using SixLabors.ImageSharp.PixelFormats; -#if SUPPORTS_RUNTIME_INTRINSICS using SixLabors.ImageSharp.Tests.TestUtilities; -#endif using Xunit; namespace SixLabors.ImageSharp.Tests.Formats.Webp @@ -24,7 +22,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp public static void ColorSpaceTransform_WithPeakImage_ProducesExpectedData() => RunColorSpaceTransformTestWithPeakImage(); -#if SUPPORTS_RUNTIME_INTRINSICS [Fact] public void ColorSpaceTransform_WithPeakImage_WithHardwareIntrinsics_Works() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ColorSpaceTransform_WithPeakImage_ProducesExpectedData, HwIntrinsics.AllowAll); @@ -44,7 +41,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp [Fact] public void ColorSpaceTransform_WithBikeImage_WithoutAvx2_Works() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ColorSpaceTransform_WithBikeImage_ProducesExpectedData, HwIntrinsics.DisableAVX2); -#endif // Test image: Input\Webp\peak.png private static void RunColorSpaceTransformTestWithPeakImage() @@ -91,7 +87,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp using var image = Image.Load(imgBytes); uint[] bgra = ToBgra(image); - int colorTransformBits = 3; + const int colorTransformBits = 3; int transformWidth = LosslessUtils.SubSampleSize(image.Width, colorTransformBits); int transformHeight = LosslessUtils.SubSampleSize(image.Height, colorTransformBits); uint[] transformData = new uint[transformWidth * transformHeight]; @@ -122,7 +118,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp using var image = Image.Load(imgBytes, new WebpDecoder()); uint[] bgra = ToBgra(image); - int colorTransformBits = 4; + const int colorTransformBits = 4; int transformWidth = LosslessUtils.SubSampleSize(image.Width, colorTransformBits); int transformHeight = LosslessUtils.SubSampleSize(image.Height, colorTransformBits); uint[] transformData = new uint[transformWidth * transformHeight]; diff --git a/tests/ImageSharp.Tests/Formats/WebP/QuantEncTests.cs b/tests/ImageSharp.Tests/Formats/WebP/QuantEncTests.cs index 86f22d67a..0e4630fdb 100644 --- a/tests/ImageSharp.Tests/Formats/WebP/QuantEncTests.cs +++ b/tests/ImageSharp.Tests/Formats/WebP/QuantEncTests.cs @@ -42,7 +42,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp [Fact] public void QuantizeBlock_Works() => RunQuantizeBlockTest(); -#if SUPPORTS_RUNTIME_INTRINSICS [Fact] public void QuantizeBlock_WithHardwareIntrinsics_Works() => FeatureTestRunner.RunWithHwIntrinsicsFeature(RunQuantizeBlockTest, HwIntrinsics.AllowAll); @@ -51,6 +50,5 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp [Fact] public void QuantizeBlock_WithoutAVX2_Works() => FeatureTestRunner.RunWithHwIntrinsicsFeature(RunQuantizeBlockTest, HwIntrinsics.DisableAVX2); -#endif } } diff --git a/tests/ImageSharp.Tests/Formats/WebP/Vp8EncodingTests.cs b/tests/ImageSharp.Tests/Formats/WebP/Vp8EncodingTests.cs index d8b4acaa1..2923d1aaa 100644 --- a/tests/ImageSharp.Tests/Formats/WebP/Vp8EncodingTests.cs +++ b/tests/ImageSharp.Tests/Formats/WebP/Vp8EncodingTests.cs @@ -138,7 +138,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp [Fact] public void TwoInverseTransform_Works() => RunTwoInverseTransformTest(); -#if SUPPORTS_RUNTIME_INTRINSICS [Fact] public void FTransform2_WithHardwareIntrinsics_Works() => FeatureTestRunner.RunWithHwIntrinsicsFeature(RunFTransform2Test, HwIntrinsics.AllowAll); @@ -162,6 +161,5 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp [Fact] public void TwoInverseTransform_WithoutHardwareIntrinsics_Works() => FeatureTestRunner.RunWithHwIntrinsicsFeature(RunTwoInverseTransformTest, HwIntrinsics.DisableHWIntrinsic); -#endif } } diff --git a/tests/ImageSharp.Tests/Formats/WebP/Vp8HistogramTests.cs b/tests/ImageSharp.Tests/Formats/WebP/Vp8HistogramTests.cs index 3d8a8dabd..053f8304d 100644 --- a/tests/ImageSharp.Tests/Formats/WebP/Vp8HistogramTests.cs +++ b/tests/ImageSharp.Tests/Formats/WebP/Vp8HistogramTests.cs @@ -215,12 +215,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp Assert.Equal(1054, alpha); } -#if SUPPORTS_RUNTIME_INTRINSICS [Fact] public void CollectHistogramTest_WithHardwareIntrinsics_Works() => FeatureTestRunner.RunWithHwIntrinsicsFeature(RunCollectHistogramTest, HwIntrinsics.AllowAll); [Fact] public void CollectHistogramTest_WithoutHardwareIntrinsics_Works() => FeatureTestRunner.RunWithHwIntrinsicsFeature(RunCollectHistogramTest, HwIntrinsics.DisableHWIntrinsic); -#endif } } diff --git a/tests/ImageSharp.Tests/Formats/WebP/Vp8LHistogramTests.cs b/tests/ImageSharp.Tests/Formats/WebP/Vp8LHistogramTests.cs index 8f56d831f..4aa3c1a5b 100644 --- a/tests/ImageSharp.Tests/Formats/WebP/Vp8LHistogramTests.cs +++ b/tests/ImageSharp.Tests/Formats/WebP/Vp8LHistogramTests.cs @@ -99,12 +99,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp [Fact] public void AddVector_Works() => RunAddVectorTest(); -#if SUPPORTS_RUNTIME_INTRINSICS [Fact] public void AddVector_WithHardwareIntrinsics_Works() => FeatureTestRunner.RunWithHwIntrinsicsFeature(RunAddVectorTest, HwIntrinsics.AllowAll); [Fact] public void AddVector_WithoutAVX2_Works() => FeatureTestRunner.RunWithHwIntrinsicsFeature(RunAddVectorTest, HwIntrinsics.DisableAVX2); -#endif } } diff --git a/tests/ImageSharp.Tests/Formats/WebP/Vp8ResidualTests.cs b/tests/ImageSharp.Tests/Formats/WebP/Vp8ResidualTests.cs index 976dc0cb3..5819320e8 100644 --- a/tests/ImageSharp.Tests/Formats/WebP/Vp8ResidualTests.cs +++ b/tests/ImageSharp.Tests/Formats/WebP/Vp8ResidualTests.cs @@ -26,12 +26,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp [Fact] public void RunSetCoeffsTest_Works() => RunSetCoeffsTest(); -#if SUPPORTS_RUNTIME_INTRINSICS [Fact] public void RunSetCoeffsTest_WithHardwareIntrinsics_Works() => FeatureTestRunner.RunWithHwIntrinsicsFeature(RunSetCoeffsTest, HwIntrinsics.AllowAll); [Fact] public void RunSetCoeffsTest_WithoutHardwareIntrinsics_Works() => FeatureTestRunner.RunWithHwIntrinsicsFeature(RunSetCoeffsTest, HwIntrinsics.DisableHWIntrinsic); -#endif } } diff --git a/tests/ImageSharp.Tests/Formats/WebP/WebpCommonUtilsTests.cs b/tests/ImageSharp.Tests/Formats/WebP/WebpCommonUtilsTests.cs index b197d0105..1346964ec 100644 --- a/tests/ImageSharp.Tests/Formats/WebP/WebpCommonUtilsTests.cs +++ b/tests/ImageSharp.Tests/Formats/WebP/WebpCommonUtilsTests.cs @@ -5,10 +5,8 @@ using System; using System.Runtime.InteropServices; using SixLabors.ImageSharp.Formats.Webp; using SixLabors.ImageSharp.PixelFormats; -using Xunit; -#if SUPPORTS_RUNTIME_INTRINSICS using SixLabors.ImageSharp.Tests.TestUtilities; -#endif +using Xunit; namespace SixLabors.ImageSharp.Tests.Formats.Webp { @@ -21,7 +19,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp [Fact] public void CheckNonOpaque_WithNoneOpaquePixels_Works() => RunCheckNoneOpaqueWithNoneOpaquePixelsTest(); -#if SUPPORTS_RUNTIME_INTRINSICS [Fact] public void CheckNonOpaque_WithOpaquePixels_WithHardwareIntrinsics_Works() => FeatureTestRunner.RunWithHwIntrinsicsFeature(RunCheckNoneOpaqueWithOpaquePixelsTest, HwIntrinsics.AllowAll); @@ -45,7 +42,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp [Fact] public void CheckNonOpaque_WithNoneOpaquePixels_WithoutAvx2_Works() => FeatureTestRunner.RunWithHwIntrinsicsFeature(RunCheckNoneOpaqueWithNoneOpaquePixelsTest, HwIntrinsics.DisableAVX2); -#endif private static void RunCheckNoneOpaqueWithNoneOpaquePixelsTest() { @@ -200,7 +196,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp for (int length = 8; length < row.Length; length += 8) { // act - noneOpaque = WebpCommonUtils.CheckNonOpaque(row.Slice(0, length)); + noneOpaque = WebpCommonUtils.CheckNonOpaque(row[..length]); // assert Assert.False(noneOpaque); diff --git a/tests/ImageSharp.Tests/Formats/WebP/WebpDecoderTests.cs b/tests/ImageSharp.Tests/Formats/WebP/WebpDecoderTests.cs index fe5520cc6..ca091bc4a 100644 --- a/tests/ImageSharp.Tests/Formats/WebP/WebpDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/WebP/WebpDecoderTests.cs @@ -44,14 +44,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp int expectedBitsPerPixel) { var testFile = TestFile.Create(imagePath); - using (var stream = new MemoryStream(testFile.Bytes, false)) - { - IImageInfo imageInfo = Image.Identify(stream); - Assert.NotNull(imageInfo); - Assert.Equal(expectedWidth, imageInfo.Width); - Assert.Equal(expectedHeight, imageInfo.Height); - Assert.Equal(expectedBitsPerPixel, imageInfo.PixelType.BitsPerPixel); - } + using var stream = new MemoryStream(testFile.Bytes, false); + IImageInfo imageInfo = Image.Identify(stream); + Assert.NotNull(imageInfo); + Assert.Equal(expectedWidth, imageInfo.Width); + Assert.Equal(expectedHeight, imageInfo.Height); + Assert.Equal(expectedBitsPerPixel, imageInfo.PixelType.BitsPerPixel); } [Theory] @@ -67,11 +65,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp public void WebpDecoder_CanDecode_Lossy_WithoutFilter(TestImageProvider provider) where TPixel : unmanaged, IPixel { - using (Image image = provider.GetImage(WebpDecoder)) - { - image.DebugSave(provider); - image.CompareToOriginal(provider, ReferenceDecoder); - } + using Image image = provider.GetImage(WebpDecoder); + image.DebugSave(provider); + image.CompareToOriginal(provider, ReferenceDecoder); } [Theory] @@ -83,11 +79,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp public void WebpDecoder_CanDecode_Lossy_WithSimpleFilter(TestImageProvider provider) where TPixel : unmanaged, IPixel { - using (Image image = provider.GetImage(WebpDecoder)) - { - image.DebugSave(provider); - image.CompareToOriginal(provider, ReferenceDecoder); - } + using Image image = provider.GetImage(WebpDecoder); + image.DebugSave(provider); + image.CompareToOriginal(provider, ReferenceDecoder); } [Theory] @@ -106,11 +100,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp public void WebpDecoder_CanDecode_Lossy_WithComplexFilter(TestImageProvider provider) where TPixel : unmanaged, IPixel { - using (Image image = provider.GetImage(WebpDecoder)) - { - image.DebugSave(provider); - image.CompareToOriginal(provider, ReferenceDecoder); - } + using Image image = provider.GetImage(WebpDecoder); + image.DebugSave(provider); + image.CompareToOriginal(provider, ReferenceDecoder); } [Theory] @@ -121,11 +113,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp public void WebpDecoder_CanDecode_Lossy_VerySmall(TestImageProvider provider) where TPixel : unmanaged, IPixel { - using (Image image = provider.GetImage(WebpDecoder)) - { - image.DebugSave(provider); - image.CompareToOriginal(provider, ReferenceDecoder); - } + using Image image = provider.GetImage(WebpDecoder); + image.DebugSave(provider); + image.CompareToOriginal(provider, ReferenceDecoder); } [Theory] @@ -140,11 +130,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp public void WebpDecoder_CanDecode_Lossy_WithPartitions(TestImageProvider provider) where TPixel : unmanaged, IPixel { - using (Image image = provider.GetImage(WebpDecoder)) - { - image.DebugSave(provider); - image.CompareToOriginal(provider, ReferenceDecoder); - } + using Image image = provider.GetImage(WebpDecoder); + image.DebugSave(provider); + image.CompareToOriginal(provider, ReferenceDecoder); } [Theory] @@ -154,11 +142,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp public void WebpDecoder_CanDecode_Lossy_WithSegmentation(TestImageProvider provider) where TPixel : unmanaged, IPixel { - using (Image image = provider.GetImage(WebpDecoder)) - { - image.DebugSave(provider); - image.CompareToOriginal(provider, ReferenceDecoder); - } + using Image image = provider.GetImage(WebpDecoder); + image.DebugSave(provider); + image.CompareToOriginal(provider, ReferenceDecoder); } [Theory] @@ -171,11 +157,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp public void WebpDecoder_CanDecode_Lossy_WithSharpnessLevel(TestImageProvider provider) where TPixel : unmanaged, IPixel { - using (Image image = provider.GetImage(WebpDecoder)) - { - image.DebugSave(provider); - image.CompareToOriginal(provider, ReferenceDecoder); - } + using Image image = provider.GetImage(WebpDecoder); + image.DebugSave(provider); + image.CompareToOriginal(provider, ReferenceDecoder); } [Theory] @@ -196,11 +180,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp public void WebpDecoder_CanDecode_Lossy_WithAlpha(TestImageProvider provider) where TPixel : unmanaged, IPixel { - using (Image image = provider.GetImage(WebpDecoder)) - { - image.DebugSave(provider); - image.CompareToOriginal(provider, ReferenceDecoder); - } + using Image image = provider.GetImage(WebpDecoder); + image.DebugSave(provider); + image.CompareToOriginal(provider, ReferenceDecoder); } [Theory] @@ -208,11 +190,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp public void WebpDecoder_CanDecode_Lossless_WithAlpha(TestImageProvider provider) where TPixel : unmanaged, IPixel { - using (Image image = provider.GetImage(WebpDecoder)) - { - image.DebugSave(provider); - image.CompareToOriginal(provider, ReferenceDecoder); - } + using Image image = provider.GetImage(WebpDecoder); + image.DebugSave(provider); + image.CompareToOriginal(provider, ReferenceDecoder); } [Theory] @@ -221,11 +201,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp public void WebpDecoder_CanDecode_Lossless_WithoutTransforms(TestImageProvider provider) where TPixel : unmanaged, IPixel { - using (Image image = provider.GetImage(WebpDecoder)) - { - image.DebugSave(provider); - image.CompareToOriginal(provider, ReferenceDecoder); - } + using Image image = provider.GetImage(WebpDecoder); + image.DebugSave(provider); + image.CompareToOriginal(provider, ReferenceDecoder); } [Theory] @@ -240,11 +218,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp TestImageProvider provider) where TPixel : unmanaged, IPixel { - using (Image image = provider.GetImage(WebpDecoder)) - { - image.DebugSave(provider); - image.CompareToOriginal(provider, ReferenceDecoder); - } + using Image image = provider.GetImage(WebpDecoder); + image.DebugSave(provider); + image.CompareToOriginal(provider, ReferenceDecoder); } [Theory] @@ -256,11 +232,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp public void WebpDecoder_CanDecode_Lossless_WithColorIndexTransform(TestImageProvider provider) where TPixel : unmanaged, IPixel { - using (Image image = provider.GetImage(WebpDecoder)) - { - image.DebugSave(provider); - image.CompareToOriginal(provider, ReferenceDecoder); - } + using Image image = provider.GetImage(WebpDecoder); + image.DebugSave(provider); + image.CompareToOriginal(provider, ReferenceDecoder); } [Theory] @@ -269,11 +243,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp public void WebpDecoder_CanDecode_Lossless_WithPredictorTransform(TestImageProvider provider) where TPixel : unmanaged, IPixel { - using (Image image = provider.GetImage(WebpDecoder)) - { - image.DebugSave(provider); - image.CompareToOriginal(provider, ReferenceDecoder); - } + using Image image = provider.GetImage(WebpDecoder); + image.DebugSave(provider); + image.CompareToOriginal(provider, ReferenceDecoder); } [Theory] @@ -282,11 +254,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp public void WebpDecoder_CanDecode_Lossless_WithCrossColorTransform(TestImageProvider provider) where TPixel : unmanaged, IPixel { - using (Image image = provider.GetImage(WebpDecoder)) - { - image.DebugSave(provider); - image.CompareToOriginal(provider, ReferenceDecoder); - } + using Image image = provider.GetImage(WebpDecoder); + image.DebugSave(provider); + image.CompareToOriginal(provider, ReferenceDecoder); } [Theory] @@ -306,11 +276,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp public void WebpDecoder_CanDecode_Lossless_WithTwoTransforms(TestImageProvider provider) where TPixel : unmanaged, IPixel { - using (Image image = provider.GetImage(WebpDecoder)) - { - image.DebugSave(provider); - image.CompareToOriginal(provider, ReferenceDecoder); - } + using Image image = provider.GetImage(WebpDecoder); + image.DebugSave(provider); + image.CompareToOriginal(provider, ReferenceDecoder); } [Theory] @@ -325,11 +293,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp public void WebpDecoder_CanDecode_Lossless_WithThreeTransforms(TestImageProvider provider) where TPixel : unmanaged, IPixel { - using (Image image = provider.GetImage(WebpDecoder)) - { - image.DebugSave(provider); - image.CompareToOriginal(provider, ReferenceDecoder); - } + using Image image = provider.GetImage(WebpDecoder); + image.DebugSave(provider); + image.CompareToOriginal(provider, ReferenceDecoder); } [Theory] @@ -337,18 +303,16 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp public void Decode_AnimatedLossless_VerifyAllFrames(TestImageProvider provider) where TPixel : unmanaged, IPixel { - using (Image image = provider.GetImage(WebpDecoder)) - { - WebpMetadata webpMetaData = image.Metadata.GetWebpMetadata(); - WebpFrameMetadata frameMetaData = image.Frames.RootFrame.Metadata.GetWebpMetadata(); - - image.DebugSaveMultiFrame(provider); - image.CompareToReferenceOutputMultiFrame(provider, ImageComparer.Exact); - - Assert.Equal(0, webpMetaData.AnimationLoopCount); - Assert.Equal(150U, frameMetaData.FrameDuration); - Assert.Equal(12, image.Frames.Count); - } + using Image image = provider.GetImage(WebpDecoder); + WebpMetadata webpMetaData = image.Metadata.GetWebpMetadata(); + WebpFrameMetadata frameMetaData = image.Frames.RootFrame.Metadata.GetWebpMetadata(); + + image.DebugSaveMultiFrame(provider); + image.CompareToReferenceOutputMultiFrame(provider, ImageComparer.Exact); + + Assert.Equal(0, webpMetaData.AnimationLoopCount); + Assert.Equal(150U, frameMetaData.FrameDuration); + Assert.Equal(12, image.Frames.Count); } [Theory] @@ -356,18 +320,16 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp public void Decode_AnimatedLossy_VerifyAllFrames(TestImageProvider provider) where TPixel : unmanaged, IPixel { - using (Image image = provider.GetImage(WebpDecoder)) - { - WebpMetadata webpMetaData = image.Metadata.GetWebpMetadata(); - WebpFrameMetadata frameMetaData = image.Frames.RootFrame.Metadata.GetWebpMetadata(); - - image.DebugSaveMultiFrame(provider); - image.CompareToReferenceOutputMultiFrame(provider, ImageComparer.Tolerant(0.04f)); - - Assert.Equal(0, webpMetaData.AnimationLoopCount); - Assert.Equal(150U, frameMetaData.FrameDuration); - Assert.Equal(12, image.Frames.Count); - } + using Image image = provider.GetImage(WebpDecoder); + WebpMetadata webpMetaData = image.Metadata.GetWebpMetadata(); + WebpFrameMetadata frameMetaData = image.Frames.RootFrame.Metadata.GetWebpMetadata(); + + image.DebugSaveMultiFrame(provider); + image.CompareToReferenceOutputMultiFrame(provider, ImageComparer.Tolerant(0.04f)); + + Assert.Equal(0, webpMetaData.AnimationLoopCount); + Assert.Equal(150U, frameMetaData.FrameDuration); + Assert.Equal(12, image.Frames.Count); } [Theory] @@ -375,10 +337,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp public void Decode_AnimatedLossless_WithFrameDecodingModeFirst_OnlyDecodesOneFrame(TestImageProvider provider) where TPixel : unmanaged, IPixel { - using (Image image = provider.GetImage(new WebpDecoder() { DecodingMode = FrameDecodingMode.First })) - { - Assert.Equal(1, image.Frames.Count); - } + using Image image = provider.GetImage(new WebpDecoder() { DecodingMode = FrameDecodingMode.First }); + Assert.Equal(1, image.Frames.Count); } [Theory] @@ -389,10 +349,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp where TPixel : unmanaged, IPixel { // Just make sure no exception is thrown. The reference decoder fails to load the image. - using (Image image = provider.GetImage(WebpDecoder)) - { - image.DebugSave(provider); - } + using Image image = provider.GetImage(WebpDecoder); + image.DebugSave(provider); } // https://github.com/SixLabors/ImageSharp/issues/1594 @@ -401,11 +359,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp public void WebpDecoder_CanDecode_Issue1594(TestImageProvider provider) where TPixel : unmanaged, IPixel { - using (Image image = provider.GetImage(WebpDecoder)) - { - image.DebugSave(provider); - image.CompareToOriginal(provider, ReferenceDecoder); - } + using Image image = provider.GetImage(WebpDecoder); + image.DebugSave(provider); + image.CompareToOriginal(provider, ReferenceDecoder); } [Theory] @@ -420,45 +376,36 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp } }); -#if SUPPORTS_RUNTIME_INTRINSICS private static void RunDecodeLossyWithHorizontalFilter() { var provider = TestImageProvider.File(TestImageLossyHorizontalFilterPath); - using (Image image = provider.GetImage(WebpDecoder)) - { - image.DebugSave(provider); - image.CompareToOriginal(provider, ReferenceDecoder); - } + using Image image = provider.GetImage(WebpDecoder); + image.DebugSave(provider); + image.CompareToOriginal(provider, ReferenceDecoder); } private static void RunDecodeLossyWithVerticalFilter() { var provider = TestImageProvider.File(TestImageLossyVerticalFilterPath); - using (Image image = provider.GetImage(WebpDecoder)) - { - image.DebugSave(provider); - image.CompareToOriginal(provider, ReferenceDecoder); - } + using Image image = provider.GetImage(WebpDecoder); + image.DebugSave(provider); + image.CompareToOriginal(provider, ReferenceDecoder); } private static void RunDecodeLossyWithSimpleFilterTest() { var provider = TestImageProvider.File(TestImageLossySimpleFilterPath); - using (Image image = provider.GetImage(WebpDecoder)) - { - image.DebugSave(provider); - image.CompareToOriginal(provider, ReferenceDecoder); - } + using Image image = provider.GetImage(WebpDecoder); + image.DebugSave(provider); + image.CompareToOriginal(provider, ReferenceDecoder); } private static void RunDecodeLossyWithComplexFilterTest() { var provider = TestImageProvider.File(TestImageLossyComplexFilterPath); - using (Image image = provider.GetImage(WebpDecoder)) - { - image.DebugSave(provider); - image.CompareToOriginal(provider, ReferenceDecoder); - } + using Image image = provider.GetImage(WebpDecoder); + image.DebugSave(provider); + image.CompareToOriginal(provider, ReferenceDecoder); } [Fact] @@ -472,6 +419,5 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp [Fact] public void DecodeLossyWithComplexFilterTest_WithoutHardwareIntrinsics_Works() => FeatureTestRunner.RunWithHwIntrinsicsFeature(RunDecodeLossyWithComplexFilterTest, HwIntrinsics.DisableHWIntrinsic); -#endif } } diff --git a/tests/ImageSharp.Tests/Formats/WebP/WebpEncoderTests.cs b/tests/ImageSharp.Tests/Formats/WebP/WebpEncoderTests.cs index 27dccf84a..f16f50b98 100644 --- a/tests/ImageSharp.Tests/Formats/WebP/WebpEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/WebP/WebpEncoderTests.cs @@ -326,13 +326,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp image.VerifyEncoder(provider, "webp", string.Empty, encoder, ImageComparer.Tolerant(0.04f)); } -#if SUPPORTS_RUNTIME_INTRINSICS [Fact] public void RunEncodeLossy_WithPeakImage_WithHardwareIntrinsics_Works() => FeatureTestRunner.RunWithHwIntrinsicsFeature(RunEncodeLossy_WithPeakImage, HwIntrinsics.AllowAll); [Fact] public void RunEncodeLossy_WithPeakImage_WithoutHardwareIntrinsics_Works() => FeatureTestRunner.RunWithHwIntrinsicsFeature(RunEncodeLossy_WithPeakImage, HwIntrinsics.DisableHWIntrinsic); -#endif private static ImageComparer GetComparer(int quality) { diff --git a/tests/ImageSharp.Tests/Formats/WebP/YuvConversionTests.cs b/tests/ImageSharp.Tests/Formats/WebP/YuvConversionTests.cs index 6b4b60491..718dd920f 100644 --- a/tests/ImageSharp.Tests/Formats/WebP/YuvConversionTests.cs +++ b/tests/ImageSharp.Tests/Formats/WebP/YuvConversionTests.cs @@ -26,25 +26,20 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp public static void RunUpSampleYuvToRgbTest() { var provider = TestImageProvider.File(TestImageLossyFullPath); - using (Image image = provider.GetImage(WebpDecoder)) - { - image.DebugSave(provider); - image.CompareToOriginal(provider, ReferenceDecoder); - } + using Image image = provider.GetImage(WebpDecoder); + image.DebugSave(provider); + image.CompareToOriginal(provider, ReferenceDecoder); } [Fact] public void UpSampleYuvToRgb_Works() => RunUpSampleYuvToRgbTest(); -#if SUPPORTS_RUNTIME_INTRINSICS [Fact] public void UpSampleYuvToRgb_WithHardwareIntrinsics_Works() => FeatureTestRunner.RunWithHwIntrinsicsFeature(RunUpSampleYuvToRgbTest, HwIntrinsics.AllowAll); [Fact] public void UpSampleYuvToRgb_WithoutSSE2_Works() => FeatureTestRunner.RunWithHwIntrinsicsFeature(RunUpSampleYuvToRgbTest, HwIntrinsics.DisableSSE2); -#endif - [Theory] [WithFile(TestImages.Webp.Yuv, PixelTypes.Rgba32)] public void ConvertRgbToYuv_Works(TestImageProvider provider) @@ -157,8 +152,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp // assert Assert.True(expectedY.AsSpan().SequenceEqual(y)); - Assert.True(expectedU.AsSpan().SequenceEqual(u.Slice(0, expectedU.Length))); - Assert.True(expectedV.AsSpan().SequenceEqual(v.Slice(0, expectedV.Length))); + Assert.True(expectedU.AsSpan().SequenceEqual(u[..expectedU.Length])); + Assert.True(expectedV.AsSpan().SequenceEqual(v[..expectedV.Length])); } [Theory] @@ -263,8 +258,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp // assert Assert.True(expectedY.AsSpan().SequenceEqual(y)); - Assert.True(expectedU.AsSpan().SequenceEqual(u.Slice(0, expectedU.Length))); - Assert.True(expectedV.AsSpan().SequenceEqual(v.Slice(0, expectedV.Length))); + Assert.True(expectedU.AsSpan().SequenceEqual(u[..expectedU.Length])); + Assert.True(expectedV.AsSpan().SequenceEqual(v[..expectedV.Length])); } } } diff --git a/tests/ImageSharp.Tests/Processing/Transforms/ResizeTests.cs b/tests/ImageSharp.Tests/Processing/Transforms/ResizeTests.cs index 306121fb0..3d084df07 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/ResizeTests.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/ResizeTests.cs @@ -89,7 +89,6 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms Assert.Equal(mode, resizeOptions.Mode); } -#if SUPPORTS_RUNTIME_INTRINSICS [Fact] public void HwIntrinsics_Resize() { @@ -106,6 +105,5 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms RunTest, HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX2 | HwIntrinsics.DisableFMA); } -#endif } } diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs index e660bb153..fc8ca6c45 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs @@ -5,9 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Numerics; -#if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.Intrinsics.X86; -#endif using Xunit; using Xunit.Abstractions; @@ -55,7 +53,6 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests HwIntrinsics.AllowAll); } -#if SUPPORTS_RUNTIME_INTRINSICS [Fact] public void CanLimitHwIntrinsicBaseFeatures() { @@ -82,7 +79,6 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests AssertDisabled, HwIntrinsics.DisableHWIntrinsic); } -#endif [Fact] public void CanLimitHwIntrinsicFeaturesWithIntrinsicsParam() @@ -91,9 +87,8 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests { Assert.NotNull(intrinsic); - switch ((HwIntrinsics)Enum.Parse(typeof(HwIntrinsics), intrinsic)) + switch (Enum.Parse(intrinsic)) { -#if SUPPORTS_RUNTIME_INTRINSICS case HwIntrinsics.DisableHWIntrinsic: Assert.False(Sse.IsSupported); Assert.False(Sse2.IsSupported); @@ -156,11 +151,10 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests case HwIntrinsics.DisableLZCNT: Assert.False(Lzcnt.IsSupported); break; -#endif } } - foreach (HwIntrinsics intrinsic in (HwIntrinsics[])Enum.GetValues(typeof(HwIntrinsics))) + foreach (HwIntrinsics intrinsic in Enum.GetValues()) { FeatureTestRunner.RunWithHwIntrinsicsFeature(AssertHwIntrinsicsFeatureDisabled, intrinsic); } @@ -173,10 +167,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests { Assert.NotNull(serializable); Assert.NotNull(FeatureTestRunner.DeserializeForXunit(serializable)); - -#if SUPPORTS_RUNTIME_INTRINSICS Assert.False(Sse.IsSupported); -#endif } FeatureTestRunner.RunWithHwIntrinsicsFeature( @@ -193,9 +184,8 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests Assert.NotNull(serializable); Assert.NotNull(FeatureTestRunner.DeserializeForXunit(serializable)); - switch ((HwIntrinsics)Enum.Parse(typeof(HwIntrinsics), intrinsic)) + switch (Enum.Parse(intrinsic)) { -#if SUPPORTS_RUNTIME_INTRINSICS case HwIntrinsics.DisableHWIntrinsic: Assert.False(Sse.IsSupported); Assert.False(Sse2.IsSupported); @@ -258,7 +248,6 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests case HwIntrinsics.DisableLZCNT: Assert.False(Lzcnt.IsSupported); break; -#endif } } From 6fc84a82f6a41ff22545d81f43330a04a678b6d1 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Sun, 24 Jul 2022 01:05:31 +1000 Subject: [PATCH 02/20] Remove other obsolete conditions and warnings --- shared-infrastructure | 2 +- .../ColorSpaces/Companding/SRgbCompanding.cs | 4 +- .../VonKriesChromaticAdaptation.cs | 2 +- src/ImageSharp/Common/Helpers/HexConverter.cs | 2 +- .../Compression/Zlib/DeflaterOutputStream.cs | 4 +- .../Compression/Zlib/DeflaterPendingBuffer.cs | 2 +- .../Diagnostics/MemoryDiagnostics.cs | 6 - src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs | 12 +- src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs | 4 +- src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs | 16 +- src/ImageSharp/Formats/Gif/GifEncoderCore.cs | 2 +- .../Gif/Sections/GifImageDescriptor.cs | 2 +- .../GifNetscapeLoopingApplicationExtension.cs | 2 +- .../Sections/GifXmpApplicationExtension.cs | 4 +- src/ImageSharp/Formats/ImageFormatManager.cs | 2 +- .../Components/Decoder/ProfileResolver.cs | 2 +- .../Decoder/SpectralConverter{TPixel}.cs | 2 +- .../Formats/Jpeg/JpegDecoderCore.cs | 16 +- src/ImageSharp/Formats/Pbm/PbmEncoderCore.cs | 6 +- src/ImageSharp/Formats/Pbm/PlainEncoder.cs | 16 +- .../Formats/Png/Chunks/PhysicalChunkData.cs | 4 +- .../Formats/Png/Filters/NoneFilter.cs | 4 +- src/ImageSharp/Formats/Png/PngDecoderCore.cs | 167 ++++++++---------- src/ImageSharp/Formats/Png/PngEncoderCore.cs | 16 +- src/ImageSharp/Formats/Png/PngHeader.cs | 4 +- src/ImageSharp/Formats/Tga/TgaDecoderCore.cs | 4 +- .../Compressors/PackBitsCompressor.cs | 2 +- .../Compression/Compressors/PackBitsWriter.cs | 2 +- .../Compressors/TiffCcittCompressor.cs | 2 +- .../Decompressors/CcittReferenceScanline.cs | 6 +- .../Decompressors/JpegTiffCompression.cs | 4 +- .../Decompressors/PackBitsTiffCompression.cs | 2 +- .../Decompressors/T6TiffCompression.cs | 18 +- .../Decompressors/WebpTiffCompression.cs | 2 +- .../Tiff/Compression/HorizontalPredictor.cs | 4 +- .../BlackIsZero24TiffColor{TPixel}.cs | 2 +- .../Rgb242424TiffColor{TPixel}.cs | 2 +- .../Rgb24PlanarTiffColor{TPixel}.cs | 2 +- .../Rgba24242424TiffColor{TPixel}.cs | 2 +- .../Rgba24PlanarTiffColor{TPixel}.cs | 2 +- .../WhiteIsZero24TiffColor{TPixel}.cs | 2 +- .../Tiff/Writers/TiffBiColorWriter{TPixel}.cs | 4 +- .../TiffCompositeColorWriter{TPixel}.cs | 2 +- .../Tiff/Writers/TiffPaletteWriter{TPixel}.cs | 6 +- .../Formats/Webp/BitReader/BitReaderBase.cs | 2 +- .../Formats/Webp/BitWriter/BitWriterBase.cs | 4 +- .../Formats/Webp/BitWriter/Vp8BitWriter.cs | 4 +- .../Webp/Lossless/BackwardReferenceEncoder.cs | 6 +- .../Formats/Webp/Lossless/HuffmanUtils.cs | 10 +- .../Formats/Webp/Lossless/NearLosslessEnc.cs | 2 +- .../Formats/Webp/Lossless/PredictorEncoder.cs | 30 ++-- .../Formats/Webp/Lossless/Vp8LEncoder.cs | 50 +++--- .../Formats/Webp/Lossless/Vp8LHashChain.cs | 14 +- .../Webp/Lossless/WebpLosslessDecoder.cs | 26 +-- src/ImageSharp/Formats/Webp/Lossy/QuantEnc.cs | 2 +- .../Formats/Webp/Lossy/Vp8EncIterator.cs | 28 +-- .../Formats/Webp/Lossy/Vp8Encoder.cs | 2 +- .../Formats/Webp/Lossy/WebpLossyDecoder.cs | 72 ++++---- .../Formats/Webp/WebpAnimationDecoder.cs | 4 +- .../Formats/Webp/WebpImageFormatDetector.cs | 2 +- src/ImageSharp/IO/ChunkedMemoryStream.cs | 4 +- src/ImageSharp/Image.LoadPixelData.cs | 2 +- src/ImageSharp/ImageFrame.LoadPixelData.cs | 2 +- src/ImageSharp/IndexedImageFrame{TPixel}.cs | 2 +- .../Allocators/Internals/Gen2GcCallback.cs | 24 ++- .../Internals/UniformUnmanagedMemoryPool.cs | 10 +- ...iformUnmanagedMemoryPoolMemoryAllocator.cs | 10 +- src/ImageSharp/Memory/Buffer2D{T}.cs | 2 +- src/ImageSharp/Memory/ByteMemoryManager{T}.cs | 2 +- .../MemoryGroupExtensions.cs | 6 +- .../DiscontiguousBuffers/MemoryGroup{T}.cs | 2 +- .../Memory/MemoryOwnerExtensions.cs | 2 +- .../Profiles/Exif/ExifEncodedStringHelpers.cs | 21 +-- .../Metadata/Profiles/Exif/ExifReader.cs | 51 ++---- .../Metadata/Profiles/Exif/ExifWriter.cs | 8 +- .../DataReader/IccDataReader.Primitives.cs | 2 +- .../DataWriter/IccDataWriter.Primitives.cs | 2 +- .../Metadata/Profiles/IPTC/IptcValue.cs | 2 +- .../PixelFormats/PixelBlender{TPixel}.cs | 12 +- .../PixelImplementations/Rgb24.cs | 14 +- .../PixelImplementations/Rgba32.cs | 2 +- .../PixelFormats/PixelOperations{TPixel}.cs | 6 +- .../Utils/Vector4Converters.RgbaCompatible.cs | 4 +- .../Convolution/BokehBlurProcessor{TPixel}.cs | 18 +- .../Convolution2DRowOperation{TPixel}.cs | 4 +- .../Convolution2PassProcessor{TPixel}.cs | 16 +- .../ConvolutionProcessor{TPixel}.cs | 4 +- .../Convolution/KernelSamplingMap.cs | 4 +- .../Processors/Dithering/OrderedDither.cs | 2 +- .../Filters/OpaqueProcessor{TPixel}.cs | 4 +- ...lHistogramEqualizationProcessor{TPixel}.cs | 10 -- .../Quantization/OctreeQuantizer{TPixel}.cs | 2 +- .../Quantization/WuQuantizer{TPixel}.cs | 4 +- .../Transforms/CropProcessor{TPixel}.cs | 4 +- .../Transforms/Resize/ResizeWorker.cs | 2 +- .../Helpers/RuntimeEnvironmentTests.cs | 12 +- .../UniformUnmanagedMemoryPoolTests.Trim.cs | 14 +- ...niformUnmanagedPoolMemoryAllocatorTests.cs | 2 - .../PixelOperations/PixelOperationsTests.cs | 2 - .../Primitives/ColorMatrixTests.cs | 48 ++--- .../Processing/Convolution/DetectEdgesTest.cs | 14 +- .../Processors/Convolution/DetectEdgesTest.cs | 1 - .../TestDataIcc/IccTestDataCurves.cs | 2 - .../TestDataIcc/IccTestDataProfiles.cs | 4 - .../TestDataIcc/IccTestDataTagDataEntry.cs | 6 - .../TestUtilities/PausedStream.cs | 2 - .../TestUtilities/PixelTypes.cs | 3 - .../TestUtilities/TestImageExtensions.cs | 2 - 108 files changed, 423 insertions(+), 586 deletions(-) diff --git a/shared-infrastructure b/shared-infrastructure index e12c30b3b..86af5a821 160000 --- a/shared-infrastructure +++ b/shared-infrastructure @@ -1 +1 @@ -Subproject commit e12c30b3b1427815cffa22ac95c77ba29f65fe5a +Subproject commit 86af5a82198c21ce6889370428eb97d1fa7b41ff diff --git a/src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs b/src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs index c15cdf8a8..82e9a123b 100644 --- a/src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs +++ b/src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs @@ -89,7 +89,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding if (Numerics.Modulo2(vectors.Length) != 0) { // Vector4 fits neatly in pairs. Any overlap has to be equal to 1. - Expand(ref MemoryMarshal.GetReference(vectors.Slice(vectors.Length - 1))); + Expand(ref MemoryMarshal.GetReference(vectors[^1..])); } } else @@ -112,7 +112,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding if (Numerics.Modulo2(vectors.Length) != 0) { // Vector4 fits neatly in pairs. Any overlap has to be equal to 1. - Compress(ref MemoryMarshal.GetReference(vectors.Slice(vectors.Length - 1))); + Compress(ref MemoryMarshal.GetReference(vectors[^1..])); } } else diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/VonKriesChromaticAdaptation.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/VonKriesChromaticAdaptation.cs index b107aacaf..5723d2691 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/VonKriesChromaticAdaptation.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/VonKriesChromaticAdaptation.cs @@ -75,7 +75,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion if (sourceWhitePoint.Equals(destinationWhitePoint)) { - source.CopyTo(destination.Slice(0, count)); + source.CopyTo(destination[..count]); return; } diff --git a/src/ImageSharp/Common/Helpers/HexConverter.cs b/src/ImageSharp/Common/Helpers/HexConverter.cs index 27a5a40f6..40f80a86f 100644 --- a/src/ImageSharp/Common/Helpers/HexConverter.cs +++ b/src/ImageSharp/Common/Helpers/HexConverter.cs @@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp.Common.Helpers { // Slightly better performance in the loop below, allows us to skip a bounds check // while still supporting output buffers that are larger than necessary - bytes = bytes.Slice(0, chars.Length / 2); + bytes = bytes[..(chars.Length / 2)]; } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/ImageSharp/Compression/Zlib/DeflaterOutputStream.cs b/src/ImageSharp/Compression/Zlib/DeflaterOutputStream.cs index 9ba9d34b1..5b8673da8 100644 --- a/src/ImageSharp/Compression/Zlib/DeflaterOutputStream.cs +++ b/src/ImageSharp/Compression/Zlib/DeflaterOutputStream.cs @@ -95,7 +95,7 @@ namespace SixLabors.ImageSharp.Compression.Zlib break; } - this.rawStream.Write(this.buffer.Span.Slice(0, deflateCount)); + this.rawStream.Write(this.buffer.Span[..deflateCount]); } if (!this.deflater.IsNeedingInput) @@ -115,7 +115,7 @@ namespace SixLabors.ImageSharp.Compression.Zlib break; } - this.rawStream.Write(this.buffer.Span.Slice(0, len)); + this.rawStream.Write(this.buffer.Span[..len]); } if (!this.deflater.IsFinished) diff --git a/src/ImageSharp/Compression/Zlib/DeflaterPendingBuffer.cs b/src/ImageSharp/Compression/Zlib/DeflaterPendingBuffer.cs index b24150faf..1ab6349f0 100644 --- a/src/ImageSharp/Compression/Zlib/DeflaterPendingBuffer.cs +++ b/src/ImageSharp/Compression/Zlib/DeflaterPendingBuffer.cs @@ -75,7 +75,7 @@ namespace SixLabors.ImageSharp.Compression.Zlib { Unsafe.CopyBlockUnaligned( ref this.buffer.Span[this.end], - ref MemoryMarshal.GetReference(block.Slice(offset)), + ref MemoryMarshal.GetReference(block[offset..]), unchecked((uint)length)); this.end += length; diff --git a/src/ImageSharp/Diagnostics/MemoryDiagnostics.cs b/src/ImageSharp/Diagnostics/MemoryDiagnostics.cs index 274486cec..33af606b9 100644 --- a/src/ImageSharp/Diagnostics/MemoryDiagnostics.cs +++ b/src/ImageSharp/Diagnostics/MemoryDiagnostics.cs @@ -85,16 +85,10 @@ namespace SixLabors.ImageSharp.Diagnostics } // Schedule on the ThreadPool, to avoid user callback messing up the finalizer thread. -#if NETSTANDARD2_1 || NETCOREAPP2_1_OR_GREATER ThreadPool.QueueUserWorkItem( stackTrace => undisposedAllocation?.Invoke(stackTrace), allocationStackTrace, preferLocal: false); -#else - ThreadPool.QueueUserWorkItem( - stackTrace => undisposedAllocation?.Invoke((string)stackTrace), - allocationStackTrace); -#endif } } } diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs index 3a96c4022..150f8eada 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs @@ -597,7 +597,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp this.stream.Read(run, 0, run.Length); - run.AsSpan().CopyTo(buffer.Slice(count)); + run.AsSpan().CopyTo(buffer[count..]); count += run.Length; @@ -676,7 +676,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp this.stream.Read(run, 0, run.Length); - run.AsSpan().CopyTo(buffer.Slice(start: uncompressedPixels * 3)); + run.AsSpan().CopyTo(buffer[(uncompressedPixels * 3)..]); uncompressedPixels += length; @@ -891,7 +891,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp int offset = 0; for (int x = 0; x < width; x++) { - short temp = BinaryPrimitives.ReadInt16LittleEndian(bufferSpan.Slice(offset)); + short temp = BinaryPrimitives.ReadInt16LittleEndian(bufferSpan[offset..]); // Rescale values, so the values range from 0 to 255. int r = (redMaskBits == 5) ? GetBytesFrom5BitValue((temp & redMask) >> rightShiftRedMask) : GetBytesFrom6BitValue((temp & redMask) >> rightShiftRedMask); @@ -1122,7 +1122,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp int offset = 0; for (int x = 0; x < width; x++) { - uint temp = BinaryPrimitives.ReadUInt32LittleEndian(bufferSpan.Slice(offset)); + uint temp = BinaryPrimitives.ReadUInt32LittleEndian(bufferSpan[offset..]); if (unusualBitMask) { @@ -1246,7 +1246,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp var bitfieldsBuffer = new byte[12]; this.stream.Read(bitfieldsBuffer, 0, 12); Span data = bitfieldsBuffer.AsSpan(); - this.infoHeader.RedMask = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(0, 4)); + this.infoHeader.RedMask = BinaryPrimitives.ReadInt32LittleEndian(data[..4]); this.infoHeader.GreenMask = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(4, 4)); this.infoHeader.BlueMask = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(8, 4)); } @@ -1255,7 +1255,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp var bitfieldsBuffer = new byte[16]; this.stream.Read(bitfieldsBuffer, 0, 16); Span data = bitfieldsBuffer.AsSpan(); - this.infoHeader.RedMask = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(0, 4)); + this.infoHeader.RedMask = BinaryPrimitives.ReadInt32LittleEndian(data[..4]); this.infoHeader.GreenMask = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(4, 4)); this.infoHeader.BlueMask = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(8, 4)); this.infoHeader.AlphaMask = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(12, 4)); diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs index f71275b7c..9671b7d27 100644 --- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs @@ -257,7 +257,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp stream.Write(iccProfileData); BinaryPrimitives.WriteInt32LittleEndian(buffer, streamPositionAfterImageData); stream.Position = BmpFileHeader.Size + 112; - stream.Write(buffer.Slice(0, 4)); + stream.Write(buffer[..4]); } } @@ -618,7 +618,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp where TPixel : unmanaged, IPixel { int quantizedColorBytes = quantizedColorPalette.Length * 4; - PixelOperations.Instance.ToBgra32(this.configuration, quantizedColorPalette, MemoryMarshal.Cast(colorPalette.Slice(0, quantizedColorBytes))); + PixelOperations.Instance.ToBgra32(this.configuration, quantizedColorPalette, MemoryMarshal.Cast(colorPalette[..quantizedColorBytes])); Span colorPaletteAsUInt = MemoryMarshal.Cast(colorPalette); for (int i = 0; i < colorPaletteAsUInt.Length; i++) { diff --git a/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs b/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs index 823569b8a..9c0efcb6d 100644 --- a/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs +++ b/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs @@ -308,7 +308,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// The parsed header. /// public static BmpInfoHeader ParseCore(ReadOnlySpan data) => new( - headerSize: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(0, 4)), + headerSize: BinaryPrimitives.ReadInt32LittleEndian(data[..4]), width: BinaryPrimitives.ReadUInt16LittleEndian(data.Slice(4, 2)), height: BinaryPrimitives.ReadUInt16LittleEndian(data.Slice(6, 2)), planes: BinaryPrimitives.ReadInt16LittleEndian(data.Slice(8, 2)), @@ -322,7 +322,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// The parsed header. /// public static BmpInfoHeader ParseOs22Short(ReadOnlySpan data) => new( - headerSize: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(0, 4)), + headerSize: BinaryPrimitives.ReadInt32LittleEndian(data[..4]), width: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(4, 4)), height: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(8, 4)), planes: BinaryPrimitives.ReadInt16LittleEndian(data.Slice(12, 2)), @@ -335,7 +335,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// The parsed header. /// public static BmpInfoHeader ParseV3(ReadOnlySpan data) => new( - headerSize: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(0, 4)), + headerSize: BinaryPrimitives.ReadInt32LittleEndian(data[..4]), width: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(4, 4)), height: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(8, 4)), planes: BinaryPrimitives.ReadInt16LittleEndian(data.Slice(12, 2)), @@ -356,7 +356,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// The parsed header. /// public static BmpInfoHeader ParseAdobeV3(ReadOnlySpan data, bool withAlpha = true) => new( - headerSize: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(0, 4)), + headerSize: BinaryPrimitives.ReadInt32LittleEndian(data[..4]), width: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(4, 4)), height: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(8, 4)), planes: BinaryPrimitives.ReadInt16LittleEndian(data.Slice(12, 2)), @@ -383,7 +383,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp public static BmpInfoHeader ParseOs2Version2(ReadOnlySpan data) { var infoHeader = new BmpInfoHeader( - headerSize: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(0, 4)), + headerSize: BinaryPrimitives.ReadInt32LittleEndian(data[..4]), width: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(4, 4)), height: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(8, 4)), planes: BinaryPrimitives.ReadInt16LittleEndian(data.Slice(12, 2)), @@ -430,7 +430,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// The parsed header. /// public static BmpInfoHeader ParseV4(ReadOnlySpan data) => new( - headerSize: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(0, 4)), + headerSize: BinaryPrimitives.ReadInt32LittleEndian(data[..4]), width: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(4, 4)), height: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(8, 4)), planes: BinaryPrimitives.ReadInt16LittleEndian(data.Slice(12, 2)), @@ -482,7 +482,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp public void WriteV3Header(Span buffer) { buffer.Clear(); - BinaryPrimitives.WriteInt32LittleEndian(buffer.Slice(0, 4), SizeV3); + BinaryPrimitives.WriteInt32LittleEndian(buffer[..4], SizeV3); BinaryPrimitives.WriteInt32LittleEndian(buffer.Slice(4, 4), this.Width); BinaryPrimitives.WriteInt32LittleEndian(buffer.Slice(8, 4), this.Height); BinaryPrimitives.WriteInt16LittleEndian(buffer.Slice(12, 2), this.Planes); @@ -502,7 +502,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp public void WriteV4Header(Span buffer) { buffer.Clear(); - BinaryPrimitives.WriteInt32LittleEndian(buffer.Slice(0, 4), SizeV4); + BinaryPrimitives.WriteInt32LittleEndian(buffer[..4], SizeV4); BinaryPrimitives.WriteInt32LittleEndian(buffer.Slice(4, 4), this.Width); BinaryPrimitives.WriteInt32LittleEndian(buffer.Slice(8, 4), this.Height); BinaryPrimitives.WriteInt16LittleEndian(buffer.Slice(12, 2), this.Planes); diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs index bb45c8364..0f7606a43 100644 --- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs @@ -448,7 +448,7 @@ namespace SixLabors.ImageSharp.Formats.Gif extensionBuffer[0] = GifConstants.ExtensionIntroducer; extensionBuffer[1] = extension.Label; - extension.WriteTo(extensionBuffer.Slice(2)); + extension.WriteTo(extensionBuffer[2..]); extensionBuffer[extensionSize + 2] = GifConstants.Terminator; diff --git a/src/ImageSharp/Formats/Gif/Sections/GifImageDescriptor.cs b/src/ImageSharp/Formats/Gif/Sections/GifImageDescriptor.cs index 07e0f6f0c..9f7755b01 100644 --- a/src/ImageSharp/Formats/Gif/Sections/GifImageDescriptor.cs +++ b/src/ImageSharp/Formats/Gif/Sections/GifImageDescriptor.cs @@ -71,7 +71,7 @@ namespace SixLabors.ImageSharp.Formats.Gif { buffer[0] = GifConstants.ImageDescriptorLabel; - ref GifImageDescriptor dest = ref Unsafe.As(ref MemoryMarshal.GetReference(buffer.Slice(1))); + ref GifImageDescriptor dest = ref Unsafe.As(ref MemoryMarshal.GetReference(buffer[1..])); dest = this; } diff --git a/src/ImageSharp/Formats/Gif/Sections/GifNetscapeLoopingApplicationExtension.cs b/src/ImageSharp/Formats/Gif/Sections/GifNetscapeLoopingApplicationExtension.cs index d9ee93883..8965ae345 100644 --- a/src/ImageSharp/Formats/Gif/Sections/GifNetscapeLoopingApplicationExtension.cs +++ b/src/ImageSharp/Formats/Gif/Sections/GifNetscapeLoopingApplicationExtension.cs @@ -22,7 +22,7 @@ namespace SixLabors.ImageSharp.Formats.Gif public static GifNetscapeLoopingApplicationExtension Parse(ReadOnlySpan buffer) { - ushort repeatCount = BinaryPrimitives.ReadUInt16LittleEndian(buffer.Slice(0, 2)); + ushort repeatCount = BinaryPrimitives.ReadUInt16LittleEndian(buffer[..2]); return new GifNetscapeLoopingApplicationExtension(repeatCount); } diff --git a/src/ImageSharp/Formats/Gif/Sections/GifXmpApplicationExtension.cs b/src/ImageSharp/Formats/Gif/Sections/GifXmpApplicationExtension.cs index d3a621e7b..9f8d8e4d0 100644 --- a/src/ImageSharp/Formats/Gif/Sections/GifXmpApplicationExtension.cs +++ b/src/ImageSharp/Formats/Gif/Sections/GifXmpApplicationExtension.cs @@ -55,11 +55,11 @@ namespace SixLabors.ImageSharp.Formats.Gif // Write "XMP DataXMP" ReadOnlySpan idBytes = GifConstants.XmpApplicationIdentificationBytes; - idBytes.CopyTo(buffer.Slice(bytesWritten)); + idBytes.CopyTo(buffer[bytesWritten..]); bytesWritten += idBytes.Length; // XMP Data itself - this.Data.CopyTo(buffer.Slice(bytesWritten)); + this.Data.CopyTo(buffer[bytesWritten..]); bytesWritten += this.Data.Length; // Write the Magic Trailer diff --git a/src/ImageSharp/Formats/ImageFormatManager.cs b/src/ImageSharp/Formats/ImageFormatManager.cs index 9f3f0d47f..78e797dcd 100644 --- a/src/ImageSharp/Formats/ImageFormatManager.cs +++ b/src/ImageSharp/Formats/ImageFormatManager.cs @@ -101,7 +101,7 @@ namespace SixLabors.ImageSharp.Formats if (extension[0] == '.') { - extension = extension.Substring(1); + extension = extension[1..]; } return this.imageFormats.FirstOrDefault(x => x.FileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase)); diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ProfileResolver.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ProfileResolver.cs index 9f1d4d91f..ed678bd2b 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ProfileResolver.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ProfileResolver.cs @@ -89,7 +89,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder public static bool IsProfile(ReadOnlySpan bytesToCheck, ReadOnlySpan profileIdentifier) { return bytesToCheck.Length >= profileIdentifier.Length - && bytesToCheck.Slice(0, profileIdentifier.Length).SequenceEqual(profileIdentifier); + && bytesToCheck[..profileIdentifier.Length].SequenceEqual(profileIdentifier); } } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs index d460d9497..fafbabe25 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs @@ -162,7 +162,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder { Span proxyRow = this.paddedProxyPixelRow.GetSpan(); PixelOperations.Instance.PackFromRgbPlanes(this.configuration, r, g, b, proxyRow); - proxyRow.Slice(0, width).CopyTo(this.pixelBuffer.DangerousGetRowSpan(yy)); + proxyRow[..width].CopyTo(this.pixelBuffer.DangerousGetRowSpan(yy)); } } diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs index 11187fb91..66fc6ce80 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs @@ -810,7 +810,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg remaining = 0; } - if (ProfileResolver.IsProfile(this.temp, ProfileResolver.XmpMarker.Slice(0, ExifMarkerLength))) + if (ProfileResolver.IsProfile(this.temp, ProfileResolver.XmpMarker[..ExifMarkerLength])) { const int remainingXmpMarkerBytes = XmpMarkerLength - ExifMarkerLength; if (remaining < remainingXmpMarkerBytes || this.IgnoreMetadata) @@ -912,13 +912,13 @@ namespace SixLabors.ImageSharp.Formats.Jpeg while (blockDataSpan.Length > 12) { - if (!ProfileResolver.IsProfile(blockDataSpan.Slice(0, 4), ProfileResolver.AdobeImageResourceBlockMarker)) + if (!ProfileResolver.IsProfile(blockDataSpan[..4], ProfileResolver.AdobeImageResourceBlockMarker)) { return; } - blockDataSpan = blockDataSpan.Slice(4); - Span imageResourceBlockId = blockDataSpan.Slice(0, 2); + blockDataSpan = blockDataSpan[4..]; + Span imageResourceBlockId = blockDataSpan[..2]; if (ProfileResolver.IsProfile(imageResourceBlockId, ProfileResolver.AdobeIptcMarker)) { int resourceBlockNameLength = ReadImageResourceNameLength(blockDataSpan); @@ -942,7 +942,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg break; } - blockDataSpan = blockDataSpan.Slice(dataStartIdx + resourceDataSize); + blockDataSpan = blockDataSpan[(dataStartIdx + resourceDataSize)..]; } } } @@ -1322,9 +1322,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg using (IMemoryOwner buffer = this.Configuration.MemoryAllocator.Allocate(totalBufferSize)) { Span bufferSpan = buffer.GetSpan(); - Span huffmanLengthsSpan = bufferSpan.Slice(0, codeLengthsByteSize); + Span huffmanLengthsSpan = bufferSpan[..codeLengthsByteSize]; Span huffmanValuesSpan = bufferSpan.Slice(codeLengthsByteSize, codeValuesMaxByteSize); - Span tableWorkspace = MemoryMarshal.Cast(bufferSpan.Slice(codeLengthsByteSize + codeValuesMaxByteSize)); + Span tableWorkspace = MemoryMarshal.Cast(bufferSpan[(codeLengthsByteSize + codeValuesMaxByteSize)..]); for (int i = 2; i < remaining;) { @@ -1367,7 +1367,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg tableType, tableIndex, huffmanLengthsSpan, - huffmanValuesSpan.Slice(0, codeLengthSum), + huffmanValuesSpan[..codeLengthSum], tableWorkspace); } } diff --git a/src/ImageSharp/Formats/Pbm/PbmEncoderCore.cs b/src/ImageSharp/Formats/Pbm/PbmEncoderCore.cs index 25c7ee450..431eea4c4 100644 --- a/src/ImageSharp/Formats/Pbm/PbmEncoderCore.cs +++ b/src/ImageSharp/Formats/Pbm/PbmEncoderCore.cs @@ -145,17 +145,17 @@ namespace SixLabors.ImageSharp.Formats.Pbm buffer[1] = signature; buffer[2] = NewLine; - Utf8Formatter.TryFormat(pixelSize.Width, buffer.Slice(written), out int bytesWritten); + Utf8Formatter.TryFormat(pixelSize.Width, buffer[written..], out int bytesWritten); written += bytesWritten; buffer[written++] = Space; - Utf8Formatter.TryFormat(pixelSize.Height, buffer.Slice(written), out bytesWritten); + Utf8Formatter.TryFormat(pixelSize.Height, buffer[written..], out bytesWritten); written += bytesWritten; buffer[written++] = NewLine; if (this.colorType != PbmColorType.BlackAndWhite) { int maxPixelValue = this.componentType == PbmComponentType.Short ? 65535 : 255; - Utf8Formatter.TryFormat(maxPixelValue, buffer.Slice(written), out bytesWritten); + Utf8Formatter.TryFormat(maxPixelValue, buffer[written..], out bytesWritten); written += bytesWritten; buffer[written++] = NewLine; } diff --git a/src/ImageSharp/Formats/Pbm/PlainEncoder.cs b/src/ImageSharp/Formats/Pbm/PlainEncoder.cs index b858d1e63..d989b6e66 100644 --- a/src/ImageSharp/Formats/Pbm/PlainEncoder.cs +++ b/src/ImageSharp/Formats/Pbm/PlainEncoder.cs @@ -94,7 +94,7 @@ namespace SixLabors.ImageSharp.Formats.Pbm int written = 0; for (int x = 0; x < width; x++) { - Utf8Formatter.TryFormat(rowSpan[x].PackedValue, plainSpan.Slice(written), out int bytesWritten, DecimalFormat); + Utf8Formatter.TryFormat(rowSpan[x].PackedValue, plainSpan[written..], out int bytesWritten, DecimalFormat); written += bytesWritten; plainSpan[written++] = Space; } @@ -127,7 +127,7 @@ namespace SixLabors.ImageSharp.Formats.Pbm int written = 0; for (int x = 0; x < width; x++) { - Utf8Formatter.TryFormat(rowSpan[x].PackedValue, plainSpan.Slice(written), out int bytesWritten, DecimalFormat); + Utf8Formatter.TryFormat(rowSpan[x].PackedValue, plainSpan[written..], out int bytesWritten, DecimalFormat); written += bytesWritten; plainSpan[written++] = Space; } @@ -160,13 +160,13 @@ namespace SixLabors.ImageSharp.Formats.Pbm int written = 0; for (int x = 0; x < width; x++) { - Utf8Formatter.TryFormat(rowSpan[x].R, plainSpan.Slice(written), out int bytesWritten, DecimalFormat); + Utf8Formatter.TryFormat(rowSpan[x].R, plainSpan[written..], out int bytesWritten, DecimalFormat); written += bytesWritten; plainSpan[written++] = Space; - Utf8Formatter.TryFormat(rowSpan[x].G, plainSpan.Slice(written), out bytesWritten, DecimalFormat); + Utf8Formatter.TryFormat(rowSpan[x].G, plainSpan[written..], out bytesWritten, DecimalFormat); written += bytesWritten; plainSpan[written++] = Space; - Utf8Formatter.TryFormat(rowSpan[x].B, plainSpan.Slice(written), out bytesWritten, DecimalFormat); + Utf8Formatter.TryFormat(rowSpan[x].B, plainSpan[written..], out bytesWritten, DecimalFormat); written += bytesWritten; plainSpan[written++] = Space; } @@ -199,13 +199,13 @@ namespace SixLabors.ImageSharp.Formats.Pbm int written = 0; for (int x = 0; x < width; x++) { - Utf8Formatter.TryFormat(rowSpan[x].R, plainSpan.Slice(written), out int bytesWritten, DecimalFormat); + Utf8Formatter.TryFormat(rowSpan[x].R, plainSpan[written..], out int bytesWritten, DecimalFormat); written += bytesWritten; plainSpan[written++] = Space; - Utf8Formatter.TryFormat(rowSpan[x].G, plainSpan.Slice(written), out bytesWritten, DecimalFormat); + Utf8Formatter.TryFormat(rowSpan[x].G, plainSpan[written..], out bytesWritten, DecimalFormat); written += bytesWritten; plainSpan[written++] = Space; - Utf8Formatter.TryFormat(rowSpan[x].B, plainSpan.Slice(written), out bytesWritten, DecimalFormat); + Utf8Formatter.TryFormat(rowSpan[x].B, plainSpan[written..], out bytesWritten, DecimalFormat); written += bytesWritten; plainSpan[written++] = Space; } diff --git a/src/ImageSharp/Formats/Png/Chunks/PhysicalChunkData.cs b/src/ImageSharp/Formats/Png/Chunks/PhysicalChunkData.cs index 8ad2c5a4a..31b845e19 100644 --- a/src/ImageSharp/Formats/Png/Chunks/PhysicalChunkData.cs +++ b/src/ImageSharp/Formats/Png/Chunks/PhysicalChunkData.cs @@ -47,7 +47,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Chunks /// The parsed PhysicalChunkData. public static PhysicalChunkData Parse(ReadOnlySpan data) { - uint hResolution = BinaryPrimitives.ReadUInt32BigEndian(data.Slice(0, 4)); + uint hResolution = BinaryPrimitives.ReadUInt32BigEndian(data[..4]); uint vResolution = BinaryPrimitives.ReadUInt32BigEndian(data.Slice(4, 4)); byte unit = data[8]; @@ -102,7 +102,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Chunks /// The buffer. public void WriteTo(Span buffer) { - BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(0, 4), this.XAxisPixelsPerUnit); + BinaryPrimitives.WriteUInt32BigEndian(buffer[..4], this.XAxisPixelsPerUnit); BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(4, 4), this.YAxisPixelsPerUnit); buffer[8] = this.UnitSpecifier; } diff --git a/src/ImageSharp/Formats/Png/Filters/NoneFilter.cs b/src/ImageSharp/Formats/Png/Filters/NoneFilter.cs index fd2d9eab4..c0e14d4ab 100644 --- a/src/ImageSharp/Formats/Png/Filters/NoneFilter.cs +++ b/src/ImageSharp/Formats/Png/Filters/NoneFilter.cs @@ -23,8 +23,8 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters { // Insert a byte before the data. result[0] = 0; - result = result.Slice(1); - scanline.Slice(0, Math.Min(scanline.Length, result.Length)).CopyTo(result); + result = result[1..]; + scanline[..Math.Min(scanline.Length, result.Length)].CopyTo(result); } } } diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs index 784d9aa11..69a23c96c 100644 --- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs @@ -4,7 +4,6 @@ using System; using System.Buffers; using System.Buffers.Binary; -using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Runtime.CompilerServices; @@ -164,10 +163,10 @@ namespace SixLabors.ImageSharp.Formats.Png this.ReadHeaderChunk(pngMetadata, chunk.Data.GetSpan()); break; case PngChunkType.Physical: - this.ReadPhysicalChunk(metadata, chunk.Data.GetSpan()); + ReadPhysicalChunk(metadata, chunk.Data.GetSpan()); break; case PngChunkType.Gamma: - this.ReadGammaChunk(pngMetadata, chunk.Data.GetSpan()); + ReadGammaChunk(pngMetadata, chunk.Data.GetSpan()); break; case PngChunkType.Data: if (image is null) @@ -203,7 +202,7 @@ namespace SixLabors.ImageSharp.Formats.Png { byte[] exifData = new byte[chunk.Length]; chunk.Data.GetSpan().CopyTo(exifData); - this.MergeOrSetExifProfile(metadata, new ExifProfile(exifData), replaceExistingKeys: true); + MergeOrSetExifProfile(metadata, new ExifProfile(exifData), replaceExistingKeys: true); } break; @@ -269,7 +268,7 @@ namespace SixLabors.ImageSharp.Formats.Png break; } - this.ReadPhysicalChunk(metadata, chunk.Data.GetSpan()); + ReadPhysicalChunk(metadata, chunk.Data.GetSpan()); break; case PngChunkType.Gamma: if (this.colorMetadataOnly) @@ -278,7 +277,7 @@ namespace SixLabors.ImageSharp.Formats.Png break; } - this.ReadGammaChunk(pngMetadata, chunk.Data.GetSpan()); + ReadGammaChunk(pngMetadata, chunk.Data.GetSpan()); break; case PngChunkType.Data: @@ -340,7 +339,7 @@ namespace SixLabors.ImageSharp.Formats.Png { byte[] exifData = new byte[chunk.Length]; chunk.Data.GetSpan().CopyTo(exifData); - this.MergeOrSetExifProfile(metadata, new ExifProfile(exifData), replaceExistingKeys: true); + MergeOrSetExifProfile(metadata, new ExifProfile(exifData), replaceExistingKeys: true); } break; @@ -429,7 +428,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// The metadata to read to. /// The data containing physical data. - private void ReadPhysicalChunk(ImageMetadata metadata, ReadOnlySpan data) + private static void ReadPhysicalChunk(ImageMetadata metadata, ReadOnlySpan data) { var physicalChunk = PhysicalChunkData.Parse(data); @@ -446,7 +445,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// The metadata to read to. /// The data containing physical data. - private void ReadGammaChunk(PngMetadata pngMetadata, ReadOnlySpan data) + private static void ReadGammaChunk(PngMetadata pngMetadata, ReadOnlySpan data) { if (data.Length < 4) { @@ -749,7 +748,7 @@ namespace SixLabors.ImageSharp.Formats.Png Span rowSpan = pixels.PixelBuffer.DangerousGetRowSpan(this.currentRow); // Trim the first marker byte from the buffer - ReadOnlySpan trimmed = defilteredScanline.Slice(1, defilteredScanline.Length - 1); + ReadOnlySpan trimmed = defilteredScanline[1..]; // Convert 1, 2, and 4 bit pixel data into the 8 bit equivalent. IMemoryOwner buffer = null; @@ -841,7 +840,7 @@ namespace SixLabors.ImageSharp.Formats.Png where TPixel : unmanaged, IPixel { // Trim the first marker byte from the buffer - ReadOnlySpan trimmed = defilteredScanline.Slice(1, defilteredScanline.Length - 1); + ReadOnlySpan trimmed = defilteredScanline[1..]; // Convert 1, 2, and 4 bit pixel data into the 8 bit equivalent. IMemoryOwner buffer = null; @@ -941,7 +940,7 @@ namespace SixLabors.ImageSharp.Formats.Png { if (this.header.BitDepth == 16) { - ushort rc = BinaryPrimitives.ReadUInt16LittleEndian(alpha.Slice(0, 2)); + ushort rc = BinaryPrimitives.ReadUInt16LittleEndian(alpha[..2]); ushort gc = BinaryPrimitives.ReadUInt16LittleEndian(alpha.Slice(2, 2)); ushort bc = BinaryPrimitives.ReadUInt16LittleEndian(alpha.Slice(4, 2)); @@ -963,7 +962,7 @@ namespace SixLabors.ImageSharp.Formats.Png { if (this.header.BitDepth == 16) { - pngMetadata.TransparentL16 = new L16(BinaryPrimitives.ReadUInt16LittleEndian(alpha.Slice(0, 2))); + pngMetadata.TransparentL16 = new L16(BinaryPrimitives.ReadUInt16LittleEndian(alpha[..2])); } else { @@ -1014,13 +1013,13 @@ namespace SixLabors.ImageSharp.Formats.Png return; } - ReadOnlySpan keywordBytes = data.Slice(0, zeroIndex); - if (!this.TryReadTextKeyword(keywordBytes, out string name)) + ReadOnlySpan keywordBytes = data[..zeroIndex]; + if (!TryReadTextKeyword(keywordBytes, out string name)) { return; } - string value = PngConstants.Encoding.GetString(data.Slice(zeroIndex + 1)); + string value = PngConstants.Encoding.GetString(data[(zeroIndex + 1)..]); if (!this.TryReadTextChunkMetadata(baseMetadata, name, value)) { @@ -1042,7 +1041,7 @@ namespace SixLabors.ImageSharp.Formats.Png } int zeroIndex = data.IndexOf((byte)0); - if (zeroIndex < PngConstants.MinTextKeywordLength || zeroIndex > PngConstants.MaxTextKeywordLength) + if (zeroIndex is < PngConstants.MinTextKeywordLength or > PngConstants.MaxTextKeywordLength) { return; } @@ -1054,13 +1053,13 @@ namespace SixLabors.ImageSharp.Formats.Png return; } - ReadOnlySpan keywordBytes = data.Slice(0, zeroIndex); - if (!this.TryReadTextKeyword(keywordBytes, out string name)) + ReadOnlySpan keywordBytes = data[..zeroIndex]; + if (!TryReadTextKeyword(keywordBytes, out string name)) { return; } - ReadOnlySpan compressedData = data.Slice(zeroIndex + 2); + ReadOnlySpan compressedData = data[(zeroIndex + 2)..]; if (this.TryUncompressTextData(compressedData, PngConstants.Encoding, out string uncompressed) && !this.TryReadTextChunkMetadata(baseMetadata, name, uncompressed)) @@ -1105,19 +1104,19 @@ namespace SixLabors.ImageSharp.Formats.Png ReadOnlySpan dataSpan = data.AsSpan(); dataSpan = dataSpan.TrimStart(); - if (!StringEqualsInsensitive(dataSpan.Slice(0, 4), "exif".AsSpan())) + if (!StringEqualsInsensitive(dataSpan[..4], "exif".AsSpan())) { // "exif" identifier is missing from the beginning of the text chunk return false; } // Skip to the data length - dataSpan = dataSpan.Slice(4).TrimStart(); + dataSpan = dataSpan[4..].TrimStart(); int dataLengthEnd = dataSpan.IndexOf('\n'); - int dataLength = ParseInt32(dataSpan.Slice(0, dataSpan.IndexOf('\n'))); + int dataLength = ParseInt32(dataSpan[..dataSpan.IndexOf('\n')]); // Skip to the hex-encoded data - dataSpan = dataSpan.Slice(dataLengthEnd).Trim(); + dataSpan = dataSpan[dataLengthEnd..].Trim(); // Sequence of bytes for the exif header ("Exif" ASCII and two zero bytes). // This doesn't actually allocate. @@ -1142,15 +1141,15 @@ namespace SixLabors.ImageSharp.Formats.Png tempExifBuf = new byte[exifHeader.Length]; } - HexConverter.HexStringToBytes(dataSpan.Slice(0, exifHeader.Length * 2), tempExifBuf); - if (!tempExifBuf.AsSpan().Slice(0, exifHeader.Length).SequenceEqual(exifHeader)) + HexConverter.HexStringToBytes(dataSpan[..(exifHeader.Length * 2)], tempExifBuf); + if (!tempExifBuf.AsSpan()[..exifHeader.Length].SequenceEqual(exifHeader)) { // Exif header in the hex data is not valid return false; } // Skip over the exif header we just tested - dataSpan = dataSpan.Slice(exifHeader.Length * 2); + dataSpan = dataSpan[(exifHeader.Length * 2)..]; dataLength -= exifHeader.Length; // Load the hex-encoded data, one line at a time @@ -1161,12 +1160,12 @@ namespace SixLabors.ImageSharp.Formats.Png int newlineIndex = dataSpan.IndexOf('\n'); if (newlineIndex != -1) { - lineSpan = dataSpan.Slice(0, newlineIndex); + lineSpan = dataSpan[..newlineIndex]; } - i += HexConverter.HexStringToBytes(lineSpan, exifBlob.AsSpan().Slice(i)); + i += HexConverter.HexStringToBytes(lineSpan, exifBlob.AsSpan()[i..]); - dataSpan = dataSpan.Slice(newlineIndex + 1); + dataSpan = dataSpan[(newlineIndex + 1)..]; } } catch @@ -1174,7 +1173,7 @@ namespace SixLabors.ImageSharp.Formats.Png return false; } - this.MergeOrSetExifProfile(metadata, new ExifProfile(exifBlob), replaceExistingKeys: false); + MergeOrSetExifProfile(metadata, new ExifProfile(exifBlob), replaceExistingKeys: false); return true; } @@ -1198,13 +1197,13 @@ namespace SixLabors.ImageSharp.Formats.Png return; } - ReadOnlySpan keywordBytes = data.Slice(0, zeroIndex); - if (!this.TryReadTextKeyword(keywordBytes, out string name)) + ReadOnlySpan keywordBytes = data[..zeroIndex]; + if (!TryReadTextKeyword(keywordBytes, out string name)) { return; } - ReadOnlySpan compressedData = data.Slice(zeroIndex + 2); + ReadOnlySpan compressedData = data[(zeroIndex + 2)..]; if (this.TryUncompressZlibData(compressedData, out byte[] iccpProfileBytes)) { @@ -1222,29 +1221,27 @@ namespace SixLabors.ImageSharp.Formats.Png { fixed (byte* compressedDataBase = compressedData) { - using (IMemoryOwner destBuffer = this.memoryAllocator.Allocate(this.Configuration.StreamProcessingBufferSize)) - using (var memoryStreamOutput = new MemoryStream(compressedData.Length)) - using (var memoryStreamInput = new UnmanagedMemoryStream(compressedDataBase, compressedData.Length)) - using (var bufferedStream = new BufferedReadStream(this.Configuration, memoryStreamInput)) - using (var inflateStream = new ZlibInflateStream(bufferedStream)) + using IMemoryOwner destBuffer = this.memoryAllocator.Allocate(this.Configuration.StreamProcessingBufferSize); + using var memoryStreamOutput = new MemoryStream(compressedData.Length); + using var memoryStreamInput = new UnmanagedMemoryStream(compressedDataBase, compressedData.Length); + using var bufferedStream = new BufferedReadStream(this.Configuration, memoryStreamInput); + using var inflateStream = new ZlibInflateStream(bufferedStream); + Span destUncompressedData = destBuffer.GetSpan(); + if (!inflateStream.AllocateNewBytes(compressedData.Length, false)) { - Span destUncompressedData = destBuffer.GetSpan(); - if (!inflateStream.AllocateNewBytes(compressedData.Length, false)) - { - uncompressedBytesArray = Array.Empty(); - return false; - } - - int bytesRead = inflateStream.CompressedStream.Read(destUncompressedData, 0, destUncompressedData.Length); - while (bytesRead != 0) - { - memoryStreamOutput.Write(destUncompressedData.Slice(0, bytesRead)); - bytesRead = inflateStream.CompressedStream.Read(destUncompressedData, 0, destUncompressedData.Length); - } + uncompressedBytesArray = Array.Empty(); + return false; + } - uncompressedBytesArray = memoryStreamOutput.ToArray(); - return true; + int bytesRead = inflateStream.CompressedStream.Read(destUncompressedData, 0, destUncompressedData.Length); + while (bytesRead != 0) + { + memoryStreamOutput.Write(destUncompressedData[..bytesRead]); + bytesRead = inflateStream.CompressedStream.Read(destUncompressedData, 0, destUncompressedData.Length); } + + uncompressedBytesArray = memoryStreamOutput.ToArray(); + return true; } } @@ -1256,31 +1253,14 @@ namespace SixLabors.ImageSharp.Formats.Png /// The second to compare. /// True if the spans were identical, false otherwise. private static bool StringEqualsInsensitive(ReadOnlySpan span1, ReadOnlySpan span2) - { -#pragma warning disable IDE0022 // Use expression body for methods -#if NETSTANDARD2_1 || NETCOREAPP2_1_OR_GREATER - return span1.Equals(span2, StringComparison.OrdinalIgnoreCase); -#else - return span1.ToString().Equals(span2.ToString(), StringComparison.OrdinalIgnoreCase); -#endif -#pragma warning restore IDE0022 // Use expression body for methods - } + => span1.Equals(span2, StringComparison.OrdinalIgnoreCase); /// /// int.Parse() a ReadOnlySpan<char>, with a fallback for older frameworks. /// /// The to parse. /// The parsed . - private static int ParseInt32(ReadOnlySpan span) - { -#pragma warning disable IDE0022 // Use expression body for methods -#if NETSTANDARD2_1 || NETCOREAPP2_1_OR_GREATER - return int.Parse(span); -#else - return int.Parse(span.ToString()); -#endif -#pragma warning restore IDE0022 // Use expression body for methods - } + private static int ParseInt32(ReadOnlySpan span) => int.Parse(span); /// /// Sets the in to , @@ -1291,7 +1271,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// If already contains an , /// controls whether existing exif tags in will be overwritten with any conflicting /// tags from . - private void MergeOrSetExifProfile(ImageMetadata metadata, ExifProfile newProfile, bool replaceExistingKeys) + private static void MergeOrSetExifProfile(ImageMetadata metadata, ExifProfile newProfile, bool replaceExistingKeys) { if (metadata.ExifProfile is null) { @@ -1331,13 +1311,13 @@ namespace SixLabors.ImageSharp.Formats.Png PngMetadata pngMetadata = metadata.GetPngMetadata(); int zeroIndexKeyword = data.IndexOf((byte)0); - if (zeroIndexKeyword < PngConstants.MinTextKeywordLength || zeroIndexKeyword > PngConstants.MaxTextKeywordLength) + if (zeroIndexKeyword is < PngConstants.MinTextKeywordLength or > PngConstants.MaxTextKeywordLength) { return; } byte compressionFlag = data[zeroIndexKeyword + 1]; - if (!(compressionFlag == 0 || compressionFlag == 1)) + if (compressionFlag is not (0 or 1)) { return; } @@ -1350,7 +1330,7 @@ namespace SixLabors.ImageSharp.Formats.Png } int langStartIdx = zeroIndexKeyword + 3; - int languageLength = data.Slice(langStartIdx).IndexOf((byte)0); + int languageLength = data[langStartIdx..].IndexOf((byte)0); if (languageLength < 0) { return; @@ -1359,11 +1339,11 @@ namespace SixLabors.ImageSharp.Formats.Png string language = PngConstants.LanguageEncoding.GetString(data.Slice(langStartIdx, languageLength)); int translatedKeywordStartIdx = langStartIdx + languageLength + 1; - int translatedKeywordLength = data.Slice(translatedKeywordStartIdx).IndexOf((byte)0); + int translatedKeywordLength = data[translatedKeywordStartIdx..].IndexOf((byte)0); string translatedKeyword = PngConstants.TranslatedEncoding.GetString(data.Slice(translatedKeywordStartIdx, translatedKeywordLength)); - ReadOnlySpan keywordBytes = data.Slice(0, zeroIndexKeyword); - if (!this.TryReadTextKeyword(keywordBytes, out string keyword)) + ReadOnlySpan keywordBytes = data[..zeroIndexKeyword]; + if (!TryReadTextKeyword(keywordBytes, out string keyword)) { return; } @@ -1371,21 +1351,21 @@ namespace SixLabors.ImageSharp.Formats.Png int dataStartIdx = translatedKeywordStartIdx + translatedKeywordLength + 1; if (compressionFlag == 1) { - ReadOnlySpan compressedData = data.Slice(dataStartIdx); + ReadOnlySpan compressedData = data[dataStartIdx..]; if (this.TryUncompressTextData(compressedData, PngConstants.TranslatedEncoding, out string uncompressed)) { pngMetadata.TextData.Add(new PngTextData(keyword, uncompressed, language, translatedKeyword)); } } - else if (this.IsXmpTextData(keywordBytes)) + else if (IsXmpTextData(keywordBytes)) { - var xmpProfile = new XmpProfile(data.Slice(dataStartIdx).ToArray()); + var xmpProfile = new XmpProfile(data[dataStartIdx..].ToArray()); metadata.XmpProfile = xmpProfile; } else { - string value = PngConstants.TranslatedEncoding.GetString(data.Slice(dataStartIdx)); + string value = PngConstants.TranslatedEncoding.GetString(data[dataStartIdx..]); pngMetadata.TextData.Add(new PngTextData(keyword, value, language, translatedKeyword)); } } @@ -1620,14 +1600,14 @@ namespace SixLabors.ImageSharp.Formats.Png /// The keyword bytes. /// The name. /// True, if the keyword could be read and is valid. - private bool TryReadTextKeyword(ReadOnlySpan keywordBytes, out string name) + private static bool TryReadTextKeyword(ReadOnlySpan keywordBytes, out string name) { name = string.Empty; // Keywords shall contain only printable Latin-1. foreach (byte c in keywordBytes) { - if (!((c >= 32 && c <= 126) || (c >= 161 && c <= 255))) + if (c is not ((>= 32 and <= 126) or (>= 161 and <= 255))) { return false; } @@ -1635,21 +1615,12 @@ namespace SixLabors.ImageSharp.Formats.Png // Keywords should not be empty or have leading or trailing whitespace. name = PngConstants.Encoding.GetString(keywordBytes); - if (string.IsNullOrWhiteSpace(name) || name.StartsWith(" ") || name.EndsWith(" ")) - { - return false; - } - - return true; + return !string.IsNullOrWhiteSpace(name) && !name.StartsWith(" ") && !name.EndsWith(" "); } - private bool IsXmpTextData(ReadOnlySpan keywordBytes) => keywordBytes.SequenceEqual(PngConstants.XmpKeyword); + private static bool IsXmpTextData(ReadOnlySpan keywordBytes) => keywordBytes.SequenceEqual(PngConstants.XmpKeyword); private void SwapScanlineBuffers() - { - IMemoryOwner temp = this.previousScanline; - this.previousScanline = this.scanline; - this.scanline = temp; - } + => (this.scanline, this.previousScanline) = (this.previousScanline, this.scanline); } } diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index 9ae8f299a..eb1d4be9b 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -694,7 +694,7 @@ namespace SixLabors.ImageSharp.Formats.Png int bytesWritten = PngConstants.XmpKeyword.Length; // Write the iTxt header (all zeros in this case). - Span iTxtHeader = payload.Slice(bytesWritten); + Span iTxtHeader = payload[bytesWritten..]; iTxtHeader[4] = 0; iTxtHeader[3] = 0; iTxtHeader[2] = 0; @@ -703,7 +703,7 @@ namespace SixLabors.ImageSharp.Formats.Png bytesWritten += 5; // And the XMP data itself. - xmpData.CopyTo(payload.Slice(bytesWritten)); + xmpData.CopyTo(payload[bytesWritten..]); this.WriteChunk(stream, PngChunkType.InternationalText, payload); } } @@ -731,7 +731,7 @@ namespace SixLabors.ImageSharp.Formats.Png int bytesWritten = ColorProfileName.Length; outputBytes[bytesWritten++] = 0; // Null separator. outputBytes[bytesWritten++] = 0; // Compression. - compressedData.CopyTo(outputBytes.Slice(bytesWritten)); + compressedData.CopyTo(outputBytes[bytesWritten..]); this.WriteChunk(stream, PngChunkType.EmbeddedColorProfile, outputBytes); } } @@ -792,13 +792,13 @@ namespace SixLabors.ImageSharp.Formats.Png } outputBytes[bytesWritten++] = 0; - languageTag.CopyTo(outputBytes.Slice(bytesWritten)); + languageTag.CopyTo(outputBytes[bytesWritten..]); bytesWritten += languageTag.Length; outputBytes[bytesWritten++] = 0; - translatedKeyword.CopyTo(outputBytes.Slice(bytesWritten)); + translatedKeyword.CopyTo(outputBytes[bytesWritten..]); bytesWritten += translatedKeyword.Length; outputBytes[bytesWritten++] = 0; - textBytes.CopyTo(outputBytes.Slice(bytesWritten)); + textBytes.CopyTo(outputBytes[bytesWritten..]); this.WriteChunk(stream, PngChunkType.InternationalText, outputBytes); } } @@ -816,7 +816,7 @@ namespace SixLabors.ImageSharp.Formats.Png int bytesWritten = textData.Keyword.Length; outputBytes[bytesWritten++] = 0; // Null separator. outputBytes[bytesWritten++] = 0; // Compression. - compressedData.CopyTo(outputBytes.Slice(bytesWritten)); + compressedData.CopyTo(outputBytes[bytesWritten..]); this.WriteChunk(stream, PngChunkType.CompressedText, outputBytes); } } @@ -830,7 +830,7 @@ namespace SixLabors.ImageSharp.Formats.Png PngConstants.Encoding.GetBytes(textData.Keyword).CopyTo(outputBytes); int bytesWritten = textData.Keyword.Length; outputBytes[bytesWritten++] = 0; - PngConstants.Encoding.GetBytes(textData.Value).CopyTo(outputBytes.Slice(bytesWritten)); + PngConstants.Encoding.GetBytes(textData.Value).CopyTo(outputBytes[bytesWritten..]); this.WriteChunk(stream, PngChunkType.Text, outputBytes); } } diff --git a/src/ImageSharp/Formats/Png/PngHeader.cs b/src/ImageSharp/Formats/Png/PngHeader.cs index da747a189..0837e0063 100644 --- a/src/ImageSharp/Formats/Png/PngHeader.cs +++ b/src/ImageSharp/Formats/Png/PngHeader.cs @@ -116,7 +116,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// The buffer to write to. public void WriteTo(Span buffer) { - BinaryPrimitives.WriteInt32BigEndian(buffer.Slice(0, 4), this.Width); + BinaryPrimitives.WriteInt32BigEndian(buffer[..4], this.Width); BinaryPrimitives.WriteInt32BigEndian(buffer.Slice(4, 4), this.Height); buffer[8] = this.BitDepth; @@ -134,7 +134,7 @@ namespace SixLabors.ImageSharp.Formats.Png public static PngHeader Parse(ReadOnlySpan data) { return new PngHeader( - width: BinaryPrimitives.ReadInt32BigEndian(data.Slice(0, 4)), + width: BinaryPrimitives.ReadInt32BigEndian(data[..4]), height: BinaryPrimitives.ReadInt32BigEndian(data.Slice(4, 4)), bitDepth: data[8], colorType: (PngColorType)data[9], diff --git a/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs b/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs index eaf4e63a0..eabf14768 100644 --- a/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs +++ b/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs @@ -772,7 +772,7 @@ namespace SixLabors.ImageSharp.Formats.Tga int bufferIdx = uncompressedPixels * bytesPerPixel; for (int i = 0; i < runLength + 1; i++, uncompressedPixels++) { - pixel.AsSpan().CopyTo(buffer.Slice(bufferIdx)); + pixel.AsSpan().CopyTo(buffer[bufferIdx..]); bufferIdx += bytesPerPixel; } } @@ -784,7 +784,7 @@ namespace SixLabors.ImageSharp.Formats.Tga for (int i = 0; i < runLength + 1; i++, uncompressedPixels++) { this.currentStream.Read(pixel, 0, bytesPerPixel); - pixel.AsSpan().CopyTo(buffer.Slice(bufferIdx)); + pixel.AsSpan().CopyTo(buffer[bufferIdx..]); bufferIdx += bytesPerPixel; } } diff --git a/src/ImageSharp/Formats/Tiff/Compression/Compressors/PackBitsCompressor.cs b/src/ImageSharp/Formats/Tiff/Compression/Compressors/PackBitsCompressor.cs index 01613222e..472ceb21e 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/Compressors/PackBitsCompressor.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/Compressors/PackBitsCompressor.cs @@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors { Span row = rows.Slice(i * this.BytesPerRow, this.BytesPerRow); int size = PackBitsWriter.PackBits(row, span); - this.Output.Write(span.Slice(0, size)); + this.Output.Write(span[..size]); } } diff --git a/src/ImageSharp/Formats/Tiff/Compression/Compressors/PackBitsWriter.cs b/src/ImageSharp/Formats/Tiff/Compression/Compressors/PackBitsWriter.cs index 06e2d663c..5c9a70729 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/Compressors/PackBitsWriter.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/Compressors/PackBitsWriter.cs @@ -65,7 +65,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors int literalRunStart = end - literalRunLength; sbyte runLength = (sbyte)(literalRunLength - 1); compressedRowSpan[compressedRowPos] = (byte)runLength; - rowSpan.Slice(literalRunStart, literalRunLength).CopyTo(compressedRowSpan.Slice(compressedRowPos + 1)); + rowSpan.Slice(literalRunStart, literalRunLength).CopyTo(compressedRowSpan[(compressedRowPos + 1)..]); } private static void WriteRun(ReadOnlySpan rowSpan, int start, int runLength, Span compressedRowSpan, int compressedRowPos) diff --git a/src/ImageSharp/Formats/Tiff/Compression/Compressors/TiffCcittCompressor.cs b/src/ImageSharp/Formats/Tiff/Compression/Compressors/TiffCcittCompressor.cs index 511c6914f..b1f5c85d9 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/Compressors/TiffCcittCompressor.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/Compressors/TiffCcittCompressor.cs @@ -511,7 +511,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors // Write the compressed data to the stream. int bytesToWrite = this.bitPosition != 0 ? this.bytePosition + 1 : this.bytePosition; - this.Output.Write(compressedData.Slice(0, bytesToWrite)); + this.Output.Write(compressedData[..bytesToWrite]); } /// diff --git a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/CcittReferenceScanline.cs b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/CcittReferenceScanline.cs index bb2828b91..1b66cbf80 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/CcittReferenceScanline.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/CcittReferenceScanline.cs @@ -100,7 +100,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors offset = a0; } - ReadOnlySpan searchSpace = this.scanLine.Slice(offset); + ReadOnlySpan searchSpace = this.scanLine[offset..]; byte searchByte = (byte)~a0Byte; int index = searchSpace.IndexOf(searchByte); if (index < 0) @@ -120,7 +120,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors return this.scanLine.Length; } - searchSpace = searchSpace.Slice(index); + searchSpace = searchSpace[index..]; offset += index; index = searchSpace.IndexOf((byte)~searchByte); if (index < 0) @@ -143,7 +143,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors byte searchByte = (byte)~this.scanLine[b1]; int offset = b1 + 1; - ReadOnlySpan searchSpace = this.scanLine.Slice(offset); + ReadOnlySpan searchSpace = this.scanLine[offset..]; int index = searchSpace.IndexOf(searchByte); if (index == -1) { diff --git a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/JpegTiffCompression.cs b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/JpegTiffCompression.cs index 0d9a6ba13..4a2909fdf 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/JpegTiffCompression.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/JpegTiffCompression.cs @@ -105,7 +105,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors { Span pixelRowSpan = pixelBuffer.DangerousGetRowSpan(y); Span rgbBytes = MemoryMarshal.AsBytes(pixelRowSpan); - rgbBytes.CopyTo(buffer.Slice(offset)); + rgbBytes.CopyTo(buffer[offset..]); offset += rgbBytes.Length; } } @@ -117,7 +117,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors { Span pixelRowSpan = pixelBuffer.DangerousGetRowSpan(y); Span rgbBytes = MemoryMarshal.AsBytes(pixelRowSpan); - rgbBytes.CopyTo(buffer.Slice(offset)); + rgbBytes.CopyTo(buffer[offset..]); offset += rgbBytes.Length; } } diff --git a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/PackBitsTiffCompression.cs b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/PackBitsTiffCompression.cs index 9df331b6e..c3ba82e8f 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/PackBitsTiffCompression.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/PackBitsTiffCompression.cs @@ -59,7 +59,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors TiffThrowHelper.ThrowImageFormatException("Tiff packbits compression error: not enough data."); } - compressedData.Slice(literalOffset, literalLength).CopyTo(buffer.Slice(decompressedOffset)); + compressedData.Slice(literalOffset, literalLength).CopyTo(buffer[decompressedOffset..]); compressedOffset += literalLength + 1; decompressedOffset += literalLength; diff --git a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/T6TiffCompression.cs b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/T6TiffCompression.cs index 2373e7b9b..41bea9de8 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/T6TiffCompression.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/T6TiffCompression.cs @@ -55,7 +55,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors buffer.Clear(); using System.Buffers.IMemoryOwner scanLineBuffer = this.Allocator.Allocate(this.width * 2); - Span scanLine = scanLineBuffer.GetSpan().Slice(0, this.width); + Span scanLine = scanLineBuffer.GetSpan()[..this.width]; Span referenceScanLineSpan = scanLineBuffer.GetSpan().Slice(this.width, this.width); var bitReader = new T6BitReader(stream, this.FillOrder, byteCount); @@ -154,7 +154,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors case CcittTwoDimensionalCodeType.Pass: int b2 = referenceScanline.FindB2(b1); - scanline.Slice(unpacked, b2 - unpacked).Fill(fillByte); + scanline[unpacked..b2].Fill(fillByte); unpacked = b2; a0 = b2; break; @@ -189,7 +189,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors case CcittTwoDimensionalCodeType.Vertical0: a1 = b1; - scanline.Slice(unpacked, a1 - unpacked).Fill(fillByte); + scanline[unpacked..a1].Fill(fillByte); unpacked = a1; a0 = a1; fillByte = (byte)~fillByte; @@ -198,7 +198,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors case CcittTwoDimensionalCodeType.VerticalR1: a1 = b1 + 1; - scanline.Slice(unpacked, a1 - unpacked).Fill(fillByte); + scanline[unpacked..a1].Fill(fillByte); unpacked = a1; a0 = a1; fillByte = (byte)~fillByte; @@ -207,7 +207,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors case CcittTwoDimensionalCodeType.VerticalR2: a1 = b1 + 2; - scanline.Slice(unpacked, a1 - unpacked).Fill(fillByte); + scanline[unpacked..a1].Fill(fillByte); unpacked = a1; a0 = a1; fillByte = (byte)~fillByte; @@ -216,7 +216,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors case CcittTwoDimensionalCodeType.VerticalR3: a1 = b1 + 3; - scanline.Slice(unpacked, a1 - unpacked).Fill(fillByte); + scanline[unpacked..a1].Fill(fillByte); unpacked = a1; a0 = a1; fillByte = (byte)~fillByte; @@ -225,7 +225,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors case CcittTwoDimensionalCodeType.VerticalL1: a1 = b1 - 1; - scanline.Slice(unpacked, a1 - unpacked).Fill(fillByte); + scanline[unpacked..a1].Fill(fillByte); unpacked = a1; a0 = a1; fillByte = (byte)~fillByte; @@ -234,7 +234,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors case CcittTwoDimensionalCodeType.VerticalL2: a1 = b1 - 2; - scanline.Slice(unpacked, a1 - unpacked).Fill(fillByte); + scanline[unpacked..a1].Fill(fillByte); unpacked = a1; a0 = a1; fillByte = (byte)~fillByte; @@ -243,7 +243,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors case CcittTwoDimensionalCodeType.VerticalL3: a1 = b1 - 3; - scanline.Slice(unpacked, a1 - unpacked).Fill(fillByte); + scanline[unpacked..a1].Fill(fillByte); unpacked = a1; a0 = a1; fillByte = (byte)~fillByte; diff --git a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/WebpTiffCompression.cs b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/WebpTiffCompression.cs index 0d63382ff..5a70baa09 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/WebpTiffCompression.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/WebpTiffCompression.cs @@ -42,7 +42,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors { Span pixelRowSpan = pixelBuffer.DangerousGetRowSpan(y); Span rgbBytes = MemoryMarshal.AsBytes(pixelRowSpan); - rgbBytes.CopyTo(buffer.Slice(offset)); + rgbBytes.CopyTo(buffer[offset..]); offset += rgbBytes.Length; } } diff --git a/src/ImageSharp/Formats/Tiff/Compression/HorizontalPredictor.cs b/src/ImageSharp/Formats/Tiff/Compression/HorizontalPredictor.cs index ab8f51844..406d6ef74 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/HorizontalPredictor.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/HorizontalPredictor.cs @@ -235,7 +235,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression for (int y = 0; y < height; y++) { Span rowBytes = pixelBytes.Slice(y * rowBytesCount, rowBytesCount); - Span rowRgb = MemoryMarshal.Cast(rowBytes).Slice(0, width); + Span rowRgb = MemoryMarshal.Cast(rowBytes)[..width]; ref Rgb24 rowRgbBase = ref MemoryMarshal.GetReference(rowRgb); byte r = rowRgbBase.R; byte g = rowRgbBase.G; @@ -260,7 +260,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression for (int y = 0; y < height; y++) { Span rowBytes = pixelBytes.Slice(y * rowBytesCount, rowBytesCount); - Span rowRgb = MemoryMarshal.Cast(rowBytes).Slice(0, width); + Span rowRgb = MemoryMarshal.Cast(rowBytes)[..width]; ref Rgba32 rowRgbBase = ref MemoryMarshal.GetReference(rowRgb); byte r = rowRgbBase.R; byte g = rowRgbBase.G; diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZero24TiffColor{TPixel}.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZero24TiffColor{TPixel}.cs index e9be797b4..d68d70e9b 100644 --- a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZero24TiffColor{TPixel}.cs +++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZero24TiffColor{TPixel}.cs @@ -31,7 +31,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation Span buffer = stackalloc byte[4]; int bufferStartIdx = this.isBigEndian ? 1 : 0; - Span bufferSpan = buffer.Slice(bufferStartIdx); + Span bufferSpan = buffer[bufferStartIdx..]; int offset = 0; for (int y = top; y < top + height; y++) { diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgb242424TiffColor{TPixel}.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgb242424TiffColor{TPixel}.cs index b74c43ceb..10c61a6d0 100644 --- a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgb242424TiffColor{TPixel}.cs +++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgb242424TiffColor{TPixel}.cs @@ -32,7 +32,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation Span buffer = stackalloc byte[4]; int bufferStartIdx = this.isBigEndian ? 1 : 0; - Span bufferSpan = buffer.Slice(bufferStartIdx); + Span bufferSpan = buffer[bufferStartIdx..]; for (int y = top; y < top + height; y++) { Span pixelRow = pixels.DangerousGetRowSpan(y).Slice(left, width); diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgb24PlanarTiffColor{TPixel}.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgb24PlanarTiffColor{TPixel}.cs index 94ba69785..074661095 100644 --- a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgb24PlanarTiffColor{TPixel}.cs +++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgb24PlanarTiffColor{TPixel}.cs @@ -35,7 +35,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation Span redData = data[0].GetSpan(); Span greenData = data[1].GetSpan(); Span blueData = data[2].GetSpan(); - Span bufferSpan = buffer.Slice(bufferStartIdx); + Span bufferSpan = buffer[bufferStartIdx..]; int offset = 0; for (int y = top; y < top + height; y++) diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgba24242424TiffColor{TPixel}.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgba24242424TiffColor{TPixel}.cs index ab5a21ac2..be10495e7 100644 --- a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgba24242424TiffColor{TPixel}.cs +++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgba24242424TiffColor{TPixel}.cs @@ -42,7 +42,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation Span buffer = stackalloc byte[4]; int bufferStartIdx = this.isBigEndian ? 1 : 0; - Span bufferSpan = buffer.Slice(bufferStartIdx); + Span bufferSpan = buffer[bufferStartIdx..]; for (int y = top; y < top + height; y++) { Span pixelRow = pixels.DangerousGetRowSpan(y).Slice(left, width); diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgba24PlanarTiffColor{TPixel}.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgba24PlanarTiffColor{TPixel}.cs index 47c2ae5ad..45f530d62 100644 --- a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgba24PlanarTiffColor{TPixel}.cs +++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgba24PlanarTiffColor{TPixel}.cs @@ -43,7 +43,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation Span greenData = data[1].GetSpan(); Span blueData = data[2].GetSpan(); Span alphaData = data[3].GetSpan(); - Span bufferSpan = buffer.Slice(bufferStartIdx); + Span bufferSpan = buffer[bufferStartIdx..]; bool hasAssociatedAlpha = this.extraSamplesType.HasValue && this.extraSamplesType == TiffExtraSampleType.AssociatedAlphaData; int offset = 0; diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero24TiffColor{TPixel}.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero24TiffColor{TPixel}.cs index 2caede066..36832a198 100644 --- a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero24TiffColor{TPixel}.cs +++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero24TiffColor{TPixel}.cs @@ -32,7 +32,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation int bufferStartIdx = this.isBigEndian ? 1 : 0; const uint maxValue = 0xFFFFFF; - Span bufferSpan = buffer.Slice(bufferStartIdx); + Span bufferSpan = buffer[bufferStartIdx..]; int offset = 0; for (int y = top; y < top + height; y++) { diff --git a/src/ImageSharp/Formats/Tiff/Writers/TiffBiColorWriter{TPixel}.cs b/src/ImageSharp/Formats/Tiff/Writers/TiffBiColorWriter{TPixel}.cs index 8d9c6c2b4..926dbf1c0 100644 --- a/src/ImageSharp/Formats/Tiff/Writers/TiffBiColorWriter{TPixel}.cs +++ b/src/ImageSharp/Formats/Tiff/Writers/TiffBiColorWriter{TPixel}.cs @@ -55,7 +55,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Writers grayRowIdx++; } - compressor.CompressStrip(pixelAsGraySpan.Slice(0, stripPixels), height); + compressor.CompressStrip(pixelAsGraySpan[..stripPixels], height); }); } else @@ -76,7 +76,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Writers { int bitIndex = 0; int byteIndex = 0; - Span outputRow = rows.Slice(outputRowIdx * this.BytesPerRow); + Span outputRow = rows[(outputRowIdx * this.BytesPerRow)..]; Span pixelsBlackWhiteRow = blackWhiteBuffer.DangerousGetRowSpan(row); PixelOperations.Instance.ToL8Bytes(this.Configuration, pixelsBlackWhiteRow, pixelAsGraySpan, width); for (int x = 0; x < this.Image.Width; x++) diff --git a/src/ImageSharp/Formats/Tiff/Writers/TiffCompositeColorWriter{TPixel}.cs b/src/ImageSharp/Formats/Tiff/Writers/TiffCompositeColorWriter{TPixel}.cs index 19b5e5f88..5bb39771e 100644 --- a/src/ImageSharp/Formats/Tiff/Writers/TiffCompositeColorWriter{TPixel}.cs +++ b/src/ImageSharp/Formats/Tiff/Writers/TiffCompositeColorWriter{TPixel}.cs @@ -31,7 +31,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Writers this.rowBuffer.Clear(); - Span outputRowSpan = this.rowBuffer.GetSpan().Slice(0, this.BytesPerRow * height); + Span outputRowSpan = this.rowBuffer.GetSpan()[..(this.BytesPerRow * height)]; int width = this.Image.Width; using IMemoryOwner stripPixelBuffer = this.MemoryAllocator.Allocate(height * width); diff --git a/src/ImageSharp/Formats/Tiff/Writers/TiffPaletteWriter{TPixel}.cs b/src/ImageSharp/Formats/Tiff/Writers/TiffPaletteWriter{TPixel}.cs index 8e123c22f..19d071c9e 100644 --- a/src/ImageSharp/Formats/Tiff/Writers/TiffPaletteWriter{TPixel}.cs +++ b/src/ImageSharp/Formats/Tiff/Writers/TiffPaletteWriter{TPixel}.cs @@ -83,7 +83,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Writers } } - compressor.CompressStrip(rows4bit.Slice(0, idx4bitRows), height); + compressor.CompressStrip(rows4bit[..idx4bitRows], height); } else { @@ -99,7 +99,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Writers indexedPixelsRowIdx++; } - compressor.CompressStrip(indexedPixels.Slice(0, stripPixels), height); + compressor.CompressStrip(indexedPixels[..stripPixels], height); } } @@ -119,7 +119,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Writers int quantizedColorBytes = quantizedColors.Length * 3 * 2; // In the ColorMap, black is represented by 0, 0, 0 and white is represented by 65535, 65535, 65535. - Span quantizedColorRgb48 = MemoryMarshal.Cast(colorPalette.Slice(0, quantizedColorBytes)); + Span quantizedColorRgb48 = MemoryMarshal.Cast(colorPalette[..quantizedColorBytes]); PixelOperations.Instance.ToRgb48(this.Configuration, quantizedColors, quantizedColorRgb48); // It can happen that the quantized colors are less than the expected maximum per channel. diff --git a/src/ImageSharp/Formats/Webp/BitReader/BitReaderBase.cs b/src/ImageSharp/Formats/Webp/BitReader/BitReaderBase.cs index 50af4b19d..ae8ac31dd 100644 --- a/src/ImageSharp/Formats/Webp/BitReader/BitReaderBase.cs +++ b/src/ImageSharp/Formats/Webp/BitReader/BitReaderBase.cs @@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.BitReader { this.Data = memoryAllocator.Allocate(bytesToRead); Span dataSpan = this.Data.Memory.Span; - input.Read(dataSpan.Slice(0, bytesToRead), 0, bytesToRead); + input.Read(dataSpan[..bytesToRead], 0, bytesToRead); } protected virtual void Dispose(bool disposing) diff --git a/src/ImageSharp/Formats/Webp/BitWriter/BitWriterBase.cs b/src/ImageSharp/Formats/Webp/BitWriter/BitWriterBase.cs index ecf87d8b5..428403f60 100644 --- a/src/ImageSharp/Formats/Webp/BitWriter/BitWriterBase.cs +++ b/src/ImageSharp/Formats/Webp/BitWriter/BitWriterBase.cs @@ -258,9 +258,9 @@ namespace SixLabors.ImageSharp.Formats.Webp.BitWriter BinaryPrimitives.WriteUInt32LittleEndian(buf, flags); stream.Write(buf); BinaryPrimitives.WriteUInt32LittleEndian(buf, width - 1); - stream.Write(buf.Slice(0, 3)); + stream.Write(buf[..3]); BinaryPrimitives.WriteUInt32LittleEndian(buf, height - 1); - stream.Write(buf.Slice(0, 3)); + stream.Write(buf[..3]); } } } diff --git a/src/ImageSharp/Formats/Webp/BitWriter/Vp8BitWriter.cs b/src/ImageSharp/Formats/Webp/BitWriter/Vp8BitWriter.cs index 7b9a79a2e..81cb9cc24 100644 --- a/src/ImageSharp/Formats/Webp/BitWriter/Vp8BitWriter.cs +++ b/src/ImageSharp/Formats/Webp/BitWriter/Vp8BitWriter.cs @@ -215,7 +215,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.BitWriter { if (this.PutBit(s >= 2, p[0])) { - p = p.Slice(1); + p = p[1..]; } this.PutBit(s & 1, p[1]); @@ -711,7 +711,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.BitWriter Span vp8ChunkHeader = stackalloc byte[WebpConstants.ChunkHeaderSize]; WebpConstants.Vp8MagicBytes.AsSpan().CopyTo(vp8ChunkHeader); - BinaryPrimitives.WriteUInt32LittleEndian(vp8ChunkHeader.Slice(4), size); + BinaryPrimitives.WriteUInt32LittleEndian(vp8ChunkHeader[4..], size); stream.Write(vp8ChunkHeader); } diff --git a/src/ImageSharp/Formats/Webp/Lossless/BackwardReferenceEncoder.cs b/src/ImageSharp/Formats/Webp/Lossless/BackwardReferenceEncoder.cs index 8c5aa43f5..88d6261cf 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/BackwardReferenceEncoder.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/BackwardReferenceEncoder.cs @@ -252,7 +252,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless BackwardReferencesHashChainDistanceOnly(xSize, ySize, memoryAllocator, bgra, cacheBits, hashChain, refsSrc, distArrayBuffer); int chosenPathSize = TraceBackwards(distArray, distArraySize); - Span chosenPath = distArray.Slice(distArraySize - chosenPathSize); + Span chosenPath = distArray[(distArraySize - chosenPathSize)..]; BackwardReferencesHashChainFollowChosenPath(bgra, cacheBits, chosenPath, chosenPathSize, hashChain, refsDst); } @@ -741,8 +741,8 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless while (i < pixelCount) { int maxLen = LosslessUtils.MaxFindCopyLength(pixelCount - i); - int rleLen = LosslessUtils.FindMatchLength(bgra.Slice(i), bgra.Slice(i - 1), 0, maxLen); - int prevRowLen = i < xSize ? 0 : LosslessUtils.FindMatchLength(bgra.Slice(i), bgra.Slice(i - xSize), 0, maxLen); + int rleLen = LosslessUtils.FindMatchLength(bgra[i..], bgra[(i - 1)..], 0, maxLen); + int prevRowLen = i < xSize ? 0 : LosslessUtils.FindMatchLength(bgra[i..], bgra[(i - xSize)..], 0, maxLen); if (rleLen >= prevRowLen && rleLen >= MinLength) { refs.Add(PixOrCopy.CreateCopy(1, (ushort)rleLen)); diff --git a/src/ImageSharp/Formats/Webp/Lossless/HuffmanUtils.cs b/src/ImageSharp/Formats/Webp/Lossless/HuffmanUtils.cs index 7bd206391..515ae7a7d 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/HuffmanUtils.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/HuffmanUtils.cs @@ -402,7 +402,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless BitsUsed = len, Value = (uint)sorted[symbol++] }; - ReplicateValue(table.Slice(key), step, tableSize, huffmanCode); + ReplicateValue(table[key..], step, tableSize, huffmanCode); key = GetNextKey(key, len); } @@ -426,7 +426,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless { if ((key & mask) != low) { - tableSpan = tableSpan.Slice(tableSize); + tableSpan = tableSpan[tableSize..]; tablePos += tableSize; tableBits = NextTableBitSize(counts, len, rootBits); tableSize = 1 << tableBits; @@ -444,7 +444,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless BitsUsed = len - rootBits, Value = (uint)sorted[symbol++] }; - ReplicateValue(tableSpan.Slice(key >> rootBits), step, tableSize, huffmanCode); + ReplicateValue(tableSpan[(key >> rootBits)..], step, tableSize, huffmanCode); key = GetNextKey(key, len); } } @@ -576,8 +576,8 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless { if (tree[0].PoolIndexLeft >= 0) { - SetBitDepths(pool.Slice(tree[0].PoolIndexLeft), pool, bitDepths, level + 1); - SetBitDepths(pool.Slice(tree[0].PoolIndexRight), pool, bitDepths, level + 1); + SetBitDepths(pool[tree[0].PoolIndexLeft..], pool, bitDepths, level + 1); + SetBitDepths(pool[tree[0].PoolIndexRight..], pool, bitDepths, level + 1); } else { diff --git a/src/ImageSharp/Formats/Webp/Lossless/NearLosslessEnc.cs b/src/ImageSharp/Formats/Webp/Lossless/NearLosslessEnc.cs index db1273f4e..b2753ab22 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/NearLosslessEnc.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/NearLosslessEnc.cs @@ -44,7 +44,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless Span prevRow = copyBuffer; Span currRow = copyBuffer.Slice(xSize, xSize); Span nextRow = copyBuffer.Slice(xSize * 2, xSize); - argbSrc.Slice(0, xSize).CopyTo(currRow); + argbSrc[..xSize].CopyTo(currRow); argbSrc.Slice(xSize, xSize).CopyTo(nextRow); int srcOffset = 0; diff --git a/src/ImageSharp/Formats/Webp/Lossless/PredictorEncoder.cs b/src/ImageSharp/Formats/Webp/Lossless/PredictorEncoder.cs index e2dd8c644..1383eba78 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/PredictorEncoder.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/PredictorEncoder.cs @@ -230,8 +230,8 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless // to allow the top right pixel to point to the leftmost pixel of the next row // when at the right edge. Span upperRow = argbScratch; - Span currentRow = upperRow.Slice(width + 1); - Span maxDiffs = MemoryMarshal.Cast(currentRow.Slice(width + 1)); + Span currentRow = upperRow[(width + 1)..]; + Span maxDiffs = MemoryMarshal.Cast(currentRow[(width + 1)..]); float bestDiff = MaxDiffCost; int bestMode = 0; uint[] residuals = new uint[1 << WebpConstants.MaxTransformBits]; @@ -250,7 +250,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless // in all cases (wrapping to the leftmost pixel of the next row if it does // not exist). Span src = argb.Slice(((startY - 1) * width) + contextStartX, maxX + haveLeft + 1); - Span dst = currentRow.Slice(contextStartX); + Span dst = currentRow[contextStartX..]; src.CopyTo(dst); } @@ -267,14 +267,14 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless // not exist in the currentRow). int offset = (y * width) + contextStartX; Span src = argb.Slice(offset, maxX + haveLeft + (y + 1 < height ? 1 : 0)); - Span dst = currentRow.Slice(contextStartX); + Span dst = currentRow[contextStartX..]; src.CopyTo(dst); if (nearLossless) { if (maxQuantization > 1 && y >= 1 && y + 1 < height) { - MaxDiffsForRow(contextWidth, width, argb, offset, maxDiffs.Slice(contextStartX), usedSubtractGreen); + MaxDiffsForRow(contextWidth, width, argb, offset, maxDiffs[contextStartX..], usedSubtractGreen); } } @@ -589,10 +589,10 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless // to allow the top right pixel to point to the leftmost pixel of the next row // when at the right edge. Span upperRow = argbScratch; - Span currentRow = upperRow.Slice(width + 1); - Span currentMaxDiffs = MemoryMarshal.Cast(currentRow.Slice(width + 1)); + Span currentRow = upperRow[(width + 1)..]; + Span currentMaxDiffs = MemoryMarshal.Cast(currentRow[(width + 1)..]); - Span lowerMaxDiffs = currentMaxDiffs.Slice(width); + Span lowerMaxDiffs = currentMaxDiffs[width..]; Span scratch = stackalloc short[8]; for (int y = 0; y < height; y++) { @@ -604,7 +604,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless if (lowEffort) { - PredictBatch(PredLowEffort, 0, y, width, currentRow, upperRow, argb.Slice(y * width), scratch); + PredictBatch(PredLowEffort, 0, y, width, currentRow, upperRow, argb[(y * width)..], scratch); } else { @@ -645,7 +645,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless transparentColorMode, usedSubtractGreen, nearLossless, - argb.Slice((y * width) + x), + argb[((y * width) + x)..], scratch); x = xEnd; @@ -820,14 +820,14 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless { int xScan = GetMin(maxTileSize, xSize - tileX); int yScan = GetMin(maxTileSize, ySize - tileY); - argb = argb.Slice((tileY * xSize) + tileX); + argb = argb[((tileY * xSize) + tileX)..]; while (yScan-- > 0) { LosslessUtils.TransformColor(colorTransform, argb, xScan); if (argb.Length > xSize) { - argb = argb.Slice(xSize); + argb = argb[xSize..]; } } } @@ -853,7 +853,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless int allYMax = GetMin(tileYOffset + maxTileSize, ySize); int tileWidth = allXMax - tileXOffset; int tileHeight = allYMax - tileYOffset; - Span tileArgb = argb.Slice((tileYOffset * xSize) + tileXOffset); + Span tileArgb = argb[((tileYOffset * xSize) + tileXOffset)..]; var bestTx = default(Vp8LMultipliers); @@ -954,7 +954,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless int greenToRed, int[] accumulatedRedHisto) { - Span histo = scratch.Slice(0, 256); + Span histo = scratch[..256]; histo.Clear(); ColorSpaceTransformUtils.CollectColorRedTransforms(argb, stride, tileWidth, tileHeight, greenToRed, histo); @@ -992,7 +992,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless int redToBlue, int[] accumulatedBlueHisto) { - Span histo = scratch.Slice(0, 256); + Span histo = scratch[..256]; histo.Clear(); ColorSpaceTransformUtils.CollectColorBlueTransforms(argb, stride, tileWidth, tileHeight, greenToBlue, redToBlue, histo); diff --git a/src/ImageSharp/Formats/Webp/Lossless/Vp8LEncoder.cs b/src/ImageSharp/Formats/Webp/Lossless/Vp8LEncoder.cs index f2b855a37..473c92d8d 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/Vp8LEncoder.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/Vp8LEncoder.cs @@ -1105,24 +1105,24 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless AddSingle( pix, - histo.Slice((int)HistoIx.HistoAlpha * 256), - histo.Slice((int)HistoIx.HistoRed * 256), - histo.Slice((int)HistoIx.HistoGreen * 256), - histo.Slice((int)HistoIx.HistoBlue * 256)); + histo[..], + histo[((int)HistoIx.HistoRed * 256)..], + histo[((int)HistoIx.HistoGreen * 256)..], + histo[((int)HistoIx.HistoBlue * 256)..]); AddSingle( pixDiff, - histo.Slice((int)HistoIx.HistoAlphaPred * 256), - histo.Slice((int)HistoIx.HistoRedPred * 256), - histo.Slice((int)HistoIx.HistoGreenPred * 256), - histo.Slice((int)HistoIx.HistoBluePred * 256)); + histo[((int)HistoIx.HistoAlphaPred * 256)..], + histo[((int)HistoIx.HistoRedPred * 256)..], + histo[((int)HistoIx.HistoGreenPred * 256)..], + histo[((int)HistoIx.HistoBluePred * 256)..]); AddSingleSubGreen( pix, - histo.Slice((int)HistoIx.HistoRedSubGreen * 256), - histo.Slice((int)HistoIx.HistoBlueSubGreen * 256)); + histo[((int)HistoIx.HistoRedSubGreen * 256)..], + histo[((int)HistoIx.HistoBlueSubGreen * 256)..]); AddSingleSubGreen( pixDiff, - histo.Slice((int)HistoIx.HistoRedPredSubGreen * 256), - histo.Slice((int)HistoIx.HistoBluePredSubGreen * 256)); + histo[((int)HistoIx.HistoRedPredSubGreen * 256)..], + histo[((int)HistoIx.HistoBluePredSubGreen * 256)..]); // Approximate the palette by the entropy of the multiplicative hash. uint hash = HashPix(pix); @@ -1213,8 +1213,8 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless new[] { (byte)HistoIx.HistoRedPredSubGreen, (byte)HistoIx.HistoBluePredSubGreen }, new[] { (byte)HistoIx.HistoRed, (byte)HistoIx.HistoBlue } }; - Span redHisto = histo.Slice(256 * histoPairs[(int)minEntropyIx][0]); - Span blueHisto = histo.Slice(256 * histoPairs[(int)minEntropyIx][1]); + Span redHisto = histo[(256 * histoPairs[(int)minEntropyIx][0])..]; + Span blueHisto = histo[(256 * histoPairs[(int)minEntropyIx][1])..]; for (int i = 1; i < 256; i++) { if ((redHisto[i] | blueHisto[i]) != 0) @@ -1245,14 +1245,8 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless return false; } -#if NET5_0_OR_GREATER - var paletteSlice = palette.Slice(0, this.PaletteSize); + Span paletteSlice = palette[..this.PaletteSize]; paletteSlice.Sort(); -#else - uint[] paletteArray = palette.Slice(0, this.PaletteSize).ToArray(); - Array.Sort(paletteArray); - paletteArray.CopyTo(palette); -#endif if (PaletteHasNonMonotonousDeltas(palette, this.PaletteSize)) { @@ -1352,8 +1346,8 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless } BundleColorMap(tmpRow, width, xBits, dst); - src = src.Slice(srcStride); - dst = dst.Slice(dstStride); + src = src[srcStride..]; + dst = dst[dstStride..]; } } else @@ -1449,8 +1443,8 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless LosslessUtils.BundleColorMap(tmpRow, width, xBits, dst); - src = src.Slice(srcStride); - dst = dst.Slice(dstStride); + src = src[srcStride..]; + dst = dst[dstStride..]; } } @@ -1474,8 +1468,8 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless LosslessUtils.BundleColorMap(tmpRow, width, xBits, dst); - src = src.Slice(srcStride); - dst = dst.Slice(dstStride); + src = src[srcStride..]; + dst = dst[dstStride..]; } } @@ -1484,7 +1478,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless /// private static void PrepareMapToPalette(Span palette, int numColors, uint[] sorted, uint[] idxMap) { - palette.Slice(0, numColors).CopyTo(sorted); + palette[..numColors].CopyTo(sorted); Array.Sort(sorted, PaletteCompareColorsForSort); for (int i = 0; i < numColors; i++) { diff --git a/src/ImageSharp/Formats/Webp/Lossless/Vp8LHashChain.cs b/src/ImageSharp/Formats/Webp/Lossless/Vp8LHashChain.cs index eea1dd363..a49671917 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/Vp8LHashChain.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/Vp8LHashChain.cs @@ -125,7 +125,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless else { // Just move one pixel forward. - hashCode = GetPixPairHash64(bgra.Slice(pos)); + hashCode = GetPixPairHash64(bgra[pos..]); chain[pos] = hashToFirstIndex[(int)hashCode]; hashToFirstIndex[(int)hashCode] = pos++; bgraComp = bgraCompNext; @@ -133,7 +133,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless } // Process the penultimate pixel. - chain[pos] = hashToFirstIndex[(int)GetPixPairHash64(bgra.Slice(pos))]; + chain[pos] = hashToFirstIndex[(int)GetPixPairHash64(bgra[pos..])]; // Find the best match interval at each pixel, defined by an offset to the // pixel and a length. The right-most pixel cannot match anything to the right @@ -157,7 +157,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless // Heuristic: use the comparison with the above line as an initialization. if (basePosition >= (uint)xSize) { - currLength = LosslessUtils.FindMatchLength(bgra.Slice(bgraStart - xSize), bgra.Slice(bgraStart), bestLength, maxLen); + currLength = LosslessUtils.FindMatchLength(bgra[(bgraStart - xSize)..], bgra[bgraStart..], bestLength, maxLen); if (currLength > bestLength) { bestLength = currLength; @@ -168,7 +168,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless } // Heuristic: compare to the previous pixel. - currLength = LosslessUtils.FindMatchLength(bgra.Slice(bgraStart - 1), bgra.Slice(bgraStart), bestLength, maxLen); + currLength = LosslessUtils.FindMatchLength(bgra[(bgraStart - 1)..], bgra[bgraStart..], bestLength, maxLen); if (currLength > bestLength) { bestLength = currLength; @@ -184,7 +184,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless } } - uint bestBgra = bgra.Slice(bgraStart)[bestLength]; + uint bestBgra = bgra[bgraStart..][bestLength]; for (; pos >= minPos && (--iter > 0); pos = chain[pos]) { @@ -193,12 +193,12 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless continue; } - currLength = LosslessUtils.VectorMismatch(bgra.Slice(pos), bgra.Slice(bgraStart), maxLen); + currLength = LosslessUtils.VectorMismatch(bgra[pos..], bgra[bgraStart..], maxLen); if (bestLength < currLength) { bestLength = currLength; bestDistance = (uint)(basePosition - pos); - bestBgra = bgra.Slice(bgraStart)[bestLength]; + bestBgra = bgra[bgraStart..][bestLength]; // Stop if we have reached a good enough length. if (bestLength >= lengthMax) diff --git a/src/ImageSharp/Formats/Webp/Lossless/WebpLosslessDecoder.cs b/src/ImageSharp/Formats/Webp/Lossless/WebpLosslessDecoder.cs index ff2b808dd..fafd5b49c 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/WebpLosslessDecoder.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/WebpLosslessDecoder.cs @@ -199,8 +199,8 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless Span pixelRow = pixels.DangerousGetRowSpan(y); PixelOperations.Instance.FromBgra32Bytes( this.configuration, - rowAsBytes.Slice(0, bytesPerRow), - pixelRow.Slice(0, width), + rowAsBytes[..bytesPerRow], + pixelRow[..width], width); } } @@ -441,7 +441,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless } // TODO: Avoid allocation. - hTreeGroup.HTrees.Add(huffmanTable.Slice(0, size).ToArray()); + hTreeGroup.HTrees.Add(huffmanTable[..size].ToArray()); HuffmanCode huffTableZero = huffmanTable[0]; if (isTrivialLiteral && LiteralMap[j] == 1) @@ -450,7 +450,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless } totalSize += huffTableZero.BitsUsed; - huffmanTable = huffmanTable.Slice(size); + huffmanTable = huffmanTable[size..]; if (j <= HuffIndex.Alpha) { @@ -862,14 +862,14 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless private uint ReadSymbol(Span table) { uint val = (uint)this.bitReader.PrefetchBits(); - Span tableSpan = table.Slice((int)(val & HuffmanUtils.HuffmanTableMask)); + Span tableSpan = table[(int)(val & HuffmanUtils.HuffmanTableMask)..]; int nBits = tableSpan[0].BitsUsed - HuffmanUtils.HuffmanTableBits; if (nBits > 0) { this.bitReader.AdvanceBitPosition(HuffmanUtils.HuffmanTableBits); val = (uint)this.bitReader.PrefetchBits(); - tableSpan = tableSpan.Slice((int)tableSpan[0].Value); - tableSpan = tableSpan.Slice((int)val & ((1 << nBits) - 1)); + tableSpan = tableSpan[(int)tableSpan[0].Value..]; + tableSpan = tableSpan[((int)val & ((1 << nBits) - 1))..]; } this.bitReader.AdvanceBitPosition(tableSpan[0].BitsUsed); @@ -949,14 +949,14 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless { // no overlap. Span src = pixelData.Slice(start, length); - Span dest = pixelData.Slice(decodedPixels); + Span dest = pixelData[decodedPixels..]; src.CopyTo(dest); } else { // There is overlap between the backward reference distance and the pixels to copy. - Span src = pixelData.Slice(start); - Span dest = pixelData.Slice(decodedPixels); + Span src = pixelData[start..]; + Span dest = pixelData[decodedPixels..]; for (int i = 0; i < length; i++) { dest[i] = src[i]; @@ -977,12 +977,12 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless if (dist >= length) { // no overlap. - data.Slice(pos - dist, length).CopyTo(data.Slice(pos)); + data.Slice(pos - dist, length).CopyTo(data[pos..]); } else { - Span dst = data.Slice(pos); - Span src = data.Slice(pos - dist); + Span dst = data[pos..]; + Span src = data[(pos - dist)..]; for (int i = 0; i < length; i++) { dst[i] = src[i]; diff --git a/src/ImageSharp/Formats/Webp/Lossy/QuantEnc.cs b/src/ImageSharp/Formats/Webp/Lossy/QuantEnc.cs index 4d60f0ae3..c169ba6f9 100644 --- a/src/ImageSharp/Formats/Webp/Lossy/QuantEnc.cs +++ b/src/ImageSharp/Formats/Webp/Lossy/QuantEnc.cs @@ -124,7 +124,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy Span tmpLevels = new short[16]; do { - int numBlocks = 1; + const int numBlocks = 1; rdi4.Clear(); int mode; int bestMode = -1; diff --git a/src/ImageSharp/Formats/Webp/Lossy/Vp8EncIterator.cs b/src/ImageSharp/Formats/Webp/Lossy/Vp8EncIterator.cs index 25894905a..c1dedeba4 100644 --- a/src/ImageSharp/Formats/Webp/Lossy/Vp8EncIterator.cs +++ b/src/ImageSharp/Formats/Webp/Lossy/Vp8EncIterator.cs @@ -288,9 +288,9 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy { int yStartIdx = ((this.Y * yStride) + this.X) * 16; int uvStartIdx = ((this.Y * uvStride) + this.X) * 8; - Span ySrc = y.Slice(yStartIdx); - Span uSrc = u.Slice(uvStartIdx); - Span vSrc = v.Slice(uvStartIdx); + Span ySrc = y[yStartIdx..]; + Span uSrc = u[uvStartIdx..]; + Span vSrc = v[uvStartIdx..]; int w = Math.Min(width - (this.X * 16), 16); int h = Math.Min(height - (this.Y * 16), 16); int uvw = (w + 1) >> 1; @@ -331,9 +331,9 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy vLeft[0] = v[uvStartIdx - 1 - uvStride]; } - this.ImportLine(y.Slice(yStartIdx - 1), yStride, yLeft.Slice(1), h, 16); - this.ImportLine(u.Slice(uvStartIdx - 1), uvStride, uLeft.Slice(1), uvh, 8); - this.ImportLine(v.Slice(uvStartIdx - 1), uvStride, vLeft.Slice(1), uvh, 8); + this.ImportLine(y[(yStartIdx - 1)..], yStride, yLeft[1..], h, 16); + this.ImportLine(u[(uvStartIdx - 1)..], uvStride, uLeft[1..], uvh, 8); + this.ImportLine(v[(uvStartIdx - 1)..], uvStride, vLeft[1..], uvh, 8); } Span yTop = this.YTop.AsSpan(this.yTopIdx, 16); @@ -344,9 +344,9 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy } else { - this.ImportLine(y.Slice(yStartIdx - yStride), 1, yTop, w, 16); - this.ImportLine(u.Slice(uvStartIdx - uvStride), 1, this.UvTop.AsSpan(this.uvTopIdx, 8), uvw, 8); - this.ImportLine(v.Slice(uvStartIdx - uvStride), 1, this.UvTop.AsSpan(this.uvTopIdx + 8, 8), uvw, 8); + this.ImportLine(y[(yStartIdx - yStride)..], 1, yTop, w, 16); + this.ImportLine(u[(uvStartIdx - uvStride)..], 1, this.UvTop.AsSpan(this.uvTopIdx, 8), uvw, 8); + this.ImportLine(v[(uvStartIdx - uvStride)..], 1, this.UvTop.AsSpan(this.uvTopIdx + 8, 8), uvw, 8); } } @@ -490,8 +490,8 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy Span preds = this.Preds.AsSpan(this.predIdx); for (int y = 0; y < 4; y++) { - preds.Slice(0, 4).Fill((byte)mode); - preds = preds.Slice(this.predsWidth); + preds[..4].Fill((byte)mode); + preds = preds[this.predsWidth..]; } this.CurrentMacroBlockInfo.MacroBlockType = Vp8MacroBlockType.I16X16; @@ -679,7 +679,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy public bool RotateI4(Span yuvOut) { - Span blk = yuvOut.Slice(WebpLookupTables.Vp8Scan[this.I4]); + Span blk = yuvOut[WebpLookupTables.Vp8Scan[this.I4]..]; Span top = this.I4Boundary.AsSpan(); int topOffset = this.I4BoundaryIdx; int i; @@ -830,7 +830,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy for (int i = 0; i < h; i++) { // memcpy(dst, src, w); - src.Slice(srcIdx, w).CopyTo(dst.Slice(dstIdx)); + src.Slice(srcIdx, w).CopyTo(dst[dstIdx..]); if (w < size) { // memset(dst + w, dst[w - 1], size - w); @@ -844,7 +844,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy for (int i = h; i < size; i++) { // memcpy(dst, dst - BPS, size); - dst.Slice(dstIdx - WebpConstants.Bps, size).CopyTo(dst.Slice(dstIdx)); + dst.Slice(dstIdx - WebpConstants.Bps, size).CopyTo(dst[dstIdx..]); dstIdx += WebpConstants.Bps; } } diff --git a/src/ImageSharp/Formats/Webp/Lossy/Vp8Encoder.cs b/src/ImageSharp/Formats/Webp/Lossy/Vp8Encoder.cs index 8eaaeda7a..9dbbccbc7 100644 --- a/src/ImageSharp/Formats/Webp/Lossy/Vp8Encoder.cs +++ b/src/ImageSharp/Formats/Webp/Lossy/Vp8Encoder.cs @@ -382,7 +382,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy (uint)width, (uint)height, hasAlpha, - alphaData.Slice(0, alphaDataSize), + alphaData[..alphaDataSize], this.alphaCompression && alphaCompressionSucceeded); } diff --git a/src/ImageSharp/Formats/Webp/Lossy/WebpLossyDecoder.cs b/src/ImageSharp/Formats/Webp/Lossy/WebpLossyDecoder.cs index 0e789060a..b290ee58b 100644 --- a/src/ImageSharp/Formats/Webp/Lossy/WebpLossyDecoder.cs +++ b/src/ImageSharp/Formats/Webp/Lossy/WebpLossyDecoder.cs @@ -252,7 +252,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy } top.CopyTo(modes); - modes = modes.Slice(4); + modes = modes[4..]; left[y] = (byte)yMode; } } @@ -290,9 +290,9 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy const int vOff = uOff + 16; Span yuv = dec.YuvBuffer.Memory.Span; - Span yDst = yuv.Slice(yOff); - Span uDst = yuv.Slice(uOff); - Span vDst = yuv.Slice(vOff); + Span yDst = yuv[yOff..]; + Span uDst = yuv[uOff..]; + Span vDst = yuv[vOff..]; // Initialize left-most block. int end = 16 * WebpConstants.Bps; @@ -349,17 +349,17 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy { int srcIdx = (i * WebpConstants.Bps) + 12 + yOff; int dstIdx = (i * WebpConstants.Bps) - 4 + yOff; - yuv.Slice(srcIdx, 4).CopyTo(yuv.Slice(dstIdx)); + yuv.Slice(srcIdx, 4).CopyTo(yuv[dstIdx..]); } for (int i = -1; i < 8; i++) { int srcIdx = (i * WebpConstants.Bps) + 4 + uOff; int dstIdx = (i * WebpConstants.Bps) - 4 + uOff; - yuv.Slice(srcIdx, 4).CopyTo(yuv.Slice(dstIdx)); + yuv.Slice(srcIdx, 4).CopyTo(yuv[dstIdx..]); srcIdx = (i * WebpConstants.Bps) + 4 + vOff; dstIdx = (i * WebpConstants.Bps) - 4 + vOff; - yuv.Slice(srcIdx, 4).CopyTo(yuv.Slice(dstIdx)); + yuv.Slice(srcIdx, 4).CopyTo(yuv[dstIdx..]); } } @@ -369,15 +369,15 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy uint bits = block.NonZeroY; if (mby > 0) { - topYuv.Y.CopyTo(yuv.Slice(yOff - WebpConstants.Bps)); - topYuv.U.CopyTo(yuv.Slice(uOff - WebpConstants.Bps)); - topYuv.V.CopyTo(yuv.Slice(vOff - WebpConstants.Bps)); + topYuv.Y.CopyTo(yuv[(yOff - WebpConstants.Bps)..]); + topYuv.U.CopyTo(yuv[(uOff - WebpConstants.Bps)..]); + topYuv.V.CopyTo(yuv[(vOff - WebpConstants.Bps)..]); } // Predict and add residuals. if (block.IsI4x4) { - Span topRight = yuv.Slice(yOff - WebpConstants.Bps + 16); + Span topRight = yuv[(yOff - WebpConstants.Bps + 16)..]; if (mby > 0) { if (mbx >= dec.MbWidth - 1) @@ -396,14 +396,14 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy } // Replicate the top-right pixels below. - Span topRightUint = MemoryMarshal.Cast(yuv.Slice(yOff - WebpConstants.Bps + 16)); + Span topRightUint = MemoryMarshal.Cast(yuv[(yOff - WebpConstants.Bps + 16)..]); topRightUint[WebpConstants.Bps] = topRightUint[2 * WebpConstants.Bps] = topRightUint[3 * WebpConstants.Bps] = topRightUint[0]; // Predict and add residuals for all 4x4 blocks in turn. for (int n = 0; n < 16; ++n, bits <<= 2) { int offset = yOff + WebpConstants.Scan[n]; - Span dst = yuv.Slice(offset); + Span dst = yuv[offset..]; byte lumaMode = block.Modes[n]; switch (lumaMode) { @@ -475,7 +475,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy { for (int n = 0; n < 16; ++n, bits <<= 2) { - this.DoTransform(bits, coeffs.AsSpan(n * 16), yDst.Slice(WebpConstants.Scan[n]), this.scratch); + this.DoTransform(bits, coeffs.AsSpan(n * 16), yDst[WebpConstants.Scan[n]..], this.scratch); } } } @@ -527,19 +527,19 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy } // Transfer reconstructed samples from yuv_buffer cache to final destination. - Span yOut = dec.CacheY.Memory.Span.Slice(dec.CacheYOffset + (mbx * 16)); - Span uOut = dec.CacheU.Memory.Span.Slice(dec.CacheUvOffset + (mbx * 8)); - Span vOut = dec.CacheV.Memory.Span.Slice(dec.CacheUvOffset + (mbx * 8)); + Span yOut = dec.CacheY.Memory.Span[(dec.CacheYOffset + (mbx * 16))..]; + Span uOut = dec.CacheU.Memory.Span[(dec.CacheUvOffset + (mbx * 8))..]; + Span vOut = dec.CacheV.Memory.Span[(dec.CacheUvOffset + (mbx * 8))..]; for (int j = 0; j < 16; j++) { - yDst.Slice(j * WebpConstants.Bps, Math.Min(16, yOut.Length)).CopyTo(yOut.Slice(j * dec.CacheYStride)); + yDst.Slice(j * WebpConstants.Bps, Math.Min(16, yOut.Length)).CopyTo(yOut[(j * dec.CacheYStride)..]); } for (int j = 0; j < 8; j++) { int jUvStride = j * dec.CacheUvStride; - uDst.Slice(j * WebpConstants.Bps, Math.Min(8, uOut.Length)).CopyTo(uOut.Slice(jUvStride)); - vDst.Slice(j * WebpConstants.Bps, Math.Min(8, vOut.Length)).CopyTo(vOut.Slice(jUvStride)); + uDst.Slice(j * WebpConstants.Bps, Math.Min(8, uOut.Length)).CopyTo(uOut[jUvStride..]); + vDst.Slice(j * WebpConstants.Bps, Math.Min(8, vOut.Length)).CopyTo(vOut[jUvStride..]); } } } @@ -649,9 +649,9 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy } else { - io.Y = dec.CacheY.Memory.Span.Slice(dec.CacheYOffset); - io.U = dec.CacheU.Memory.Span.Slice(dec.CacheUvOffset); - io.V = dec.CacheV.Memory.Span.Slice(dec.CacheUvOffset); + io.Y = dec.CacheY.Memory.Span[dec.CacheYOffset..]; + io.U = dec.CacheU.Memory.Span[dec.CacheUvOffset..]; + io.V = dec.CacheV.Memory.Span[dec.CacheUvOffset..]; } if (!isLastRow) @@ -696,7 +696,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy int bpp = 3; int bufferStride = bpp * io.Width; int dstStartIdx = io.MbY * bufferStride; - Span dst = buf.Slice(dstStartIdx); + Span dst = buf[dstStartIdx..]; int yEnd = io.MbY + io.MbH; int mbw = io.MbW; int uvw = (mbw + 1) / 2; @@ -711,7 +711,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy else { // We can finish the left-over line from previous call. - YuvConversion.UpSample(tmpYBuffer, curY, topU, topV, curU, curV, buf.Slice(dstStartIdx - bufferStride), dst, mbw, uvBuffer); + YuvConversion.UpSample(tmpYBuffer, curY, topU, topV, curU, curV, buf[(dstStartIdx - bufferStride)..], dst, mbw, uvBuffer); numLinesOut++; } @@ -722,21 +722,21 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy { topU = curU; topV = curV; - curU = curU.Slice(io.UvStride); - curV = curV.Slice(io.UvStride); - YuvConversion.UpSample(curY.Slice(io.YStride), curY.Slice(ioStride2), topU, topV, curU, curV, dst.Slice(bufferStride), dst.Slice(bufferStride2), mbw, uvBuffer); - curY = curY.Slice(ioStride2); - dst = dst.Slice(bufferStride2); + curU = curU[io.UvStride..]; + curV = curV[io.UvStride..]; + YuvConversion.UpSample(curY[io.YStride..], curY[ioStride2..], topU, topV, curU, curV, dst[bufferStride..], dst[bufferStride2..], mbw, uvBuffer); + curY = curY[ioStride2..]; + dst = dst[bufferStride2..]; } // Move to last row. - curY = curY.Slice(io.YStride); + curY = curY[io.YStride..]; if (yEnd < io.Height) { // Save the unfinished samples for next call (as we're not done yet). - curY.Slice(0, mbw).CopyTo(tmpYBuffer); - curU.Slice(0, uvw).CopyTo(tmpUBuffer); - curV.Slice(0, uvw).CopyTo(tmpVBuffer); + curY[..mbw].CopyTo(tmpYBuffer); + curU[..uvw].CopyTo(tmpUBuffer); + curV[..uvw].CopyTo(tmpVBuffer); // The upsampler leaves a row unfinished behind (except for the very last row). numLinesOut--; @@ -746,7 +746,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy // Process the very last row of even-sized picture. if ((yEnd & 1) == 0) { - YuvConversion.UpSample(curY, default, curU, curV, curU, curV, dst.Slice(bufferStride), default, mbw, uvBuffer); + YuvConversion.UpSample(curY, default, curU, curV, curU, curV, dst[bufferStride..], default, mbw, uvBuffer); } } @@ -1149,7 +1149,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy dec.Vp8BitReaders[p] = new Vp8BitReader(this.bitReader.Data, (uint)pSize, partStart); partStart += pSize; sizeLeft -= pSize; - sz = sz.Slice(3); + sz = sz[3..]; } dec.Vp8BitReaders[lastPart] = new Vp8BitReader(this.bitReader.Data, (uint)sizeLeft, partStart); diff --git a/src/ImageSharp/Formats/Webp/WebpAnimationDecoder.cs b/src/ImageSharp/Formats/Webp/WebpAnimationDecoder.cs index 7bd4a3eb5..d327e7293 100644 --- a/src/ImageSharp/Formats/Webp/WebpAnimationDecoder.cs +++ b/src/ImageSharp/Formats/Webp/WebpAnimationDecoder.cs @@ -294,8 +294,8 @@ namespace SixLabors.ImageSharp.Formats.Webp for (int y = frameY; y < frameY + frameHeight; y++) { Span framePixelRow = imageFramePixels.DangerousGetRowSpan(y); - Span decodedPixelRow = decodedImage.DangerousGetRowSpan(decodedRowIdx++).Slice(0, frameWidth); - decodedPixelRow.TryCopyTo(framePixelRow.Slice(frameX)); + Span decodedPixelRow = decodedImage.DangerousGetRowSpan(decodedRowIdx++)[..frameWidth]; + decodedPixelRow.TryCopyTo(framePixelRow[frameX..]); } } diff --git a/src/ImageSharp/Formats/Webp/WebpImageFormatDetector.cs b/src/ImageSharp/Formats/Webp/WebpImageFormatDetector.cs index fa270b528..9e672afb3 100644 --- a/src/ImageSharp/Formats/Webp/WebpImageFormatDetector.cs +++ b/src/ImageSharp/Formats/Webp/WebpImageFormatDetector.cs @@ -23,7 +23,7 @@ namespace SixLabors.ImageSharp.Formats.Webp /// /// The header bytes. /// True, if its a valid RIFF FourCC. - private bool IsRiffContainer(ReadOnlySpan header) => header.Slice(0, 4).SequenceEqual(WebpConstants.RiffFourCc); + private bool IsRiffContainer(ReadOnlySpan header) => header[..4].SequenceEqual(WebpConstants.RiffFourCc); /// /// Checks if 'WEBP' is present in the header. diff --git a/src/ImageSharp/IO/ChunkedMemoryStream.cs b/src/ImageSharp/IO/ChunkedMemoryStream.cs index 44ec7aa29..49e3d7f2f 100644 --- a/src/ImageSharp/IO/ChunkedMemoryStream.cs +++ b/src/ImageSharp/IO/ChunkedMemoryStream.cs @@ -286,7 +286,7 @@ namespace SixLabors.ImageSharp.IO } int readCount = Math.Min(count, chunkSize - this.readOffset); - chunkBuffer.Slice(this.readOffset, readCount).CopyTo(buffer.Slice(offset)); + chunkBuffer.Slice(this.readOffset, readCount).CopyTo(buffer[offset..]); offset += readCount; count -= readCount; this.readOffset += readCount; @@ -382,7 +382,7 @@ namespace SixLabors.ImageSharp.IO } int copyCount = Math.Min(count, chunkSize - this.writeOffset); - buffer.Slice(offset, copyCount).CopyTo(chunkBuffer.Slice(this.writeOffset)); + buffer.Slice(offset, copyCount).CopyTo(chunkBuffer[this.writeOffset..]); offset += copyCount; count -= copyCount; diff --git a/src/ImageSharp/Image.LoadPixelData.cs b/src/ImageSharp/Image.LoadPixelData.cs index 93563c794..ab96a1c72 100644 --- a/src/ImageSharp/Image.LoadPixelData.cs +++ b/src/ImageSharp/Image.LoadPixelData.cs @@ -130,7 +130,7 @@ namespace SixLabors.ImageSharp Guard.MustBeGreaterThanOrEqualTo(data.Length, count, nameof(data)); var image = new Image(configuration, width, height); - data = data.Slice(0, count); + data = data[..count]; data.CopyTo(image.Frames.RootFrame.PixelBuffer.FastMemoryGroup); return image; diff --git a/src/ImageSharp/ImageFrame.LoadPixelData.cs b/src/ImageSharp/ImageFrame.LoadPixelData.cs index f6432757e..b1f2b14bd 100644 --- a/src/ImageSharp/ImageFrame.LoadPixelData.cs +++ b/src/ImageSharp/ImageFrame.LoadPixelData.cs @@ -44,7 +44,7 @@ namespace SixLabors.ImageSharp var image = new ImageFrame(configuration, width, height); - data = data.Slice(0, count); + data = data[..count]; data.CopyTo(image.PixelBuffer.FastMemoryGroup); return image; diff --git a/src/ImageSharp/IndexedImageFrame{TPixel}.cs b/src/ImageSharp/IndexedImageFrame{TPixel}.cs index 87bdbff69..2bd509902 100644 --- a/src/ImageSharp/IndexedImageFrame{TPixel}.cs +++ b/src/ImageSharp/IndexedImageFrame{TPixel}.cs @@ -46,7 +46,7 @@ namespace SixLabors.ImageSharp // Copy the palette over. We want the lifetime of this frame to be independant of any palette source. this.paletteOwner = configuration.MemoryAllocator.Allocate(palette.Length); palette.Span.CopyTo(this.paletteOwner.GetSpan()); - this.Palette = this.paletteOwner.Memory.Slice(0, palette.Length); + this.Palette = this.paletteOwner.Memory[..palette.Length]; } /// diff --git a/src/ImageSharp/Memory/Allocators/Internals/Gen2GcCallback.cs b/src/ImageSharp/Memory/Allocators/Internals/Gen2GcCallback.cs index dd30efa06..54d8e17f0 100644 --- a/src/ImageSharp/Memory/Allocators/Internals/Gen2GcCallback.cs +++ b/src/ImageSharp/Memory/Allocators/Internals/Gen2GcCallback.cs @@ -1,9 +1,8 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. // Port of BCL internal utility: // https://github.com/dotnet/runtime/blob/57bfe474518ab5b7cfe6bf7424a79ce3af9d6657/src/libraries/System.Private.CoreLib/src/System/Gen2GcCallback.cs -#if NETCOREAPP3_1_OR_GREATER using System; using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; @@ -20,10 +19,7 @@ namespace SixLabors.ImageSharp.Memory.Internals private readonly Func callback1; private GCHandle weakTargetObj; - private Gen2GcCallback(Func callback) - { - this.callback0 = callback; - } + private Gen2GcCallback(Func callback) => this.callback0 = callback; private Gen2GcCallback(Func callback, object targetObj) { @@ -92,24 +88,24 @@ namespace SixLabors.ImageSharp.Memory.Internals /// Schedule 'callback' to be called in the next GC. If the callback returns true it is /// rescheduled for the next Gen 2 GC. Otherwise the callbacks stop. /// - public static void Register(Func callback) - { + public static void Register(Func callback) => + // Create a unreachable object that remembers the callback function and target object. _ = new Gen2GcCallback(callback); - } /// + /// /// Schedule 'callback' to be called in the next GC. If the callback returns true it is /// rescheduled for the next Gen 2 GC. Otherwise the callbacks stop. - /// + /// + /// /// NOTE: This callback will be kept alive until either the callback function returns false, /// or the target object dies. + /// /// - public static void Register(Func callback, object targetObj) - { + public static void Register(Func callback, object targetObj) => + // Create a unreachable object that remembers the callback function and target object. _ = new Gen2GcCallback(callback, targetObj); - } } } -#endif diff --git a/src/ImageSharp/Memory/Allocators/Internals/UniformUnmanagedMemoryPool.cs b/src/ImageSharp/Memory/Allocators/Internals/UniformUnmanagedMemoryPool.cs index e960aef0d..756f5a995 100644 --- a/src/ImageSharp/Memory/Allocators/Internals/UniformUnmanagedMemoryPool.cs +++ b/src/ImageSharp/Memory/Allocators/Internals/UniformUnmanagedMemoryPool.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -40,9 +40,7 @@ namespace SixLabors.ImageSharp.Memory.Internals if (trimSettings.Enabled) { UpdateTimer(trimSettings, this); -#if NETCOREAPP3_1_OR_GREATER Gen2GcCallback.Register(s => ((UniformUnmanagedMemoryPool)s).Trim(), this); -#endif this.lastTrimTimestamp = Stopwatch.ElapsedMilliseconds; } } @@ -326,14 +324,8 @@ namespace SixLabors.ImageSharp.Memory.Internals private bool IsHighMemoryPressure() { -#if NETCOREAPP3_1_OR_GREATER GCMemoryInfo memoryInfo = GC.GetGCMemoryInfo(); return memoryInfo.MemoryLoadBytes >= memoryInfo.HighMemoryLoadThresholdBytes * this.trimSettings.HighPressureThresholdRate; -#else - // We don't have high pressure detection triggering full trimming on other platforms, - // to counterpart this, the maximum pool size is small. - return false; -#endif } public class TrimSettings diff --git a/src/ImageSharp/Memory/Allocators/UniformUnmanagedMemoryPoolMemoryAllocator.cs b/src/ImageSharp/Memory/Allocators/UniformUnmanagedMemoryPoolMemoryAllocator.cs index e79eb4967..af04718e8 100644 --- a/src/ImageSharp/Memory/Allocators/UniformUnmanagedMemoryPoolMemoryAllocator.cs +++ b/src/ImageSharp/Memory/Allocators/UniformUnmanagedMemoryPoolMemoryAllocator.cs @@ -4,7 +4,6 @@ using System; using System.Buffers; using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; using SixLabors.ImageSharp.Memory.Internals; namespace SixLabors.ImageSharp.Memory @@ -73,11 +72,9 @@ namespace SixLabors.ImageSharp.Memory this.nonPoolAllocator = new UnmanagedMemoryAllocator(unmanagedBufferSizeInBytes); } -#if NETCOREAPP3_1_OR_GREATER // This delegate allows overriding the method returning the available system memory, // so we can test our workaround for https://github.com/dotnet/runtime/issues/65466 internal static Func GetTotalAvailableMemoryBytes { get; set; } = () => GC.GetGCMemoryInfo().TotalAvailableMemoryBytes; -#endif /// protected internal override int GetBufferCapacityInBytes() => this.poolBufferSizeInBytes; @@ -151,11 +148,9 @@ namespace SixLabors.ImageSharp.Memory private static long GetDefaultMaxPoolSizeBytes() { -#if NETCOREAPP3_1_OR_GREATER - // On 64 bit .NET Core 3.1+, set the pool size to a portion of the total available memory. - // There is a bug in GC.GetGCMemoryInfo() on .NET 5 + 32 bit, making TotalAvailableMemoryBytes unreliable: + // On 64 bit set the pool size to a portion of the total available memory. // https://github.com/dotnet/runtime/issues/55126#issuecomment-876779327 - if (Environment.Is64BitProcess || !RuntimeInformation.FrameworkDescription.StartsWith(".NET 5.0")) + if (Environment.Is64BitProcess) { long total = GetTotalAvailableMemoryBytes(); @@ -165,7 +160,6 @@ namespace SixLabors.ImageSharp.Memory return total / 8; } } -#endif // Stick to a conservative value of 128 Megabytes on other platforms and 32 bit .NET 5.0: return 128 * OneMegabyte; diff --git a/src/ImageSharp/Memory/Buffer2D{T}.cs b/src/ImageSharp/Memory/Buffer2D{T}.cs index f35ec9b61..c73b96ae6 100644 --- a/src/ImageSharp/Memory/Buffer2D{T}.cs +++ b/src/ImageSharp/Memory/Buffer2D{T}.cs @@ -120,7 +120,7 @@ namespace SixLabors.ImageSharp.Memory return false; } - paddedSpan = slice.Slice(0, stride); + paddedSpan = slice[..stride]; return true; } diff --git a/src/ImageSharp/Memory/ByteMemoryManager{T}.cs b/src/ImageSharp/Memory/ByteMemoryManager{T}.cs index fd9a06db0..f6d79642a 100644 --- a/src/ImageSharp/Memory/ByteMemoryManager{T}.cs +++ b/src/ImageSharp/Memory/ByteMemoryManager{T}.cs @@ -47,7 +47,7 @@ namespace SixLabors.ImageSharp.Memory // We need to adjust the offset into the wrapped byte segment, // as the input index refers to the target-cast memory of T. // We just have to shift this index by the byte size of T. - return this.memory.Slice(elementIndex * Unsafe.SizeOf()).Pin(); + return this.memory[(elementIndex * Unsafe.SizeOf())..].Pin(); } /// diff --git a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupExtensions.cs b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupExtensions.cs index fc8e150d9..51774c881 100644 --- a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupExtensions.cs +++ b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupExtensions.cs @@ -82,7 +82,7 @@ namespace SixLabors.ImageSharp.Memory cur.GetSpan(fwd).CopyTo(target); cur.Forward(fwd); - target = target.Slice(fwd); + target = target[fwd..]; position += fwd; } } @@ -102,9 +102,9 @@ namespace SixLabors.ImageSharp.Memory while (!source.IsEmpty) { int fwd = Math.Min(cur.LookAhead(), source.Length); - source.Slice(0, fwd).CopyTo(cur.GetSpan(fwd)); + source[..fwd].CopyTo(cur.GetSpan(fwd)); cur.Forward(fwd); - source = source.Slice(fwd); + source = source[fwd..]; } } diff --git a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.cs b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.cs index ace02c8fa..f044e6cb9 100644 --- a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.cs +++ b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.cs @@ -285,7 +285,7 @@ namespace SixLabors.ImageSharp.Memory { long bufferIdx = Math.DivRem(start, this.BufferLength, out long bufferStart); Memory memory = this[(int)bufferIdx]; - return memory.Span.Slice((int)bufferStart); + return memory.Span[(int)bufferStart..]; } public static bool CanSwapContent(MemoryGroup target, MemoryGroup source) => diff --git a/src/ImageSharp/Memory/MemoryOwnerExtensions.cs b/src/ImageSharp/Memory/MemoryOwnerExtensions.cs index 0c415806f..8c3d49d1e 100644 --- a/src/ImageSharp/Memory/MemoryOwnerExtensions.cs +++ b/src/ImageSharp/Memory/MemoryOwnerExtensions.cs @@ -44,7 +44,7 @@ namespace SixLabors.ImageSharp.Memory [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Span Slice(this IMemoryOwner buffer, int start) { - return buffer.GetSpan().Slice(start); + return buffer.GetSpan()[start..]; } /// diff --git a/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs b/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs index 03f1566d2..f5f884f28 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs @@ -57,7 +57,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif { if (TryDetect(buffer, out CharacterCode code)) { - string text = GetEncoding(code).GetString(buffer.Slice(CharacterCodeBytesLength)); + string text = GetEncoding(code).GetString(buffer[CharacterCodeBytesLength..]); encodedString = new EncodedString(code, text); return true; } @@ -74,30 +74,13 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif GetCodeBytes(encodedString.Code).CopyTo(destination); string text = encodedString.Text; - int count = Write(GetEncoding(encodedString.Code), text, destination.Slice(CharacterCodeBytesLength)); + int count = Write(GetEncoding(encodedString.Code), text, destination[CharacterCodeBytesLength..]); return CharacterCodeBytesLength + count; } public static unsafe int Write(Encoding encoding, string value, Span destination) -#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER || NET => encoding.GetBytes(value.AsSpan(), destination); -#else - { - if (value.Length == 0) - { - return 0; - } - - fixed (char* c = value) - { - fixed (byte* b = destination) - { - return encoding.GetBytes(c, value.Length, b, destination.Length); - } - } - } -#endif private static bool TryDetect(ReadOnlySpan buffer, out CharacterCode code) { diff --git a/src/ImageSharp/Metadata/Profiles/Exif/ExifReader.cs b/src/ImageSharp/Metadata/Profiles/Exif/ExifReader.cs index dc6fad909..b2b1b2831 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/ExifReader.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/ExifReader.cs @@ -150,7 +150,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif foreach ((ulong Offset, ExifDataType DataType, ulong NumberOfComponents, ExifValue Exif) tag in this.BigValues) { ulong size = tag.NumberOfComponents * ExifDataTypes.GetSize(tag.DataType); - this.ReadBigValue(values, tag, buf.Slice(0, (int)size)); + this.ReadBigValue(values, tag, buf[..(int)size]); } } else @@ -160,7 +160,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif foreach ((ulong Offset, ExifDataType DataType, ulong NumberOfComponents, ExifValue Exif) tag in this.BigValues) { ulong size = tag.NumberOfComponents * ExifDataTypes.GetSize(tag.DataType); - this.ReadBigValue(values, tag, buf.Slice(0, (int)size)); + this.ReadBigValue(values, tag, buf[..(int)size]); } } @@ -247,13 +247,13 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif if (nullCharIndex > -1) { - buffer = buffer.Slice(0, nullCharIndex); + buffer = buffer[..nullCharIndex]; } return encoding.GetString(buffer); } - private byte ConvertToByte(ReadOnlySpan buffer) => buffer[0]; + private static byte ConvertToByte(ReadOnlySpan buffer) => buffer[0]; private object ConvertValue(ExifDataType dataType, ReadOnlySpan buffer, bool isArray) { @@ -272,7 +272,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif case ExifDataType.Undefined: if (!isArray) { - return this.ConvertToByte(buffer); + return ConvertToByte(buffer); } return buffer.ToArray(); @@ -414,7 +414,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif } else { - object value = this.ConvertValue(dataType, offsetBuffer.Slice(0, (int)size), numberOfComponents > 1 || exifValue.IsArray); + object value = this.ConvertValue(dataType, offsetBuffer[..(int)size], numberOfComponents > 1 || exifValue.IsArray); this.Add(values, exifValue, value); } } @@ -443,31 +443,14 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif numberOfComponents = 8 / ExifDataTypes.GetSize(dataType); } - // The StripOffsets, StripByteCounts, TileOffsets, and TileByteCounts tags are allowed to have the datatype TIFF_LONG8 in BigTIFF. - // Old datatypes TIFF_LONG, and TIFF_SHORT where allowed in the TIFF 6.0 specification, are still valid in BigTIFF, too. - // Likewise, tags that point to other IFDs, like e.g. the SubIFDs tag, are now allowed to have the datatype TIFF_IFD8 in BigTIFF. - // Again, the old datatypes TIFF_IFD, and the hardly recommendable TIFF_LONG, are still valid, too. - // https://www.awaresystems.be/imaging/tiff/bigtiff.html - ExifValue exifValue; - switch (tag) - { - case ExifTagValue.StripOffsets: - exifValue = new ExifLong8Array(ExifTagValue.StripOffsets); - break; - case ExifTagValue.StripByteCounts: - exifValue = new ExifLong8Array(ExifTagValue.StripByteCounts); - break; - case ExifTagValue.TileOffsets: - exifValue = new ExifLong8Array(ExifTagValue.TileOffsets); - break; - case ExifTagValue.TileByteCounts: - exifValue = new ExifLong8Array(ExifTagValue.TileByteCounts); - break; - default: - exifValue = ExifValues.Create(tag) ?? ExifValues.Create(tag, dataType, numberOfComponents); - break; - } - + ExifValue exifValue = tag switch + { + ExifTagValue.StripOffsets => new ExifLong8Array(ExifTagValue.StripOffsets), + ExifTagValue.StripByteCounts => new ExifLong8Array(ExifTagValue.StripByteCounts), + ExifTagValue.TileOffsets => new ExifLong8Array(ExifTagValue.TileOffsets), + ExifTagValue.TileByteCounts => new ExifLong8Array(ExifTagValue.TileByteCounts), + _ => ExifValues.Create(tag) ?? ExifValues.Create(tag, dataType, numberOfComponents), + }; if (exifValue is null) { this.AddInvalidTag(new UnkownExifTag(tag)); @@ -488,7 +471,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif } else { - object value = this.ConvertValue(dataType, offsetBuffer.Slice(0, (int)size), numberOfComponents > 1 || exifValue.IsArray); + object value = this.ConvertValue(dataType, offsetBuffer[..(int)size], numberOfComponents > 1 || exifValue.IsArray); this.Add(values, exifValue, value); } } @@ -644,7 +627,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif return default; } - uint numerator = this.ConvertToUInt32(buffer.Slice(0, 4)); + uint numerator = this.ConvertToUInt32(buffer[..4]); uint denominator = this.ConvertToUInt32(buffer.Slice(4, 4)); return new Rational(numerator, denominator, false); @@ -671,7 +654,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif return default; } - int numerator = this.ConvertToInt32(buffer.Slice(0, 4)); + int numerator = this.ConvertToInt32(buffer[..4]); int denominator = this.ConvertToInt32(buffer.Slice(4, 4)); return new SignedRational(numerator, denominator, false); diff --git a/src/ImageSharp/Metadata/Profiles/Exif/ExifWriter.cs b/src/ImageSharp/Metadata/Profiles/Exif/ExifWriter.cs index 6e98128d5..ed22ff647 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/ExifWriter.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/ExifWriter.cs @@ -367,13 +367,13 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif private static void WriteRational(Span destination, in Rational value) { - BinaryPrimitives.WriteUInt32LittleEndian(destination.Slice(0, 4), value.Numerator); + BinaryPrimitives.WriteUInt32LittleEndian(destination[..4], value.Numerator); BinaryPrimitives.WriteUInt32LittleEndian(destination.Slice(4, 4), value.Denominator); } private static void WriteSignedRational(Span destination, in SignedRational value) { - BinaryPrimitives.WriteInt32LittleEndian(destination.Slice(0, 4), value.Numerator); + BinaryPrimitives.WriteInt32LittleEndian(destination[..4], value.Numerator); BinaryPrimitives.WriteInt32LittleEndian(destination.Slice(4, 4), value.Denominator); } @@ -435,11 +435,11 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif if (ExifUcs2StringHelpers.IsUcs2Tag((ExifTagValue)(ushort)exifValue.Tag)) { - return offset + ExifUcs2StringHelpers.Write((string)value, destination.Slice(offset)); + return offset + ExifUcs2StringHelpers.Write((string)value, destination[offset..]); } else if (value is EncodedString encodedString) { - return offset + ExifEncodedStringHelpers.Write(encodedString, destination.Slice(offset)); + return offset + ExifEncodedStringHelpers.Write(encodedString, destination[offset..]); } if (exifValue.IsArray) diff --git a/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.Primitives.cs b/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.Primitives.cs index c9f4bab45..d63bb7449 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.Primitives.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.Primitives.cs @@ -108,7 +108,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc int pos = value.IndexOf('\0'); if (pos >= 0) { - value = value.Substring(0, pos); + value = value[..pos]; } return value; diff --git a/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.Primitives.cs b/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.Primitives.cs index 180fdba03..d3113b014 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.Primitives.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.Primitives.cs @@ -213,7 +213,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc lengthAdjust = 1; } - value = value.Substring(0, Math.Min(length - lengthAdjust, value.Length)); + value = value[..Math.Min(length - lengthAdjust, value.Length)]; byte[] textData = Encoding.ASCII.GetBytes(value); int actualLength = Math.Min(length - lengthAdjust, textData.Length); diff --git a/src/ImageSharp/Metadata/Profiles/IPTC/IptcValue.cs b/src/ImageSharp/Metadata/Profiles/IPTC/IptcValue.cs index f0d40a718..1a74ea418 100644 --- a/src/ImageSharp/Metadata/Profiles/IPTC/IptcValue.cs +++ b/src/ImageSharp/Metadata/Profiles/IPTC/IptcValue.cs @@ -101,7 +101,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Iptc byte[] valueBytes; if (this.Strict && value.Length > maxLength) { - string cappedValue = value.Substring(0, maxLength); + string cappedValue = value[..maxLength]; valueBytes = this.encoding.GetBytes(cappedValue); // It is still possible that the bytes of the string exceed the limit. diff --git a/src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs index fe9acd4aa..3f325eed8 100644 --- a/src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs @@ -58,14 +58,14 @@ namespace SixLabors.ImageSharp.PixelFormats Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); - ReadOnlySpan sourcePixels = background.Slice(0, background.Length); + ReadOnlySpan sourcePixels = background[..]; PixelOperations.Instance.ToVector4(configuration, sourcePixels, backgroundSpan, PixelConversionModifiers.Scale); - ReadOnlySpan sourcePixels1 = source.Slice(0, background.Length); + ReadOnlySpan sourcePixels1 = source[..background.Length]; PixelOperations.Instance.ToVector4(configuration, sourcePixels1, sourceSpan, PixelConversionModifiers.Scale); this.BlendFunction(destinationSpan, backgroundSpan, sourceSpan, amount); - Span sourceVectors = destinationSpan.Slice(0, background.Length); + Span sourceVectors = destinationSpan[..background.Length]; PixelOperations.Instance.FromVector4Destructive(configuration, sourceVectors, destination, PixelConversionModifiers.Scale); } } @@ -120,14 +120,14 @@ namespace SixLabors.ImageSharp.PixelFormats Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); - ReadOnlySpan sourcePixels = background.Slice(0, background.Length); + ReadOnlySpan sourcePixels = background[..]; PixelOperations.Instance.ToVector4(configuration, sourcePixels, backgroundSpan, PixelConversionModifiers.Scale); - ReadOnlySpan sourcePixels1 = source.Slice(0, background.Length); + ReadOnlySpan sourcePixels1 = source[..background.Length]; PixelOperations.Instance.ToVector4(configuration, sourcePixels1, sourceSpan, PixelConversionModifiers.Scale); this.BlendFunction(destinationSpan, backgroundSpan, sourceSpan, amount); - Span sourceVectors = destinationSpan.Slice(0, background.Length); + Span sourceVectors = destinationSpan[..background.Length]; PixelOperations.Instance.FromVector4Destructive(configuration, sourceVectors, destination, PixelConversionModifiers.Scale); } } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs index 96d4579c7..240e85ff1 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs @@ -59,7 +59,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// The . /// The . [MethodImpl(InliningOptions.ShortMethod)] - public static implicit operator Color(Rgb24 source) => new Color(source); + public static implicit operator Color(Rgb24 source) => new(source); /// /// Converts a to . @@ -210,17 +210,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// [MethodImpl(InliningOptions.ShortMethod)] - public void FromRgba32(Rgba32 source) - { -#if NETSTANDARD2_0 - // See https://github.com/SixLabors/ImageSharp/issues/1275 - this.R = source.R; - this.G = source.G; - this.B = source.B; -#else - this = source.Rgb; -#endif - } + public void FromRgba32(Rgba32 source) => this = source.Rgb; /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs index 599857961..55dd80af1 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs @@ -517,7 +517,7 @@ namespace SixLabors.ImageSharp.PixelFormats { if (hex[0] == '#') { - hex = hex.Substring(1); + hex = hex[1..]; } if (hex.Length == 8) diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs index 94dc69388..6721627de 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs @@ -134,9 +134,9 @@ namespace SixLabors.ImageSharp.PixelFormats int remainder = sourcePixels.Length - endOfCompleteSlices; if (remainder > 0) { - ReadOnlySpan s = sourcePixels.Slice(endOfCompleteSlices); - Span d = destinationPixels.Slice(endOfCompleteSlices); - vectorSpan = vectorSpan.Slice(0, remainder); + ReadOnlySpan s = sourcePixels[endOfCompleteSlices..]; + Span d = destinationPixels[endOfCompleteSlices..]; + vectorSpan = vectorSpan[..remainder]; PixelOperations.Instance.ToVector4(configuration, s, vectorSpan, PixelConversionModifiers.Scale); this.FromVector4Destructive(configuration, vectorSpan, d, PixelConversionModifiers.Scale); } diff --git a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs index 38250b24a..92007732d 100644 --- a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs +++ b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs @@ -56,7 +56,7 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils // Using the last quarter of 'destVectors' as a temporary buffer to avoid allocation: int countWithoutLastItem = count - 1; - ReadOnlySpan reducedSource = sourcePixels.Slice(0, countWithoutLastItem); + ReadOnlySpan reducedSource = sourcePixels[..countWithoutLastItem]; Span lastQuarterOfDestBuffer = MemoryMarshal.Cast(destVectors).Slice((3 * count) + 1, countWithoutLastItem); pixelOperations.ToRgba32(configuration, reducedSource, lastQuarterOfDestBuffer); @@ -64,7 +64,7 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils // but we are always reading/writing at different positions: SimdUtils.ByteToNormalizedFloat( MemoryMarshal.Cast(lastQuarterOfDestBuffer), - MemoryMarshal.Cast(destVectors.Slice(0, countWithoutLastItem))); + MemoryMarshal.Cast(destVectors[..countWithoutLastItem])); destVectors[countWithoutLastItem] = sourcePixels[countWithoutLastItem].ToVector4(); diff --git a/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs index eb36183ad..e0221f815 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs @@ -295,8 +295,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution [MethodImpl(InliningOptions.ShortMethod)] public void Invoke(int y, Span span) { - Span targetRowSpan = this.targetPixels.DangerousGetRowSpan(y).Slice(this.bounds.X); - PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, span.Length), span, PixelConversionModifiers.Premultiply); + Span targetRowSpan = this.targetPixels.DangerousGetRowSpan(y)[this.bounds.X..]; + PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan[..span.Length], span, PixelConversionModifiers.Premultiply); ref Vector4 baseRef = ref MemoryMarshal.GetReference(span); for (int x = 0; x < this.bounds.Width; x++) @@ -335,9 +335,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution [MethodImpl(InliningOptions.ShortMethod)] public void Invoke(int y, Span span) { - Span targetRowSpan = this.targetPixels.DangerousGetRowSpan(y).Slice(this.bounds.X); + Span targetRowSpan = this.targetPixels.DangerousGetRowSpan(y)[this.bounds.X..]; - PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, span.Length), span, PixelConversionModifiers.Premultiply); + PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan[..span.Length], span, PixelConversionModifiers.Premultiply); Numerics.CubePowOnXYZ(span); @@ -378,8 +378,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution Vector4 low = Vector4.Zero; var high = new Vector4(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity); - Span targetPixelSpan = this.targetPixels.DangerousGetRowSpan(y).Slice(this.bounds.X); - Span sourceRowSpan = this.sourceValues.DangerousGetRowSpan(y).Slice(this.bounds.X); + Span targetPixelSpan = this.targetPixels.DangerousGetRowSpan(y)[this.bounds.X..]; + Span sourceRowSpan = this.sourceValues.DangerousGetRowSpan(y)[this.bounds.X..]; ref Vector4 sourceRef = ref MemoryMarshal.GetReference(sourceRowSpan); for (int x = 0; x < this.bounds.Width; x++) @@ -391,7 +391,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution v.Z = MathF.Pow(clamp.Z, this.inverseGamma); } - PixelOperations.Instance.FromVector4Destructive(this.configuration, sourceRowSpan.Slice(0, this.bounds.Width), targetPixelSpan, PixelConversionModifiers.Premultiply); + PixelOperations.Instance.FromVector4Destructive(this.configuration, sourceRowSpan[..this.bounds.Width], targetPixelSpan, PixelConversionModifiers.Premultiply); } } @@ -428,9 +428,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution Numerics.Clamp(MemoryMarshal.Cast(sourceRowSpan), 0, float.PositiveInfinity); Numerics.CubeRootOnXYZ(sourceRowSpan); - Span targetPixelSpan = this.targetPixels.DangerousGetRowSpan(y).Slice(this.bounds.X); + Span targetPixelSpan = this.targetPixels.DangerousGetRowSpan(y)[this.bounds.X..]; - PixelOperations.Instance.FromVector4Destructive(this.configuration, sourceRowSpan.Slice(0, this.bounds.Width), targetPixelSpan, PixelConversionModifiers.Premultiply); + PixelOperations.Instance.FromVector4Destructive(this.configuration, sourceRowSpan[..this.bounds.Width], targetPixelSpan, PixelConversionModifiers.Premultiply); } } } diff --git a/src/ImageSharp/Processing/Processors/Convolution/Convolution2DRowOperation{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/Convolution2DRowOperation{TPixel}.cs index 5ccaa77c4..8b4eaab80 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/Convolution2DRowOperation{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/Convolution2DRowOperation{TPixel}.cs @@ -67,7 +67,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution // Span is 3x bounds. int boundsX = this.bounds.X; int boundsWidth = this.bounds.Width; - Span sourceBuffer = span.Slice(0, boundsWidth); + Span sourceBuffer = span[..boundsWidth]; Span targetYBuffer = span.Slice(boundsWidth, boundsWidth); Span targetXBuffer = span.Slice(boundsWidth * 2, boundsWidth); @@ -133,7 +133,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution // Span is 3x bounds. int boundsX = this.bounds.X; int boundsWidth = this.bounds.Width; - Span sourceBuffer = span.Slice(0, boundsWidth); + Span sourceBuffer = span[..boundsWidth]; Span targetYBuffer = span.Slice(boundsWidth, boundsWidth); Span targetXBuffer = span.Slice(boundsWidth * 2, boundsWidth); diff --git a/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor{TPixel}.cs index db9557124..697351abc 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor{TPixel}.cs @@ -166,8 +166,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution int boundsWidth = this.bounds.Width; int kernelSize = this.kernel.Length; - Span sourceBuffer = span.Slice(0, this.bounds.Width); - Span targetBuffer = span.Slice(this.bounds.Width); + Span sourceBuffer = span[..this.bounds.Width]; + Span targetBuffer = span[this.bounds.Width..]; // Clear the target buffer for each row run. targetBuffer.Clear(); @@ -228,8 +228,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution int boundsWidth = this.bounds.Width; int kernelSize = this.kernel.Length; - Span sourceBuffer = span.Slice(0, this.bounds.Width); - Span targetBuffer = span.Slice(this.bounds.Width); + Span sourceBuffer = span[..this.bounds.Width]; + Span targetBuffer = span[this.bounds.Width..]; // Clear the target buffer for each row run. targetBuffer.Clear(); @@ -327,8 +327,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution int boundsWidth = this.bounds.Width; int kernelSize = this.kernel.Length; - Span sourceBuffer = span.Slice(0, this.bounds.Width); - Span targetBuffer = span.Slice(this.bounds.Width); + Span sourceBuffer = span[..this.bounds.Width]; + Span targetBuffer = span[this.bounds.Width..]; ref int sampleRowBase = ref Unsafe.Add(ref MemoryMarshal.GetReference(this.map.GetRowOffsetSpan()), (y - this.bounds.Y) * kernelSize); @@ -392,8 +392,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution int boundsWidth = this.bounds.Width; int kernelSize = this.kernel.Length; - Span sourceBuffer = span.Slice(0, this.bounds.Width); - Span targetBuffer = span.Slice(this.bounds.Width); + Span sourceBuffer = span[..this.bounds.Width]; + Span targetBuffer = span[this.bounds.Width..]; ref int sampleRowBase = ref Unsafe.Add(ref MemoryMarshal.GetReference(this.map.GetRowOffsetSpan()), (y - this.bounds.Y) * kernelSize); diff --git a/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor{TPixel}.cs index fa0a01229..ed8b63ab2 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor{TPixel}.cs @@ -114,8 +114,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution // Span is 2x bounds. int boundsX = this.bounds.X; int boundsWidth = this.bounds.Width; - Span sourceBuffer = span.Slice(0, this.bounds.Width); - Span targetBuffer = span.Slice(this.bounds.Width); + Span sourceBuffer = span[..this.bounds.Width]; + Span targetBuffer = span[this.bounds.Width..]; ref Vector4 targetRowRef = ref MemoryMarshal.GetReference(span); Span targetRowSpan = this.targetPixels.DangerousGetRowSpan(y).Slice(boundsX, boundsWidth); diff --git a/src/ImageSharp/Processing/Processors/Convolution/KernelSamplingMap.cs b/src/ImageSharp/Processing/Processors/Convolution/KernelSamplingMap.cs index 06d4a2755..a455df412 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/KernelSamplingMap.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/KernelSamplingMap.cs @@ -110,8 +110,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution switch (borderMode) { case BorderWrappingMode.Repeat: - Numerics.Clamp(span.Slice(0, affectedSize), min, max); - Numerics.Clamp(span.Slice(span.Length - affectedSize), min, max); + Numerics.Clamp(span[..affectedSize], min, max); + Numerics.Clamp(span[^affectedSize..], min, max); break; case BorderWrappingMode.Mirror: var min2dec = min + min - 1; diff --git a/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.cs b/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.cs index 0e85b20ea..4c6e8e043 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.cs @@ -124,7 +124,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering for (int y = bounds.Top; y < bounds.Bottom; y++) { ReadOnlySpan sourceRow = sourceBuffer.DangerousGetRowSpan(y).Slice(bounds.X, bounds.Width); - Span destRow = destination.GetWritablePixelRowSpanUnsafe(y - bounds.Y).Slice(0, sourceRow.Length); + Span destRow = destination.GetWritablePixelRowSpanUnsafe(y - bounds.Y)[..sourceRow.Length]; for (int x = 0; x < sourceRow.Length; x++) { diff --git a/src/ImageSharp/Processing/Processors/Filters/OpaqueProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Filters/OpaqueProcessor{TPixel}.cs index 5c1282666..7cc115137 100644 --- a/src/ImageSharp/Processing/Processors/Filters/OpaqueProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Filters/OpaqueProcessor{TPixel}.cs @@ -51,8 +51,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters [MethodImpl(InliningOptions.ShortMethod)] public void Invoke(int y, Span span) { - Span targetRowSpan = this.target.DangerousGetRowSpan(y).Slice(this.bounds.X); - PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, span.Length), span, PixelConversionModifiers.Scale); + Span targetRowSpan = this.target.DangerousGetRowSpan(y)[this.bounds.X..]; + PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan[..span.Length], span, PixelConversionModifiers.Scale); ref Vector4 baseRef = ref MemoryMarshal.GetReference(span); for (int x = 0; x < this.bounds.Width; x++) diff --git a/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs index 433207562..c27118be4 100644 --- a/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs @@ -107,12 +107,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization } /// -#if NETSTANDARD2_0 - // https://github.com/SixLabors/ImageSharp/issues/1204 - [MethodImpl(MethodImplOptions.NoOptimization)] -#else [MethodImpl(InliningOptions.ShortMethod)] -#endif public void Invoke(int y) { ref int histogramBase = ref MemoryMarshal.GetReference(this.histogramBuffer.GetSpan()); @@ -156,12 +151,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization } /// -#if NETSTANDARD2_0 - // https://github.com/SixLabors/ImageSharp/issues/1204 - [MethodImpl(MethodImplOptions.NoOptimization)] -#else [MethodImpl(InliningOptions.ShortMethod)] -#endif public void Invoke(int y) { ref int cdfBase = ref MemoryMarshal.GetReference(this.cdfBuffer.GetSpan()); diff --git a/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer{TPixel}.cs index 4e47b0ac5..a066bfdc4 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer{TPixel}.cs @@ -108,7 +108,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization } this.octree.Palletize(paletteSpan, max, ref paletteIndex); - ReadOnlyMemory result = this.paletteOwner.Memory.Slice(0, paletteSpan.Length); + ReadOnlyMemory result = this.paletteOwner.Memory[..paletteSpan.Length]; // When called multiple times by QuantizerUtilities.BuildPalette // this prevents memory churn caused by reallocation. diff --git a/src/ImageSharp/Processing/Processors/Quantization/WuQuantizer{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/WuQuantizer{TPixel}.cs index 576e34a26..39c753722 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/WuQuantizer{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/WuQuantizer{TPixel}.cs @@ -127,7 +127,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization this.BuildCube(); // Slice again since maxColors has been updated since the buffer was created. - Span paletteSpan = this.paletteOwner.GetSpan().Slice(0, this.maxColors); + Span paletteSpan = this.paletteOwner.GetSpan()[..this.maxColors]; ReadOnlySpan momentsSpan = this.momentsOwner.GetSpan(); for (int k = 0; k < paletteSpan.Length; k++) { @@ -142,7 +142,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization } } - ReadOnlyMemory result = this.paletteOwner.Memory.Slice(0, paletteSpan.Length); + ReadOnlyMemory result = this.paletteOwner.Memory[..paletteSpan.Length]; if (this.isDithering) { // When called multiple times by QuantizerUtilities.BuildPalette diff --git a/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs index 92f3e8b98..32c93c281 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs @@ -86,9 +86,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms [MethodImpl(InliningOptions.ShortMethod)] public void Invoke(int y) { - Span sourceRow = this.source.DangerousGetRowSpan(y).Slice(this.bounds.Left); + Span sourceRow = this.source.DangerousGetRowSpan(y)[this.bounds.Left..]; Span targetRow = this.destination.DangerousGetRowSpan(y - this.bounds.Top); - sourceRow.Slice(0, this.bounds.Width).CopyTo(targetRow); + sourceRow[..this.bounds.Width].CopyTo(targetRow); } } } diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs index 888143af4..cb8b68b57 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs @@ -102,7 +102,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms [MethodImpl(InliningOptions.ShortMethod)] public Span GetColumnSpan(int x, int startY) - => this.transposedFirstPassBuffer.DangerousGetRowSpan(x).Slice(startY - this.currentWindow.Min); + => this.transposedFirstPassBuffer.DangerousGetRowSpan(x)[(startY - this.currentWindow.Min)..]; public void Initialize() => this.CalculateFirstPassValues(this.currentWindow); diff --git a/tests/ImageSharp.Tests/Helpers/RuntimeEnvironmentTests.cs b/tests/ImageSharp.Tests/Helpers/RuntimeEnvironmentTests.cs index 39a5dccce..d61b8b86c 100644 --- a/tests/ImageSharp.Tests/Helpers/RuntimeEnvironmentTests.cs +++ b/tests/ImageSharp.Tests/Helpers/RuntimeEnvironmentTests.cs @@ -4,22 +4,12 @@ using System.Runtime.InteropServices; using Xunit; -#pragma warning disable IDE0022 // Use expression body for methods namespace SixLabors.ImageSharp.Tests.Helpers { public class RuntimeEnvironmentTests { [Fact] - public void CanDetectNetCore() - { -#if NET5_0_OR_GREATER - Assert.False(RuntimeEnvironment.IsNetCore); -#elif NETCOREAPP - Assert.True(RuntimeEnvironment.IsNetCore); -#else - Assert.False(RuntimeEnvironment.IsNetCore); -#endif - } + public void CanDetectNetCore() => Assert.False(RuntimeEnvironment.IsNetCore); [Fact] public void CanDetectOSPlatform() diff --git a/tests/ImageSharp.Tests/Memory/Allocators/UniformUnmanagedMemoryPoolTests.Trim.cs b/tests/ImageSharp.Tests/Memory/Allocators/UniformUnmanagedMemoryPoolTests.Trim.cs index a65fd2325..5b9d430af 100644 --- a/tests/ImageSharp.Tests/Memory/Allocators/UniformUnmanagedMemoryPoolTests.Trim.cs +++ b/tests/ImageSharp.Tests/Memory/Allocators/UniformUnmanagedMemoryPoolTests.Trim.cs @@ -1,11 +1,9 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; using System.Collections.Generic; -using System.IO; using System.Runtime.CompilerServices; -using System.Text; using System.Threading; using Microsoft.DotNet.RemoteExecutor; using SixLabors.ImageSharp.Memory.Internals; @@ -109,7 +107,6 @@ namespace SixLabors.ImageSharp.Tests.Memory.Allocators } } -#if NETCOREAPP3_1_OR_GREATER public static readonly bool Is32BitProcess = !Environment.Is64BitProcess; private static readonly List PressureArrays = new(); @@ -121,21 +118,21 @@ namespace SixLabors.ImageSharp.Tests.Memory.Allocators static void RunTest() { Assert.False(Environment.Is64BitProcess); - const int OneMb = 1 << 20; + const int oneMb = 1 << 20; var trimSettings = new UniformUnmanagedMemoryPool.TrimSettings { HighPressureThresholdRate = 0.2f }; GCMemoryInfo memInfo = GC.GetGCMemoryInfo(); - int highLoadThreshold = (int)(memInfo.HighMemoryLoadThresholdBytes / OneMb); + int highLoadThreshold = (int)(memInfo.HighMemoryLoadThresholdBytes / oneMb); highLoadThreshold = (int)(trimSettings.HighPressureThresholdRate * highLoadThreshold); - var pool = new UniformUnmanagedMemoryPool(OneMb, 16, trimSettings); + var pool = new UniformUnmanagedMemoryPool(oneMb, 16, trimSettings); pool.Return(pool.Rent(16)); Assert.Equal(16, UnmanagedMemoryHandle.TotalOutstandingHandles); for (int i = 0; i < highLoadThreshold; i++) { - byte[] array = new byte[OneMb]; + byte[] array = new byte[oneMb]; TouchPage(array); PressureArrays.Add(array); } @@ -163,7 +160,6 @@ namespace SixLabors.ImageSharp.Tests.Memory.Allocators } } } -#endif } } } diff --git a/tests/ImageSharp.Tests/Memory/Allocators/UniformUnmanagedPoolMemoryAllocatorTests.cs b/tests/ImageSharp.Tests/Memory/Allocators/UniformUnmanagedPoolMemoryAllocatorTests.cs index e002fcc8e..2cd1c696d 100644 --- a/tests/ImageSharp.Tests/Memory/Allocators/UniformUnmanagedPoolMemoryAllocatorTests.cs +++ b/tests/ImageSharp.Tests/Memory/Allocators/UniformUnmanagedPoolMemoryAllocatorTests.cs @@ -380,7 +380,6 @@ namespace SixLabors.ImageSharp.Tests.Memory.Allocators } } -#if NETCOREAPP3_1_OR_GREATER [Fact] public void Issue2001_NegativeMemoryReportedByGc() { @@ -393,6 +392,5 @@ namespace SixLabors.ImageSharp.Tests.Memory.Allocators _ = MemoryAllocator.Create(); } } -#endif } } diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs index c22b5dbcd..3a6c04540 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs @@ -20,13 +20,11 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations [Trait("Category", "PixelFormats")] public partial class PixelOperationsTests { -#pragma warning disable SA1313 // Parameter names should begin with lower-case letter [Theory] [WithBlankImages(1, 1, PixelTypes.All)] public void GetGlobalInstance(TestImageProvider _) where T : unmanaged, IPixel => Assert.NotNull(PixelOperations.Instance); } -#pragma warning restore SA1313 // Parameter names should begin with lower-case letter public abstract class PixelOperationsTests : MeasureFixture where TPixel : unmanaged, IPixel diff --git a/tests/ImageSharp.Tests/Primitives/ColorMatrixTests.cs b/tests/ImageSharp.Tests/Primitives/ColorMatrixTests.cs index c214a4caa..2e418c5a7 100644 --- a/tests/ImageSharp.Tests/Primitives/ColorMatrixTests.cs +++ b/tests/ImageSharp.Tests/Primitives/ColorMatrixTests.cs @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.Tests.Primitives { public class ColorMatrixTests { - private readonly ApproximateFloatComparer approximateFloatComparer = new ApproximateFloatComparer(1e-6f); + private readonly ApproximateFloatComparer approximateFloatComparer = new(1e-6f); [Fact] public void ColorMatrixIdentityIsCorrect() @@ -47,8 +47,8 @@ namespace SixLabors.ImageSharp.Tests.Primitives [Fact] public void ColorMatrixMultiply() { - ColorMatrix value1 = this.CreateAllTwos(); - ColorMatrix value2 = this.CreateAllThrees(); + ColorMatrix value1 = CreateAllTwos(); + ColorMatrix value2 = CreateAllThrees(); var m = default(ColorMatrix); @@ -88,35 +88,34 @@ namespace SixLabors.ImageSharp.Tests.Primitives [Fact] public void ColorMatrixMultiplyScalar() { - ColorMatrix m = this.CreateAllTwos(); - Assert.Equal(this.CreateAllFours(), m * 2, this.approximateFloatComparer); + ColorMatrix m = CreateAllTwos(); + Assert.Equal(CreateAllFours(), m * 2, this.approximateFloatComparer); } [Fact] public void ColorMatrixSubtract() { - ColorMatrix m = this.CreateAllOnes() + this.CreateAllTwos(); - Assert.Equal(this.CreateAllThrees(), m); + ColorMatrix m = CreateAllOnes() + CreateAllTwos(); + Assert.Equal(CreateAllThrees(), m); } [Fact] public void ColorMatrixNegate() { - ColorMatrix m = this.CreateAllOnes() * -1F; - Assert.Equal(m, -this.CreateAllOnes()); + ColorMatrix m = CreateAllOnes() * -1F; + Assert.Equal(m, -CreateAllOnes()); } [Fact] public void ColorMatrixAdd() { - ColorMatrix m = this.CreateAllOnes() + this.CreateAllTwos(); - Assert.Equal(this.CreateAllThrees(), m); + ColorMatrix m = CreateAllOnes() + CreateAllTwos(); + Assert.Equal(CreateAllThrees(), m); } [Fact] public void ColorMatrixHashCode() { -#if NETCOREAPP2_1 ColorMatrix m = KnownFilterMatrices.CreateBrightnessFilter(.5F); HashCode hash = default; hash.Add(m.M11); @@ -141,7 +140,6 @@ namespace SixLabors.ImageSharp.Tests.Primitives hash.Add(m.M54); Assert.Equal(hash.ToHashCode(), m.GetHashCode()); -#endif } [Fact] @@ -163,9 +161,8 @@ namespace SixLabors.ImageSharp.Tests.Primitives Assert.Equal(expected, m.ToString()); } - private ColorMatrix CreateAllOnes() - { - return new ColorMatrix + private static ColorMatrix CreateAllOnes() + => new() { M11 = 1F, M12 = 1F, @@ -188,11 +185,9 @@ namespace SixLabors.ImageSharp.Tests.Primitives M53 = 1F, M54 = 1F }; - } - private ColorMatrix CreateAllTwos() - { - return new ColorMatrix + private static ColorMatrix CreateAllTwos() + => new() { M11 = 2F, M12 = 2F, @@ -215,11 +210,9 @@ namespace SixLabors.ImageSharp.Tests.Primitives M53 = 2F, M54 = 2F }; - } - private ColorMatrix CreateAllThrees() - { - return new ColorMatrix + private static ColorMatrix CreateAllThrees() + => new() { M11 = 3F, M12 = 3F, @@ -242,11 +235,9 @@ namespace SixLabors.ImageSharp.Tests.Primitives M53 = 3F, M54 = 3F }; - } - private ColorMatrix CreateAllFours() - { - return new ColorMatrix + private static ColorMatrix CreateAllFours() + => new() { M11 = 4F, M12 = 4F, @@ -269,6 +260,5 @@ namespace SixLabors.ImageSharp.Tests.Primitives M53 = 4F, M54 = 4F }; - } } } diff --git a/tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs b/tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs index b8668b211..9e0fd2d93 100644 --- a/tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs +++ b/tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -using System.Diagnostics.CodeAnalysis; using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing.Processors.Convolution; using Xunit; @@ -9,7 +8,6 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Processing.Convolution { [Trait("Category", "Processors")] - [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1313:Parameter names should begin with lower-case letter", Justification = "OK. Used for TheoryData compatibility.")] public class DetectEdgesTest : BaseImageOperationsExtensionTest { [Fact] @@ -32,8 +30,8 @@ namespace SixLabors.ImageSharp.Tests.Processing.Convolution Assert.Equal(KnownEdgeDetectorKernels.Sobel, processor.Kernel); } - public static TheoryData EdgeDetector2DKernelData = - new TheoryData + public static TheoryData EdgeDetector2DKernelData { get; } = + new() { { KnownEdgeDetectorKernels.Kayyali, true }, { KnownEdgeDetectorKernels.Kayyali, false }, @@ -91,8 +89,8 @@ namespace SixLabors.ImageSharp.Tests.Processing.Convolution Assert.Equal(kernel, processor.Kernel); } - public static TheoryData EdgeDetectorKernelData = - new TheoryData + public static TheoryData EdgeDetectorKernelData { get; } = + new() { { KnownEdgeDetectorKernels.Laplacian3x3, true }, { KnownEdgeDetectorKernels.Laplacian3x3, false }, @@ -146,8 +144,8 @@ namespace SixLabors.ImageSharp.Tests.Processing.Convolution Assert.Equal(kernel, processor.Kernel); } - public static TheoryData EdgeDetectorCompassKernelData = - new TheoryData + public static TheoryData EdgeDetectorCompassKernelData { get; } = + new() { { KnownEdgeDetectorKernels.Kirsch, true }, { KnownEdgeDetectorKernels.Kirsch, false }, diff --git a/tests/ImageSharp.Tests/Processing/Processors/Convolution/DetectEdgesTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Convolution/DetectEdgesTest.cs index 90f407484..02bdb8267 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Convolution/DetectEdgesTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Convolution/DetectEdgesTest.cs @@ -13,7 +13,6 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution { [Trait("Category", "Processors")] [GroupOutput("Convolution")] - [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1313:Parameter names should begin with lower-case letter", Justification = "OK. Used for TheoryData compatibility.")] public class DetectEdgesTest { private static readonly ImageComparer OpaqueComparer = ImageComparer.TolerantPercentage(0.01F); diff --git a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataCurves.cs b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataCurves.cs index d79880d8c..1b91a11b5 100644 --- a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataCurves.cs +++ b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataCurves.cs @@ -8,7 +8,6 @@ namespace SixLabors.ImageSharp.Tests { internal static class IccTestDataCurves { -#pragma warning disable SA1118 // Parameter should not span multiple lines /// /// Channels: 3 /// @@ -26,7 +25,6 @@ namespace SixLabors.ImageSharp.Tests new IccResponseNumber[] { IccTestDataNonPrimitives.ResponseNumber_Val3, IccTestDataNonPrimitives.ResponseNumber_Val4 }, new IccResponseNumber[] { IccTestDataNonPrimitives.ResponseNumber_Val5, IccTestDataNonPrimitives.ResponseNumber_Val6 }, }); -#pragma warning restore SA1118 // Parameter should not span multiple lines /// /// Channels: 3 diff --git a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataProfiles.cs b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataProfiles.cs index 1710dba9a..feabf0e19 100644 --- a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataProfiles.cs +++ b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataProfiles.cs @@ -78,7 +78,6 @@ namespace SixLabors.ImageSharp.Tests 0x64, 0x63, 0x62, 0x61, // CreatorSignature }, profileId, -#pragma warning disable SA1118 // Parameter should not span multiple lines new byte[] { // Padding @@ -93,12 +92,10 @@ namespace SixLabors.ImageSharp.Tests (byte)(nrOfEntries >> 8), (byte)nrOfEntries }); -#pragma warning restore SA1118 // Parameter should not span multiple lines } public static readonly byte[] Profile_Random_Array = ArrayHelper.Concat( CreateHeaderRandomArray(168, 2, Profile_Random_Id_Array), -#pragma warning disable SA1118 // Parameter should not span multiple lines new byte[] { 0x00, 0x00, 0x00, 0x00, // tag signature (Unknown) @@ -108,7 +105,6 @@ namespace SixLabors.ImageSharp.Tests 0x00, 0x00, 0x00, 0x9C, // tag offset (156) 0x00, 0x00, 0x00, 0x0C, // tag size (12) }, -#pragma warning restore SA1118 // Parameter should not span multiple lines IccTestDataTagDataEntry.TagDataEntryHeader_UnknownArr, IccTestDataTagDataEntry.Unknown_Arr); diff --git a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataTagDataEntry.cs b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataTagDataEntry.cs index 9cbf4e120..9b56bb98c 100644 --- a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataTagDataEntry.cs +++ b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataTagDataEntry.cs @@ -237,8 +237,6 @@ namespace SixLabors.ImageSharp.Tests new IccCurveTagDataEntry[] { Curve_Val_1, Curve_Val_2, Curve_Val_0 }, IccTestDataLut.CLUT_Val16, new IccCurveTagDataEntry[] { Curve_Val_2, Curve_Val_1 }); - -#pragma warning disable SA1115 // Parameter should follow comma public static readonly byte[] LutAToB_Arr = ArrayHelper.Concat( new byte[] { 0x02, 0x03, 0x00, 0x00 }, new byte[] { 0x00, 0x00, 0x00, 0x20 }, // b: 32 @@ -275,7 +273,6 @@ namespace SixLabors.ImageSharp.Tests CurveFull_1, // 14 bytes new byte[] { 0x00, 0x00 }); // Padding -#pragma warning restore SA1115 // Parameter should follow comma public static readonly object[][] LutAToBTagDataEntryTestData = { @@ -293,8 +290,6 @@ namespace SixLabors.ImageSharp.Tests null, IccTestDataLut.CLUT_Val16, new[] { Curve_Val_2, Curve_Val_1, Curve_Val_0 }); - -#pragma warning disable SA1115 // Parameter should follow comma public static readonly byte[] LutBToA_Arr = ArrayHelper.Concat( new byte[] { 0x02, 0x03, 0x00, 0x00 }, @@ -320,7 +315,6 @@ namespace SixLabors.ImageSharp.Tests new byte[] { 0x00, 0x00 }, // Padding CurveFull_0); // 12 bytes -#pragma warning restore SA1115 // Parameter should follow comma public static readonly object[][] LutBToATagDataEntryTestData = { diff --git a/tests/ImageSharp.Tests/TestUtilities/PausedStream.cs b/tests/ImageSharp.Tests/TestUtilities/PausedStream.cs index 4dd1e010f..511b2cef5 100644 --- a/tests/ImageSharp.Tests/TestUtilities/PausedStream.cs +++ b/tests/ImageSharp.Tests/TestUtilities/PausedStream.cs @@ -122,7 +122,6 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities protected override void Dispose(bool disposing) => this.innerStream.Dispose(); -#if NETCOREAPP public override void CopyTo(Stream destination, int bufferSize) => this.Await(() => this.innerStream.CopyTo(destination, bufferSize)); public override int Read(Span buffer) @@ -140,6 +139,5 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities } public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) => this.Await(() => this.innerStream.WriteAsync(buffer, cancellationToken)); -#endif } } diff --git a/tests/ImageSharp.Tests/TestUtilities/PixelTypes.cs b/tests/ImageSharp.Tests/TestUtilities/PixelTypes.cs index e78659aa6..e0a6ec860 100644 --- a/tests/ImageSharp.Tests/TestUtilities/PixelTypes.cs +++ b/tests/ImageSharp.Tests/TestUtilities/PixelTypes.cs @@ -12,7 +12,6 @@ namespace SixLabors.ImageSharp.Tests [Flags] public enum PixelTypes { -#pragma warning disable SA1602 // Enumeration items should be documented Undefined = 0, A8 = 1 << 0, @@ -75,7 +74,5 @@ namespace SixLabors.ImageSharp.Tests // "All" is handled as a separate, individual case instead of using bitwise OR All = 30 - -#pragma warning restore SA1602 // Enumeration items should be documented } } diff --git a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs index 0bb0cf262..86dfb11ee 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs @@ -781,7 +781,6 @@ namespace SixLabors.ImageSharp.Tests internal class AllocatorBufferCapacityConfigurator { -#pragma warning disable CS0618 // 'ArrayPoolMemoryAllocator' is obsolete private readonly TestMemoryAllocator allocator; private readonly int pixelSizeInBytes; @@ -790,7 +789,6 @@ namespace SixLabors.ImageSharp.Tests this.allocator = allocator; this.pixelSizeInBytes = pixelSizeInBytes; } -#pragma warning restore CS0618 public void InBytes(int totalBytes) => this.allocator.BufferCapacityInBytes = totalBytes; From ca0b2841faa960929854d56ea068942385f3c111 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Sun, 24 Jul 2022 01:09:15 +1000 Subject: [PATCH 03/20] Remove obsolete OSX transform methods --- .../AffineTransformProcessor{TPixel}.cs | 81 ------------------- .../ProjectiveTransformProcessor{TPixel}.cs | 80 ------------------ 2 files changed, 161 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor{TPixel}.cs index 01de78198..680ada1d3 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor{TPixel}.cs @@ -2,11 +2,8 @@ // Licensed under the Six Labors Split License. using System; -using System.Buffers; -using System.Diagnostics.CodeAnalysis; using System.Numerics; using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; @@ -183,19 +180,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms [MethodImpl(InliningOptions.ShortMethod)] public void Invoke(in RowInterval rows, Span span) { - if (RuntimeEnvironment.IsOSPlatform(OSPlatform.OSX) - && RuntimeEnvironment.IsNetCore) - { - // There's something wrong with the JIT in .NET Core 3.1 on certain - // macOS machines so we have to use different pipelines. - // It's: - // - Not reproducable locally - // - Doesn't seem to be triggered by the bulk Numerics.UnPremultiply method but by caller. - // https://github.com/SixLabors/ImageSharp/pull/1591 - this.InvokeMacOS(in rows, span); - return; - } - Matrix3x2 matrix = this.matrix; TResampler sampler = this.sampler; float yRadius = this.yRadius; @@ -256,71 +240,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms PixelConversionModifiers.Scale); } } - - [ExcludeFromCodeCoverage] - [MethodImpl(InliningOptions.ShortMethod)] - private void InvokeMacOS(in RowInterval rows, Span span) - { - Matrix3x2 matrix = this.matrix; - TResampler sampler = this.sampler; - float yRadius = this.yRadius; - float xRadius = this.xRadius; - int minY = this.bounds.Y; - int maxY = this.bounds.Bottom - 1; - int minX = this.bounds.X; - int maxX = this.bounds.Right - 1; - - for (int y = rows.Min; y < rows.Max; y++) - { - Span rowSpan = this.destination.DangerousGetRowSpan(y); - PixelOperations.Instance.ToVector4( - this.configuration, - rowSpan, - span, - PixelConversionModifiers.Scale); - - for (int x = 0; x < span.Length; x++) - { - var point = Vector2.Transform(new Vector2(x, y), matrix); - float pY = point.Y; - float pX = point.X; - - int top = LinearTransformUtility.GetRangeStart(yRadius, pY, minY, maxY); - int bottom = LinearTransformUtility.GetRangeEnd(yRadius, pY, minY, maxY); - int left = LinearTransformUtility.GetRangeStart(xRadius, pX, minX, maxX); - int right = LinearTransformUtility.GetRangeEnd(xRadius, pX, minX, maxX); - - if (bottom == top || right == left) - { - continue; - } - - Vector4 sum = Vector4.Zero; - for (int yK = top; yK <= bottom; yK++) - { - float yWeight = sampler.GetValue(yK - pY); - - for (int xK = left; xK <= right; xK++) - { - float xWeight = sampler.GetValue(xK - pX); - - Vector4 current = this.source.GetElementUnsafe(xK, yK).ToScaledVector4(); - Numerics.Premultiply(ref current); - sum += current * xWeight * yWeight; - } - } - - Numerics.UnPremultiply(ref sum); - span[x] = sum; - } - - PixelOperations.Instance.FromVector4Destructive( - this.configuration, - span, - rowSpan, - PixelConversionModifiers.Scale); - } - } } } } diff --git a/src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs index a379dfa8f..9dbf4708f 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs @@ -2,10 +2,8 @@ // Licensed under the Six Labors Split License. using System; -using System.Diagnostics.CodeAnalysis; using System.Numerics; using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; @@ -182,19 +180,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms [MethodImpl(InliningOptions.ShortMethod)] public void Invoke(in RowInterval rows, Span span) { - if (RuntimeEnvironment.IsOSPlatform(OSPlatform.OSX) - && RuntimeEnvironment.IsNetCore) - { - // There's something wrong with the JIT in .NET Core 3.1 on certain - // macOS machines so we have to use different pipelines. - // It's: - // - Not reproducable locally - // - Doesn't seem to be triggered by the bulk Numerics.UnPremultiply method but by caller. - // https://github.com/SixLabors/ImageSharp/pull/1591 - this.InvokeMacOS(in rows, span); - return; - } - Matrix4x4 matrix = this.matrix; TResampler sampler = this.sampler; float yRadius = this.yRadius; @@ -255,71 +240,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms PixelConversionModifiers.Scale); } } - - [ExcludeFromCodeCoverage] - [MethodImpl(InliningOptions.ShortMethod)] - public void InvokeMacOS(in RowInterval rows, Span span) - { - Matrix4x4 matrix = this.matrix; - TResampler sampler = this.sampler; - float yRadius = this.yRadius; - float xRadius = this.xRadius; - int minY = this.bounds.Y; - int maxY = this.bounds.Bottom - 1; - int minX = this.bounds.X; - int maxX = this.bounds.Right - 1; - - for (int y = rows.Min; y < rows.Max; y++) - { - Span rowSpan = this.destination.DangerousGetRowSpan(y); - PixelOperations.Instance.ToVector4( - this.configuration, - rowSpan, - span, - PixelConversionModifiers.Scale); - - for (int x = 0; x < span.Length; x++) - { - Vector2 point = TransformUtils.ProjectiveTransform2D(x, y, matrix); - float pY = point.Y; - float pX = point.X; - - int top = LinearTransformUtility.GetRangeStart(yRadius, pY, minY, maxY); - int bottom = LinearTransformUtility.GetRangeEnd(yRadius, pY, minY, maxY); - int left = LinearTransformUtility.GetRangeStart(xRadius, pX, minX, maxX); - int right = LinearTransformUtility.GetRangeEnd(xRadius, pX, minX, maxX); - - if (bottom <= top || right <= left) - { - continue; - } - - Vector4 sum = Vector4.Zero; - for (int yK = top; yK <= bottom; yK++) - { - float yWeight = sampler.GetValue(yK - pY); - - for (int xK = left; xK <= right; xK++) - { - float xWeight = sampler.GetValue(xK - pX); - - Vector4 current = this.source.GetElementUnsafe(xK, yK).ToScaledVector4(); - Numerics.Premultiply(ref current); - sum += current * xWeight * yWeight; - } - } - - Numerics.UnPremultiply(ref sum); - span[x] = sum; - } - - PixelOperations.Instance.FromVector4Destructive( - this.configuration, - span, - rowSpan, - PixelConversionModifiers.Scale); - } - } } } } From 3fb4787c3a98c20ec5e1c775611688a94e3ddcf7 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 26 Jul 2022 17:33:34 +1000 Subject: [PATCH 04/20] Normalize some reference swapping --- .../Common/Helpers/RuntimeUtility.cs | 48 ++++++++++++++ .../Common/Helpers/UnitConverter.cs | 3 +- .../Formats/Jpeg/Components/Block8x8.cs | 59 +++++++++-------- .../Formats/Jpeg/Components/Block8x8F.cs | 64 +++++++++---------- src/ImageSharp/Formats/Png/PngEncoderCore.cs | 31 ++++----- src/ImageSharp/Formats/Webp/Lossy/QuantEnc.cs | 12 ++-- .../Formats/Webp/Lossy/Vp8EncIterator.cs | 3 + 7 files changed, 128 insertions(+), 92 deletions(-) create mode 100644 src/ImageSharp/Common/Helpers/RuntimeUtility.cs diff --git a/src/ImageSharp/Common/Helpers/RuntimeUtility.cs b/src/ImageSharp/Common/Helpers/RuntimeUtility.cs new file mode 100644 index 000000000..66e2fc9dc --- /dev/null +++ b/src/ImageSharp/Common/Helpers/RuntimeUtility.cs @@ -0,0 +1,48 @@ +// Copyright (c) Six Labors. +// Licensed under the Six Labors Split License. + +using System; +using System.Runtime.CompilerServices; + +namespace SixLabors.ImageSharp.Common.Helpers +{ + /// + /// A helper class that with utility methods for dealing with references, and other low-level details. + /// + internal static class RuntimeUtility + { + /// + /// Swaps the two references. + /// + /// The type to swap. + /// The first item. + /// The second item. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Swap(ref T a, ref T b) + { + // Tuple swap uses 2 more IL bytes +#pragma warning disable IDE0180 // Use tuple to swap values + T tmp = a; +#pragma warning restore IDE0180 // Use tuple to swap values + a = b; + b = tmp; + } + + /// + /// Swaps the two references. + /// + /// The type to swap. + /// The first item. + /// The second item. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Swap(ref Span a, ref Span b) + { + // Tuple swap uses 2 more IL bytes +#pragma warning disable IDE0180 // Use tuple to swap values + Span tmp = a; +#pragma warning restore IDE0180 // Use tuple to swap values + a = b; + b = tmp; + } + } +} diff --git a/src/ImageSharp/Common/Helpers/UnitConverter.cs b/src/ImageSharp/Common/Helpers/UnitConverter.cs index ba7bdb0e0..09bb40312 100644 --- a/src/ImageSharp/Common/Helpers/UnitConverter.cs +++ b/src/ImageSharp/Common/Helpers/UnitConverter.cs @@ -114,11 +114,10 @@ namespace SixLabors.ImageSharp.Common.Helpers case PixelResolutionUnit.PixelsPerCentimeter: break; case PixelResolutionUnit.PixelsPerMeter: - { + unit = PixelResolutionUnit.PixelsPerCentimeter; horizontal = MeterToCm(horizontal); vertical = MeterToCm(vertical); - } break; default: diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8.cs b/src/ImageSharp/Formats/Jpeg/Components/Block8x8.cs index 86c69a8be..c66df0a94 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8.cs @@ -8,6 +8,7 @@ using System.Runtime.InteropServices; using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; using System.Text; +using SixLabors.ImageSharp.Common.Helpers; namespace SixLabors.ImageSharp.Formats.Jpeg.Components { @@ -226,48 +227,46 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components ref short elemRef = ref Unsafe.As(ref this); // row #0 - Swap(ref Unsafe.Add(ref elemRef, 1), ref Unsafe.Add(ref elemRef, 8)); - Swap(ref Unsafe.Add(ref elemRef, 2), ref Unsafe.Add(ref elemRef, 16)); - Swap(ref Unsafe.Add(ref elemRef, 3), ref Unsafe.Add(ref elemRef, 24)); - Swap(ref Unsafe.Add(ref elemRef, 4), ref Unsafe.Add(ref elemRef, 32)); - Swap(ref Unsafe.Add(ref elemRef, 5), ref Unsafe.Add(ref elemRef, 40)); - Swap(ref Unsafe.Add(ref elemRef, 6), ref Unsafe.Add(ref elemRef, 48)); - Swap(ref Unsafe.Add(ref elemRef, 7), ref Unsafe.Add(ref elemRef, 56)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 1), ref Unsafe.Add(ref elemRef, 8)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 2), ref Unsafe.Add(ref elemRef, 16)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 3), ref Unsafe.Add(ref elemRef, 24)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 4), ref Unsafe.Add(ref elemRef, 32)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 5), ref Unsafe.Add(ref elemRef, 40)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 6), ref Unsafe.Add(ref elemRef, 48)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 7), ref Unsafe.Add(ref elemRef, 56)); // row #1 - Swap(ref Unsafe.Add(ref elemRef, 10), ref Unsafe.Add(ref elemRef, 17)); - Swap(ref Unsafe.Add(ref elemRef, 11), ref Unsafe.Add(ref elemRef, 25)); - Swap(ref Unsafe.Add(ref elemRef, 12), ref Unsafe.Add(ref elemRef, 33)); - Swap(ref Unsafe.Add(ref elemRef, 13), ref Unsafe.Add(ref elemRef, 41)); - Swap(ref Unsafe.Add(ref elemRef, 14), ref Unsafe.Add(ref elemRef, 49)); - Swap(ref Unsafe.Add(ref elemRef, 15), ref Unsafe.Add(ref elemRef, 57)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 10), ref Unsafe.Add(ref elemRef, 17)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 11), ref Unsafe.Add(ref elemRef, 25)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 12), ref Unsafe.Add(ref elemRef, 33)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 13), ref Unsafe.Add(ref elemRef, 41)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 14), ref Unsafe.Add(ref elemRef, 49)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 15), ref Unsafe.Add(ref elemRef, 57)); // row #2 - Swap(ref Unsafe.Add(ref elemRef, 19), ref Unsafe.Add(ref elemRef, 26)); - Swap(ref Unsafe.Add(ref elemRef, 20), ref Unsafe.Add(ref elemRef, 34)); - Swap(ref Unsafe.Add(ref elemRef, 21), ref Unsafe.Add(ref elemRef, 42)); - Swap(ref Unsafe.Add(ref elemRef, 22), ref Unsafe.Add(ref elemRef, 50)); - Swap(ref Unsafe.Add(ref elemRef, 23), ref Unsafe.Add(ref elemRef, 58)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 19), ref Unsafe.Add(ref elemRef, 26)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 20), ref Unsafe.Add(ref elemRef, 34)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 21), ref Unsafe.Add(ref elemRef, 42)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 22), ref Unsafe.Add(ref elemRef, 50)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 23), ref Unsafe.Add(ref elemRef, 58)); // row #3 - Swap(ref Unsafe.Add(ref elemRef, 28), ref Unsafe.Add(ref elemRef, 35)); - Swap(ref Unsafe.Add(ref elemRef, 29), ref Unsafe.Add(ref elemRef, 43)); - Swap(ref Unsafe.Add(ref elemRef, 30), ref Unsafe.Add(ref elemRef, 51)); - Swap(ref Unsafe.Add(ref elemRef, 31), ref Unsafe.Add(ref elemRef, 59)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 28), ref Unsafe.Add(ref elemRef, 35)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 29), ref Unsafe.Add(ref elemRef, 43)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 30), ref Unsafe.Add(ref elemRef, 51)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 31), ref Unsafe.Add(ref elemRef, 59)); // row #4 - Swap(ref Unsafe.Add(ref elemRef, 37), ref Unsafe.Add(ref elemRef, 44)); - Swap(ref Unsafe.Add(ref elemRef, 38), ref Unsafe.Add(ref elemRef, 52)); - Swap(ref Unsafe.Add(ref elemRef, 39), ref Unsafe.Add(ref elemRef, 60)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 37), ref Unsafe.Add(ref elemRef, 44)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 38), ref Unsafe.Add(ref elemRef, 52)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 39), ref Unsafe.Add(ref elemRef, 60)); // row #5 - Swap(ref Unsafe.Add(ref elemRef, 46), ref Unsafe.Add(ref elemRef, 53)); - Swap(ref Unsafe.Add(ref elemRef, 47), ref Unsafe.Add(ref elemRef, 61)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 46), ref Unsafe.Add(ref elemRef, 53)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 47), ref Unsafe.Add(ref elemRef, 61)); // row #6 - Swap(ref Unsafe.Add(ref elemRef, 55), ref Unsafe.Add(ref elemRef, 62)); - - static void Swap(ref short a, ref short b) => (b, a) = (a, b); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 55), ref Unsafe.Add(ref elemRef, 62)); } /// diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs index 7466d74f4..7350b865a 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs @@ -8,6 +8,7 @@ using System.Runtime.InteropServices; using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; using System.Text; +using SixLabors.ImageSharp.Common.Helpers; // ReSharper disable InconsistentNaming namespace SixLabors.ImageSharp.Formats.Jpeg.Components @@ -496,53 +497,46 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components ref float elemRef = ref Unsafe.As(ref this); // row #0 - Swap(ref Unsafe.Add(ref elemRef, 1), ref Unsafe.Add(ref elemRef, 8)); - Swap(ref Unsafe.Add(ref elemRef, 2), ref Unsafe.Add(ref elemRef, 16)); - Swap(ref Unsafe.Add(ref elemRef, 3), ref Unsafe.Add(ref elemRef, 24)); - Swap(ref Unsafe.Add(ref elemRef, 4), ref Unsafe.Add(ref elemRef, 32)); - Swap(ref Unsafe.Add(ref elemRef, 5), ref Unsafe.Add(ref elemRef, 40)); - Swap(ref Unsafe.Add(ref elemRef, 6), ref Unsafe.Add(ref elemRef, 48)); - Swap(ref Unsafe.Add(ref elemRef, 7), ref Unsafe.Add(ref elemRef, 56)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 1), ref Unsafe.Add(ref elemRef, 8)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 2), ref Unsafe.Add(ref elemRef, 16)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 3), ref Unsafe.Add(ref elemRef, 24)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 4), ref Unsafe.Add(ref elemRef, 32)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 5), ref Unsafe.Add(ref elemRef, 40)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 6), ref Unsafe.Add(ref elemRef, 48)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 7), ref Unsafe.Add(ref elemRef, 56)); // row #1 - Swap(ref Unsafe.Add(ref elemRef, 10), ref Unsafe.Add(ref elemRef, 17)); - Swap(ref Unsafe.Add(ref elemRef, 11), ref Unsafe.Add(ref elemRef, 25)); - Swap(ref Unsafe.Add(ref elemRef, 12), ref Unsafe.Add(ref elemRef, 33)); - Swap(ref Unsafe.Add(ref elemRef, 13), ref Unsafe.Add(ref elemRef, 41)); - Swap(ref Unsafe.Add(ref elemRef, 14), ref Unsafe.Add(ref elemRef, 49)); - Swap(ref Unsafe.Add(ref elemRef, 15), ref Unsafe.Add(ref elemRef, 57)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 10), ref Unsafe.Add(ref elemRef, 17)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 11), ref Unsafe.Add(ref elemRef, 25)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 12), ref Unsafe.Add(ref elemRef, 33)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 13), ref Unsafe.Add(ref elemRef, 41)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 14), ref Unsafe.Add(ref elemRef, 49)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 15), ref Unsafe.Add(ref elemRef, 57)); // row #2 - Swap(ref Unsafe.Add(ref elemRef, 19), ref Unsafe.Add(ref elemRef, 26)); - Swap(ref Unsafe.Add(ref elemRef, 20), ref Unsafe.Add(ref elemRef, 34)); - Swap(ref Unsafe.Add(ref elemRef, 21), ref Unsafe.Add(ref elemRef, 42)); - Swap(ref Unsafe.Add(ref elemRef, 22), ref Unsafe.Add(ref elemRef, 50)); - Swap(ref Unsafe.Add(ref elemRef, 23), ref Unsafe.Add(ref elemRef, 58)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 19), ref Unsafe.Add(ref elemRef, 26)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 20), ref Unsafe.Add(ref elemRef, 34)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 21), ref Unsafe.Add(ref elemRef, 42)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 22), ref Unsafe.Add(ref elemRef, 50)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 23), ref Unsafe.Add(ref elemRef, 58)); // row #3 - Swap(ref Unsafe.Add(ref elemRef, 28), ref Unsafe.Add(ref elemRef, 35)); - Swap(ref Unsafe.Add(ref elemRef, 29), ref Unsafe.Add(ref elemRef, 43)); - Swap(ref Unsafe.Add(ref elemRef, 30), ref Unsafe.Add(ref elemRef, 51)); - Swap(ref Unsafe.Add(ref elemRef, 31), ref Unsafe.Add(ref elemRef, 59)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 28), ref Unsafe.Add(ref elemRef, 35)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 29), ref Unsafe.Add(ref elemRef, 43)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 30), ref Unsafe.Add(ref elemRef, 51)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 31), ref Unsafe.Add(ref elemRef, 59)); // row #4 - Swap(ref Unsafe.Add(ref elemRef, 37), ref Unsafe.Add(ref elemRef, 44)); - Swap(ref Unsafe.Add(ref elemRef, 38), ref Unsafe.Add(ref elemRef, 52)); - Swap(ref Unsafe.Add(ref elemRef, 39), ref Unsafe.Add(ref elemRef, 60)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 37), ref Unsafe.Add(ref elemRef, 44)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 38), ref Unsafe.Add(ref elemRef, 52)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 39), ref Unsafe.Add(ref elemRef, 60)); // row #5 - Swap(ref Unsafe.Add(ref elemRef, 46), ref Unsafe.Add(ref elemRef, 53)); - Swap(ref Unsafe.Add(ref elemRef, 47), ref Unsafe.Add(ref elemRef, 61)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 46), ref Unsafe.Add(ref elemRef, 53)); + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 47), ref Unsafe.Add(ref elemRef, 61)); // row #6 - Swap(ref Unsafe.Add(ref elemRef, 55), ref Unsafe.Add(ref elemRef, 62)); - - static void Swap(ref float a, ref float b) - { - float tmp = a; - a = b; - b = tmp; - } + RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 55), ref Unsafe.Add(ref elemRef, 62)); } [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index eb1d4be9b..11142ea64 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -8,6 +8,7 @@ using System.IO; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading; +using SixLabors.ImageSharp.Common.Helpers; using SixLabors.ImageSharp.Compression.Zlib; using SixLabors.ImageSharp.Formats.Png.Chunks; using SixLabors.ImageSharp.Formats.Png.Filters; @@ -520,27 +521,27 @@ namespace SixLabors.ImageSharp.Formats.Png if (sum < min) { min = sum; - SwapSpans(ref filter, ref attempt); + RuntimeUtility.Swap(ref filter, ref attempt); } UpFilter.Encode(current, previous, attempt, out sum); if (sum < min) { min = sum; - SwapSpans(ref filter, ref attempt); + RuntimeUtility.Swap(ref filter, ref attempt); } AverageFilter.Encode(current, previous, attempt, this.bytesPerPixel, out sum); if (sum < min) { min = sum; - SwapSpans(ref filter, ref attempt); + RuntimeUtility.Swap(ref filter, ref attempt); } PaethFilter.Encode(current, previous, attempt, this.bytesPerPixel, out sum); if (sum < min) { - SwapSpans(ref filter, ref attempt); + RuntimeUtility.Swap(ref filter, ref attempt); } } @@ -749,21 +750,21 @@ namespace SixLabors.ImageSharp.Formats.Png return; } - const int MaxLatinCode = 255; + const int maxLatinCode = 255; for (int i = 0; i < meta.TextData.Count; i++) { PngTextData textData = meta.TextData[i]; bool hasUnicodeCharacters = false; - foreach (var c in textData.Value) + foreach (char c in textData.Value) { - if (c > MaxLatinCode) + if (c > maxLatinCode) { hasUnicodeCharacters = true; break; } } - if (hasUnicodeCharacters || (!string.IsNullOrWhiteSpace(textData.LanguageTag) || !string.IsNullOrWhiteSpace(textData.TranslatedKeyword))) + if (hasUnicodeCharacters || !string.IsNullOrWhiteSpace(textData.LanguageTag) || !string.IsNullOrWhiteSpace(textData.TranslatedKeyword)) { // Write iTXt chunk. byte[] keywordBytes = PngConstants.Encoding.GetBytes(textData.Keyword); @@ -1206,18 +1207,12 @@ namespace SixLabors.ImageSharp.Formats.Png return scanlineLength / mod; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] private void SwapScanlineBuffers() { - IMemoryOwner temp = this.previousScanline; - this.previousScanline = this.currentScanline; - this.currentScanline = temp; - } - - private static void SwapSpans(ref Span a, ref Span b) - { - Span t = b; - b = a; - a = t; + ref IMemoryOwner prev = ref this.previousScanline; + ref IMemoryOwner current = ref this.currentScanline; + RuntimeUtility.Swap(ref prev, ref current); } } } diff --git a/src/ImageSharp/Formats/Webp/Lossy/QuantEnc.cs b/src/ImageSharp/Formats/Webp/Lossy/QuantEnc.cs index c169ba6f9..a8e365270 100644 --- a/src/ImageSharp/Formats/Webp/Lossy/QuantEnc.cs +++ b/src/ImageSharp/Formats/Webp/Lossy/QuantEnc.cs @@ -6,6 +6,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; +using SixLabors.ImageSharp.Common.Helpers; namespace SixLabors.ImageSharp.Formats.Webp.Lossy { @@ -75,7 +76,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy if (mode == 0 || rdCur.Score < rdBest.Score) { - (rdBest, rdCur) = (rdCur, rdBest); + RuntimeUtility.Swap(ref rdBest, ref rdCur); it.SwapOut(); } } @@ -174,9 +175,8 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy { rdi4.CopyScore(rdTmp); bestMode = mode; - Span tmp = tmpDst; - tmpDst = bestBlock; - bestBlock = tmp; + + RuntimeUtility.Swap(ref tmpDst, ref bestBlock); tmpLevels.CopyTo(rdBest.YAcLevels.AsSpan(it.I4 * 16, 16)); } } @@ -258,9 +258,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy rd.Derr[i, 2] = rdUv.Derr[i, 2]; } - Span tmp = dst; - dst = tmpDst; - tmpDst = tmp; + RuntimeUtility.Swap(ref tmpDst, ref dst); } } diff --git a/src/ImageSharp/Formats/Webp/Lossy/Vp8EncIterator.cs b/src/ImageSharp/Formats/Webp/Lossy/Vp8EncIterator.cs index c1dedeba4..cac598a72 100644 --- a/src/ImageSharp/Formats/Webp/Lossy/Vp8EncIterator.cs +++ b/src/ImageSharp/Formats/Webp/Lossy/Vp8EncIterator.cs @@ -2,6 +2,7 @@ // Licensed under the Six Labors Split License. using System; +using SixLabors.ImageSharp.Common.Helpers; namespace SixLabors.ImageSharp.Formats.Webp.Lossy { @@ -754,7 +755,9 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy public void SwapOut() { +#pragma warning disable IDE0180 // Use tuple to swap values byte[] tmp = this.YuvOut; +#pragma warning restore IDE0180 // Use tuple to swap values this.YuvOut = this.YuvOut2; this.YuvOut2 = tmp; } From 3c40500b442b4a47dfde5c48d580873b5e5e42f7 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 27 Jul 2022 11:19:21 +1000 Subject: [PATCH 05/20] Clean up pixel blender defaults --- .../PorterDuffFunctions.Generated.cs | 216 +++++++++--------- .../PorterDuffFunctions.Generated.tt | 28 +-- .../PixelFormats/PixelBlender{TPixel}.cs | 30 ++- 3 files changed, 133 insertions(+), 141 deletions(-) diff --git a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.cs b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.cs index 0a00fcf35..4c9afecfd 100644 --- a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.cs @@ -20,7 +20,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 NormalSrc(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -35,7 +35,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 NormalSrcAtop(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -50,7 +50,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 NormalSrcOver(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -65,7 +65,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 NormalSrcIn(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -80,7 +80,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 NormalSrcOut(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -95,7 +95,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 NormalDest(Vector4 backdrop, Vector4 source, float opacity) { return backdrop; @@ -108,7 +108,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 NormalDestAtop(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -123,7 +123,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 NormalDestOver(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -138,7 +138,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 NormalDestIn(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -153,7 +153,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 NormalDestOut(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -168,7 +168,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 NormalXor(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -183,7 +183,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 NormalClear(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -425,7 +425,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 MultiplySrc(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -440,7 +440,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 MultiplySrcAtop(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -455,7 +455,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 MultiplySrcOver(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -470,7 +470,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 MultiplySrcIn(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -485,7 +485,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 MultiplySrcOut(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -500,7 +500,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 MultiplyDest(Vector4 backdrop, Vector4 source, float opacity) { return backdrop; @@ -513,7 +513,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 MultiplyDestAtop(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -528,7 +528,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 MultiplyDestOver(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -543,7 +543,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 MultiplyDestIn(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -558,7 +558,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 MultiplyDestOut(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -573,7 +573,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 MultiplyXor(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -588,7 +588,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 MultiplyClear(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -830,7 +830,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 AddSrc(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -845,7 +845,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 AddSrcAtop(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -860,7 +860,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 AddSrcOver(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -875,7 +875,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 AddSrcIn(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -890,7 +890,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 AddSrcOut(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -905,7 +905,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 AddDest(Vector4 backdrop, Vector4 source, float opacity) { return backdrop; @@ -918,7 +918,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 AddDestAtop(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -933,7 +933,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 AddDestOver(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -948,7 +948,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 AddDestIn(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -963,7 +963,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 AddDestOut(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -978,7 +978,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 AddXor(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -993,7 +993,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 AddClear(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -1235,7 +1235,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 SubtractSrc(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -1250,7 +1250,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 SubtractSrcAtop(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -1265,7 +1265,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 SubtractSrcOver(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -1280,7 +1280,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 SubtractSrcIn(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -1295,7 +1295,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 SubtractSrcOut(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -1310,7 +1310,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 SubtractDest(Vector4 backdrop, Vector4 source, float opacity) { return backdrop; @@ -1323,7 +1323,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 SubtractDestAtop(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -1338,7 +1338,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 SubtractDestOver(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -1353,7 +1353,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 SubtractDestIn(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -1368,7 +1368,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 SubtractDestOut(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -1383,7 +1383,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 SubtractXor(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -1398,7 +1398,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 SubtractClear(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -1640,7 +1640,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 ScreenSrc(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -1655,7 +1655,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 ScreenSrcAtop(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -1670,7 +1670,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 ScreenSrcOver(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -1685,7 +1685,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 ScreenSrcIn(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -1700,7 +1700,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 ScreenSrcOut(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -1715,7 +1715,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 ScreenDest(Vector4 backdrop, Vector4 source, float opacity) { return backdrop; @@ -1728,7 +1728,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 ScreenDestAtop(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -1743,7 +1743,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 ScreenDestOver(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -1758,7 +1758,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 ScreenDestIn(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -1773,7 +1773,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 ScreenDestOut(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -1788,7 +1788,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 ScreenXor(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -1803,7 +1803,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 ScreenClear(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -2045,7 +2045,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 DarkenSrc(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -2060,7 +2060,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 DarkenSrcAtop(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -2075,7 +2075,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 DarkenSrcOver(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -2090,7 +2090,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 DarkenSrcIn(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -2105,7 +2105,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 DarkenSrcOut(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -2120,7 +2120,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 DarkenDest(Vector4 backdrop, Vector4 source, float opacity) { return backdrop; @@ -2133,7 +2133,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 DarkenDestAtop(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -2148,7 +2148,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 DarkenDestOver(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -2163,7 +2163,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 DarkenDestIn(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -2178,7 +2178,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 DarkenDestOut(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -2193,7 +2193,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 DarkenXor(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -2208,7 +2208,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 DarkenClear(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -2450,7 +2450,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 LightenSrc(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -2465,7 +2465,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 LightenSrcAtop(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -2480,7 +2480,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 LightenSrcOver(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -2495,7 +2495,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 LightenSrcIn(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -2510,7 +2510,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 LightenSrcOut(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -2525,7 +2525,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 LightenDest(Vector4 backdrop, Vector4 source, float opacity) { return backdrop; @@ -2538,7 +2538,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 LightenDestAtop(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -2553,7 +2553,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 LightenDestOver(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -2568,7 +2568,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 LightenDestIn(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -2583,7 +2583,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 LightenDestOut(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -2598,7 +2598,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 LightenXor(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -2613,7 +2613,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 LightenClear(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -2855,7 +2855,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 OverlaySrc(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -2870,7 +2870,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 OverlaySrcAtop(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -2885,7 +2885,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 OverlaySrcOver(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -2900,7 +2900,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 OverlaySrcIn(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -2915,7 +2915,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 OverlaySrcOut(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -2930,7 +2930,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 OverlayDest(Vector4 backdrop, Vector4 source, float opacity) { return backdrop; @@ -2943,7 +2943,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 OverlayDestAtop(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -2958,7 +2958,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 OverlayDestOver(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -2973,7 +2973,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 OverlayDestIn(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -2988,7 +2988,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 OverlayDestOut(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -3003,7 +3003,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 OverlayXor(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -3018,7 +3018,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 OverlayClear(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -3260,7 +3260,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 HardLightSrc(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -3275,7 +3275,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 HardLightSrcAtop(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -3290,7 +3290,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 HardLightSrcOver(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -3305,7 +3305,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 HardLightSrcIn(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -3320,7 +3320,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 HardLightSrcOut(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -3335,7 +3335,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 HardLightDest(Vector4 backdrop, Vector4 source, float opacity) { return backdrop; @@ -3348,7 +3348,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 HardLightDestAtop(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -3363,7 +3363,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 HardLightDestOver(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -3378,7 +3378,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 HardLightDestIn(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -3393,7 +3393,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 HardLightDestOut(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -3408,7 +3408,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 HardLightXor(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -3423,7 +3423,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 HardLightClear(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; diff --git a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.tt b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.tt index c651ab4a4..0cd4e637c 100644 --- a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.tt +++ b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.tt @@ -13,10 +13,6 @@ // -<# -// Note use of MethodImplOptions.NoInlining. We have tests that are failing on certain architectures when -// AggresiveInlining is used. Confirmed on Intel i7-6600U in 64bit. -#> using System.Numerics; using System.Runtime.CompilerServices; @@ -32,7 +28,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 <#=blender#>Src(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -47,7 +43,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 <#=blender#>SrcAtop(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -62,7 +58,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 <#=blender#>SrcOver(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -77,7 +73,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 <#=blender#>SrcIn(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -92,7 +88,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 <#=blender#>SrcOut(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -107,7 +103,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 <#=blender#>Dest(Vector4 backdrop, Vector4 source, float opacity) { return backdrop; @@ -120,7 +116,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 <#=blender#>DestAtop(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -135,7 +131,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 <#=blender#>DestOver(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -150,7 +146,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 <#=blender#>DestIn(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -165,7 +161,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 <#=blender#>DestOut(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -180,7 +176,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 <#=blender#>Xor(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; @@ -195,7 +191,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders /// The source vector. /// The source opacity. Range 0..1 /// The . - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 <#=blender#>Clear(Vector4 backdrop, Vector4 source, float opacity) { source.W *= opacity; diff --git a/src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs index 3f325eed8..26b052dee 100644 --- a/src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs @@ -109,27 +109,23 @@ namespace SixLabors.ImageSharp.PixelFormats ReadOnlySpan amount) where TPixelSrc : unmanaged, IPixel { - Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); - Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); - Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + int maxLength = destination.Length; + Guard.MustBeGreaterThanOrEqualTo(background.Length, maxLength, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, maxLength, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, maxLength, nameof(amount.Length)); - using (IMemoryOwner buffer = - configuration.MemoryAllocator.Allocate(destination.Length * 3)) - { - Span destinationSpan = buffer.Slice(0, destination.Length); - Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); - Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + using IMemoryOwner buffer = configuration.MemoryAllocator.Allocate(maxLength * 3); - ReadOnlySpan sourcePixels = background[..]; - PixelOperations.Instance.ToVector4(configuration, sourcePixels, backgroundSpan, PixelConversionModifiers.Scale); - ReadOnlySpan sourcePixels1 = source[..background.Length]; - PixelOperations.Instance.ToVector4(configuration, sourcePixels1, sourceSpan, PixelConversionModifiers.Scale); + Span destinationVectors = buffer.Slice(0, maxLength); + Span backgroundVectors = buffer.Slice(maxLength, maxLength); + Span sourceVectors = buffer.Slice(maxLength * 2, maxLength); - this.BlendFunction(destinationSpan, backgroundSpan, sourceSpan, amount); + PixelOperations.Instance.ToVector4(configuration, background[..maxLength], backgroundVectors, PixelConversionModifiers.Scale); + PixelOperations.Instance.ToVector4(configuration, source[..maxLength], sourceVectors, PixelConversionModifiers.Scale); - Span sourceVectors = destinationSpan[..background.Length]; - PixelOperations.Instance.FromVector4Destructive(configuration, sourceVectors, destination, PixelConversionModifiers.Scale); - } + this.BlendFunction(destinationVectors, backgroundVectors, sourceVectors, amount); + + PixelOperations.Instance.FromVector4Destructive(configuration, destinationVectors[..maxLength], destination, PixelConversionModifiers.Scale); } /// From 3d837b109de72c6a9039bdf08821cb3e88aea9a6 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 27 Jul 2022 12:27:57 +1000 Subject: [PATCH 06/20] Update PixelBlender{TPixel}.cs --- .../PixelFormats/PixelBlender{TPixel}.cs | 28 ++++++++----------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs index 26b052dee..43bcdf426 100644 --- a/src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs @@ -47,27 +47,22 @@ namespace SixLabors.ImageSharp.PixelFormats float amount) where TPixelSrc : unmanaged, IPixel { - Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); - Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + int maxLength = destination.Length; + Guard.MustBeGreaterThanOrEqualTo(background.Length, maxLength, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, maxLength, nameof(source.Length)); Guard.MustBeBetweenOrEqualTo(amount, 0, 1, nameof(amount)); - using (IMemoryOwner buffer = - configuration.MemoryAllocator.Allocate(destination.Length * 3)) - { - Span destinationSpan = buffer.Slice(0, destination.Length); - Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); - Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + using IMemoryOwner buffer = configuration.MemoryAllocator.Allocate(maxLength * 3); + Span destinationVectors = buffer.Slice(0, maxLength); + Span backgroundVectors = buffer.Slice(maxLength, maxLength); + Span sourceVectors = buffer.Slice(maxLength * 2, maxLength); - ReadOnlySpan sourcePixels = background[..]; - PixelOperations.Instance.ToVector4(configuration, sourcePixels, backgroundSpan, PixelConversionModifiers.Scale); - ReadOnlySpan sourcePixels1 = source[..background.Length]; - PixelOperations.Instance.ToVector4(configuration, sourcePixels1, sourceSpan, PixelConversionModifiers.Scale); + PixelOperations.Instance.ToVector4(configuration, background[..maxLength], backgroundVectors, PixelConversionModifiers.Scale); + PixelOperations.Instance.ToVector4(configuration, source[..maxLength], sourceVectors, PixelConversionModifiers.Scale); - this.BlendFunction(destinationSpan, backgroundSpan, sourceSpan, amount); + this.BlendFunction(destinationVectors, backgroundVectors, sourceVectors, amount); - Span sourceVectors = destinationSpan[..background.Length]; - PixelOperations.Instance.FromVector4Destructive(configuration, sourceVectors, destination, PixelConversionModifiers.Scale); - } + PixelOperations.Instance.FromVector4Destructive(configuration, destinationVectors[..maxLength], destination, PixelConversionModifiers.Scale); } /// @@ -115,7 +110,6 @@ namespace SixLabors.ImageSharp.PixelFormats Guard.MustBeGreaterThanOrEqualTo(amount.Length, maxLength, nameof(amount.Length)); using IMemoryOwner buffer = configuration.MemoryAllocator.Allocate(maxLength * 3); - Span destinationVectors = buffer.Slice(0, maxLength); Span backgroundVectors = buffer.Slice(maxLength, maxLength); Span sourceVectors = buffer.Slice(maxLength * 2, maxLength); From 89faddfa71a1e9c2e39b3df214140995912b513a Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Fri, 2 Sep 2022 19:27:38 +1000 Subject: [PATCH 07/20] Fix build --- .../JpegColorConverter.CmykAvx.cs | 2 - .../JpegColorConverter.GrayScaleAvx.cs | 2 - .../JpegColorConverter.YCbCrAvx.cs | 2 - .../JpegColorConverter.YccKAvx.cs | 2 - src/ImageSharp/Formats/Png/PngDecoderCore.cs | 40 +++---- .../Formats/Jpg/JpegEncoderTests.cs | 5 - .../Formats/Png/PngEncoderTests.cs | 2 +- .../TestDataIcc/IccTestDataTagDataEntry.cs | 107 +++++++++--------- .../Tests/TestImageProviderTests.cs | 12 +- 9 files changed, 77 insertions(+), 97 deletions(-) diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykAvx.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykAvx.cs index 8edaa2efe..63e112dd7 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykAvx.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykAvx.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#if SUPPORTS_RUNTIME_INTRINSICS using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -96,4 +95,3 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components } } } -#endif diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleAvx.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleAvx.cs index 26e879185..0fc1fcd55 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleAvx.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleAvx.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#if SUPPORTS_RUNTIME_INTRINSICS using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -69,4 +68,3 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components } } } -#endif diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrAvx.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrAvx.cs index 219584b05..62e0fc1b6 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrAvx.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrAvx.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#if SUPPORTS_RUNTIME_INTRINSICS using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -122,4 +121,3 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components } } } -#endif diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YccKAvx.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YccKAvx.cs index f4549911e..dea9fa0a7 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YccKAvx.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YccKAvx.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#if SUPPORTS_RUNTIME_INTRINSICS using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -133,4 +132,3 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components } } } -#endif diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs index ee116d1e1..9a1f89c47 100644 --- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs @@ -519,26 +519,15 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// The private int CalculateBytesPerPixel() - { - switch (this.pngColorType) + => this.pngColorType + switch { - case PngColorType.Grayscale: - return this.header.BitDepth == 16 ? 2 : 1; - - case PngColorType.GrayscaleWithAlpha: - return this.header.BitDepth == 16 ? 4 : 2; - - case PngColorType.Palette: - return 1; - - case PngColorType.Rgb: - return this.header.BitDepth == 16 ? 6 : 3; - - case PngColorType.RgbWithAlpha: - default: - return this.header.BitDepth == 16 ? 8 : 4; - } - } + PngColorType.Grayscale => this.header.BitDepth == 16 ? 2 : 1, + PngColorType.GrayscaleWithAlpha => this.header.BitDepth == 16 ? 4 : 2, + PngColorType.Palette => 1, + PngColorType.Rgb => this.header.BitDepth == 16 ? 6 : 3, + _ => this.header.BitDepth == 16 ? 8 : 4, + }; /// /// Calculates the scanline length. @@ -1229,11 +1218,14 @@ namespace SixLabors.ImageSharp.Formats.Png { fixed (byte* compressedDataBase = compressedData) { - using (IMemoryOwner destBuffer = this.memoryAllocator.Allocate(this.configuration.StreamProcessingBufferSize)) - using (var memoryStreamOutput = new MemoryStream(compressedData.Length)) - using (var memoryStreamInput = new UnmanagedMemoryStream(compressedDataBase, compressedData.Length)) - using (var bufferedStream = new BufferedReadStream(this.configuration, memoryStreamInput)) - using (var inflateStream = new ZlibInflateStream(bufferedStream)) + using IMemoryOwner destBuffer = this.memoryAllocator.Allocate(this.configuration.StreamProcessingBufferSize); + using var memoryStreamOutput = new MemoryStream(compressedData.Length); + using var memoryStreamInput = new UnmanagedMemoryStream(compressedDataBase, compressedData.Length); + using var bufferedStream = new BufferedReadStream(this.configuration, memoryStreamInput); + using var inflateStream = new ZlibInflateStream(bufferedStream); + + Span destUncompressedData = destBuffer.GetSpan(); + if (!inflateStream.AllocateNewBytes(compressedData.Length, false)) { uncompressedBytesArray = Array.Empty(); return false; diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs index 8a78ef648..a3cf66eeb 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs @@ -6,7 +6,6 @@ using System.Threading; using System.Threading.Tasks; using SixLabors.ImageSharp.Formats.Jpeg; using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Tests.TestUtilities; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; @@ -33,7 +32,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg { JpegEncodingColor.Rgb, 100, 0.0238f / 100 }, { JpegEncodingColor.Rgb, 80, 1.3044f / 100 }, { JpegEncodingColor.Rgb, 40, 2.9879f / 100 }, - { JpegEncodingColor.YCbCrRatio444, 100, 0.0780f / 100 }, { JpegEncodingColor.YCbCrRatio444, 80, 1.4585f / 100 }, { JpegEncodingColor.YCbCrRatio444, 40, 3.1413f / 100 }, @@ -44,15 +42,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg { JpegEncodingColor.YCbCrRatio422, 100, 0.4895f / 100 }, { JpegEncodingColor.YCbCrRatio422, 80, 1.6043f / 100 }, { JpegEncodingColor.YCbCrRatio422, 40, 3.1996f / 100 }, - { JpegEncodingColor.YCbCrRatio420, 100, 0.5790f / 100 }, { JpegEncodingColor.YCbCrRatio420, 80, 1.6692f / 100 }, { JpegEncodingColor.YCbCrRatio420, 40, 3.2324f / 100 }, - { JpegEncodingColor.YCbCrRatio411, 100, 0.6868f / 100 }, { JpegEncodingColor.YCbCrRatio411, 80, 1.7139f / 100 }, { JpegEncodingColor.YCbCrRatio411, 40, 3.2634f / 100 }, - { JpegEncodingColor.YCbCrRatio410, 100, 0.7357f / 100 }, { JpegEncodingColor.YCbCrRatio410, 80, 1.7495f / 100 }, { JpegEncodingColor.YCbCrRatio410, 40, 3.2911f / 100 }, diff --git a/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs index f0611e9c4..7211d5367 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs @@ -340,7 +340,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png 0x0A, // Line ending CRLF 0x1A, // EOF 0x0A // LF - }; + }; Assert.Equal(expected, data); } diff --git a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataTagDataEntry.cs b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataTagDataEntry.cs index 9b56bb98c..f6d5aadac 100644 --- a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataTagDataEntry.cs +++ b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataTagDataEntry.cs @@ -37,7 +37,8 @@ namespace SixLabors.ImageSharp.Tests new object[] { TagDataEntryHeader_CurveArr, TagDataEntryHeader_CurveVal }, }; - public static readonly IccUnknownTagDataEntry Unknown_Val = new IccUnknownTagDataEntry(new byte[] { 0x00, 0x01, 0x02, 0x03 }); + public static readonly IccUnknownTagDataEntry Unknown_Val = new(new byte[] { 0x00, 0x01, 0x02, 0x03 }); + public static readonly byte[] Unknown_Arr = { 0x00, 0x01, 0x02, 0x03 }; public static readonly object[][] UnknownTagDataEntryTestData = @@ -45,7 +46,7 @@ namespace SixLabors.ImageSharp.Tests new object[] { Unknown_Arr, Unknown_Val, 12u }, }; - public static readonly IccChromaticityTagDataEntry Chromaticity_Val1 = new IccChromaticityTagDataEntry(IccColorantEncoding.ItuRBt709_2); + public static readonly IccChromaticityTagDataEntry Chromaticity_Val1 = new(IccColorantEncoding.ItuRBt709_2); public static readonly byte[] Chromaticity_Arr1 = ArrayHelper.Concat( IccTestDataPrimitives.UInt16_3, IccTestDataPrimitives.UInt16_1, @@ -56,7 +57,7 @@ namespace SixLabors.ImageSharp.Tests new byte[] { 0x00, 0x00, 0x26, 0x66 }, // 0.150 new byte[] { 0x00, 0x00, 0x0F, 0x5C }); // 0.060 - public static readonly IccChromaticityTagDataEntry Chromaticity_Val2 = new IccChromaticityTagDataEntry( + public static readonly IccChromaticityTagDataEntry Chromaticity_Val2 = new( new double[][] { new double[] { 1, 2 }, @@ -91,7 +92,7 @@ namespace SixLabors.ImageSharp.Tests new object[] { Chromaticity_Arr2, Chromaticity_Val2 }, }; - public static readonly IccColorantOrderTagDataEntry ColorantOrder_Val = new IccColorantOrderTagDataEntry(new byte[] { 0x00, 0x01, 0x02 }); + public static readonly IccColorantOrderTagDataEntry ColorantOrder_Val = new(new byte[] { 0x00, 0x01, 0x02 }); public static readonly byte[] ColorantOrder_Arr = ArrayHelper.Concat(IccTestDataPrimitives.UInt32_3, new byte[] { 0x00, 0x01, 0x02 }); public static readonly object[][] ColorantOrderTagDataEntryTestData = @@ -99,7 +100,7 @@ namespace SixLabors.ImageSharp.Tests new object[] { ColorantOrder_Arr, ColorantOrder_Val }, }; - public static readonly IccColorantTableTagDataEntry ColorantTable_Val = new IccColorantTableTagDataEntry( + public static readonly IccColorantTableTagDataEntry ColorantTable_Val = new( new IccColorantTableEntry[] { IccTestDataNonPrimitives.ColorantTableEntry_ValRand1, @@ -116,15 +117,15 @@ namespace SixLabors.ImageSharp.Tests new object[] { ColorantTable_Arr, ColorantTable_Val }, }; - public static readonly IccCurveTagDataEntry Curve_Val_0 = new IccCurveTagDataEntry(); + public static readonly IccCurveTagDataEntry Curve_Val_0 = new(); public static readonly byte[] Curve_Arr_0 = IccTestDataPrimitives.UInt32_0; - public static readonly IccCurveTagDataEntry Curve_Val_1 = new IccCurveTagDataEntry(1f); + public static readonly IccCurveTagDataEntry Curve_Val_1 = new(1f); public static readonly byte[] Curve_Arr_1 = ArrayHelper.Concat( IccTestDataPrimitives.UInt32_1, IccTestDataPrimitives.UFix8_1); - public static readonly IccCurveTagDataEntry Curve_Val_2 = new IccCurveTagDataEntry(new float[] { 1 / 65535f, 2 / 65535f, 3 / 65535f }); + public static readonly IccCurveTagDataEntry Curve_Val_2 = new(new float[] { 1 / 65535f, 2 / 65535f, 3 / 65535f }); public static readonly byte[] Curve_Arr_2 = ArrayHelper.Concat( IccTestDataPrimitives.UInt32_3, IccTestDataPrimitives.UInt16_1, @@ -138,7 +139,7 @@ namespace SixLabors.ImageSharp.Tests new object[] { Curve_Arr_2, Curve_Val_2 }, }; - public static readonly IccDataTagDataEntry Data_ValNoASCII = new IccDataTagDataEntry( + public static readonly IccDataTagDataEntry Data_ValNoASCII = new( new byte[] { 0x01, 0x02, 0x03, 0x04 }, false); @@ -148,7 +149,7 @@ namespace SixLabors.ImageSharp.Tests 0x01, 0x02, 0x03, 0x04 }; - public static readonly IccDataTagDataEntry Data_ValASCII = new IccDataTagDataEntry( + public static readonly IccDataTagDataEntry Data_ValASCII = new( new byte[] { (byte)'A', (byte)'S', (byte)'C', (byte)'I', (byte)'I' }, true); @@ -164,7 +165,7 @@ namespace SixLabors.ImageSharp.Tests new object[] { Data_ArrASCII, Data_ValASCII, 17u }, }; - public static readonly IccDateTimeTagDataEntry DateTime_Val = new IccDateTimeTagDataEntry(IccTestDataNonPrimitives.DateTime_ValRand1); + public static readonly IccDateTimeTagDataEntry DateTime_Val = new(IccTestDataNonPrimitives.DateTime_ValRand1); public static readonly byte[] DateTime_Arr = IccTestDataNonPrimitives.DateTime_Rand1; public static readonly object[][] DateTimeTagDataEntryTestData = @@ -172,7 +173,7 @@ namespace SixLabors.ImageSharp.Tests new object[] { DateTime_Arr, DateTime_Val }, }; - public static readonly IccLut16TagDataEntry Lut16_Val = new IccLut16TagDataEntry( + public static readonly IccLut16TagDataEntry Lut16_Val = new( new IccLut[] { IccTestDataLut.LUT16_ValGrad, IccTestDataLut.LUT16_ValGrad }, IccTestDataLut.CLUT16_ValGrad, new IccLut[] { IccTestDataLut.LUT16_ValGrad, IccTestDataLut.LUT16_ValGrad, IccTestDataLut.LUT16_ValGrad }); @@ -193,7 +194,7 @@ namespace SixLabors.ImageSharp.Tests new object[] { Lut16_Arr, Lut16_Val }, }; - public static readonly IccLut8TagDataEntry Lut8_Val = new IccLut8TagDataEntry( + public static readonly IccLut8TagDataEntry Lut8_Val = new( new IccLut[] { IccTestDataLut.LUT8_ValGrad, IccTestDataLut.LUT8_ValGrad }, IccTestDataLut.CLUT8_ValGrad, new IccLut[] { IccTestDataLut.LUT8_ValGrad, IccTestDataLut.LUT8_ValGrad, IccTestDataLut.LUT8_ValGrad }); @@ -225,18 +226,20 @@ namespace SixLabors.ImageSharp.Tests TagDataEntryHeader_CurveArr, Curve_Arr_2); - public static readonly IccLutAToBTagDataEntry LutAToB_Val = new IccLutAToBTagDataEntry( - new IccCurveTagDataEntry[] + public static readonly IccLutAToBTagDataEntry LutAToB_Val + = new( + new IccCurveTagDataEntry[] { Curve_Val_0, Curve_Val_1, Curve_Val_2, }, - IccTestDataMatrix.Single_2DArray_ValGrad, - IccTestDataMatrix.Single_1DArray_ValGrad, - new IccCurveTagDataEntry[] { Curve_Val_1, Curve_Val_2, Curve_Val_0 }, - IccTestDataLut.CLUT_Val16, - new IccCurveTagDataEntry[] { Curve_Val_2, Curve_Val_1 }); + IccTestDataMatrix.Single_2DArray_ValGrad, + IccTestDataMatrix.Single_1DArray_ValGrad, + new IccCurveTagDataEntry[] { Curve_Val_1, Curve_Val_2, Curve_Val_0 }, + IccTestDataLut.CLUT_Val16, + new IccCurveTagDataEntry[] { Curve_Val_2, Curve_Val_1 }); + public static readonly byte[] LutAToB_Arr = ArrayHelper.Concat( new byte[] { 0x02, 0x03, 0x00, 0x00 }, new byte[] { 0x00, 0x00, 0x00, 0x20 }, // b: 32 @@ -273,13 +276,12 @@ namespace SixLabors.ImageSharp.Tests CurveFull_1, // 14 bytes new byte[] { 0x00, 0x00 }); // Padding - public static readonly object[][] LutAToBTagDataEntryTestData = { new object[] { LutAToB_Arr, LutAToB_Val }, }; - public static readonly IccLutBToATagDataEntry LutBToA_Val = new IccLutBToATagDataEntry( + public static readonly IccLutBToATagDataEntry LutBToA_Val = new( new[] { Curve_Val_0, @@ -290,9 +292,9 @@ namespace SixLabors.ImageSharp.Tests null, IccTestDataLut.CLUT_Val16, new[] { Curve_Val_2, Curve_Val_1, Curve_Val_0 }); + public static readonly byte[] LutBToA_Arr = ArrayHelper.Concat( new byte[] { 0x02, 0x03, 0x00, 0x00 }, - new byte[] { 0x00, 0x00, 0x00, 0x20 }, // b: 32 new byte[] { 0x00, 0x00, 0x00, 0x00 }, // matrix: 0 new byte[] { 0x00, 0x00, 0x00, 0x00 }, // m: 0 @@ -315,13 +317,12 @@ namespace SixLabors.ImageSharp.Tests new byte[] { 0x00, 0x00 }, // Padding CurveFull_0); // 12 bytes - public static readonly object[][] LutBToATagDataEntryTestData = { new object[] { LutBToA_Arr, LutBToA_Val }, }; - public static readonly IccMeasurementTagDataEntry Measurement_Val = new IccMeasurementTagDataEntry( + public static readonly IccMeasurementTagDataEntry Measurement_Val = new( IccStandardObserver.Cie1931Observer, IccTestDataNonPrimitives.XyzNumber_ValVar1, IccMeasurementGeometry.Degree0ToDOrDTo0, @@ -346,7 +347,7 @@ namespace SixLabors.ImageSharp.Tests private static readonly IccLocalizedString LocalizedString_Rand2_esXL = CreateLocalizedString("es", "XL", IccTestDataPrimitives.Unicode_ValRand2); private static readonly IccLocalizedString LocalizedString_Rand2_xyXL = CreateLocalizedString("xy", "XL", IccTestDataPrimitives.Unicode_ValRand2); private static readonly IccLocalizedString LocalizedString_Rand_en = CreateLocalizedString("en", null, IccTestDataPrimitives.Unicode_ValRand2); - private static readonly IccLocalizedString LocalizedString_Rand_Invariant = new IccLocalizedString(CultureInfo.InvariantCulture, IccTestDataPrimitives.Unicode_ValRand3); + private static readonly IccLocalizedString LocalizedString_Rand_Invariant = new(CultureInfo.InvariantCulture, IccTestDataPrimitives.Unicode_ValRand3); private static IccLocalizedString CreateLocalizedString(string language, string country, string text) { @@ -397,7 +398,7 @@ namespace SixLabors.ImageSharp.Tests LocalizedString_Rand2_xyXL, }; - public static readonly IccMultiLocalizedUnicodeTagDataEntry MultiLocalizedUnicode_Val = new IccMultiLocalizedUnicodeTagDataEntry(LocalizedString_RandArr_enUS_deDE); + public static readonly IccMultiLocalizedUnicodeTagDataEntry MultiLocalizedUnicode_Val = new(LocalizedString_RandArr_enUS_deDE); public static readonly byte[] MultiLocalizedUnicode_Arr = ArrayHelper.Concat( IccTestDataPrimitives.UInt32_2, new byte[] { 0x00, 0x00, 0x00, 0x0C }, // 12 @@ -410,7 +411,7 @@ namespace SixLabors.ImageSharp.Tests IccTestDataPrimitives.Unicode_Rand2, IccTestDataPrimitives.Unicode_Rand3); - public static readonly IccMultiLocalizedUnicodeTagDataEntry MultiLocalizedUnicode_Val2 = new IccMultiLocalizedUnicodeTagDataEntry(LocalizedString_RandArr_en_Invariant); + public static readonly IccMultiLocalizedUnicodeTagDataEntry MultiLocalizedUnicode_Val2 = new(LocalizedString_RandArr_en_Invariant); public static readonly byte[] MultiLocalizedUnicode_Arr2_Read = ArrayHelper.Concat( IccTestDataPrimitives.UInt32_2, new byte[] { 0x00, 0x00, 0x00, 0x0C }, // 12 @@ -435,7 +436,7 @@ namespace SixLabors.ImageSharp.Tests IccTestDataPrimitives.Unicode_Rand2, IccTestDataPrimitives.Unicode_Rand3); - public static readonly IccMultiLocalizedUnicodeTagDataEntry MultiLocalizedUnicode_Val3 = new IccMultiLocalizedUnicodeTagDataEntry(LocalizedString_SameArr_enUS_deDE_esXL_xyXL); + public static readonly IccMultiLocalizedUnicodeTagDataEntry MultiLocalizedUnicode_Val3 = new(LocalizedString_SameArr_enUS_deDE_esXL_xyXL); public static readonly byte[] MultiLocalizedUnicode_Arr3 = ArrayHelper.Concat( IccTestDataPrimitives.UInt32_4, new byte[] { 0x00, 0x00, 0x00, 0x0C }, // 12 @@ -467,7 +468,7 @@ namespace SixLabors.ImageSharp.Tests new object[] { MultiLocalizedUnicode_Arr3, MultiLocalizedUnicode_Val3 }, }; - public static readonly IccMultiProcessElementsTagDataEntry MultiProcessElements_Val = new IccMultiProcessElementsTagDataEntry( + public static readonly IccMultiProcessElementsTagDataEntry MultiProcessElements_Val = new( new IccMultiProcessElement[] { IccTestDataMultiProcessElements.MPE_ValCLUT, @@ -490,11 +491,11 @@ namespace SixLabors.ImageSharp.Tests new object[] { MultiProcessElements_Arr, MultiProcessElements_Val }, }; - public static readonly IccNamedColor2TagDataEntry NamedColor2_Val = new IccNamedColor2TagDataEntry( + public static readonly IccNamedColor2TagDataEntry NamedColor2_Val = new( 16909060, ArrayHelper.Fill('A', 31), ArrayHelper.Fill('4', 31), - new IccNamedColor[] { IccTestDataNonPrimitives.NamedColor_ValMin, IccTestDataNonPrimitives.NamedColor_ValMin }); + new IccNamedColor[] { IccTestDataNonPrimitives.NamedColor_ValMin, IccTestDataNonPrimitives.NamedColor_ValMin }); public static readonly byte[] NamedColor2_Arr = ArrayHelper.Concat( new byte[] { 0x01, 0x02, 0x03, 0x04 }, @@ -512,7 +513,7 @@ namespace SixLabors.ImageSharp.Tests new object[] { NamedColor2_Arr, NamedColor2_Val }, }; - public static readonly IccParametricCurveTagDataEntry ParametricCurve_Val = new IccParametricCurveTagDataEntry(IccTestDataCurves.Parametric_ValVar1); + public static readonly IccParametricCurveTagDataEntry ParametricCurve_Val = new(IccTestDataCurves.Parametric_ValVar1); public static readonly byte[] ParametricCurve_Arr = IccTestDataCurves.Parametric_Var1; public static readonly object[][] ParametricCurveTagDataEntryTestData = @@ -520,7 +521,7 @@ namespace SixLabors.ImageSharp.Tests new object[] { ParametricCurve_Arr, ParametricCurve_Val }, }; - public static readonly IccProfileSequenceDescTagDataEntry ProfileSequenceDesc_Val = new IccProfileSequenceDescTagDataEntry( + public static readonly IccProfileSequenceDescTagDataEntry ProfileSequenceDesc_Val = new( new IccProfileDescription[] { IccTestDataNonPrimitives.ProfileDescription_ValRand1, @@ -537,7 +538,7 @@ namespace SixLabors.ImageSharp.Tests new object[] { ProfileSequenceDesc_Arr, ProfileSequenceDesc_Val }, }; - public static readonly IccProfileSequenceIdentifierTagDataEntry ProfileSequenceIdentifier_Val = new IccProfileSequenceIdentifierTagDataEntry( + public static readonly IccProfileSequenceIdentifierTagDataEntry ProfileSequenceIdentifier_Val = new( new IccProfileSequenceIdentifier[] { new IccProfileSequenceIdentifier(IccTestDataNonPrimitives.ProfileId_ValRand, LocalizedString_RandArr_enUS_deDE), @@ -564,7 +565,7 @@ namespace SixLabors.ImageSharp.Tests new object[] { ProfileSequenceIdentifier_Arr, ProfileSequenceIdentifier_Val }, }; - public static readonly IccResponseCurveSet16TagDataEntry ResponseCurveSet16_Val = new IccResponseCurveSet16TagDataEntry( + public static readonly IccResponseCurveSet16TagDataEntry ResponseCurveSet16_Val = new( new IccResponseCurve[] { IccTestDataCurves.Response_ValGrad, @@ -584,7 +585,7 @@ namespace SixLabors.ImageSharp.Tests new object[] { ResponseCurveSet16_Arr, ResponseCurveSet16_Val }, }; - public static readonly IccFix16ArrayTagDataEntry Fix16Array_Val = new IccFix16ArrayTagDataEntry(new float[] { 1 / 256f, 2 / 256f, 3 / 256f }); + public static readonly IccFix16ArrayTagDataEntry Fix16Array_Val = new(new float[] { 1 / 256f, 2 / 256f, 3 / 256f }); public static readonly byte[] Fix16Array_Arr = ArrayHelper.Concat( IccTestDataPrimitives.Fix16_1, IccTestDataPrimitives.Fix16_2, @@ -595,7 +596,7 @@ namespace SixLabors.ImageSharp.Tests new object[] { Fix16Array_Arr, Fix16Array_Val, 20u }, }; - public static readonly IccSignatureTagDataEntry Signature_Val = new IccSignatureTagDataEntry("ABCD"); + public static readonly IccSignatureTagDataEntry Signature_Val = new("ABCD"); public static readonly byte[] Signature_Arr = { 0x41, 0x42, 0x43, 0x44, }; public static readonly object[][] SignatureTagDataEntryTestData = @@ -603,7 +604,7 @@ namespace SixLabors.ImageSharp.Tests new object[] { Signature_Arr, Signature_Val }, }; - public static readonly IccTextTagDataEntry Text_Val = new IccTextTagDataEntry("ABCD"); + public static readonly IccTextTagDataEntry Text_Val = new("ABCD"); public static readonly byte[] Text_Arr = { 0x41, 0x42, 0x43, 0x44 }; public static readonly object[][] TextTagDataEntryTestData = @@ -611,7 +612,7 @@ namespace SixLabors.ImageSharp.Tests new object[] { Text_Arr, Text_Val, 12u }, }; - public static readonly IccUFix16ArrayTagDataEntry UFix16Array_Val = new IccUFix16ArrayTagDataEntry(new float[] { 1, 2, 3 }); + public static readonly IccUFix16ArrayTagDataEntry UFix16Array_Val = new(new float[] { 1, 2, 3 }); public static readonly byte[] UFix16Array_Arr = ArrayHelper.Concat( IccTestDataPrimitives.UFix16_1, IccTestDataPrimitives.UFix16_2, @@ -622,7 +623,7 @@ namespace SixLabors.ImageSharp.Tests new object[] { UFix16Array_Arr, UFix16Array_Val, 20u }, }; - public static readonly IccUInt16ArrayTagDataEntry UInt16Array_Val = new IccUInt16ArrayTagDataEntry(new ushort[] { 1, 2, 3 }); + public static readonly IccUInt16ArrayTagDataEntry UInt16Array_Val = new(new ushort[] { 1, 2, 3 }); public static readonly byte[] UInt16Array_Arr = ArrayHelper.Concat( IccTestDataPrimitives.UInt16_1, IccTestDataPrimitives.UInt16_2, @@ -633,7 +634,7 @@ namespace SixLabors.ImageSharp.Tests new object[] { UInt16Array_Arr, UInt16Array_Val, 14u }, }; - public static readonly IccUInt32ArrayTagDataEntry UInt32Array_Val = new IccUInt32ArrayTagDataEntry(new uint[] { 1, 2, 3 }); + public static readonly IccUInt32ArrayTagDataEntry UInt32Array_Val = new(new uint[] { 1, 2, 3 }); public static readonly byte[] UInt32Array_Arr = ArrayHelper.Concat( IccTestDataPrimitives.UInt32_1, IccTestDataPrimitives.UInt32_2, @@ -644,7 +645,7 @@ namespace SixLabors.ImageSharp.Tests new object[] { UInt32Array_Arr, UInt32Array_Val, 20u }, }; - public static readonly IccUInt64ArrayTagDataEntry UInt64Array_Val = new IccUInt64ArrayTagDataEntry(new ulong[] { 1, 2, 3 }); + public static readonly IccUInt64ArrayTagDataEntry UInt64Array_Val = new(new ulong[] { 1, 2, 3 }); public static readonly byte[] UInt64Array_Arr = ArrayHelper.Concat( IccTestDataPrimitives.UInt64_1, IccTestDataPrimitives.UInt64_2, @@ -655,7 +656,7 @@ namespace SixLabors.ImageSharp.Tests new object[] { UInt64Array_Arr, UInt64Array_Val, 32u }, }; - public static readonly IccUInt8ArrayTagDataEntry UInt8Array_Val = new IccUInt8ArrayTagDataEntry(new byte[] { 1, 2, 3 }); + public static readonly IccUInt8ArrayTagDataEntry UInt8Array_Val = new(new byte[] { 1, 2, 3 }); public static readonly byte[] UInt8Array_Arr = { 1, 2, 3 }; public static readonly object[][] UInt8ArrayTagDataEntryTestData = @@ -663,7 +664,7 @@ namespace SixLabors.ImageSharp.Tests new object[] { UInt8Array_Arr, UInt8Array_Val, 11u }, }; - public static readonly IccViewingConditionsTagDataEntry ViewingConditions_Val = new IccViewingConditionsTagDataEntry( + public static readonly IccViewingConditionsTagDataEntry ViewingConditions_Val = new( IccTestDataNonPrimitives.XyzNumber_ValVar1, IccTestDataNonPrimitives.XyzNumber_ValVar2, IccStandardIlluminant.D50); @@ -678,7 +679,7 @@ namespace SixLabors.ImageSharp.Tests new object[] { ViewingConditions_Arr, ViewingConditions_Val }, }; - public static readonly IccXyzTagDataEntry XYZ_Val = new IccXyzTagDataEntry(new Vector3[] + public static readonly IccXyzTagDataEntry XYZ_Val = new(new Vector3[] { IccTestDataNonPrimitives.XyzNumber_ValVar1, IccTestDataNonPrimitives.XyzNumber_ValVar2, @@ -695,7 +696,7 @@ namespace SixLabors.ImageSharp.Tests new object[] { XYZ_Arr, XYZ_Val, 44u }, }; - public static readonly IccTextDescriptionTagDataEntry TextDescription_Val1 = new IccTextDescriptionTagDataEntry( + public static readonly IccTextDescriptionTagDataEntry TextDescription_Val1 = new( IccTestDataPrimitives.Ascii_ValRand, IccTestDataPrimitives.Unicode_ValRand1, ArrayHelper.Fill('A', 66), @@ -714,7 +715,7 @@ namespace SixLabors.ImageSharp.Tests ArrayHelper.Fill((byte)0x41, 66), new byte[] { 0x00 }); // Null terminator - public static readonly IccTextDescriptionTagDataEntry TextDescription_Val2 = new IccTextDescriptionTagDataEntry(IccTestDataPrimitives.Ascii_ValRand, null, null, 0, 0); + public static readonly IccTextDescriptionTagDataEntry TextDescription_Val2 = new(IccTestDataPrimitives.Ascii_ValRand, null, null, 0, 0); public static readonly byte[] TextDescription_Arr2 = ArrayHelper.Concat( new byte[] { 0x00, 0x00, 0x00, 0x0B }, // 11 IccTestDataPrimitives.Ascii_Rand, @@ -730,7 +731,7 @@ namespace SixLabors.ImageSharp.Tests new object[] { TextDescription_Arr2, TextDescription_Val2 }, }; - public static readonly IccCrdInfoTagDataEntry CrdInfo_Val = new IccCrdInfoTagDataEntry( + public static readonly IccCrdInfoTagDataEntry CrdInfo_Val = new( IccTestDataPrimitives.Ascii_ValRand4, IccTestDataPrimitives.Ascii_ValRand1, IccTestDataPrimitives.Ascii_ValRand2, @@ -759,7 +760,7 @@ namespace SixLabors.ImageSharp.Tests new object[] { CrdInfo_Arr, CrdInfo_Val }, }; - public static readonly IccScreeningTagDataEntry Screening_Val = new IccScreeningTagDataEntry( + public static readonly IccScreeningTagDataEntry Screening_Val = new( IccScreeningFlag.DefaultScreens | IccScreeningFlag.UnitLinesPerCm, new IccScreeningChannel[] { IccTestDataNonPrimitives.ScreeningChannel_ValRand1, IccTestDataNonPrimitives.ScreeningChannel_ValRand2 }); @@ -774,7 +775,7 @@ namespace SixLabors.ImageSharp.Tests new object[] { Screening_Arr, Screening_Val }, }; - public static readonly IccUcrBgTagDataEntry UcrBg_Val = new IccUcrBgTagDataEntry( + public static readonly IccUcrBgTagDataEntry UcrBg_Val = new( new ushort[] { 3, 4, 6 }, new ushort[] { 9, 7, 2, 5 }, IccTestDataPrimitives.Ascii_ValRand); @@ -809,12 +810,12 @@ namespace SixLabors.ImageSharp.Tests MultiLocalizedUnicode_Arr, new byte[] { 0x00, 0x00 }); // padding - public static readonly IccTagTableEntry TagDataEntry_MultiLocalizedUnicodeTable = new IccTagTableEntry( + public static readonly IccTagTableEntry TagDataEntry_MultiLocalizedUnicodeTable = new( IccProfileTag.Unknown, 0, (uint)TagDataEntry_MultiLocalizedUnicodeArr.Length - 2); - public static readonly IccTagTableEntry TagDataEntry_CurveTable = new IccTagTableEntry(IccProfileTag.Unknown, 0, (uint)TagDataEntry_CurveArr.Length - 2); + public static readonly IccTagTableEntry TagDataEntry_CurveTable = new(IccProfileTag.Unknown, 0, (uint)TagDataEntry_CurveArr.Length - 2); public static readonly object[][] TagDataEntryTestData = { diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs index 46e8b34bc..f37e89c41 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs @@ -369,14 +369,14 @@ namespace SixLabors.ImageSharp.Tests } public IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - => this.Decode((TestDecoderOptions)(new() { GeneralOptions = options }), stream, cancellationToken); + => this.Decode((TestDecoderOptions)new() { GeneralOptions = options }, stream, cancellationToken); public Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) where TPixel : unmanaged, IPixel - => this.Decode((TestDecoderOptions)(new() { GeneralOptions = options }), stream, cancellationToken); + => this.Decode((TestDecoderOptions)new() { GeneralOptions = options }, stream, cancellationToken); public Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - => this.Decode((TestDecoderOptions)(new() { GeneralOptions = options }), stream, cancellationToken); + => this.Decode((TestDecoderOptions)new() { GeneralOptions = options }, stream, cancellationToken); public Image Decode(TestDecoderOptions options, Stream stream, CancellationToken cancellationToken) where TPixel : unmanaged, IPixel @@ -414,14 +414,14 @@ namespace SixLabors.ImageSharp.Tests } public IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - => this.Decode((TestDecoderWithParametersOptions)(new() { GeneralOptions = options }), stream, cancellationToken); + => this.Decode((TestDecoderWithParametersOptions)new() { GeneralOptions = options }, stream, cancellationToken); public Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) where TPixel : unmanaged, IPixel - => this.Decode((TestDecoderWithParametersOptions)(new() { GeneralOptions = options }), stream, cancellationToken); + => this.Decode((TestDecoderWithParametersOptions)new() { GeneralOptions = options }, stream, cancellationToken); public Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - => this.Decode((TestDecoderWithParametersOptions)(new() { GeneralOptions = options }), stream, cancellationToken); + => this.Decode((TestDecoderWithParametersOptions)new() { GeneralOptions = options }, stream, cancellationToken); public Image Decode(TestDecoderWithParametersOptions options, Stream stream, CancellationToken cancellationToken) where TPixel : unmanaged, IPixel From 61299f99ef8857b7e7754a74019b71f34b6e97c1 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Fri, 2 Sep 2022 19:53:42 +1000 Subject: [PATCH 08/20] PR feedback --- src/ImageSharp/Common/Helpers/RuntimeUtility.cs | 10 ++++------ src/ImageSharp/Formats/Webp/Lossy/Vp8EncIterator.cs | 4 ++-- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/ImageSharp/Common/Helpers/RuntimeUtility.cs b/src/ImageSharp/Common/Helpers/RuntimeUtility.cs index 66e2fc9dc..9c8348c0d 100644 --- a/src/ImageSharp/Common/Helpers/RuntimeUtility.cs +++ b/src/ImageSharp/Common/Helpers/RuntimeUtility.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -11,6 +11,8 @@ namespace SixLabors.ImageSharp.Common.Helpers /// internal static class RuntimeUtility { + // Tuple swap uses 2 more IL bytes +#pragma warning disable IDE0180 // Use tuple to swap values /// /// Swaps the two references. /// @@ -20,10 +22,7 @@ namespace SixLabors.ImageSharp.Common.Helpers [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Swap(ref T a, ref T b) { - // Tuple swap uses 2 more IL bytes -#pragma warning disable IDE0180 // Use tuple to swap values T tmp = a; -#pragma warning restore IDE0180 // Use tuple to swap values a = b; b = tmp; } @@ -38,11 +37,10 @@ namespace SixLabors.ImageSharp.Common.Helpers public static void Swap(ref Span a, ref Span b) { // Tuple swap uses 2 more IL bytes -#pragma warning disable IDE0180 // Use tuple to swap values Span tmp = a; -#pragma warning restore IDE0180 // Use tuple to swap values a = b; b = tmp; } +#pragma warning restore IDE0180 // Use tuple to swap values } } diff --git a/src/ImageSharp/Formats/Webp/Lossy/Vp8EncIterator.cs b/src/ImageSharp/Formats/Webp/Lossy/Vp8EncIterator.cs index cac598a72..0043d6d28 100644 --- a/src/ImageSharp/Formats/Webp/Lossy/Vp8EncIterator.cs +++ b/src/ImageSharp/Formats/Webp/Lossy/Vp8EncIterator.cs @@ -2,7 +2,6 @@ // Licensed under the Six Labors Split License. using System; -using SixLabors.ImageSharp.Common.Helpers; namespace SixLabors.ImageSharp.Formats.Webp.Lossy { @@ -755,11 +754,12 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy public void SwapOut() { + // Tuple swap uses 2 more IL bytes #pragma warning disable IDE0180 // Use tuple to swap values byte[] tmp = this.YuvOut; -#pragma warning restore IDE0180 // Use tuple to swap values this.YuvOut = this.YuvOut2; this.YuvOut2 = tmp; +#pragma warning restore IDE0180 // Use tuple to swap values } public void NzToBytes() From ba1adc39a29afc0f19692f18be2b432c0d528c61 Mon Sep 17 00:00:00 2001 From: Dirk Lemstra Date: Sat, 3 Sep 2022 09:44:25 +0200 Subject: [PATCH 09/20] Use BitOperations directly. --- src/ImageSharp/Common/Helpers/Numerics.cs | 26 ------------------- .../Helpers/Shuffle/IComponentShuffle.cs | 7 ++--- 2 files changed, 4 insertions(+), 29 deletions(-) diff --git a/src/ImageSharp/Common/Helpers/Numerics.cs b/src/ImageSharp/Common/Helpers/Numerics.cs index 9f81de1c2..8be59ca9a 100644 --- a/src/ImageSharp/Common/Helpers/Numerics.cs +++ b/src/ImageSharp/Common/Helpers/Numerics.cs @@ -836,14 +836,6 @@ namespace SixLabors.ImageSharp return Sse2.ConvertToInt32(vsum); } - /// - /// Calculates floored log of the specified value, base 2. - /// Note that by convention, input value 0 returns 0 since Log(0) is undefined. - /// - /// The value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Log2(uint value) => BitOperations.Log2(value); - /// /// Fast division with ceiling for numbers. /// @@ -852,24 +844,6 @@ namespace SixLabors.ImageSharp /// Ceiled division result. public static uint DivideCeil(uint value, uint divisor) => (value + divisor - 1) / divisor; - /// - /// Rotates the specified value left by the specified number of bits. - /// - /// The value to rotate. - /// The number of bits to rotate with. - /// The rotated value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static uint RotateLeft(uint value, int offset) => BitOperations.RotateLeft(value, offset); - - /// - /// Rotates the specified value right by the specified number of bits. - /// - /// The value to rotate. - /// The number of bits to rotate with. - /// The rotated value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static uint RotateRight(uint value, int offset) => BitOperations.RotateRight(value, offset); - /// /// Tells whether input value is outside of the given range. /// diff --git a/src/ImageSharp/Common/Helpers/Shuffle/IComponentShuffle.cs b/src/ImageSharp/Common/Helpers/Shuffle/IComponentShuffle.cs index 0d27ea437..9cd7db10d 100644 --- a/src/ImageSharp/Common/Helpers/Shuffle/IComponentShuffle.cs +++ b/src/ImageSharp/Common/Helpers/Shuffle/IComponentShuffle.cs @@ -3,6 +3,7 @@ using System; using System.Buffers.Binary; +using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -157,7 +158,7 @@ namespace SixLabors.ImageSharp // packed = [W Z Y X] // ROTR(8, packedArgb) = [Y Z W X] - Unsafe.Add(ref dBase, i) = Numerics.RotateRight(packed, 8); + Unsafe.Add(ref dBase, i) = BitOperations.RotateRight(packed, 8); } } } @@ -188,7 +189,7 @@ namespace SixLabors.ImageSharp // tmp1 + tmp3 = [W X Y Z] uint tmp1 = packed & 0xFF00FF00; uint tmp2 = packed & 0x00FF00FF; - uint tmp3 = Numerics.RotateLeft(tmp2, 16); + uint tmp3 = BitOperations.RotateLeft(tmp2, 16); Unsafe.Add(ref dBase, i) = tmp1 + tmp3; } @@ -221,7 +222,7 @@ namespace SixLabors.ImageSharp // tmp1 + tmp3 = [Y Z W X] uint tmp1 = packed & 0x00FF00FF; uint tmp2 = packed & 0xFF00FF00; - uint tmp3 = Numerics.RotateLeft(tmp2, 16); + uint tmp3 = BitOperations.RotateLeft(tmp2, 16); Unsafe.Add(ref dBase, i) = tmp1 + tmp3; } From 303140000986c4f23bba7fbf0f89e6ef1e174fae Mon Sep 17 00:00:00 2001 From: Dirk Lemstra Date: Sat, 3 Sep 2022 10:20:56 +0200 Subject: [PATCH 10/20] Did not push all files.... --- src/ImageSharp/Formats/Webp/BitReader/Vp8BitReader.cs | 3 ++- src/ImageSharp/Formats/Webp/Lossless/LosslessUtils.cs | 5 +++-- src/ImageSharp/Formats/Webp/Lossless/Vp8LEncoder.cs | 5 +++-- src/ImageSharp/Formats/Webp/Lossy/Vp8Residual.cs | 3 ++- tests/ImageSharp.Tests/Common/NumericsTests.cs | 7 ++++--- 5 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/ImageSharp/Formats/Webp/BitReader/Vp8BitReader.cs b/src/ImageSharp/Formats/Webp/BitReader/Vp8BitReader.cs index e1639b899..52e3907e9 100644 --- a/src/ImageSharp/Formats/Webp/BitReader/Vp8BitReader.cs +++ b/src/ImageSharp/Formats/Webp/BitReader/Vp8BitReader.cs @@ -4,6 +4,7 @@ using System.Buffers; using System.Buffers.Binary; using System.IO; +using System.Numerics; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Memory; @@ -111,7 +112,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.BitReader range = split + 1; } - int shift = 7 ^ Numerics.Log2(range); + int shift = 7 ^ BitOperations.Log2(range); range <<= shift; this.bits -= shift; diff --git a/src/ImageSharp/Formats/Webp/Lossless/LosslessUtils.cs b/src/ImageSharp/Formats/Webp/Lossless/LosslessUtils.cs index c6d0d1cfa..cb826f75d 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/LosslessUtils.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/LosslessUtils.cs @@ -2,6 +2,7 @@ // Licensed under the Six Labors Split License. using System; +using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Intrinsics; @@ -1041,7 +1042,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless /// private static int PrefixEncodeBitsNoLut(int distance, ref int extraBits) { - int highestBit = Numerics.Log2((uint)--distance); + int highestBit = BitOperations.Log2((uint)--distance); int secondHighestBit = (distance >> (highestBit - 1)) & 1; extraBits = highestBit - 1; int code = (2 * highestBit) + secondHighestBit; @@ -1050,7 +1051,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless private static int PrefixEncodeNoLut(int distance, ref int extraBits, ref int extraBitsValue) { - int highestBit = Numerics.Log2((uint)--distance); + int highestBit = BitOperations.Log2((uint)--distance); int secondHighestBit = (distance >> (highestBit - 1)) & 1; extraBits = highestBit - 1; extraBitsValue = distance & ((1 << extraBits) - 1); diff --git a/src/ImageSharp/Formats/Webp/Lossless/Vp8LEncoder.cs b/src/ImageSharp/Formats/Webp/Lossless/Vp8LEncoder.cs index 473c92d8d..a09cdb8bc 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/Vp8LEncoder.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/Vp8LEncoder.cs @@ -6,6 +6,7 @@ using System.Buffers; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using SixLabors.ImageSharp.Formats.Webp.BitWriter; @@ -382,7 +383,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless // If using a color cache, do not have it bigger than the number of colors. if (useCache && this.PaletteSize < 1 << WebpConstants.MaxColorCacheBits) { - this.CacheBits = Numerics.Log2((uint)this.PaletteSize) + 1; + this.CacheBits = BitOperations.Log2((uint)this.PaletteSize) + 1; } } @@ -951,7 +952,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless } else { - int nBits = Numerics.Log2((uint)trimmedLength - 2); + int nBits = BitOperations.Log2((uint)trimmedLength - 2); int nBitPairs = (nBits / 2) + 1; this.bitWriter.PutBits((uint)nBitPairs - 1, 3); this.bitWriter.PutBits((uint)trimmedLength - 2, nBitPairs * 2); diff --git a/src/ImageSharp/Formats/Webp/Lossy/Vp8Residual.cs b/src/ImageSharp/Formats/Webp/Lossy/Vp8Residual.cs index 42116932a..9541ee1f7 100644 --- a/src/ImageSharp/Formats/Webp/Lossy/Vp8Residual.cs +++ b/src/ImageSharp/Formats/Webp/Lossy/Vp8Residual.cs @@ -2,6 +2,7 @@ // Licensed under the Six Labors Split License. using System; +using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Intrinsics; @@ -62,7 +63,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy // The position of the most significant non-zero bit indicates the position of // the last non-zero value. - this.Last = mask != 0 ? Numerics.Log2(mask) : -1; + this.Last = mask != 0 ? BitOperations.Log2(mask) : -1; } else { diff --git a/tests/ImageSharp.Tests/Common/NumericsTests.cs b/tests/ImageSharp.Tests/Common/NumericsTests.cs index e8643de27..30345390a 100644 --- a/tests/ImageSharp.Tests/Common/NumericsTests.cs +++ b/tests/ImageSharp.Tests/Common/NumericsTests.cs @@ -2,6 +2,7 @@ // Licensed under the Six Labors Split License. using System; +using System.Numerics; using Xunit; using Xunit.Abstractions; @@ -34,7 +35,7 @@ namespace SixLabors.ImageSharp.Tests.Common { uint value = 0; int expected = 0; - int actual = Numerics.Log2(value); + int actual = BitOperations.Log2(value); Assert.Equal(expected, actual); } @@ -47,7 +48,7 @@ namespace SixLabors.ImageSharp.Tests.Common // from 2^0 to 2^32 uint value = (uint)(1 << i); int expected = i; - int actual = Numerics.Log2(value); + int actual = BitOperations.Log2(value); Assert.Equal(expected, actual); } @@ -66,7 +67,7 @@ namespace SixLabors.ImageSharp.Tests.Common rng.NextBytes(bytes); uint value = BitConverter.ToUInt32(bytes, 0); int expected = Log2_ReferenceImplementation(value); - int actual = Numerics.Log2(value); + int actual = BitOperations.Log2(value); Assert.Equal(expected, actual); } From f9c9a019d1ae0509cb85b3c63197b4bdff1db4be Mon Sep 17 00:00:00 2001 From: Dirk Lemstra Date: Sat, 3 Sep 2022 10:54:53 +0200 Subject: [PATCH 11/20] Removed unused argument. --- src/ImageSharp/Configuration.cs | 2 +- .../Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs | 4 ++-- .../PixelOperations/Rgb24.PixelOperations.cs | 2 -- .../PixelOperations/Rgba32.PixelOperations.cs | 2 -- src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs | 4 ---- .../PixelFormats/PixelOperations/PixelOperationsTests.cs | 2 +- 6 files changed, 4 insertions(+), 12 deletions(-) diff --git a/src/ImageSharp/Configuration.cs b/src/ImageSharp/Configuration.cs index ea1c4eea2..76c2b31b3 100644 --- a/src/ImageSharp/Configuration.cs +++ b/src/ImageSharp/Configuration.cs @@ -70,7 +70,7 @@ namespace SixLabors.ImageSharp get => this.maxDegreeOfParallelism; set { - if (value == 0 || value < -1) + if (value is 0 or < -1) { throw new ArgumentOutOfRangeException(nameof(this.MaxDegreeOfParallelism)); } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs index 985c45715..938815dae 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs @@ -155,12 +155,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder // pack pixels to a temporary, padded proxy buffer, then copy the relevant values to the destination row. if (this.pixelBuffer.DangerousTryGetPaddedRowSpan(yy, 3, out Span destRow)) { - PixelOperations.Instance.PackFromRgbPlanes(this.configuration, r, g, b, destRow); + PixelOperations.Instance.PackFromRgbPlanes(r, g, b, destRow); } else { Span proxyRow = this.paddedProxyPixelRow.GetSpan(); - PixelOperations.Instance.PackFromRgbPlanes(this.configuration, r, g, b, proxyRow); + PixelOperations.Instance.PackFromRgbPlanes(r, g, b, proxyRow); proxyRow[..width].CopyTo(this.pixelBuffer.DangerousGetRowSpan(yy)); } } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgb24.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgb24.PixelOperations.cs index c4b84dca3..50ea3533b 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgb24.PixelOperations.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgb24.PixelOperations.cs @@ -24,13 +24,11 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void PackFromRgbPlanes( - Configuration configuration, ReadOnlySpan redChannel, ReadOnlySpan greenChannel, ReadOnlySpan blueChannel, Span destination) { - Guard.NotNull(configuration, nameof(configuration)); int count = redChannel.Length; GuardPackFromRgbPlanes(greenChannel, blueChannel, destination, count); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgba32.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgba32.PixelOperations.cs index 98d9177a9..ed3a53758 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgba32.PixelOperations.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgba32.PixelOperations.cs @@ -59,13 +59,11 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void PackFromRgbPlanes( - Configuration configuration, ReadOnlySpan redChannel, ReadOnlySpan greenChannel, ReadOnlySpan blueChannel, Span destination) { - Guard.NotNull(configuration, nameof(configuration)); int count = redChannel.Length; GuardPackFromRgbPlanes(greenChannel, blueChannel, destination, count); diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs index 4721a3748..9d2a2f1b2 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs @@ -166,20 +166,16 @@ namespace SixLabors.ImageSharp.PixelFormats /// Bulk operation that packs 3 seperate RGB channels to . /// The destination must have a padding of 3. /// - /// A to configure internal operations. /// A to the red values. /// A to the green values. /// A to the blue values. /// A to the destination pixels. internal virtual void PackFromRgbPlanes( - Configuration configuration, ReadOnlySpan redChannel, ReadOnlySpan greenChannel, ReadOnlySpan blueChannel, Span destination) { - Guard.NotNull(configuration, nameof(configuration)); - int count = redChannel.Length; GuardPackFromRgbPlanes(greenChannel, blueChannel, destination, count); diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs index 3a6c04540..6f11e7aec 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs @@ -1057,7 +1057,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations public void PackFromRgbPlanes(int count) => SimdUtilsTests.TestPackFromRgbPlanes( count, - (r, g, b, actual) => PixelOperations.Instance.PackFromRgbPlanes(this.Configuration, r, g, b, actual)); + (r, g, b, actual) => PixelOperations.Instance.PackFromRgbPlanes(r, g, b, actual)); public delegate void RefAction(ref T1 arg1); From 1c5a78ce78935a1533660fd0827c4f5354defd60 Mon Sep 17 00:00:00 2001 From: Dirk Lemstra Date: Sat, 3 Sep 2022 11:00:40 +0200 Subject: [PATCH 12/20] Removed unit tests. --- .../ImageSharp.Tests/Common/NumericsTests.cs | 60 +------------------ 1 file changed, 1 insertion(+), 59 deletions(-) diff --git a/tests/ImageSharp.Tests/Common/NumericsTests.cs b/tests/ImageSharp.Tests/Common/NumericsTests.cs index 30345390a..6f5df4313 100644 --- a/tests/ImageSharp.Tests/Common/NumericsTests.cs +++ b/tests/ImageSharp.Tests/Common/NumericsTests.cs @@ -2,7 +2,6 @@ // Licensed under the Six Labors Split License. using System; -using System.Numerics; using Xunit; using Xunit.Abstractions; @@ -12,67 +11,10 @@ namespace SixLabors.ImageSharp.Tests.Common { private ITestOutputHelper Output { get; } - public NumericsTests(ITestOutputHelper output) - { - this.Output = output; - } + public NumericsTests(ITestOutputHelper output) => this.Output = output; public static TheoryData IsOutOfRangeTestData = new() { int.MinValue, -1, 0, 1, 6, 7, 8, 91, 92, 93, int.MaxValue }; - private static int Log2_ReferenceImplementation(uint value) - { - int n = 0; - while ((value >>= 1) != 0) - { - ++n; - } - - return n; - } - - [Fact] - public void Log2_ZeroConvention() - { - uint value = 0; - int expected = 0; - int actual = BitOperations.Log2(value); - - Assert.Equal(expected, actual); - } - - [Fact] - public void Log2_PowersOfTwo() - { - for (int i = 0; i < sizeof(int) * 8; i++) - { - // from 2^0 to 2^32 - uint value = (uint)(1 << i); - int expected = i; - int actual = BitOperations.Log2(value); - - Assert.Equal(expected, actual); - } - } - - [Theory] - [InlineData(1, 100)] - [InlineData(2, 100)] - public void Log2_RandomValues(int seed, int count) - { - var rng = new Random(seed); - byte[] bytes = new byte[4]; - - for (int i = 0; i < count; i++) - { - rng.NextBytes(bytes); - uint value = BitConverter.ToUInt32(bytes, 0); - int expected = Log2_ReferenceImplementation(value); - int actual = BitOperations.Log2(value); - - Assert.Equal(expected, actual); - } - } - private static uint DivideCeil_ReferenceImplementation(uint value, uint divisor) => (uint)MathF.Ceiling((float)value / divisor); [Fact] From 3a6f26d136f18934adbead5dabef0fbe4276a4c2 Mon Sep 17 00:00:00 2001 From: Dirk Lemstra Date: Sat, 3 Sep 2022 11:05:12 +0200 Subject: [PATCH 13/20] Removed unused class. --- .../Common/Helpers/RuntimeEnvironment.cs | 32 ------------------- .../Helpers/RuntimeEnvironmentTests.cs | 31 ------------------ 2 files changed, 63 deletions(-) delete mode 100644 src/ImageSharp/Common/Helpers/RuntimeEnvironment.cs delete mode 100644 tests/ImageSharp.Tests/Helpers/RuntimeEnvironmentTests.cs diff --git a/src/ImageSharp/Common/Helpers/RuntimeEnvironment.cs b/src/ImageSharp/Common/Helpers/RuntimeEnvironment.cs deleted file mode 100644 index 925925ff9..000000000 --- a/src/ImageSharp/Common/Helpers/RuntimeEnvironment.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Six Labors Split License. - -using System; -using System.Runtime.InteropServices; - -namespace SixLabors.ImageSharp -{ - /// - /// Provides information about the .NET runtime installation. - /// Many methods defer to when available. - /// - internal static class RuntimeEnvironment - { - private static readonly Lazy IsNetCoreLazy = new Lazy(() => FrameworkDescription.StartsWith(".NET Core", StringComparison.OrdinalIgnoreCase)); - - /// - /// Gets a value indicating whether the .NET installation is .NET Core 3.1 or lower. - /// - public static bool IsNetCore => IsNetCoreLazy.Value; - - /// - /// Gets the name of the .NET installation on which an app is running. - /// - public static string FrameworkDescription => RuntimeInformation.FrameworkDescription; - - /// - /// Indicates whether the current application is running on the specified platform. - /// - public static bool IsOSPlatform(OSPlatform osPlatform) => RuntimeInformation.IsOSPlatform(osPlatform); - } -} diff --git a/tests/ImageSharp.Tests/Helpers/RuntimeEnvironmentTests.cs b/tests/ImageSharp.Tests/Helpers/RuntimeEnvironmentTests.cs deleted file mode 100644 index d61b8b86c..000000000 --- a/tests/ImageSharp.Tests/Helpers/RuntimeEnvironmentTests.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Six Labors Split License. - -using System.Runtime.InteropServices; -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Helpers -{ - public class RuntimeEnvironmentTests - { - [Fact] - public void CanDetectNetCore() => Assert.False(RuntimeEnvironment.IsNetCore); - - [Fact] - public void CanDetectOSPlatform() - { - if (TestEnvironment.IsLinux) - { - Assert.True(RuntimeEnvironment.IsOSPlatform(OSPlatform.Linux)); - } - else if (TestEnvironment.IsMacOS) - { - Assert.True(RuntimeEnvironment.IsOSPlatform(OSPlatform.OSX)); - } - else if (TestEnvironment.IsWindows) - { - Assert.True(RuntimeEnvironment.IsOSPlatform(OSPlatform.Windows)); - } - } - } -} From b22785ed33bafc531b9a71534463fbb0e93068e5 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 6 Sep 2022 23:29:23 +1000 Subject: [PATCH 14/20] Update editorconfig and fix all new warnings. --- .editorconfig | 30 +- shared-infrastructure | 2 +- .../Advanced/AdvancedImageExtensions.cs | 21 +- src/ImageSharp/Advanced/PreserveAttribute.cs | 5 +- src/ImageSharp/Color/Color.cs | 11 +- src/ImageSharp/ColorSpaces/CieLab.cs | 60 ++-- src/ImageSharp/ColorSpaces/CieLch.cs | 66 ++-- src/ImageSharp/ColorSpaces/CieLchuv.cs | 62 ++-- src/ImageSharp/ColorSpaces/CieLuv.cs | 58 ++-- src/ImageSharp/ColorSpaces/CieXyy.cs | 46 ++- src/ImageSharp/ColorSpaces/CieXyz.cs | 48 ++- src/ImageSharp/ColorSpaces/Cmyk.cs | 60 ++-- .../Conversion/ColorSpaceConverter.Adapt.cs | 4 +- .../Conversion/ColorSpaceConverter.CieLab.cs | 27 +- .../Conversion/ColorSpaceConverter.CieLch.cs | 7 +- .../ColorSpaceConverter.CieLchuv.cs | 29 +- .../Conversion/ColorSpaceConverter.CieLuv.cs | 24 +- .../Conversion/ColorSpaceConverter.CieXyy.cs | 56 ++-- .../Conversion/ColorSpaceConverter.CieXyz.cs | 30 +- .../Conversion/ColorSpaceConverter.Cmyk.cs | 50 ++-- .../Conversion/ColorSpaceConverter.Hsl.cs | 50 ++-- .../Conversion/ColorSpaceConverter.Hsv.cs | 50 ++-- .../ColorSpaceConverter.HunterLab.cs | 2 +- .../ColorSpaceConverter.LinearRgb.cs | 61 ++-- .../Conversion/ColorSpaceConverter.Lms.cs | 2 +- .../Conversion/ColorSpaceConverter.Rgb.cs | 60 ++-- .../Conversion/ColorSpaceConverter.YCbCr.cs | 54 ++-- .../CieXyChromaticityCoordinates.cs | 46 +-- .../Converters/CIeLchToCieLabConverter.cs | 6 +- .../Converters/CieLabToCieLchConverter.cs | 4 +- .../Converters/CieLabToCieXyzConverter.cs | 8 +- .../Converters/CieLchuvToCieLuvConverter.cs | 4 +- .../Converters/CieLuvToCieLchuvConverter.cs | 4 +- .../Converters/CieLuvToCieXyzConverter.cs | 4 +- .../Converters/CieXyzAndCieXyyConverter.cs | 8 +- .../Converters/CieXyzAndLmsConverter.cs | 6 +- .../Converters/CmykAndRgbConverter.cs | 10 +- .../Converters/HslAndRgbConverter.cs | 6 +- .../Converters/HsvAndRgbConverter.cs | 6 +- .../Converters/HunterLabToCieXyzConverter.cs | 4 +- .../LinearRgbAndCieXyzConverterBase.cs | 19 +- .../Converters/LinearRgbToCieXyzConverter.cs | 2 +- .../Converters/LinearRgbToRgbConverter.cs | 8 +- .../Converters/RgbToLinearRgbConverter.cs | 8 +- .../Converters/YCbCrAndRgbConverter.cs | 8 +- src/ImageSharp/ColorSpaces/Hsl.cs | 48 ++- src/ImageSharp/ColorSpaces/Hsv.cs | 48 ++- src/ImageSharp/ColorSpaces/HunterLab.cs | 58 ++-- src/ImageSharp/ColorSpaces/LinearRgb.cs | 56 ++-- src/ImageSharp/ColorSpaces/Lms.cs | 48 ++- src/ImageSharp/ColorSpaces/Rgb.cs | 60 ++-- src/ImageSharp/ColorSpaces/YCbCr.cs | 46 ++- .../Diagnostics/MemoryDiagnostics.cs | 1 + src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs | 25 +- src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs | 47 ++- src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs | 15 +- src/ImageSharp/Formats/DecoderOptions.cs | 4 +- src/ImageSharp/Formats/Gif/GifEncoderCore.cs | 25 +- .../Formats/Jpeg/Components/Block8x8F.cs | 50 +++- .../ColorConverters/JpegColorConverterBase.cs | 14 +- .../Decoder/ArithmeticScanDecoder.cs | 25 +- .../Jpeg/Components/Decoder/JpegFileMarker.cs | 7 +- .../EncodingConfigs/JpegFrameConfig.cs | 2 +- .../Jpeg/Components/Encoder/HuffmanSpec.cs | 20 +- .../Formats/Jpeg/Components/RowOctet.cs | 3 + .../Formats/Jpeg/JpegDecoderCore.cs | 95 +++--- .../Formats/Jpeg/JpegImageFormatDetector.cs | 18 +- .../Formats/Pbm/PbmImageFormatDetector.cs | 8 +- src/ImageSharp/Formats/Png/PngDecoderCore.cs | 48 +-- src/ImageSharp/Formats/Png/PngEncoderCore.cs | 281 ++++++++---------- src/ImageSharp/Formats/Png/PngTextData.cs | 28 +- src/ImageSharp/Formats/Png/PngThrowHelper.cs | 10 + src/ImageSharp/Formats/Tga/TgaEncoderCore.cs | 20 +- src/ImageSharp/Formats/Tga/TgaMetadata.cs | 8 +- .../Compressors/T4BitCompressor.cs | 6 +- .../Compressors/T6BitCompressor.cs | 26 +- .../Compressors/TiffCcittCompressor.cs | 34 +-- .../Formats/Tiff/TiffBitsPerSample.cs | 72 +++-- .../Formats/Tiff/TiffEncoderCore.cs | 27 +- .../Formats/Tiff/Writers/TiffStreamWriter.cs | 6 +- .../Formats/Webp/BitReader/Vp8BitReader.cs | 6 +- .../Formats/Webp/BitWriter/BitWriterBase.cs | 14 +- .../Formats/Webp/BitWriter/Vp8BitWriter.cs | 8 +- .../Formats/Webp/BitWriter/Vp8LBitWriter.cs | 6 +- .../Formats/Webp/Lossless/Vp8LEncoder.cs | 50 ++-- .../Webp/Lossless/WebpLosslessDecoder.cs | 66 ++-- .../Formats/Webp/Lossy/Vp8EncIterator.cs | 97 +++--- .../Formats/Webp/Lossy/Vp8Encoder.cs | 83 ++++-- .../Formats/Webp/Lossy/WebpLossyDecoder.cs | 226 ++++++++------ .../Formats/Webp/WebpAnimationDecoder.cs | 50 ++-- .../Formats/Webp/WebpImageFormatDetector.cs | 12 +- src/ImageSharp/Formats/Webp/WebpImageInfo.cs | 8 +- src/ImageSharp/IO/BufferedReadStream.cs | 2 +- src/ImageSharp/IO/ChunkedMemoryStream.cs | 4 +- src/ImageSharp/Image.FromStream.cs | 17 +- src/ImageSharp/Image.WrapMemory.cs | 16 +- src/ImageSharp/ImageExtensions.cs | 11 +- src/ImageSharp/ImageSharp.csproj.DotSettings | 15 - ...mageSharp.netstandard1.1.v3.ncrunchproject | 5 - .../Internals/UnmanagedMemoryHandle.cs | 27 +- .../Metadata/Profiles/Exif/ExifReader.cs | 17 +- .../Metadata/Profiles/Exif/ExifWriter.cs | 20 +- .../Profiles/Exif/Values/EncodedString.cs | 22 ++ .../Profiles/ICC/Curves/IccCurveSegment.cs | 12 +- .../ICC/Curves/IccFormulaCurveElement.cs | 21 +- .../ICC/Curves/IccOneDimensionalCurve.cs | 10 +- .../ICC/Curves/IccSampledCurveElement.cs | 14 +- .../DataReader/IccDataReader.TagDataEntry.cs | 2 +- .../Profiles/ICC/DataReader/IccDataReader.cs | 18 +- .../DataWriter/IccDataWriter.TagDataEntry.cs | 197 ++++-------- .../Profiles/ICC/Enums/IccProfileFlag.cs | 6 +- .../Profiles/ICC/Enums/IccScreeningFlag.cs | 4 +- .../Metadata/Profiles/ICC/ICC.1-2022-05.pdf | Bin 0 -> 905961 bytes .../Metadata/Profiles/ICC/IccProfile.cs | 64 ++-- .../Metadata/Profiles/ICC/IccReader.cs | 36 +-- .../Metadata/Profiles/ICC/IccWriter.cs | 24 +- .../IccBAcsProcessElement.cs | 13 +- .../IccClutProcessElement.cs | 17 +- .../IccCurveSetProcessElement.cs | 8 +- .../IccEAcsProcessElement.cs | 12 +- .../IccMatrixProcessElement.cs | 18 +- .../IccMultiProcessElement.cs | 8 +- .../TagDataEntries/IccCrdInfoTagDataEntry.cs | 24 +- .../ICC/TagDataEntries/IccDataTagDataEntry.cs | 16 +- .../ICC/TagDataEntries/IccLut8TagDataEntry.cs | 14 +- .../TagDataEntries/IccLutAToBTagDataEntry.cs | 46 ++- .../TagDataEntries/IccLutBToATagDataEntry.cs | 44 +-- .../IccNamedColor2TagDataEntry.cs | 18 +- .../IccSignatureTagDataEntry.cs | 17 +- .../IccTextDescriptionTagDataEntry.cs | 22 +- .../ICC/TagDataEntries/IccTextTagDataEntry.cs | 16 +- .../TagDataEntries/IccUcrBgTagDataEntry.cs | 16 +- .../ICC/TagDataEntries/IccXyzTagDataEntry.cs | 18 +- .../ICC/Various/IccLocalizedString.cs | 8 +- .../Metadata/Profiles/ICC/Various/IccLut.cs | 14 +- .../Profiles/ICC/Various/IccNamedColor.cs | 14 +- .../Profiles/ICC/Various/IccProfileId.cs | 21 +- .../Profiles/ICC/Various/IccVersion.cs | 32 +- .../Metadata/Profiles/IPTC/IptcProfile.cs | 14 +- .../Metadata/Profiles/XMP/XmpProfile.cs | 6 +- .../PixelImplementations/HalfSingle.cs | 4 +- .../PixelImplementations/Rgba32.cs | 3 +- .../PixelImplementations/RgbaVector.cs | 3 +- .../PixelFormats/PixelOperations{TPixel}.cs | 5 +- src/ImageSharp/Primitives/DenseMatrix{T}.cs | 58 ++-- src/ImageSharp/Primitives/LongRational.cs | 27 +- src/ImageSharp/Primitives/Point.cs | 26 +- src/ImageSharp/Primitives/PointF.cs | 22 +- src/ImageSharp/Primitives/Rectangle.cs | 2 +- src/ImageSharp/Primitives/RectangleF.cs | 18 +- src/ImageSharp/Primitives/Size.cs | 2 +- src/ImageSharp/Primitives/SizeF.cs | 16 +- .../Convolution/KernelSamplingMap.cs | 34 +-- .../Kernels/EdgeDetector2DKernel.cs | 10 +- .../Kernels/EdgeDetectorCompassKernel.cs | 8 +- .../Convolution/Kernels/EdgeDetectorKernel.cs | 6 +- .../Dithering/ErroDither.KnownTypes.cs | 138 ++++----- .../Dithering/OrderedDither.KnownTypes.cs | 10 +- .../PaletteDitherProcessor{TPixel}.cs | 9 +- .../Effects/OilPaintingProcessor{TPixel}.cs | 14 +- ...eHistogramEqualizationProcessor{TPixel}.cs | 2 +- ...alizationSlidingWindowProcessor{TPixel}.cs | 48 +-- ...lHistogramEqualizationProcessor{TPixel}.cs | 2 +- .../HistogramEqualizationOptions.cs | 2 +- .../HistogramEqualizationProcessor{TPixel}.cs | 5 +- .../Quantization/EuclideanPixelMap{TPixel}.cs | 4 +- .../Quantization/OctreeQuantizer{TPixel}.cs | 9 +- .../Quantization/PaletteQuantizer.cs | 4 +- .../Quantization/PaletteQuantizer{TPixel}.cs | 5 + .../Quantization/WuQuantizer{TPixel}.cs | 171 +++++------ .../Linear/FlipProcessor{TPixel}.cs | 13 +- .../Linear/RotateProcessor{TPixel}.cs | 12 +- .../Transforms/Resamplers/CubicResampler.cs | 12 +- .../Transforms/Resamplers/LanczosResampler.cs | 8 +- src/ImageSharp/Processing/ResizeOptions.cs | 2 +- .../Advanced/AdvancedImageExtensionsTests.cs | 3 +- .../CieXyzAndCieXyyConversionTest.cs | 8 +- .../Conversion/CmykAndHslConversionTests.cs | 8 +- .../Conversion/CmykAndHsvConversionTests.cs | 8 +- .../Conversion/CmykAndYCbCrConversionTests.cs | 4 +- .../Conversion/RgbAndCmykConversionTest.cs | 8 +- .../Conversion/RgbAndHslConversionTest.cs | 8 +- .../Conversion/RgbAndHsvConversionTest.cs | 8 +- .../Conversion/RgbAndYCbCrConversionTest.cs | 4 +- .../Formats/Jpg/JpegColorConverterTests.cs | 4 +- .../Formats/Tiff/BigTiffMetadataTests.cs | 2 +- .../Formats/Tiff/TiffEncoderHeaderTests.cs | 4 +- .../Formats/Tiff/Utils/TiffWriterTests.cs | 2 +- .../Metadata/Profiles/ICC/IccReaderTests.cs | 4 +- .../Metadata/Profiles/ICC/IccWriterTests.cs | 4 +- 190 files changed, 2385 insertions(+), 2459 deletions(-) delete mode 100644 src/ImageSharp/ImageSharp.csproj.DotSettings delete mode 100644 src/ImageSharp/ImageSharp.netstandard1.1.v3.ncrunchproject create mode 100644 src/ImageSharp/Metadata/Profiles/ICC/ICC.1-2022-05.pdf diff --git a/.editorconfig b/.editorconfig index 753a4dbc2..f84e6de2a 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,5 +1,5 @@ -# Version: 2.1.0 (Using https://semver.org/) -# Updated: 2021-03-03 +# Version: 4.1.1 (Using https://semver.org/) +# Updated: 2022-05-23 # See https://github.com/RehanSaeed/EditorConfig/releases for release notes. # See https://github.com/RehanSaeed/EditorConfig for updates to this file. # See http://EditorConfig.org for more information about .editorconfig files. @@ -49,11 +49,11 @@ indent_size = 2 indent_size = 2 # Markdown Files -[*.md] +[*.{md,mdx}] trim_trailing_whitespace = false # Web Files -[*.{htm,html,js,jsm,ts,tsx,css,sass,scss,less,svg,vue}] +[*.{htm,html,js,jsm,ts,tsx,cjs,cts,ctsx,mjs,mts,mtsx,css,sass,scss,less,pcss,svg,vue}] indent_size = 2 # Batch Files @@ -75,7 +75,7 @@ indent_style = tab [*.{cs,csx,cake,vb,vbx}] # Default Severity for all .NET Code Style rules below -dotnet_analyzer_diagnostic.category-style.severity = warning +dotnet_analyzer_diagnostic.severity = warning ########################################## # Language Rules @@ -128,14 +128,15 @@ file_header_template = Copyright (c) Six Labors.\nLicensed under the Six Labors # dotnet_diagnostic.SA1636.severity = none # Undocumented -dotnet_style_operator_placement_when_wrapping = end_of_line +dotnet_style_operator_placement_when_wrapping = end_of_line:warning +csharp_style_prefer_null_check_over_type_check = true:warning # C# Style Rules # https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/language-rules#c-style-rules [*.{cs,csx,cake}] # 'var' preferences -csharp_style_var_for_built_in_types = never -csharp_style_var_when_type_is_apparent = true:warning +csharp_style_var_for_built_in_types = false:warning +csharp_style_var_when_type_is_apparent = false:warning csharp_style_var_elsewhere = false:warning # Expression-bodied members csharp_style_expression_bodied_methods = true:warning @@ -200,12 +201,15 @@ dotnet_diagnostic.IDE0059.severity = suggestion # Organize using directives dotnet_sort_system_directives_first = true dotnet_separate_import_directive_groups = false +# Dotnet namespace options +dotnet_style_namespace_match_folder = true:suggestion +dotnet_diagnostic.IDE0130.severity = suggestion # C# formatting rules # https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules#c-formatting-rules [*.{cs,csx,cake}] # Newline options -# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#new-line-options +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules#new-line-options csharp_new_line_before_open_brace = all csharp_new_line_before_else = true csharp_new_line_before_catch = true @@ -214,7 +218,7 @@ csharp_new_line_before_members_in_object_initializers = true csharp_new_line_before_members_in_anonymous_types = true csharp_new_line_between_query_expression_clauses = true # Indentation options -# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#indentation-options +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules#indentation-options csharp_indent_case_contents = true csharp_indent_switch_labels = true csharp_indent_labels = no_change @@ -222,7 +226,7 @@ csharp_indent_block_contents = true csharp_indent_braces = false csharp_indent_case_contents_when_block = false # Spacing options -# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#spacing-options +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules#spacing-options csharp_space_after_cast = false csharp_space_after_keywords_in_control_flow_statements = true csharp_space_between_parentheses = false @@ -246,7 +250,7 @@ csharp_space_before_open_square_brackets = false csharp_space_between_empty_square_brackets = false csharp_space_between_square_brackets = false # Wrap options -# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#wrap-options +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules#wrap-options csharp_preserve_single_line_statements = false csharp_preserve_single_line_blocks = true @@ -448,4 +452,4 @@ dotnet_naming_rule.parameters_rule.severity = warning # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR # OTHER DEALINGS IN THE SOFTWARE. -########################################## +########################################## \ No newline at end of file diff --git a/shared-infrastructure b/shared-infrastructure index 86af5a821..5eb77e2d9 160000 --- a/shared-infrastructure +++ b/shared-infrastructure @@ -1 +1 @@ -Subproject commit 86af5a82198c21ce6889370428eb97d1fa7b41ff +Subproject commit 5eb77e2d9eb4f0ece012c996941ab78db1af2a41 diff --git a/src/ImageSharp/Advanced/AdvancedImageExtensions.cs b/src/ImageSharp/Advanced/AdvancedImageExtensions.cs index 8a7046c9a..2fbb42995 100644 --- a/src/ImageSharp/Advanced/AdvancedImageExtensions.cs +++ b/src/ImageSharp/Advanced/AdvancedImageExtensions.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Text; using System.Threading; @@ -34,11 +35,11 @@ namespace SixLabors.ImageSharp.Advanced IImageFormat format = source.GetConfiguration().ImageFormatsManager.FindFormatByFileExtension(ext); if (format is null) { - var sb = new StringBuilder(); - sb.AppendLine($"No encoder was found for extension '{ext}'. Registered encoders include:"); + StringBuilder sb = new(); + sb.AppendLine(CultureInfo.InvariantCulture, $"No encoder was found for extension '{ext}'. Registered encoders include:"); foreach (IImageFormat fmt in source.GetConfiguration().ImageFormats) { - sb.AppendFormat(" - {0} : {1}{2}", fmt.Name, string.Join(", ", fmt.FileExtensions), Environment.NewLine); + sb.AppendFormat(CultureInfo.InvariantCulture, " - {0} : {1}{2}", fmt.Name, string.Join(", ", fmt.FileExtensions), Environment.NewLine); } throw new NotSupportedException(sb.ToString()); @@ -48,11 +49,11 @@ namespace SixLabors.ImageSharp.Advanced if (encoder is null) { - var sb = new StringBuilder(); - sb.AppendLine($"No encoder was found for extension '{ext}' using image format '{format.Name}'. Registered encoders include:"); + StringBuilder sb = new(); + sb.AppendLine(CultureInfo.InvariantCulture, $"No encoder was found for extension '{ext}' using image format '{format.Name}'. Registered encoders include:"); foreach (KeyValuePair enc in source.GetConfiguration().ImageFormatsManager.ImageEncoders) { - sb.AppendFormat(" - {0} : {1}{2}", enc.Key, enc.Value.GetType().Name, Environment.NewLine); + sb.AppendFormat(CultureInfo.InvariantCulture, " - {0} : {1}{2}", enc.Key, enc.Value.GetType().Name, Environment.NewLine); } throw new NotSupportedException(sb.ToString()); @@ -116,6 +117,7 @@ namespace SixLabors.ImageSharp.Advanced /// Certain Image Processors may invalidate the returned and all it's buffers, /// therefore it's not recommended to mutate the image while holding a reference to it's . /// + /// Thrown when the in . public static IMemoryGroup GetPixelMemoryGroup(this ImageFrame source) where TPixel : unmanaged, IPixel => source?.PixelBuffer.FastMemoryGroup.View ?? throw new ArgumentNullException(nameof(source)); @@ -131,13 +133,14 @@ namespace SixLabors.ImageSharp.Advanced /// Certain Image Processors may invalidate the returned and all it's buffers, /// therefore it's not recommended to mutate the image while holding a reference to it's . /// + /// Thrown when the in . public static IMemoryGroup GetPixelMemoryGroup(this Image source) where TPixel : unmanaged, IPixel => source?.Frames.RootFrame.GetPixelMemoryGroup() ?? throw new ArgumentNullException(nameof(source)); /// /// Gets the representation of the pixels as a of contiguous memory - /// at row beginning from the the first pixel on that row. + /// at row beginning from the first pixel on that row. /// /// The type of the pixel. /// The source. @@ -154,8 +157,8 @@ namespace SixLabors.ImageSharp.Advanced } /// - /// Gets the representation of the pixels as of of contiguous memory - /// at row beginning from the the first pixel on that row. + /// Gets the representation of the pixels as of contiguous memory + /// at row beginning from the first pixel on that row. /// /// The type of the pixel. /// The source. diff --git a/src/ImageSharp/Advanced/PreserveAttribute.cs b/src/ImageSharp/Advanced/PreserveAttribute.cs index d543a043c..5e3a71270 100644 --- a/src/ImageSharp/Advanced/PreserveAttribute.cs +++ b/src/ImageSharp/Advanced/PreserveAttribute.cs @@ -1,6 +1,8 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +using System; + namespace SixLabors.ImageSharp.Advanced { /// @@ -8,7 +10,8 @@ namespace SixLabors.ImageSharp.Advanced /// The only thing that matters is the class name. /// There is no need to use or inherit from the PreserveAttribute class in each environment. /// - internal sealed class PreserveAttribute : System.Attribute + [AttributeUsage(AttributeTargets.Method)] + internal sealed class PreserveAttribute : Attribute { } } diff --git a/src/ImageSharp/Color/Color.cs b/src/ImageSharp/Color/Color.cs index d8fb34891..17e0964d0 100644 --- a/src/ImageSharp/Color/Color.cs +++ b/src/ImageSharp/Color/Color.cs @@ -151,7 +151,7 @@ namespace SixLabors.ImageSharp [MethodImpl(InliningOptions.ShortMethod)] public static Color ParseHex(string hex) { - var rgba = Rgba32.ParseHex(hex); + Rgba32 rgba = Rgba32.ParseHex(hex); return new Color(rgba); } @@ -193,6 +193,7 @@ namespace SixLabors.ImageSharp /// /// The . /// + /// Input string is not in the correct format. public static Color Parse(string input) { Guard.NotNull(input, nameof(input)); @@ -241,7 +242,7 @@ namespace SixLabors.ImageSharp /// The color having it's alpha channel altered. public Color WithAlpha(float alpha) { - var v = (Vector4)this; + Vector4 v = (Vector4)this; v.W = alpha; return new Color(v); } @@ -286,14 +287,10 @@ namespace SixLabors.ImageSharp /// Bulk converts a span of to a span of a specified type. /// /// The pixel type to convert to. - /// The configuration. /// The source color span. /// The destination pixel span. [MethodImpl(InliningOptions.ShortMethod)] - public static void ToPixel( - Configuration configuration, - ReadOnlySpan source, - Span destination) + public static void ToPixel(ReadOnlySpan source, Span destination) where TPixel : unmanaged, IPixel { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); diff --git a/src/ImageSharp/ColorSpaces/CieLab.cs b/src/ImageSharp/ColorSpaces/CieLab.cs index b72a2eecd..bc84342de 100644 --- a/src/ImageSharp/ColorSpaces/CieLab.cs +++ b/src/ImageSharp/ColorSpaces/CieLab.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -19,29 +19,6 @@ namespace SixLabors.ImageSharp.ColorSpaces /// public static readonly CieXyz DefaultWhitePoint = Illuminants.D50; - /// - /// Gets the lightness dimension. - /// A value usually ranging between 0 (black), 100 (diffuse white) or higher (specular white). - /// - public readonly float L; - - /// - /// Gets the a color component. - /// A value usually ranging from -100 to 100. Negative is green, positive magenta. - /// - public readonly float A; - - /// - /// Gets the b color component. - /// A value usually ranging from -100 to 100. Negative is blue, positive is yellow - /// - public readonly float B; - - /// - /// Gets the reference white point of this color - /// - public readonly CieXyz WhitePoint; - /// /// Initializes a new instance of the struct. /// @@ -95,6 +72,29 @@ namespace SixLabors.ImageSharp.ColorSpaces this.WhitePoint = whitePoint; } + /// + /// Gets the lightness dimension. + /// A value usually ranging between 0 (black), 100 (diffuse white) or higher (specular white). + /// + public readonly float L { get; } + + /// + /// Gets the a color component. + /// A value usually ranging from -100 to 100. Negative is green, positive magenta. + /// + public readonly float A { get; } + + /// + /// Gets the b color component. + /// A value usually ranging from -100 to 100. Negative is blue, positive is yellow + /// + public readonly float B { get; } + + /// + /// Gets the reference white point of this color + /// + public readonly CieXyz WhitePoint { get; } + /// /// Compares two objects for equality. /// @@ -128,12 +128,10 @@ namespace SixLabors.ImageSharp.ColorSpaces /// [MethodImpl(InliningOptions.ShortMethod)] - public bool Equals(CieLab other) - { - return this.L.Equals(other.L) - && this.A.Equals(other.A) - && this.B.Equals(other.B) - && this.WhitePoint.Equals(other.WhitePoint); - } + public bool Equals(CieLab other) => + this.L.Equals(other.L) + && this.A.Equals(other.A) + && this.B.Equals(other.B) + && this.WhitePoint.Equals(other.WhitePoint); } } diff --git a/src/ImageSharp/ColorSpaces/CieLch.cs b/src/ImageSharp/ColorSpaces/CieLch.cs index 899c7d8db..0c46e9b7c 100644 --- a/src/ImageSharp/ColorSpaces/CieLch.cs +++ b/src/ImageSharp/ColorSpaces/CieLch.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -19,31 +19,8 @@ namespace SixLabors.ImageSharp.ColorSpaces /// public static readonly CieXyz DefaultWhitePoint = Illuminants.D50; - private static readonly Vector3 Min = new Vector3(0, -200, 0); - private static readonly Vector3 Max = new Vector3(100, 200, 360); - - /// - /// Gets the lightness dimension. - /// A value ranging between 0 (black), 100 (diffuse white) or higher (specular white). - /// - public readonly float L; - - /// - /// Gets the a chroma component. - /// A value ranging from 0 to 200. - /// - public readonly float C; - - /// - /// Gets the h° hue component in degrees. - /// A value ranging from 0 to 360. - /// - public readonly float H; - - /// - /// Gets the reference white point of this color - /// - public readonly CieXyz WhitePoint; + private static readonly Vector3 Min = new(0, -200, 0); + private static readonly Vector3 Max = new(100, 200, 360); /// /// Initializes a new instance of the struct. @@ -97,6 +74,29 @@ namespace SixLabors.ImageSharp.ColorSpaces this.WhitePoint = whitePoint; } + /// + /// Gets the lightness dimension. + /// A value ranging between 0 (black), 100 (diffuse white) or higher (specular white). + /// + public readonly float L { get; } + + /// + /// Gets the a chroma component. + /// A value ranging from 0 to 200. + /// + public readonly float C { get; } + + /// + /// Gets the h° hue component in degrees. + /// A value ranging from 0 to 360. + /// + public readonly float H { get; } + + /// + /// Gets the reference white point of this color + /// + public readonly CieXyz WhitePoint { get; } + /// /// Compares two objects for equality. /// @@ -121,9 +121,7 @@ namespace SixLabors.ImageSharp.ColorSpaces /// public override int GetHashCode() - { - return HashCode.Combine(this.L, this.C, this.H, this.WhitePoint); - } + => HashCode.Combine(this.L, this.C, this.H, this.WhitePoint); /// public override string ToString() => FormattableString.Invariant($"CieLch({this.L:#0.##}, {this.C:#0.##}, {this.H:#0.##})"); @@ -135,12 +133,10 @@ namespace SixLabors.ImageSharp.ColorSpaces /// [MethodImpl(InliningOptions.ShortMethod)] public bool Equals(CieLch other) - { - return this.L.Equals(other.L) - && this.C.Equals(other.C) - && this.H.Equals(other.H) - && this.WhitePoint.Equals(other.WhitePoint); - } + => this.L.Equals(other.L) + && this.C.Equals(other.C) + && this.H.Equals(other.H) + && this.WhitePoint.Equals(other.WhitePoint); /// /// Computes the saturation of the color (chroma normalized by lightness) diff --git a/src/ImageSharp/ColorSpaces/CieLchuv.cs b/src/ImageSharp/ColorSpaces/CieLchuv.cs index 2a41fd490..2227b6022 100644 --- a/src/ImageSharp/ColorSpaces/CieLchuv.cs +++ b/src/ImageSharp/ColorSpaces/CieLchuv.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -13,8 +13,8 @@ namespace SixLabors.ImageSharp.ColorSpaces /// public readonly struct CieLchuv : IEquatable { - private static readonly Vector3 Min = new Vector3(0, -200, 0); - private static readonly Vector3 Max = new Vector3(100, 200, 360); + private static readonly Vector3 Min = new(0, -200, 0); + private static readonly Vector3 Max = new(100, 200, 360); /// /// D50 standard illuminant. @@ -22,29 +22,6 @@ namespace SixLabors.ImageSharp.ColorSpaces /// public static readonly CieXyz DefaultWhitePoint = Illuminants.D65; - /// - /// Gets the lightness dimension. - /// A value ranging between 0 (black), 100 (diffuse white) or higher (specular white). - /// - public readonly float L; - - /// - /// Gets the a chroma component. - /// A value ranging from 0 to 200. - /// - public readonly float C; - - /// - /// Gets the h° hue component in degrees. - /// A value ranging from 0 to 360. - /// - public readonly float H; - - /// - /// Gets the reference white point of this color - /// - public readonly CieXyz WhitePoint; - /// /// Initializes a new instance of the struct. /// @@ -98,6 +75,29 @@ namespace SixLabors.ImageSharp.ColorSpaces this.WhitePoint = whitePoint; } + /// + /// Gets the lightness dimension. + /// A value ranging between 0 (black), 100 (diffuse white) or higher (specular white). + /// + public readonly float L { get; } + + /// + /// Gets the a chroma component. + /// A value ranging from 0 to 200. + /// + public readonly float C { get; } + + /// + /// Gets the h° hue component in degrees. + /// A value ranging from 0 to 360. + /// + public readonly float H { get; } + + /// + /// Gets the reference white point of this color + /// + public readonly CieXyz WhitePoint { get; } + /// /// Compares two objects for equality. /// @@ -130,12 +130,10 @@ namespace SixLabors.ImageSharp.ColorSpaces /// [MethodImpl(InliningOptions.ShortMethod)] public bool Equals(CieLchuv other) - { - return this.L.Equals(other.L) - && this.C.Equals(other.C) - && this.H.Equals(other.H) - && this.WhitePoint.Equals(other.WhitePoint); - } + => this.L.Equals(other.L) + && this.C.Equals(other.C) + && this.H.Equals(other.H) + && this.WhitePoint.Equals(other.WhitePoint); /// /// Computes the saturation of the color (chroma normalized by lightness) diff --git a/src/ImageSharp/ColorSpaces/CieLuv.cs b/src/ImageSharp/ColorSpaces/CieLuv.cs index a45042ba8..32481bcb5 100644 --- a/src/ImageSharp/ColorSpaces/CieLuv.cs +++ b/src/ImageSharp/ColorSpaces/CieLuv.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -21,29 +21,6 @@ namespace SixLabors.ImageSharp.ColorSpaces /// public static readonly CieXyz DefaultWhitePoint = Illuminants.D65; - /// - /// Gets the lightness dimension - /// A value usually ranging between 0 and 100. - /// - public readonly float L; - - /// - /// Gets the blue-yellow chromaticity coordinate of the given whitepoint. - /// A value usually ranging between -100 and 100. - /// - public readonly float U; - - /// - /// Gets the red-green chromaticity coordinate of the given whitepoint. - /// A value usually ranging between -100 and 100. - /// - public readonly float V; - - /// - /// Gets the reference white point of this color - /// - public readonly CieXyz WhitePoint; - /// /// Initializes a new instance of the struct. /// @@ -96,6 +73,29 @@ namespace SixLabors.ImageSharp.ColorSpaces this.WhitePoint = whitePoint; } + /// + /// Gets the lightness dimension + /// A value usually ranging between 0 and 100. + /// + public readonly float L { get; } + + /// + /// Gets the blue-yellow chromaticity coordinate of the given whitepoint. + /// A value usually ranging between -100 and 100. + /// + public readonly float U { get; } + + /// + /// Gets the red-green chromaticity coordinate of the given whitepoint. + /// A value usually ranging between -100 and 100. + /// + public readonly float V { get; } + + /// + /// Gets the reference white point of this color + /// + public readonly CieXyz WhitePoint { get; } + /// /// Compares two objects for equality. /// @@ -130,11 +130,9 @@ namespace SixLabors.ImageSharp.ColorSpaces /// [MethodImpl(InliningOptions.ShortMethod)] public bool Equals(CieLuv other) - { - return this.L.Equals(other.L) - && this.U.Equals(other.U) - && this.V.Equals(other.V) - && this.WhitePoint.Equals(other.WhitePoint); - } + => this.L.Equals(other.L) + && this.U.Equals(other.U) + && this.V.Equals(other.V) + && this.WhitePoint.Equals(other.WhitePoint); } } diff --git a/src/ImageSharp/ColorSpaces/CieXyy.cs b/src/ImageSharp/ColorSpaces/CieXyy.cs index 9306606db..6bbcad075 100644 --- a/src/ImageSharp/ColorSpaces/CieXyy.cs +++ b/src/ImageSharp/ColorSpaces/CieXyy.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -13,24 +13,6 @@ namespace SixLabors.ImageSharp.ColorSpaces /// public readonly struct CieXyy : IEquatable { - /// - /// Gets the X chrominance component. - /// A value usually ranging between 0 and 1. - /// - public readonly float X; - - /// - /// Gets the Y chrominance component. - /// A value usually ranging between 0 and 1. - /// - public readonly float Y; - - /// - /// Gets the Y luminance component. - /// A value usually ranging between 0 and 1. - /// - public readonly float Yl; - /// /// Initializes a new instance of the struct. /// @@ -60,6 +42,24 @@ namespace SixLabors.ImageSharp.ColorSpaces this.Yl = vector.Z; } + /// + /// Gets the X chrominance component. + /// A value usually ranging between 0 and 1. + /// + public readonly float X { get; } + + /// + /// Gets the Y chrominance component. + /// A value usually ranging between 0 and 1. + /// + public readonly float Y { get; } + + /// + /// Gets the Y luminance component. + /// A value usually ranging between 0 and 1. + /// + public readonly float Yl { get; } + /// /// Compares two objects for equality. /// @@ -94,10 +94,8 @@ namespace SixLabors.ImageSharp.ColorSpaces /// [MethodImpl(InliningOptions.ShortMethod)] public bool Equals(CieXyy other) - { - return this.X.Equals(other.X) - && this.Y.Equals(other.Y) - && this.Yl.Equals(other.Yl); - } + => this.X.Equals(other.X) + && this.Y.Equals(other.Y) + && this.Yl.Equals(other.Yl); } } diff --git a/src/ImageSharp/ColorSpaces/CieXyz.cs b/src/ImageSharp/ColorSpaces/CieXyz.cs index e52904c55..b76712843 100644 --- a/src/ImageSharp/ColorSpaces/CieXyz.cs +++ b/src/ImageSharp/ColorSpaces/CieXyz.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -13,24 +13,6 @@ namespace SixLabors.ImageSharp.ColorSpaces /// public readonly struct CieXyz : IEquatable { - /// - /// Gets the X component. A mix (a linear combination) of cone response curves chosen to be nonnegative. - /// A value usually ranging between 0 and 1. - /// - public readonly float X; - - /// - /// Gets the Y luminance component. - /// A value usually ranging between 0 and 1. - /// - public readonly float Y; - - /// - /// Gets the Z component. Quasi-equal to blue stimulation, or the S cone response. - /// A value usually ranging between 0 and 1. - /// - public readonly float Z; - /// /// Initializes a new instance of the struct. /// @@ -56,6 +38,24 @@ namespace SixLabors.ImageSharp.ColorSpaces this.Z = vector.Z; } + /// + /// Gets the X component. A mix (a linear combination) of cone response curves chosen to be nonnegative. + /// A value usually ranging between 0 and 1. + /// + public readonly float X { get; } + + /// + /// Gets the Y luminance component. + /// A value usually ranging between 0 and 1. + /// + public readonly float Y { get; } + + /// + /// Gets the Z component. Quasi-equal to blue stimulation, or the S cone response. + /// A value usually ranging between 0 and 1. + /// + public readonly float Z { get; } + /// /// Compares two objects for equality. /// @@ -83,7 +83,7 @@ namespace SixLabors.ImageSharp.ColorSpaces /// /// The . [MethodImpl(InliningOptions.ShortMethod)] - public Vector3 ToVector3() => new Vector3(this.X, this.Y, this.Z); + public Vector3 ToVector3() => new(this.X, this.Y, this.Z); /// public override int GetHashCode() => HashCode.Combine(this.X, this.Y, this.Z); @@ -97,10 +97,8 @@ namespace SixLabors.ImageSharp.ColorSpaces /// [MethodImpl(InliningOptions.ShortMethod)] public bool Equals(CieXyz other) - { - return this.X.Equals(other.X) - && this.Y.Equals(other.Y) - && this.Z.Equals(other.Z); - } + => this.X.Equals(other.X) + && this.Y.Equals(other.Y) + && this.Z.Equals(other.Z); } } diff --git a/src/ImageSharp/ColorSpaces/Cmyk.cs b/src/ImageSharp/ColorSpaces/Cmyk.cs index cd2899ee7..fad331101 100644 --- a/src/ImageSharp/ColorSpaces/Cmyk.cs +++ b/src/ImageSharp/ColorSpaces/Cmyk.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -15,30 +15,6 @@ namespace SixLabors.ImageSharp.ColorSpaces private static readonly Vector4 Min = Vector4.Zero; private static readonly Vector4 Max = Vector4.One; - /// - /// Gets the cyan color component. - /// A value ranging between 0 and 1. - /// - public readonly float C; - - /// - /// Gets the magenta color component. - /// A value ranging between 0 and 1. - /// - public readonly float M; - - /// - /// Gets the yellow color component. - /// A value ranging between 0 and 1. - /// - public readonly float Y; - - /// - /// Gets the keyline black color component. - /// A value ranging between 0 and 1. - /// - public readonly float K; - /// /// Initializes a new instance of the struct. /// @@ -66,6 +42,30 @@ namespace SixLabors.ImageSharp.ColorSpaces this.K = vector.W; } + /// + /// Gets the cyan color component. + /// A value ranging between 0 and 1. + /// + public readonly float C { get; } + + /// + /// Gets the magenta color component. + /// A value ranging between 0 and 1. + /// + public readonly float M { get; } + + /// + /// Gets the yellow color component. + /// A value ranging between 0 and 1. + /// + public readonly float Y { get; } + + /// + /// Gets the keyline black color component. + /// A value ranging between 0 and 1. + /// + public readonly float K { get; } + /// /// Compares two objects for equality. /// @@ -101,11 +101,9 @@ namespace SixLabors.ImageSharp.ColorSpaces /// [MethodImpl(InliningOptions.ShortMethod)] public bool Equals(Cmyk other) - { - return this.C.Equals(other.C) - && this.M.Equals(other.M) - && this.Y.Equals(other.Y) - && this.K.Equals(other.K); - } + => this.C.Equals(other.C) + && this.M.Equals(other.M) + && this.Y.Equals(other.Y) + && this.K.Equals(other.K); } } diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Adapt.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Adapt.cs index 60ae18b5c..d200aa83e 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Adapt.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Adapt.cs @@ -150,9 +150,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion return color; } - var linearInput = this.ToLinearRgb(color); + var linearInput = ToLinearRgb(color); LinearRgb linearOutput = this.Adapt(linearInput); - return this.ToRgb(linearOutput); + return ToRgb(linearOutput); } } } diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLab.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLab.cs index 1a7c627db..c3dd3b473 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLab.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLab.cs @@ -12,11 +12,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// public partial class ColorSpaceConverter { - /// - /// The converter for converting between CieLch to CieLab. - /// - private static readonly CieLchToCieLabConverter CieLchToCieLabConverter = new CieLchToCieLabConverter(); - /// /// Converts a into a . /// @@ -58,7 +53,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLab ToCieLab(in CieLchuv color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToCieLab(xyzColor); } @@ -91,7 +86,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLab ToCieLab(in CieLuv color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToCieLab(xyzColor); } @@ -124,7 +119,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLab ToCieLab(in CieXyy color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = ToCieXyz(color); return this.ToCieLab(xyzColor); } @@ -190,7 +185,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLab ToCieLab(in Cmyk color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToCieLab(xyzColor); } @@ -222,7 +217,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLab ToCieLab(in Hsl color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToCieLab(xyzColor); } @@ -255,7 +250,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLab ToCieLab(in Hsv color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToCieLab(xyzColor); } @@ -287,7 +282,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLab ToCieLab(in HunterLab color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToCieLab(xyzColor); } @@ -320,7 +315,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLab ToCieLab(in Lms color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToCieLab(xyzColor); } @@ -353,7 +348,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLab ToCieLab(in LinearRgb color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToCieLab(xyzColor); } @@ -386,7 +381,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLab ToCieLab(in Rgb color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToCieLab(xyzColor); } @@ -419,7 +414,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLab ToCieLab(in YCbCr color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToCieLab(xyzColor); } diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs index 06ff11b1e..ec7d48b78 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs @@ -12,11 +12,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// public partial class ColorSpaceConverter { - /// - /// The converter for converting between CieLab to CieLch. - /// - private static readonly CieLabToCieLchConverter CieLabToCieLchConverter = new CieLabToCieLchConverter(); - /// /// Converts a into a /// @@ -123,7 +118,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLch ToCieLch(in CieXyy color) { - var xyzColor = this.ToCieXyz(color); + var xyzColor = ToCieXyz(color); return this.ToCieLch(xyzColor); } diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLchuv.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLchuv.cs index 5752cb9b1..52c092a2e 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLchuv.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLchuv.cs @@ -12,11 +12,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// public partial class ColorSpaceConverter { - /// - /// The converter for converting between CieLab to CieLchuv. - /// - private static readonly CieLuvToCieLchuvConverter CieLuvToCieLchuvConverter = new CieLuvToCieLchuvConverter(); - /// /// Converts a into a /// @@ -24,7 +19,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLchuv ToCieLchuv(in CieLab color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToCieLchuv(xyzColor); } @@ -57,7 +52,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLchuv ToCieLchuv(in CieLch color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToCieLchuv(xyzColor); } @@ -123,7 +118,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLchuv ToCieLchuv(in CieXyy color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = ToCieXyz(color); return this.ToCieLchuv(xyzColor); } @@ -156,7 +151,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLchuv ToCieLchuv(in CieXyz color) { - var luvColor = this.ToCieLuv(color); + CieLuv luvColor = this.ToCieLuv(color); return this.ToCieLchuv(luvColor); } @@ -189,7 +184,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLchuv ToCieLchuv(in Cmyk color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToCieLchuv(xyzColor); } @@ -222,7 +217,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLchuv ToCieLchuv(in Hsl color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToCieLchuv(xyzColor); } @@ -255,7 +250,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLchuv ToCieLchuv(in Hsv color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToCieLchuv(xyzColor); } @@ -288,7 +283,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLchuv ToCieLchuv(in HunterLab color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToCieLchuv(xyzColor); } @@ -321,7 +316,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLchuv ToCieLchuv(in LinearRgb color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToCieLchuv(xyzColor); } @@ -354,7 +349,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLchuv ToCieLchuv(in Lms color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToCieLchuv(xyzColor); } @@ -387,7 +382,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLchuv ToCieLchuv(in Rgb color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToCieLchuv(xyzColor); } @@ -420,7 +415,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLchuv ToCieLchuv(in YCbCr color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToCieLchuv(xyzColor); } diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLuv.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLuv.cs index 486924b9a..572d8875d 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLuv.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLuv.cs @@ -12,8 +12,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// public partial class ColorSpaceConverter { - private static readonly CieLchuvToCieLuvConverter CieLchuvToCieLuvConverter = new CieLchuvToCieLuvConverter(); - /// /// Converts a into a . /// @@ -21,7 +19,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLuv ToCieLuv(in CieLab color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToCieLuv(xyzColor); } @@ -53,7 +51,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLuv ToCieLuv(in CieLch color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToCieLuv(xyzColor); } @@ -120,7 +118,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLuv ToCieLuv(in CieXyy color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = ToCieXyz(color); return this.ToCieLuv(xyzColor); } @@ -187,7 +185,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLuv ToCieLuv(in Cmyk color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToCieLuv(xyzColor); } @@ -219,7 +217,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLuv ToCieLuv(in Hsl color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToCieLuv(xyzColor); } @@ -251,7 +249,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLuv ToCieLuv(in Hsv color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToCieLuv(xyzColor); } @@ -283,7 +281,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLuv ToCieLuv(in HunterLab color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToCieLuv(xyzColor); } @@ -315,7 +313,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLuv ToCieLuv(in Lms color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToCieLuv(xyzColor); } @@ -347,7 +345,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLuv ToCieLuv(in LinearRgb color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToCieLuv(xyzColor); } @@ -379,7 +377,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLuv ToCieLuv(in Rgb color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToCieLuv(xyzColor); } @@ -411,7 +409,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLuv ToCieLuv(in YCbCr color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToCieLuv(xyzColor); } diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyy.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyy.cs index 603308751..b5d655e68 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyy.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyy.cs @@ -12,8 +12,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// public partial class ColorSpaceConverter { - private static readonly CieXyzAndCieXyyConverter CieXyzAndCieXyyConverter = new CieXyzAndCieXyyConverter(); - /// /// Converts a into a /// @@ -21,9 +19,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieXyy ToCieXyy(in CieLab color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); - return this.ToCieXyy(xyzColor); + return ToCieXyy(xyzColor); } /// @@ -54,9 +52,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieXyy ToCieXyy(in CieLch color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); - return this.ToCieXyy(xyzColor); + return ToCieXyy(xyzColor); } /// @@ -87,9 +85,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieXyy ToCieXyy(in CieLchuv color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); - return this.ToCieXyy(xyzColor); + return ToCieXyy(xyzColor); } /// @@ -120,9 +118,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieXyy ToCieXyy(in CieLuv color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); - return this.ToCieXyy(xyzColor); + return ToCieXyy(xyzColor); } /// @@ -151,14 +149,14 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The color to convert. /// The - public CieXyy ToCieXyy(in CieXyz color) => CieXyzAndCieXyyConverter.Convert(color); + public static CieXyy ToCieXyy(in CieXyz color) => CieXyzAndCieXyyConverter.Convert(color); /// /// Performs the bulk conversion from into /// /// The span to the source colors /// The span to the destination colors - public void Convert(ReadOnlySpan source, Span destination) + public static void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); int count = source.Length; @@ -170,7 +168,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion { ref CieXyz sp = ref Unsafe.Add(ref sourceRef, i); ref CieXyy dp = ref Unsafe.Add(ref destRef, i); - dp = this.ToCieXyy(sp); + dp = ToCieXyy(sp); } } @@ -181,9 +179,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieXyy ToCieXyy(in Cmyk color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); - return this.ToCieXyy(xyzColor); + return ToCieXyy(xyzColor); } /// @@ -214,9 +212,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieXyy ToCieXyy(Hsl color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); - return this.ToCieXyy(xyzColor); + return ToCieXyy(xyzColor); } /// @@ -247,9 +245,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieXyy ToCieXyy(in Hsv color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); - return this.ToCieXyy(xyzColor); + return ToCieXyy(xyzColor); } /// @@ -280,9 +278,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieXyy ToCieXyy(in HunterLab color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); - return this.ToCieXyy(xyzColor); + return ToCieXyy(xyzColor); } /// @@ -313,9 +311,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieXyy ToCieXyy(in LinearRgb color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); - return this.ToCieXyy(xyzColor); + return ToCieXyy(xyzColor); } /// @@ -346,9 +344,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieXyy ToCieXyy(in Lms color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); - return this.ToCieXyy(xyzColor); + return ToCieXyy(xyzColor); } /// @@ -379,9 +377,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieXyy ToCieXyy(in Rgb color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); - return this.ToCieXyy(xyzColor); + return ToCieXyy(xyzColor); } /// @@ -412,9 +410,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieXyy ToCieXyy(in YCbCr color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); - return this.ToCieXyy(xyzColor); + return ToCieXyy(xyzColor); } /// diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs index 242392acc..d1f0ca489 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs @@ -12,12 +12,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// public partial class ColorSpaceConverter { - private static readonly CieLabToCieXyzConverter CieLabToCieXyzConverter = new CieLabToCieXyzConverter(); - - private static readonly CieLuvToCieXyzConverter CieLuvToCieXyzConverter = new CieLuvToCieXyzConverter(); - - private static readonly HunterLabToCieXyzConverter - HunterLabToCieXyzConverter = new HunterLabToCieXyzConverter(); + private static readonly HunterLabToCieXyzConverter HunterLabToCieXyzConverter = new(); private LinearRgbToCieXyzConverter linearRgbToCieXyzConverter; @@ -166,18 +161,17 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The color to convert. /// The - public CieXyz ToCieXyz(in CieXyy color) - { + public static CieXyz ToCieXyz(in CieXyy color) + // Conversion - return CieXyzAndCieXyyConverter.Convert(color); - } + => CieXyzAndCieXyyConverter.Convert(color); /// /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors - public void Convert(ReadOnlySpan source, Span destination) + public static void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); int count = source.Length; @@ -189,7 +183,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion { ref CieXyy sp = ref Unsafe.Add(ref sourceRef, i); ref CieXyz dp = ref Unsafe.Add(ref destRef, i); - dp = this.ToCieXyz(sp); + dp = ToCieXyz(sp); } } @@ -200,7 +194,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieXyz ToCieXyz(in Cmyk color) { - var rgb = this.ToRgb(color); + Rgb rgb = ToRgb(color); return this.ToCieXyz(rgb); } @@ -233,7 +227,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieXyz ToCieXyz(in Hsl color) { - var rgb = this.ToRgb(color); + Rgb rgb = ToRgb(color); return this.ToCieXyz(rgb); } @@ -267,7 +261,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion public CieXyz ToCieXyz(in Hsv color) { // Conversion - var rgb = this.ToRgb(color); + Rgb rgb = ToRgb(color); return this.ToCieXyz(rgb); } @@ -367,9 +361,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The color to convert. /// The public CieXyz ToCieXyz(in Lms color) - { - return this.cieXyzAndLmsConverter.Convert(color); - } + => this.cieXyzAndLmsConverter.Convert(color); /// /// Performs the bulk conversion from into . @@ -432,7 +424,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieXyz ToCieXyz(in YCbCr color) { - var rgb = this.ToRgb(color); + Rgb rgb = this.ToRgb(color); return this.ToCieXyz(rgb); } diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Cmyk.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Cmyk.cs index 664511be9..152a7f7fc 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Cmyk.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Cmyk.cs @@ -12,8 +12,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// public partial class ColorSpaceConverter { - private static readonly CmykAndRgbConverter CmykAndRgbConverter = new CmykAndRgbConverter(); - /// /// Converts a into a . /// @@ -21,7 +19,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public Cmyk ToCmyk(in CieLab color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToCmyk(xyzColor); } @@ -54,7 +52,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public Cmyk ToCmyk(in CieLch color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToCmyk(xyzColor); } @@ -87,7 +85,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public Cmyk ToCmyk(in CieLchuv color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToCmyk(xyzColor); } @@ -120,7 +118,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public Cmyk ToCmyk(in CieLuv color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToCmyk(xyzColor); } @@ -153,7 +151,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public Cmyk ToCmyk(in CieXyy color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = ToCieXyz(color); return this.ToCmyk(xyzColor); } @@ -186,7 +184,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public Cmyk ToCmyk(in CieXyz color) { - var rgb = this.ToRgb(color); + Rgb rgb = this.ToRgb(color); return CmykAndRgbConverter.Convert(rgb); } @@ -217,9 +215,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The color to convert. /// The - public Cmyk ToCmyk(in Hsl color) + public static Cmyk ToCmyk(in Hsl color) { - var rgb = this.ToRgb(color); + Rgb rgb = ToRgb(color); return CmykAndRgbConverter.Convert(rgb); } @@ -229,7 +227,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The span to the source colors /// The span to the destination colors - public void Convert(ReadOnlySpan source, Span destination) + public static void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); int count = source.Length; @@ -241,7 +239,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion { ref Hsl sp = ref Unsafe.Add(ref sourceRef, i); ref Cmyk dp = ref Unsafe.Add(ref destRef, i); - dp = this.ToCmyk(sp); + dp = ToCmyk(sp); } } @@ -250,9 +248,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The color to convert. /// The - public Cmyk ToCmyk(in Hsv color) + public static Cmyk ToCmyk(in Hsv color) { - var rgb = this.ToRgb(color); + Rgb rgb = ToRgb(color); return CmykAndRgbConverter.Convert(rgb); } @@ -262,7 +260,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The span to the source colors /// The span to the destination colors - public void Convert(ReadOnlySpan source, Span destination) + public static void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); int count = source.Length; @@ -274,7 +272,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion { ref Hsv sp = ref Unsafe.Add(ref sourceRef, i); ref Cmyk dp = ref Unsafe.Add(ref destRef, i); - dp = this.ToCmyk(sp); + dp = ToCmyk(sp); } } @@ -285,7 +283,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public Cmyk ToCmyk(in HunterLab color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToCmyk(xyzColor); } @@ -316,9 +314,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The color to convert. /// The - public Cmyk ToCmyk(in LinearRgb color) + public static Cmyk ToCmyk(in LinearRgb color) { - var rgb = this.ToRgb(color); + Rgb rgb = ToRgb(color); return CmykAndRgbConverter.Convert(rgb); } @@ -328,7 +326,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The span to the source colors /// The span to the destination colors - public void Convert(ReadOnlySpan source, Span destination) + public static void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); int count = source.Length; @@ -340,7 +338,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion { ref LinearRgb sp = ref Unsafe.Add(ref sourceRef, i); ref Cmyk dp = ref Unsafe.Add(ref destRef, i); - dp = this.ToCmyk(sp); + dp = ToCmyk(sp); } } @@ -351,7 +349,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public Cmyk ToCmyk(in Lms color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToCmyk(xyzColor); } @@ -382,14 +380,14 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The color to convert. /// The - public Cmyk ToCmyk(in Rgb color) => CmykAndRgbConverter.Convert(color); + public static Cmyk ToCmyk(in Rgb color) => CmykAndRgbConverter.Convert(color); /// /// Performs the bulk conversion from into /// /// The span to the source colors /// The span to the destination colors - public void Convert(ReadOnlySpan source, Span destination) + public static void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); int count = source.Length; @@ -401,7 +399,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion { ref Rgb sp = ref Unsafe.Add(ref sourceRef, i); ref Cmyk dp = ref Unsafe.Add(ref destRef, i); - dp = this.ToCmyk(sp); + dp = ToCmyk(sp); } } @@ -412,7 +410,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public Cmyk ToCmyk(in YCbCr color) { - var rgb = this.ToRgb(color); + Rgb rgb = this.ToRgb(color); return CmykAndRgbConverter.Convert(rgb); } diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsl.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsl.cs index 666a6b03c..19e1bef0d 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsl.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsl.cs @@ -12,8 +12,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// public partial class ColorSpaceConverter { - private static readonly HslAndRgbConverter HslAndRgbConverter = new HslAndRgbConverter(); - /// /// Converts a into a . /// @@ -21,7 +19,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public Hsl ToHsl(in CieLab color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToHsl(xyzColor); } @@ -54,7 +52,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public Hsl ToHsl(in CieLch color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToHsl(xyzColor); } @@ -87,7 +85,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public Hsl ToHsl(in CieLchuv color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToHsl(xyzColor); } @@ -120,7 +118,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public Hsl ToHsl(in CieLuv color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToHsl(xyzColor); } @@ -153,7 +151,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public Hsl ToHsl(in CieXyy color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = ToCieXyz(color); return this.ToHsl(xyzColor); } @@ -186,7 +184,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public Hsl ToHsl(in CieXyz color) { - var rgb = this.ToRgb(color); + Rgb rgb = this.ToRgb(color); return HslAndRgbConverter.Convert(rgb); } @@ -217,9 +215,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The color to convert. /// The - public Hsl ToHsl(in Cmyk color) + public static Hsl ToHsl(in Cmyk color) { - var rgb = this.ToRgb(color); + Rgb rgb = ToRgb(color); return HslAndRgbConverter.Convert(rgb); } @@ -229,7 +227,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The span to the source colors /// The span to the destination colors - public void Convert(ReadOnlySpan source, Span destination) + public static void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); int count = source.Length; @@ -241,7 +239,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion { ref Cmyk sp = ref Unsafe.Add(ref sourceRef, i); ref Hsl dp = ref Unsafe.Add(ref destRef, i); - dp = this.ToHsl(sp); + dp = ToHsl(sp); } } @@ -250,9 +248,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The color to convert. /// The - public Hsl ToHsl(in Hsv color) + public static Hsl ToHsl(in Hsv color) { - var rgb = this.ToRgb(color); + Rgb rgb = ToRgb(color); return HslAndRgbConverter.Convert(rgb); } @@ -262,7 +260,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The span to the source colors /// The span to the destination colors - public void Convert(ReadOnlySpan source, Span destination) + public static void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); int count = source.Length; @@ -274,7 +272,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion { ref Hsv sp = ref Unsafe.Add(ref sourceRef, i); ref Hsl dp = ref Unsafe.Add(ref destRef, i); - dp = this.ToHsl(sp); + dp = ToHsl(sp); } } @@ -285,7 +283,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public Hsl ToHsl(in HunterLab color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToHsl(xyzColor); } @@ -316,9 +314,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The color to convert. /// The - public Hsl ToHsl(in LinearRgb color) + public static Hsl ToHsl(in LinearRgb color) { - var rgb = this.ToRgb(color); + Rgb rgb = ToRgb(color); return HslAndRgbConverter.Convert(rgb); } @@ -328,7 +326,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The span to the source colors /// The span to the destination colors - public void Convert(ReadOnlySpan source, Span destination) + public static void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); int count = source.Length; @@ -340,7 +338,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion { ref LinearRgb sp = ref Unsafe.Add(ref sourceRef, i); ref Hsl dp = ref Unsafe.Add(ref destRef, i); - dp = this.ToHsl(sp); + dp = ToHsl(sp); } } @@ -351,7 +349,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public Hsl ToHsl(Lms color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToHsl(xyzColor); } @@ -382,14 +380,14 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The color to convert. /// The - public Hsl ToHsl(in Rgb color) => HslAndRgbConverter.Convert(color); + public static Hsl ToHsl(in Rgb color) => HslAndRgbConverter.Convert(color); /// /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors - public void Convert(ReadOnlySpan source, Span destination) + public static void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); int count = source.Length; @@ -401,7 +399,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion { ref Rgb sp = ref Unsafe.Add(ref sourceRef, i); ref Hsl dp = ref Unsafe.Add(ref destRef, i); - dp = this.ToHsl(sp); + dp = ToHsl(sp); } } @@ -412,7 +410,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public Hsl ToHsl(in YCbCr color) { - var rgb = this.ToRgb(color); + Rgb rgb = this.ToRgb(color); return HslAndRgbConverter.Convert(rgb); } diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsv.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsv.cs index 615a26e36..c6a3a68d7 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsv.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsv.cs @@ -12,8 +12,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// public partial class ColorSpaceConverter { - private static readonly HsvAndRgbConverter HsvAndRgbConverter = new HsvAndRgbConverter(); - /// /// Converts a into a /// @@ -21,7 +19,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public Hsv ToHsv(in CieLab color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToHsv(xyzColor); } @@ -54,7 +52,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public Hsv ToHsv(in CieLch color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToHsv(xyzColor); } @@ -87,7 +85,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public Hsv ToHsv(in CieLchuv color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToHsv(xyzColor); } @@ -120,7 +118,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public Hsv ToHsv(in CieLuv color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToHsv(xyzColor); } @@ -153,7 +151,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public Hsv ToHsv(in CieXyy color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = ToCieXyz(color); return this.ToHsv(xyzColor); } @@ -186,7 +184,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public Hsv ToHsv(in CieXyz color) { - var rgb = this.ToRgb(color); + Rgb rgb = this.ToRgb(color); return HsvAndRgbConverter.Convert(rgb); } @@ -217,9 +215,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The color to convert. /// The - public Hsv ToHsv(in Cmyk color) + public static Hsv ToHsv(in Cmyk color) { - var rgb = this.ToRgb(color); + Rgb rgb = ToRgb(color); return HsvAndRgbConverter.Convert(rgb); } @@ -229,7 +227,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The span to the source colors /// The span to the destination colors - public void Convert(ReadOnlySpan source, Span destination) + public static void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); int count = source.Length; @@ -241,7 +239,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion { ref Cmyk sp = ref Unsafe.Add(ref sourceRef, i); ref Hsv dp = ref Unsafe.Add(ref destRef, i); - dp = this.ToHsv(sp); + dp = ToHsv(sp); } } @@ -250,9 +248,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The color to convert. /// The - public Hsv ToHsv(in Hsl color) + public static Hsv ToHsv(in Hsl color) { - var rgb = this.ToRgb(color); + Rgb rgb = ToRgb(color); return HsvAndRgbConverter.Convert(rgb); } @@ -262,7 +260,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The span to the source colors /// The span to the destination colors. - public void Convert(ReadOnlySpan source, Span destination) + public static void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); int count = source.Length; @@ -274,7 +272,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion { ref Hsl sp = ref Unsafe.Add(ref sourceRef, i); ref Hsv dp = ref Unsafe.Add(ref destRef, i); - dp = this.ToHsv(sp); + dp = ToHsv(sp); } } @@ -285,7 +283,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public Hsv ToHsv(in HunterLab color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToHsv(xyzColor); } @@ -316,9 +314,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The color to convert. /// The - public Hsv ToHsv(in LinearRgb color) + public static Hsv ToHsv(in LinearRgb color) { - var rgb = this.ToRgb(color); + Rgb rgb = ToRgb(color); return HsvAndRgbConverter.Convert(rgb); } @@ -328,7 +326,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The span to the source colors /// The span to the destination colors - public void Convert(ReadOnlySpan source, Span destination) + public static void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); int count = source.Length; @@ -340,7 +338,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion { ref LinearRgb sp = ref Unsafe.Add(ref sourceRef, i); ref Hsv dp = ref Unsafe.Add(ref destRef, i); - dp = this.ToHsv(sp); + dp = ToHsv(sp); } } @@ -351,7 +349,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public Hsv ToHsv(Lms color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToHsv(xyzColor); } @@ -382,14 +380,14 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The color to convert. /// The - public Hsv ToHsv(in Rgb color) => HsvAndRgbConverter.Convert(color); + public static Hsv ToHsv(in Rgb color) => HsvAndRgbConverter.Convert(color); /// /// Performs the bulk conversion from into /// /// The span to the source colors /// The span to the destination colors - public void Convert(ReadOnlySpan source, Span destination) + public static void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); int count = source.Length; @@ -401,7 +399,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion { ref Rgb sp = ref Unsafe.Add(ref sourceRef, i); ref Hsv dp = ref Unsafe.Add(ref destRef, i); - dp = this.ToHsv(sp); + dp = ToHsv(sp); } } @@ -412,7 +410,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public Hsv ToHsv(in YCbCr color) { - var rgb = this.ToRgb(color); + Rgb rgb = this.ToRgb(color); return HsvAndRgbConverter.Convert(rgb); } diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.HunterLab.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.HunterLab.cs index ad2fbd626..0e880ed59 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.HunterLab.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.HunterLab.cs @@ -336,7 +336,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public HunterLab ToHunterLab(in CieXyy color) { - var xyzColor = this.ToCieXyz(color); + var xyzColor = ToCieXyz(color); return this.ToHunterLab(xyzColor); } diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.LinearRgb.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.LinearRgb.cs index c317c8e8b..c5801b0b4 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.LinearRgb.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.LinearRgb.cs @@ -12,8 +12,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// public partial class ColorSpaceConverter { - private static readonly RgbToLinearRgbConverter RgbToLinearRgbConverter = new RgbToLinearRgbConverter(); - /// /// Performs the bulk conversion from into . /// @@ -145,7 +143,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The span to the source colors. /// The span to the destination colors. - public void Convert(ReadOnlySpan source, Span destination) + public static void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); int count = source.Length; @@ -157,7 +155,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion { ref Cmyk sp = ref Unsafe.Add(ref sourceRef, i); ref LinearRgb dp = ref Unsafe.Add(ref destRef, i); - dp = this.ToLinearRgb(sp); + dp = ToLinearRgb(sp); } } @@ -166,7 +164,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The span to the source colors. /// The span to the destination colors. - public void Convert(ReadOnlySpan source, Span destination) + public static void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); int count = source.Length; @@ -178,7 +176,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion { ref Hsl sp = ref Unsafe.Add(ref sourceRef, i); ref LinearRgb dp = ref Unsafe.Add(ref destRef, i); - dp = this.ToLinearRgb(sp); + dp = ToLinearRgb(sp); } } @@ -187,7 +185,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The span to the source colors. /// The span to the destination colors. - public void Convert(ReadOnlySpan source, Span destination) + public static void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); int count = source.Length; @@ -199,7 +197,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion { ref Hsv sp = ref Unsafe.Add(ref sourceRef, i); ref LinearRgb dp = ref Unsafe.Add(ref destRef, i); - dp = this.ToLinearRgb(sp); + dp = ToLinearRgb(sp); } } @@ -250,7 +248,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The span to the source colors /// The span to the destination colors - public void Convert(ReadOnlySpan source, Span destination) + public static void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); int count = source.Length; @@ -262,7 +260,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion { ref Rgb sp = ref Unsafe.Add(ref sourceRef, i); ref LinearRgb dp = ref Unsafe.Add(ref destRef, i); - dp = this.ToLinearRgb(sp); + dp = ToLinearRgb(sp); } } @@ -294,7 +292,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public LinearRgb ToLinearRgb(in CieLab color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToLinearRgb(xyzColor); } @@ -305,7 +303,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public LinearRgb ToLinearRgb(in CieLch color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToLinearRgb(xyzColor); } @@ -316,7 +314,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public LinearRgb ToLinearRgb(in CieLchuv color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToLinearRgb(xyzColor); } @@ -327,7 +325,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public LinearRgb ToLinearRgb(in CieLuv color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToLinearRgb(xyzColor); } @@ -338,7 +336,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public LinearRgb ToLinearRgb(in CieXyy color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = ToCieXyz(color); return this.ToLinearRgb(xyzColor); } @@ -361,10 +359,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The color to convert. /// The - public LinearRgb ToLinearRgb(in Cmyk color) + public static LinearRgb ToLinearRgb(in Cmyk color) { - var rgb = this.ToRgb(color); - return this.ToLinearRgb(rgb); + Rgb rgb = ToRgb(color); + return ToLinearRgb(rgb); } /// @@ -372,10 +370,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The color to convert. /// The - public LinearRgb ToLinearRgb(in Hsl color) + public static LinearRgb ToLinearRgb(in Hsl color) { - var rgb = this.ToRgb(color); - return this.ToLinearRgb(rgb); + Rgb rgb = ToRgb(color); + return ToLinearRgb(rgb); } /// @@ -383,10 +381,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The color to convert. /// The - public LinearRgb ToLinearRgb(in Hsv color) + public static LinearRgb ToLinearRgb(in Hsv color) { - var rgb = this.ToRgb(color); - return this.ToLinearRgb(rgb); + Rgb rgb = ToRgb(color); + return ToLinearRgb(rgb); } /// @@ -396,7 +394,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public LinearRgb ToLinearRgb(in HunterLab color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToLinearRgb(xyzColor); } @@ -407,7 +405,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public LinearRgb ToLinearRgb(in Lms color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToLinearRgb(xyzColor); } @@ -416,11 +414,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The color to convert. /// The - public LinearRgb ToLinearRgb(in Rgb color) - { - // Conversion - return RgbToLinearRgbConverter.Convert(color); - } + public static LinearRgb ToLinearRgb(in Rgb color) + => RgbToLinearRgbConverter.Convert(color); /// /// Converts a into a . @@ -429,8 +424,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public LinearRgb ToLinearRgb(in YCbCr color) { - var rgb = this.ToRgb(color); - return this.ToLinearRgb(rgb); + Rgb rgb = this.ToRgb(color); + return ToLinearRgb(rgb); } } } diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Lms.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Lms.cs index be36c46dc..dbaaa4dd0 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Lms.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Lms.cs @@ -336,7 +336,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public Lms ToLms(in CieXyy color) { - var xyzColor = this.ToCieXyz(color); + var xyzColor = ToCieXyz(color); return this.ToLms(xyzColor); } diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Rgb.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Rgb.cs index cfb6d3b76..461ce8c21 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Rgb.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Rgb.cs @@ -12,8 +12,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// public partial class ColorSpaceConverter { - private static readonly LinearRgbToRgbConverter LinearRgbToRgbConverter = new LinearRgbToRgbConverter(); - /// /// Performs the bulk conversion from into /// @@ -145,7 +143,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The span to the source colors /// The span to the destination colors - public void Convert(ReadOnlySpan source, Span destination) + public static void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); int count = source.Length; @@ -157,7 +155,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion { ref Cmyk sp = ref Unsafe.Add(ref sourceRef, i); ref Rgb dp = ref Unsafe.Add(ref destRef, i); - dp = this.ToRgb(sp); + dp = ToRgb(sp); } } @@ -166,7 +164,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The span to the source colors /// The span to the destination colors - public void Convert(ReadOnlySpan source, Span destination) + public static void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); int count = source.Length; @@ -178,7 +176,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion { ref Hsv sp = ref Unsafe.Add(ref sourceRef, i); ref Rgb dp = ref Unsafe.Add(ref destRef, i); - dp = this.ToRgb(sp); + dp = ToRgb(sp); } } @@ -187,7 +185,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The span to the source colors /// The span to the destination colors - public void Convert(ReadOnlySpan source, Span destination) + public static void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); int count = source.Length; @@ -199,7 +197,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion { ref Hsl sp = ref Unsafe.Add(ref sourceRef, i); ref Rgb dp = ref Unsafe.Add(ref destRef, i); - dp = this.ToRgb(sp); + dp = ToRgb(sp); } } @@ -229,7 +227,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The span to the source colors /// The span to the destination colors - public void Convert(ReadOnlySpan source, Span destination) + public static void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); int count = source.Length; @@ -241,7 +239,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion { ref LinearRgb sp = ref Unsafe.Add(ref sourceRef, i); ref Rgb dp = ref Unsafe.Add(ref destRef, i); - dp = this.ToRgb(sp); + dp = ToRgb(sp); } } @@ -294,7 +292,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public Rgb ToRgb(in CieLab color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToRgb(xyzColor); } @@ -305,7 +303,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public Rgb ToRgb(in CieLch color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToRgb(xyzColor); } @@ -316,7 +314,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public Rgb ToRgb(in CieLchuv color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToRgb(xyzColor); } @@ -327,7 +325,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public Rgb ToRgb(in CieLuv color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToRgb(xyzColor); } @@ -338,7 +336,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public Rgb ToRgb(in CieXyy color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = ToCieXyz(color); return this.ToRgb(xyzColor); } @@ -350,10 +348,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion public Rgb ToRgb(in CieXyz color) { // Conversion - var linear = this.ToLinearRgb(color); + LinearRgb linear = this.ToLinearRgb(color); // Compand - return this.ToRgb(linear); + return ToRgb(linear); } /// @@ -361,33 +359,21 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The color to convert. /// The - public Rgb ToRgb(in Cmyk color) - { - // Conversion - return CmykAndRgbConverter.Convert(color); - } + public static Rgb ToRgb(in Cmyk color) => CmykAndRgbConverter.Convert(color); /// /// Converts a into a /// /// The color to convert. /// The - public Rgb ToRgb(in Hsv color) - { - // Conversion - return HsvAndRgbConverter.Convert(color); - } + public static Rgb ToRgb(in Hsv color) => HsvAndRgbConverter.Convert(color); /// /// Converts a into a /// /// The color to convert. /// The - public Rgb ToRgb(in Hsl color) - { - // Conversion - return HslAndRgbConverter.Convert(color); - } + public static Rgb ToRgb(in Hsl color) => HslAndRgbConverter.Convert(color); /// /// Converts a into a @@ -396,7 +382,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public Rgb ToRgb(in HunterLab color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToRgb(xyzColor); } @@ -405,11 +391,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The color to convert. /// The - public Rgb ToRgb(in LinearRgb color) - { - // Conversion - return LinearRgbToRgbConverter.Convert(color); - } + public static Rgb ToRgb(in LinearRgb color) => LinearRgbToRgbConverter.Convert(color); /// /// Converts a into a @@ -418,7 +400,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public Rgb ToRgb(in Lms color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToRgb(xyzColor); } diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.YCbCr.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.YCbCr.cs index db6dc2133..48bb8ebd6 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.YCbCr.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.YCbCr.cs @@ -12,8 +12,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// public partial class ColorSpaceConverter { - private static readonly YCbCrAndRgbConverter YCbCrAndRgbConverter = new YCbCrAndRgbConverter(); - /// /// Performs the bulk conversion from into . /// @@ -124,7 +122,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The span to the source colors /// The span to the destination colors - public void Convert(ReadOnlySpan source, Span destination) + public static void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); int count = source.Length; @@ -136,7 +134,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion { ref Cmyk sp = ref Unsafe.Add(ref sourceRef, i); ref YCbCr dp = ref Unsafe.Add(ref destRef, i); - dp = this.ToYCbCr(sp); + dp = ToYCbCr(sp); } } @@ -145,7 +143,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The span to the source colors /// The span to the destination colors - public void Convert(ReadOnlySpan source, Span destination) + public static void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); int count = source.Length; @@ -157,7 +155,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion { ref Hsl sp = ref Unsafe.Add(ref sourceRef, i); ref YCbCr dp = ref Unsafe.Add(ref destRef, i); - dp = this.ToYCbCr(sp); + dp = ToYCbCr(sp); } } @@ -166,7 +164,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The span to the source colors /// The span to the destination colors - public void Convert(ReadOnlySpan source, Span destination) + public static void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); int count = source.Length; @@ -178,7 +176,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion { ref Hsv sp = ref Unsafe.Add(ref sourceRef, i); ref YCbCr dp = ref Unsafe.Add(ref destRef, i); - dp = this.ToYCbCr(sp); + dp = ToYCbCr(sp); } } @@ -208,7 +206,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The span to the source colors /// The span to the destination colors - public void Convert(ReadOnlySpan source, Span destination) + public static void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); int count = source.Length; @@ -220,7 +218,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion { ref LinearRgb sp = ref Unsafe.Add(ref sourceRef, i); ref YCbCr dp = ref Unsafe.Add(ref destRef, i); - dp = this.ToYCbCr(sp); + dp = ToYCbCr(sp); } } @@ -250,7 +248,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The span to the source colors /// The span to the destination colors - public void Convert(ReadOnlySpan source, Span destination) + public static void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); int count = source.Length; @@ -262,7 +260,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion { ref Rgb sp = ref Unsafe.Add(ref sourceRef, i); ref YCbCr dp = ref Unsafe.Add(ref destRef, i); - dp = this.ToYCbCr(sp); + dp = ToYCbCr(sp); } } @@ -273,7 +271,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public YCbCr ToYCbCr(in CieLab color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToYCbCr(xyzColor); } @@ -285,7 +283,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public YCbCr ToYCbCr(in CieLch color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToYCbCr(xyzColor); } @@ -297,7 +295,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public YCbCr ToYCbCr(in CieLuv color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToYCbCr(xyzColor); } @@ -309,7 +307,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public YCbCr ToYCbCr(in CieXyy color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = ToCieXyz(color); return this.ToYCbCr(xyzColor); } @@ -321,7 +319,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public YCbCr ToYCbCr(in CieXyz color) { - var rgb = this.ToRgb(color); + Rgb rgb = this.ToRgb(color); return YCbCrAndRgbConverter.Convert(rgb); } @@ -331,9 +329,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The color to convert. /// The - public YCbCr ToYCbCr(in Cmyk color) + public static YCbCr ToYCbCr(in Cmyk color) { - var rgb = this.ToRgb(color); + Rgb rgb = ToRgb(color); return YCbCrAndRgbConverter.Convert(rgb); } @@ -343,9 +341,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The color to convert. /// The - public YCbCr ToYCbCr(in Hsl color) + public static YCbCr ToYCbCr(in Hsl color) { - var rgb = this.ToRgb(color); + Rgb rgb = ToRgb(color); return YCbCrAndRgbConverter.Convert(rgb); } @@ -355,9 +353,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The color to convert. /// The - public YCbCr ToYCbCr(in Hsv color) + public static YCbCr ToYCbCr(in Hsv color) { - var rgb = this.ToRgb(color); + Rgb rgb = ToRgb(color); return YCbCrAndRgbConverter.Convert(rgb); } @@ -369,7 +367,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public YCbCr ToYCbCr(in HunterLab color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToYCbCr(xyzColor); } @@ -379,9 +377,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The color to convert. /// The - public YCbCr ToYCbCr(in LinearRgb color) + public static YCbCr ToYCbCr(in LinearRgb color) { - var rgb = this.ToRgb(color); + Rgb rgb = ToRgb(color); return YCbCrAndRgbConverter.Convert(rgb); } @@ -393,7 +391,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public YCbCr ToYCbCr(in Lms color) { - var xyzColor = this.ToCieXyz(color); + CieXyz xyzColor = this.ToCieXyz(color); return this.ToYCbCr(xyzColor); } @@ -403,6 +401,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The color to convert. /// The - public YCbCr ToYCbCr(in Rgb color) => YCbCrAndRgbConverter.Convert(color); + public static YCbCr ToYCbCr(in Rgb color) => YCbCrAndRgbConverter.Convert(color); } } diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyChromaticityCoordinates.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyChromaticityCoordinates.cs index 728d7cd22..bb021f610 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyChromaticityCoordinates.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyChromaticityCoordinates.cs @@ -12,13 +12,25 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// public readonly struct CieXyChromaticityCoordinates : IEquatable { + /// + /// Initializes a new instance of the struct. + /// + /// Chromaticity coordinate x (usually from 0 to 1) + /// Chromaticity coordinate y (usually from 0 to 1) + [MethodImpl(InliningOptions.ShortMethod)] + public CieXyChromaticityCoordinates(float x, float y) + { + this.X = x; + this.Y = y; + } + /// /// Gets the chromaticity X-coordinate. /// /// /// Ranges usually from 0 to 1. /// - public readonly float X; + public readonly float X { get; } /// /// Gets the chromaticity Y-coordinate @@ -26,19 +38,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// Ranges usually from 0 to 1. /// - public readonly float Y; - - /// - /// Initializes a new instance of the struct. - /// - /// Chromaticity coordinate x (usually from 0 to 1) - /// Chromaticity coordinate y (usually from 0 to 1) - [MethodImpl(InliningOptions.ShortMethod)] - public CieXyChromaticityCoordinates(float x, float y) - { - this.X = x; - this.Y = y; - } + public readonly float Y { get; } /// /// Compares two objects for equality. @@ -49,7 +49,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// True if the current left is equal to the parameter; otherwise, false. /// [MethodImpl(InliningOptions.ShortMethod)] - public static bool operator ==(CieXyChromaticityCoordinates left, CieXyChromaticityCoordinates right) => left.Equals(right); + public static bool operator ==(CieXyChromaticityCoordinates left, CieXyChromaticityCoordinates right) + => left.Equals(right); /// /// Compares two objects for inequality @@ -60,20 +61,25 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// True if the current left is unequal to the parameter; otherwise, false. /// [MethodImpl(InliningOptions.ShortMethod)] - public static bool operator !=(CieXyChromaticityCoordinates left, CieXyChromaticityCoordinates right) => !left.Equals(right); + public static bool operator !=(CieXyChromaticityCoordinates left, CieXyChromaticityCoordinates right) + => !left.Equals(right); /// [MethodImpl(InliningOptions.ShortMethod)] - public override int GetHashCode() => HashCode.Combine(this.X, this.Y); + public override int GetHashCode() + => HashCode.Combine(this.X, this.Y); /// - public override string ToString() => FormattableString.Invariant($"CieXyChromaticityCoordinates({this.X:#0.##}, {this.Y:#0.##})"); + public override string ToString() + => FormattableString.Invariant($"CieXyChromaticityCoordinates({this.X:#0.##}, {this.Y:#0.##})"); /// - public override bool Equals(object obj) => obj is CieXyChromaticityCoordinates other && this.Equals(other); + public override bool Equals(object obj) + => obj is CieXyChromaticityCoordinates other && this.Equals(other); /// [MethodImpl(InliningOptions.ShortMethod)] - public bool Equals(CieXyChromaticityCoordinates other) => this.X.Equals(other.X) && this.Y.Equals(other.Y); + public bool Equals(CieXyChromaticityCoordinates other) + => this.X.Equals(other.X) && this.Y.Equals(other.Y); } } diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CIeLchToCieLabConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CIeLchToCieLabConverter.cs index 6485da076..9da7826c4 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CIeLchToCieLabConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CIeLchToCieLabConverter.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// Converts from to . /// - internal sealed class CieLchToCieLabConverter + internal static class CieLchToCieLabConverter { /// /// Performs the conversion from the input to an instance of type. @@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The input color instance. /// The converted result [MethodImpl(InliningOptions.ShortMethod)] - public CieLab Convert(in CieLch input) + public static CieLab Convert(in CieLch input) { // Conversion algorithm described here: // https://en.wikipedia.org/wiki/Lab_color_space#Cylindrical_representation:_CIELCh_or_CIEHLC diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLabToCieLchConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLabToCieLchConverter.cs index 0aefeda85..da7d3f509 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLabToCieLchConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLabToCieLchConverter.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// Converts from to . /// - internal sealed class CieLabToCieLchConverter + internal static class CieLabToCieLchConverter { /// /// Performs the conversion from the input to an instance of type. @@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The input color instance. /// The converted result [MethodImpl(InliningOptions.ShortMethod)] - public CieLch Convert(in CieLab input) + public static CieLch Convert(in CieLab input) { // Conversion algorithm described here: // https://en.wikipedia.org/wiki/Lab_color_space#Cylindrical_representation:_CIELCh_or_CIEHLC diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLabToCieXyzConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLabToCieXyzConverter.cs index 3634ebe99..e852e61be 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLabToCieXyzConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLabToCieXyzConverter.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// Converts from to . /// - internal sealed class CieLabToCieXyzConverter + internal static class CieLabToCieXyzConverter { /// /// Performs the conversion from the input to an instance of type. @@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The input color instance. /// The converted result [MethodImpl(InliningOptions.ShortMethod)] - public CieXyz Convert(in CieLab input) + public static CieXyz Convert(in CieLab input) { // Conversion algorithm described here: http://www.brucelindbloom.com/index.html?Eqn_Lab_to_XYZ.html float l = input.L, a = input.A, b = input.B; @@ -32,10 +32,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion float yr = l > CieConstants.Kappa * CieConstants.Epsilon ? Numerics.Pow3((l + 16F) / 116F) : l / CieConstants.Kappa; float zr = fz3 > CieConstants.Epsilon ? fz3 : ((116F * fz) - 16F) / CieConstants.Kappa; - var wxyz = new Vector3(input.WhitePoint.X, input.WhitePoint.Y, input.WhitePoint.Z); + Vector3 wxyz = new(input.WhitePoint.X, input.WhitePoint.Y, input.WhitePoint.Z); // Avoids XYZ coordinates out range (restricted by 0 and XYZ reference white) - var xyzr = Vector3.Clamp(new Vector3(xr, yr, zr), Vector3.Zero, Vector3.One); + Vector3 xyzr = Vector3.Clamp(new Vector3(xr, yr, zr), Vector3.Zero, Vector3.One); Vector3 xyz = xyzr * wxyz; return new CieXyz(xyz); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLchuvToCieLuvConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLchuvToCieLuvConverter.cs index fc064a6de..c2f2e5d29 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLchuvToCieLuvConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLchuvToCieLuvConverter.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// Converts from to . /// - internal sealed class CieLchuvToCieLuvConverter + internal static class CieLchuvToCieLuvConverter { /// /// Performs the conversion from the input to an instance of type. @@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The input color instance. /// The converted result [MethodImpl(InliningOptions.ShortMethod)] - public CieLuv Convert(in CieLchuv input) + public static CieLuv Convert(in CieLchuv input) { // Conversion algorithm described here: // https://en.wikipedia.org/wiki/CIELUV#Cylindrical_representation_.28CIELCH.29 diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLuvToCieLchuvConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLuvToCieLchuvConverter.cs index d69fb4697..f894d748b 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLuvToCieLchuvConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLuvToCieLchuvConverter.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// Converts from to . /// - internal sealed class CieLuvToCieLchuvConverter + internal static class CieLuvToCieLchuvConverter { /// /// Performs the conversion from the input to an instance of type. @@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The input color instance. /// The converted result [MethodImpl(InliningOptions.ShortMethod)] - public CieLchuv Convert(in CieLuv input) + public static CieLchuv Convert(in CieLuv input) { // Conversion algorithm described here: // https://en.wikipedia.org/wiki/CIELUV#Cylindrical_representation_.28CIELCH.29 diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLuvToCieXyzConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLuvToCieXyzConverter.cs index 0b4a4a9b8..aa12e511e 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLuvToCieXyzConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLuvToCieXyzConverter.cs @@ -8,14 +8,14 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// Converts from to . /// - internal sealed class CieLuvToCieXyzConverter + internal static class CieLuvToCieXyzConverter { /// /// Performs the conversion from the input to an instance of type. /// /// The input color instance. /// The converted result - public CieXyz Convert(in CieLuv input) + public static CieXyz Convert(in CieLuv input) { // Conversion algorithm described here: http://www.brucelindbloom.com/index.html?Eqn_Luv_to_XYZ.html float l = input.L, u = input.U, v = input.V; diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndCieXyyConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndCieXyyConverter.cs index 5db91eb75..619d04d0c 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndCieXyyConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndCieXyyConverter.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// Color converter between CIE XYZ and CIE xyY. /// for formulas. /// - internal sealed class CieXyzAndCieXyyConverter + internal static class CieXyzAndCieXyyConverter { /// /// Performs the conversion from the input to an instance of type. @@ -18,7 +18,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The input color instance. /// The converted result [MethodImpl(InliningOptions.ShortMethod)] - public CieXyy Convert(in CieXyz input) + public static CieXyy Convert(in CieXyz input) { float x = input.X / (input.X + input.Y + input.Z); float y = input.Y / (input.X + input.Y + input.Z); @@ -37,7 +37,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The input color instance. /// The converted result [MethodImpl(InliningOptions.ShortMethod)] - public CieXyz Convert(in CieXyy input) + public static CieXyz Convert(in CieXyy input) { if (MathF.Abs(input.Y) < Constants.Epsilon) { diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndLmsConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndLmsConverter.cs index 533d94465..ac9f1f636 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndLmsConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndLmsConverter.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System.Numerics; @@ -49,7 +49,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion [MethodImpl(InliningOptions.ShortMethod)] public Lms Convert(in CieXyz input) { - var vector = Vector3.Transform(input.ToVector3(), this.transformationMatrix); + Vector3 vector = Vector3.Transform(input.ToVector3(), this.transformationMatrix); return new Lms(vector); } @@ -62,7 +62,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion [MethodImpl(InliningOptions.ShortMethod)] public CieXyz Convert(in Lms input) { - var vector = Vector3.Transform(input.ToVector3(), this.inverseTransformationMatrix); + Vector3 vector = Vector3.Transform(input.ToVector3(), this.inverseTransformationMatrix); return new CieXyz(vector); } diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CmykAndRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CmykAndRgbConverter.cs index 20a03fb41..31b11575b 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CmykAndRgbConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CmykAndRgbConverter.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// Color converter between and . /// - internal sealed class CmykAndRgbConverter + internal static class CmykAndRgbConverter { /// /// Performs the conversion from the input to an instance of type. @@ -18,7 +18,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The input color instance. /// The converted result [MethodImpl(InliningOptions.ShortMethod)] - public Rgb Convert(in Cmyk input) + public static Rgb Convert(in Cmyk input) { Vector3 rgb = (Vector3.One - new Vector3(input.C, input.M, input.Y)) * (Vector3.One - new Vector3(input.K)); return new Rgb(rgb); @@ -30,13 +30,13 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The input color instance. /// The converted result. [MethodImpl(InliningOptions.ShortMethod)] - public Cmyk Convert(in Rgb input) + public static Cmyk Convert(in Rgb input) { // To CMY Vector3 cmy = Vector3.One - input.ToVector3(); // To CMYK - var k = new Vector3(MathF.Min(cmy.X, MathF.Min(cmy.Y, cmy.Z))); + Vector3 k = new(MathF.Min(cmy.X, MathF.Min(cmy.Y, cmy.Z))); if (MathF.Abs(k.X - 1F) < Constants.Epsilon) { diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HslAndRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HslAndRgbConverter.cs index c5a599e9e..70cc064a8 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HslAndRgbConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HslAndRgbConverter.cs @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// Color converter between HSL and Rgb /// See for formulas. /// - internal sealed class HslAndRgbConverter + internal static class HslAndRgbConverter { /// /// Performs the conversion from the input to an instance of type. @@ -18,7 +18,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The input color instance. /// The converted result [MethodImpl(InliningOptions.ShortMethod)] - public Rgb Convert(in Hsl input) + public static Rgb Convert(in Hsl input) { float rangedH = input.H / 360F; float r = 0; @@ -53,7 +53,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The input color instance. /// The converted result [MethodImpl(InliningOptions.ShortMethod)] - public Hsl Convert(in Rgb input) + public static Hsl Convert(in Rgb input) { float r = input.R; float g = input.G; diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HsvAndRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HsvAndRgbConverter.cs index de187ee59..9b01c8088 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HsvAndRgbConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HsvAndRgbConverter.cs @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// Color converter between HSV and Rgb /// See for formulas. /// - internal sealed class HsvAndRgbConverter + internal static class HsvAndRgbConverter { /// /// Performs the conversion from the input to an instance of type. @@ -18,7 +18,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The input color instance. /// The converted result [MethodImpl(InliningOptions.ShortMethod)] - public Rgb Convert(in Hsv input) + public static Rgb Convert(in Hsv input) { float s = input.S; float v = input.V; @@ -85,7 +85,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The input color instance. /// The converted result [MethodImpl(InliningOptions.ShortMethod)] - public Hsv Convert(in Rgb input) + public static Hsv Convert(in Rgb input) { float r = input.R; float g = input.G; diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HunterLabToCieXyzConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HunterLabToCieXyzConverter.cs index a804d1d5f..ead2f37d8 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HunterLabToCieXyzConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HunterLabToCieXyzConverter.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// Color converter between and /// - internal sealed class HunterLabToCieXyzConverter : CieXyzAndHunterLabConverterBase + internal class HunterLabToCieXyzConverter : CieXyzAndHunterLabConverterBase { /// /// Performs the conversion from the input to an instance of type. @@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The input color instance. /// The converted result [MethodImpl(InliningOptions.ShortMethod)] - public CieXyz Convert(in HunterLab input) + public static CieXyz Convert(in HunterLab input) { // Conversion algorithm described here: http://en.wikipedia.org/wiki/Lab_color_space#Hunter_Lab float l = input.L, a = input.A, b = input.B; diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbAndCieXyzConverterBase.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbAndCieXyzConverterBase.cs index 8a406cb33..ac0ab7311 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbAndCieXyzConverterBase.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbAndCieXyzConverterBase.cs @@ -28,25 +28,22 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion float yb = chromaticity.B.Y; float mXr = xr / yr; - const float Yr = 1; float mZr = (1 - xr - yr) / yr; float mXg = xg / yg; - const float Yg = 1; float mZg = (1 - xg - yg) / yg; float mXb = xb / yb; - const float Yb = 1; float mZb = (1 - xb - yb) / yb; - var xyzMatrix = new Matrix4x4 + Matrix4x4 xyzMatrix = new() { M11 = mXr, M21 = mXg, M31 = mXb, - M12 = Yr, - M22 = Yg, - M32 = Yb, + M12 = 1F, + M22 = 1F, + M32 = 1F, M13 = mZr, M23 = mZg, M33 = mZb, @@ -55,7 +52,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion Matrix4x4.Invert(xyzMatrix, out Matrix4x4 inverseXyzMatrix); - var vector = Vector3.Transform(workingSpace.WhitePoint.ToVector3(), inverseXyzMatrix); + Vector3 vector = Vector3.Transform(workingSpace.WhitePoint.ToVector3(), inverseXyzMatrix); // Use transposed Rows/Columns // TODO: Is there a built in method for this multiplication? @@ -64,9 +61,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion M11 = vector.X * mXr, M21 = vector.Y * mXg, M31 = vector.Z * mXb, - M12 = vector.X * Yr, - M22 = vector.Y * Yg, - M32 = vector.Z * Yb, + M12 = vector.X * 1, + M22 = vector.Y * 1, + M32 = vector.Z * 1, M13 = vector.X * mZr, M23 = vector.Y * mZg, M33 = vector.Z * mZb, diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToCieXyzConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToCieXyzConverter.cs index f124fdd80..5f0755969 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToCieXyzConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToCieXyzConverter.cs @@ -46,7 +46,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion { DebugGuard.IsTrue(input.WorkingSpace.Equals(this.SourceWorkingSpace), nameof(input.WorkingSpace), "Input and source working spaces must be equal."); - var vector = Vector3.Transform(input.ToVector3(), this.conversionMatrix); + Vector3 vector = Vector3.Transform(input.ToVector3(), this.conversionMatrix); return new CieXyz(vector); } } diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToRgbConverter.cs index ea5ef2bc1..d8cfa7c56 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToRgbConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToRgbConverter.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// Color converter between and . /// - internal sealed class LinearRgbToRgbConverter + internal static class LinearRgbToRgbConverter { /// /// Performs the conversion from the input to an instance of type. @@ -16,13 +16,11 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The input color instance. /// The converted result. [MethodImpl(InliningOptions.ShortMethod)] - public Rgb Convert(in LinearRgb input) - { - return new Rgb( + public static Rgb Convert(in LinearRgb input) => + new( r: input.WorkingSpace.Compress(input.R), g: input.WorkingSpace.Compress(input.G), b: input.WorkingSpace.Compress(input.B), workingSpace: input.WorkingSpace); - } } } diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/RgbToLinearRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/RgbToLinearRgbConverter.cs index 5ce09802c..08a684baa 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/RgbToLinearRgbConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/RgbToLinearRgbConverter.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// Color converter between Rgb and LinearRgb. /// - internal class RgbToLinearRgbConverter + internal static class RgbToLinearRgbConverter { /// /// Performs the conversion from the input to an instance of type. @@ -16,13 +16,11 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The input color instance. /// The converted result. [MethodImpl(InliningOptions.ShortMethod)] - public LinearRgb Convert(in Rgb input) - { - return new LinearRgb( + public static LinearRgb Convert(in Rgb input) + => new( r: input.WorkingSpace.Expand(input.R), g: input.WorkingSpace.Expand(input.G), b: input.WorkingSpace.Expand(input.B), workingSpace: input.WorkingSpace); - } } } diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/YCbCrAndRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/YCbCrAndRgbConverter.cs index 727c89dd7..ac4d85738 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/YCbCrAndRgbConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/YCbCrAndRgbConverter.cs @@ -11,9 +11,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// Color converter between and /// See for formulas. /// - internal sealed class YCbCrAndRgbConverter + internal static class YCbCrAndRgbConverter { - private static readonly Vector3 MaxBytes = new Vector3(255F); + private static readonly Vector3 MaxBytes = new(255F); /// /// Performs the conversion from the input to an instance of type. @@ -21,7 +21,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The input color instance. /// The converted result. [MethodImpl(InliningOptions.ShortMethod)] - public Rgb Convert(in YCbCr input) + public static Rgb Convert(in YCbCr input) { float y = input.Y; float cb = input.Cb - 128F; @@ -40,7 +40,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The input color instance. /// The converted result. [MethodImpl(InliningOptions.ShortMethod)] - public YCbCr Convert(in Rgb input) + public static YCbCr Convert(in Rgb input) { Vector3 rgb = input.ToVector3() * MaxBytes; float r = rgb.X; diff --git a/src/ImageSharp/ColorSpaces/Hsl.cs b/src/ImageSharp/ColorSpaces/Hsl.cs index 98f9bdb7c..01ea512a6 100644 --- a/src/ImageSharp/ColorSpaces/Hsl.cs +++ b/src/ImageSharp/ColorSpaces/Hsl.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -13,25 +13,7 @@ namespace SixLabors.ImageSharp.ColorSpaces public readonly struct Hsl : IEquatable { private static readonly Vector3 Min = Vector3.Zero; - private static readonly Vector3 Max = new Vector3(360, 1, 1); - - /// - /// Gets the hue component. - /// A value ranging between 0 and 360. - /// - public readonly float H; - - /// - /// Gets the saturation component. - /// A value ranging between 0 and 1. - /// - public readonly float S; - - /// - /// Gets the lightness component. - /// A value ranging between 0 and 1. - /// - public readonly float L; + private static readonly Vector3 Max = new(360, 1, 1); /// /// Initializes a new instance of the struct. @@ -58,6 +40,24 @@ namespace SixLabors.ImageSharp.ColorSpaces this.L = vector.Z; } + /// + /// Gets the hue component. + /// A value ranging between 0 and 360. + /// + public readonly float H { get; } + + /// + /// Gets the saturation component. + /// A value ranging between 0 and 1. + /// + public readonly float S { get; } + + /// + /// Gets the lightness component. + /// A value ranging between 0 and 1. + /// + public readonly float L { get; } + /// /// Compares two objects for equality. /// @@ -95,10 +95,8 @@ namespace SixLabors.ImageSharp.ColorSpaces /// [MethodImpl(InliningOptions.ShortMethod)] public bool Equals(Hsl other) - { - return this.H.Equals(other.H) - && this.S.Equals(other.S) - && this.L.Equals(other.L); - } + => this.H.Equals(other.H) + && this.S.Equals(other.S) + && this.L.Equals(other.L); } } diff --git a/src/ImageSharp/ColorSpaces/Hsv.cs b/src/ImageSharp/ColorSpaces/Hsv.cs index a44aebbb1..284ef4e53 100644 --- a/src/ImageSharp/ColorSpaces/Hsv.cs +++ b/src/ImageSharp/ColorSpaces/Hsv.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -13,25 +13,7 @@ namespace SixLabors.ImageSharp.ColorSpaces public readonly struct Hsv : IEquatable { private static readonly Vector3 Min = Vector3.Zero; - private static readonly Vector3 Max = new Vector3(360, 1, 1); - - /// - /// Gets the hue component. - /// A value ranging between 0 and 360. - /// - public readonly float H; - - /// - /// Gets the saturation component. - /// A value ranging between 0 and 1. - /// - public readonly float S; - - /// - /// Gets the value (brightness) component. - /// A value ranging between 0 and 1. - /// - public readonly float V; + private static readonly Vector3 Max = new(360, 1, 1); /// /// Initializes a new instance of the struct. @@ -58,6 +40,24 @@ namespace SixLabors.ImageSharp.ColorSpaces this.V = vector.Z; } + /// + /// Gets the hue component. + /// A value ranging between 0 and 360. + /// + public readonly float H { get; } + + /// + /// Gets the saturation component. + /// A value ranging between 0 and 1. + /// + public readonly float S { get; } + + /// + /// Gets the value (brightness) component. + /// A value ranging between 0 and 1. + /// + public readonly float V { get; } + /// /// Compares two objects for equality. /// @@ -93,10 +93,8 @@ namespace SixLabors.ImageSharp.ColorSpaces /// [MethodImpl(InliningOptions.ShortMethod)] public bool Equals(Hsv other) - { - return this.H.Equals(other.H) - && this.S.Equals(other.S) - && this.V.Equals(other.V); - } + => this.H.Equals(other.H) + && this.S.Equals(other.S) + && this.V.Equals(other.V); } } diff --git a/src/ImageSharp/ColorSpaces/HunterLab.cs b/src/ImageSharp/ColorSpaces/HunterLab.cs index c3d808c6c..4b5ea842d 100644 --- a/src/ImageSharp/ColorSpaces/HunterLab.cs +++ b/src/ImageSharp/ColorSpaces/HunterLab.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -19,29 +19,6 @@ namespace SixLabors.ImageSharp.ColorSpaces /// public static readonly CieXyz DefaultWhitePoint = Illuminants.C; - /// - /// Gets the lightness dimension. - /// A value usually ranging between 0 (black), 100 (diffuse white) or higher (specular white). - /// - public readonly float L; - - /// - /// Gets the a color component. - /// A value usually ranging from -100 to 100. Negative is green, positive magenta. - /// - public readonly float A; - - /// - /// Gets the b color component. - /// A value usually ranging from -100 to 100. Negative is blue, positive is yellow - /// - public readonly float B; - - /// - /// Gets the reference white point of this color. - /// - public readonly CieXyz WhitePoint; - /// /// Initializes a new instance of the struct. /// @@ -94,6 +71,29 @@ namespace SixLabors.ImageSharp.ColorSpaces this.WhitePoint = whitePoint; } + /// + /// Gets the lightness dimension. + /// A value usually ranging between 0 (black), 100 (diffuse white) or higher (specular white). + /// + public readonly float L { get; } + + /// + /// Gets the a color component. + /// A value usually ranging from -100 to 100. Negative is green, positive magenta. + /// + public readonly float A { get; } + + /// + /// Gets the b color component. + /// A value usually ranging from -100 to 100. Negative is blue, positive is yellow + /// + public readonly float B { get; } + + /// + /// Gets the reference white point of this color. + /// + public readonly CieXyz WhitePoint { get; } + /// /// Compares two objects for equality. /// @@ -128,11 +128,9 @@ namespace SixLabors.ImageSharp.ColorSpaces /// [MethodImpl(InliningOptions.ShortMethod)] public bool Equals(HunterLab other) - { - return this.L.Equals(other.L) - && this.A.Equals(other.A) - && this.B.Equals(other.B) - && this.WhitePoint.Equals(other.WhitePoint); - } + => this.L.Equals(other.L) + && this.A.Equals(other.A) + && this.B.Equals(other.B) + && this.WhitePoint.Equals(other.WhitePoint); } } diff --git a/src/ImageSharp/ColorSpaces/LinearRgb.cs b/src/ImageSharp/ColorSpaces/LinearRgb.cs index 5dffea678..abf2c6e81 100644 --- a/src/ImageSharp/ColorSpaces/LinearRgb.cs +++ b/src/ImageSharp/ColorSpaces/LinearRgb.cs @@ -21,29 +21,6 @@ namespace SixLabors.ImageSharp.ColorSpaces /// public static readonly RgbWorkingSpace DefaultWorkingSpace = RgbWorkingSpaces.SRgb; - /// - /// Gets the red component. - /// A value usually ranging between 0 and 1. - /// - public readonly float R; - - /// - /// Gets the green component. - /// A value usually ranging between 0 and 1. - /// - public readonly float G; - - /// - /// Gets the blue component. - /// A value usually ranging between 0 and 1. - /// - public readonly float B; - - /// - /// Gets the LinearRgb color space - /// - public readonly RgbWorkingSpace WorkingSpace; - /// /// Initializes a new instance of the struct. /// @@ -95,6 +72,29 @@ namespace SixLabors.ImageSharp.ColorSpaces this.WorkingSpace = workingSpace; } + /// + /// Gets the red component. + /// A value usually ranging between 0 and 1. + /// + public readonly float R { get; } + + /// + /// Gets the green component. + /// A value usually ranging between 0 and 1. + /// + public readonly float G { get; } + + /// + /// Gets the blue component. + /// A value usually ranging between 0 and 1. + /// + public readonly float B { get; } + + /// + /// Gets the LinearRgb color space + /// + public readonly RgbWorkingSpace WorkingSpace { get; } + /// /// Compares two objects for equality. /// @@ -122,7 +122,7 @@ namespace SixLabors.ImageSharp.ColorSpaces /// /// The . [MethodImpl(InliningOptions.ShortMethod)] - public Vector3 ToVector3() => new Vector3(this.R, this.G, this.B); + public Vector3 ToVector3() => new(this.R, this.G, this.B); /// [MethodImpl(InliningOptions.ShortMethod)] @@ -137,10 +137,8 @@ namespace SixLabors.ImageSharp.ColorSpaces /// [MethodImpl(InliningOptions.ShortMethod)] public bool Equals(LinearRgb other) - { - return this.R.Equals(other.R) - && this.G.Equals(other.G) - && this.B.Equals(other.B); - } + => this.R.Equals(other.R) + && this.G.Equals(other.G) + && this.B.Equals(other.B); } } diff --git a/src/ImageSharp/ColorSpaces/Lms.cs b/src/ImageSharp/ColorSpaces/Lms.cs index 7ca8c3cf0..ee7711890 100644 --- a/src/ImageSharp/ColorSpaces/Lms.cs +++ b/src/ImageSharp/ColorSpaces/Lms.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -14,24 +14,6 @@ namespace SixLabors.ImageSharp.ColorSpaces /// public readonly struct Lms : IEquatable { - /// - /// Gets the L long component. - /// A value usually ranging between -1 and 1. - /// - public readonly float L; - - /// - /// Gets the M medium component. - /// A value usually ranging between -1 and 1. - /// - public readonly float M; - - /// - /// Gets the S short component. - /// A value usually ranging between -1 and 1. - /// - public readonly float S; - /// /// Initializes a new instance of the struct. /// @@ -57,6 +39,24 @@ namespace SixLabors.ImageSharp.ColorSpaces this.S = vector.Z; } + /// + /// Gets the L long component. + /// A value usually ranging between -1 and 1. + /// + public readonly float L { get; } + + /// + /// Gets the M medium component. + /// A value usually ranging between -1 and 1. + /// + public readonly float M { get; } + + /// + /// Gets the S short component. + /// A value usually ranging between -1 and 1. + /// + public readonly float S { get; } + /// /// Compares two objects for equality. /// @@ -84,7 +84,7 @@ namespace SixLabors.ImageSharp.ColorSpaces /// /// The . [MethodImpl(InliningOptions.ShortMethod)] - public Vector3 ToVector3() => new Vector3(this.L, this.M, this.S); + public Vector3 ToVector3() => new(this.L, this.M, this.S); /// public override int GetHashCode() => HashCode.Combine(this.L, this.M, this.S); @@ -98,10 +98,8 @@ namespace SixLabors.ImageSharp.ColorSpaces /// [MethodImpl(InliningOptions.ShortMethod)] public bool Equals(Lms other) - { - return this.L.Equals(other.L) - && this.M.Equals(other.M) - && this.S.Equals(other.S); - } + => this.L.Equals(other.L) + && this.M.Equals(other.M) + && this.S.Equals(other.S); } } diff --git a/src/ImageSharp/ColorSpaces/Rgb.cs b/src/ImageSharp/ColorSpaces/Rgb.cs index 4902d98fd..76d55d04d 100644 --- a/src/ImageSharp/ColorSpaces/Rgb.cs +++ b/src/ImageSharp/ColorSpaces/Rgb.cs @@ -22,29 +22,6 @@ namespace SixLabors.ImageSharp.ColorSpaces private static readonly Vector3 Min = Vector3.Zero; private static readonly Vector3 Max = Vector3.One; - /// - /// Gets the red component. - /// A value usually ranging between 0 and 1. - /// - public readonly float R; - - /// - /// Gets the green component. - /// A value usually ranging between 0 and 1. - /// - public readonly float G; - - /// - /// Gets the blue component. - /// A value usually ranging between 0 and 1. - /// - public readonly float B; - - /// - /// Gets the Rgb color space - /// - public readonly RgbWorkingSpace WorkingSpace; - /// /// Initializes a new instance of the struct. /// @@ -95,6 +72,29 @@ namespace SixLabors.ImageSharp.ColorSpaces this.WorkingSpace = workingSpace; } + /// + /// Gets the red component. + /// A value usually ranging between 0 and 1. + /// + public readonly float R { get; } + + /// + /// Gets the green component. + /// A value usually ranging between 0 and 1. + /// + public readonly float G { get; } + + /// + /// Gets the blue component. + /// A value usually ranging between 0 and 1. + /// + public readonly float B { get; } + + /// + /// Gets the Rgb color space + /// + public readonly RgbWorkingSpace WorkingSpace { get; } + /// /// Allows the implicit conversion of an instance of to a /// . @@ -102,7 +102,7 @@ namespace SixLabors.ImageSharp.ColorSpaces /// The instance of to convert. /// An instance of . [MethodImpl(InliningOptions.ShortMethod)] - public static implicit operator Rgb(Rgb24 color) => new Rgb(color.R / 255F, color.G / 255F, color.B / 255F); + public static implicit operator Rgb(Rgb24 color) => new(color.R / 255F, color.G / 255F, color.B / 255F); /// /// Allows the implicit conversion of an instance of to a @@ -111,7 +111,7 @@ namespace SixLabors.ImageSharp.ColorSpaces /// The instance of to convert. /// An instance of . [MethodImpl(InliningOptions.ShortMethod)] - public static implicit operator Rgb(Rgba32 color) => new Rgb(color.R / 255F, color.G / 255F, color.B / 255F); + public static implicit operator Rgb(Rgba32 color) => new(color.R / 255F, color.G / 255F, color.B / 255F); /// /// Compares two objects for equality. @@ -144,7 +144,7 @@ namespace SixLabors.ImageSharp.ColorSpaces /// /// The . [MethodImpl(InliningOptions.ShortMethod)] - public Vector3 ToVector3() => new Vector3(this.R, this.G, this.B); + public Vector3 ToVector3() => new(this.R, this.G, this.B); /// public override int GetHashCode() => HashCode.Combine(this.R, this.G, this.B); @@ -158,10 +158,8 @@ namespace SixLabors.ImageSharp.ColorSpaces /// [MethodImpl(InliningOptions.ShortMethod)] public bool Equals(Rgb other) - { - return this.R.Equals(other.R) - && this.G.Equals(other.G) - && this.B.Equals(other.B); - } + => this.R.Equals(other.R) + && this.G.Equals(other.G) + && this.B.Equals(other.B); } } diff --git a/src/ImageSharp/ColorSpaces/YCbCr.cs b/src/ImageSharp/ColorSpaces/YCbCr.cs index cb4d7d091..2670a2700 100644 --- a/src/ImageSharp/ColorSpaces/YCbCr.cs +++ b/src/ImageSharp/ColorSpaces/YCbCr.cs @@ -15,25 +15,7 @@ namespace SixLabors.ImageSharp.ColorSpaces public readonly struct YCbCr : IEquatable { private static readonly Vector3 Min = Vector3.Zero; - private static readonly Vector3 Max = new Vector3(255); - - /// - /// Gets the Y luminance component. - /// A value ranging between 0 and 255. - /// - public readonly float Y; - - /// - /// Gets the Cb chroma component. - /// A value ranging between 0 and 255. - /// - public readonly float Cb; - - /// - /// Gets the Cr chroma component. - /// A value ranging between 0 and 255. - /// - public readonly float Cr; + private static readonly Vector3 Max = new(255); /// /// Initializes a new instance of the struct. @@ -60,6 +42,24 @@ namespace SixLabors.ImageSharp.ColorSpaces this.Cr = vector.Z; } + /// + /// Gets the Y luminance component. + /// A value ranging between 0 and 255. + /// + public readonly float Y { get; } + + /// + /// Gets the Cb chroma component. + /// A value ranging between 0 and 255. + /// + public readonly float Cb { get; } + + /// + /// Gets the Cr chroma component. + /// A value ranging between 0 and 255. + /// + public readonly float Cr { get; } + /// /// Compares two objects for equality. /// @@ -94,10 +94,8 @@ namespace SixLabors.ImageSharp.ColorSpaces /// [MethodImpl(InliningOptions.ShortMethod)] public bool Equals(YCbCr other) - { - return this.Y.Equals(other.Y) - && this.Cb.Equals(other.Cb) - && this.Cr.Equals(other.Cr); - } + => this.Y.Equals(other.Y) + && this.Cb.Equals(other.Cb) + && this.Cr.Equals(other.Cr); } } diff --git a/src/ImageSharp/Diagnostics/MemoryDiagnostics.cs b/src/ImageSharp/Diagnostics/MemoryDiagnostics.cs index 33af606b9..2cd286cd6 100644 --- a/src/ImageSharp/Diagnostics/MemoryDiagnostics.cs +++ b/src/ImageSharp/Diagnostics/MemoryDiagnostics.cs @@ -9,6 +9,7 @@ namespace SixLabors.ImageSharp.Diagnostics /// /// Represents the method to handle . /// + /// The allocation stack trace. public delegate void UndisposedAllocationDelegate(string allocationStackTrace); /// diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs index 7af2d9a36..4812b550d 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs @@ -491,7 +491,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp int max = cmd[1]; int bytesToRead = (max + 1) / 2; - var run = new byte[bytesToRead]; + byte[] run = new byte[bytesToRead]; this.stream.Read(run, 0, run.Length); @@ -501,13 +501,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp byte twoPixels = run[idx]; if (i % 2 == 0) { - byte leftPixel = (byte)((twoPixels >> 4) & 0xF); - buffer[count++] = leftPixel; + buffer[count++] = (byte)((twoPixels >> 4) & 0xF); } else { - byte rightPixel = (byte)(twoPixels & 0xF); - buffer[count++] = rightPixel; + buffer[count++] = (byte)(twoPixels & 0xF); idx++; } } @@ -597,7 +595,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp // Take this number of bytes from the stream as uncompressed data. int length = cmd[1]; - var run = new byte[length]; + byte[] run = new byte[length]; this.stream.Read(run, 0, run.Length); @@ -676,7 +674,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp // Take this number of bytes from the stream as uncompressed data. int length = cmd[1]; - var run = new byte[length * 3]; + byte[] run = new byte[length * 3]; this.stream.Read(run, 0, run.Length); @@ -909,7 +907,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp int r = (redMaskBits == 5) ? GetBytesFrom5BitValue((temp & redMask) >> rightShiftRedMask) : GetBytesFrom6BitValue((temp & redMask) >> rightShiftRedMask); int g = (greenMaskBits == 5) ? GetBytesFrom5BitValue((temp & greenMask) >> rightShiftGreenMask) : GetBytesFrom6BitValue((temp & greenMask) >> rightShiftGreenMask); int b = (blueMaskBits == 5) ? GetBytesFrom5BitValue((temp & blueMask) >> rightShiftBlueMask) : GetBytesFrom6BitValue((temp & blueMask) >> rightShiftBlueMask); - var rgb = new Rgb24((byte)r, (byte)g, (byte)b); + Rgb24 rgb = new((byte)r, (byte)g, (byte)b); color.FromRgb24(rgb); pixelRow[x] = color; @@ -1164,7 +1162,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp uint g = (uint)(temp & greenMask) >> rightShiftGreenMask; uint b = (uint)(temp & blueMask) >> rightShiftBlueMask; float alpha = alphaMask != 0 ? invMaxValueAlpha * ((uint)(temp & alphaMask) >> rightShiftAlphaMask) : 1.0f; - var vector4 = new Vector4( + Vector4 vector4 = new( r * invMaxValueRed, g * invMaxValueGreen, b * invMaxValueBlue, @@ -1246,7 +1244,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp this.stream.Read(buffer, 0, BmpInfoHeader.HeaderSizeSize); int headerSize = BinaryPrimitives.ReadInt32LittleEndian(buffer); - if (headerSize < BmpInfoHeader.CoreSize || headerSize > BmpInfoHeader.MaxHeaderSize) + if (headerSize is < BmpInfoHeader.CoreSize or > BmpInfoHeader.MaxHeaderSize) { BmpThrowHelper.ThrowNotSupportedException($"ImageSharp does not support this BMP file. HeaderSize is '{headerSize}'."); } @@ -1277,7 +1275,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp // color masks for each color channel follow the info header. if (this.infoHeader.Compression == BmpCompression.BitFields) { - var bitfieldsBuffer = new byte[12]; + byte[] bitfieldsBuffer = new byte[12]; this.stream.Read(bitfieldsBuffer, 0, 12); Span data = bitfieldsBuffer.AsSpan(); this.infoHeader.RedMask = BinaryPrimitives.ReadInt32LittleEndian(data[..4]); @@ -1286,7 +1284,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp } else if (this.infoHeader.Compression == BmpCompression.BI_ALPHABITFIELDS) { - var bitfieldsBuffer = new byte[16]; + byte[] bitfieldsBuffer = new byte[16]; this.stream.Read(bitfieldsBuffer, 0, 16); Span data = bitfieldsBuffer.AsSpan(); this.infoHeader.RedMask = BinaryPrimitives.ReadInt32LittleEndian(data[..4]); @@ -1396,6 +1394,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// /// Reads the and from the stream and sets the corresponding fields. /// + /// The input stream. + /// Whether the image orientation is inverted. + /// The color palette. /// Bytes per color palette entry. Usually 4 bytes, but in case of Windows 2.x bitmaps or OS/2 1.x bitmaps /// the bytes per color palette entry's can be 3 bytes instead of 4. private int ReadImageHeaders(BufferedReadStream stream, out bool inverted, out byte[] palette) diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs index dce6368c8..b216fd7a5 100644 --- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs @@ -160,10 +160,10 @@ namespace SixLabors.ImageSharp.Formats.Bmp Span buffer = stackalloc byte[infoHeaderSize]; - this.WriteBitmapFileHeader(stream, infoHeaderSize, colorPaletteSize, iccProfileSize, infoHeader, buffer); + WriteBitmapFileHeader(stream, infoHeaderSize, colorPaletteSize, iccProfileSize, infoHeader, buffer); this.WriteBitmapInfoHeader(stream, infoHeader, buffer, infoHeaderSize); this.WriteImage(stream, image.Frames.RootFrame); - this.WriteColorProfile(stream, iccProfileData, buffer); + WriteColorProfile(stream, iccProfileData, buffer); stream.Flush(); } @@ -184,34 +184,33 @@ namespace SixLabors.ImageSharp.Formats.Bmp int hResolution = 0; int vResolution = 0; - if (metadata.ResolutionUnits != PixelResolutionUnit.AspectRatio) + if (metadata.ResolutionUnits != PixelResolutionUnit.AspectRatio + && metadata.HorizontalResolution > 0 + && metadata.VerticalResolution > 0) { - if (metadata.HorizontalResolution > 0 && metadata.VerticalResolution > 0) + switch (metadata.ResolutionUnits) { - switch (metadata.ResolutionUnits) - { - case PixelResolutionUnit.PixelsPerInch: + case PixelResolutionUnit.PixelsPerInch: - hResolution = (int)Math.Round(UnitConverter.InchToMeter(metadata.HorizontalResolution)); - vResolution = (int)Math.Round(UnitConverter.InchToMeter(metadata.VerticalResolution)); - break; + hResolution = (int)Math.Round(UnitConverter.InchToMeter(metadata.HorizontalResolution)); + vResolution = (int)Math.Round(UnitConverter.InchToMeter(metadata.VerticalResolution)); + break; - case PixelResolutionUnit.PixelsPerCentimeter: + case PixelResolutionUnit.PixelsPerCentimeter: - hResolution = (int)Math.Round(UnitConverter.CmToMeter(metadata.HorizontalResolution)); - vResolution = (int)Math.Round(UnitConverter.CmToMeter(metadata.VerticalResolution)); - break; + hResolution = (int)Math.Round(UnitConverter.CmToMeter(metadata.HorizontalResolution)); + vResolution = (int)Math.Round(UnitConverter.CmToMeter(metadata.VerticalResolution)); + break; - case PixelResolutionUnit.PixelsPerMeter: - hResolution = (int)Math.Round(metadata.HorizontalResolution); - vResolution = (int)Math.Round(metadata.VerticalResolution); + case PixelResolutionUnit.PixelsPerMeter: + hResolution = (int)Math.Round(metadata.HorizontalResolution); + vResolution = (int)Math.Round(metadata.VerticalResolution); - break; - } + break; } } - var infoHeader = new BmpInfoHeader( + BmpInfoHeader infoHeader = new( headerSize: infoHeaderSize, height: height, width: width, @@ -248,7 +247,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// The stream to write to. /// The color profile data. /// The buffer. - private void WriteColorProfile(Stream stream, byte[] iccProfileData, Span buffer) + private static void WriteColorProfile(Stream stream, byte[] iccProfileData, Span buffer) { if (iccProfileData != null) { @@ -270,9 +269,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// The size in bytes of the color profile. /// The information header to write. /// The buffer to write to. - private void WriteBitmapFileHeader(Stream stream, int infoHeaderSize, int colorPaletteSize, int iccProfileSize, BmpInfoHeader infoHeader, Span buffer) + private static void WriteBitmapFileHeader(Stream stream, int infoHeaderSize, int colorPaletteSize, int iccProfileSize, BmpInfoHeader infoHeader, Span buffer) { - var fileHeader = new BmpFileHeader( + BmpFileHeader fileHeader = new( type: BmpConstants.TypeMarkers.Bitmap, fileSize: BmpFileHeader.Size + infoHeaderSize + colorPaletteSize + iccProfileSize + infoHeader.ImageSize, reserved: 0, @@ -555,7 +554,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp if (pixelRowSpan.Length % 2 != 0) { - stream.WriteByte((byte)((pixelRowSpan[pixelRowSpan.Length - 1] << 4) | 0)); + stream.WriteByte((byte)((pixelRowSpan[^1] << 4) | 0)); } for (int i = 0; i < rowPadding; i++) diff --git a/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs b/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs index 9c0efcb6d..e7536ccac 100644 --- a/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs +++ b/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs @@ -382,18 +382,16 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// public static BmpInfoHeader ParseOs2Version2(ReadOnlySpan data) { - var infoHeader = new BmpInfoHeader( + BmpInfoHeader infoHeader = new( headerSize: BinaryPrimitives.ReadInt32LittleEndian(data[..4]), width: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(4, 4)), height: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(8, 4)), planes: BinaryPrimitives.ReadInt16LittleEndian(data.Slice(12, 2)), bitsPerPixel: BinaryPrimitives.ReadInt16LittleEndian(data.Slice(14, 2))); - int compression = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(16, 4)); - // The compression value in OS/2 bitmap has a different meaning than in windows bitmaps. // Map the OS/2 value to the windows values. - switch (compression) + switch (BinaryPrimitives.ReadInt32LittleEndian(data.Slice(16, 4))) { case 0: infoHeader.Compression = BmpCompression.RGB; @@ -465,11 +463,12 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// The data to parse. /// The parsed header. /// + /// Invalid size. public static BmpInfoHeader ParseV5(ReadOnlySpan data) { if (data.Length < SizeV5) { - throw new ArgumentException(nameof(data), $"Must be {SizeV5} bytes. Was {data.Length} bytes."); + throw new ArgumentException($"Must be {SizeV5} bytes. Was {data.Length} bytes.", nameof(data)); } return MemoryMarshal.Cast(data)[0]; @@ -545,13 +544,13 @@ namespace SixLabors.ImageSharp.Formats.Bmp internal void VerifyDimensions() { - const int MaximumBmpDimension = 65535; + const int maximumBmpDimension = 65535; - if (this.Width > MaximumBmpDimension || this.Height > MaximumBmpDimension) + if (this.Width > maximumBmpDimension || this.Height > maximumBmpDimension) { throw new InvalidOperationException( $"The input bmp '{this.Width}x{this.Height}' is " - + $"bigger then the max allowed size '{MaximumBmpDimension}x{MaximumBmpDimension}'"); + + $"bigger then the max allowed size '{maximumBmpDimension}x{maximumBmpDimension}'"); } } } diff --git a/src/ImageSharp/Formats/DecoderOptions.cs b/src/ImageSharp/Formats/DecoderOptions.cs index 8f16c6ecc..e21f21f7b 100644 --- a/src/ImageSharp/Formats/DecoderOptions.cs +++ b/src/ImageSharp/Formats/DecoderOptions.cs @@ -29,7 +29,7 @@ namespace SixLabors.ImageSharp.Formats /// /// Gets or sets the target size to decode the image into. /// - public Size? TargetSize { get; set; } = null; + public Size? TargetSize { get; set; } /// /// Gets or sets the sampler to use when resizing during decoding. @@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.Formats /// /// Gets or sets a value indicating whether to ignore encoded metadata when decoding. /// - public bool SkipMetadata { get; set; } = false; + public bool SkipMetadata { get; set; } /// /// Gets or sets the maximum number of image frames to decode, inclusive. diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs index 0f7606a43..f354e42f3 100644 --- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs @@ -108,10 +108,10 @@ namespace SixLabors.ImageSharp.Formats.Gif this.bitDepth = ColorNumerics.GetBitsNeededForColorDepth(quantized.Palette.Length); // Write the header. - this.WriteHeader(stream); + WriteHeader(stream); // Write the LSD. - int index = this.GetTransparentIndex(quantized); + int index = GetTransparentIndex(quantized); this.WriteLogicalScreenDescriptor(metadata, image.Width, image.Height, index, useGlobalTable, stream); if (useGlobalTable) @@ -193,7 +193,7 @@ namespace SixLabors.ImageSharp.Formats.Gif if (previousFrame != null && previousMeta.ColorTableLength != frameMetadata.ColorTableLength && frameMetadata.ColorTableLength > 0) { - var options = new QuantizerOptions + QuantizerOptions options = new() { Dither = this.quantizer.Options.Dither, DitherScale = this.quantizer.Options.DitherScale, @@ -211,7 +211,7 @@ namespace SixLabors.ImageSharp.Formats.Gif } this.bitDepth = ColorNumerics.GetBitsNeededForColorDepth(quantized.Palette.Length); - this.WriteGraphicalControlExtension(frameMetadata, this.GetTransparentIndex(quantized), stream); + this.WriteGraphicalControlExtension(frameMetadata, GetTransparentIndex(quantized), stream); this.WriteImageDescriptor(frame, true, stream); this.WriteColorTable(quantized, stream); this.WriteImageData(quantized, stream); @@ -231,7 +231,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// /// The . /// - private int GetTransparentIndex(IndexedImageFrame quantized) + private static int GetTransparentIndex(IndexedImageFrame quantized) where TPixel : unmanaged, IPixel { // Transparent pixels are much more likely to be found at the end of a palette. @@ -259,7 +259,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// /// The stream to write to. [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void WriteHeader(Stream stream) => stream.Write(GifConstants.MagicNumber); + private static void WriteHeader(Stream stream) => stream.Write(GifConstants.MagicNumber); /// /// Writes the logical screen descriptor to the stream. @@ -308,7 +308,7 @@ namespace SixLabors.ImageSharp.Formats.Gif } } - var descriptor = new GifLogicalScreenDescriptor( + GifLogicalScreenDescriptor descriptor = new( width: (ushort)width, height: (ushort)height, packed: packedValue, @@ -332,14 +332,14 @@ namespace SixLabors.ImageSharp.Formats.Gif // Application Extension: Loop repeat count. if (frameCount > 1 && repeatCount != 1) { - var loopingExtension = new GifNetscapeLoopingApplicationExtension(repeatCount); + GifNetscapeLoopingApplicationExtension loopingExtension = new(repeatCount); this.WriteExtension(loopingExtension, stream); } // Application Extension: XMP Profile. if (xmpProfile != null) { - var xmpExtension = new GifXmpApplicationExtension(xmpProfile.Data); + GifXmpApplicationExtension xmpExtension = new(xmpProfile.Data); this.WriteExtension(xmpExtension, stream); } } @@ -411,7 +411,7 @@ namespace SixLabors.ImageSharp.Formats.Gif disposalMethod: metadata.DisposalMethod, transparencyFlag: transparencyIndex > -1); - var extension = new GifGraphicControlExtension( + GifGraphicControlExtension extension = new( packed: packedValue, delayTime: (ushort)metadata.FrameDelay, transparencyIndex: unchecked((byte)transparencyIndex)); @@ -422,6 +422,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// /// Writes the provided extension to the stream. /// + /// The type of gif extension. /// The extension to write to the stream. /// The stream to write to. private void WriteExtension(TGifExtension extension, Stream stream) @@ -472,7 +473,7 @@ namespace SixLabors.ImageSharp.Formats.Gif sortFlag: false, localColorTableSize: this.bitDepth - 1); - var descriptor = new GifImageDescriptor( + GifImageDescriptor descriptor = new( left: 0, top: 0, width: (ushort)image.Width, @@ -517,7 +518,7 @@ namespace SixLabors.ImageSharp.Formats.Gif private void WriteImageData(IndexedImageFrame image, Stream stream) where TPixel : unmanaged, IPixel { - using var encoder = new LzwEncoder(this.memoryAllocator, (byte)this.bitDepth); + using LzwEncoder encoder = new(this.memoryAllocator, (byte)this.bitDepth); encoder.Encode(((IPixelSource)image).PixelBuffer, stream); } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs index 7d71730d1..16d95f99f 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs @@ -161,7 +161,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components { if (Avx.IsSupported) { - var valueVec = Vector256.Create(value); + Vector256 valueVec = Vector256.Create(value); this.V0 = Avx.Multiply(this.V0, valueVec); this.V1 = Avx.Multiply(this.V1, valueVec); this.V2 = Avx.Multiply(this.V2, valueVec); @@ -173,7 +173,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components } else { - var valueVec = new Vector4(value); + Vector4 valueVec = new(value); this.V0L *= valueVec; this.V0R *= valueVec; this.V1L *= valueVec; @@ -196,6 +196,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components /// /// Multiply all elements of the block by the corresponding elements of 'other'. /// + /// The other block. [MethodImpl(InliningOptions.ShortMethod)] public unsafe void MultiplyInPlace(ref Block8x8F other) { @@ -240,7 +241,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components { if (Avx.IsSupported) { - var valueVec = Vector256.Create(value); + Vector256 valueVec = Vector256.Create(value); this.V0 = Avx.Add(this.V0, valueVec); this.V1 = Avx.Add(this.V1, valueVec); this.V2 = Avx.Add(this.V2, valueVec); @@ -252,7 +253,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components } else { - var valueVec = new Vector4(value); + Vector4 valueVec = new(value); this.V0L += valueVec; this.V0R += valueVec; this.V1L += valueVec; @@ -330,6 +331,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components /// /// Level shift by +maximum/2, clip to [0..maximum], and round all the values in the block. /// + /// The maximum value. public void NormalizeColorsAndRoundInPlace(float maximum) { if (SimdUtils.HasVector8) @@ -421,7 +423,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components { const int equalityMask = unchecked((int)0b1111_1111_1111_1111_1111_1111_1111_1111); - var targetVector = Vector256.Create(value); + Vector256 targetVector = Vector256.Create(value); ref Vector256 blockStride = ref this.V0; for (int i = 0; i < RowCount; i++) @@ -468,20 +470,46 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components && this.V7L == other.V7L && this.V7R == other.V7R; + /// + public override bool Equals(object obj) => this.Equals((Block8x8F)obj); + + /// + public override int GetHashCode() + { + int left = HashCode.Combine( + this.V0L, + this.V1L, + this.V2L, + this.V3L, + this.V4L, + this.V5L, + this.V6L, + this.V7L); + + int right = HashCode.Combine( + this.V0R, + this.V1R, + this.V2R, + this.V3R, + this.V4R, + this.V5R, + this.V6R, + this.V7R); + + return HashCode.Combine(left, right); + } + /// public override string ToString() { - var sb = new StringBuilder(); + StringBuilder sb = new(); sb.Append('['); for (int i = 0; i < Size - 1; i++) { - sb.Append(this[i]); - sb.Append(','); + sb.Append(this[i]).Append(','); } - sb.Append(this[Size - 1]); - - sb.Append(']'); + sb.Append(this[Size - 1]).Append(']'); return sb.ToString(); } diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterBase.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterBase.cs index c2e01df99..c159ed7d2 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterBase.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterBase.cs @@ -20,6 +20,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components /// /// Initializes a new instance of the class. /// + /// The color space. + /// The precision in bits. protected JpegColorConverterBase(JpegColorSpace colorSpace, int precision) { this.ColorSpace = colorSpace; @@ -66,6 +68,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components /// /// Returns the corresponding to the given /// + /// The color space. + /// The precision in bits. + /// Invalid colorspace. public static JpegColorConverterBase GetConverter(JpegColorSpace colorSpace, int precision) { JpegColorConverterBase converter = Array.Find( @@ -75,7 +80,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components if (converter is null) { - throw new Exception($"Could not find any converter for JpegColorSpace {colorSpace}!"); + throw new InvalidImageContentException($"Could not find any converter for JpegColorSpace {colorSpace}!"); } return converter; @@ -104,7 +109,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components // 5 color types with 2 supported precisions: 8 bit & 12 bit const int colorConvertersCount = 5 * 2; - var converters = new JpegColorConverterBase[colorConvertersCount]; + JpegColorConverterBase[] converters = new JpegColorConverterBase[colorConvertersCount]; // 8-bit converters converters[0] = GetYCbCrConverter(8); @@ -126,6 +131,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components /// /// Returns the s for the YCbCr colorspace. /// + /// The precision in bits. private static JpegColorConverterBase GetYCbCrConverter(int precision) { if (JpegColorConverterAvx.IsSupported) @@ -144,6 +150,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components /// /// Returns the s for the YccK colorspace. /// + /// The precision in bits. private static JpegColorConverterBase GetYccKConverter(int precision) { if (JpegColorConverterAvx.IsSupported) @@ -162,6 +169,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components /// /// Returns the s for the CMYK colorspace. /// + /// The precision in bits. private static JpegColorConverterBase GetCmykConverter(int precision) { if (JpegColorConverterAvx.IsSupported) @@ -180,6 +188,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components /// /// Returns the s for the gray scale colorspace. /// + /// The precision in bits. private static JpegColorConverterBase GetGrayScaleConverter(int precision) { if (JpegColorConverterAvx.IsSupported) @@ -198,6 +207,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components /// /// Returns the s for the RGB colorspace. /// + /// The precision in bits. private static JpegColorConverterBase GetRgbConverter(int precision) { if (JpegColorConverterAvx.IsSupported) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ArithmeticScanDecoder.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ArithmeticScanDecoder.cs index ae97c7e54..21727bc99 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ArithmeticScanDecoder.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ArithmeticScanDecoder.cs @@ -225,10 +225,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder { for (int i = 0; i < this.components.Length; i++) { - var component = this.components[i] as ArithmeticDecodingComponent; - this.dcDecodingTables[i] = this.GetArithmeticTable(arithmeticDecodingTables, true, component.DcTableId); + ArithmeticDecodingComponent component = this.components[i] as ArithmeticDecodingComponent; + this.dcDecodingTables[i] = GetArithmeticTable(arithmeticDecodingTables, true, component.DcTableId); component.DcStatistics = this.CreateOrGetStatisticsBin(true, component.DcTableId); - this.acDecodingTables[i] = this.GetArithmeticTable(arithmeticDecodingTables, false, component.AcTableId); + this.acDecodingTables[i] = GetArithmeticTable(arithmeticDecodingTables, false, component.AcTableId); component.AcStatistics = this.CreateOrGetStatisticsBin(false, component.AcTableId); } } @@ -276,7 +276,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder this.spectralConverter.InjectFrameData(frame, jpegData); } - private ArithmeticDecodingTable GetArithmeticTable(List arithmeticDecodingTables, bool isDcTable, int identifier) + private static ArithmeticDecodingTable GetArithmeticTable(List arithmeticDecodingTables, bool isDcTable, int identifier) { int tableClass = isDcTable ? 0 : 1; @@ -306,15 +306,16 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder } } - var statistic = new ArithmeticStatistics(dc, identifier); + ArithmeticStatistics statistic = new(dc, identifier); this.statistics.Add(statistic); return statistic; } private void ParseBaselineData() { - foreach (ArithmeticDecodingComponent component in this.components) + for (int i = 0; i < this.components.Length; i++) { + ArithmeticDecodingComponent component = (ArithmeticDecodingComponent)this.components[i]; component.DcPredictor = 0; component.DcContext = 0; component.DcStatistics?.Reset(); @@ -441,7 +442,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder for (int k = 0; k < this.scanComponentCount; k++) { int order = this.frame.ComponentOrder[k]; - var component = this.components[order] as ArithmeticDecodingComponent; + ArithmeticDecodingComponent component = this.components[order] as ArithmeticDecodingComponent; ref ArithmeticDecodingTable dcDecodingTable = ref this.dcDecodingTables[component.DcTableId]; ref ArithmeticDecodingTable acDecodingTable = ref this.acDecodingTables[component.AcTableId]; @@ -491,7 +492,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder private void ParseBaselineDataSingleComponent() { - var component = this.frame.Components[0] as ArithmeticDecodingComponent; + ArithmeticDecodingComponent component = this.frame.Components[0] as ArithmeticDecodingComponent; int mcuLines = this.frame.McusPerColumn; int w = component.WidthInBlocks; int h = component.SamplingFactors.Height; @@ -537,7 +538,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder private void ParseBaselineDataNonInterleaved() { - var component = (ArithmeticDecodingComponent)this.components[this.frame.ComponentOrder[0]]; + ArithmeticDecodingComponent component = (ArithmeticDecodingComponent)this.components[this.frame.ComponentOrder[0]]; ref JpegBitReader reader = ref this.scanBuffer; int w = component.WidthInBlocks; @@ -586,7 +587,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder for (int k = 0; k < this.scanComponentCount; k++) { int order = this.frame.ComponentOrder[k]; - var component = this.components[order] as ArithmeticDecodingComponent; + ArithmeticDecodingComponent component = this.components[order] as ArithmeticDecodingComponent; ref ArithmeticDecodingTable dcDecodingTable = ref this.dcDecodingTables[component.DcTableId]; int h = component.HorizontalSamplingFactor; @@ -628,7 +629,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder private void ParseProgressiveDataNonInterleaved() { - var component = this.components[this.frame.ComponentOrder[0]] as ArithmeticDecodingComponent; + ArithmeticDecodingComponent component = this.components[this.frame.ComponentOrder[0]] as ArithmeticDecodingComponent; ref JpegBitReader reader = ref this.scanBuffer; int w = component.WidthInBlocks; @@ -1140,7 +1141,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder { for (int i = 0; i < this.components.Length; i++) { - var component = this.components[i] as ArithmeticDecodingComponent; + ArithmeticDecodingComponent component = this.components[i] as ArithmeticDecodingComponent; component.DcPredictor = 0; } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegFileMarker.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegFileMarker.cs index f3ceb3584..185e5b06b 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegFileMarker.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegFileMarker.cs @@ -1,6 +1,7 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +using System.Globalization; using System.Runtime.CompilerServices; namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder @@ -62,8 +63,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder /// public override string ToString() - { - return this.Marker.ToString("X"); - } + => this.Marker.ToString("X", CultureInfo.InvariantCulture); } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Encoder/EncodingConfigs/JpegFrameConfig.cs b/src/ImageSharp/Formats/Jpeg/Components/Encoder/EncodingConfigs/JpegFrameConfig.cs index 18afff738..feb1ae8ee 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Encoder/EncodingConfigs/JpegFrameConfig.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Encoder/EncodingConfigs/JpegFrameConfig.cs @@ -39,6 +39,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder public int MaxVerticalSamplingFactor { get; } - public byte? AdobeColorTransformMarkerFlag { get; set; } = null; + public byte? AdobeColorTransformMarkerFlag { get; set; } } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanSpec.cs b/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanSpec.cs index 97f051c76..1a262f480 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanSpec.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanSpec.cs @@ -122,16 +122,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder 0xf9, 0xfa }); - /// - /// Gets count[i] - The number of codes of length i bits. - /// - public readonly byte[] Count; - - /// - /// Gets value[i] - The decoded value of the codeword at the given index. - /// - public readonly byte[] Values; - /// /// Initializes a new instance of the struct. /// @@ -146,5 +136,15 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder this.Count = count; this.Values = values; } + + /// + /// Gets the count[i] - The number of codes of length i bits. + /// + public readonly byte[] Count { get; } + + /// + /// Gets the value[i] - The decoded value of the codeword at the given index. + /// + public readonly byte[] Values { get; } } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/RowOctet.cs b/src/ImageSharp/Formats/Jpeg/Components/RowOctet.cs index c899cf3ad..5872d4767 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/RowOctet.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/RowOctet.cs @@ -11,6 +11,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components /// /// Cache 8 pixel rows on the stack, which may originate from different buffers of a . /// + /// The type of element in each row. [StructLayout(LayoutKind.Sequential)] internal ref struct RowOctet where T : struct @@ -92,6 +93,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components [MethodImpl(MethodImplOptions.NoInlining)] private static Span ThrowIndexOutOfRangeException() +#pragma warning disable CA2201 // Do not raise reserved exception types => throw new IndexOutOfRangeException(); +#pragma warning restore CA2201 // Do not raise reserved exception types } } diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs index 242e61e60..3d65021a7 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs @@ -213,7 +213,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg public Image Decode(BufferedReadStream stream, CancellationToken cancellationToken) where TPixel : unmanaged, IPixel { - using var spectralConverter = new SpectralConverter(this.configuration, this.resizeMode == JpegDecoderResizeMode.ScaleOnly ? null : this.Options.TargetSize); + using SpectralConverter spectralConverter = new(this.configuration, this.resizeMode == JpegDecoderResizeMode.ScaleOnly ? null : this.Options.TargetSize); this.ParseStream(stream, spectralConverter, cancellationToken); this.InitExifProfile(); this.InitIccProfile(); @@ -257,12 +257,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg JpegThrowHelper.ThrowInvalidImageContentException("Not enough data to read marker"); } - using var ms = new MemoryStream(tableBytes); - using var stream = new BufferedReadStream(this.configuration, ms); + using MemoryStream ms = new(tableBytes); + using BufferedReadStream stream = new(this.configuration, ms); // Check for the Start Of Image marker. int bytesRead = stream.Read(this.markerBuffer, 0, 2); - var fileMarker = new JpegFileMarker(this.markerBuffer[1], 0); + JpegFileMarker fileMarker = new(this.markerBuffer[1], 0); if (fileMarker.Marker != JpegConstants.Markers.SOI) { JpegThrowHelper.ThrowInvalidImageContentException("Missing SOI marker."); @@ -290,7 +290,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg switch (fileMarker.Marker) { case JpegConstants.Markers.SOI: - break; case JpegConstants.Markers.RST0: case JpegConstants.Markers.RST7: break; @@ -335,7 +334,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg // Check for the Start Of Image marker. stream.Read(this.markerBuffer, 0, 2); - var fileMarker = new JpegFileMarker(this.markerBuffer[1], 0); + JpegFileMarker fileMarker = new(this.markerBuffer[1], 0); if (fileMarker.Marker != JpegConstants.Markers.SOI) { JpegThrowHelper.ThrowInvalidImageContentException("Missing SOI marker."); @@ -409,12 +408,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg this.ProcessStartOfScanMarker(stream, markerContentByteSize); break; } - else - { - // It's highly unlikely that APPn related data will be found after the SOS marker - // We should have gathered everything we need by now. - return; - } + + // It's highly unlikely that APPn related data will be found after the SOS marker + // We should have gathered everything we need by now. + return; case JpegConstants.Markers.DHT: @@ -654,7 +651,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg { if (this.hasIcc) { - var profile = new IccProfile(this.iccData); + IccProfile profile = new(this.iccData); if (profile.CheckIsValid()) { this.Metadata.IccProfile = profile; @@ -669,8 +666,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg { if (this.hasIptc) { - var profile = new IptcProfile(this.iptcData); - this.Metadata.IptcProfile = profile; + this.Metadata.IptcProfile = new IptcProfile(this.iptcData); } } @@ -681,8 +677,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg { if (this.hasXmp) { - var profile = new XmpProfile(this.xmpData); - this.Metadata.XmpProfile = profile; + this.Metadata.XmpProfile = new XmpProfile(this.xmpData); } } @@ -723,7 +718,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// /// The profile data array. /// The array containing addition profile data. - private void ExtendProfile(ref byte[] profile, byte[] extension) + private static void ExtendProfile(ref byte[] profile, byte[] extension) { int currentLength = profile.Length; @@ -751,7 +746,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg stream.Read(this.temp, 0, JFifMarker.Length); remaining -= JFifMarker.Length; - JFifMarker.TryParse(this.temp, out this.jFif); + _ = JFifMarker.TryParse(this.temp, out this.jFif); // TODO: thumbnail if (remaining > 0) @@ -772,9 +767,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// The remaining bytes in the segment block. private void ProcessApp1Marker(BufferedReadStream stream, int remaining) { - const int ExifMarkerLength = 6; - const int XmpMarkerLength = 29; - if (remaining < ExifMarkerLength || this.skipMetadata) + const int exifMarkerLength = 6; + const int xmpMarkerLength = 29; + if (remaining < exifMarkerLength || this.skipMetadata) { // Skip the application header length. stream.Skip(remaining); @@ -787,8 +782,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg } // XMP marker is the longer then the EXIF marker, so first try read the EXIF marker bytes. - stream.Read(this.temp, 0, ExifMarkerLength); - remaining -= ExifMarkerLength; + stream.Read(this.temp, 0, exifMarkerLength); + remaining -= exifMarkerLength; if (ProfileResolver.IsProfile(this.temp, ProfileResolver.ExifMarker)) { @@ -803,15 +798,15 @@ namespace SixLabors.ImageSharp.Formats.Jpeg else { // If the EXIF information exceeds 64K, it will be split over multiple APP1 markers. - this.ExtendProfile(ref this.exifData, profile); + ExtendProfile(ref this.exifData, profile); } remaining = 0; } - if (ProfileResolver.IsProfile(this.temp, ProfileResolver.XmpMarker[..ExifMarkerLength])) + if (ProfileResolver.IsProfile(this.temp, ProfileResolver.XmpMarker[..exifMarkerLength])) { - const int remainingXmpMarkerBytes = XmpMarkerLength - ExifMarkerLength; + const int remainingXmpMarkerBytes = xmpMarkerLength - exifMarkerLength; if (remaining < remainingXmpMarkerBytes || this.skipMetadata) { // Skip the application header length. @@ -819,7 +814,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg return; } - stream.Read(this.temp, ExifMarkerLength, remainingXmpMarkerBytes); + stream.Read(this.temp, exifMarkerLength, remainingXmpMarkerBytes); remaining -= remainingXmpMarkerBytes; if (ProfileResolver.IsProfile(this.temp, ProfileResolver.XmpMarker)) { @@ -834,7 +829,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg else { // If the XMP information exceeds 64K, it will be split over multiple APP1 markers. - this.ExtendProfile(ref this.xmpData, profile); + ExtendProfile(ref this.xmpData, profile); } remaining = 0; @@ -853,16 +848,16 @@ namespace SixLabors.ImageSharp.Formats.Jpeg private void ProcessApp2Marker(BufferedReadStream stream, int remaining) { // Length is 14 though we only need to check 12. - const int Icclength = 14; - if (remaining < Icclength || this.skipMetadata) + const int icclength = 14; + if (remaining < icclength || this.skipMetadata) { stream.Skip(remaining); return; } - byte[] identifier = new byte[Icclength]; - stream.Read(identifier, 0, Icclength); - remaining -= Icclength; // We have read it by this point + byte[] identifier = new byte[icclength]; + stream.Read(identifier, 0, icclength); + remaining -= icclength; // We have read it by this point if (ProfileResolver.IsProfile(identifier, ProfileResolver.IccMarker)) { @@ -877,7 +872,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg else { // If the ICC information exceeds 64K, it will be split over multiple APP2 markers - this.ExtendProfile(ref this.iccData, profile); + ExtendProfile(ref this.iccData, profile); } } else @@ -971,7 +966,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg byte conditioningTableValue = (byte)stream.ReadByte(); remaining--; - var arithmeticTable = new ArithmeticDecodingTable(tableClass, identifier); + ArithmeticDecodingTable arithmeticTable = new(tableClass, identifier); arithmeticTable.Configure(conditioningTableValue); bool tableEntryReplaced = false; @@ -1029,16 +1024,16 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// The remaining bytes in the segment block. private void ProcessApp14Marker(BufferedReadStream stream, int remaining) { - const int MarkerLength = AdobeMarker.Length; - if (remaining < MarkerLength) + const int markerLength = AdobeMarker.Length; + if (remaining < markerLength) { // Skip the application header length stream.Skip(remaining); return; } - stream.Read(this.temp, 0, MarkerLength); - remaining -= MarkerLength; + stream.Read(this.temp, 0, markerLength); + remaining -= markerLength; if (AdobeMarker.TryParse(this.temp, out this.adobe)) { @@ -1086,7 +1081,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg { // 8 bit values case 0: - { // Validate: 8 bit table needs exactly 64 bytes if (remaining < 64) { @@ -1103,11 +1097,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg } break; - } // 16 bit values case 1: - { // Validate: 16 bit table needs exactly 128 bytes if (remaining < 128) { @@ -1124,14 +1116,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg } break; - } // Unknown precision - error default: - { JpegThrowHelper.ThrowBadQuantizationTablePrecision(tablePrecision); break; - } } // Estimating quality @@ -1139,17 +1128,13 @@ namespace SixLabors.ImageSharp.Formats.Jpeg { // luminance table case 0: - { jpegMetadata.LuminanceQuality = Quantization.EstimateLuminanceQuality(ref table); break; - } // chrominance table case 1: - { jpegMetadata.ChrominanceQuality = Quantization.EstimateChrominanceQuality(ref table); break; - } } } } @@ -1312,7 +1297,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg const int codeValuesMaxByteSize = 256; const int totalBufferSize = codeLengthsByteSize + codeValuesMaxByteSize + HuffmanTable.WorkspaceByteSize; - var huffmanScanDecoder = this.scanDecoder as HuffmanScanDecoder; + HuffmanScanDecoder huffmanScanDecoder = this.scanDecoder as HuffmanScanDecoder; if (huffmanScanDecoder is null) { JpegThrowHelper.ThrowInvalidImageContentException("missing huffman table data"); @@ -1399,6 +1384,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// /// Processes the SOS (Start of scan marker). /// + /// The input stream. + /// The remaining bytes in the segment block. private void ProcessStartOfScanMarker(BufferedReadStream stream, int remaining) { if (this.Frame is null) @@ -1479,11 +1466,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg JpegThrowHelper.ThrowInvalidImageContentException("Not enough data to read progressive scan decoding data"); } - int spectralStart = this.temp[0]; - this.scanDecoder.SpectralStart = spectralStart; + this.scanDecoder.SpectralStart = this.temp[0]; - int spectralEnd = this.temp[1]; - this.scanDecoder.SpectralEnd = spectralEnd; + this.scanDecoder.SpectralEnd = this.temp[1]; int successiveApproximation = this.temp[2]; this.scanDecoder.SuccessiveHigh = successiveApproximation >> 4; diff --git a/src/ImageSharp/Formats/Jpeg/JpegImageFormatDetector.cs b/src/ImageSharp/Formats/Jpeg/JpegImageFormatDetector.cs index fbbe210ff..61b4a36ad 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegImageFormatDetector.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegImageFormatDetector.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -15,22 +15,18 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// public IImageFormat DetectFormat(ReadOnlySpan header) - { - return this.IsSupportedFileFormat(header) ? JpegFormat.Instance : null; - } + => this.IsSupportedFileFormat(header) ? JpegFormat.Instance : null; private bool IsSupportedFileFormat(ReadOnlySpan header) - { - return header.Length >= this.HeaderSize && - (this.IsJfif(header) || this.IsExif(header) || this.IsJpeg(header)); - } + => header.Length >= this.HeaderSize + && (IsJfif(header) || IsExif(header) || IsJpeg(header)); /// /// Returns a value indicating whether the given bytes identify Jfif data. /// /// The bytes representing the file header. /// The - private bool IsJfif(ReadOnlySpan header) => + private static bool IsJfif(ReadOnlySpan header) => header[6] == 0x4A && // J header[7] == 0x46 && // F header[8] == 0x49 && // I @@ -42,7 +38,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// /// The bytes representing the file header. /// The - private bool IsExif(ReadOnlySpan header) => + private static bool IsExif(ReadOnlySpan header) => header[6] == 0x45 && // E header[7] == 0x78 && // X header[8] == 0x69 && // I @@ -55,7 +51,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// /// The bytes representing the file header. /// The - private bool IsJpeg(ReadOnlySpan header) => + private static bool IsJpeg(ReadOnlySpan header) => header[0] == 0xFF && // 255 header[1] == 0xD8; // 216 } diff --git a/src/ImageSharp/Formats/Pbm/PbmImageFormatDetector.cs b/src/ImageSharp/Formats/Pbm/PbmImageFormatDetector.cs index b8d776a37..4446d4b18 100644 --- a/src/ImageSharp/Formats/Pbm/PbmImageFormatDetector.cs +++ b/src/ImageSharp/Formats/Pbm/PbmImageFormatDetector.cs @@ -18,13 +18,11 @@ namespace SixLabors.ImageSharp.Formats.Pbm public int HeaderSize => 2; /// - public IImageFormat DetectFormat(ReadOnlySpan header) => this.IsSupportedFileFormat(header) ? PbmFormat.Instance : null; + public IImageFormat DetectFormat(ReadOnlySpan header) => IsSupportedFileFormat(header) ? PbmFormat.Instance : null; - private bool IsSupportedFileFormat(ReadOnlySpan header) + private static bool IsSupportedFileFormat(ReadOnlySpan header) { -#pragma warning disable SA1131 // Use readable conditions - if (1 < (uint)header.Length) -#pragma warning restore SA1131 // Use readable conditions + if ((uint)header.Length > 1) { // Signature should be between P1 and P6. return header[0] == P && (uint)(header[1] - Zero - 1) < (Seven - Zero - 1); diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs index 9a1f89c47..b7cd5dd93 100644 --- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs @@ -150,7 +150,7 @@ namespace SixLabors.ImageSharp.Formats.Png public Image Decode(BufferedReadStream stream, CancellationToken cancellationToken) where TPixel : unmanaged, IPixel { - var metadata = new ImageMetadata(); + ImageMetadata metadata = new(); PngMetadata pngMetadata = metadata.GetPngMetadata(); this.currentStream = stream; this.currentStream.Skip(8); @@ -250,7 +250,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// public IImageInfo Identify(BufferedReadStream stream, CancellationToken cancellationToken) { - var metadata = new ImageMetadata(); + ImageMetadata metadata = new(); PngMetadata pngMetadata = metadata.GetPngMetadata(); this.currentStream = stream; this.currentStream.Skip(8); @@ -434,7 +434,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// The data containing physical data. private static void ReadPhysicalChunk(ImageMetadata metadata, ReadOnlySpan data) { - var physicalChunk = PhysicalChunkData.Parse(data); + PhysicalChunkData physicalChunk = PhysicalChunkData.Parse(data); metadata.ResolutionUnits = physicalChunk.UnitSpecifier == byte.MinValue ? PixelResolutionUnit.AspectRatio @@ -560,7 +560,7 @@ namespace SixLabors.ImageSharp.Formats.Png private void ReadScanlines(PngChunk chunk, ImageFrame image, PngMetadata pngMetadata) where TPixel : unmanaged, IPixel { - using var deframeStream = new ZlibInflateStream(this.currentStream, this.ReadNextDataChunk); + using ZlibInflateStream deframeStream = new(this.currentStream, this.ReadNextDataChunk); deframeStream.AllocateNewBytes(chunk.Length, true); DeflateStream dataStream = deframeStream.CompressedStream; @@ -1018,7 +1018,7 @@ namespace SixLabors.ImageSharp.Formats.Png string value = PngConstants.Encoding.GetString(data[(zeroIndex + 1)..]); - if (!this.TryReadTextChunkMetadata(baseMetadata, name, value)) + if (!TryReadTextChunkMetadata(baseMetadata, name, value)) { metadata.TextData.Add(new PngTextData(name, value, string.Empty, string.Empty)); } @@ -1058,8 +1058,8 @@ namespace SixLabors.ImageSharp.Formats.Png ReadOnlySpan compressedData = data[(zeroIndex + 2)..]; - if (this.TryUncompressTextData(compressedData, PngConstants.Encoding, out string uncompressed) && - !this.TryReadTextChunkMetadata(baseMetadata, name, uncompressed)) + if (this.TryUncompressTextData(compressedData, PngConstants.Encoding, out string uncompressed) + && !TryReadTextChunkMetadata(baseMetadata, name, uncompressed)) { metadata.TextData.Add(new PngTextData(name, uncompressed, string.Empty, string.Empty)); } @@ -1074,10 +1074,10 @@ namespace SixLabors.ImageSharp.Formats.Png /// True if metadata was successfully parsed from the text chunk. False if the /// text chunk was not identified as metadata, and should be stored in the metadata /// object unmodified. - private bool TryReadTextChunkMetadata(ImageMetadata baseMetadata, string chunkName, string chunkText) + private static bool TryReadTextChunkMetadata(ImageMetadata baseMetadata, string chunkName, string chunkText) { if (chunkName.Equals("Raw profile type exif", StringComparison.OrdinalIgnoreCase) && - this.TryReadLegacyExifTextChunk(baseMetadata, chunkText)) + TryReadLegacyExifTextChunk(baseMetadata, chunkText)) { // Successfully parsed legacy exif data from text return true; @@ -1096,7 +1096,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// The to store the decoded exif tags into. /// The contents of the "raw profile type exif" text chunk. - private bool TryReadLegacyExifTextChunk(ImageMetadata metadata, string data) + private static bool TryReadLegacyExifTextChunk(ImageMetadata metadata, string data) { ReadOnlySpan dataSpan = data.AsSpan(); dataSpan = dataSpan.TrimStart(); @@ -1219,10 +1219,10 @@ namespace SixLabors.ImageSharp.Formats.Png fixed (byte* compressedDataBase = compressedData) { using IMemoryOwner destBuffer = this.memoryAllocator.Allocate(this.configuration.StreamProcessingBufferSize); - using var memoryStreamOutput = new MemoryStream(compressedData.Length); - using var memoryStreamInput = new UnmanagedMemoryStream(compressedDataBase, compressedData.Length); - using var bufferedStream = new BufferedReadStream(this.configuration, memoryStreamInput); - using var inflateStream = new ZlibInflateStream(bufferedStream); + using MemoryStream memoryStreamOutput = new(compressedData.Length); + using UnmanagedMemoryStream memoryStreamInput = new(compressedDataBase, compressedData.Length); + using BufferedReadStream bufferedStream = new(this.configuration, memoryStreamInput); + using ZlibInflateStream inflateStream = new(bufferedStream); Span destUncompressedData = destBuffer.GetSpan(); if (!inflateStream.AllocateNewBytes(compressedData.Length, false)) @@ -1358,7 +1358,7 @@ namespace SixLabors.ImageSharp.Formats.Png } else if (IsXmpTextData(keywordBytes)) { - var xmpProfile = new XmpProfile(data[dataStartIdx..].ToArray()); + XmpProfile xmpProfile = new(data[dataStartIdx..].ToArray()); metadata.XmpProfile = xmpProfile; } else @@ -1561,18 +1561,17 @@ namespace SixLabors.ImageSharp.Formats.Png { return (PngChunkType)BinaryPrimitives.ReadUInt32BigEndian(this.buffer); } - else - { - PngThrowHelper.ThrowInvalidChunkType(); - // The IDE cannot detect the throw here. - return default; - } + PngThrowHelper.ThrowInvalidChunkType(); + + // The IDE cannot detect the throw here. + return default; } /// /// Attempts to read the length of the next chunk. /// + /// The result length. If the return type is this parameter is passed uninitialized. /// /// Whether the length was read. /// @@ -1613,10 +1612,13 @@ namespace SixLabors.ImageSharp.Formats.Png // Keywords should not be empty or have leading or trailing whitespace. name = PngConstants.Encoding.GetString(keywordBytes); - return !string.IsNullOrWhiteSpace(name) && !name.StartsWith(" ") && !name.EndsWith(" "); + return !string.IsNullOrWhiteSpace(name) + && !name.StartsWith(" ", StringComparison.Ordinal) + && !name.EndsWith(" ", StringComparison.Ordinal); } - private static bool IsXmpTextData(ReadOnlySpan keywordBytes) => keywordBytes.SequenceEqual(PngConstants.XmpKeyword); + private static bool IsXmpTextData(ReadOnlySpan keywordBytes) + => keywordBytes.SequenceEqual(PngConstants.XmpKeyword); private void SwapScanlineBuffers() => (this.scanline, this.previousScanline) = (this.previousScanline, this.scanline); diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index 11142ea64..7ba28393d 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -245,62 +245,56 @@ namespace SixLabors.ImageSharp.Formats.Png } } } - else - { - if (this.bitDepth == 8) - { - // 8 bit grayscale - PixelOperations.Instance.ToL8Bytes( - this.configuration, - rowSpan, - rawScanlineSpan, - rowSpan.Length); - } - else - { - // 1, 2, and 4 bit grayscale - using IMemoryOwner temp = this.memoryAllocator.Allocate(rowSpan.Length, AllocationOptions.Clean); - int scaleFactor = 255 / (ColorNumerics.GetColorCountForBitDepth(this.bitDepth) - 1); - Span tempSpan = temp.GetSpan(); - - // We need to first create an array of luminance bytes then scale them down to the correct bit depth. - PixelOperations.Instance.ToL8Bytes( - this.configuration, - rowSpan, - tempSpan, - rowSpan.Length); - PngEncoderHelpers.ScaleDownFrom8BitArray(tempSpan, rawScanlineSpan, this.bitDepth, scaleFactor); - } - } - } - else - { - if (this.use16Bit) + else if (this.bitDepth == 8) { - // 16 bit grayscale + alpha - using IMemoryOwner laBuffer = this.memoryAllocator.Allocate(rowSpan.Length); - Span laSpan = laBuffer.GetSpan(); - ref La32 laRef = ref MemoryMarshal.GetReference(laSpan); - PixelOperations.Instance.ToLa32(this.configuration, rowSpan, laSpan); - - // Can't map directly to byte array as it's big endian. - for (int x = 0, o = 0; x < laSpan.Length; x++, o += 4) - { - La32 la = Unsafe.Add(ref laRef, x); - BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o, 2), la.L); - BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 2, 2), la.A); - } + // 8 bit grayscale + PixelOperations.Instance.ToL8Bytes( + this.configuration, + rowSpan, + rawScanlineSpan, + rowSpan.Length); } else { - // 8 bit grayscale + alpha - PixelOperations.Instance.ToLa16Bytes( + // 1, 2, and 4 bit grayscale + using IMemoryOwner temp = this.memoryAllocator.Allocate(rowSpan.Length, AllocationOptions.Clean); + int scaleFactor = 255 / (ColorNumerics.GetColorCountForBitDepth(this.bitDepth) - 1); + Span tempSpan = temp.GetSpan(); + + // We need to first create an array of luminance bytes then scale them down to the correct bit depth. + PixelOperations.Instance.ToL8Bytes( this.configuration, rowSpan, - rawScanlineSpan, + tempSpan, rowSpan.Length); + PngEncoderHelpers.ScaleDownFrom8BitArray(tempSpan, rawScanlineSpan, this.bitDepth, scaleFactor); } } + else if (this.use16Bit) + { + // 16 bit grayscale + alpha + using IMemoryOwner laBuffer = this.memoryAllocator.Allocate(rowSpan.Length); + Span laSpan = laBuffer.GetSpan(); + ref La32 laRef = ref MemoryMarshal.GetReference(laSpan); + PixelOperations.Instance.ToLa32(this.configuration, rowSpan, laSpan); + + // Can't map directly to byte array as it's big endian. + for (int x = 0, o = 0; x < laSpan.Length; x++, o += 4) + { + La32 la = Unsafe.Add(ref laRef, x); + BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o, 2), la.L); + BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 2, 2), la.A); + } + } + else + { + // 8 bit grayscale + alpha + PixelOperations.Instance.ToLa16Bytes( + this.configuration, + rowSpan, + rawScanlineSpan, + rowSpan.Length); + } } /// @@ -316,7 +310,7 @@ namespace SixLabors.ImageSharp.Formats.Png switch (this.bytesPerPixel) { case 4: - { + // 8 bit Rgba PixelOperations.Instance.ToRgba32Bytes( this.configuration, @@ -324,10 +318,9 @@ namespace SixLabors.ImageSharp.Formats.Png rawScanlineSpan, rowSpan.Length); break; - } case 3: - { + // 8 bit Rgb PixelOperations.Instance.ToRgb24Bytes( this.configuration, @@ -335,10 +328,9 @@ namespace SixLabors.ImageSharp.Formats.Png rawScanlineSpan, rowSpan.Length); break; - } case 8: - { + // 16 bit Rgba using (IMemoryOwner rgbaBuffer = this.memoryAllocator.Allocate(rowSpan.Length)) { @@ -358,10 +350,9 @@ namespace SixLabors.ImageSharp.Formats.Png } break; - } default: - { + // 16 bit Rgb using (IMemoryOwner rgbBuffer = this.memoryAllocator.Allocate(rowSpan.Length)) { @@ -380,7 +371,6 @@ namespace SixLabors.ImageSharp.Formats.Png } break; - } } } @@ -413,8 +403,6 @@ namespace SixLabors.ImageSharp.Formats.Png case PngColorType.GrayscaleWithAlpha: this.CollectGrayscaleBytes(rowSpan); break; - case PngColorType.Rgb: - case PngColorType.RgbWithAlpha: default: this.CollectTPixelBytes(rowSpan); break; @@ -424,6 +412,8 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// Apply the line filter for the raw scanline to enable better compression. /// + /// The filtered buffer. + /// Used for attempting optimized filtering. private void FilterPixelBytes(ref Span filter, ref Span attempt) { switch (this.options.FilterMethod) @@ -446,7 +436,6 @@ namespace SixLabors.ImageSharp.Formats.Png case PngFilterMethod.Paeth: PaethFilter.Encode(this.currentScanline.GetSpan(), this.previousScanline.GetSpan(), filter, this.bytesPerPixel, out int _); break; - case PngFilterMethod.Adaptive: default: this.ApplyOptimalFilteredScanline(ref filter, ref attempt); break; @@ -503,6 +492,8 @@ namespace SixLabors.ImageSharp.Formats.Png /// Applies all PNG filters to the given scanline and returns the filtered scanline that is deemed /// to be most compressible, using lowest total variation as proxy for compressibility. /// + /// The filtered buffer. + /// Used for attempting optimized filtering. private void ApplyOptimalFilteredScanline(ref Span filter, ref Span attempt) { // Palette images don't compress well with adaptive filtering. @@ -551,7 +542,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// The containing image data. private void WriteHeaderChunk(Stream stream) { - var header = new PngHeader( + PngHeader header = new( width: this.width, height: this.height, bitDepth: this.bitDepth, @@ -688,25 +679,24 @@ namespace SixLabors.ImageSharp.Formats.Png } int payloadLength = xmpData.Length + PngConstants.XmpKeyword.Length + iTxtHeaderSize; - using (IMemoryOwner owner = this.memoryAllocator.Allocate(payloadLength)) - { - Span payload = owner.GetSpan(); - PngConstants.XmpKeyword.CopyTo(payload); - int bytesWritten = PngConstants.XmpKeyword.Length; - - // Write the iTxt header (all zeros in this case). - Span iTxtHeader = payload[bytesWritten..]; - iTxtHeader[4] = 0; - iTxtHeader[3] = 0; - iTxtHeader[2] = 0; - iTxtHeader[1] = 0; - iTxtHeader[0] = 0; - bytesWritten += 5; - - // And the XMP data itself. - xmpData.CopyTo(payload[bytesWritten..]); - this.WriteChunk(stream, PngChunkType.InternationalText, payload); - } + + using IMemoryOwner owner = this.memoryAllocator.Allocate(payloadLength); + Span payload = owner.GetSpan(); + PngConstants.XmpKeyword.CopyTo(payload); + int bytesWritten = PngConstants.XmpKeyword.Length; + + // Write the iTxt header (all zeros in this case). + Span iTxtHeader = payload[bytesWritten..]; + iTxtHeader[4] = 0; + iTxtHeader[3] = 0; + iTxtHeader[2] = 0; + iTxtHeader[1] = 0; + iTxtHeader[0] = 0; + bytesWritten += 5; + + // And the XMP data itself. + xmpData.CopyTo(payload[bytesWritten..]); + this.WriteChunk(stream, PngChunkType.InternationalText, payload); } /// @@ -725,16 +715,15 @@ namespace SixLabors.ImageSharp.Formats.Png byte[] compressedData = this.GetZlibCompressedBytes(iccProfileBytes); int payloadLength = ColorProfileName.Length + compressedData.Length + 2; - using (IMemoryOwner owner = this.memoryAllocator.Allocate(payloadLength)) - { - Span outputBytes = owner.GetSpan(); - PngConstants.Encoding.GetBytes(ColorProfileName).CopyTo(outputBytes); - int bytesWritten = ColorProfileName.Length; - outputBytes[bytesWritten++] = 0; // Null separator. - outputBytes[bytesWritten++] = 0; // Compression. - compressedData.CopyTo(outputBytes[bytesWritten..]); - this.WriteChunk(stream, PngChunkType.EmbeddedColorProfile, outputBytes); - } + + using IMemoryOwner owner = this.memoryAllocator.Allocate(payloadLength); + Span outputBytes = owner.GetSpan(); + PngConstants.Encoding.GetBytes(ColorProfileName).CopyTo(outputBytes); + int bytesWritten = ColorProfileName.Length; + outputBytes[bytesWritten++] = 0; // Null separator. + outputBytes[bytesWritten++] = 0; // Compression. + compressedData.CopyTo(outputBytes[bytesWritten..]); + this.WriteChunk(stream, PngChunkType.EmbeddedColorProfile, outputBytes); } /// @@ -776,65 +765,59 @@ namespace SixLabors.ImageSharp.Formats.Png byte[] languageTag = PngConstants.LanguageEncoding.GetBytes(textData.LanguageTag); int payloadLength = keywordBytes.Length + textBytes.Length + translatedKeyword.Length + languageTag.Length + 5; - using (IMemoryOwner owner = this.memoryAllocator.Allocate(payloadLength)) - { - Span outputBytes = owner.GetSpan(); - keywordBytes.CopyTo(outputBytes); - int bytesWritten = keywordBytes.Length; - outputBytes[bytesWritten++] = 0; - if (textData.Value.Length > this.options.TextCompressionThreshold) - { - // Indicate that the text is compressed. - outputBytes[bytesWritten++] = 1; - } - else - { - outputBytes[bytesWritten++] = 0; - } - outputBytes[bytesWritten++] = 0; - languageTag.CopyTo(outputBytes[bytesWritten..]); - bytesWritten += languageTag.Length; - outputBytes[bytesWritten++] = 0; - translatedKeyword.CopyTo(outputBytes[bytesWritten..]); - bytesWritten += translatedKeyword.Length; - outputBytes[bytesWritten++] = 0; - textBytes.CopyTo(outputBytes[bytesWritten..]); - this.WriteChunk(stream, PngChunkType.InternationalText, outputBytes); - } - } - else - { + using IMemoryOwner owner = this.memoryAllocator.Allocate(payloadLength); + Span outputBytes = owner.GetSpan(); + keywordBytes.CopyTo(outputBytes); + int bytesWritten = keywordBytes.Length; + outputBytes[bytesWritten++] = 0; if (textData.Value.Length > this.options.TextCompressionThreshold) { - // Write zTXt chunk. - byte[] compressedData = this.GetZlibCompressedBytes(PngConstants.Encoding.GetBytes(textData.Value)); - int payloadLength = textData.Keyword.Length + compressedData.Length + 2; - using (IMemoryOwner owner = this.memoryAllocator.Allocate(payloadLength)) - { - Span outputBytes = owner.GetSpan(); - PngConstants.Encoding.GetBytes(textData.Keyword).CopyTo(outputBytes); - int bytesWritten = textData.Keyword.Length; - outputBytes[bytesWritten++] = 0; // Null separator. - outputBytes[bytesWritten++] = 0; // Compression. - compressedData.CopyTo(outputBytes[bytesWritten..]); - this.WriteChunk(stream, PngChunkType.CompressedText, outputBytes); - } + // Indicate that the text is compressed. + outputBytes[bytesWritten++] = 1; } else { - // Write tEXt chunk. - int payloadLength = textData.Keyword.Length + textData.Value.Length + 1; - using (IMemoryOwner owner = this.memoryAllocator.Allocate(payloadLength)) - { - Span outputBytes = owner.GetSpan(); - PngConstants.Encoding.GetBytes(textData.Keyword).CopyTo(outputBytes); - int bytesWritten = textData.Keyword.Length; - outputBytes[bytesWritten++] = 0; - PngConstants.Encoding.GetBytes(textData.Value).CopyTo(outputBytes[bytesWritten..]); - this.WriteChunk(stream, PngChunkType.Text, outputBytes); - } + outputBytes[bytesWritten++] = 0; } + + outputBytes[bytesWritten++] = 0; + languageTag.CopyTo(outputBytes[bytesWritten..]); + bytesWritten += languageTag.Length; + outputBytes[bytesWritten++] = 0; + translatedKeyword.CopyTo(outputBytes[bytesWritten..]); + bytesWritten += translatedKeyword.Length; + outputBytes[bytesWritten++] = 0; + textBytes.CopyTo(outputBytes[bytesWritten..]); + this.WriteChunk(stream, PngChunkType.InternationalText, outputBytes); + } + else if (textData.Value.Length > this.options.TextCompressionThreshold) + { + // Write zTXt chunk. + byte[] compressedData = this.GetZlibCompressedBytes(PngConstants.Encoding.GetBytes(textData.Value)); + int payloadLength = textData.Keyword.Length + compressedData.Length + 2; + + using IMemoryOwner owner = this.memoryAllocator.Allocate(payloadLength); + Span outputBytes = owner.GetSpan(); + PngConstants.Encoding.GetBytes(textData.Keyword).CopyTo(outputBytes); + int bytesWritten = textData.Keyword.Length; + outputBytes[bytesWritten++] = 0; // Null separator. + outputBytes[bytesWritten++] = 0; // Compression. + compressedData.CopyTo(outputBytes[bytesWritten..]); + this.WriteChunk(stream, PngChunkType.CompressedText, outputBytes); + } + else + { + // Write tEXt chunk. + int payloadLength = textData.Keyword.Length + textData.Value.Length + 1; + + using IMemoryOwner owner = this.memoryAllocator.Allocate(payloadLength); + Span outputBytes = owner.GetSpan(); + PngConstants.Encoding.GetBytes(textData.Keyword).CopyTo(outputBytes); + int bytesWritten = textData.Keyword.Length; + outputBytes[bytesWritten++] = 0; + PngConstants.Encoding.GetBytes(textData.Value).CopyTo(outputBytes[bytesWritten..]); + this.WriteChunk(stream, PngChunkType.Text, outputBytes); } } } @@ -846,15 +829,13 @@ namespace SixLabors.ImageSharp.Formats.Png /// The compressed byte array. private byte[] GetZlibCompressedBytes(byte[] dataBytes) { - using (var memoryStream = new MemoryStream()) + using MemoryStream memoryStream = new(); + using (ZlibDeflateStream deflateStream = new(this.memoryAllocator, memoryStream, this.options.CompressionLevel)) { - using (var deflateStream = new ZlibDeflateStream(this.memoryAllocator, memoryStream, this.options.CompressionLevel)) - { - deflateStream.Write(dataBytes); - } - - return memoryStream.ToArray(); + deflateStream.Write(dataBytes); } + + return memoryStream.ToArray(); } /// @@ -944,9 +925,9 @@ namespace SixLabors.ImageSharp.Formats.Png byte[] buffer; int bufferLength; - using (var memoryStream = new MemoryStream()) + using (MemoryStream memoryStream = new()) { - using (var deflateStream = new ZlibDeflateStream(this.memoryAllocator, memoryStream, this.options.CompressionLevel)) + using (ZlibDeflateStream deflateStream = new(this.memoryAllocator, memoryStream, this.options.CompressionLevel)) { if (this.options.InterlaceMethod == PngInterlaceMode.Adam7) { @@ -1174,7 +1155,7 @@ namespace SixLabors.ImageSharp.Formats.Png uint crc = Crc32.Calculate(this.buffer.AsSpan(4, 4)); // Write the type buffer - if (data != null && length > 0) + if (data.Length > 0 && length > 0) { stream.Write(data, offset, length); diff --git a/src/ImageSharp/Formats/Png/PngTextData.cs b/src/ImageSharp/Formats/Png/PngTextData.cs index 3d495cba6..7db26b60b 100644 --- a/src/ImageSharp/Formats/Png/PngTextData.cs +++ b/src/ImageSharp/Formats/Png/PngTextData.cs @@ -72,9 +72,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// True if the current left is equal to the parameter; otherwise, false. /// public static bool operator ==(PngTextData left, PngTextData right) - { - return left.Equals(right); - } + => left.Equals(right); /// /// Compares two objects. The result specifies whether the values @@ -90,9 +88,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// True if the current left is unequal to the parameter; otherwise, false. /// public static bool operator !=(PngTextData left, PngTextData right) - { - return !(left == right); - } + => !(left == right); /// /// Indicates whether this instance and a specified object are equal. @@ -105,9 +101,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// same value; otherwise, false. /// public override bool Equals(object obj) - { - return obj is PngTextData other && this.Equals(other); - } + => obj is PngTextData other && this.Equals(other); /// /// Returns the hash code for this instance. @@ -115,7 +109,8 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// A 32-bit signed integer that is the hash code for this instance. /// - public override int GetHashCode() => HashCode.Combine(this.Keyword, this.Value, this.LanguageTag, this.TranslatedKeyword); + public override int GetHashCode() + => HashCode.Combine(this.Keyword, this.Value, this.LanguageTag, this.TranslatedKeyword); /// /// Returns the fully qualified type name of this instance. @@ -123,7 +118,8 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// A containing a fully qualified type name. /// - public override string ToString() => $"PngTextData [ Name={this.Keyword}, Value={this.Value} ]"; + public override string ToString() + => $"PngTextData [ Name={this.Keyword}, Value={this.Value} ]"; /// /// Indicates whether the current object is equal to another object of the same type. @@ -133,11 +129,9 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// An object to compare with this object. public bool Equals(PngTextData other) - { - return this.Keyword.Equals(other.Keyword) - && this.Value.Equals(other.Value) - && this.LanguageTag.Equals(other.LanguageTag) - && this.TranslatedKeyword.Equals(other.TranslatedKeyword); - } + => this.Keyword.Equals(other.Keyword, StringComparison.OrdinalIgnoreCase) + && this.Value.Equals(other.Value, StringComparison.OrdinalIgnoreCase) + && this.LanguageTag.Equals(other.LanguageTag, StringComparison.OrdinalIgnoreCase) + && this.TranslatedKeyword.Equals(other.TranslatedKeyword, StringComparison.OrdinalIgnoreCase); } } diff --git a/src/ImageSharp/Formats/Png/PngThrowHelper.cs b/src/ImageSharp/Formats/Png/PngThrowHelper.cs index 7cf954f1d..c62775f87 100644 --- a/src/ImageSharp/Formats/Png/PngThrowHelper.cs +++ b/src/ImageSharp/Formats/Png/PngThrowHelper.cs @@ -2,6 +2,7 @@ // Licensed under the Six Labors Split License. using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; namespace SixLabors.ImageSharp.Formats.Png @@ -11,31 +12,40 @@ namespace SixLabors.ImageSharp.Formats.Png /// internal static class PngThrowHelper { + [DoesNotReturn] [MethodImpl(InliningOptions.ColdPath)] public static void ThrowInvalidImageContentException(string errorMessage, Exception innerException) => throw new InvalidImageContentException(errorMessage, innerException); + [DoesNotReturn] [MethodImpl(InliningOptions.ColdPath)] public static void ThrowNoHeader() => throw new InvalidImageContentException("PNG Image does not contain a header chunk"); + [DoesNotReturn] [MethodImpl(InliningOptions.ColdPath)] public static void ThrowNoData() => throw new InvalidImageContentException("PNG Image does not contain a data chunk"); + [DoesNotReturn] [MethodImpl(InliningOptions.ColdPath)] public static void ThrowMissingPalette() => throw new InvalidImageContentException("PNG Image does not contain a palette chunk"); + [DoesNotReturn] [MethodImpl(InliningOptions.ColdPath)] public static void ThrowInvalidChunkType() => throw new InvalidImageContentException("Invalid PNG data."); + [DoesNotReturn] [MethodImpl(InliningOptions.ColdPath)] public static void ThrowInvalidChunkType(string message) => throw new InvalidImageContentException(message); + [DoesNotReturn] [MethodImpl(InliningOptions.ColdPath)] public static void ThrowInvalidChunkCrc(string chunkTypeName) => throw new InvalidImageContentException($"CRC Error. PNG {chunkTypeName} chunk is corrupt!"); + [DoesNotReturn] [MethodImpl(InliningOptions.ColdPath)] public static void ThrowNotSupportedColor() => throw new NotSupportedException("Unsupported PNG color type"); + [DoesNotReturn] [MethodImpl(InliningOptions.ColdPath)] public static void ThrowUnknownFilter() => throw new InvalidImageContentException("Unknown filter type."); } diff --git a/src/ImageSharp/Formats/Tga/TgaEncoderCore.cs b/src/ImageSharp/Formats/Tga/TgaEncoderCore.cs index fa0ea6f90..5cfdf3022 100644 --- a/src/ImageSharp/Formats/Tga/TgaEncoderCore.cs +++ b/src/ImageSharp/Formats/Tga/TgaEncoderCore.cs @@ -5,6 +5,7 @@ using System; using System.Buffers; using System.Buffers.Binary; using System.IO; +using System.Numerics; using System.Runtime.CompilerServices; using System.Threading; using SixLabors.ImageSharp.Advanced; @@ -99,7 +100,7 @@ namespace SixLabors.ImageSharp.Formats.Tga imageDescriptor |= 0x1; } - var fileHeader = new TgaFileHeader( + TgaFileHeader fileHeader = new( idLength: 0, colorMapType: 0, imageType: imageType, @@ -158,8 +159,6 @@ namespace SixLabors.ImageSharp.Formats.Tga case TgaBitsPerPixel.Pixel32: this.Write32Bit(stream, pixels); break; - default: - break; } } @@ -181,7 +180,7 @@ namespace SixLabors.ImageSharp.Formats.Tga { TPixel currentPixel = pixelRow[x]; currentPixel.ToRgba32(ref color); - byte equalPixelCount = this.FindEqualPixels(pixelRow, x); + byte equalPixelCount = FindEqualPixels(pixelRow, x); if (equalPixelCount > 0) { @@ -193,7 +192,7 @@ namespace SixLabors.ImageSharp.Formats.Tga else { // Write Raw Packet (i.e., Non-Run-Length Encoded): - byte unEqualPixelCount = this.FindUnEqualPixels(pixelRow, x); + byte unEqualPixelCount = FindUnEqualPixels(pixelRow, x); stream.WriteByte(unEqualPixelCount); this.WritePixel(stream, currentPixel, color); x++; @@ -227,7 +226,7 @@ namespace SixLabors.ImageSharp.Formats.Tga break; case TgaBitsPerPixel.Pixel16: - var bgra5551 = new Bgra5551(color.ToVector4()); + Bgra5551 bgra5551 = new(color.ToVector4()); BinaryPrimitives.TryWriteInt16LittleEndian(this.buffer, (short)bgra5551.PackedValue); stream.WriteByte(this.buffer[0]); stream.WriteByte(this.buffer[1]); @@ -246,8 +245,6 @@ namespace SixLabors.ImageSharp.Formats.Tga stream.WriteByte(color.R); stream.WriteByte(color.A); break; - default: - break; } } @@ -258,7 +255,7 @@ namespace SixLabors.ImageSharp.Formats.Tga /// A pixel row of the image to encode. /// X coordinate to start searching for the same pixels. /// The number of equal pixels. - private byte FindEqualPixels(Span pixelRow, int xStart) + private static byte FindEqualPixels(Span pixelRow, int xStart) where TPixel : unmanaged, IPixel { byte equalPixelCount = 0; @@ -291,7 +288,7 @@ namespace SixLabors.ImageSharp.Formats.Tga /// A pixel row of the image to encode. /// X coordinate to start searching for the unequal pixels. /// The number of equal pixels. - private byte FindUnEqualPixels(Span pixelRow, int xStart) + private static byte FindUnEqualPixels(Span pixelRow, int xStart) where TPixel : unmanaged, IPixel { byte unEqualPixelCount = 0; @@ -419,12 +416,13 @@ namespace SixLabors.ImageSharp.Formats.Tga /// /// Convert the pixel values to grayscale using ITU-R Recommendation BT.709. /// + /// The type of pixel format. /// The pixel to get the luminance from. [MethodImpl(InliningOptions.ShortMethod)] public static int GetLuminance(TPixel sourcePixel) where TPixel : unmanaged, IPixel { - var vector = sourcePixel.ToVector4(); + Vector4 vector = sourcePixel.ToVector4(); return ColorNumerics.GetBT709Luminance(ref vector, 256); } } diff --git a/src/ImageSharp/Formats/Tga/TgaMetadata.cs b/src/ImageSharp/Formats/Tga/TgaMetadata.cs index a29eac21e..61b92d731 100644 --- a/src/ImageSharp/Formats/Tga/TgaMetadata.cs +++ b/src/ImageSharp/Formats/Tga/TgaMetadata.cs @@ -20,9 +20,7 @@ namespace SixLabors.ImageSharp.Formats.Tga /// /// The metadata to create an instance from. private TgaMetadata(TgaMetadata other) - { - this.BitsPerPixel = other.BitsPerPixel; - } + => this.BitsPerPixel = other.BitsPerPixel; /// /// Gets or sets the number of bits per pixel. @@ -30,9 +28,9 @@ namespace SixLabors.ImageSharp.Formats.Tga public TgaBitsPerPixel BitsPerPixel { get; set; } = TgaBitsPerPixel.Pixel24; /// - /// Gets or sets the the number of alpha bits per pixel. + /// Gets or sets the number of alpha bits per pixel. /// - public byte AlphaChannelBits { get; set; } = 0; + public byte AlphaChannelBits { get; set; } /// public IDeepCloneable DeepClone() => new TgaMetadata(this); diff --git a/src/ImageSharp/Formats/Tiff/Compression/Compressors/T4BitCompressor.cs b/src/ImageSharp/Formats/Tiff/Compression/Compressors/T4BitCompressor.cs index 11bc49f27..7c3ecc643 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/Compressors/T4BitCompressor.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/Compressors/T4BitCompressor.cs @@ -93,14 +93,14 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors uint codeLength; if (runLength <= 63) { - code = this.GetTermCode(runLength, out codeLength, isWhiteRun); + code = GetTermCode(runLength, out codeLength, isWhiteRun); this.WriteCode(codeLength, code, compressedData); x += (int)runLength; } else { - runLength = this.GetBestFittingMakeupRunLength(runLength); - code = this.GetMakeupCode(runLength, out codeLength, isWhiteRun); + runLength = GetBestFittingMakeupRunLength(runLength); + code = GetMakeupCode(runLength, out codeLength, isWhiteRun); this.WriteCode(codeLength, code, compressedData); x += (int)runLength; diff --git a/src/ImageSharp/Formats/Tiff/Compression/Compressors/T6BitCompressor.cs b/src/ImageSharp/Formats/Tiff/Compression/Compressors/T6BitCompressor.cs index 7e0b6042c..99b4a9fcc 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/Compressors/T6BitCompressor.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/Compressors/T6BitCompressor.cs @@ -61,12 +61,12 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors { Span row = pixelsAsGray.Slice(y * this.Width, this.Width); uint a0 = 0; - uint a1 = row[0] == 0 ? 0 : this.FindRunEnd(row, 0); - uint b1 = referenceLine[0] == 0 ? 0 : this.FindRunEnd(referenceLine, 0); + uint a1 = row[0] == 0 ? 0 : FindRunEnd(row, 0); + uint b1 = referenceLine[0] == 0 ? 0 : FindRunEnd(referenceLine, 0); while (true) { - uint b2 = this.FindRunEnd(referenceLine, b1); + uint b2 = FindRunEnd(referenceLine, b1); if (b2 < a1) { // Pass mode. @@ -85,7 +85,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors d = -(int)(a1 - b1); } - if ((d >= -3) && (d <= 3)) + if (d is >= -3 and <= 3) { // Vertical mode. (uint length, uint code) = VerticalCodes[d + 3]; @@ -97,7 +97,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors // Horizontal mode. this.WriteCode(3, 1, compressedData); - uint a2 = this.FindRunEnd(row, a1); + uint a2 = FindRunEnd(row, a1); if ((a0 + a1 == 0) || (row[(int)a0] != 0)) { this.WriteRun(a1 - a0, true, compressedData); @@ -119,9 +119,9 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors } byte thisPixel = row[(int)a0]; - a1 = this.FindRunEnd(row, a0, thisPixel); - b1 = this.FindRunEnd(referenceLine, a0, (byte)~thisPixel); - b1 = this.FindRunEnd(referenceLine, b1, thisPixel); + a1 = FindRunEnd(row, a0, thisPixel); + b1 = FindRunEnd(referenceLine, a0, (byte)~thisPixel); + b1 = FindRunEnd(referenceLine, b1, thisPixel); } // This row is now the reference line. @@ -149,14 +149,14 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors /// The index of the first pixel at or after /// that does not match , or the length of , /// whichever comes first. - private uint FindRunEnd(Span row, uint startIndex, byte? color = null) + private static uint FindRunEnd(Span row, uint startIndex, byte? color = null) { if (startIndex >= row.Length) { return (uint)row.Length; } - byte colorValue = color.GetValueOrDefault(row[(int)startIndex]); + byte colorValue = color ?? row[(int)startIndex]; for (int i = (int)startIndex; i < row.Length; i++) { if (row[i] != colorValue) @@ -188,13 +188,13 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors uint codeLength; while (runLength > 63) { - uint makeupLength = this.GetBestFittingMakeupRunLength(runLength); - code = this.GetMakeupCode(makeupLength, out codeLength, isWhiteRun); + uint makeupLength = GetBestFittingMakeupRunLength(runLength); + code = GetMakeupCode(makeupLength, out codeLength, isWhiteRun); this.WriteCode(codeLength, code, compressedData); runLength -= makeupLength; } - code = this.GetTermCode(runLength, out codeLength, isWhiteRun); + code = GetTermCode(runLength, out codeLength, isWhiteRun); this.WriteCode(codeLength, code, compressedData); } } diff --git a/src/ImageSharp/Formats/Tiff/Compression/Compressors/TiffCcittCompressor.cs b/src/ImageSharp/Formats/Tiff/Compression/Compressors/TiffCcittCompressor.cs index b1f5c85d9..8ff41ed07 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/Compressors/TiffCcittCompressor.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/Compressors/TiffCcittCompressor.cs @@ -195,7 +195,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors this.bitPosition = 0; } - private uint GetWhiteMakeupCode(uint runLength, out uint codeLength) + private static uint GetWhiteMakeupCode(uint runLength, out uint codeLength) { codeLength = 0; @@ -244,7 +244,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors return 0; } - private uint GetBlackMakeupCode(uint runLength, out uint codeLength) + private static uint GetBlackMakeupCode(uint runLength, out uint codeLength) { codeLength = 0; @@ -275,7 +275,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors return 0; } - private uint GetWhiteTermCode(uint runLength, out uint codeLength) + private static uint GetWhiteTermCode(uint runLength, out uint codeLength) { codeLength = 0; @@ -312,7 +312,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors return 0; } - private uint GetBlackTermCode(uint runLength, out uint codeLength) + private static uint GetBlackTermCode(uint runLength, out uint codeLength) { codeLength = 0; @@ -390,7 +390,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors /// /// A run length needing a makeup code /// The makeup length for . - protected uint GetBestFittingMakeupRunLength(uint runLength) + protected static uint GetBestFittingMakeupRunLength(uint runLength) { DebugGuard.MustBeGreaterThanOrEqualTo(runLength, MakeupRunLength[0], nameof(runLength)); @@ -402,7 +402,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors } } - return MakeupRunLength[MakeupRunLength.Length - 1]; + return MakeupRunLength[^1]; } /// @@ -413,14 +413,14 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors /// If true, the run is of white pixels. /// If false the run is of black pixels /// The terminating code for a run of length - protected uint GetTermCode(uint runLength, out uint codeLength, bool isWhiteRun) + protected static uint GetTermCode(uint runLength, out uint codeLength, bool isWhiteRun) { if (isWhiteRun) { - return this.GetWhiteTermCode(runLength, out codeLength); + return GetWhiteTermCode(runLength, out codeLength); } - return this.GetBlackTermCode(runLength, out codeLength); + return GetBlackTermCode(runLength, out codeLength); } /// @@ -431,14 +431,14 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors /// If true, the run is of white pixels. /// If false the run is of black pixels /// The makeup code for a run of length - protected uint GetMakeupCode(uint runLength, out uint codeLength, bool isWhiteRun) + protected static uint GetMakeupCode(uint runLength, out uint codeLength, bool isWhiteRun) { if (isWhiteRun) { - return this.GetWhiteMakeupCode(runLength, out codeLength); + return GetWhiteMakeupCode(runLength, out codeLength); } - return this.GetBlackMakeupCode(runLength, out codeLength); + return GetBlackMakeupCode(runLength, out codeLength); } /// @@ -494,12 +494,12 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors /// /// Writes a image compressed with CCITT T6 to the stream. /// - /// The pixels as 8-bit gray array. + /// The pixels as 8-bit gray array. /// The strip height. - public override void CompressStrip(Span pixelsAsGray, int height) + public override void CompressStrip(Span rows, int height) { - DebugGuard.IsTrue(pixelsAsGray.Length / height == this.Width, "Values must be equals"); - DebugGuard.IsTrue(pixelsAsGray.Length % height == 0, "Values must be equals"); + DebugGuard.IsTrue(rows.Length / height == this.Width, "Values must be equals"); + DebugGuard.IsTrue(rows.Length % height == 0, "Values must be equals"); this.compressedDataBuffer.Clear(); Span compressedData = this.compressedDataBuffer.GetSpan(); @@ -507,7 +507,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors this.bytePosition = 0; this.bitPosition = 0; - this.CompressStrip(pixelsAsGray, height, compressedData); + this.CompressStrip(rows, height, compressedData); // Write the compressed data to the stream. int bytesToWrite = this.bitPosition != 0 ? this.bytePosition + 1 : this.bytePosition; diff --git a/src/ImageSharp/Formats/Tiff/TiffBitsPerSample.cs b/src/ImageSharp/Formats/Tiff/TiffBitsPerSample.cs index 2412d166b..d277af900 100644 --- a/src/ImageSharp/Formats/Tiff/TiffBitsPerSample.cs +++ b/src/ImageSharp/Formats/Tiff/TiffBitsPerSample.cs @@ -10,31 +10,6 @@ namespace SixLabors.ImageSharp.Formats.Tiff /// public readonly struct TiffBitsPerSample : IEquatable { - /// - /// The bits for the channel 0. - /// - public readonly ushort Channel0; - - /// - /// The bits for the channel 1. - /// - public readonly ushort Channel1; - - /// - /// The bits for the channel 2. - /// - public readonly ushort Channel2; - - /// - /// The bits for the alpha channel. - /// - public readonly ushort Channel3; - - /// - /// The number of channels. - /// - public readonly byte Channels; - /// /// Initializes a new instance of the struct. /// @@ -56,6 +31,53 @@ namespace SixLabors.ImageSharp.Formats.Tiff this.Channels += (byte)(this.Channel3 != 0 ? 1 : 0); } + /// + /// Gets the bits for the channel 0. + /// + public readonly ushort Channel0 { get; } + + /// + /// Gets the bits for the channel 1. + /// + public readonly ushort Channel1 { get; } + + /// + /// Gets the bits for the channel 2. + /// + public readonly ushort Channel2 { get; } + + /// + /// Gets the bits for the alpha channel. + /// + public readonly ushort Channel3 { get; } + + /// + /// Gets the number of channels. + /// + public readonly byte Channels { get; } + + /// + /// Checks whether two structures are equal. + /// + /// The left hand operand. + /// The right hand operand. + /// + /// True if the parameter is equal to the parameter; + /// otherwise, false. + /// + public static bool operator ==(TiffBitsPerSample left, TiffBitsPerSample right) => left.Equals(right); + + /// + /// Checks whether two structures are not equal. + /// + /// The left hand operand. + /// The right hand operand. + /// + /// True if the parameter is not equal to the parameter; + /// otherwise, false. + /// + public static bool operator !=(TiffBitsPerSample left, TiffBitsPerSample right) => !(left == right); + /// /// Tries to parse a ushort array and convert it into a TiffBitsPerSample struct. /// diff --git a/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs b/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs index 16071001d..9ccd4416f 100644 --- a/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs +++ b/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs @@ -73,7 +73,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff /// private const TiffPhotometricInterpretation DefaultPhotometricInterpretation = TiffPhotometricInterpretation.Rgb; - private readonly List<(long, uint)> frameMarkers = new List<(long, uint)>(); + private readonly List<(long, uint)> frameMarkers = new(); /// /// Initializes a new instance of the class. @@ -148,15 +148,15 @@ namespace SixLabors.ImageSharp.Formats.Tiff // Make sure, the Encoder options makes sense in combination with each other. this.SanitizeAndSetEncoderOptions(bitsPerPixel, image.PixelType.BitsPerPixel, photometricInterpretation, compression, predictor); - using var writer = new TiffStreamWriter(stream); - long ifdMarker = this.WriteHeader(writer); + using TiffStreamWriter writer = new(stream); + long ifdMarker = WriteHeader(writer); Image metadataImage = image; foreach (ImageFrame frame in image.Frames) { cancellationToken.ThrowIfCancellationRequested(); - var subfileType = (TiffNewSubfileType)(frame.Metadata.ExifProfile?.GetValue(ExifTag.SubfileType)?.Value ?? (int)TiffNewSubfileType.FullImage); + TiffNewSubfileType subfileType = (TiffNewSubfileType)(frame.Metadata.ExifProfile?.GetValue(ExifTag.SubfileType)?.Value ?? (int)TiffNewSubfileType.FullImage); ifdMarker = this.WriteFrame(writer, frame, image.Metadata, metadataImage, ifdMarker); metadataImage = null; @@ -178,7 +178,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff /// /// The marker to write the first IFD offset. /// - public long WriteHeader(TiffStreamWriter writer) + public static long WriteHeader(TiffStreamWriter writer) { writer.Write(ByteOrderMarker); writer.Write(TiffConstants.HeaderMagicNumber); @@ -214,7 +214,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff this.compressionLevel, this.HorizontalPredictor == TiffPredictor.Horizontal ? this.HorizontalPredictor.Value : TiffPredictor.None); - var entriesCollector = new TiffEncoderEntriesCollector(); + TiffEncoderEntriesCollector entriesCollector = new(); using TiffBaseColorWriter colorWriter = TiffColorWriterFactory.Create( this.PhotometricInterpretation, frame, @@ -224,7 +224,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff entriesCollector, (int)this.BitsPerPixel); - int rowsPerStrip = this.CalcRowsPerStrip(frame.Height, colorWriter.BytesPerRow, this.CompressionType); + int rowsPerStrip = CalcRowsPerStrip(frame.Height, colorWriter.BytesPerRow, this.CompressionType); colorWriter.Write(compressor, rowsPerStrip); @@ -248,7 +248,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff /// The number of bytes per row. /// The compression used. /// Number of rows per strip. - private int CalcRowsPerStrip(int height, int bytesPerRow, TiffCompression? compression) + private static int CalcRowsPerStrip(int height, int bytesPerRow, TiffCompression? compression) { DebugGuard.MustBeGreaterThan(height, 0, nameof(height)); DebugGuard.MustBeGreaterThan(bytesPerRow, 0, nameof(bytesPerRow)); @@ -290,7 +290,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff } uint dataOffset = (uint)writer.Position + (uint)(6 + (entries.Count * 12)); - var largeDataBlocks = new List(); + List largeDataBlocks = new(); entries.Sort((a, b) => (ushort)a.Tag - (ushort)b.Tag); @@ -440,13 +440,6 @@ namespace SixLabors.ImageSharp.Formats.Tiff } public static bool IsOneBitCompression(TiffCompression? compression) - { - if (compression is TiffCompression.Ccitt1D or TiffCompression.CcittGroup3Fax or TiffCompression.CcittGroup4Fax) - { - return true; - } - - return false; - } + => compression is TiffCompression.Ccitt1D or TiffCompression.CcittGroup3Fax or TiffCompression.CcittGroup4Fax; } } diff --git a/src/ImageSharp/Formats/Tiff/Writers/TiffStreamWriter.cs b/src/ImageSharp/Formats/Tiff/Writers/TiffStreamWriter.cs index 667f75be4..d35d16948 100644 --- a/src/ImageSharp/Formats/Tiff/Writers/TiffStreamWriter.cs +++ b/src/ImageSharp/Formats/Tiff/Writers/TiffStreamWriter.cs @@ -28,7 +28,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Writers /// /// Gets a value indicating whether the architecture is little-endian. /// - public bool IsLittleEndian => BitConverter.IsLittleEndian; + public static bool IsLittleEndian => BitConverter.IsLittleEndian; /// /// Gets the current position within the stream. @@ -75,7 +75,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Writers /// The two-byte unsigned integer to write. public void Write(ushort value) { - if (this.IsLittleEndian) + if (IsLittleEndian) { BinaryPrimitives.WriteUInt16LittleEndian(this.buffer, value); } @@ -93,7 +93,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Writers /// The four-byte unsigned integer to write. public void Write(uint value) { - if (this.IsLittleEndian) + if (IsLittleEndian) { BinaryPrimitives.WriteUInt32LittleEndian(this.buffer, value); } diff --git a/src/ImageSharp/Formats/Webp/BitReader/Vp8BitReader.cs b/src/ImageSharp/Formats/Webp/BitReader/Vp8BitReader.cs index 52e3907e9..24761213e 100644 --- a/src/ImageSharp/Formats/Webp/BitReader/Vp8BitReader.cs +++ b/src/ImageSharp/Formats/Webp/BitReader/Vp8BitReader.cs @@ -133,7 +133,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.BitReader uint split = this.range >> 1; ulong value = this.value >> pos; ulong mask = (split - value) >> 31; // -1 or 0 - this.bits -= 1; + this.bits--; this.range = (this.range + (uint)mask) | 1; this.value -= ((split + 1) & mask) << pos; @@ -189,7 +189,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.BitReader { ulong inBits = BinaryPrimitives.ReadUInt64LittleEndian(this.Data.Memory.Span.Slice((int)this.pos, 8)); this.pos += BitsCount >> 3; - ulong bits = this.ByteSwap64(inBits); + ulong bits = ByteSwap64(inBits); bits >>= 64 - BitsCount; this.value = bits | (this.value << BitsCount); this.bits += BitsCount; @@ -221,7 +221,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.BitReader } [MethodImpl(InliningOptions.ShortMethod)] - private ulong ByteSwap64(ulong x) + private static ulong ByteSwap64(ulong x) { x = ((x & 0xffffffff00000000ul) >> 32) | ((x & 0x00000000fffffffful) << 32); x = ((x & 0xffff0000ffff0000ul) >> 16) | ((x & 0x0000ffff0000fffful) << 16); diff --git a/src/ImageSharp/Formats/Webp/BitWriter/BitWriterBase.cs b/src/ImageSharp/Formats/Webp/BitWriter/BitWriterBase.cs index 428403f60..ed41c29fe 100644 --- a/src/ImageSharp/Formats/Webp/BitWriter/BitWriterBase.cs +++ b/src/ImageSharp/Formats/Webp/BitWriter/BitWriterBase.cs @@ -5,7 +5,6 @@ using System; using System.Buffers.Binary; using System.IO; using SixLabors.ImageSharp.Metadata.Profiles.Exif; -using SixLabors.ImageSharp.Metadata.Profiles.Icc; using SixLabors.ImageSharp.Metadata.Profiles.Xmp; namespace SixLabors.ImageSharp.Formats.Webp.BitWriter @@ -38,6 +37,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.BitWriter /// Initializes a new instance of the class. /// Used internally for cloning. /// + /// The byte buffer. private protected BitWriterBase(byte[] buffer) => this.buffer = buffer; public byte[] Buffer => this.buffer; @@ -102,12 +102,10 @@ namespace SixLabors.ImageSharp.Formats.Webp.BitWriter /// /// The metadata profile bytes. /// The metadata chunk size in bytes. - protected uint MetadataChunkSize(byte[] metadataBytes) + protected static uint MetadataChunkSize(byte[] metadataBytes) { uint metaSize = (uint)metadataBytes.Length; - uint metaChunkSize = WebpConstants.ChunkHeaderSize + metaSize + (metaSize & 1); - - return metaChunkSize; + return WebpConstants.ChunkHeaderSize + metaSize + (metaSize & 1); } /// @@ -115,12 +113,10 @@ namespace SixLabors.ImageSharp.Formats.Webp.BitWriter /// /// The alpha chunk bytes. /// The alpha data chunk size in bytes. - protected uint AlphaChunkSize(Span alphaBytes) + protected static uint AlphaChunkSize(Span alphaBytes) { uint alphaSize = (uint)alphaBytes.Length + 1; - uint alphaChunkSize = WebpConstants.ChunkHeaderSize + alphaSize + (alphaSize & 1); - - return alphaChunkSize; + return WebpConstants.ChunkHeaderSize + alphaSize + (alphaSize & 1); } /// diff --git a/src/ImageSharp/Formats/Webp/BitWriter/Vp8BitWriter.cs b/src/ImageSharp/Formats/Webp/BitWriter/Vp8BitWriter.cs index 81cb9cc24..a218d50f4 100644 --- a/src/ImageSharp/Formats/Webp/BitWriter/Vp8BitWriter.cs +++ b/src/ImageSharp/Formats/Webp/BitWriter/Vp8BitWriter.cs @@ -433,27 +433,27 @@ namespace SixLabors.ImageSharp.Formats.Webp.BitWriter { isVp8X = true; exifBytes = exifProfile.ToByteArray(); - riffSize += this.MetadataChunkSize(exifBytes); + riffSize += MetadataChunkSize(exifBytes); } if (xmpProfile != null) { isVp8X = true; xmpBytes = xmpProfile.Data; - riffSize += this.MetadataChunkSize(xmpBytes); + riffSize += MetadataChunkSize(xmpBytes); } if (iccProfile != null) { isVp8X = true; iccProfileBytes = iccProfile.ToByteArray(); - riffSize += this.MetadataChunkSize(iccProfileBytes); + riffSize += MetadataChunkSize(iccProfileBytes); } if (hasAlpha) { isVp8X = true; - riffSize += this.AlphaChunkSize(alphaData); + riffSize += AlphaChunkSize(alphaData); } if (isVp8X) diff --git a/src/ImageSharp/Formats/Webp/BitWriter/Vp8LBitWriter.cs b/src/ImageSharp/Formats/Webp/BitWriter/Vp8LBitWriter.cs index 78494004d..cb4d6d654 100644 --- a/src/ImageSharp/Formats/Webp/BitWriter/Vp8LBitWriter.cs +++ b/src/ImageSharp/Formats/Webp/BitWriter/Vp8LBitWriter.cs @@ -150,21 +150,21 @@ namespace SixLabors.ImageSharp.Formats.Webp.BitWriter { isVp8X = true; exifBytes = exifProfile.ToByteArray(); - riffSize += this.MetadataChunkSize(exifBytes); + riffSize += MetadataChunkSize(exifBytes); } if (xmpProfile != null) { isVp8X = true; xmpBytes = xmpProfile.Data; - riffSize += this.MetadataChunkSize(xmpBytes); + riffSize += MetadataChunkSize(xmpBytes); } if (iccProfile != null) { isVp8X = true; iccBytes = iccProfile.ToByteArray(); - riffSize += this.MetadataChunkSize(iccBytes); + riffSize += MetadataChunkSize(iccBytes); } if (isVp8X) diff --git a/src/ImageSharp/Formats/Webp/Lossless/Vp8LEncoder.cs b/src/ImageSharp/Formats/Webp/Lossless/Vp8LEncoder.cs index a09cdb8bc..6e7cbd5e8 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/Vp8LEncoder.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/Vp8LEncoder.cs @@ -344,7 +344,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless foreach (CrunchConfig crunchConfig in crunchConfigs) { bgra.CopyTo(encodedData); - bool useCache = true; + const bool useCache = true; this.UsePalette = crunchConfig.EntropyIdx is EntropyIx.Palette or EntropyIx.PaletteAndSpatial; this.UseSubtractGreenTransform = crunchConfig.EntropyIdx is EntropyIx.SubGreen or EntropyIx.SpatialSubGreen; this.UsePredictorTransform = crunchConfig.EntropyIdx is EntropyIx.Spatial or EntropyIx.SpatialSubGreen; @@ -418,7 +418,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless if (isFirstConfig || this.bitWriter.NumBytes() < bestSize) { bestSize = this.bitWriter.NumBytes(); - this.BitWriterSwap(ref this.bitWriter, ref bitWriterBest); + BitWriterSwap(ref this.bitWriter, ref bitWriterBest); } // Reset the bit writer for the following iteration if any. @@ -430,7 +430,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless isFirstConfig = false; } - this.BitWriterSwap(ref bitWriterBest, ref this.bitWriter); + BitWriterSwap(ref bitWriterBest, ref this.bitWriter); } /// @@ -485,7 +485,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless EntropyIx entropyIdx = this.AnalyzeEntropy(bgra, width, height, usePalette, this.PaletteSize, this.TransformBits, out redAndBlueAlwaysZero); bool doNotCache = false; - var crunchConfigs = new List(); + List crunchConfigs = new(); if (this.method == WebpEncodingMethod.BestQuality && this.quality == 100) { @@ -540,7 +540,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless Span bgra = this.EncodedData.GetSpan(); int histogramImageXySize = LosslessUtils.SubSampleSize(width, this.HistoBits) * LosslessUtils.SubSampleSize(height, this.HistoBits); ushort[] histogramSymbols = new ushort[histogramImageXySize]; - var huffTree = new HuffmanTree[3 * WebpConstants.CodeLengthCodes]; + HuffmanTree[] huffTree = new HuffmanTree[3 * WebpConstants.CodeLengthCodes]; for (int i = 0; i < huffTree.Length; i++) { huffTree[i] = default; @@ -583,8 +583,8 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless Vp8LBackwardRefs refsTmp = this.Refs[refsBest.Equals(this.Refs[0]) ? 1 : 0]; this.bitWriter.Reset(bwInit); - var tmpHisto = new Vp8LHistogram(cacheBits); - var histogramImage = new List(histogramImageXySize); + Vp8LHistogram tmpHisto = new(cacheBits); + List histogramImage = new(histogramImageXySize); for (int i = 0; i < histogramImageXySize; i++) { histogramImage.Add(new Vp8LHistogram(cacheBits)); @@ -596,7 +596,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless // Create Huffman bit lengths and codes for each histogram image. int histogramImageSize = histogramImage.Count; int bitArraySize = 5 * histogramImageSize; - var huffmanCodes = new HuffmanTreeCode[bitArraySize]; + HuffmanTreeCode[] huffmanCodes = new HuffmanTreeCode[bitArraySize]; for (int i = 0; i < huffmanCodes.Length; i++) { huffmanCodes[i] = default; @@ -657,7 +657,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless } } - var tokens = new HuffmanTreeToken[maxTokens]; + HuffmanTreeToken[] tokens = new HuffmanTreeToken[maxTokens]; for (int i = 0; i < tokens.Length; i++) { tokens[i] = new HuffmanTreeToken(); @@ -767,13 +767,13 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless int cacheBits = 0; ushort[] histogramSymbols = new ushort[1]; // Only one tree, one symbol. - var huffmanCodes = new HuffmanTreeCode[5]; + HuffmanTreeCode[] huffmanCodes = new HuffmanTreeCode[5]; for (int i = 0; i < huffmanCodes.Length; i++) { huffmanCodes[i] = default; } - var huffTree = new HuffmanTree[3UL * WebpConstants.CodeLengthCodes]; + HuffmanTree[] huffTree = new HuffmanTree[3UL * WebpConstants.CodeLengthCodes]; for (int i = 0; i < huffTree.Length; i++) { huffTree[i] = default; @@ -794,7 +794,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless refsTmp1, refsTmp2); - var histogramImage = new List() + List histogramImage = new() { new(cacheBits) }; @@ -819,7 +819,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless } } - var tokens = new HuffmanTreeToken[maxTokens]; + HuffmanTreeToken[] tokens = new HuffmanTreeToken[maxTokens]; for (int i = 0; i < tokens.Length; i++) { tokens[i] = new HuffmanTreeToken(); @@ -842,8 +842,8 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless int count = 0; Span symbols = this.scratch.AsSpan(0, 2); symbols.Clear(); - int maxBits = 8; - int maxSymbol = 1 << maxBits; + const int maxBits = 8; + const int maxSymbol = 1 << maxBits; // Check whether it's a small tree. for (int i = 0; i < huffmanCode.NumSymbols && count < 3; i++) @@ -896,7 +896,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless int i; byte[] codeLengthBitDepth = new byte[WebpConstants.CodeLengthCodes]; short[] codeLengthBitDepthSymbols = new short[WebpConstants.CodeLengthCodes]; - var huffmanCode = new HuffmanTreeCode + HuffmanTreeCode huffmanCode = new() { NumSymbols = WebpConstants.CodeLengthCodes, CodeLengths = codeLengthBitDepth, @@ -1099,7 +1099,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless uint pix = currentRow[x]; uint pixDiff = LosslessUtils.SubPixels(pix, pixPrev); pixPrev = pix; - if (pixDiff == 0 || (prevRow != null && pix == prevRow[x])) + if (pixDiff == 0 || (prevRow.Length > 0 && pix == prevRow[x])) { continue; } @@ -1147,7 +1147,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless histo[(int)HistoIx.HistoBluePred * 256]++; histo[(int)HistoIx.HistoAlphaPred * 256]++; - var bitEntropy = new Vp8LBitEntropy(); + Vp8LBitEntropy bitEntropy = new(); for (int j = 0; j < (int)HistoIx.HistoTotal; j++) { bitEntropy.Init(); @@ -1239,7 +1239,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless private bool AnalyzeAndCreatePalette(ReadOnlySpan bgra, int width, int height) { Span palette = this.Palette.Memory.Span; - this.PaletteSize = this.GetColorPalette(bgra, width, height, palette); + this.PaletteSize = GetColorPalette(bgra, width, height, palette); if (this.PaletteSize > WebpConstants.MaxPaletteSize) { this.PaletteSize = 0; @@ -1265,9 +1265,9 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless /// The image height. /// The span to store the palette into. /// The number of palette entries. - private int GetColorPalette(ReadOnlySpan bgra, int width, int height, Span palette) + private static int GetColorPalette(ReadOnlySpan bgra, int width, int height, Span palette) { - var colors = new HashSet(); + HashSet colors = new(); for (int y = 0; y < height; y++) { ReadOnlySpan bgraRow = bgra.Slice(y * width, width); @@ -1547,7 +1547,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless /// True, if the palette has no monotonous deltas. private static bool PaletteHasNonMonotonousDeltas(Span palette, int numColors) { - uint predict = 0x000000; + const uint predict = 0x000000; byte signFound = 0x00; for (int i = 0; i < numColors; i++) { @@ -1637,7 +1637,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless // Create Huffman trees. bool[] bufRle = new bool[maxNumSymbols]; - var huffTree = new HuffmanTree[3 * maxNumSymbols]; + HuffmanTree[] huffTree = new HuffmanTree[3 * maxNumSymbols]; for (int i = 0; i < huffTree.Length; i++) { huffTree[i] = default; @@ -1665,7 +1665,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless private static uint PaletteColorDistance(uint col1, uint col2) { uint diff = LosslessUtils.SubPixels(col1, col2); - uint moreWeightForRGBThanForAlpha = 9; + const uint moreWeightForRGBThanForAlpha = 9; uint score = PaletteComponentDistance((diff >> 0) & 0xff); score += PaletteComponentDistance((diff >> 8) & 0xff); score += PaletteComponentDistance((diff >> 16) & 0xff); @@ -1730,7 +1730,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless } [MethodImpl(InliningOptions.ShortMethod)] - private void BitWriterSwap(ref Vp8LBitWriter src, ref Vp8LBitWriter dst) + private static void BitWriterSwap(ref Vp8LBitWriter src, ref Vp8LBitWriter dst) { Vp8LBitWriter tmp = src; src = dst; diff --git a/src/ImageSharp/Formats/Webp/Lossless/WebpLosslessDecoder.cs b/src/ImageSharp/Formats/Webp/Lossless/WebpLosslessDecoder.cs index fafd5b49c..b90dbf4db 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/WebpLosslessDecoder.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/WebpLosslessDecoder.cs @@ -96,7 +96,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless public void Decode(Buffer2D pixels, int width, int height) where TPixel : unmanaged, IPixel { - using (var decoder = new Vp8LDecoder(width, height, this.memoryAllocator)) + using (Vp8LDecoder decoder = new(width, height, this.memoryAllocator)) { this.DecodeImageStream(decoder, width, height, true); this.DecodeImageData(decoder, decoder.Pixels.Memory.Span); @@ -169,7 +169,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless decoder.Metadata.ColorCacheSize = 0; } - this.UpdateDecoder(decoder, transformXSize, transformYSize); + UpdateDecoder(decoder, transformXSize, transformYSize); if (isLevel0) { // level 0 complete. @@ -207,7 +207,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless public void DecodeImageData(Vp8LDecoder decoder, Span pixelData) { - int lastPixel = 0; + const int lastPixel = 0; int width = decoder.Width; int height = decoder.Height; int row = lastPixel / width; @@ -233,7 +233,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless if (hTreeGroup[0].IsTrivialCode) { pixelData[decodedPixels] = hTreeGroup[0].LiteralArb; - this.AdvanceByOne(ref col, ref row, width, colorCache, ref decodedPixels, pixelData, ref lastCached); + AdvanceByOne(ref col, ref row, width, colorCache, ref decodedPixels, pixelData, ref lastCached); continue; } @@ -248,7 +248,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless if (code == PackedNonLiteralCode) { - this.AdvanceByOne(ref col, ref row, width, colorCache, ref decodedPixels, pixelData, ref lastCached); + AdvanceByOne(ref col, ref row, width, colorCache, ref decodedPixels, pixelData, ref lastCached); continue; } } @@ -283,7 +283,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless pixelData[decodedPixels] = (uint)(((byte)alpha << 24) | ((byte)red << 16) | ((byte)code << 8) | (byte)blue); } - this.AdvanceByOne(ref col, ref row, width, colorCache, ref decodedPixels, pixelData, ref lastCached); + AdvanceByOne(ref col, ref row, width, colorCache, ref decodedPixels, pixelData, ref lastCached); } else if (code < lenCodeLimit) { @@ -333,7 +333,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless } pixelData[decodedPixels] = colorCache.Lookup(key); - this.AdvanceByOne(ref col, ref row, width, colorCache, ref decodedPixels, pixelData, ref lastCached); + AdvanceByOne(ref col, ref row, width, colorCache, ref decodedPixels, pixelData, ref lastCached); } else { @@ -342,7 +342,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless } } - private void AdvanceByOne(ref int col, ref int row, int width, ColorCache colorCache, ref int decodedPixels, Span pixelData, ref int lastCached) + private static void AdvanceByOne(ref int col, ref int row, int width, ColorCache colorCache, ref int decodedPixels, Span pixelData, ref int lastCached) { col++; decodedPixels++; @@ -414,8 +414,8 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless } int tableSize = TableSize[colorCacheBits]; - var huffmanTables = new HuffmanCode[numHTreeGroups * tableSize]; - var hTreeGroups = new HTreeGroup[numHTreeGroups]; + HuffmanCode[] huffmanTables = new HuffmanCode[numHTreeGroups * tableSize]; + HTreeGroup[] hTreeGroups = new HTreeGroup[numHTreeGroups]; Span huffmanTable = huffmanTables.AsSpan(); int[] codeLengths = new int[maxAlphabetSize]; for (int i = 0; i < numHTreeGroupsMax; i++) @@ -488,7 +488,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless hTreeGroup.UsePackedTable = !hTreeGroup.IsTrivialCode && maxBits < HuffmanUtils.HuffmanPackedBits; if (hTreeGroup.UsePackedTable) { - this.BuildPackedTable(hTreeGroup); + BuildPackedTable(hTreeGroup); } } @@ -546,9 +546,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless this.ReadHuffmanCodeLengths(table, codeLengthCodeLengths, alphabetSize, codeLengths); } - int size = HuffmanUtils.BuildHuffmanTable(table, HuffmanUtils.HuffmanTableBits, codeLengths, alphabetSize); - - return size; + return HuffmanUtils.BuildHuffmanTable(table, HuffmanUtils.HuffmanTableBits, codeLengths, alphabetSize); } private void ReadHuffmanCodeLengths(Span table, int[] codeLengthCodeLengths, int numSymbols, int[] codeLengths) @@ -622,8 +620,8 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless /// Vp8LDecoder where the transformations will be stored. private void ReadTransformation(int xSize, int ySize, Vp8LDecoder decoder) { - var transformType = (Vp8LTransformType)this.bitReader.ReadValue(2); - var transform = new Vp8LTransform(transformType, xSize, ySize); + Vp8LTransformType transformType = (Vp8LTransformType)this.bitReader.ReadValue(2); + Vp8LTransform transform = new(transformType, xSize, ySize); // Each transform is allowed to be used only once. foreach (Vp8LTransform decoderTransform in decoder.Transforms) @@ -643,11 +641,23 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless // The transform data contains color table size and the entries in the color table. // 8 bit value for color table size. uint numColors = this.bitReader.ReadValue(8) + 1; - int bits = numColors > 16 ? 0 - : numColors > 4 ? 1 - : numColors > 2 ? 2 - : 3; - transform.Bits = bits; + if (numColors > 16) + { + transform.Bits = 0; + } + else if (numColors > 4) + { + transform.Bits = 1; + } + else if (numColors > 2) + { + transform.Bits = 2; + } + else + { + transform.Bits = 3; + } + using (IMemoryOwner colorMap = this.DecodeImageStream(decoder, (int)numColors, 1, false)) { int finalNumColors = 1 << (8 >> transform.Bits); @@ -660,15 +670,13 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless case Vp8LTransformType.PredictorTransform: case Vp8LTransformType.CrossColorTransform: - { + // The first 3 bits of prediction data define the block width and height in number of bits. transform.Bits = (int)this.bitReader.ReadValue(3) + 2; int blockWidth = LosslessUtils.SubSampleSize(transform.XSize, transform.Bits); int blockHeight = LosslessUtils.SubSampleSize(transform.YSize, transform.Bits); - IMemoryOwner transformData = this.DecodeImageStream(decoder, blockWidth, blockHeight, false); - transform.Data = transformData; + transform.Data = this.DecodeImageStream(decoder, blockWidth, blockHeight, false); break; - } } decoder.Transforms.Add(transform); @@ -687,8 +695,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless for (int i = transforms.Count - 1; i >= 0; i--) { Vp8LTransform transform = transforms[i]; - Vp8LTransformType transformType = transform.TransformType; - switch (transformType) + switch (transform.TransformType) { case Vp8LTransformType.PredictorTransform: using (IMemoryOwner output = memoryAllocator.Allocate(pixelData.Length, AllocationOptions.Clean)) @@ -806,7 +813,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless dec.ExtractPalettedAlphaRows(row > lastRow ? lastRow : row); } - private void UpdateDecoder(Vp8LDecoder decoder, int width, int height) + private static void UpdateDecoder(Vp8LDecoder decoder, int width, int height) { int numBits = decoder.Metadata.HuffmanSubSampleBits; decoder.Width = width; @@ -831,7 +838,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless return code.Value; } - private void BuildPackedTable(HTreeGroup hTreeGroup) + private static void BuildPackedTable(HTreeGroup hTreeGroup) { for (uint code = 0; code < HuffmanUtils.HuffmanPackedTableSize; code++) { @@ -859,6 +866,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless /// Decodes the next Huffman code from the bit-stream. /// FillBitWindow() needs to be called at minimum every second call to ReadSymbol, in order to pre-fetch enough bits. /// + /// The Huffman table. private uint ReadSymbol(Span table) { uint val = (uint)this.bitReader.PrefetchBits(); diff --git a/src/ImageSharp/Formats/Webp/Lossy/Vp8EncIterator.cs b/src/ImageSharp/Formats/Webp/Lossy/Vp8EncIterator.cs index 0043d6d28..3092e01e3 100644 --- a/src/ImageSharp/Formats/Webp/Lossy/Vp8EncIterator.cs +++ b/src/ImageSharp/Formats/Webp/Lossy/Vp8EncIterator.cs @@ -34,7 +34,9 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy /// private readonly int predsWidth; - // Array to record the position of the top sample to pass to the prediction functions. + /// + /// Array to record the position of the top sample to pass to the prediction functions. + /// private readonly byte[] vp8TopLeftI4 = { 17, 21, 25, 29, @@ -46,9 +48,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy private int currentMbIdx; private int nzIdx; - - private int predIdx; - private int yTopIdx; private int uvTopIdx; @@ -69,7 +68,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy this.yTopIdx = 0; this.uvTopIdx = 0; this.predsWidth = (4 * mbw) + 1; - this.predIdx = this.predsWidth; + this.PredIdx = this.predsWidth; this.YuvIn = new byte[WebpConstants.Bps * 16]; this.YuvOut = new byte[WebpConstants.Bps * 16]; this.YuvOut2 = new byte[WebpConstants.Bps * 16]; @@ -85,7 +84,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy this.Scratch3 = new int[16]; // To match the C initial values of the reference implementation, initialize all with 204. - byte defaultInitVal = 204; + const byte defaultInitVal = 204; this.YuvIn.AsSpan().Fill(defaultInitVal); this.YuvOut.AsSpan().Fill(defaultInitVal); this.YuvOut2.AsSpan().Fill(defaultInitVal); @@ -160,7 +159,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy /// /// Gets the current start index of the intra mode predictors. /// - public int PredIdx => this.predIdx; + public int PredIdx { get; private set; } /// /// Gets the non-zero pattern. @@ -238,7 +237,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy public void Init() => this.Reset(); - public void InitFilter() + public static void InitFilter() { // TODO: add support for autofilter } @@ -299,9 +298,9 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy Span yuvIn = this.YuvIn.AsSpan(YOffEnc); Span uIn = this.YuvIn.AsSpan(UOffEnc); Span vIn = this.YuvIn.AsSpan(VOffEnc); - this.ImportBlock(ySrc, yStride, yuvIn, w, h, 16); - this.ImportBlock(uSrc, uvStride, uIn, uvw, uvh, 8); - this.ImportBlock(vSrc, uvStride, vIn, uvw, uvh, 8); + ImportBlock(ySrc, yStride, yuvIn, w, h, 16); + ImportBlock(uSrc, uvStride, uIn, uvw, uvh, 8); + ImportBlock(vSrc, uvStride, vIn, uvw, uvh, 8); if (!importBoundarySamples) { @@ -331,9 +330,9 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy vLeft[0] = v[uvStartIdx - 1 - uvStride]; } - this.ImportLine(y[(yStartIdx - 1)..], yStride, yLeft[1..], h, 16); - this.ImportLine(u[(uvStartIdx - 1)..], uvStride, uLeft[1..], uvh, 8); - this.ImportLine(v[(uvStartIdx - 1)..], uvStride, vLeft[1..], uvh, 8); + ImportLine(y[(yStartIdx - 1)..], yStride, yLeft[1..], h, 16); + ImportLine(u[(uvStartIdx - 1)..], uvStride, uLeft[1..], uvh, 8); + ImportLine(v[(uvStartIdx - 1)..], uvStride, vLeft[1..], uvh, 8); } Span yTop = this.YTop.AsSpan(this.yTopIdx, 16); @@ -344,9 +343,9 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy } else { - this.ImportLine(y[(yStartIdx - yStride)..], 1, yTop, w, 16); - this.ImportLine(u[(uvStartIdx - uvStride)..], 1, this.UvTop.AsSpan(this.uvTopIdx, 8), uvw, 8); - this.ImportLine(v[(uvStartIdx - uvStride)..], 1, this.UvTop.AsSpan(this.uvTopIdx + 8, 8), uvw, 8); + ImportLine(y[(yStartIdx - yStride)..], 1, yTop, w, 16); + ImportLine(u[(uvStartIdx - uvStride)..], 1, this.UvTop.AsSpan(this.uvTopIdx, 8), uvw, 8); + ImportLine(v[(uvStartIdx - uvStride)..], 1, this.UvTop.AsSpan(this.uvTopIdx + 8, 8), uvw, 8); } } @@ -386,7 +385,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy public int MbAnalyzeBestIntra16Mode() { - int maxMode = MaxIntra16Mode; + const int maxMode = MaxIntra16Mode; int mode; int bestAlpha = DefaultAlpha; int bestMode = 0; @@ -394,7 +393,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy this.MakeLuma16Preds(); for (mode = 0; mode < maxMode; mode++) { - var histo = new Vp8Histogram(); + Vp8Histogram histo = new(); histo.CollectHistogram(this.YuvIn.AsSpan(YOffEnc), this.YuvP.AsSpan(Vp8Encoding.Vp8I16ModeOffsets[mode]), 0, 16); int alpha = histo.GetAlpha(); if (alpha > bestAlpha) @@ -411,15 +410,15 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy public int MbAnalyzeBestIntra4Mode(int bestAlpha) { byte[] modes = new byte[16]; - int maxMode = MaxIntra4Mode; - var totalHisto = new Vp8Histogram(); + const int maxMode = MaxIntra4Mode; + Vp8Histogram totalHisto = new(); int curHisto = 0; this.StartI4(); do { int mode; int bestModeAlpha = DefaultAlpha; - var histos = new Vp8Histogram[2]; + Vp8Histogram[] histos = new Vp8Histogram[2]; Span src = this.YuvIn.AsSpan(YOffEnc + WebpLookupTables.Vp8Scan[this.I4]); this.MakeIntra4Preds(); @@ -459,13 +458,13 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy int bestAlpha = DefaultAlpha; int smallestAlpha = 0; int bestMode = 0; - int maxMode = MaxUvMode; + const int maxMode = MaxUvMode; int mode; this.MakeChroma8Preds(); for (mode = 0; mode < maxMode; ++mode) { - var histo = new Vp8Histogram(); + Vp8Histogram histo = new(); histo.CollectHistogram(this.YuvIn.AsSpan(UOffEnc), this.YuvP.AsSpan(Vp8Encoding.Vp8UvModeOffsets[mode]), 16, 16 + 4 + 4); int alpha = histo.GetAlpha(); if (alpha > bestAlpha) @@ -487,7 +486,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy public void SetIntra16Mode(int mode) { - Span preds = this.Preds.AsSpan(this.predIdx); + Span preds = this.Preds.AsSpan(this.PredIdx); for (int y = 0; y < 4; y++) { preds[..4].Fill((byte)mode); @@ -500,7 +499,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy public void SetIntra4Mode(byte[] modes) { int modesIdx = 0; - int predIdx = this.predIdx; + int predIdx = this.PredIdx; for (int y = 4; y > 0; y--) { modes.AsSpan(modesIdx, 4).CopyTo(this.Preds.AsSpan(predIdx)); @@ -542,7 +541,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy public short[] GetCostModeI4(byte[] modes) { int predsWidth = this.predsWidth; - int predIdx = this.predIdx; + int predIdx = this.PredIdx; int x = this.I4 & 3; int y = this.I4 >> 2; int left = x == 0 ? this.Preds[predIdx + (y * predsWidth) - 1] : modes[this.I4 - 1]; @@ -635,7 +634,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy { this.currentMbIdx++; this.nzIdx++; - this.predIdx += 4; + this.PredIdx += 4; this.yTopIdx += 16; this.uvTopIdx += 16; } @@ -772,35 +771,35 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy Span leftNz = this.LeftNz; // Top-Y - topNz[0] = this.Bit(tnz, 12); - topNz[1] = this.Bit(tnz, 13); - topNz[2] = this.Bit(tnz, 14); - topNz[3] = this.Bit(tnz, 15); + topNz[0] = Bit(tnz, 12); + topNz[1] = Bit(tnz, 13); + topNz[2] = Bit(tnz, 14); + topNz[3] = Bit(tnz, 15); // Top-U - topNz[4] = this.Bit(tnz, 18); - topNz[5] = this.Bit(tnz, 19); + topNz[4] = Bit(tnz, 18); + topNz[5] = Bit(tnz, 19); // Top-V - topNz[6] = this.Bit(tnz, 22); - topNz[7] = this.Bit(tnz, 23); + topNz[6] = Bit(tnz, 22); + topNz[7] = Bit(tnz, 23); // DC - topNz[8] = this.Bit(tnz, 24); + topNz[8] = Bit(tnz, 24); // left-Y - leftNz[0] = this.Bit(lnz, 3); - leftNz[1] = this.Bit(lnz, 7); - leftNz[2] = this.Bit(lnz, 11); - leftNz[3] = this.Bit(lnz, 15); + leftNz[0] = Bit(lnz, 3); + leftNz[1] = Bit(lnz, 7); + leftNz[2] = Bit(lnz, 11); + leftNz[3] = Bit(lnz, 15); // left-U - leftNz[4] = this.Bit(lnz, 17); - leftNz[5] = this.Bit(lnz, 19); + leftNz[4] = Bit(lnz, 17); + leftNz[5] = Bit(lnz, 19); // left-V - leftNz[6] = this.Bit(lnz, 21); - leftNz[7] = this.Bit(lnz, 23); + leftNz[6] = Bit(lnz, 21); + leftNz[7] = Bit(lnz, 23); // left-DC is special, iterated separately. } @@ -826,7 +825,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy this.Nz[this.nzIdx] = nz; } - private void ImportBlock(Span src, int srcStride, Span dst, int w, int h, int size) + private static void ImportBlock(Span src, int srcStride, Span dst, int w, int h, int size) { int dstIdx = 0; int srcIdx = 0; @@ -852,7 +851,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy } } - private void ImportLine(Span src, int srcStride, Span dst, int len, int totalLen) + private static void ImportLine(Span src, int srcStride, Span dst, int len, int totalLen) { int i; int srcIdx = 0; @@ -892,7 +891,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy this.nzIdx = 1; // note: in reference source nz starts at -1. this.yTopIdx = 0; this.uvTopIdx = 0; - this.predIdx = this.predsWidth + (y * 4 * this.predsWidth); + this.PredIdx = this.predsWidth + (y * 4 * this.predsWidth); this.InitLeft(); } @@ -931,7 +930,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy this.TopDerr.AsSpan().Clear(); } - private int Bit(uint nz, int n) => (nz & (1 << n)) != 0 ? 1 : 0; + private static int Bit(uint nz, int n) => (nz & (1 << n)) != 0 ? 1 : 0; /// /// Set count down. diff --git a/src/ImageSharp/Formats/Webp/Lossy/Vp8Encoder.cs b/src/ImageSharp/Formats/Webp/Lossy/Vp8Encoder.cs index 9dbbccbc7..12b2ea7dc 100644 --- a/src/ImageSharp/Formats/Webp/Lossy/Vp8Encoder.cs +++ b/src/ImageSharp/Formats/Webp/Lossy/Vp8Encoder.cs @@ -123,10 +123,22 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy this.filterStrength = Numerics.Clamp(filterStrength, 0, 100); this.spatialNoiseShaping = Numerics.Clamp(spatialNoiseShaping, 0, 100); this.alphaCompression = alphaCompression; - this.rdOptLevel = method is WebpEncodingMethod.BestQuality ? Vp8RdLevel.RdOptTrellisAll - : method >= WebpEncodingMethod.Level5 ? Vp8RdLevel.RdOptTrellis - : method >= WebpEncodingMethod.Level3 ? Vp8RdLevel.RdOptBasic - : Vp8RdLevel.RdOptNone; + if (method is WebpEncodingMethod.BestQuality) + { + this.rdOptLevel = Vp8RdLevel.RdOptTrellisAll; + } + else if (method >= WebpEncodingMethod.Level5) + { + this.rdOptLevel = Vp8RdLevel.RdOptTrellis; + } + else if (method >= WebpEncodingMethod.Level3) + { + this.rdOptLevel = Vp8RdLevel.RdOptBasic; + } + else + { + this.rdOptLevel = Vp8RdLevel.RdOptNone; + } int pixelCount = width * height; this.Mbw = (width + 15) >> 4; @@ -142,7 +154,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy this.TopDerr = new sbyte[this.Mbw * 4]; // TODO: make partition_limit configurable? - int limit = 100; // original code: limit = 100 - config->partition_limit; + const int limit = 100; // original code: limit = 100 - config->partition_limit; this.maxI4HeaderBits = 256 * 16 * 16 * limit * limit / (100 * 100); // ... modulated with a quadratic curve. @@ -307,7 +319,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy int yStride = width; int uvStride = (yStride + 1) >> 1; - var it = new Vp8EncIterator(this.YTop, this.UvTop, this.Nz, this.MbInfo, this.Preds, this.TopDerr, this.Mbw, this.Mbh); + Vp8EncIterator it = new(this.YTop, this.UvTop, this.Nz, this.MbInfo, this.Preds, this.TopDerr, this.Mbw, this.Mbh); int[] alphas = new int[WebpConstants.MaxAlpha + 1]; this.alpha = this.MacroBlockAnalysis(width, height, it, y, u, v, yStride, uvStride, alphas, out this.uvAlpha); int totalMb = this.Mbw * this.Mbw; @@ -327,7 +339,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy // Extract and encode alpha channel data, if present. int alphaDataSize = 0; bool alphaCompressionSucceeded = false; - using var alphaEncoder = new AlphaEncoder(); + using AlphaEncoder alphaEncoder = new(); Span alphaData = Span.Empty; if (hasAlpha) { @@ -344,9 +356,9 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy // Stats-collection loop. this.StatLoop(width, height, yStride, uvStride); it.Init(); - it.InitFilter(); - var info = new Vp8ModeScore(); - var residual = new Vp8Residual(); + Vp8EncIterator.InitFilter(); + Vp8ModeScore info = new(); + Vp8Residual residual = new(); do { bool dontUseSkip = !this.Proba.UseSkipProba; @@ -399,17 +411,21 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy /// This is used for deciding optimal probabilities. It also modifies the /// quantizer value if some target (size, PSNR) was specified. /// + /// The image width. + /// The image height. + /// The y-luminance stride. + /// The uv stride. private void StatLoop(int width, int height, int yStride, int uvStride) { - int targetSize = 0; // TODO: target size is hardcoded. - float targetPsnr = 0.0f; // TODO: targetPsnr is hardcoded. - bool doSearch = targetSize > 0 || targetPsnr > 0; + const int targetSize = 0; // TODO: target size is hardcoded. + const float targetPsnr = 0.0f; // TODO: targetPsnr is hardcoded. + const bool doSearch = targetSize > 0 || targetPsnr > 0; bool fastProbe = (this.method == 0 || this.method == WebpEncodingMethod.Level3) && !doSearch; int numPassLeft = this.entropyPasses; Vp8RdLevel rdOpt = this.method >= WebpEncodingMethod.Level3 || doSearch ? Vp8RdLevel.RdOptBasic : Vp8RdLevel.RdOptNone; int nbMbs = this.Mbw * this.Mbh; - var stats = new PassStats(targetSize, targetPsnr, QMin, QMax, this.quality); + PassStats stats = new(targetSize, targetPsnr, QMin, QMax, this.quality); this.Proba.ResetTokenStats(); // Fast mode: quick analysis pass over few mbs. Better than nothing. @@ -450,7 +466,10 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy // If no target size: just do several pass without changing 'q' if (doSearch) { + // Unreachable due to hardcoding above. +#pragma warning disable CS0162 // Unreachable code detected stats.ComputeNextQ(); +#pragma warning restore CS0162 // Unreachable code detected if (MathF.Abs(stats.Dq) <= DqLimit) { break; @@ -474,7 +493,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy Span y = this.Y.GetSpan(); Span u = this.U.GetSpan(); Span v = this.V.GetSpan(); - var it = new Vp8EncIterator(this.YTop, this.UvTop, this.Nz, this.MbInfo, this.Preds, this.TopDerr, this.Mbw, this.Mbh); + Vp8EncIterator it = new(this.YTop, this.UvTop, this.Nz, this.MbInfo, this.Preds, this.TopDerr, this.Mbw, this.Mbh); long size = 0; long sizeP0 = 0; long distortion = 0; @@ -482,7 +501,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy it.Init(); this.SetLoopParams(stats.Q); - var info = new Vp8ModeScore(); + Vp8ModeScore info = new(); do { info.Clear(); @@ -540,7 +559,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy // this '>> 3' accounts for some inverse WHT scaling int delta = (dqm.MaxEdge * dqm.Y2.Q[1]) >> 3; - int level = this.FilterStrengthFromDelta(this.FilterHeader.Sharpness, delta); + int level = FilterStrengthFromDelta(this.FilterHeader.Sharpness, delta); if (level > dqm.FStrength) { dqm.FStrength = level; @@ -757,8 +776,8 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy private void SetupFilterStrength() { - int filterSharpness = 0; // TODO: filterSharpness is hardcoded - int filterType = 1; // TODO: filterType is hardcoded + const int filterSharpness = 0; // TODO: filterSharpness is hardcoded + const int filterType = 1; // TODO: filterType is hardcoded // level0 is in [0..500]. Using '-f 50' as filter_strength is mid-filtering. int level0 = 5 * this.filterStrength; @@ -768,11 +787,22 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy // We focus on the quantization of AC coeffs. int qstep = WebpLookupTables.AcTable[Numerics.Clamp(m.Quant, 0, 127)] >> 2; - int baseStrength = this.FilterStrengthFromDelta(this.FilterHeader.Sharpness, qstep); + int baseStrength = FilterStrengthFromDelta(this.FilterHeader.Sharpness, qstep); // Segments with lower complexity ('beta') will be less filtered. int f = baseStrength * level0 / (256 + m.Beta); - m.FStrength = f < WebpConstants.FilterStrengthCutoff ? 0 : f > 63 ? 63 : f; + if (f < WebpConstants.FilterStrengthCutoff) + { + m.FStrength = 0; + } + else if (f > 63) + { + m.FStrength = 63; + } + else + { + m.FStrength = f; + } } // We record the initial strength (mainly for the case of 1-segment only). @@ -1027,10 +1057,12 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy /// Same as CodeResiduals, but doesn't actually write anything. /// Instead, it just records the event distribution. /// + /// The iterator. + /// The score accumulator. private void RecordResiduals(Vp8EncIterator it, Vp8ModeScore rd) { int x, y, ch; - var residual = new Vp8Residual(); + Vp8Residual residual = new(); bool i16 = it.CurrentMacroBlockInfo.MacroBlockType == Vp8MacroBlockType.I16X16; it.NzToBytes(); @@ -1096,6 +1128,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy /// is around q=75. Internally, our "good" middle is around c=50. So we /// map accordingly using linear piece-wise function /// + /// The compression level. [MethodImpl(InliningOptions.ShortMethod)] private static double QualityToCompression(double c) { @@ -1107,13 +1140,11 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy // this power-law: quant ~= compression ^ 1/3. This law holds well for // low quant. Finer modeling for high-quant would make use of AcTable[] // more explicitly. - double v = Math.Pow(linearC, 1 / 3.0d); - - return v; + return (double)Math.Pow(linearC, 1 / 3.0d); } [MethodImpl(InliningOptions.ShortMethod)] - private int FilterStrengthFromDelta(int sharpness, int delta) + private static int FilterStrengthFromDelta(int sharpness, int delta) { int pos = delta < WebpConstants.MaxDelzaSize ? delta : WebpConstants.MaxDelzaSize - 1; return WebpLookupTables.LevelsFromDelta[sharpness, pos]; diff --git a/src/ImageSharp/Formats/Webp/Lossy/WebpLossyDecoder.cs b/src/ImageSharp/Formats/Webp/Lossy/WebpLossyDecoder.cs index b290ee58b..e913e9898 100644 --- a/src/ImageSharp/Formats/Webp/Lossy/WebpLossyDecoder.cs +++ b/src/ImageSharp/Formats/Webp/Lossy/WebpLossyDecoder.cs @@ -72,7 +72,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy // Paragraph 9.2: color space and clamp type follow. sbyte colorSpace = (sbyte)this.bitReader.ReadValue(1); sbyte clampType = (sbyte)this.bitReader.ReadValue(1); - var pictureHeader = new Vp8PictureHeader() + Vp8PictureHeader pictureHeader = new() { Width = (uint)width, Height = (uint)height, @@ -83,10 +83,10 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy }; // Paragraph 9.3: Parse the segment header. - var proba = new Vp8Proba(); + Vp8Proba proba = new(); Vp8SegmentHeader vp8SegmentHeader = this.ParseSegmentHeader(proba); - using (var decoder = new Vp8Decoder(info.Vp8FrameHeader, pictureHeader, vp8SegmentHeader, proba, this.memoryAllocator)) + using (Vp8Decoder decoder = new(info.Vp8FrameHeader, pictureHeader, vp8SegmentHeader, proba, this.memoryAllocator)) { Vp8Io io = InitializeVp8Io(decoder, pictureHeader); @@ -111,7 +111,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy if (info.Features?.Alpha == true) { - using (var alphaDecoder = new AlphaDecoder( + using (AlphaDecoder alphaDecoder = new( width, height, alphaData, @@ -120,7 +120,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy this.configuration)) { alphaDecoder.Decode(); - this.DecodePixelValues(width, height, decoder.Pixels.Memory.Span, pixels, alphaDecoder.Alpha); + DecodePixelValues(width, height, decoder.Pixels.Memory.Span, pixels, alphaDecoder.Alpha); } } else @@ -146,7 +146,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy } } - private void DecodePixelValues(int width, int height, Span pixelData, Buffer2D decodedPixels, IMemoryOwner alpha) + private static void DecodePixelValues(int width, int height, Span pixelData, Buffer2D decodedPixels, IMemoryOwner alpha) where TPixel : unmanaged, IPixel { TPixel color = default; @@ -187,7 +187,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy } // Prepare for next scanline. - this.InitScanline(dec); + InitScanline(dec); // Reconstruct, filter and emit the row. this.ProcessRow(dec, io); @@ -222,9 +222,27 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy if (!block.IsI4x4) { // Hardcoded 16x16 intra-mode decision tree. - int yMode = this.bitReader.GetBit(156) != 0 ? - this.bitReader.GetBit(128) != 0 ? (int)IntraPredictionMode.TrueMotion : (int)IntraPredictionMode.HPrediction : - this.bitReader.GetBit(163) != 0 ? (int)IntraPredictionMode.VPrediction : (int)IntraPredictionMode.DcPrediction; + int yMode; + if (this.bitReader.GetBit(156) != 0) + { + if (this.bitReader.GetBit(128) != 0) + { + yMode = (int)IntraPredictionMode.TrueMotion; + } + else + { + yMode = (int)IntraPredictionMode.HPrediction; + } + } + else if (this.bitReader.GetBit(163) != 0) + { + yMode = (int)IntraPredictionMode.VPrediction; + } + else + { + yMode = (int)IntraPredictionMode.DcPrediction; + } + block.Modes[0] = (byte)yMode; for (int i = 0; i < left.Length; i++) { @@ -258,12 +276,29 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy } // Hardcoded UVMode decision tree. - block.UvMode = (byte)(this.bitReader.GetBit(142) == 0 ? 0 : - this.bitReader.GetBit(114) == 0 ? 2 : - this.bitReader.GetBit(183) != 0 ? 1 : 3); + if (this.bitReader.GetBit(142) == 0) + { + // Hardcoded UVMode decision tree. + block.UvMode = 0; + } + else if (this.bitReader.GetBit(114) == 0) + { + // Hardcoded UVMode decision tree. + block.UvMode = 2; + } + else if (this.bitReader.GetBit(183) != 0) + { + // Hardcoded UVMode decision tree. + block.UvMode = 1; + } + else + { + // Hardcoded UVMode decision tree. + block.UvMode = 3; + } } - private void InitScanline(Vp8Decoder dec) + private static void InitScanline(Vp8Decoder dec) { Vp8MacroBlock left = dec.LeftMacroBlock; left.NoneZeroAcDcCoeffs = 0; @@ -279,7 +314,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy private void ProcessRow(Vp8Decoder dec, Vp8Io io) { this.ReconstructRow(dec); - this.FinishRow(dec, io); + FinishRow(dec, io); } private void ReconstructRow(Vp8Decoder dec) @@ -404,8 +439,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy { int offset = yOff + WebpConstants.Scan[n]; Span dst = yuv[offset..]; - byte lumaMode = block.Modes[n]; - switch (lumaMode) + switch (block.Modes[n]) { case 0: LossyUtils.DC4(dst, yuv, offset); @@ -439,14 +473,13 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy break; } - this.DoTransform(bits, coeffs.AsSpan(n * 16), dst, this.scratch); + DoTransform(bits, coeffs.AsSpan(n * 16), dst, this.scratch); } } else { // 16x16 - int mode = CheckMode(mbx, mby, block.Modes[0]); - switch (mode) + switch (CheckMode(mbx, mby, block.Modes[0])) { case 0: LossyUtils.DC16(yDst, yuv, yOff); @@ -475,15 +508,14 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy { for (int n = 0; n < 16; ++n, bits <<= 2) { - this.DoTransform(bits, coeffs.AsSpan(n * 16), yDst[WebpConstants.Scan[n]..], this.scratch); + DoTransform(bits, coeffs.AsSpan(n * 16), yDst[WebpConstants.Scan[n]..], this.scratch); } } } // Chroma uint bitsUv = block.NonZeroUv; - int chromaMode = CheckMode(mbx, mby, block.UvMode); - switch (chromaMode) + switch (CheckMode(mbx, mby, block.UvMode)) { case 0: LossyUtils.DC8uv(uDst, yuv, uOff); @@ -515,8 +547,8 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy break; } - this.DoUVTransform(bitsUv, coeffs.AsSpan(16 * 16), uDst, this.scratch); - this.DoUVTransform(bitsUv >> 8, coeffs.AsSpan(20 * 16), vDst, this.scratch); + DoUVTransform(bitsUv, coeffs.AsSpan(16 * 16), uDst, this.scratch); + DoUVTransform(bitsUv >> 8, coeffs.AsSpan(20 * 16), vDst, this.scratch); // Stash away top samples for next block. if (mby < dec.MbHeight - 1) @@ -544,16 +576,16 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy } } - private void FilterRow(Vp8Decoder dec) + private static void FilterRow(Vp8Decoder dec) { int mby = dec.MbY; for (int mbx = dec.TopLeftMbX; mbx < dec.BottomRightMbX; ++mbx) { - this.DoFilter(dec, mbx, mby); + DoFilter(dec, mbx, mby); } } - private void DoFilter(Vp8Decoder dec, int mbx, int mby) + private static void DoFilter(Vp8Decoder dec, int mbx, int mby) { int yBps = dec.CacheYStride; Vp8FilterInfo filterInfo = dec.FilterInfo[mbx]; @@ -620,7 +652,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy } } - private void FinishRow(Vp8Decoder dec, Vp8Io io) + private static void FinishRow(Vp8Decoder dec, Vp8Io io) { int extraYRows = WebpConstants.FilterExtraRows[(int)dec.Filter]; int ySize = extraYRows * dec.CacheYStride; @@ -635,7 +667,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy if (filterRow) { - this.FilterRow(dec); + FilterRow(dec); } int yStart = mby * 16; @@ -669,7 +701,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy io.MbY = yStart; io.MbW = io.Width; io.MbH = yEnd - yStart; - this.EmitRgb(dec, io); + EmitRgb(dec, io); } // Rotate top samples if needed. @@ -681,7 +713,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy } } - private int EmitRgb(Vp8Decoder dec, Vp8Io io) + private static int EmitRgb(Vp8Decoder dec, Vp8Io io) { Span buf = dec.Pixels.Memory.Span; int numLinesOut = io.MbH; // a priori guess. @@ -693,7 +725,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy Span tmpVBuffer = dec.TmpVBuffer.Memory.Span; Span topU = tmpUBuffer; Span topV = tmpVBuffer; - int bpp = 3; + const int bpp = 3; int bufferStride = bpp * io.Width; int dstStartIdx = io.MbY * bufferStride; Span dst = buf[dstStartIdx..]; @@ -753,7 +785,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy return numLinesOut; } - private void DoTransform(uint bits, Span src, Span dst, Span scratch) + private static void DoTransform(uint bits, Span src, Span dst, Span scratch) { switch (bits >> 30) { @@ -769,7 +801,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy } } - private void DoUVTransform(uint bits, Span src, Span dst, Span scratch) + private static void DoUVTransform(uint bits, Span src, Span dst, Span scratch) { // any non-zero coeff at all? if ((bits & 0xff) > 0) @@ -845,7 +877,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy // Parse DC short[] dc = new short[16]; int ctx = (int)(mb.NoneZeroDcCoeffs + leftMb.NoneZeroDcCoeffs); - int nz = this.GetCoeffs(br, bands[1], ctx, q.Y2Mat, 0, dc); + int nz = GetCoeffs(br, bands[1], ctx, q.Y2Mat, 0, dc); mb.NoneZeroDcCoeffs = leftMb.NoneZeroDcCoeffs = (uint)(nz > 0 ? 1 : 0); if (nz > 1) { @@ -876,7 +908,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy for (int x = 0; x < 4; x++) { int ctx = l + (tnz & 1); - int nz = this.GetCoeffs(br, acProba, ctx, q.Y1Mat, first, dst.AsSpan(dstOffset)); + int nz = GetCoeffs(br, acProba, ctx, q.Y1Mat, first, dst.AsSpan(dstOffset)); l = nz > first ? 1 : 0; tnz = (byte)((tnz >> 1) | (l << 7)); nzCoeffs = NzCodeBits(nzCoeffs, nz, dst[dstOffset] != 0 ? 1 : 0); @@ -903,7 +935,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy for (int x = 0; x < 2; x++) { int ctx = l + (tnz & 1); - int nz = this.GetCoeffs(br, bands[2], ctx, q.UvMat, 0, dst.AsSpan(dstOffset)); + int nz = GetCoeffs(br, bands[2], ctx, q.UvMat, 0, dst.AsSpan(dstOffset)); l = nz > 0 ? 1 : 0; tnz = (byte)((tnz >> 1) | (l << 3)); nzCoeffs = NzCodeBits(nzCoeffs, nz, dst[dstOffset] != 0 ? 1 : 0); @@ -929,7 +961,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy return (nonZeroY | nonZeroUv) == 0; } - private int GetCoeffs(Vp8BitReader br, Vp8BandProbas[] prob, int ctx, int[] dq, int n, Span coeffs) + private static int GetCoeffs(Vp8BitReader br, Vp8BandProbas[] prob, int ctx, int[] dq, int n, Span coeffs) { // Returns the position of the last non-zero coeff plus one. Vp8ProbaArray p = prob[n].Probabilities[ctx]; @@ -960,7 +992,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy } else { - v = this.GetLargeValue(br, p.Probabilities); + v = GetLargeValue(br, p.Probabilities); p = prob[n + 1].Probabilities[2]; } @@ -971,7 +1003,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy return 16; } - private int GetLargeValue(Vp8BitReader br, byte[] p) + private static int GetLargeValue(Vp8BitReader br, byte[] p) { // See section 13 - 2: http://tools.ietf.org/html/rfc6386#section-13.2 int v; @@ -986,53 +1018,50 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy v = 3 + br.GetBit(p[5]); } } - else + else if (br.GetBit(p[6]) == 0) { - if (br.GetBit(p[6]) == 0) + if (br.GetBit(p[7]) == 0) { - if (br.GetBit(p[7]) == 0) - { - v = 5 + br.GetBit(159); - } - else - { - v = 7 + (2 * br.GetBit(165)); - v += br.GetBit(145); - } + v = 5 + br.GetBit(159); } else { - int bit1 = br.GetBit(p[8]); - int bit0 = br.GetBit(p[9 + bit1]); - int cat = (2 * bit1) + bit0; - v = 0; - byte[] tab = null; - switch (cat) - { - case 0: - tab = WebpConstants.Cat3; - break; - case 1: - tab = WebpConstants.Cat4; - break; - case 2: - tab = WebpConstants.Cat5; - break; - case 3: - tab = WebpConstants.Cat6; - break; - default: - WebpThrowHelper.ThrowImageFormatException("VP8 parsing error"); - break; - } - - for (int i = 0; i < tab.Length; i++) - { - v += v + br.GetBit(tab[i]); - } + v = 7 + (2 * br.GetBit(165)); + v += br.GetBit(145); + } + } + else + { + int bit1 = br.GetBit(p[8]); + int bit0 = br.GetBit(p[9 + bit1]); + int cat = (2 * bit1) + bit0; + v = 0; + byte[] tab = null; + switch (cat) + { + case 0: + tab = WebpConstants.Cat3; + break; + case 1: + tab = WebpConstants.Cat4; + break; + case 2: + tab = WebpConstants.Cat5; + break; + case 3: + tab = WebpConstants.Cat6; + break; + default: + WebpThrowHelper.ThrowImageFormatException("VP8 parsing error"); + break; + } - v += 3 + (8 << cat); + for (int i = 0; i < tab.Length; i++) + { + v += v + br.GetBit(tab[i]); } + + v += 3 + (8 << cat); } return v; @@ -1040,7 +1069,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy private Vp8SegmentHeader ParseSegmentHeader(Vp8Proba proba) { - var vp8SegmentHeader = new Vp8SegmentHeader + Vp8SegmentHeader vp8SegmentHeader = new() { UseSegment = this.bitReader.ReadBool() }; @@ -1055,15 +1084,13 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy for (int i = 0; i < vp8SegmentHeader.Quantizer.Length; i++) { hasValue = this.bitReader.ReadBool(); - byte quantizeValue = (byte)(hasValue ? this.bitReader.ReadSignedValue(7) : 0); - vp8SegmentHeader.Quantizer[i] = quantizeValue; + vp8SegmentHeader.Quantizer[i] = (byte)(hasValue ? this.bitReader.ReadSignedValue(7) : 0); } for (int i = 0; i < vp8SegmentHeader.FilterStrength.Length; i++) { hasValue = this.bitReader.ReadBool(); - byte filterStrengthValue = (byte)(hasValue ? this.bitReader.ReadSignedValue(6) : 0); - vp8SegmentHeader.FilterStrength[i] = filterStrengthValue; + vp8SegmentHeader.FilterStrength[i] = (byte)(hasValue ? this.bitReader.ReadSignedValue(6) : 0); } if (vp8SegmentHeader.UpdateMap) @@ -1188,10 +1215,8 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy decoder.DeQuantMatrices[i] = decoder.DeQuantMatrices[0]; continue; } - else - { - q = baseQ0; - } + + q = baseQ0; } Vp8QuantMatrix m = decoder.DeQuantMatrices[i]; @@ -1228,10 +1253,9 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy for (int p = 0; p < WebpConstants.NumProbas; ++p) { byte prob = WebpLookupTables.CoeffsUpdateProba[t, b, c, p]; - byte v = (byte)(this.bitReader.GetBit(prob) != 0 + proba.Bands[t, b].Probabilities[c].Probabilities[p] = (byte)(this.bitReader.GetBit(prob) != 0 ? this.bitReader.ReadValue(8) : WebpLookupTables.DefaultCoeffsProba[t, b, c, p]); - proba.Bands[t, b].Probabilities[c].Probabilities[p] = v; } } } @@ -1251,7 +1275,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy private static Vp8Io InitializeVp8Io(Vp8Decoder dec, Vp8PictureHeader pictureHeader) { - var io = default(Vp8Io); + Vp8Io io = default; io.Width = (int)pictureHeader.Width; io.Height = (int)pictureHeader.Height; io.UseScaling = false; @@ -1311,7 +1335,19 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy private static uint NzCodeBits(uint nzCoeffs, int nz, int dcNz) { nzCoeffs <<= 2; - nzCoeffs |= (uint)(nz > 3 ? 3 : nz > 1 ? 2 : dcNz); + if (nz > 3) + { + nzCoeffs |= 3; + } + else if (nz > 1) + { + nzCoeffs |= 2; + } + else + { + nzCoeffs |= (uint)dcNz; + } + return nzCoeffs; } @@ -1337,6 +1373,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy } [MethodImpl(InliningOptions.ShortMethod)] - private static int Clip(int value, int max) => value < 0 ? 0 : value > max ? max : value; + private static int Clip(int value, int max) => Math.Clamp(value, 0, max); } } diff --git a/src/ImageSharp/Formats/Webp/WebpAnimationDecoder.cs b/src/ImageSharp/Formats/Webp/WebpAnimationDecoder.cs index abf501f4f..2be64492e 100644 --- a/src/ImageSharp/Formats/Webp/WebpAnimationDecoder.cs +++ b/src/ImageSharp/Formats/Webp/WebpAnimationDecoder.cs @@ -147,7 +147,7 @@ namespace SixLabors.ImageSharp.Formats.Webp } WebpImageInfo webpInfo = null; - var features = new WebpFeatures(); + WebpFeatures features = new(); switch (chunkType) { case WebpChunkType.Vp8: @@ -169,7 +169,7 @@ namespace SixLabors.ImageSharp.Formats.Webp { image = new Image(this.configuration, (int)width, (int)height, backgroundColor.ToPixel(), this.metadata); - this.SetFrameMetadata(image.Frames.RootFrame.Metadata, frameData.Duration); + SetFrameMetadata(image.Frames.RootFrame.Metadata, frameData.Duration); imageFrame = image.Frames.RootFrame; } @@ -177,7 +177,7 @@ namespace SixLabors.ImageSharp.Formats.Webp { currentFrame = image.Frames.AddFrame(previousFrame); // This clones the frame and adds it the collection. - this.SetFrameMetadata(currentFrame.Metadata, frameData.Duration); + SetFrameMetadata(currentFrame.Metadata, frameData.Duration); imageFrame = currentFrame; } @@ -186,7 +186,7 @@ namespace SixLabors.ImageSharp.Formats.Webp int frameY = (int)(frameData.Y * 2); int frameWidth = (int)frameData.Width; int frameHeight = (int)frameData.Height; - var regionRectangle = Rectangle.FromLTRB(frameX, frameY, frameX + frameWidth, frameY + frameHeight); + Rectangle regionRectangle = Rectangle.FromLTRB(frameX, frameY, frameX + frameWidth, frameY + frameHeight); if (frameData.DisposalMethod is AnimationDisposalMethod.Dispose) { @@ -194,7 +194,7 @@ namespace SixLabors.ImageSharp.Formats.Webp } using Buffer2D decodedImage = this.DecodeImageData(frameData, webpInfo); - this.DrawDecodedImageOnCanvas(decodedImage, imageFrame, frameX, frameY, frameWidth, frameHeight); + DrawDecodedImageOnCanvas(decodedImage, imageFrame, frameX, frameY, frameWidth, frameHeight); if (previousFrame != null && frameData.BlendingMethod is AnimationBlendingMethod.AlphaBlending) { @@ -213,7 +213,7 @@ namespace SixLabors.ImageSharp.Formats.Webp /// The metadata. /// The frame duration. [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void SetFrameMetadata(ImageFrameMetadata meta, uint duration) + private static void SetFrameMetadata(ImageFrameMetadata meta, uint duration) { WebpFrameMetadata frameMetadata = meta.GetWebpMetadata(); frameMetadata.FrameDuration = duration; @@ -248,19 +248,19 @@ namespace SixLabors.ImageSharp.Formats.Webp private Buffer2D DecodeImageData(AnimationFrameData frameData, WebpImageInfo webpInfo) where TPixel : unmanaged, IPixel { - var decodedImage = new Image((int)frameData.Width, (int)frameData.Height); + Image decodedImage = new((int)frameData.Width, (int)frameData.Height); try { Buffer2D pixelBufferDecoded = decodedImage.Frames.RootFrame.PixelBuffer; if (webpInfo.IsLossless) { - var losslessDecoder = new WebpLosslessDecoder(webpInfo.Vp8LBitReader, this.memoryAllocator, this.configuration); + WebpLosslessDecoder losslessDecoder = new(webpInfo.Vp8LBitReader, this.memoryAllocator, this.configuration); losslessDecoder.Decode(pixelBufferDecoded, (int)webpInfo.Width, (int)webpInfo.Height); } else { - var lossyDecoder = new WebpLossyDecoder(webpInfo.Vp8BitReader, this.memoryAllocator, this.configuration); + WebpLossyDecoder lossyDecoder = new(webpInfo.Vp8BitReader, this.memoryAllocator, this.configuration); lossyDecoder.Decode(pixelBufferDecoded, (int)webpInfo.Width, (int)webpInfo.Height, webpInfo, this.alphaData); } @@ -278,7 +278,7 @@ namespace SixLabors.ImageSharp.Formats.Webp } /// - /// Draws the decoded image on canvas. The decoded image can be smaller the the canvas. + /// Draws the decoded image on canvas. The decoded image can be smaller the canvas. /// /// The type of the pixel. /// The decoded image. @@ -287,7 +287,7 @@ namespace SixLabors.ImageSharp.Formats.Webp /// The frame y coordinate. /// The width of the frame. /// The height of the frame. - private void DrawDecodedImageOnCanvas(Buffer2D decodedImage, ImageFrame imageFrame, int frameX, int frameY, int frameWidth, int frameHeight) + private static void DrawDecodedImageOnCanvas(Buffer2D decodedImage, ImageFrame imageFrame, int frameX, int frameY, int frameWidth, int frameHeight) where TPixel : unmanaged, IPixel { Buffer2D imageFramePixels = imageFrame.PixelBuffer; @@ -341,7 +341,7 @@ namespace SixLabors.ImageSharp.Formats.Webp return; } - var interest = Rectangle.Intersect(imageFrame.Bounds(), this.restoreArea.Value); + Rectangle interest = Rectangle.Intersect(imageFrame.Bounds(), this.restoreArea.Value); Buffer2DRegion pixelRegion = imageFrame.PixelBuffer.GetRegion(interest); TPixel backgroundPixel = backgroundColor.ToPixel(); pixelRegion.Fill(backgroundPixel); @@ -354,25 +354,25 @@ namespace SixLabors.ImageSharp.Formats.Webp /// Animation frame data. private AnimationFrameData ReadFrameHeader(BufferedReadStream stream) { - var data = new AnimationFrameData + AnimationFrameData data = new() { - DataSize = WebpChunkParsingUtils.ReadChunkSize(stream, this.buffer) - }; + DataSize = WebpChunkParsingUtils.ReadChunkSize(stream, this.buffer), - // 3 bytes for the X coordinate of the upper left corner of the frame. - data.X = WebpChunkParsingUtils.ReadUnsignedInt24Bit(stream, this.buffer); + // 3 bytes for the X coordinate of the upper left corner of the frame. + X = WebpChunkParsingUtils.ReadUnsignedInt24Bit(stream, this.buffer), - // 3 bytes for the Y coordinate of the upper left corner of the frame. - data.Y = WebpChunkParsingUtils.ReadUnsignedInt24Bit(stream, this.buffer); + // 3 bytes for the Y coordinate of the upper left corner of the frame. + Y = WebpChunkParsingUtils.ReadUnsignedInt24Bit(stream, this.buffer), - // Frame width Minus One. - data.Width = WebpChunkParsingUtils.ReadUnsignedInt24Bit(stream, this.buffer) + 1; + // Frame width Minus One. + Width = WebpChunkParsingUtils.ReadUnsignedInt24Bit(stream, this.buffer) + 1, - // Frame height Minus One. - data.Height = WebpChunkParsingUtils.ReadUnsignedInt24Bit(stream, this.buffer) + 1; + // Frame height Minus One. + Height = WebpChunkParsingUtils.ReadUnsignedInt24Bit(stream, this.buffer) + 1, - // Frame duration. - data.Duration = WebpChunkParsingUtils.ReadUnsignedInt24Bit(stream, this.buffer); + // Frame duration. + Duration = WebpChunkParsingUtils.ReadUnsignedInt24Bit(stream, this.buffer) + }; byte flags = (byte)stream.ReadByte(); data.DisposalMethod = (flags & 1) == 1 ? AnimationDisposalMethod.Dispose : AnimationDisposalMethod.DoNotDispose; diff --git a/src/ImageSharp/Formats/Webp/WebpImageFormatDetector.cs b/src/ImageSharp/Formats/Webp/WebpImageFormatDetector.cs index 9e672afb3..cdb6e5662 100644 --- a/src/ImageSharp/Formats/Webp/WebpImageFormatDetector.cs +++ b/src/ImageSharp/Formats/Webp/WebpImageFormatDetector.cs @@ -14,22 +14,26 @@ namespace SixLabors.ImageSharp.Formats.Webp public int HeaderSize => 12; /// - public IImageFormat DetectFormat(ReadOnlySpan header) => this.IsSupportedFileFormat(header) ? WebpFormat.Instance : null; + public IImageFormat DetectFormat(ReadOnlySpan header) + => this.IsSupportedFileFormat(header) ? WebpFormat.Instance : null; - private bool IsSupportedFileFormat(ReadOnlySpan header) => header.Length >= this.HeaderSize && this.IsRiffContainer(header) && this.IsWebpFile(header); + private bool IsSupportedFileFormat(ReadOnlySpan header) + => header.Length >= this.HeaderSize && IsRiffContainer(header) && IsWebpFile(header); /// /// Checks, if the header starts with a valid RIFF FourCC. /// /// The header bytes. /// True, if its a valid RIFF FourCC. - private bool IsRiffContainer(ReadOnlySpan header) => header[..4].SequenceEqual(WebpConstants.RiffFourCc); + private static bool IsRiffContainer(ReadOnlySpan header) + => header[..4].SequenceEqual(WebpConstants.RiffFourCc); /// /// Checks if 'WEBP' is present in the header. /// /// The header bytes. /// True, if its a webp file. - private bool IsWebpFile(ReadOnlySpan header) => header.Slice(8, 4).SequenceEqual(WebpConstants.WebpHeader); + private static bool IsWebpFile(ReadOnlySpan header) + => header.Slice(8, 4).SequenceEqual(WebpConstants.WebpHeader); } } diff --git a/src/ImageSharp/Formats/Webp/WebpImageInfo.cs b/src/ImageSharp/Formats/Webp/WebpImageInfo.cs index 5b74de680..3c9eea38c 100644 --- a/src/ImageSharp/Formats/Webp/WebpImageInfo.cs +++ b/src/ImageSharp/Formats/Webp/WebpImageInfo.cs @@ -49,14 +49,14 @@ namespace SixLabors.ImageSharp.Formats.Webp public Vp8FrameHeader Vp8FrameHeader { get; set; } /// - /// Gets or sets the VP8L bitreader. Will be null, if its not a lossless image. + /// Gets or sets the VP8L bitreader. Will be , if its not a lossless image. /// - public Vp8LBitReader Vp8LBitReader { get; set; } = null; + public Vp8LBitReader Vp8LBitReader { get; set; } /// - /// Gets or sets the VP8 bitreader. Will be null, if its not a lossy image. + /// Gets or sets the VP8 bitreader. Will be , if its not a lossy image. /// - public Vp8BitReader Vp8BitReader { get; set; } = null; + public Vp8BitReader Vp8BitReader { get; set; } /// public void Dispose() diff --git a/src/ImageSharp/IO/BufferedReadStream.cs b/src/ImageSharp/IO/BufferedReadStream.cs index 572563ef3..e6aeadea2 100644 --- a/src/ImageSharp/IO/BufferedReadStream.cs +++ b/src/ImageSharp/IO/BufferedReadStream.cs @@ -112,7 +112,7 @@ namespace SixLabors.ImageSharp.IO public override bool CanSeek { get; } = true; /// - public override bool CanWrite { get; } = false; + public override bool CanWrite { get; } /// /// Gets remaining byte count available to read. diff --git a/src/ImageSharp/IO/ChunkedMemoryStream.cs b/src/ImageSharp/IO/ChunkedMemoryStream.cs index 49e3d7f2f..837af618e 100644 --- a/src/ImageSharp/IO/ChunkedMemoryStream.cs +++ b/src/ImageSharp/IO/ChunkedMemoryStream.cs @@ -203,7 +203,7 @@ namespace SixLabors.ImageSharp.IO this.isDisposed = true; if (disposing) { - this.ReleaseMemoryChunks(this.memoryChunk); + ReleaseMemoryChunks(this.memoryChunk); } this.memoryChunk = null; @@ -530,7 +530,7 @@ namespace SixLabors.ImageSharp.IO }; } - private void ReleaseMemoryChunks(MemoryChunk chunk) + private static void ReleaseMemoryChunks(MemoryChunk chunk) { while (chunk != null) { diff --git a/src/ImageSharp/Image.FromStream.cs b/src/ImageSharp/Image.FromStream.cs index 5c73590aa..4d1b17231 100644 --- a/src/ImageSharp/Image.FromStream.cs +++ b/src/ImageSharp/Image.FromStream.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using System.Globalization; using System.IO; using System.Text; using System.Threading; @@ -546,7 +547,7 @@ namespace SixLabors.ImageSharp } // We want to be able to load images from things like HttpContext.Request.Body - using var memoryStream = new ChunkedMemoryStream(configuration.MemoryAllocator); + using ChunkedMemoryStream memoryStream = new(configuration.MemoryAllocator); stream.CopyTo(memoryStream, configuration.StreamProcessingBufferSize); memoryStream.Position = 0; @@ -562,6 +563,7 @@ namespace SixLabors.ImageSharp /// The action to perform. /// The cancellation token. /// The . + /// Cannot read from the stream. internal static async Task WithSeekableStreamAsync( DecoderOptions options, Stream stream, @@ -577,19 +579,16 @@ namespace SixLabors.ImageSharp } Configuration configuration = options.Configuration; - if (stream.CanSeek) + if (stream.CanSeek && configuration.ReadOrigin == ReadOrigin.Begin) { - if (configuration.ReadOrigin == ReadOrigin.Begin) - { - stream.Position = 0; - } + stream.Position = 0; // NOTE: We are explicitly not executing the action against the stream here as we do in WithSeekableStream() because that // would incur synchronous IO reads which must be avoided in this asynchronous method. Instead, we will *always* run the // code below to copy the stream to an in-memory buffer before invoking the action. } - using var memoryStream = new ChunkedMemoryStream(configuration.MemoryAllocator); + using ChunkedMemoryStream memoryStream = new(configuration.MemoryAllocator); await stream.CopyToAsync(memoryStream, configuration.StreamProcessingBufferSize, cancellationToken).ConfigureAwait(false); memoryStream.Position = 0; @@ -599,12 +598,12 @@ namespace SixLabors.ImageSharp [DoesNotReturn] private static void ThrowNotLoaded(DecoderOptions options) { - var sb = new StringBuilder(); + StringBuilder sb = new(); sb.AppendLine("Image cannot be loaded. Available decoders:"); foreach (KeyValuePair val in options.Configuration.ImageFormatsManager.ImageDecoders) { - sb.AppendFormat(" - {0} : {1}{2}", val.Key.Name, val.Value.GetType().Name, Environment.NewLine); + sb.AppendFormat(CultureInfo.InvariantCulture, " - {0} : {1}{2}", val.Key.Name, val.Value.GetType().Name, Environment.NewLine); } throw new UnknownImageFormatException(sb.ToString()); diff --git a/src/ImageSharp/Image.WrapMemory.cs b/src/ImageSharp/Image.WrapMemory.cs index 6646e43c2..9e68d901a 100644 --- a/src/ImageSharp/Image.WrapMemory.cs +++ b/src/ImageSharp/Image.WrapMemory.cs @@ -53,7 +53,7 @@ namespace SixLabors.ImageSharp Guard.NotNull(metadata, nameof(metadata)); Guard.IsTrue(pixelMemory.Length >= width * height, nameof(pixelMemory), "The length of the input memory is less than the specified image size"); - var memorySource = MemoryGroup.Wrap(pixelMemory); + MemoryGroup memorySource = MemoryGroup.Wrap(pixelMemory); return new Image(configuration, memorySource, width, height, metadata); } @@ -148,7 +148,7 @@ namespace SixLabors.ImageSharp Guard.NotNull(metadata, nameof(metadata)); Guard.IsTrue(pixelMemoryOwner.Memory.Length >= width * height, nameof(pixelMemoryOwner), "The length of the input memory is less than the specified image size"); - var memorySource = MemoryGroup.Wrap(pixelMemoryOwner); + MemoryGroup memorySource = MemoryGroup.Wrap(pixelMemoryOwner); return new Image(configuration, memorySource, width, height, metadata); } @@ -231,11 +231,11 @@ namespace SixLabors.ImageSharp Guard.NotNull(configuration, nameof(configuration)); Guard.NotNull(metadata, nameof(metadata)); - var memoryManager = new ByteMemoryManager(byteMemory); + ByteMemoryManager memoryManager = new(byteMemory); Guard.IsTrue(memoryManager.Memory.Length >= width * height, nameof(byteMemory), "The length of the input memory is less than the specified image size"); - var memorySource = MemoryGroup.Wrap(memoryManager.Memory); + MemoryGroup memorySource = MemoryGroup.Wrap(memoryManager.Memory); return new Image(configuration, memorySource, width, height, metadata); } @@ -329,11 +329,11 @@ namespace SixLabors.ImageSharp Guard.NotNull(configuration, nameof(configuration)); Guard.NotNull(metadata, nameof(metadata)); - var pixelMemoryOwner = new ByteMemoryOwner(byteMemoryOwner); + ByteMemoryOwner pixelMemoryOwner = new(byteMemoryOwner); Guard.IsTrue(pixelMemoryOwner.Memory.Length >= (long)width * height, nameof(pixelMemoryOwner), "The length of the input memory is less than the specified image size"); - var memorySource = MemoryGroup.Wrap(pixelMemoryOwner); + MemoryGroup memorySource = MemoryGroup.Wrap(pixelMemoryOwner); return new Image(configuration, memorySource, width, height, metadata); } @@ -422,9 +422,9 @@ namespace SixLabors.ImageSharp Guard.NotNull(configuration, nameof(configuration)); Guard.NotNull(metadata, nameof(metadata)); - var memoryManager = new UnmanagedMemoryManager(pointer, width * height); + UnmanagedMemoryManager memoryManager = new(pointer, width * height); - var memorySource = MemoryGroup.Wrap(memoryManager.Memory); + MemoryGroup memorySource = MemoryGroup.Wrap(memoryManager.Memory); return new Image(configuration, memorySource, width, height, metadata); } diff --git a/src/ImageSharp/ImageExtensions.cs b/src/ImageSharp/ImageExtensions.cs index 182047aff..9427c8d61 100644 --- a/src/ImageSharp/ImageExtensions.cs +++ b/src/ImageSharp/ImageExtensions.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Text; using System.Threading; @@ -106,12 +107,12 @@ namespace SixLabors.ImageSharp if (encoder is null) { - var sb = new StringBuilder(); + StringBuilder sb = new(); sb.AppendLine("No encoder was found for the provided mime type. Registered encoders include:"); foreach (KeyValuePair val in source.GetConfiguration().ImageFormatsManager.ImageEncoders) { - sb.AppendFormat(" - {0} : {1}{2}", val.Key.Name, val.Value.GetType().Name, Environment.NewLine); + sb.AppendFormat(CultureInfo.InvariantCulture, " - {0} : {1}{2}", val.Key.Name, val.Value.GetType().Name, Environment.NewLine); } throw new NotSupportedException(sb.ToString()); @@ -150,12 +151,12 @@ namespace SixLabors.ImageSharp if (encoder is null) { - var sb = new StringBuilder(); + StringBuilder sb = new(); sb.AppendLine("No encoder was found for the provided mime type. Registered encoders include:"); foreach (KeyValuePair val in source.GetConfiguration().ImageFormatsManager.ImageEncoders) { - sb.AppendFormat(" - {0} : {1}{2}", val.Key.Name, val.Value.GetType().Name, Environment.NewLine); + sb.AppendFormat(CultureInfo.InvariantCulture, " - {0} : {1}{2}", val.Key.Name, val.Value.GetType().Name, Environment.NewLine); } throw new NotSupportedException(sb.ToString()); @@ -182,7 +183,7 @@ namespace SixLabors.ImageSharp { Guard.NotNull(format, nameof(format)); - using var stream = new MemoryStream(); + using MemoryStream stream = new(); source.Save(stream, format); // Always available. diff --git a/src/ImageSharp/ImageSharp.csproj.DotSettings b/src/ImageSharp/ImageSharp.csproj.DotSettings deleted file mode 100644 index 6896e069c..000000000 --- a/src/ImageSharp/ImageSharp.csproj.DotSettings +++ /dev/null @@ -1,15 +0,0 @@ - - True - True - True - True - True - True - True - True - True - True - True - True - True - True \ No newline at end of file diff --git a/src/ImageSharp/ImageSharp.netstandard1.1.v3.ncrunchproject b/src/ImageSharp/ImageSharp.netstandard1.1.v3.ncrunchproject deleted file mode 100644 index 319cd523c..000000000 --- a/src/ImageSharp/ImageSharp.netstandard1.1.v3.ncrunchproject +++ /dev/null @@ -1,5 +0,0 @@ - - - True - - \ No newline at end of file diff --git a/src/ImageSharp/Memory/Allocators/Internals/UnmanagedMemoryHandle.cs b/src/ImageSharp/Memory/Allocators/Internals/UnmanagedMemoryHandle.cs index 74a98ed1a..7933f3e13 100644 --- a/src/ImageSharp/Memory/Allocators/Internals/UnmanagedMemoryHandle.cs +++ b/src/ImageSharp/Memory/Allocators/Internals/UnmanagedMemoryHandle.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.Memory.Internals // A Monitor to wait/signal when we are low on memory. private static object lowMemoryMonitor; - public static readonly UnmanagedMemoryHandle NullHandle = default; + public static readonly UnmanagedMemoryHandle NullHandle; private IntPtr handle; private int lengthInBytes; @@ -80,24 +80,17 @@ namespace SixLabors.ImageSharp.Memory.Internals { handle = Marshal.AllocHGlobal(lengthInBytes); } - catch (OutOfMemoryException) + catch (OutOfMemoryException) when (counter < MaxAllocationAttempts) { // We are low on memory, but expect some memory to be freed soon. // Block the thread & retry to avoid OOM. - if (counter < MaxAllocationAttempts) - { - counter++; - Interlocked.Increment(ref totalOomRetries); - - Interlocked.CompareExchange(ref lowMemoryMonitor, new object(), null); - Monitor.Enter(lowMemoryMonitor); - Monitor.Wait(lowMemoryMonitor, millisecondsTimeout: 1); - Monitor.Exit(lowMemoryMonitor); - } - else - { - throw; - } + counter++; + Interlocked.Increment(ref totalOomRetries); + + Interlocked.CompareExchange(ref lowMemoryMonitor, new object(), null); + Monitor.Enter(lowMemoryMonitor); + Monitor.Wait(lowMemoryMonitor, millisecondsTimeout: 1); + Monitor.Exit(lowMemoryMonitor); } } diff --git a/src/ImageSharp/Metadata/Profiles/Exif/ExifReader.cs b/src/ImageSharp/Metadata/Profiles/Exif/ExifReader.cs index b2b1b2831..722f59316 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/ExifReader.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/ExifReader.cs @@ -7,7 +7,9 @@ using System.Buffers.Binary; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; +using System.Globalization; using System.IO; +using System.Linq; using System.Runtime.CompilerServices; using System.Text; using SixLabors.ImageSharp.Memory; @@ -34,7 +36,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif /// public List ReadValues() { - var values = new List(); + List values = new(); // II == 0x4949 this.IsBigEndian = this.ReadUInt16() != 0x4949; @@ -64,11 +66,12 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif return; } - var values = new List(); + List values = new(); this.ReadValues(values, offset); - foreach (ExifValue value in values) + for (int i = 0; i < values.Count; i++) { + ExifValue value = (ExifValue)values[i]; if (value == ExifTag.JPEGInterchangeFormat) { this.ThumbnailOffset = ((ExifLong)value).Value; @@ -229,7 +232,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif int dataTypeSize = (int)ExifDataTypes.GetSize(dataType); int length = data.Length / dataTypeSize; - var result = new TDataType[length]; + TDataType[] result = new TDataType[length]; for (int i = 0; i < length; i++) { @@ -370,7 +373,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif return; } - var tag = (ExifTagValue)this.ReadUInt16(); + ExifTagValue tag = (ExifTagValue)this.ReadUInt16(); ExifDataType dataType = EnumUtils.Parse(this.ReadUInt16(), ExifDataType.Unknown); uint numberOfComponents = this.ReadUInt32(); @@ -426,7 +429,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif return; } - var tag = (ExifTagValue)this.ReadUInt16(); + ExifTagValue tag = (ExifTagValue)this.ReadUInt16(); ExifDataType dataType = EnumUtils.Parse(this.ReadUInt16(), ExifDataType.Unknown); ulong numberOfComponents = this.ReadUInt64(); @@ -511,7 +514,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif => (this.invalidTags ??= new List()).Add(tag); private void AddSubIfd(object val) - => (this.subIfds ??= new List()).Add(Convert.ToUInt64(val)); + => (this.subIfds ??= new List()).Add(Convert.ToUInt64(val, CultureInfo.InvariantCulture)); private void Seek(ulong pos) => this.data.Seek((long)pos, SeekOrigin.Begin); diff --git a/src/ImageSharp/Metadata/Profiles/Exif/ExifWriter.cs b/src/ImageSharp/Metadata/Profiles/Exif/ExifWriter.cs index ed22ff647..1212e16cc 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/ExifWriter.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/ExifWriter.cs @@ -49,9 +49,9 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif IExifValue exifOffset = GetOffsetValue(this.ifdValues, this.exifValues, ExifTag.SubIFDOffset); IExifValue gpsOffset = GetOffsetValue(this.ifdValues, this.gpsValues, ExifTag.GPSIFDOffset); - uint ifdLength = this.GetLength(this.ifdValues); - uint exifLength = this.GetLength(this.exifValues); - uint gpsLength = this.GetLength(this.gpsValues); + uint ifdLength = GetLength(this.ifdValues); + uint exifLength = GetLength(this.exifValues); + uint gpsLength = GetLength(this.gpsValues); uint length = ifdLength + exifLength + gpsLength; @@ -100,14 +100,14 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif private static unsafe int WriteSingle(float value, Span destination, int offset) { - BinaryPrimitives.WriteInt32LittleEndian(destination.Slice(offset, 4), *((int*)&value)); + BinaryPrimitives.WriteInt32LittleEndian(destination.Slice(offset, 4), *(int*)&value); return offset + 4; } private static unsafe int WriteDouble(double value, Span destination, int offset) { - BinaryPrimitives.WriteInt64LittleEndian(destination.Slice(offset, 8), *((long*)&value)); + BinaryPrimitives.WriteInt64LittleEndian(destination.Slice(offset, 8), *(long*)&value); return offset + 8; } @@ -195,7 +195,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif private List GetPartValues(ExifParts part) { - var result = new List(); + List result = new(); if (!EnumUtils.HasFlag(this.allowedParts, part)) { @@ -240,7 +240,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif return true; } - private uint GetLength(IList values) + private static uint GetLength(IList values) { if (values.Count == 0) { @@ -360,9 +360,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif } // next IFD offset - newOffset = WriteUInt32(0, destination, newOffset); - - return newOffset; + return WriteUInt32(0, destination, newOffset); } private static void WriteRational(Span destination, in Rational value) @@ -413,7 +411,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif WriteRational(destination.Slice(offset, 8), (Rational)value); return offset + 8; case ExifDataType.SignedByte: - destination[offset] = unchecked((byte)((sbyte)value)); + destination[offset] = unchecked((byte)(sbyte)value); return offset + 1; case ExifDataType.SignedLong: return WriteInt32((int)value, destination, offset); diff --git a/src/ImageSharp/Metadata/Profiles/Exif/Values/EncodedString.cs b/src/ImageSharp/Metadata/Profiles/Exif/Values/EncodedString.cs index 2209586ab..2af413cb9 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/Values/EncodedString.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/Values/EncodedString.cs @@ -79,6 +79,28 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif /// The to convert. public static explicit operator string(EncodedString encodedString) => encodedString.Text; + /// + /// Checks whether two structures are equal. + /// + /// The left hand operand. + /// The right hand operand. + /// + /// True if the parameter is equal to the parameter; + /// otherwise, false. + /// + public static bool operator ==(EncodedString left, EncodedString right) => left.Equals(right); + + /// + /// Checks whether two structures are not equal. + /// + /// The left hand operand. + /// The right hand operand. + /// + /// True if the parameter is not equal to the parameter; + /// otherwise, false. + /// + public static bool operator !=(EncodedString left, EncodedString right) => !(left == right); + /// public override bool Equals(object obj) => obj is EncodedString other && this.Equals(other); diff --git a/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccCurveSegment.cs b/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccCurveSegment.cs index a4603a02a..6fa985eb2 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccCurveSegment.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccCurveSegment.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -15,9 +15,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// /// The signature of this segment protected IccCurveSegment(IccCurveSegmentSignature signature) - { - this.Signature = signature; - } + => this.Signature = signature; /// /// Gets the signature of this segment @@ -39,5 +37,11 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc return this.Signature == other.Signature; } + + /// + public override bool Equals(object obj) => this.Equals(obj as IccCurveSegment); + + /// + public override int GetHashCode() => this.Signature.GetHashCode(); } } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccFormulaCurveElement.cs b/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccFormulaCurveElement.cs index a22c7dcde..5ad61d4a0 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccFormulaCurveElement.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccFormulaCurveElement.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -85,9 +85,20 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc } /// - public bool Equals(IccFormulaCurveElement other) - { - return this.Equals((IccCurveSegment)other); - } + public bool Equals(IccFormulaCurveElement other) => this.Equals((IccCurveSegment)other); + + /// + public override bool Equals(object obj) => this.Equals(obj as IccFormulaCurveElement); + + /// + public override int GetHashCode() + => HashCode.Combine( + this.Type, + this.Gamma, + this.A, + this.B, + this.C, + this.D, + this.E); } } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccOneDimensionalCurve.cs b/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccOneDimensionalCurve.cs index 773140ab2..d84a18f90 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccOneDimensionalCurve.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccOneDimensionalCurve.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -53,5 +53,13 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc return this.BreakPoints.AsSpan().SequenceEqual(other.BreakPoints) && this.Segments.AsSpan().SequenceEqual(other.Segments); } + + /// + public override bool Equals(object obj) + => this.Equals(obj as IccOneDimensionalCurve); + + /// + public override int GetHashCode() + => HashCode.Combine(this.BreakPoints, this.Segments); } } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccSampledCurveElement.cs b/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccSampledCurveElement.cs index 30b3dafa3..a305eea31 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccSampledCurveElement.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccSampledCurveElement.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -41,8 +41,14 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// public bool Equals(IccSampledCurveElement other) - { - return this.Equals((IccCurveSegment)other); - } + => this.Equals((IccCurveSegment)other); + + /// + public override bool Equals(object obj) + => this.Equals(obj as IccSampledCurveElement); + + /// + public override int GetHashCode() + => HashCode.Combine(base.GetHashCode(), this.CurveEntries); } } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.TagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.TagDataEntry.cs index f7c7d0a81..176c46335 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.TagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.TagDataEntry.cs @@ -230,7 +230,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc byte b = this.data[this.AddIndex(1)]; // last bit of 4th byte is either 0 = ASCII or 1 = binary - bool ascii = this.GetBit(b, 7); + bool ascii = GetBit(b, 7); int length = (int)size - 12; byte[] cdata = this.ReadBytes(length); diff --git a/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.cs b/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.cs index bd85cfbf4..35c867827 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.cs @@ -25,9 +25,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// /// The data to read public IccDataReader(byte[] data) - { - this.data = data ?? throw new ArgumentNullException(nameof(data)); - } + => this.data = data ?? throw new ArgumentNullException(nameof(data)); /// /// Gets the length in bytes of the raw data @@ -39,9 +37,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// /// The new index position public void SetIndex(int index) - { - this.currentIndex = Numerics.Clamp(index, 0, this.data.Length); - } + => this.currentIndex = Numerics.Clamp(index, 0, this.data.Length); /// /// Returns the current without increment and adds the given increment @@ -59,9 +55,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// Calculates the 4 byte padding and adds it to the variable /// private void AddPadding() - { - this.currentIndex += this.CalcPadding(); - } + => this.currentIndex += this.CalcPadding(); /// /// Calculates the 4 byte padding @@ -79,9 +73,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// The value from where the bit will be extracted /// Position of the bit. Zero based index from left to right. /// The bit value at specified position - private bool GetBit(byte value, int position) - { - return ((value >> (7 - position)) & 1) == 1; - } + private static bool GetBit(byte value, int position) + => ((value >> (7 - position)) & 1) == 1; } } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs index 411cdacec..8ff48bf13 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs @@ -34,116 +34,46 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { int count = this.WriteTagDataEntryHeader(entry.Signature); - switch (entry.Signature) - { - case IccTypeSignature.Chromaticity: - count += this.WriteChromaticityTagDataEntry((IccChromaticityTagDataEntry)entry); - break; - case IccTypeSignature.ColorantOrder: - count += this.WriteColorantOrderTagDataEntry((IccColorantOrderTagDataEntry)entry); - break; - case IccTypeSignature.ColorantTable: - count += this.WriteColorantTableTagDataEntry((IccColorantTableTagDataEntry)entry); - break; - case IccTypeSignature.Curve: - count += this.WriteCurveTagDataEntry((IccCurveTagDataEntry)entry); - break; - case IccTypeSignature.Data: - count += this.WriteDataTagDataEntry((IccDataTagDataEntry)entry); - break; - case IccTypeSignature.DateTime: - count += this.WriteDateTimeTagDataEntry((IccDateTimeTagDataEntry)entry); - break; - case IccTypeSignature.Lut16: - count += this.WriteLut16TagDataEntry((IccLut16TagDataEntry)entry); - break; - case IccTypeSignature.Lut8: - count += this.WriteLut8TagDataEntry((IccLut8TagDataEntry)entry); - break; - case IccTypeSignature.LutAToB: - count += this.WriteLutAtoBTagDataEntry((IccLutAToBTagDataEntry)entry); - break; - case IccTypeSignature.LutBToA: - count += this.WriteLutBtoATagDataEntry((IccLutBToATagDataEntry)entry); - break; - case IccTypeSignature.Measurement: - count += this.WriteMeasurementTagDataEntry((IccMeasurementTagDataEntry)entry); - break; - case IccTypeSignature.MultiLocalizedUnicode: - count += this.WriteMultiLocalizedUnicodeTagDataEntry((IccMultiLocalizedUnicodeTagDataEntry)entry); - break; - case IccTypeSignature.MultiProcessElements: - count += this.WriteMultiProcessElementsTagDataEntry((IccMultiProcessElementsTagDataEntry)entry); - break; - case IccTypeSignature.NamedColor2: - count += this.WriteNamedColor2TagDataEntry((IccNamedColor2TagDataEntry)entry); - break; - case IccTypeSignature.ParametricCurve: - count += this.WriteParametricCurveTagDataEntry((IccParametricCurveTagDataEntry)entry); - break; - case IccTypeSignature.ProfileSequenceDesc: - count += this.WriteProfileSequenceDescTagDataEntry((IccProfileSequenceDescTagDataEntry)entry); - break; - case IccTypeSignature.ProfileSequenceIdentifier: - count += this.WriteProfileSequenceIdentifierTagDataEntry((IccProfileSequenceIdentifierTagDataEntry)entry); - break; - case IccTypeSignature.ResponseCurveSet16: - count += this.WriteResponseCurveSet16TagDataEntry((IccResponseCurveSet16TagDataEntry)entry); - break; - case IccTypeSignature.S15Fixed16Array: - count += this.WriteFix16ArrayTagDataEntry((IccFix16ArrayTagDataEntry)entry); - break; - case IccTypeSignature.Signature: - count += this.WriteSignatureTagDataEntry((IccSignatureTagDataEntry)entry); - break; - case IccTypeSignature.Text: - count += this.WriteTextTagDataEntry((IccTextTagDataEntry)entry); - break; - case IccTypeSignature.U16Fixed16Array: - count += this.WriteUFix16ArrayTagDataEntry((IccUFix16ArrayTagDataEntry)entry); - break; - case IccTypeSignature.UInt16Array: - count += this.WriteUInt16ArrayTagDataEntry((IccUInt16ArrayTagDataEntry)entry); - break; - case IccTypeSignature.UInt32Array: - count += this.WriteUInt32ArrayTagDataEntry((IccUInt32ArrayTagDataEntry)entry); - break; - case IccTypeSignature.UInt64Array: - count += this.WriteUInt64ArrayTagDataEntry((IccUInt64ArrayTagDataEntry)entry); - break; - case IccTypeSignature.UInt8Array: - count += this.WriteUInt8ArrayTagDataEntry((IccUInt8ArrayTagDataEntry)entry); - break; - case IccTypeSignature.ViewingConditions: - count += this.WriteViewingConditionsTagDataEntry((IccViewingConditionsTagDataEntry)entry); - break; - case IccTypeSignature.Xyz: - count += this.WriteXyzTagDataEntry((IccXyzTagDataEntry)entry); - break; + count += entry.Signature switch + { + IccTypeSignature.Chromaticity => this.WriteChromaticityTagDataEntry((IccChromaticityTagDataEntry)entry), + IccTypeSignature.ColorantOrder => this.WriteColorantOrderTagDataEntry((IccColorantOrderTagDataEntry)entry), + IccTypeSignature.ColorantTable => this.WriteColorantTableTagDataEntry((IccColorantTableTagDataEntry)entry), + IccTypeSignature.Curve => this.WriteCurveTagDataEntry((IccCurveTagDataEntry)entry), + IccTypeSignature.Data => this.WriteDataTagDataEntry((IccDataTagDataEntry)entry), + IccTypeSignature.DateTime => this.WriteDateTimeTagDataEntry((IccDateTimeTagDataEntry)entry), + IccTypeSignature.Lut16 => this.WriteLut16TagDataEntry((IccLut16TagDataEntry)entry), + IccTypeSignature.Lut8 => this.WriteLut8TagDataEntry((IccLut8TagDataEntry)entry), + IccTypeSignature.LutAToB => this.WriteLutAtoBTagDataEntry((IccLutAToBTagDataEntry)entry), + IccTypeSignature.LutBToA => this.WriteLutBtoATagDataEntry((IccLutBToATagDataEntry)entry), + IccTypeSignature.Measurement => this.WriteMeasurementTagDataEntry((IccMeasurementTagDataEntry)entry), + IccTypeSignature.MultiLocalizedUnicode => this.WriteMultiLocalizedUnicodeTagDataEntry((IccMultiLocalizedUnicodeTagDataEntry)entry), + IccTypeSignature.MultiProcessElements => this.WriteMultiProcessElementsTagDataEntry((IccMultiProcessElementsTagDataEntry)entry), + IccTypeSignature.NamedColor2 => this.WriteNamedColor2TagDataEntry((IccNamedColor2TagDataEntry)entry), + IccTypeSignature.ParametricCurve => this.WriteParametricCurveTagDataEntry((IccParametricCurveTagDataEntry)entry), + IccTypeSignature.ProfileSequenceDesc => this.WriteProfileSequenceDescTagDataEntry((IccProfileSequenceDescTagDataEntry)entry), + IccTypeSignature.ProfileSequenceIdentifier => this.WriteProfileSequenceIdentifierTagDataEntry((IccProfileSequenceIdentifierTagDataEntry)entry), + IccTypeSignature.ResponseCurveSet16 => this.WriteResponseCurveSet16TagDataEntry((IccResponseCurveSet16TagDataEntry)entry), + IccTypeSignature.S15Fixed16Array => this.WriteFix16ArrayTagDataEntry((IccFix16ArrayTagDataEntry)entry), + IccTypeSignature.Signature => this.WriteSignatureTagDataEntry((IccSignatureTagDataEntry)entry), + IccTypeSignature.Text => this.WriteTextTagDataEntry((IccTextTagDataEntry)entry), + IccTypeSignature.U16Fixed16Array => this.WriteUFix16ArrayTagDataEntry((IccUFix16ArrayTagDataEntry)entry), + IccTypeSignature.UInt16Array => this.WriteUInt16ArrayTagDataEntry((IccUInt16ArrayTagDataEntry)entry), + IccTypeSignature.UInt32Array => this.WriteUInt32ArrayTagDataEntry((IccUInt32ArrayTagDataEntry)entry), + IccTypeSignature.UInt64Array => this.WriteUInt64ArrayTagDataEntry((IccUInt64ArrayTagDataEntry)entry), + IccTypeSignature.UInt8Array => this.WriteUInt8ArrayTagDataEntry((IccUInt8ArrayTagDataEntry)entry), + IccTypeSignature.ViewingConditions => this.WriteViewingConditionsTagDataEntry((IccViewingConditionsTagDataEntry)entry), + IccTypeSignature.Xyz => this.WriteXyzTagDataEntry((IccXyzTagDataEntry)entry), // V2 Types: - case IccTypeSignature.TextDescription: - count += this.WriteTextDescriptionTagDataEntry((IccTextDescriptionTagDataEntry)entry); - break; - case IccTypeSignature.CrdInfo: - count += this.WriteCrdInfoTagDataEntry((IccCrdInfoTagDataEntry)entry); - break; - case IccTypeSignature.Screening: - count += this.WriteScreeningTagDataEntry((IccScreeningTagDataEntry)entry); - break; - case IccTypeSignature.UcrBg: - count += this.WriteUcrBgTagDataEntry((IccUcrBgTagDataEntry)entry); - break; + IccTypeSignature.TextDescription => this.WriteTextDescriptionTagDataEntry((IccTextDescriptionTagDataEntry)entry), + IccTypeSignature.CrdInfo => this.WriteCrdInfoTagDataEntry((IccCrdInfoTagDataEntry)entry), + IccTypeSignature.Screening => this.WriteScreeningTagDataEntry((IccScreeningTagDataEntry)entry), + IccTypeSignature.UcrBg => this.WriteUcrBgTagDataEntry((IccUcrBgTagDataEntry)entry), // Unsupported or unknown - case IccTypeSignature.DeviceSettings: - case IccTypeSignature.NamedColor: - case IccTypeSignature.Unknown: - default: - count += this.WriteUnknownTagDataEntry(entry as IccUnknownTagDataEntry); - break; - } - + _ => this.WriteUnknownTagDataEntry(entry as IccUnknownTagDataEntry), + }; return count; } @@ -153,10 +83,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// The signature of the entry /// The number of bytes written public int WriteTagDataEntryHeader(IccTypeSignature signature) - { - return this.WriteUInt32((uint)signature) - + this.WriteEmpty(4); - } + => this.WriteUInt32((uint)signature) + this.WriteEmpty(4); /// /// Writes a @@ -190,10 +117,8 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// The entry to write /// The number of bytes written public int WriteColorantOrderTagDataEntry(IccColorantOrderTagDataEntry value) - { - return this.WriteUInt32((uint)value.ColorantNumber.Length) - + this.WriteArray(value.ColorantNumber); - } + => this.WriteUInt32((uint)value.ColorantNumber.Length) + + this.WriteArray(value.ColorantNumber); /// /// Writes a @@ -255,11 +180,9 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// The entry to write /// The number of bytes written public int WriteDataTagDataEntry(IccDataTagDataEntry value) - { - return this.WriteEmpty(3) - + this.WriteByte((byte)(value.IsAscii ? 0x01 : 0x00)) - + this.WriteArray(value.Data); - } + => this.WriteEmpty(3) + + this.WriteByte((byte)(value.IsAscii ? 0x01 : 0x00)) + + this.WriteArray(value.Data); /// /// Writes a @@ -531,13 +454,11 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// The entry to write /// The number of bytes written public int WriteMeasurementTagDataEntry(IccMeasurementTagDataEntry value) - { - return this.WriteUInt32((uint)value.Observer) - + this.WriteXyzNumber(value.XyzBacking) - + this.WriteUInt32((uint)value.Geometry) - + this.WriteUFix16(value.Flare) - + this.WriteUInt32((uint)value.Illuminant); - } + => this.WriteUInt32((uint)value.Observer) + + this.WriteXyzNumber(value.XyzBacking) + + this.WriteUInt32((uint)value.Geometry) + + this.WriteUFix16(value.Flare) + + this.WriteUInt32((uint)value.Illuminant); /// /// Writes a @@ -560,8 +481,8 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc // TODO: Investigate cost of Linq GroupBy IGrouping[] texts = value.Texts.GroupBy(t => t.Text).ToArray(); - var offset = new uint[texts.Length]; - var lengths = new int[texts.Length]; + uint[] offset = new uint[texts.Length]; + int[] lengths = new int[texts.Length]; for (int i = 0; i < texts.Length; i++) { @@ -582,11 +503,11 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc count += this.WriteAsciiString("xx", 2, false); count += this.WriteAsciiString("\0\0", 2, false); } - else if (cultureName.Contains("-")) + else if (cultureName.Contains('-')) { string[] code = cultureName.Split('-'); - count += this.WriteAsciiString(code[0].ToLower(), 2, false); - count += this.WriteAsciiString(code[1].ToUpper(), 2, false); + count += this.WriteAsciiString(code[0].ToLower(localizedString.Culture), 2, false); + count += this.WriteAsciiString(code[1].ToUpper(localizedString.Culture), 2, false); } else { @@ -620,7 +541,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc long tpos = this.dataStream.Position; this.dataStream.Position += value.Data.Length * 8; - var posTable = new IccPositionNumber[value.Data.Length]; + IccPositionNumber[] posTable = new IccPositionNumber[value.Data.Length]; for (int i = 0; i < value.Data.Length; i++) { uint offset = (uint)(this.dataStream.Position - start); @@ -704,7 +625,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc // Jump over position table long tablePosition = this.dataStream.Position; this.dataStream.Position += length * 8; - var table = new IccPositionNumber[length]; + IccPositionNumber[] table = new IccPositionNumber[length]; for (int i = 0; i < length; i++) { @@ -746,7 +667,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc long tablePosition = this.dataStream.Position; this.dataStream.Position += value.Curves.Length * 4; - var offset = new uint[value.Curves.Length]; + uint[] offset = new uint[value.Curves.Length]; for (int i = 0; i < value.Curves.Length; i++) { @@ -844,11 +765,9 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// The entry to write /// The number of bytes written public int WriteViewingConditionsTagDataEntry(IccViewingConditionsTagDataEntry value) - { - return this.WriteXyzNumber(value.IlluminantXyz) - + this.WriteXyzNumber(value.SurroundXyz) - + this.WriteUInt32((uint)value.Illuminant); - } + => this.WriteXyzNumber(value.IlluminantXyz) + + this.WriteXyzNumber(value.SurroundXyz) + + this.WriteUInt32((uint)value.Illuminant); /// /// Writes a diff --git a/src/ImageSharp/Metadata/Profiles/ICC/Enums/IccProfileFlag.cs b/src/ImageSharp/Metadata/Profiles/ICC/Enums/IccProfileFlag.cs index 7807ea4df..8a0c73882 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/Enums/IccProfileFlag.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/Enums/IccProfileFlag.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// the rest can be used for vendor specific values /// [Flags] - public enum IccProfileFlag : int + public enum IccProfileFlag { /// /// No flags (equivalent to NotEmbedded and Independent) @@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc Embedded = 1 << 0, /// - /// Profile is embedded within another file + /// Profile is not embedded within another file /// NotEmbedded = 0, diff --git a/src/ImageSharp/Metadata/Profiles/ICC/Enums/IccScreeningFlag.cs b/src/ImageSharp/Metadata/Profiles/ICC/Enums/IccScreeningFlag.cs index d76da6324..bcfc4f8c9 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/Enums/IccScreeningFlag.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/Enums/IccScreeningFlag.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// Screening flags. Can be combined with a logical OR. /// [Flags] - internal enum IccScreeningFlag : int + internal enum IccScreeningFlag { /// /// No flags (equivalent to NotDefaultScreens and UnitLinesPerCm) diff --git a/src/ImageSharp/Metadata/Profiles/ICC/ICC.1-2022-05.pdf b/src/ImageSharp/Metadata/Profiles/ICC/ICC.1-2022-05.pdf new file mode 100644 index 0000000000000000000000000000000000000000..6c488c874b60f841a5467f5c6f03a49bf8f8ad9a GIT binary patch literal 905961 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%0D1k~ybv41AX%SQpTA5yVM6gs5av9USatT;lL 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

{bypMKh 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 R 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%0AE2z#hj*h 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

^UJd3aWx@Bi+N&dV=Xv*FtAHI$m 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%0A03pc_$5gx0^7} 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 z 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

sfZGw)V+8(Q#e~Iz)2aA!}+U5 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

pN_a zQv647OtqqBX34y{5n|Iv>f3hOAw$tu<@jyNdPcro1?q$Pj3)HAZen}ayyP)yB1_u* zR*qlzUrP=0`)5UMBWPxnf{`6LQ_*3f?DCQ?v>)^37l?bc5yL|klwQv#>(tm=A;ZHe zSO-V$+sD(B3zZ6SCCdk26Sz726-V#ZdwZ=DLB11g&WX3`ob6LBtWls}EE2Gt%9JW3 zMrJnDZU`iX)(;4V)@n$-hYiLj`QD_JH3tkX|MKkB{)N%El=3xWhUK@8GBEzX@h?)s zS3IzgJo$|N+m?o{3a|ePTIEEmD)FoV%p5|c z(z`wIJNaFRG$|F*0_YPttVEtsY_`pIZmSjiCKn%8PpwP4EP1|xfIb@mrb)2@YLumc zC=>rCw@$m?)${A_?#ON;08c0aZ^#88C*cEnnSW*jK2$O1@c{flo`GEqQu@K_pstml ztWm;m$$Iphp0&B8p1hAO`rgI)>r_w@>=N8HnFb<4T7q*x``=PLIyd|Tbf1=2v4w^1 zj*em(+svuOw3P}f;ppPLkm;Bmn``X_)ihmNu#ZV8T;|0DU`6oD0PoJXV;yGYzw;Fd znXxmH#p^`@$(MKfv1fXn6{z3r?Y5re_+)qT=VDnF9o*;|UsbI5Zn2&|O3;*i zIE1|&9*I>VGp_QLEAi*>fab1Q^;X9CW}V^j?&nPN3U|4*mS;Obe5Sq2;>ZlyA86B< zip#%o9OYJiza5LdJxsoxo%E${Wc@$T0H+%Pb_j(z;I<BH-xjZ#~ zp2~<3ez%M2m7@Ogrp&n=c51ceSBsuR=n}9Am>kpSUh`Z#0eZ!Jpdy~72>$vi6+q|C zz7M9oT7@#n`0DqOfW7Xt*aV){2T~t?J0JT*FlmfU6(0Bh+A7CvIkk16*Qb}+aZ27T z?N+Pd1e-CtxXcM^G0Y|(cNp;XVs0$)VLN8Lfa~4r{XOKA;lYP|e^=86qsPsZEtR1= z+&vWwL9W_{$3)xb{?0e;C4c|Xwe5x3u3$6$*VVT)>8q!Vd-CEyyjIKBBR}j@J(4?x zYxPxLywN_Kaj?7FYgT>CHR+Yr{&!Q>r#p9^KlW$WyuuCgc-qo-<>-gXjl81vJDlv( zP2-DB?kzW0e8}W(<&Zpf;dg7zbBtm1T6BHv@vr7#;_Z;p3mkG|yPKUe{#-Cw2;wA| zlQ`vFPE8B5i%VTN9sAu+9u)9_u-2`7R=r`hYakSNH_D3zs6@Y;r$x3rwR2@}>^BR_ zj()DH{fMf#ojsfr`m>VOnSlHDdM%V!jw)F+shm$a)CS$2?PSBPiW;|&_hm8Q5yUBn zPZQXV#06^7qzr!@G!1~248J{j8-(`x>t*qyx>59V4%b@f@(y1Bjmc0U{Cc2abdKFb=^N`Te3FX~VPj-g5n9T0OL(j2@t*bH#x;a6inje>2NOG^#l z_7AdAyhGJ%Jsnibis)SM-1_+Wm1wYPVC3NwofCd~2Va#g&MD^65*2w}*k@he_)_`^ zcorp9-Rz>h8-&-)_u($)u;*N-dg8WTc`>uxW?O5?*B_7XSH&RhGcL#6`?XitGvhgo zt32PRt#jo&!1^OTcUn%T5MMam;_obuZLu5|p~Y*;t7m)zW=`A2mb)xy}?N!J5ep;XBu60z9Aq-Z(bxxq8X_6u%m*737_ z?Ml8Q?7-{ht3wc*md>)^?ELYS?k;I+b-#j(O<|VMclOP|xawvm8UD*MxkkFe?K20| z_j?UZTYA;{W?XC@fo^!KEV*}%CiM0P3FCLWyg-l6wP_W@=2hUlOkPbV*eoL|*(9H) zMUXm(Cctk2@j2`%AkjSjw_Y~*dmlg#32*^l-R-asq&mtJKQ(&L_B>v5&|0hv$ZxUB z3V5X(`S)TDJ`laX=XdPG4-WjJu_GrxFSK>cKWy$yIlH$pz0fi@xpKtu&n9_vU9*P`KA4U1^#-i#CGWa-T8}B5CsD_An)zI0 z{I0i49y=_Kn?%R&yT|EUrgNK3O5C-U zqV|8Gwql;vMQVIl+x6l+m5)1BEU#!uR=pI^J2{VjUoC<@gHqnzeE1)dV2?bin+B{z zYM$Xgx@G8Guzk?X@NMfE#w*Phw|4TGx_}*612zJMsvvVNk-Ubnw;ytE3whZi6 z!1lw8n3}t0KhIrj9&A-;z?s~Qg1BG{(=RI7q25lbbj;z_9_agBKZcmIVr0h+>LQ*E z=fr;M`UKaGzU$VMd@kvS(0${9_Ww;G*^Yn#yvVK74PrkgKN6WMim&hZ1pDaCmvpFt zZz=GjzJ~1q^Pw$ito7?o>w&!Ju7yxP=$4kdOEVR)V_zCI*a>QOkU)4{mW^_dhv88NPwkG1Grw{KTz3n-xsfZcJDV2pXLJdbFBThb+p%} zHk}#;*zNcxci|V@{S*Z!npp8S{1GA1@-FbD`wAZdZ?T#`0{z+Arp+X3`jnO_#M=@6 z6TeiB`vvdc1KeB;2!b^FxkJB;m-{|Rxr!?tT8P0z9Rjk;>pao(MZHP>ayiJ+W02F)F{4>s+Qq&eJIe|Gm-B>s zxnodc472Kl25X5blQnO(zca=Osj${+v3yrgBh*72ZzYSXmLu}As{p68UH1vqCPz~n7H_s)n^bztE$3FLz#x&uu zdQnkor z>mB_f&@F_MHsHkgUx|12!`-ydOYvO$=&jud-5wroQ?6Qg zwhWI~Ec=s4^Mh)g9DH$l!#C(9dzkOODe_~^zFb)V5_mT8R{8jn9w8Z-zvq1Xjq025 z(yEtW_jYT)bv60OE9;Vt;3mM$Il0H7P67AU-x5S(v(D>6e9n{4*j=i1jS*bln9q0J zGn*qyJz+D^U+8wtLu}x{112+p%Xbd z=#AXsUlRvU)TP5~{&=3lwibK8C)d$<>fWGfQz7a7)5jbLs{$8fXQ1{UKy&EjM(MOn zFVee;6m@2b-28BV_U5s7?Aw1^4&gTx2EOUkB9xZX-8JJ@Yh=Fsy)JeM^R=nvRAx!> zv(}j(vybK1HSQfCpV1fWFGJ4>-9gRBZdC2Q@H28x2z>L)_Z8v?UgYzk?%j8EXD>FV zO#MA;ZSaW`-zDQepbqf!4CdqccYdr9nR9;pJY@GzfwWQfA&Pm#Vuww*$XZ2d37VEfY$OnKig{tTtXSP{r8M}hC7ch(Hb2a<8&U8=pA2PcrhcPv4 zo$P8s&f$*?H#zEqBd?^`aw-mVy{rELT0o`0 zh)>^$-+l#sjsE#+<~YR3$y(-~1@E9Tkg+#?T074w=$xSzHTpF1V|aaEAJ#XzxbJfg z(Z}e5jP(<`IG-WI+cAB8o#^K_i|aE*-Ms5Lhv-6HKc9S~9`o+PKC?MD^_^G1PTsSp za|VeO&Wp%JzHi;F^PEHIyA~Om(&uu{ZwBWOecaWYyRYHbWglK+Ok?WTsJWM_Y3`8d z%U&PKv+$93IETksXE5VWqQhyN!`+<26AA~z>|F(Vzldyyp;f&9wsQY(lY%QG-lyW; zOy;havzK@CAL0L&+~8;2^)EwvsuOz3_knYj>SZd0`&&tKC2tGuA5gD^w&i{N5%ayK zQSNZ$znZtkpQ-OQyy!9ReI;en?*w=d9goxh9p)VaCaZ~S@{y0}(~SB7-t&KgE>rX1 zde%LP-Fxtkn~VH!Ym7ffYc)g1uT^E>8w z5&3_Cym!$Dd9aVX`P3f*a{>kXWe9p!G_YP-x^=Jo4ljxHr7yl7{*xdcC26$cYtx^qg^LP{GD~DWn zF+SYL-OX7%sGh9$H4b`7WUwalU8p8TEA2@Qr8i^S|;wJ)sWP z-|>SFIOjc7VJ+tF5oaQ(ZdM2Nu#mypMUK~=wMQY#Ky-SYoclDj#dj*K&&eH%)XO@b zbDu{Hc}Hh?^_jassZLX6+0sDrcaL0fl{Z2w$$3_B23L{OF0p55l|5K>yw?7A9;<@G z$m3h_ZvB-Ox$~6c-h%H)*csS9t8*=`@sY((YU(_@`0vEyV7 zwoY;vAB~>GuLfJ6YH;vAO?1uQiu|4a{n?{-^#6)D_lC|T{$(;Ik9@Pf_W^P9CeHtQ z;%&ahk?#%grgBzaP?@(u0}ORnvDed~$CbvpZO!>?jlEkFD_SSb*D!A*WA4QEh0uf0 zN)7St|0U=AZR|fqJ$aw^bUCwLcjmm4eVe5v&N<`~{jhniCXk<05KGT=rc*CeA8VVM zSv!cypQ@d8y#{-SiFF@>Y;x9h_%$)yUQV8HE&KH=?vK~~v)b5O1MeHvaW+Ep)Q5AG z>O8Ci#E|8@dk(P22iU6vyvxn+I1gBP2GPULcKEO806HAt4S#^PRnD|Hy@s~uRN((^ zt%dfIJ2nkYRZH?)mpro>aVFpXgfmdCd+ZgwbIO6G`IgB)Y;ukPx+f6TZGmX?d2&)y zzK3&kkKsEb{QmctG34F%*dsO8dJJ6#Xs7+Knt5sX*&Rx@ACCUnuEd^aD%A}kLlN)D ztDxOLs`k3QsBh9Sp^Ml|V~~IVE--V)`=pH|b`pz##e@d+3+Fw{^4O6NgRzo6Q)` z$IaZsL#=PvpPO_&=c1W+flk9-$xhSgTg*Mgt;5-ROWDNN3SwwBc~ps027QwH7-d^i z!5z^O&Oo+3Mnk-L%H|D}O`NGf-cdf?N&h;;$QH`LCs&dSZVkT2n{yrUy$D-A25pbr z%b8<8cgl26{Pms1^q<4{k^~;-PRM{ z9jfp?r~h-r-{-UwEC%a9KX4mZ3N8h+zzp_wjs1W+;1BJ&yZUin}@2faX7dW}?tUshRvR7dwl z`1{FwyJ~}1R~y{d=--5XhF(J3YRcWn6JBJ_3Z0qMg}bq>&U7=li=Nj)XD<8nnMM%L z*AiFOQeVrw=Q%5R4<6S!)(x6#U5rkwNx|8~*C6}*JpFBzGIp)~jON;Z(@Hx7 zfB6R94z>6Gp3Zu)z2f|d-1s{5 z{)X~Y-ujQxZuBTu3+O#=7hPn31g{JAKP$x>OL-A=j;4CsbrHNu`%QS)a_3&fJ#~`u zKrQtyr+$wvvwH{X*u9B$?;$q`mN6%L%bR|?0r5Y{ov$3{O>N}up5wLx7U-`lJX<-u z*K&Asi@1~Hlqe^dOk7K0zU%1UfqsVO&^8aden|Z}J?-{ZA$QvpcMUQ`c{hBaOlYNJ zVoW<_NJg%kIA9RQPI6D4`^2^#8yg==-YkO?B7Juu=*h=Dmd;8Do z%6s%m+A_(dx_O)M^GAr;4H!E>t$4pBkt^q5&m1?Ee04gsmomKq=y>cuid?n<<=$$9 z-(-8|qRW}&UWd`+EBM=>i~aG9eEo9h)0G&DF5Yro>^_ZLj<&iJ(c?mL!AJ4KXV`}% zbQ?e%dx`c2?CnN>AD23JAyWtXZKK~LVv^Bkq`KlKqmk=;`(66fWB+#`V;%CP!stow zY|0mEHE*7aoVKh}f_{B;I{E5qa;U0cJ#|f-ff~C#p>1Ff*bMFhlfYA8D|j%@zmWX@ zmkE%|-3PjPEqN~*q;l2|Ya98=PH!A^4M+taQm@oDyTkwD-8=xJD)K-6d-KZfCLsk# z0tpF$6d;=rQV8r3$c7SxP(lw)1Xds*&4d!99U6L7kgA|3f`}3V3fw7RgQ#@9Q&ABC z%hB~bFbKT=cV^#9HcL>i{R5x*&CHvbH|5RD@Auv;s86ji57uHHtcAY2Rx1LX=mo3+ zZuuSRagLtDJbyrY0Q2Q5O1Hj`_QI}KmxCDWdnZtjA$Tr^qMS#N{us)QqsL$)j!|7` z*EyQaK15xDDIfDb-*OXuPzchHemoT-?`q87+0dDmp#C}PNW}S)(=wmBV&7`T{mLI{ zW<`6f;3)MM?ZN$dTXp+lqpFc<4;4?~`& z9LovV9s58UZBWY$`3bJwfSyx`x$^}5fc0a5bq{RacF-@Lgx$0V^JFBgRAaHX!EHvX_2x7Vg6oaHtmKT`x0z|`FOVM z>W7eoIru6)F50sbcIfl)uS33M;Ro=4d(t@ z=$!djbH-DObsDAk6vKXZpNr1He93_=F%JF=K?3&Hc*7vy9xgf1YQh;Smp zi3lgkYiPIp6Ktxp(AUq<(+FoFoP}@}!db9CF2GK>fOYnQk_rDo zh8zqAxxX)g<_I@OxcP70zvB9k`&>UN;;NRxzpLGwuG_ue(0IJ@9qk8-#&cL-lPFq? z1Thqi{*BgNqK4XGYG|2A4Xq8Sq3;oDsJun_S|R0Ivnk&Py0B#f<=dX8e7|-GPk}r^ z`GHRH9&@~zu1cCmE7PbU?y_v-q!p&0r}y;RYDus8tf#QR7wMJIWY|u%k-sM82PIQ} z=m5%>Gb^7>{{lR#4Y>V=Fyj2jBJ6!V)9X4pdTf^aJRKPTT zHpMdxdu0GeebWs;gW`!b&o~>ipK>|o866&PQgLp_z`G3fXPPHStBRHZd9hML4|Q{~ zD*U?O5X!&dMw#OV{Wz7QO`)-1hQV0q?Kxlu_F6aQSsph973X3eG|nEGXMld99vt&L zkdXY0kZ~qQ=I^qBN4SSLGjvOwTPlIyhhv0yR9we>q0{Di%3p)0@km$T4fa6M_x#KP z){zCg9gqb|0ru|#$TG_1_{^hMf;4)^TUwjab-&?s%bMVp{M)-_ticDA;S)p|rnG%V z`}z4{zCQ4^!PD<|n1y!=7SeuXwY_g@`c?m(k16vubvbkuLrHwd~vW%Zgk@>qVu6vKea~XlO5s>>K_rq?e zO=sjn+Qxpy9+!o6Ad6h`66}3TAhT!_D3gQW52CVr&TyEr9Q#{2%Br$Q>$)6Pv~yWWCf&@c0#KaW8>htX7V%}q}sx8Ql>m|;`CM=FRiWp!tNtYtLycbyUP zz}C+V?Dsj|SVJH`fPGd;wt9%>Xp7K?u*tM8w8v zD1$9{@0pyZVEolI5b$BqCGtd&_$+(d@ z5kQA3Q!kT?Ux#il()}B3uRdNXxPPANukku)E9edQKY{<_`{hTP{kY!8I}JaR>ru{r z*w)iIRoYe`{aRm)Un&3Xsqx#=41U%gagEI1nyLe-g=Hq{@(kr!9;egTM{k*ZC3p+_ za!1^ADi{I(0gOo<-0u;3!$g~m_|BAv@yf#<=gs4=(eim&@*&i>yTM%K1BwMYz6G|p zkd;{c8ed zPiKCkROZq!@qKbe<@ZWu7$x!Vl>ED-mO?}LH%iQpAy_+yh;r{h?>SG~l~}CPn`wmn zSDNVlZbbbmz8k%SIWe8$#W%?2u)#OdNdBEtZHT>YE3GlV8_E29*t@V{Yha98>3`K) zV$U3Hd^b8y4`H0MlwxY&@!crJ{NAV5LY?_pN&da>7je!&eADCK`}ns$p046sUmDtp zYa0JdB03_o+ynY?setKEy zO_`=1>Kje_IYB8jfD>S&=hRF?cbg)f}_(^K3y$$`(0N48~ zCG@_DwM+`<@6`A^1TbH20oelWPjgEimfj~~Z@G~bH8AMo)CB$;EoBAL zJ&1bsg#FNy;*5828Rq!Nm(h;P)RtYQ^B_@n(NNGvS&g~9n%c@W={!i3Z_~pdOD&{l zK$hGd@$D&5c^hlV+tdMhFYx@{Qa*)#K85fKx~Vph2BNGBqC9VT1M&vaJx@24BXkpG zU*P3?OC^pjfJC+r<@wW1_8w$6-eTPe(m^M*Jp&+o=VS0T(d}Qr?#l3;S3rsJ8@FxM z$XDF*ZZZFT)W5_!D)J)DGtAbw;lB~{U_zDfvHOrj12~$kdX(i<(?tHBay?MI!uRqW zjq)PWGt3;+iz9vySIHl$gg?9wW2lqh_IerBPlq@(i<~Zj{GSk4gr5 zhN1UW3-*JK9Cb+bC?OP5!8qJwKjzVE*ry!iz?$|n^n@a{7s$leuf+8~ft5yIK0@7% z-*=k7?Q9KJ8qZx3=n4vq-$+jJ_}%4d<9C;Jz;NStmS4i(%=m5PLL1Af>Hf{6 zzSGU!+K7YJdABi$g#R`0YSrIT-VJhJyE_l~BkrG&agaYlN|4ha`xxb4cmGE7&JFNG zrMx=~@(ts6mXCu?zao2q8I@A}Mze>TJ400H(Rh}Ml*2SsnN8!s6txHJXhp;iQC<*p zXfpQYX-ba14SLHI^zTND0UM@v79>!bQMKF730$lo4$U#24YXY6gms2RpD zk&hvCpCa*_%bS=>U9s=BqlwA`*smX>hiz+Us`V;O)ece-_L(Bfw=~J}6iwoDANQ#* z=C3hNJu%k@?W%YuJcZYf*U6mo{2pf6{F-Gb63GbgOc(-p6 z@+@-qk0%)SiQe$Gds6LKevJ7JEJNHVPg1a8x$(T1^r2LxkA4aFP7q@=2lU0g`87Pl z(5H)(p%ep}DHD*k71o>yAQd|2Bl@!(Z7TH6epn+@s5_fVzF3Pxpv(4BCu1!cNUh|F zG=d$VSibJ4b*Z-eC+Z<@fekwcd-Tf`ZLNj!x>BaLhI;XJ9%~PYwc1>hJ&>tS|YoMzoFJQ}n%oJkRKVFU)p%Fp96=9MK18i#KTh zX*aMtQj9(XEI~k^7E93YXj`e53Gd4)c=tsC`Va8FtOD-`FZlD|Np<6m{;9=*?H9q3 z&rm2w^f~WW1JNFo!PAIq{5i^Sw_iMy-%~34Qa`Q~qV3TAMV@H=w!D)D$j?L9yhx+f zQrL}=utWM_j5{IzD(ZO+Z7QYqYCjR*M`-}t31c8%p&9aD_04#0^Ob2BL-!sYq2QU< zwoo_aUEGWB+wb7|S>$bx@jixpUt|4t!2aR;?_bFesA$NqN>s zXtXU3YttE&Hy3M(4m<1>tg+B1aGzR2FEIB0DtPK0UB$f0=XEmm2!0Q+t4eH-p4SLh<65zjI1$IHVSISPB*D5V+7M>{I=SJh|og${yiyiesl z=qvPr{50iY&uWCS0+o*Le5@5&l=b3X5j+nIq(gEyI?NVRBj!t+Mfnp^zJVB{Z8Z8G z?$x_SVLclq`h?fHl58%~*6+~PRMB4ssAm<_ztF=bqQ5-xZf`2eNHzM)1Nj9!S6+zc z!ISF7wj*>;puK>(0F-d_XSiFp6VH!8DVi2vHB7W-IE#^YG{V zuUK37b3cf-^En~bm8oE>`0eEod7n7DIZD|AFdz9ECg6JFV*PV%J?82Z{ZGmt#9G=* zvC~i%tIuP70H51C$ro!&zS4-#Y1D_W(Z~zk2|Ak&EA{SU;2Nlhum$?mPlnF7#n8`+ zajhrhdxq_^*sbr~8EnKqXE4#w5qG=GzH{0r<2@sfS>|g-__P5Jzb5nxLwDm+`vdl( zFZ3U@?wEVqFi+aTPMuBZAfHQREWM_Tgk8_)7JsgdHG@kfRlj8-p1UUy-41 zq&LWg{g@h~Z%}UQ|I}3doR&$X{#idJt|y`%UUuBC<*_7?#<;Fw1%1sy^{YP=`PA1h+Z4BKg6Z`9r;Diwlg#Qz;6R8e>Z2K z^ZpmHB>y(QYyIwy^&40-u#T)1Yt9BscdXxeSihenverPp-?Q$X#Jc+h)*h_)SZj}A z4ccH`N93bnP2%xgQO@sK+up|7mXGvfQN{S*|6z9q9V(3=o9?i z!Eo5B<3TDl)!M@jhV5!m!CJ(v#(vHBaBd@;?;OujuyzvZWJ*#QB`G@6y{n(&@cUVY z!9MMWxCs=aK4RFyNT)5Ve77Oqjkw=WOy=-Bye|CR2(PQa)2@G-#w$mW#z5RR8{>AA zw@2TG=htnQAEtrY=ipiB(|u{MrHEoIyzO71oC9b>9!*mRzz*Mw^}7)yx3QjwJ{S$V zanqrh;AkJp9kccQL)MZSEl7Yg0* z9n{nFT`J0ypF%xvV{dw1|BHOwuR~o-QA8}}tup79pZN4APqYy0$ z;mH&)z88*#zTc93IDB2wUWdN-Jo1*H|35Ra^T!aNzm$3$(2zDJ*m_YYi`Zwwx#NIW;4F!s5K%f&uClnvLf zusYOCS%!6CG48t-`uwBdNgAd_;(q*$%VE^7Ej1LRf^6I`iMq)xs3HG0DeU{c`W7}* z-y$bcLzbZzvPZyc`afW!YZ!a03|&*$?-#}UAP4&n+wvFWBdZh%U9SK-+yEsBW8N5J zU5L8Aj%P1cFNEEGLw<&a@^>iQ9x?N2AE3WKf=wHQI%eb9Xb$j#P(zMVN58FZ)qm20Xb9}9Ecpb+W(vxlOWCl+N60UuUml>|EFE@fCxoBD zJSf1JFF~L5LmwYTJy(ct8v~Thu+5gimad02!F;!Lhej$+YJht-kniH&{n6jsVcUO$ z^m|~3`%^7E>rwJ*^utE#&CjRe*^A}#LJ1IOi$|j#qtr}_=JQc5!T6n^BzYB{t4-+p z&maeahcPeLqwjCfVCfq84rzBFJ`B$omp=*yz!q`IQz=jGhwxf3h!W(F@th2#NOq07 zfMmG~@{Ffm7}u7ty$7?af^O`2>daPBI=e|((%X0z>tfCL9OK>@Bp}TpX>VMZx>pv?mff@Qqd8~d_?y8@bx5Ga8QvX8!vp555l?$;RouZ>8z;#M;TylWD*U=De-*Q`;EzmECcZ$pKY;~b_>}9m&6#AzbHCG zJZBgS=^I*svQ|j%Q9kG>=kIM16?>JV} z!@Dk3>VfBfr(hSQU=ECsC9GBOv$2?a*YLao=%QKt*_BraTCfeoq?uH}#?WHMe+O(x zd5-v&!O39LC>v{JHp@p@`>@t$(HxFgSFgI)Me!VCEma75JivND3{vXD&qV0Z%Jo>c zyxT*9t}Y$M^_${6Mn3A9&%VK4w3Qyg9N(sPrX0+*4qzScnuIJnM-hH0Nv!^Id9!1geXy}fou|`k8zJ3BaoD2T5*n^H!SDyC2 z&a)nD^a}r*V0`%bfezL(Du>RLCa64PySU1k+kNyX$MfvBc}7{j?B+gagIDq2IzZnZ z58Y|KnvZc_j`4e!M(v|0>F#b@9jSBFUg?(UDK|Yoo1UAd=Z5LIZhEeno~x$kis`v* zdM=rsZ%xlPrssm`Id6K-nVzpr&so#+k?A>QdQO_2ek$CLgnLxDM}+%< zaNiehnQ#vY_g&$>E!=~`Js{jSg}Y0*JB7PLxSNIhf^atpcd2lf2zRk?7YTQva2E)- zSh!CJ_i?z+Hl3qpi_k3L&J^wp;SLjS58>tt_W|Ly6|O&b1G0u=^QjM#Kqlx8hJf*4 z7FY&0f*s%hI1XxHskulJ&4%*49Bcw5;2<~w&VuV)u|}z>C^Z$OrlQnTl$wfCQ&DOv zN=-$nsVFs-d{Bopq)tQXG^9>L>NKQIL+UiL;I7g16}Sdu3V>T5WP%}JqY~|mRvt5lkPqr7^t1YPU73*Oqr{@x2jQLoXTfzP*6F95-G6;Q6HY)@ zkkSAJH^7D)$nuan0Pb19a9bZ9R;;_FfH)~2D_pUNum*P)3l(WMP<@aDGC_AR1ZeaX z+-pE*8=Sr5ug->q*8BLca2}f;68_lqx+hP;KY0qAu@m4tG9J#DaUtPj#?5*(tZ-88 z;CdrR!x@ne=iyPc!yg`1JTa_pLCCarbsH3cx>?EWNm>gS)q|VBeQYgT2esIbEn!R9 zGRTE&5nD`t6wcPtB7i2r-3a~yJ_ichj5J%Q2HS|d&p~cL-e;+X{yke-T07dY51w`0 zlNHA1uo)O)JNqM>PAcR~=r#)E3`0(1{Y3l}Hd4rutY4{WkJ`&7l!iw+-eiyBI!`wa z@d}Ucw<|f-Vav*56Jdu;q;0sqSER{D=rnxa1DQR+iqNBWHXD-Xp9RV5@t7ftSYL5{ zDjNZH$<8K2^7u)HEHLB`k(A5te8!ciCX}ARB@%?7@1nUXa~b zcb1E;^kv;Z5AtDysTKVF;hzj9A-o>p*C0QG^kMnPF$Ntv93?#r`4CDP2AL0?a5#7f z3Qf-q2a<}|`>5az9J&4SQt*;&Dem!MB(&>_HBD_pnWx&xB8u7#1l z0n%G|FQ=B)3UOqGuq5L`Q$r>~@*5-=VY?yYkx{jG%xa6U1mi4-Hj65?VyTqF_%WX# zD&%QdTNWs8odwBD%7o-q|AP_V(vazfY;MRXL#7$|k`39+h;L%Z#w-v`SeP{qVTr=v z?qexvawx0A>S9oQnIEeGX=OI%BL>F`e9`%#sI3))O2s5%?y^6^2a5J)YnBkl4Tg&h{Z9ecZN!sPi zT?C)RqvfcS! zLbBt@6|#N)iZv^kZFrsGhlk5i!)pYf@awxf){k|3xL5LV)|1w(lI$&>m7ZS3>~&Vh z#XCY*OM$C0osQ2|NpDE$QUdl1yVR`osA7k5QF?@n#L}ZOL;{a|L+T=R7HK+{&Qk6B zq=8az%&UN`x>9d6w>K=hxzc$F@QmXNhwUnl$IJnp$^KRI6CQ=NmGw6#tVUG7dknJCoDRyUBgN8hIS6OhV zkcZHlLWYEi)X@hLlO4G|&`&+k-`}8F7tSMaK0e-Y^a!4yBW>G@^hX*s;&RWC&@ji_ z7bUdXR(e|8*qM4UHrDagMalVYc!XouPSw5>1LHi{y0zor4#ob_4%NP62A1p7HA5Wl zy(vX4l>(PayvRlAEk)6b8relvQWl}?#Y4gq%EnC7ypC|M6_}&mU(= z_L->F4BX-h_;i*ut2nm){9?&I4?KapJPw)^JBm9M%Oi@V>|!asSc)r_!dnE_Ne>Qg z9$YgmI3P9HFD2NP9IQ19mXm_1X>j?ifT;3j94+xhcYSgiW)d&s@tx;2{ zT_dS{eEG)mP36bSPn2t!<<9aQL> zGU78DXT)X1WHii(%81MeToKZ6)Aj6iSWyl$nk(=6EDyf-6IlbGK)RG{3wJk}t z=j@fEdX}Wvb4qNv1M_xD($fBjEn)L9pL>@m^Y=1{n(YP*%-bu~<(G@Y_u=uTlAMQ% zm-M&WBT8I3z4A(CNAxdA;hyCY{VAs;rAJA4bX$9Me+7k;Oj%H9MB$(K+u1m-LrHvx zp(P0&9%^qlW5u6TfIoM7BUgp=_(Pc$_p#siub@&$!bgR?utFYFSXd=tVYLO&eL|wd zf~tAQY_Qq<- z5K7M-SmGDm7G)Q>{|fp4Ndn+d0h_=wuoNr=^T9kY7YqagK!1=2 zdV^fh1>}IvARROVNgxp<02{CX)tT@5$@Qb_2iJAiHP;o_W!FX5H?9k=^RBO5XI!UU zpSnJB9d#XXec*cERpvV6de`-~>!9m^>rK}#*G|_C*JjrXu1&6`t|hL;u0^het_7}Q z*AuSCU9(-YTr*uWT*F*FT)D0XTy0(cF8lw>U;qD~+YolP{cz^0y{R!JP%}!S9A|8B zQd;9C36v1wo7^-l!MABs--I-!c{(+*H%qNqtCoMAI!%*h$~>Bqg#Vde{_SW=P)#Y+ zk%Yg%qk%_*QUi~s1b%raxtY{Ftqp6@MsA)K7v0dGS)!Y#r>CYwvf$bX_{+h;p~2D3 zrJx2u9M(b$iH`}53lGR@6V)uHuI-_W1?{qjx2YEplaUY=7i_7yT)KTnlZW1JDSa0b z5*y#VQQf3eM|4il+A%4Sb0V8Yq-HmXYtuSAu|Yzk#`Uyu&pmhdg0k+H5z5V5+xcNI znTpWX(P|%xpm<8BG0s*Y!Rhhw>2mrCXS`oT{EEiSA`<1q6%oz|>BaUDHT~k`xD|d* zKi?PI`^iBw8#G7`iLW~|Ik{!LeU_T^bxKV~($_%_?oy_m!s-NGu~Qw>2X9i?6?;%k zayXKkr8aNFng^vdWsRCQNC^oEuB~a7V7H8xQ_`E`O7#CR?j>+do$31LJLhEIPWBD5 zLJ|mMJ0xKV2&7K-cCEyO}osUrBgZF?>h-Do!kHK|3eN53Ca7u&+|U-@w# zxwclLP<5+TsR)%GgFP4%fWN{pya`S+Z{nngz%6fX~OpKz$Nd zsT|_1CjYxI5cIo{3MKF#7UyDNLRad1cUP*!OPz-o$O)yB^A(an#W@?Ll`senOj)GL zp+h=S)n}+*Ts?TAv*GUH=Al`(zOI)?S@y~0oN!wt-9`@2p=h;sV_y_vf z_l!oc5VXDnVBv$FA&m1O#y)J<4>1L7EoO_PwFWr9a4seGW0i z+~GWxbQlQ3LB`=LJeBl`2+=_wp**QjsSMyGjvMT@lU8d$Y}n?`fX-bwcafhNq|-mA zE_gZ24SpB}KXoDFG3m4`GtMISol1MCf{4ykyq?y&%aX;vMai}Nqzkc4 zjLDPh$~~3DTtGy)Tv9xnmrZ0JWB^aCK$z!2%oP~bMDA$&SW*R*l}I4n)D-IXP+pPdmrsg6;f*UxLJ= zS`&Mzz2Cc^{p`i_?8gTNm&e+h3gp3{)at9MNOJ#i_SwfD9zI;&7H)SJmj>8RTuJ*v5A6*GSB|s|cSb9Bu5QQYv5(YN+L5={ zyME^TdtQhLjj6>aYa2YmV0csfbVF^n1b=YqF=Nfm9o<_KFe**cpA%0Ilb8z&VSj<` z=Jbb8DJWR%&rN^Gh|w+F2eL`ex#>SKNs*$~BayfX_aSDrWK8me!<)9A+}LI8#yk{fb< z#G4w4XQU3{k)i!a`mPt=3Qvc}b%0-}h(#JTD`61{kQ zCJvB_`iy@X&Ud%K4GBrO!%zaD!zk<1U4a&)$eL7N+43Xv`(E5xzoWLMnvm(;^p|CF zdwfn{!`-`aIW~x@%!IhV|J8NWW1*#Y*C4d#9zPF*bxh<&!4|=(OF;X zgZaJ`df5yaX2;euNgD_N{0RVnbxb|WhN&o(O+|>TDxgpSBP<54yjqpQpdb{78H3IW zi`xWar6@|QvZ>Wh8~~?yhZ&`xe-e6ZGEO3dv24^Gm%1|O$GaNUR_ROkY&y>(}7PZm;^~&nkb~f)L9(b#A zwx#{tclxk|8!D-34wTArEw5W1SO)k(^*`Ayvnfpn5M7@lG`T%-!4LGPE0%z1M z$FF&#N4P>?A$y^ukYR$%;K$c^BcH~kig;>i?BtVcU*4P;E|J@dtNdfPu3TMET3l+D zUx(tRIaMB`q)2>{tg7;S^~uQ(R%;FH**RTIfoAfB7hX}=O9K@_6oDa#?%fbwBgA(D zld!3E7Q2#A9%Afvi4L1(`=jwQBaRspcL;f5hBx*$@2FhP&u>W%ZkC*>YViK^i;4HQFsmNgtr|ViQCFWQ8t_H1>2i8o{X>|Obw3QS{rOzbBLTn z*#Q2v{Q;X7A2%q_j)ek^3cr{BBJ?)$lPlJUriirhOLU0qS-H9goL8#{5mrKdB4O`N zhhUSA6btq1G~V}_%$Qfm4i>ny;*Bn&UMV9*q3#wd9cf(TDk;mCe;ys9E2&=^AW1ll^3462KEf)HP z5kffeLIfxx)`&ksh$0ccq8T(Z7zMOYixiZV@>8Et(-hB1P?WzGz?UGf%S=dNtR-qE z7-N<{PQ)ktlv^xyG~}Ql<-tJY(}Ks-(iqm- zfU1B*0iV&J)wa?*^ErY{df`RMsh&z-g7mve$a5nmFt{Sjtf?d+2Ny-l^Vz~ZU;fgZZHP#aoM+`Ys| z)3@K%zC9^-*OpGqBiaNK>+*{G&uUAHb6r$oRejf8&4!XxO?=R;t`C)Tm*?NnxnSG; zJSF?)&AZ*nMZtxm(XCf5xmqLbt%3GfRyf}XIShLo(gAg<6kEo`2ozo111|twFm$2R zUc!^-Ih|DHX>EXOMNu6pj-E~yVk6?I=?AynrkASHv!BK7;H4ks-}&0C%G z70y^8&4deGwTr8oH!?CcQoa@N62(4*sjO$j#1msUcpS%hWZDTRzfgG5${_mMhaY~3 zo<9s;#AA3Te7=oQ;ef!OVlV)-1R!|;^OT}S8F~x-hVI$Jc09%gz?3dT_D5b)Dqa0t@t&=-yW z`OL32M8X?>eWoT-?hRO+N|nW#m7hzOb+L^DZ-F_$0claJLJ6IlbR% z6z|x;TkMnUd+ht{<2M)u$}&a)?0vQwzYj)PfNa7cVGl7lzyyQtB-Rz~M}bQUV1KP%3nz2Ua{7%0#J z+Rp*$<1OrC>>2hrJAuE>{)qhJM}Lpb@?d#<16pLlDj17Or`76(e34Le zBq`LBdQ7g7%kv05gy&wN(Wnyf1bo|ml`7xp5s3`98U63leq@;c zi+4hk=qKjqdaMgx8iq48vp7M;5hgkm9d1JsL42I4d6^v|ERu2pCJ+8xFqWgGT9sE` z_1<~wTDmxD2=vW=g4!5z9-Ep^s~PUEdAZYSfX}m%0GKe;>{OI z==+a_7qu-J-0&()59|)efY+dJ0c`d4Rn-U zrQJ}?G+(_My`4y|SYTar;}6&JgD$1D7RZL7}idHh4#c5zWyyZ*T8=~C#hy9HUr zfj}4PIR{hKn!5r^=xVrm`jJWe&1n>F2%wtTGey-J#leiHV#D2WmZy;8AT11NTF9fz z)|0&T;4%v&24MCPwPyE)B(wMuVw*n-Z}4UCbj(H8^C6r}naS=fmHlL!QdzzK1uCz8 zFj=-W0<>F63p>AsIz8TiGQ;)8J>N?7E8>3rx{%K1Dpe$N6W>%aV<^lwSe zLcJYQUdA}067}a_EG9@SqWn6HNW2IU=qor$M4v0 zdKpdHK*wC(j5>E|qyGgN*2j!RI03bdxaVCjyZ!L)KKb!XHI^zeRbr(Bo-kdL z7Wyn}C6$U}s^%&_`=;$TByx?x)9~|v_A|u={ zK|aO@(rYUDBBF?PV&3sKqaWuczv}}*8IupvL9QJK1z=?cB@};)_{CL(=pg337r7E| ztFt_qkoQ6`n}c-^){Php{m3A4HYO6cdBRAaOUh3(z==iUxkx*{g254^;c27@GwWjnhbjXEz3G zV$twbD2e>oyQi?DfQuz*AIBJFRY9S{_OYYYD2+!Wig|$Hd41Af-?z?7zEd=dWK!6&Y=FzE)eU#flM zn#ysAoSJGwsVi#*bm9j?*S~6CO-echnbl>q^vRONSo6cNnxCsln0IR2vE=@O(L`O0 zAFH?xOA0cAUvk}m0>ypHi;mm6#5wi!eQc656icAVlQy*Y#lIw z6y0to|6?xC#Y+m^B!gM_aBqRpiSJrEFrof!SlvrsfVz)|Q(%@dkO&^GNA@b6SfX+W zuPGV^N-VET>5=EWaYnyKnH~uWQpjD49;VUX?8vmMsc_p^V-%_$l>k4-df)k&Or-uB zA$f7M8AFNebq><2;x}l?b0`S%6UGK=9VP3buA{Oy3V#p}Mc2$=IOPuUT_njMq2-*o z>7$kaR+EwW7d*bn`4L=VK=};>g-!V1{fQYs3So0sxBLN8<}v-1iF;rtMNfwomIZ@C zZhqDf+$u6}=(jn$1jQ-q{Sm1E)S$-J?K)@yI|xuG&_WwVzsc8 zlT>69=EUNZlnTab2did_9>{Y*;eH^B?UiMBqlE0aIaM?|1*Rw8!(U^m@&%=}wSFSF zq`L3z5?FHtV>W~;8{(-Wx-n39vYIqCU-d%eiPAp?_u&W&c68%h!j6o?qC`~{egn{z z_yls(aWg|;Cu)SqPYId6tUl2QbEovURnjQ5loonxdW-ZKfu1Giha-CVMAZc2XgBE2 z&?;z? z`C-g>Uw{q>?7KxWg3=_th=FU8J#l53HHu0C*|kK4avA%4j=51<{ZXzIR=8-+El;o} zudC;5Hq-pIJPsnPKvkkrsxam?+g!W)>+>{sA5P3wMc>!N^-oPTOG4)#08Vwu*aLX4 z548S|Ea{}SYChLz(8po(0S7r_yV#DRugh?}@URKwjUK4|$CZ54w}=%Z_VCy81QRFO z@AW(Caii2ryyl2R)^ZC@h)jHmd$4zSUEtGWK8}Ue8BQJJm6zY)fQX#LwkBsUcSPS- zf=iC!m-myPfvfL};w(8;I`}yiU)qydLYU*kDD94m>6rWKMcRG`H~3s0z^Ji5BxA5B z9Cma0e5?Q|(v7eA)uMC9`Q{B7tHQp&Cn#o5ATO}Phe`QI%GvGULfvHV1XH22HQ{ez z(L@V^c1AU2Q`5?-DDa6>+~!z7-&!^uR#gr)n(xQS9?EFM7Uf?UCdJ9A%m34*IOf3?`C%+vFFj}ke1Gs&c^)N{yQzZNqe8>j10v5-aaqe2HL&fYN|}l z>4nR(7Y#uNPYKTlV1+_Med+;BGcEGZ0fHE5ro?2^qL}-TxTGWEkz0(p5_rkNBSjyjqD#oKRFcW;K#ic9;#P8fQLN$RWjU}LXkZ2 zcB|Ld+>d|*8z#x8IwQCa%~7lq_`4=^jk?!Sjla)j$xplp6MnzPr4*|fJ$8@dH+!q^ z-G_7U9W?c0)6XyyLyc< z4(IeO#3&9NvC@Xe*sWRuxNBD;19zHHhJFFew!XfGRq7>a#Z|kNALFOIpX|i1K6BB zFK`W*sj*==YYYJB29uxOVx-5;qd}^+hX9GLwWi9+{rz>7a~lVWmN9i5qHRvV_{=cp z1BR#5N#))Q;6-gdO4eq~mWiXZqKbC;=vQv*zFlq%G!}qQl+C^U3wotyTZ7&1$6; zBO1x7K2@>CA9gt_$frDySs{XY8X`>{rI|!n+*B3(_^t!ePc&6Z`g*A$91*~?jr+D0 ze20`{E^v9G>oYr;CMGh9MMK=xXL)LCAJ6OerTu82;0m%bQK}Gdi#YU?$iyFEzaqTm z4HsurS97xByt-O<-x0rb0S+PqVjiv)_=*2gg6*)riT~`xC*jxqe5$I)#5A^|b}O9R)VIO)4(rtfiBaM*~U_G3-0rm4QCND##3l>V_pLN0aY!_dWSCRJBK3` z{KKk$FQ%rmlLM3<#*&Yy_Yk7OV$FGf%WXC>R-C?x+kO-?c^4d@kkxox!|ZIIqJ8| zjL#6&8;lGvb?1v@K=h#V-*N>jM&sj%NsVv!n3L;zkTnf&Pp+UCPcE{@G_jvv%Z=*x zYj|2Xzo|^)Bu}QMcjhn=kha2wX)Qs=_3i^oNYv-2q@$G!*IWqEVE5Bm(<}9z+ zznxFZeWx5H)!dMZVF%Xef`iYrVST#eI6_8Y{4c#S{0e2^c;x!f-fO0s&HWk&Rv5Ni zZG!x>y;Pzw-Ggd#s=N{R&Gd0U)g}jJ?GtWNS7njyG|}I*O+^a+u!chB^+mwB&7v4I98x@V@ZD^a@ysuQ zSEOkh9a3Vm>Pa86n~`{%TZm_#&pq8_mSOap+8lN!IdDw9Vkr~1-+n(@mOD(&HQ>W8 z&!)cr0G*GNT^0^cm%TxT6}STko1(~M!dFyXVv*?)=HZRwKJ(HCLH!rcq}|m_$yNXh ztZZ}pfmr_7Ry2*j!0y!PW}m#IWYX@6P=j9Bn)k^_3c+#OKm^aiejJ>Qu$hpzG3Ro1 zcD{09rgRK1RspMU&Ol?I2+au;RsSmI8C#y9=vnW&@hj5CP6A2)RzBp!*3?j^-=vT_~Os!d#b-|jB%a~ zAmr%Td|1&7;2@s!K%qd+PxU`5Ke-kQdomy3kHMPtd~JWmMn&sbN-UQ3*LFj}2JPK2 zPlgTi*!9>>p~i+>OndZ_>QG>}OqTnhY)!bx(=p1}@ON45cJPy2*suFKY%}OmV`J_C zL1;M7`hIg(y0|>mrsavq6eHdHb0YWWJc*?JswbOzk5MT^F$%?w6$rwOC-rj3}yL`FU_jp_SBKb`)9|+SLixfM~wb_a;=~ zew7J7S|x5#qc04mxHzlHagE`WT#cY`>EQ>?_;Z$yUc1p>Xw+R@1LXQ@IoaIaK%3uH zCr-_-9{TRzzGp0XOWRgtb_?`KP2!V=8^OWf+3;7sYNgR?5>MHU(?Z7==9SwZg)ul*g`d>AWMcq&TYZXm^6MQTosG z37GF^ly|U$8K85;C50NS*cx4jNQc?M%eRydfTh)gQTOlN&}viU=U`QN-gxbaait1H z*~UcNNmxxvO(mn!re0pE%CbtKb%*{)Ks_!3M`Rw2(dwm>) z<~RV-#*L+A<;1RZGo(pwDqvdWGwM^@U0)7ck4y7nqUKDz#c=rER2hNXC@>1!V{ObG z8WZ3g;1k7&W!)bi(Px6Scbg1}&7KocGNkAPD?Xs0;N-1)(&T;Agw5(VlqXjZR_Y** zwivw;#vX51iyEn|a8I|fe9E|eA3VRCTqUCt|9NoV? z*M?^1p>(w+1|L@~HM8dG_%?JNUKba2jVK>2Yd_=8aRFrfX`#((J$jKqg&atuPvi$f z_LElzWGcRq&Sr&QG%oND`NnbZqny7i|Lmktc1$_w&R6f8b6g5v&9ZXein$|-Ggu_U z#vlIb4JW5EtwLDUaV})3%VL>>xKdsfL$?yU#{^U?C(x9Tj zR)jF#rexroRpcvW8*u#lLG0=sFba;qh;JJh-_ND|TJmO!@VQg4(=X}xfVY~cl@MV^ zO~53Ph_qGD4B1&VY5+kEdK|7$7rA?f{NbbHQYe;WTJS^MATH;dab>rTCXbH`z#c`jTWbnS?3T zKtCDoL!s_7>?Utam1g@--6vv98jLHeWLOuG)U;rZ#>lH=5tb=1>qiOhnVH4mw=Z%U zfyOoyj7E_%Gid>04>T(E^DQq2N0RguL2)hhX#MG`x6OY0>#OU{O{0n)zjOId=MqF` zqjHLk{=D$lp9=nI;}SFE`Nvw@t$F^eJYN&}VwD0VF722cqCf1$`%ZJ7Z9EN^-B`e) z$lv|DT9!W|Wg>n!F_(I@7*513cjnQSY6ERGbUPI|sjj4J)7=UsixN^{_ zR7uWdG?mOBMnWZ%iYWff^xBOpU%@8im&Wc=Jq-&wL({s)6l-O}gvuL1OSXEIRX3@p z?~!iH)Ngl?S+!R@#ekinVykIwjrSzVaceYA16u0f*RuXq%i>6Bj%~v;Z;&9SfT&G%n>7a+s$ThBAF;G=;W5sWmB|Oh22Vck`a3rA4GV<4aaI zk5BwfQ@r*GLDfbVpv&@BqE=wmaa%%Q$5XkOtg7m<J&+$J2jOjkivj=SolO^gg@8 z5Tm~w8Nl-$ip!66%f)q3fw#vWe{|`%wdQT1RFOHRk28I`Pd#b3(CQKy>fpgXP)pS~ z&`ztpR;%9NIbb=V!95`plRSX-XAs{S7fT%8;fXKf-P@BUH_cftjy5?Qkt9k-A3sb% zg>-X}7L7w*dgq?x(Y!!|@C(h*2q(7QfiynhF`Ozn*wm&yUtnQwCz`6kR*6YvPF?Vq zx-UJ>Or04pl@HdE-pnuhIj+=>&!fS>dO0~YO*0`E)k>vhllcNz>N7j4+;h4!op-cs zlrK+LVe}IqXIv>sjXGFPqWqZH5_Ehy+BH3kk!|hNHl9*fZ>u@g(n0CzsvXKpRMesw zpB}%`>D$8k=r^2RmTt*3u0W1-iVZTWxX3FD`t8WBSq^XYwr-fqqRIh_HSnFMDGt}} z5lWLZTPmKiis3ZClwTh)=(>y(#GbNB(9K@YeAEJ_^rxUlQr%`LlW;=jg~QfI2kn8- zlA~O++l`LbF8nAb2Sfy0tC?TQpg>{8%$i8e)D+u^MKPVl%z4+FxS}iyYiX@9Ik%u* zGV_G6!}-ZqZDx9aL9W_J=J#vkfbag&q}l}syGpG09Piwf>6}6+Lb#ff=YnVTTp~n9 zet!J%vtxs=ona2OUn8zXg5@{)wp2?bd$3 zbjIuTa$KW)@NI^_@1jDuRU)OHNM@h26YZo*jN=5GRT`M~YaOqN+Z$``rMmm7KW{O= zBxPk6)?>$08gGW%Rqee;dwfk(UDFc#ttds58`e@^4ip~sxrmlbCmWN+Zj1qDPbEKD z4;@u~7bL1=!ssqs14n0L5bE5+^FidA=b7EIGKas=Ma078M!evObaZ)xFvy-@OezTQ6X+Xnj@*8@ky%3R`epXZ7DEh4HzWD8rdqkAad$lhvQBfBjJ2iBIq z?8>Y9SGp~yahvRYb(S**%^oy<;F?A2t2{zakYmvV$-{||68{c{JS}lenQFj@0rCUz zf<8D$TSb2`2D05c$Xny4IAN-@n55%6)O}n@WgKpoTZJM89$CSO(3BCSVC}^02EcrS zdzyxIc5KuCPI~z>H+w?6xdYpo^-E=?m;O0ro*-A$G^UizIQfTg4n)k~W;fcl<=MEVZm{E6MmM^8T3SAX>w(0|}}))q@}#3yARJ9h6N!VM~Vi+Z1RTVE4#i4bcm!9ANyy-Oo4d^C+T}7e}o@ zS!e(GsF`U1E@@TLmM4p#;d+iR-a6T>tF!yG=GdBT-Bs=`;#?UeF}F(X1fJFPvn}yh;ah%u!Y@%h}%kWihlpMiRf}{cEd&f8#!*#ih5ZbFbd|b#t+nC^%h~ zzxQYWav?y-MkD%?2hk9vYzcS&N;myL@I1lRJ>OY(+?(-qT@=YYN^NozWRglZUo$n? zX2i(OIBu}Oko@9*$_cF4e8_@SvMU-T&LH&S@62Vf4`fXJg@tS+WKF>pTWQj__Ju$_L zE}>9pGKCOj@)=fX&QLPt;%?tgg1~E}T%^qZH}A7NmQPQzkBu4iK~7c?uDi|NEX2rE zyuHp$S+r@k0aH=x2g+c@gD^9ZmcjbiXnm8pC4*POSq82WF_16beYn?ieq=SZXXRGo z=B27Odz+s}s!jY!u`s&T#`|Phs(p-wRk-c%M7bDDI-@v3NRjnR>U)}iXIki41W`%H zzb4l51v9T%`awX8Zu7j3$>H5g)$_aB$}DlzWucBa72_v$75n`JP0m-W`!|p{<>~ny zP5Yie2Uc7hW#KN*fP%We!dzit=A`(FBIZmTsjnfL@oUq!`O3-g z34WQ_H^r^D%bv}7^cn~~w{d)-ATljz!bjhqgK4;pf#T}RzlX95j5xT08O{}={_+AlpL}0h?g|2$?@UVhJLS<4999;0Zdy8n{MeU^0>P$-jPmH-++l+xbtA zj9EcmJF_sDmqKF*cXwo1-=UcDUGoY9l3_3fQ1(%FzYy1>vdx8h1A1UQz7~Hi2H=KZ zJ;JAG3dmXR9;-k-F$TZ26On&6IH)lQ{K~tHVhptHcfNauA$5oRpFRC2@aKh9D1!f- z`=87C{~Qc75)cSO5`>-?XTvqq3Xn;~zjM#Z0VBVm#w&W5Ga+9ZGU%XQ#xv-I*8iA1 zGuZH!{9Y(!&J<_qWTj+HxQrgB8(TMN#5uSMlnq3f6(NorzvhjBA`~QOB**vBBWWoB zITInp5Z&(wffLatlq7ZeN&HGe0kVM8IGBmY24;ZdD!4|17v#L}GleW6pxXmG=-1we zbQ@cwF9{p)S16+HZipG7<2scfp9st|K>+_q#nBGwx2~PQU-4ZW;h_Yq?yTcib7(th z>~~R<_nzxT2MeyhVDGFuw>(0(Hw})xQ_Pa|aeP7!c~HJ6>oDd+-FeSeK+qYxrjGVB zK?CYvLp46_dn+-{rg%PI+oX0&1&yrAH%?U zXQPIZbPaRvpa(@hQI7Y8KL`3fR*7$)oOcuIwgt}M5uJs6%=BG$UT23OM}D;DbgVMT9fow4reGvDycL0|I~A;Qn9jbWNobup(VlnI5|Fj5$ zT+PnDhs8dDTI9|tk6wg9d<+I9EhM~eRMvf{pkp%d>70R&lUS5fRD<BBH%OrpRF0O%eN1)FnL;+&7%9yLr&J zHD;Y4+vp)QA!RKUC&QuvgSG&XR3)L66g0PJubSrsM+?V+L8k$^#QJ`7O=L&Dgnj(( zvR@oYjxdCeu(g$%Ym=e!oJ0%?1u~deoAF<#hvR=UJ-_}R7rd3uz+eEv0dc|Y4JZSN zU4o4v3DK&pAqhBjLS-Oq>g3>fuX^Hf%Jh!*I-9N z=dD7ZAm7S*o-5d?{~8tN|0XIHmS6n*&Mr=-Mz)A>-#1M{kKHf{La2M*ph*=H3PwvM zM#BaJ?rSmS#SCO}^b*QJ0;#=0!D$UQ$Zdnbo1x!X{_76 z|2kB^{x?I#%*4g{i&56p&fLX4pZ$4A z>he(N`mHXDt?72V=#NzM0ddaPxizhMIWb;uH1(CV>Z?MDrOdGH?}QailY3Em6`RVB z%(4lOI@0Wn&IA8fqqE-^WgVVl>~IB1yPke42$CcpW5G3D(p z3$eK=5I^vdRg&_AB1Hk^{pPa3a-DofUX>TfXCMKJZPDmo7q1w%`KCP_Wj=Wx3;Z70 z8k+pe;_MR!ZDGn-i7^(u*!;ljF43fx*v@&Vm?5Y&=q*RKcsJ#ri59-{cb18d*d^Mc z%u8`j7C)woQjIfQ>E#NZ9zvJ0!{*i4bV90?fmlE!AgEV@n+2l|6?5Y_8)Tm^Kx4$9 z#{Cbx@`l{g+}mDU1=Sq*KGQ8v^V=z&cClV1JkSX!u|yJED?#XjC;#@>E;DlD=c!5} zwcWyP!sJy={R3~i@~Lu`xV1(32?f+Rn@JG+#y6`&aYXmP3we3L?fvW|{=U`1ilB+8 zK28bEwT#qamSc_4&H8}~d&#_b6yaW3;w(Bt>z>LhQXd`kCML&}jlD6Zz_IuNs-=X8 z4XVW#hvti+H~sE9yRN4KTf1Wk;lqjNiK9o5IO6xbTnvhdsRWly?Q$(Cqx5;80i>LS zf1UW{Ritc#9!Dy4^EOcDe%~znbx55xMiOdM=4p|Y42u3Cn)XJ=QPStf-GQiQ-MeC! zjK8S=CM#@BZ;aW3^qTN?w8y+e3|b%B;$J!A$acLA^2f-Pzve6wX=Avz6&!M1+Hb{q z(FP6rrHpJ?_>xY)Q9Xhh0nS^^u3s)6uagV7@3soyVwaUW57ebTYgWFzLf)k z17vOMn%uNM4+~HhrfYOdR*`P_ehL=EC*!Z6o5BL-xK%N(Ba|l5H`R_)HfJw2>D_gC z&mZIRRNGbMucZ%FXV$eo_+VYji5v3NG?^srg(i^8l}USM8go>HC+Uz=B}_ttfq2zP!l)rpkVy#fIM%K~x@ z-6i_`57qdGlfZ!|nVQ8A#Sb+*G?_#Dza0OzGOQodKZYq>WM>5p`lwgNuYUX6wo{`G zyM&$_9h4VXn z)%c3STZX;=Bpl$?m+nKyd_8o5f570JFTY1I6O-7dZA#80c^o_SYOx`0O*kqS9L2-b}W4ATtWwmN|&L}Md#_919q z^;K`pA(q>(2|pnMI(1HT26qY)(>2%$$7P?OccyYgiaqp|{aeCf zJ?3McqE3O15w41^PO~33?l`-@5wkCk7JUWl6X<6}>Fm|^PmZEl*ES*yad8g_>j|e^ zRD8v$d55Dw0Jy2lzRLWLRjZg5_uej70t}@oh%T}LrSSq=ZiV87l6f<6_Ukx>@9K*-{Xz2T^l{SSdeeB1nv-uvK6^2|^9@ldR zA#txa!7jGGI@|1}l!KDLfEqOI)(Cqd>~*>_%j6U4x=}V4Ik+=j6l%JsaMp<-FLA@` z9foscS>gT?anM5}fgm`AW7xMz%T7`pAWU4=aP8>=kQa@a`Nd|k-4X#hqXZl0N>!fNa zWk+h=Mz z25xEUW#s8f8l@j7Pe=P$%+^s+%|?e+C@IhuqGQ@t$D-IzdZ_U{q!hT(-+cCSf|+f6 z*$B^9MBCQM$syb|BMJU}nW8kX*}+Y^z((26N=~Md$ae@(QXp`8pTUr8y_dC4sIy21 zaAb?MJg=~cP+=IJsV$mE6U9aE9+1$cSD57 zEmK*=zTn~2a_OC`D+@{n;W4z()4b&UMM=TcvSJex6VETURipO%x^FEHBTO z4+|}wgN6TsKvSS7wfyX6iXE7e9sT0Ab|)6slKvIJFlhocmQQ%#pE$8t8YzW!Ws!av7)egn zV8*8vSp}NfyuB_G1a8nWGSb$i37&@?rtBA}8l6K57^;OyB3uc4evgWYg5=hv8aL(V z{g;#_#;%wJ?D$tK1aDJ>q?p%?ki}t0HNtT=Kv^x zfv~6J{r<|@J`jpw3A&^wG_p{g2rE{)}Y3qv!8MLY-#Ol-#zGz*>%m2qDACaDGWrl1++ zka5?6WV=A8qG1vzpP}5Ih^FW{?I#d3R z)Zk^zAG99J)35BHFi2X_Ph&3cl}b7c3;d@dK&dUi-G0X)z>zSvQQkuH{D!W;GF2Pown)Crsqm<@y($VUKK0r&)EN)?S~=v2K8?Mr|S4r3v*5+_BI8$O`& zruldZii(keYT75o?3d&|uV-)lR1pKa-4<`TrkQT#H~uu~t*$+nP6ZLeS>Y=Q%8_u1 zAjGC4<(Tkn>dq*YKtx7pMKBJ#amwjKcj9BPvFsJXd9V;1ucf6ci@X3&sXy@{l)?3_ zC{Vr_I>Eey3zyrJ4-s(O&)=6z2^^(107~k`Uc!iY_v5D-ELbqwxW^pAJYPi?RN>|Y z@4=aHu600ucqUv*GlC=Hvf(#L+q6J>(A-7d~&@&tSnD{aCpEg1Aj+ zfaG?Leh77(Yn;pD@sRiE#n=SxlR?#o4+)Upl5JSy5n1vaQOuFLM`V&gRu&+a?0MM4 z$%i=coPrFAXXY=^Ta(r5J3)Na6e=f zmNyq2GhdYKh$*qM4fJzAra5bvvK0VI0355ywPqXg9AC&Si|?16SPwEDuKDqA) zR`(^Das1wbr`dI<3@veSY7fyY#N{s|jxjtg1(jD`=14^XN>{jET(3TeHG(`z%@i5& zFwm3^`4tT$(g&`AE20;6_pEhdKP?L%k}ss3NO7?aR91i1ZFYCu}A4C zrSXBan{t@E>KjP4$niZ-+EF)@f(isBM6cvKQUw;*H5$GsCE=;M4r{og8`ya?2Z2-i zU_>+a!P4j@9_0c=ioS&lLs&+*N4it{ApE%%N=9Jc#OwE!#p@)-NJ3p#HoO>T@>^q(B z3-5&+g?Qe>mhK2(-0ojbWXi8L!eLDyLM*GN+9|H+>WZplt`(w=IGj<`d(L0eTVXB2 zx5=GX>Q|YY!??g4@5hKJD9{66vfk{MqAR5n@NjE8u^6_9Xq?=F{-KQ%I1u~c#psAW zr*8r->(fGVPBmaBk6a4Cq{im_F-&I1>X28#b~BHEe}{x>IOQvPNo;KEji%h6|`pk z+t;&b!zTfy1tthp3>&4{FO+^g}kcCGa!*^@FPac?Oz6?c)uTVwFX7`Y$O^ zZ?0hvW!Q2>7z*^ctABg&Lcu);#jhML9!Fpd&M{viOyZS%^ufokBbAaP>?bthtphaT z?~{K!&}1K5d~69uy#ejmGxtE`eCYi@$*o~P2;A-+**>ly2E(z(3Tu|~fgEtWcjy9g zkR!EI6AP5!V+IksAwNWmh$}J381WA;)TgS}kvR9!QNr}G8=;S&S3f+kEYLOVW*nCa z8T{FQW1jf9M`uY*H=CK z^HL{C=$irI1>w?y+oCw?SFdq`2piL=Zd@lHqN9DGZ+IcZ%|=pup#UB?Q?$WW9?Kqi zzhSr6eMa<;XTwN%do7;N1JUO?@Vu}unddqP z>D^vLHqd6)Ij{(cS2cuIiJ8^#&)L&|Ps9T0gJzjQUa!wn@b_h7e1B)lEuh+MKHxfqa&d7g`At0X>&_0V@nc=9p2GlOj)GAl<^jjho`EgIom5!2 zAM}sn$V@x-P%$k=g#Bxn(Jgk^_m^!2Z#(wjuQgp|9i0ydgx-1V7ycJtrPc@j^<`#U z890H?pkf}Ki}C9gziPJij`c(lOX$L=EG~YFu9cdvf*#-G z&(3_5eoA)jW51D~qpc7}vhI3~m)rQaAtm0m8})Me-75*1 z2qL>U0On%nu>YZ*d^M-&}-9AU|Exb>>C4~SI3VX~Y% zhmbq#*jLuoOqp_(L)zvtoAlxnweqv+=kOorn33Z#VkKl>utV^FGknW9{QmR&O7843 z&l`GOA$e|>ZG-dKmbObW%>W&t(5;uVUdvQBVtUb4-#ncYepZ#ux){e5HGTA1r^iwA z%yC5XEctA5TQIdgShkp16TEa_*&UWK{fBn0$iL%^;|AOM5e;z6N8iwg&405zH5$3j zvz9Y>{(3`M#Gdj3f#Q~T^;gcbzlp*4MAJ{BLCfRGfqQA8eq5dmI%6$zJ4EF(ujg+> z{J~c9Cq%W14|m5_-C@@mxXc+t4ZNQKq+>q@jeK}NDXCYbetvJ=y^VDW(ES6Q9fN2t zFU%vj-->-Io4cFmAl(2F+RfC*o=h!--^KbWiFT~pgdGK9<%Yi1@r729uC->iDfBgj z1uJ73ON1uX&e$0xbp_w+W1eU7OiEV;Gc`OX6d)tS?Vz8Jl@~~AzL=t&n&-gwSRam+ zR2WD7nm%Xovum%s5@7|D+qDq5*qSB%Y{)lLP8U7e5j*M;_B1RjVr88kWV!h)6-W^b z?YH6dg7-b_1Ot+H`nmPpEUpCB`O48=*LoY8E@dG%9{Z4H|+ zK$&&S4PK5#kysFZpvX>pH@xYwa%i;(E>H9F8UGmT~lPB z81MYx{3c1#{h_e5pCn20o;2nqC}2da^F{Vp79aGvtaT*-O$Y^dTIEknbok;1j&RcMZ=K?!jA7<-#4ujth`0NM%^9hgDwVKf$0g zK-1(`mHT;MQotzjtOM%bHmPFTbh!zO2LkwYp>vjk-wM?CKc@M7RqcwU)qBREL&S-_ z=bzhCsqh~Rd-!I@g79Pej{m{#TIc>4u=Pv2<1WQMk?=)y5$8e$oTYv5Xj%4`8%mks zb6C@6*Et=Ew@6-af7kX0G0kMI7r89gZN=9N$4`y&?@$VCi8RcQQG4=ay&w90!l;;Z z11q;wSL9>MbG|1u*G4U}IZ0vS6rBXK7Z)02CT+d>qnXrKC z>Mz_{W*c6_-OV1a`^r@=PV2ArjukJO_3AR^+}QN4pco`>oYhEq2c=>OG^(7bU_56c z^aiF~c7g6I-%Ev7&QhGsoT4r?NKoxl11?FI2GAkbtMKV#rAr=;+%3XkdDvApCly>@ zdwI46JQ>P~M$jf4o-U6@Pma-|+-SB(JB~r?H#trgQ+jafE?aW$0-(;02A*t5wFm4e z$S&|!;;iava#(}HSfSha3cCF`nzsvM&k^5bjX2L2AtnyId0i>dq;k3ccz16mP>kk1 zoEH@mA>NZ_SuvCuoBVn$g~asEEB2Trk^cQQwXfv1DXU)`OKcd8r2;iVIh%R40?wNb z#pUdSG`I~x)N)Kd%ZQ}mjBZ4=@@rQEgcEe}!XvKfX#Fx-;^JLxLyqH1YDy&fYUg)x zQ`VDhg>OV(L+)93skRRkpR4=qt%`^KE9>l>2hv@3Wz)uu!~%~{d57Ps=aos^R$#MV zzstpmzv7mEI=5?C*6a?4PEZ0QmdG*NpgQ^wVZmyZxel z{E#-FkKFCafgMRx_NmR%V=ARyb*l+S2wa+xJv2i%JXiLz=xMoB^LfzkkE2kjxi$X0 zsjcsx4E1kPJ?jm&bqaHFILEOU-#*=zcswcm9QQ_k0KKNWXP)~?e&L_;bszPHp8Qr0 z<6O4>?TrkP&|6I4(@5+b>}Yj*>`Of)NQ!GyFdq_Ny*2-#{SIkC^(v5akvulA$5sdG zuArNCM`(1*jOP&#{~>>ExBTqzO#forV$@Mu`AR0(%AZd;KaTIiMS7uEl=mF6*M5Og z38@ZuO{~7=d3sv+xQ8yEuN&Hm9O{Ebd40*k@9quHPXoMylZ#iL(HPP26I;#8-G5ss zmvK6P$UofY>;idjDVykEz&>}CVWGa5NnDUYJkUMm!Q7Vp#1Q%ms#e%{biu`w)pfqi zSl}J+JQpIw0C6ga2bB$r8vGKxwwQ?a{nx>P#5H&p(pOah)Z-)6pr1qiAk=8p$D>HG|ev9oT_v8obd|c%a3ptaSE_Uy!x8_4SCK$0=60fgMCji?x2@^9U`%# z7M+gFuFUd-{2tg&4jE85+w(o*9Ii|f#)RG}nrW}#-EG+uSCPv)d%*y|r}OntEooRK z#yOH0(wjHL^a*+pfezwg0QsB!+p5>PvCi+ak7mA=lw9C=d1%IHXusj{=9B8%_p3Yg zQJ!6&%0+>Iq^%84+>_$N34Qdj2(ydG(7&H5ev2cGhpR!7R(!Mu$G$bo*;lj&l74li z3!f8P>DoT}zS#ZdX;18({@TOO{=R*fp2)7XZ$)=K)4#TLVp-q&uH`9iFGgOroN`u( z9gm%Q-&n?I*T+INHQX|@Yl5!@U^kFHUO_~tCY6tiTYFk%t%ExFpuOivm$taj51kiU z=L~EgFwbQD8*+(T0_-MQW{+ynXSTU2?o|1+O}bQNRQ;h7&)@Y#ppUQ6pt}4y=N;s| zNn?%lCb`vWaNk?;-`GyF;Q;hb$PX!0HiSQrXi7C$V1l$+-Ja@y*pps+sY65CPF*g zulb>5A=C#6w(Zp$!}|+k(mCM^>B#3X$wbF4vOuBZ-p8#l+3f$Y_m*LmExV#9PB-rE z?lN(AXxyc7cXxMpcWvCYad-Cy8gJa)_0nt0+UvZ1-#zEObN`(I492WVC8;D;W9IuR zNkqb)l=uD_goQZtcd{;F+(#>$zRrk}Vt4FUm+v~5k*B+}g0nBjdc9=!x#Z zJ#+dDj?WHH9qOOhux7$o=Q$@{A1F`iOe@;@lrX35jyj7+p9V|G&t>BYipQ|;yw9{J z*DMfj7Z+zimv?J|TCX!mzOVDGnfg2f33U+u6oM~n8qfW-0@>Mf*P6Ewi|)JV%Ll3h z9CG4NmSA(a0cY36d=j#7`Rwa4Fm_8R?1Q0w(XW(jJGGiGH)MH3v;A7uDoc!-I3Kp-O&6&^* zBn8sF_Ne9Gi}HQJO=}F)^XC_sK~g`hLRElD4Ga<1`#yHlZKj5QHm|feKL~4Ws?w?& zUZAcTS6CNsbm=V|ZFAC0lMacgGkZhGsLYvI*cRk!wy2V(Kd_v8xT!#xJ4mfqMFVc%NW{L4?c)@t0eqk3T34eCGn~pyLf9u}w#dmM4Z*~8{81&dzs~dQeLU*+9 zp(AF)W16J)%4QyR7=jGscaMBG@q4gMre_NNXeoVLJuv0Q0Gmu_fN@8FO@$|RRnzWD z$+C{Q$Nj`|9!}aCP6+*)U4x7r&ShoY(a!OAKF2^|Bi#Z*d0DelQ-a(1Q6K=BV@*qGE7(EOEd$*vw zqOuFG`4KQ6U5qZ8%S&Z(%VoqJkC~C)kEN8bxO?V!ew|U>jR@}~(vfq7H`SQ#xEfe) zw(W4*c*Hl>2Vtz`M7`;}Ec5Aky8_)Xz zWY)2>ja9MCK`l$qcyyL$UKY_!!>1^;yeJ|iO2KPkQ@>BJ2zg_|6pDcgA|;idz(o!y zXCSo@k$S9(-JT(kMNF$d@sJ5B6D1M~9um!K2floBsgWuA0e4vX#g9nC!FAS8n;T)7 zT%{;aY>wdCZ2EKC1rLzgC^}d|SJp)4e6m?vWmcV)&!YF&dV7em{n!f*m_COa-dqFU z>;Md&5UFe-h}sV;LH1kwumun)+a{p_8|4i(&o?Ao8-a zXPBPPsg7PPh`Z^zPLci^wx-41F8%bQZk=G!=}F+Ivy^fW#Bv$T&`lNcoPQQiId@?; zVs-@g*X+q`=9sCu!GtZd!>Ic~w+y!o_xuj+>cbx$vy$t{P7A+u$=;ppBo$xd7&DOl z9e1M>UXt!|h$Vj|F(>xYHV}PP%A^kOZ7Y_WG4y$8+v3j(#be>M1hW@m?+gu>uzH19N3kJ6Vb~!cMdy zs4JIH9{?rwS{^Kl4tnICt(C6#*RS$f808Pc^lzVezl`&t=Ac6}UB_*#EbM6*To)4a zJS;N->nNcVQg_~zPz)49@0FLD>%{8Jb#`o-ofcCKDE?U9NHwwHbe)|;l`Tg&Rp$24 z2udaAma8o&@-MV1(?=XhEK^eusnf^w2rta&tE=!cN~01-E_PM0%1-U0lO5N)Fnn9} zNoq+;)3#N(I$40&Z?DkvasHW8?65iAs(f>B)jWn3YP_9*RGhVEQtojCK(cW%;3nkMDd z6F&*p=VH=H$)BGsjF4GIXrS3(cY+OoqL1R|NJH`&irLFB{SC58`rTgV6l!E0zilC` za>q)hIaF1)CL=)??XSF-U%(4ERPDkwb)_lqKZP{=+uAC4|G@e7&9->!o9$i6Wg!b5 zyx>@i_%Cm3wFEM7rv+=S8fuVdyWAoc2Kyx-xQK9jj47OV3*7XfdIFN1Wh#HG0h}_b zxn8RX2@)lN5!VK%-iO(&nnG8%5-K6ka^a#9`)k{>tTge)oaPC-J&+q{JWNdg=$%(o2;%!h`G4hw?Gh~5)=medO33Ka$+calk z{4XQ=o>7Tzq=h}u851$6wbH@}ZGJz81!82aw#21=WP}=j##tq z5=ZuIv(vikxFj;dAK^v1e<}PLiMOWcAMh<5O2=F~qJ3e2He4g6iNeOKx?S~|?<7O# z3yv7hkPnlCi-*tMnM&pR?P|&Q21xh)9E34Ha>^crsZd7X!VvAtdByD`_qeA5+9<0$ zST8t~cminyOOo0~@!Y)cw1KR#A%b~?OM*|+f-#LfMX{o%Hms1RLgPZ&5|5{6CVN~T z^>v;nCT-4~;r0q#1T-k*v)1+RKgot6J~KM?a_xJ`YB_oBXe<8!ankPS3#zW0vUxCh z?VX~#9ypNtRG|2Ju)t*tIM#!}^{EfY>06He+cV%)uip|W)khVaym>}6Dh#f&a4LS6!S z3W|!#hr>Q)xq04Ap_(-Bx4o5>d=ohvFPqK-_Lr9D*b&gxQJK0!(0rXEqiG&tm#WFK zDbdkhZxc-x)uX%`O|(}5cPu9v1s~^)CG_lwhjNozy1CT@^phtp&(j$CX(j^#fg!db zzmgB(v*rC_-gYwXGgf+KsIhkhF&%n-@uEUH86rzd7W@V$V7O22~ z-)*#tL$!J(dFPJo39TH)>siEMlM;iL3FY8&Y0C_UHTfo3vRcZ0YVXsVa>3J#9tC#Z z(Vrh(UV&^-&!i5r|I=-4@VWcYeH~4Y@I(r3AbX^V27W6}&6xO`QEqb;Nq~lYSn>?u zo+tw`IYDD7GQ_jSO`0aB*3(FJt}6B6sV8~!r3cS0Yr`ie>*HX>Sml(8H(y)FD?{h0 zMZ0L#tsYc6tj@?SA2kMoA2qvZP7p!cL9AaFl%Ma=92QNKJE1LAw+SfCrXTCiQyyvf zcg&#uP_dqcu&m8jF5=aGpLA<~f=~a)-z|AxcsgCG3Kmsj6{?R?;(B35i~1}*Q59&L z36d`~Rzjy!=8#8M6)FVd{#SIY=nILp==JIO6JuX#YrJ{OtxBd0zk}Yge8lHH^;sKz z+;n^$a)o#T2_j43))-*K#|?D5+2eyTQ)|rc^hbng=fD<h!cW+N(!}DG4LOiLc7g z$lY8*_P~sZF_t@>LCnd(c7G~>)pUpl0=EX<|J~dNW`!(g3IV4t-tu;vCg*1Ly~Jdf z;^MAXE3~@}qX~z(B!C!WO)}d;cc|{WVY4yA`>;;&^Gh6GW}%G5QfA9_q~v!q zIlT>>*``u0#ZW9u)!WCxS>ooHh<|%o0{QV;0h5C5nwl_59 zR1g;ZJGqZfJVd6Bj<%fi^e!$gbS_MEHufg;j2s*s^b7!c0D$%bg4V&!+ELGy*4lyi zZ%F=uN7%^0z~0Q((agr0;5S}9eH$l79wMUOg#LN`ZC-{3|D8tRt7mI#X=b4Jn+mJh+Jt6jg0l2 zEFFn>#f60E7-<0j1^_Js3*8^W_}{blSL}bV_ZLR~Hi>`H;Xio!gSUTa|3B&W!-D^* zTx$oqKkS#zz{ZN+RnPWAu?&Az><2Wb&~Hr{34i?Ye$3@#GR(9979~b@P8McPMs{ij zMotC>ZuuViCm$t$P$haIxe8CqHrs2JHh{IKVi}?4N_~`i1 z1k+zN@zKaBXK!QZWME{^D_~%6qp#;kAZ+H~Xl7|?WKY1zK=-jKSqUgq&8!V=TpTF5 ze=om3NBnm)|DjZA>3`4uKMcvr>aR2SV+g0Pje*neT|``%*U8DukW*iuiAkUFV+%CU zV=<;>HUzNJaxk+n(E>R17+Ba@I5>=q82_*fY3Y9*`&XrY^od(LIOmCEI*thdQr>Y-`0%`Yz&S5 z9+67G&dl+r?`yigqcRq~B8t#{P5tx*YvH6l1Q`t2^5>^SA#KT>x;ueQ1$A(w!%$7g z$G9DA`w_Mx<6w7a6&a2tgyc+IXH^$jRdl!e(~exDoY&;fm0{caG)&1jCLc+qm}pDa z4PEM^a@n-*6rI^lX@Bs9Jscmieng!z&{O&*`Zr29vitW>*2?!Ld_H$dT2of;E<;O; z*~_jl?j+flG-g*-vI59Rz9>62zhrw&)V@mJT9C1C12_wR9H=FakL)zF?J^5QvXNtt zdwA7_C@D#Z{QMM=kx1xLjIzzCCxdY!GQ3Ba^IfQ(mQ0}*U=#7V{?Sv->C{uJy}A?H zmFyR$ae-4Hi6pAvpuRnof?P_Z9M~-WSdTg&eFe_lV0MPuI#FW|W7Y6;*^(rEEzemb@^C?=nlMsG}RZN9A(*%E<%YfND zL+~EOd;ba(r?v@ZgTI@XWMJU3Y&&P{R{_@_976D4aiQ)Il%%1E>*tERTAt1GFX*5Wjay%rhCnaSNLL8FtZR^^)0tMn<_` zfYYGIjxjry!7uztN!}W!bBmqMyPQWF z>F8nqF23zV!_@*+;Hn(Mh3}(kRvtyvflgGV8s1Fxv#O#V7@FZ#3PXYK(}$KC+?Qx;Mep4>DSmgAjLmV!3-p-2MU; z5kK*!*&<+#$@fTQI!$d9)I@J-QogGO0tMO{r*HbVOP%>Yvo0C`5+!b~iviw;5A>1j z;bsrW@84qmPbGU`WCAcV|1%h!nT3VrU&wq3J5lkFQ(DA)U-P)%1yw`9p)#Lz57Kul zeMlZ1JtIm+5|A>MH*od?XZ4Q-zmzwyl4|%WWMLtdVE&_%*-YAgri7$+rij(*sb;}& zPzGSN|HqW!F*lYyeSI=>ZqHbW^l6pG^}_kho=Xz~xaty5cR| z+*L4%Df`y&ZvH;-?X8?`77cApE_}Vq`?mEtKcW;mBD}iG!D~T^^hW|!Y<2}_)*+mi zdLHNfHOF;$gbBU;{^ZC^F=@GA29wPjQl;yilCq>Mg`|=-_42My<$}r$*Zisb;p@O% zX@bIR0*)E?K3D05TbIhnCqQsqxhK zqZ6O0Y|m?(yB!T)jpNE<=Ao_cg>&Cc23wUf`exWzt{rsLPQH5kjDj^;t%A8638yg8 zI(b(4SiM(8j(A3oU}ElRzAD%7N~8t;f4};DAV{`FS}itnMD6xh!>sF2QgeQ~E^cAP zCtad7A?6s`L0)P`aMh}%4VlzN5gOH9)eI!a-%xuIW3Qs6f@>@r~aNWb$=P0WL471e4(ZaBHIu`X$5FS$yl5ipAx z<|Kv%U9Lh?PDed;9i)+eTYIoZbKLVSi)Or4|JUFb4fe+D?`*YI$-_0I83w1=T+OS~ z>kEkM2vLq`v%xC5m}T<8_B&Bju=H9?Ru#%9+tzXKmFMq`YmU*DZll^uzv}ob=!+8A ze|Vaw)JO(Fn}=&DD`ylfR|(+WY&{TULD;pHnPUc^V_-Py0*!+26S9N|aL~Z*V|oC1 zF!&@Vg;46@`}lsihN5iMbP4kM@o=a&dBc zBpV239jBeqHgQ@kZC&Lqj-_YNnmXXD2VTq!AMOO(5&ni_mO&*_T7f>{$)(WeqDX!8 zw8w2##RXXwk(k#W56jhTbEyPtUYBJ-mllsdR9!(9);h0|Tlmzfkktxd0pf~ft|P1h zlCsS28+#Y-59XW2t0kD za@w%FZtF8a>?=A;d0q4s(A>zFVWa>Vamnh4Na|9ys?c8CHpT0+|;-ru#_2n*F%A#xO z-O9;T`K*ZS$j(;H2<}rv{mhZcW$`5sr{6{~S2dLhAAxmUpFjK}JnR4-;vM`Y@k^?^ zoz(BSL?iJ9?;lvcgYga6wOU{Q8u#oBMHk+Ox!D4f*)lrXG0POlnLgiZOYokZm4%_K z-c)WEwHZEUm)&5tnNE`P7G36$>>yyC^9JoA$Pi0g$ap~Y5_*N`8aTgze2K4!*m|?5 zqx%I|A4DY$Tf)CIX}#Z$e+7MlH=)$^NjmaGIIfv&tGMiOg0Il3Z>4kHC|gcq`9XbF z`DDMFlB`NY4gc^Fo!L<+*{N3NI@1e&y+1)qMKe4#F_K*++eXgB^CK&s+4=+{Wlpcy z#u)q&xP!YtGBZ|hY=)W&s<|>m{1ZH~AjInt)-JID3>uQ2rC~wJN9ke__lYm(as^w) zq!g6HCcs&kUH8WovR}23N!GU)k5lc0E~t8}IC{Sj^=;=N(!~DUG6_b~2hMMABgOml zXx6!IXW-RJ4`?L7?=Tob#1$JK{=wy*v`QLIU~a7|Pyb3sdT9hp%Y|UgTxQ`9?2|mC zNY4DwuNmBD!akr$GwLviw~*n(`(~JfeVf;Q8Rc%^YBfFG%S=%PzIC}KYM#v~bdSx{ z=p8Gr5smTK%BQx+Th)l*bgq*8D4*08e=jLaii$f)oe804-f z=Ik3cUiMfvFa6O7gY!I?bVeTUF<85Zn^Q2>R`&I0*+H+>dg5Q0Sa`EM?aF?!w~K4> zAMxHM;EzgPmnqUdJ0`)&$YnOBzou+Ss-9ns*Hpk^t8+rxEKgacx#~l=`UsbW6I1fY zOi>PTMO(FvA!55-;lF(sVC=^-E_j9s#Hx@NmG7Rq*7tKAwjmqdpSAF>&UL*|KgUUS zs>5)Q8@gs7dn%#i@N=!H9cd;{{PE@71R2`c4aNpHsaghJ^vE^Ev59dTi*_H8I$XY? zNq#0wx6{F-F#`MtO=Yx81el5pTSrA8j?1-wE_jroSGeipi&;Zn;^Nir?3N%`zCT!FExoo!p+ELmL@iGRF+n#H1k^VFr_4 z!_qao!-u0V$Z5$~wL)YQ#hqO&cub^B_-H538I9zluEYdQF*@$g8ig6~&Dz09k9mM5 z@yS5JXM6#+v~3eZy)}3u&PAbMw4Vn&1S(#vUMp^lu;VmY8EyQnW8atpyQ&dK2`qnP z+xGsr^U;(|RRP@1x`9rUc3)su;OF8lHC)JMV=eGZ0egBRVtf|jw0`sv@fu=QFFQ6) z?vYN2L<1cPY*Ye0Y!y7Ei%i5Uw*zPN8lECPtqwCG3a0s9xeaoT|B5QTG+;pXd9M=lQIaCRtJ!PWKm`Bel!! zwe&kkq8Y(Gen##E<*<@m6~>IRb4l`Sr&&9_II&(EIcf^~6Pyr+60j+DcWOS#$|nN# ze&+&HAT3)I%eaK-T>4pv2GjT#sNp6LRK@K< zqM=Fi=ItT1L+g;}u9>|$BShHSick?a?a&A1a&X@)kz>)0Gmb9^hC>&t70q>SaNM18 zLqF{{*O?j<5v7pnS5$bni^p(!YW;jySmvKe(ZK%_n2YuXXVr?Y&+^?DRv&#=(iL}k zL65HSmUG81gg-C8>0;pEp2q4#jP^#IlO}zn+DRc|!3Klnlp znwmf#d_nJxD-w2z59RixRq+kR;W!tquls?%-wfn?Svy3#ghgk(&XR5>%ZsWjI)W9& zhVaj#FF!?;EDhE`bo!48v3i75s;z#-h#inTS;L5b%w};e4fw+?(dM6cKb+Fe9 zFU(nnkQi~9x`BMXpFtS}!)8oNzj#$*rva1gKdQ1(47ya!{h4c(#16yiJEAmkJ{|7Y z-55XR8s;gEyMtVv=h;g+^+i`6B-;8!DwhygtgF}yu+CUMwd8Tmi_B(qqqpM_MTp-e zsE8zQaVndTYMF&vUqN?@b-GyfHA7EPkJ=aA5>%iD?FnJJpMJ(WP6YD1j|MKB-W%}& zTpcXNm?(wDx3xUPijee3tj8)3wUQIF@~=P5*ke4t&dX-#8E7h-pko(@cSuXKs-T}3 zXG=?3ZZ`c?k*%o8sqayfUiO)O!!fF-=3oAZ_P5Kb8;JJv>zH&->h5|6FfdGsUSt}; z`-128P_o?xu_;Ec%P1oKYO^KJD#-Na7AAyDshcy!t}epThSsqv{CT3&5J#)zjAv2Y zvTTGk5WOAA`z=a6wd}j}LXP}KNoBuRBZ^fub+{7W%}l3n)|a5=5W`VkOTMU`90fcN zEXFgSD8m>zLh3%RMo{L_lC=QC+-C@lWu3m4P*spZryMW~@=xY+ z17dpZ8q<5e-zE6Kv-es`&;wvE8SgFxN{amnB`m;AmY@&bL2V_>@crO1>|yTE*kc+~ zdY*?llLvcXRG`+W&oYb?2#KI`KjX+1 za_|}zY3AHH{ahD0@$oMr2VJFf6f}CKM6G=Y5Ap=Vy0Dx#bmfI*hs+sAwEbj_rjiln zT$r0BGXyqFEGfQ%$2xxzs@Zz1bI`AS@HL+cm?j5Iw*)c>PUQ@bDj^|^8KA*ruR^uC^Z{faIQF0 zBpbb6N|F#`#iGeJPX22I%4^is23{7rF@1}ew3|2^GAA-iUkv)?mc!l%GvDpA#WfS> zuHiiRTX~a4Z^cS+j`7NJ@X9vq~ z#md<>KY{M8q$xFl?e%%z}PrC zac-(KF{Z&&ti=1-zD~_nK8RC!Q|=9I(it$wk1~iyNz9rX(5Da& z;>02to6y2Ai;2+>^u~HR1vXBb+Fe`Iga)yw!r5$^gJGSFINRt1F*=x;_Fv_>4{9Gpqx24Ehj4B+?_F&$`MiD!v z?OgiMGy2(-U})#xg{9r;kFG~5Qv^Jqar|xYdse-puDF<`!7Au5GwjweJ((8vfONb> zdSy(lo&DDnFRmN#E0kVfJGDgE1hA{~))SX$qIOJKf~#N+FTnZ_bc~}z6DoD zKQ9`)w6R7$g>3ujTw%tgT;tV%a-!?KTJC*tO$oK|*5!s~Y4+D2kRiJ9Im)7m^-&W~3;rZ_fSb8>GQ$I79e9OBwUX4fPzN8N)O4<{|+MZD0n z#pKP;nA7+9dJ)#IDNXbuJltfyS0j|O+55Z)dan-qV2{i#e^HqQeF(RBxSz|sTq#Ua zq(ZKwdbx5-19QuaX}r^+oHNXO<+5*Nei6VjX{&_^#$`Y+611T3Ph-Fo#lY)jr7jHW zz~Ezt_fez7Juw?MKxZ9}ugZ+F^k|CI%=#OC0`=BR$TPI`1|-F zeFB)qsZ;^0S~ZyK3DIX$MnF@bp{MCnurgR=0j1dZe8b*a#8o;8I23^%dV&w!5Y0j- z$`>6#qDOAdd`ZtZs_w2shMXSn#K$0y8!Y0po^Ni#a3W{2GxI5;e< zvGU8oT5b8CwyB98JTukOto&WV%Pasb$=zIk!{2 z#d>Zk$DySYx{4@FHWG)6(<+Ua>m3{d+NcWU^sj7sd+W<+aqxY|KHV9j+!Hb6Y|H9%I`d+=o>O=-?-GOrbNVu`ocqaDt%KWhQ=tC2_l zndMg_t02^NlPg{sl>u#kD!WP_g{d~C2%GE6jO#ECAEqgTu#Wr+5dgx*W~|spIw46( z6QIs5rzdZ;^;k{&@#ApCljpFdbBg{H(ZncoNlBJKq-!re#3$2SwG~70VRvxpI_5mO zP4schNNsgm$(E4CQrX}lQJWthBCS{AOLK+U^}9p5oUvr#ha+aJ|drX*QjqB(cYRdUb*OK_5F+1@ZY713bI4U_A z1uThJnAK(uY*AGkVMUXWKC+PLFm5oPq(dLxB!%vKyKv1b^_@m$Lh=&786Bh0n0tS} zgz%6YSBYZu5Q0C+5o0zqM{($|Y6A zKX`9WILxWVPeyr0*5@ykvNP6S0ba7IY%o~W(LhBKJC+jNZs?CGPQA?~78+IBuN6zW z)f+D)lq5h!Gq9-_%`yPVYB1C?V-UNiHblNI3&fNAG*HGyJkQG}XX7Or&V(%;mWDxZbMbi3k~^71!hR z@%%(=bXi+>tq#*=EyC-44a-p10gvI)*a`ZKFXrsb8xJoDWXBKH!BlrgEZ&Z&FvP`= za(iA!UuntUv&mZQzAvuq$hchEe2)}Hjt10nC}#)ikO^w$^z-GTo(;N^5AhkD_wCV3 zR8vgO-M^ZS3eM4QjN_EO@(4_Jzmu_*aP+c^>;R)TL^%!TnBc~*WGZ>`mvI|R8dJ60 zdsHYo9OCSK{QP3?vlt?VtVtem-)CBw!s=jAIN+IDN(enJlXvRKR9?QTeR_OXp7&0U zsg#Km8)s2Bsd~e1^Y1*4e1AYSf$1nU2zFM@R#~&K)QJhy{35!E>O7_;W@u&e>ael30{@)KsnISGdK$==V=B|7cN^QyLG5{~USq~kmt-0oyorp-L;T=zEBdx>@ z5#g3%u64db2c~PTP&gO|vBB69o7X+m*f!~S=}Ggw`=BnqVX=`G^pWYM$MpQjTZ~in zv_|w7+6n`x?NH2!M^4#T_=NYL&uPz43kZAlpIgisti@B2RmHhH`NcdU-_u^b8ma>L zzK%RQdG-=r1$N%NRz!W$1q)tk@l;&l7QmE)tGrFSb@l^U8;T7YZvp}16yTaNh!L8%W|Q+-dycZA8h?Yl z3Hp&4Q~}nXm>Cw!l`GO*%=dZhad6L^{NiaeAlxgJsUk6zX(!!*nMV!Ui<$X7u#wF< z$G3Ayc0@Ci?_!E{n$>;5;S%3yUd-(|H}=5mLHg>ElyK&`uGPeZ_h|?FBHD*(blfTM zyc^$km*uPM@xvQ4uT5PdR^<8heY*3bZ?!|1-|8i$bvnxC{+T$zg->|_%Goa&J|npe z@5$=Mr)O2^meq}r_c1yAP@TgAZW$Pg*nJ`&lNU8S2Nir580U}VfQfNr(TSsAigm_p zbjY=em=<`Fbj-$|xlJr|H)eS{a5&tP zNeLU2;Tt?t-eK+fC1W{2?i_D;&R~(6j8NV*JM`SIN}7dZ2;oxqrEab3OCuY&)-}A@ zDa#;UUt!l;lBcl2r)SgG3};UVd&)`Dr8jrlDXO zN)qkDIgR@B6g5yG)YWG|m;~)@y4Kq0JKJAkWo{=t9q#r|I_o`Lrm~4SryS{ZZ2(iN zG~lPhOxv0cZIQE&MI$U$*=F|Rv^#_vhRGgMqNRR`F#|^SlU%USBa$pr!$2m%i9{x) zM2^weqOAsosc~3?ocIpfGP5p;soKYtu@_d0s~z?CKggN_B|hG>5eD;kEYFx7(x*zs;OKzOi{MhaeGy zQM*O7z@NQl4y4(l+^wYA;M79Zg4rE8ibU>ZCPN007V$i;^KB|$73J)=+j?IzzIJGY zzTy!(bHpR%EOC{cSMW0J!FKv_xe1qbfX7d%;~Bt4QpF~g0e8&E`O4}POm@5T`mEyGG(kwR3E|#TK7zfYiBKb4Jqc+B=CFWZ6@code z>xUj9Yc#n8|urq$%3<2Jl!v_@I2sck4B`pIUbACXI+boWtL<(b4Aw@^Z7(~CGJSA5A|cLg`mk|xS1c+;~h5|-6Y zMdGqKsVW@=X`=KYR|xB7>-fXO(a`hH06I0gukCHn-SuzRdj<1u5lx?RsyAk^Zq~c; znQ~mvAK@8;)q%$IHgs^wGt}rQRqec0f*c~}?Jil<1nHLN&`0M&vtqu9y_A{fvng3U zkR-}a`ms?~%aqawiI*jFO@CQ2@V9SarHEPoG}=d=7YVSM$w*WsKVA>JXjsNo>CsnQ zN9Wc12*%7RgO`0i4_2;OqK7+HFR=l+Sz3%ZfbbZpzY8u#KJKMb%WPI}VySGS;y(38 z_!!vKFz`gCwqIrnLvtr4=I6s&0mT`VRP^H3Omflp_;zrCU@6b>%k11$?bM|&daQ5g zhl3vOEtf$-@gP0JHdTORpNO}#+M?RK=!2T3NtM5Cgbu;IwiH_&={;H9H-cK?3aNH% zIti&ct442jPpQQp37LI&jE_FkR)9&5I5k$|illAYBCV)Bn3&}67br@_^NU6EECZCg z&W8?sxGrCAz-R&hNBYOH2J+ROp$zG zo*6U&Hy-E8vFGc-l`C#T@JR5TUp7cw`RiU~;t%(cs4Wv{!)%Bl2kpSm1&yz~9KR{GPf``t6M9t?JfuxxrTX3Nk;Q895-~QuU4M%ZY$Lz*hOjM9F&q_g86GB_?=#B0- zse7N1R&Vmh9+p`aitgw*gF)iaOB82USeoB3G-JML$J3?ydMFL0l}S1 zGt!mCQ#~=X{Tm$wyJU^j$#{e4zO9nRgberfyidJhhEZ(dD)x}jADe9nYYzx{KqvGWF+lKDV{qBEBN3y6-hdqJ{t_4R zOLf2FBi4x`D?bhyS`g`oSyb86Wjf zhxHV7-^d2SnBwCezSJQdw*Zrk8QJHQQa6knrl_yi}mu6%om+}~w!Qd?*ZF-i-* za^C4{ebtYZjSioZ6KdKq1MvC?No1$4G@PLowu83ie>tz!*~D>38NMp0TKF{-LEsbO zBjB9yxJ>Z6XgY;^nYqq8nr63_`z-oZJCu<%8RJ!_2cBRkIb&LaZuVy^*74~}{Cp}6 zX;r$Ar#%5gmde)WyR?;+XjH4mEeI?_2UdQSDuP0dMy6PE zv@vSzRFV<9U{~23sawB;__)#s(;xn^S#)6zA7^CMt#4CEF8XK zHYlfo*O=6Z_qZ+Dr5qDV9$>sh*T-^JW7RNLKj~yX6N?vYp1jgo9s^JvRmSu>@WTWn zikieCyrDU}L{u*Mt>xw}X@ROO9(Opqu~q_M66^)85nRuQVRAQv>dW1%bKO&-alx z%IV(Sr{0`pd*Mj5dDkwXV*{DG$T|aaNrrhZ6)4NTbP-TsbHB2Q+nfsSb9oPRTn~d?-PPBTVc`6i8H)fFVua%7rO_$-ODQ$-gPQ$-61K`F2xqlk1r8 zSm>DNSmgN4u|Qa!Q*K$2h!Qc;Ik7R(Rsy3CwveR|wUD$BypW?1vyigzb0K3PVj*E6 zFlnMfjzWw=ib9A&hC+lwfPgV5vl@V5wB8aOsy)eo9$NF-pnLMTvQdMTy@M z3leitic#`W3Q_VC z@d~RH;uKXV=;7Z|y~Cdb9%aOH`xQIoI~6+Rcoli&c@=o&))m*~*A>>~v=z1GwH37G zvK2onQYd80;VI(D<0;_DohhElpDCQlSu0x0TPs-0RVh}KoB4e5C(_?_yMv3(ST$?Fd!We4v4>E+od1#xXLa)n!o)t*u`;tn+CFF7kcI?2Q>RDeoi&!#!$YB6Bs3vkvn6QJc|5U4}C zf5O3l1%m*3_4DS;t;ns0qo6+ky@7Dot0WiY@jXjDDFPk++zO)QJGnIb`QVfAVFM~S zuJ0W`2?B7#oEi0}WqlO5KwvB11%B#W(rJ+Wbc1;qQz&L&EYK+5V17^nloI%P&?68h z-(`N6fh{gM&N!R&7^#>@WT;fS3oUxbm+0j!@!1+b--W!Xqq{h5CXZF zfHD1GnmKu5;r3xZisb>#g1q_W+?7*afO|IR&4(03yzPy$15 z`mr!=!WDF@+Y?~MDm^ctHJfd4`jhxllW8$1_);PsL0<6KMM!j0;5|Ti4lJWb@`C30 z#&koTD(YNlKhGn#_Z`q)K)6PISHQepPP-i8Q?4o{204Ubx|0QxZVd3=yky^$Qf`RgjO`5 zgUvj!d*pOO8=H_}ARx>c>MIeVdC+ws?uqvit0sLeDQa=$ggqAN`|VhFfdMW80ml~R2k1?l0(%x#b%?b=YL zjFd39FcA2h+uX>xfi>X!ZCU-RoUjJ=XDAB`WC6koR4^!03mF0LlkwupNqm~>MozvA zH{VtEZ0MK|OY|G71N~|HRfPaL7W31r%6@s`=iyK;rp?KlW*S^;MqmC+=s)Zcf3v(J z9on-&6=H0`?Efn5zJr?Tx4nT=1f&ZB3Q~fEst`yhp$ee|r1xGEAanxK zn;^aSj+D@(Nz))r1?eEtK?Ld2LArok&U4Or&vWNK=iW2({+FHEvof=j{mXan+3T|y z;9>ZBjQbxkoQc%0ahRu3-D+Mcr8vp>eZiRNjqp4r{tXf=4hcWO^}eGu^za*G5WY_) zvh=A#sa?6fcg{BJ0(j1K4)6gT?g3qpJ8`k*PtBCfl+AiC-TNShemu*Z$vw%6$r0Ra zu|(W#aTm#c$t}s^U@v3ur)X`oZ1+^y6i}aCADF?b+0Fh`YPo1Xq@>twK6wVpDf%d| zJGm3eE6Og)y~T;x#g?SFsa%$yQ5|%qQ*^UF^;<4rAB9>(@t+LL1fUnp`k0mW6Tbc2 z_DtCA7EWO9)=S9mrt7om(eYG^0)fD-AXu9=tm&q)6}HWgGK3d64EMtCwm&874TIE5y(ERBv-WB-*dbrGL5O zGA4J;eOGc_bjW@0a3#RcW9JQwS9>52XE}3rI&UD&t z`c#L+@DjZFk-hWg(6QK0MP6q-ii=l^3KiGI#@)G`6dze5kNG;;H9SOR{_@V$_h@*w zc%w#BIe}VC_JV}^&?@e_LBqJCZMyxN>~WPcrJ>iQm8eOb2|HCy@?jdGnOEA!YI(1k z?8kw_>W#0`(64mUbSpTZX|LvZw2|8xMwUYJ#FcK7_k||uixrGng`zX2&~u_bqT%A_ zI7m^6sI`J->A3!G4ze zV8~a97jk!4WrKcjkcDxy)!8L~Y9F{TWNgH=*-95b=fwnWJT!gU7H|=vl90*Vp~$j& z8kznjsgARAf7|tK%d;_>F_lc;kriy#uKHAp_QP+tODXB;z+;yvU$ioYe%^vXyw8Pk zq^(E{@$Qn(l=fY}sqcuc0X4}xLfRLCvOnbn-P{GVL|fz~eka!D@v7d8lXo0>g}+!` zG5f+*qNzxV&td86RkHi*dcOH*swUdcj)j~aZrOj8169PIlITzF7}pxL=ne2v^te~r z3)4RkS)-c@U#{-Euy}namDD-~)p}qTIr~K#F!_G`P8@;Qld3MY8oa)t6;1~0yvqjh zDI<#x>jeS6I8BA^j-lz_*IU<8E7DKie|R!07+5AGPkiNAt@MP{c8RRfie0S-W$=8} zAiTsNMcC@b~a2 z4@{xB$&YZ^q-fa@TGK?WR14t(*#ea6$NbCCj)Qx@yI9VcIu`XWLtfV1d$Oo_87w&+ zw|BtQ{z>GF!F=(l|MSlW^irQV&+fAn;S!sy2hK(CPRFX+$ugcU zG0(-deE+UC_x!8d1Lse?SbC8~g}LB3Ec4W&kx6K!8*NP&EtWB3QOhJG#*K=vi?FIk ztm+d1lx2OvtwkKZUf9oVVFP9vlbWKdC>JASgxQ}y8K7aX_EkS=8 zFnVK%{DGq&L2^h>lr>UI5%#|{1%ib{ML=o*$e%j{bJM+abf)McKDT-K77p=`()*_H z@dqFA0hn%S-nSvV-;dKtrs^13E-gnzg)5&}5R6+~2(OB?V&y8gpoHJiu;Py{FGna$ zD*OBR?5(bz_Ova`+U~iZ&iK7-;==)|v+#ik((wRUoZpFjp=0`CiX(MbIE3E8xTQG! zh8q>_GP@t7fgq84zVCX8FJtD(aN(Ej$R8W(Wue#Vqg6WXI5@rLU2BeNVo$ryAFB1! zV4`;*4@~R z5?o!>xJI2N4aZ$Du2bJvu_ZpIk8xOXARYa)7?yZ9n8@N*Z0NcL zVJq(8om-ZyV7ccjth#VgaPT025JA~2Bc%bLp^%q#yF*D0YaXF1zs(cIQ)pC9^@~o7 zz%;l9hCd={N0S{A7&hN|TP398HMolWK_}TX@kw~-qL3?NF5&w7^L;feUQKAihn;;K_JFr`T1oH0ZjEz0F9O5%H);XmNOn(CsePr>tvnxis0o@Ck4o zz^FkL>>I#lJ+NZE$xqA*c^`_q_2zy?42`yZs7~5AcZFqzAu77DqVc6iy+@r#%8~Ad z5`9(do7fyOV-EAR*Mss|0wl061y~J(RNhqIe)fJSt?Wdhujbuy`Ei%>t8scm`Wa+> zVZC9!ZoMr+(eAct&YJwwqO=jUk#M`c3@(tH(MQ92Yo&qY5A5#fXmmW9u^HB^*DQ|S zTiy8S{4?rj%c}Sa3wHs{5iK4Kn3jUaL@QGd!!yfMPeV$p&NZ(el6I7amo~}Gq_?S^ zt*fVbqM@ccU+b^wV-!}pRGwU*Rf^U_DyJ3M*Y@l3YD<>=isgIiRmAz_(GSTZdLecp zb)iC|YNL+X)_3u~k-qu9mA}}?LkMNr^omuAjja{5b;tA}`VEGM?Q~`_g|xLz>XrHq zYQ~D^BSY}y}=3el;YJkB4?1@>2@^v__ zqXp`{5Y&SIHBH;NFSiTo+o+{%a$$;PxMjm)In_{a57+1N&L3fQrEV_{oR`g()j8-m zlsJw#C{>Uu`k8B4o>{-`OI^CbmEaa9HDNE21-p6FZ*>>kH5-ICtM$+YP=$>Fw{fbPzZ)_FZX>WyV@*PTCGf{>te z{o<)Xl1kbw{Uh&`*3i~RZ7Gm6Uaj%cHTt?FcUr339GN44Z#cKT1TV)SwG z6fw@xzuzBOPYT#tw_3fjwlUzV3aDClRP?+-SFL-vS5>-ZKc#o8b`f7Ks1cp=nRu zHRAfbUhca;e9MlT9u$xZJa{K!?>M*sZSS)l`!e)mC@LqY7t;4=$ghpv@u_}0`giGN zT{W|D4k?i2jG*(YGMW=P=y#>p5>+5*+u3w zW9_%;#S@)w{rL)XjeWJ=t9eaHuiyZS{etBW=?tscMcJn}ot(RqzTbIW<$mPj6NIB!#R z<7CnDckKRIgG+G-lh|TF(FJfBG2msip!-&HmgH;U$@WQB{8@a`@c!^~?MG_Qyk(pLVD}h#b0yxvVZQ2lRMP zT}W+Tb@{ImZAU~W__DM}`2_i56I);J=iGF=pT0P}_{$LbpUsmO_*c|~M_E}|oKfB) zyJn@4!MS6BV>5O8>@Q3INAuUg;Qv_~fY)UOxP^m9_U~)|XGEod;J=F7&Fg3gICt`s z%^j1(^NPVeAq<4k9tVkU%D?SK%eCNHDHp7M=tuxUiNz9cB}mLA{hV&|T6x$DIw|eB zUCcIsJxe41NYAOLF=3Gx<)>et^$aJg_v(#Yt~i6FU|iw?3M)7N9d-ZJy<@VUDZKT? z+^iA5)4TeloOFcU5YX^u|l#@TaO5iw#nZZeZ~f{LS~Id5gq6Th9_|`Qw5*GhtBdoE-3AZ@{Xs8k-yoXE8^Ppn*C1Mdb*TYIqHOIv00Ke+ z|D;F+1VjY?pU|n~bYq)z$Mr%@$3*8tYm8b9RPrSgKx40CSv-{p@4YA-z+n3t&A@EYnWr#V z2u-9f3lWv0Ozp0)sB$Y1p3Aa$d@Mc2KN{-F!Dz><_z{cmYM_SY3|&LjwSD5Ka!cfR zj^cX*t$J*iW@txKL&Hy^F9+ytGa%?6tbs;4!3f1*88(pn> zb@uX)^D|Qt;15JegZNoJ(ytv3WCaP*|WCf zbMt+Ej5aGd?A~xLdyVBm3Oz>aF~&7UZ)uPEEkCsFvmYBvDnsMkS&6O8y;b%=9T}zH zYj3dH>c%WAQcf)%-{0K!lylU&t216<*+q}6XLlDAWuMltC=u(!|7m7rPBea~6CaLp z7Er@+V5XknvF-6;?1A{NIF`t|srYm!Q6q3nbrNyaj#1 znV#}}zhz}OdX3liH*r|wWAAPQHJv_Ii4Xay6=Eq)4#qWf^mtRAzGTfDv6}x=&jyy2U!%fOHn;Z9adDcNt zNz#bkthQKfc%_3rm8cJ6tzt?Bo5*A~o&6A0)@(SnGihv7oXK63fU#Cxc6G(=MdL5V zSK%SKChWCPvsG#4frB0B=SypJn_W$YXRctintgIPHrIaxgE}s%=;dCNXzV)ryO#~{tS1J8Jll*)A$_xERMWtTV~p-9qF-aY@V$}acp zm^M{}oCk|af*e$P_$n7Et*R{PIiEA-;0*zK50Es~%}~yDEjh#RZZ{rrgKua?{?POI zy|abxC%A+-<=o*kf4OD~{7ZfLzt+sZvrd0uHvMDGgbMw0$rOT!{NF34fDr$m|E0Dw zjpI83Wb&3o!aIb~^}#w-0G3fRI(WJwix7y4)hlcI3@@H{7p5Q z{YVhoP!zp8?SOwe7?@d{ovaMcwUh~{Zw<~z-v5|9X_%(NHXVg>qI`DOE}bM5$yHTr zv2xxEPZgC6Wnnk>co=Ov~QZ_e#Qvtw-7*ko9b*ejF8?mt9T{*ajDH06)>uj)JIeEVVoeuyjD zq6A}Ec-)*?(ji!VKP2|k^*gVD^D~l%bq6E6R99Mtn=!HhqqcgP&0)dSRcFrnmP6l~ zJgd8m$}EYGH_h%oe#<#n^^7jPQLBriH0&HB^xETP>3~sKliG*q$#lcdSx-wqMzw<^ z1rg0fv@VO?#<;6GOMc--HI)rd-b ztKyEk+!o8^`HKP0mQ$;;2kImo_~4#y2_fOd0VmuB`9;%a`MyF2x z>(SS~zc*Vp)o&Q>W877$zxvUF|CEAco_W~0pt=5cWtkiFhX{P5_Wq5~<&qQon+nV? z2o@563JLxJ0(0{7bN*wmn`-~w`{f4RFui{+A_RuqloI`e^8I^}f0DOc|DL=x`KNhn z!p#lR`J3L%^*`uk?thtSBEo-4Hh*{0G%V3h?l*$kO{jV1rioUp8@oGe&?UluGXC?_H>BL{{G2+F~PWo2)2qlAJWLEf400=<9^uL|=Qy1pyUW`Qh?ow&W@*mOH_Edd&<%4s3_RTKN zdXv6MmCwhuM} zqo?eB{^NfA?Ftli9K><~U0$>)n0_L5OrvZF_83zsQ{I5qd-yC)$)<>pp$-p~Bn^(? zuK&EEQOYG?3=hfrI4jO)8@;$~O8o?$uXwBL1h3DdG*fWcI8?lwZ|#)4Ctx7kctkhI zWaz-0yrLlrh@&+v$!PT~8$qb8QX+4u;)60!025eEIN)RUY5Lah_{joS@@e~YBCV%= zd*hmcV*p;G>QIw@z&YO1yaO-L@aT{pqu#a$AaYmYfDukahjgu_sDzwhgGi&A;Y*~% znXSb2%2k7i-lD;{#B)BNRN{oDF(5Dy_!5@9<`RBnqy(l&J^&JqmJ9cJ!<}bO6YcYq zIQT!QoW$Go$J7IplM?MKp1{y8NwFc`ap$XteD`mtp$1lGI37e;aV1aHGF7jthV_u3Nv;6OM4r;ovvq)1$0lwK<_h}z0D zW<|C%bD$*%sf@~^RJsRm^6`c5@+8;XiMZedh%mv$U?zFP(!+=ptjsUMG8lziB34$x zQ=EJzUwH{PYb_Zs>W(^$6CP;_24XTXyuiV2iLQlI3=_irmuT;_FmQ*}O?C`m76q)i z)3)c5IBcvWCS9{R49jInZVX1O|E8!gPQb8Z-XDXzevv3WDmBPd%E;8xvR4{q(9-sz z`YC-hMz};1fSW88hvDwB))ZSwg%;?rhSsrq@4-4Sj&(js z1aN_;lnb~!i zG`yq_-gn?~RH`Obi5`B=TS3 zM+TWE8{Irnf68jz#it+E<<%GAozGqumK*7hcdk+8B-Go)lfbHKo;WSDn>QFbeacZm z;WNX1@8fWaj!kr0oFA2T{%Xt~%_I0Xz0ZJ|rLX-AquZm}y|g0K4R$-h2ZBFhYv}@Eerc%>m=xuPrnlx#ZjS}l^u>3x1UPRP+@wo>5$dg@XPqCgdjtXo79)VBUPv9 zd0$-{!afV#qs`dtC&Y$W#E|0zZ$?EjW;cGL`{x4jPGu#k>BRt7e(`y;zPW0{$tL%@ zS_iZ3mtiA&&%|Aa5sB+Cg<>$Tx$VJ>mMSH3a~fuD;b^;WUZyi$N62DH6sXLyulqFQnJaI2hNK5Rw1+nuX+usT$`2705FsaFXO~x3 HASd}RH5L31 literal 0 HcmV?d00001 diff --git a/src/ImageSharp/Metadata/Profiles/ICC/IccProfile.cs b/src/ImageSharp/Metadata/Profiles/ICC/IccProfile.cs index 2f1aa1952..3752be1ba 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/IccProfile.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/IccProfile.cs @@ -91,7 +91,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc } /// - public IccProfile DeepClone() => new IccProfile(this); + public IccProfile DeepClone() => new(this); /// /// Calculates the MD5 hash value of an ICC profile @@ -108,33 +108,33 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc const int profileIdPos = 84; // need to copy some values because they need to be zero for the hashing - var temp = new byte[24]; + byte[] temp = new byte[24]; Buffer.BlockCopy(data, profileFlagPos, temp, 0, 4); Buffer.BlockCopy(data, renderingIntentPos, temp, 4, 4); Buffer.BlockCopy(data, profileIdPos, temp, 8, 16); - using (var md5 = MD5.Create()) +#pragma warning disable CA5351 // Do Not Use Broken Cryptographic Algorithms + using MD5 md5 = MD5.Create(); +#pragma warning restore CA5351 // Do Not Use Broken Cryptographic Algorithms + try { - try - { - // Zero out some values - Array.Clear(data, profileFlagPos, 4); - Array.Clear(data, renderingIntentPos, 4); - Array.Clear(data, profileIdPos, 16); - - // Calculate hash - byte[] hash = md5.ComputeHash(data); - - // Read values from hash - var reader = new IccDataReader(hash); - return reader.ReadProfileId(); - } - finally - { - Buffer.BlockCopy(temp, 0, data, profileFlagPos, 4); - Buffer.BlockCopy(temp, 4, data, renderingIntentPos, 4); - Buffer.BlockCopy(temp, 8, data, profileIdPos, 16); - } + // Zero out some values + Array.Clear(data, profileFlagPos, 4); + Array.Clear(data, renderingIntentPos, 4); + Array.Clear(data, profileIdPos, 16); + + // Calculate hash + byte[] hash = md5.ComputeHash(data); + + // Read values from hash + IccDataReader reader = new(hash); + return reader.ReadProfileId(); + } + finally + { + Buffer.BlockCopy(temp, 0, data, profileFlagPos, 4); + Buffer.BlockCopy(temp, 4, data, renderingIntentPos, 4); + Buffer.BlockCopy(temp, 8, data, profileIdPos, 16); } } @@ -171,15 +171,13 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { if (this.data != null) { - var copy = new byte[this.data.Length]; + byte[] copy = new byte[this.data.Length]; Buffer.BlockCopy(this.data, 0, copy, 0, copy.Length); return copy; } - else - { - var writer = new IccWriter(); - return writer.Write(this); - } + + IccWriter writer = new(); + return IccWriter.Write(this); } private void InitializeHeader() @@ -195,8 +193,8 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc return; } - var reader = new IccReader(); - this.header = reader.ReadHeader(this.data); + IccReader reader = new(); + this.header = IccReader.ReadHeader(this.data); } private void InitializeEntries() @@ -212,8 +210,8 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc return; } - var reader = new IccReader(); - this.entries = reader.ReadTagData(this.data); + IccReader reader = new(); + this.entries = IccReader.ReadTagData(this.data); } } } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/IccReader.cs b/src/ImageSharp/Metadata/Profiles/ICC/IccReader.cs index 96a5e77a0..5e6e69fff 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/IccReader.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/IccReader.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -16,14 +16,14 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// /// The raw ICC data /// The read ICC profile - public IccProfile Read(byte[] data) + public static IccProfile Read(byte[] data) { Guard.NotNull(data, nameof(data)); Guard.IsTrue(data.Length >= 128, nameof(data), "Data length must be at least 128 to be a valid ICC profile"); - var reader = new IccDataReader(data); - IccProfileHeader header = this.ReadHeader(reader); - IccTagDataEntry[] tagData = this.ReadTagData(reader); + IccDataReader reader = new(data); + IccProfileHeader header = ReadHeader(reader); + IccTagDataEntry[] tagData = ReadTagData(reader); return new IccProfile(header, tagData); } @@ -33,13 +33,13 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc ///
/// The raw ICC data /// The read ICC profile header - public IccProfileHeader ReadHeader(byte[] data) + public static IccProfileHeader ReadHeader(byte[] data) { Guard.NotNull(data, nameof(data)); Guard.IsTrue(data.Length >= 128, nameof(data), "Data length must be at least 128 to be a valid profile header"); - var reader = new IccDataReader(data); - return this.ReadHeader(reader); + IccDataReader reader = new(data); + return ReadHeader(reader); } /// @@ -47,16 +47,16 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// /// The raw ICC data /// The read ICC profile tag data - public IccTagDataEntry[] ReadTagData(byte[] data) + public static IccTagDataEntry[] ReadTagData(byte[] data) { Guard.NotNull(data, nameof(data)); Guard.IsTrue(data.Length >= 128, nameof(data), "Data length must be at least 128 to be a valid ICC profile"); - var reader = new IccDataReader(data); - return this.ReadTagData(reader); + IccDataReader reader = new(data); + return ReadTagData(reader); } - private IccProfileHeader ReadHeader(IccDataReader reader) + private static IccProfileHeader ReadHeader(IccDataReader reader) { reader.SetIndex(0); @@ -82,11 +82,11 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc }; } - private IccTagDataEntry[] ReadTagData(IccDataReader reader) + private static IccTagDataEntry[] ReadTagData(IccDataReader reader) { - IccTagTableEntry[] tagTable = this.ReadTagTable(reader); - var entries = new List(tagTable.Length); - var store = new Dictionary(); + IccTagTableEntry[] tagTable = ReadTagTable(reader); + List entries = new(tagTable.Length); + Dictionary store = new(); foreach (IccTagTableEntry tag in tagTable) { @@ -117,7 +117,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc return entries.ToArray(); } - private IccTagTableEntry[] ReadTagTable(IccDataReader reader) + private static IccTagTableEntry[] ReadTagTable(IccDataReader reader) { reader.SetIndex(128); // An ICC header is 128 bytes long @@ -130,7 +130,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc return Array.Empty(); } - var table = new List((int)tagCount); + List table = new((int)tagCount); for (int i = 0; i < tagCount; i++) { uint tagSignature = reader.ReadUInt32(); diff --git a/src/ImageSharp/Metadata/Profiles/ICC/IccWriter.cs b/src/ImageSharp/Metadata/Profiles/ICC/IccWriter.cs index 2adfbbc7e..4bf8b5eb9 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/IccWriter.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/IccWriter.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System.Collections.Generic; @@ -16,20 +16,18 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc ///
/// The ICC profile to write /// The ICC profile as a byte array - public byte[] Write(IccProfile profile) + public static byte[] Write(IccProfile profile) { Guard.NotNull(profile, nameof(profile)); - using (var writer = new IccDataWriter()) - { - IccTagTableEntry[] tagTable = this.WriteTagData(writer, profile.Entries); - this.WriteTagTable(writer, tagTable); - this.WriteHeader(writer, profile.Header); - return writer.GetData(); - } + using IccDataWriter writer = new(); + IccTagTableEntry[] tagTable = WriteTagData(writer, profile.Entries); + WriteTagTable(writer, tagTable); + WriteHeader(writer, profile.Header); + return writer.GetData(); } - private void WriteHeader(IccDataWriter writer, IccProfileHeader header) + private static void WriteHeader(IccDataWriter writer, IccProfileHeader header) { writer.SetIndex(0); @@ -54,7 +52,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc writer.WriteProfileId(id); } - private void WriteTagTable(IccDataWriter writer, IccTagTableEntry[] table) + private static void WriteTagTable(IccDataWriter writer, IccTagTableEntry[] table) { // 128 = size of ICC header writer.SetIndex(128); @@ -68,7 +66,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc } } - private IccTagTableEntry[] WriteTagData(IccDataWriter writer, IccTagDataEntry[] entries) + private static IccTagTableEntry[] WriteTagData(IccDataWriter writer, IccTagDataEntry[] entries) { // TODO: Investigate cost of Linq GroupBy IEnumerable> grouped = entries.GroupBy(t => t); @@ -76,7 +74,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc // (Header size) + (entry count) + (nr of entries) * (size of table entry) writer.SetIndex(128 + 4 + (entries.Length * 12)); - var table = new List(); + List table = new(); foreach (IGrouping group in grouped) { writer.WriteTagDataEntry(group.Key, out IccTagTableEntry tableEntry); diff --git a/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccBAcsProcessElement.cs b/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccBAcsProcessElement.cs index d6882957f..ef2e6eae0 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccBAcsProcessElement.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccBAcsProcessElement.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -21,9 +21,12 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc } /// - public bool Equals(IccBAcsProcessElement other) - { - return base.Equals(other); - } + public bool Equals(IccBAcsProcessElement other) => base.Equals(other); + + /// + public override bool Equals(object obj) => this.Equals(obj as IccBAcsProcessElement); + + /// + public override int GetHashCode() => base.GetHashCode(); } } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccClutProcessElement.cs b/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccClutProcessElement.cs index e450362a5..00183b6e8 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccClutProcessElement.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccClutProcessElement.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -16,9 +16,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// The color lookup table of this element public IccClutProcessElement(IccClut clutValue) : base(IccMultiProcessElementSignature.Clut, clutValue?.InputChannelCount ?? 1, clutValue?.OutputChannelCount ?? 1) - { - this.ClutValue = clutValue ?? throw new ArgumentNullException(nameof(clutValue)); - } + => this.ClutValue = clutValue ?? throw new ArgumentNullException(nameof(clutValue)); /// /// Gets the color lookup table of this element @@ -37,9 +35,12 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc } /// - public bool Equals(IccClutProcessElement other) - { - return this.Equals((IccMultiProcessElement)other); - } + public bool Equals(IccClutProcessElement other) => this.Equals((IccMultiProcessElement)other); + + /// + public override bool Equals(object obj) => this.Equals(obj as IccClutProcessElement); + + /// + public override int GetHashCode() => base.GetHashCode(); } } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccCurveSetProcessElement.cs b/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccCurveSetProcessElement.cs index 3ea707eec..21b372ffa 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccCurveSetProcessElement.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccCurveSetProcessElement.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -36,5 +36,11 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// public bool Equals(IccCurveSetProcessElement other) => this.Equals((IccMultiProcessElement)other); + + /// + public override bool Equals(object obj) => this.Equals(obj as IccCurveSetProcessElement); + + /// + public override int GetHashCode() => base.GetHashCode(); } } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccEAcsProcessElement.cs b/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccEAcsProcessElement.cs index 67f25b5ce..5ce56bd11 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccEAcsProcessElement.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccEAcsProcessElement.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -21,9 +21,11 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc } /// - public bool Equals(IccEAcsProcessElement other) - { - return base.Equals(other); - } + public bool Equals(IccEAcsProcessElement other) => base.Equals(other); + + public override bool Equals(object obj) => this.Equals(obj as IccEAcsProcessElement); + + /// + public override int GetHashCode() => base.GetHashCode(); } } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccMatrixProcessElement.cs b/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccMatrixProcessElement.cs index b7bde3f79..c448a71cd 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccMatrixProcessElement.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccMatrixProcessElement.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -52,13 +52,17 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// public bool Equals(IccMatrixProcessElement other) - { - return this.Equals((IccMultiProcessElement)other); - } + => this.Equals((IccMultiProcessElement)other); + + /// + public override bool Equals(object obj) + => this.Equals(obj as IccMatrixProcessElement); + + /// + public override int GetHashCode() + => HashCode.Combine(base.GetHashCode(), this.MatrixIxO, this.MatrixOx1); private bool EqualsMatrix(IccMatrixProcessElement element) - { - return this.MatrixIxO.Equals(element.MatrixIxO); - } + => this.MatrixIxO.Equals(element.MatrixIxO); } } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccMultiProcessElement.cs b/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccMultiProcessElement.cs index 392121259..84d399459 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccMultiProcessElement.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccMultiProcessElement.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -58,5 +58,11 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc && this.InputChannelCount == other.InputChannelCount && this.OutputChannelCount == other.OutputChannelCount; } + + public override bool Equals(object obj) => this.Equals(obj as IccMultiProcessElement); + + /// + public override int GetHashCode() + => HashCode.Combine(this.Signature, this.InputChannelCount, this.OutputChannelCount); } } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccCrdInfoTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccCrdInfoTagDataEntry.cs index 5d0bdabe7..8b40dd783 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccCrdInfoTagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccCrdInfoTagDataEntry.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -87,9 +87,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// public override bool Equals(IccTagDataEntry other) - { - return other is IccCrdInfoTagDataEntry entry && this.Equals(entry); - } + => other is IccCrdInfoTagDataEntry entry && this.Equals(entry); /// public bool Equals(IccCrdInfoTagDataEntry other) @@ -105,29 +103,25 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc } return base.Equals(other) - && string.Equals(this.PostScriptProductName, other.PostScriptProductName) - && string.Equals(this.RenderingIntent0Crd, other.RenderingIntent0Crd) - && string.Equals(this.RenderingIntent1Crd, other.RenderingIntent1Crd) - && string.Equals(this.RenderingIntent2Crd, other.RenderingIntent2Crd) - && string.Equals(this.RenderingIntent3Crd, other.RenderingIntent3Crd); + && string.Equals(this.PostScriptProductName, other.PostScriptProductName, StringComparison.OrdinalIgnoreCase) + && string.Equals(this.RenderingIntent0Crd, other.RenderingIntent0Crd, StringComparison.OrdinalIgnoreCase) + && string.Equals(this.RenderingIntent1Crd, other.RenderingIntent1Crd, StringComparison.OrdinalIgnoreCase) + && string.Equals(this.RenderingIntent2Crd, other.RenderingIntent2Crd, StringComparison.OrdinalIgnoreCase) + && string.Equals(this.RenderingIntent3Crd, other.RenderingIntent3Crd, StringComparison.OrdinalIgnoreCase); } /// public override bool Equals(object obj) - { - return obj is IccCrdInfoTagDataEntry other && this.Equals(other); - } + => obj is IccCrdInfoTagDataEntry other && this.Equals(other); /// public override int GetHashCode() - { - return HashCode.Combine( + => HashCode.Combine( this.Signature, this.PostScriptProductName, this.RenderingIntent0Crd, this.RenderingIntent1Crd, this.RenderingIntent2Crd, this.RenderingIntent3Crd); - } } } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccDataTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccDataTagDataEntry.cs index 1a178b89a..e5f817e95 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccDataTagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccDataTagDataEntry.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -40,7 +40,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc public IccDataTagDataEntry(byte[] data, bool isAscii, IccProfileTag tagSignature) : base(IccTypeSignature.Data, tagSignature) { - this.Data = data ?? throw new ArgumentException(nameof(data)); + this.Data = data ?? throw new ArgumentNullException(nameof(data)); this.IsAscii = isAscii; } @@ -62,9 +62,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// public override bool Equals(IccTagDataEntry other) - { - return other is IccDataTagDataEntry entry && this.Equals(entry); - } + => other is IccDataTagDataEntry entry && this.Equals(entry); /// public bool Equals(IccDataTagDataEntry other) @@ -84,17 +82,13 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// public override bool Equals(object obj) - { - return obj is IccDataTagDataEntry other && this.Equals(other); - } + => obj is IccDataTagDataEntry other && this.Equals(other); /// public override int GetHashCode() - { - return HashCode.Combine( + => HashCode.Combine( this.Signature, this.Data, this.IsAscii); - } } } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccLut8TagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccLut8TagDataEntry.cs index 35542c1b4..aa63c3b35 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccLut8TagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccLut8TagDataEntry.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -71,7 +71,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc bool is3By3 = matrix.GetLength(0) == 3 && matrix.GetLength(1) == 3; Guard.IsTrue(is3By3, nameof(matrix), "Matrix must have a size of three by three"); - this.Matrix = this.CreateMatrix(matrix); + this.Matrix = CreateMatrix(matrix); this.InputValues = inputValues ?? throw new ArgumentNullException(nameof(inputValues)); this.ClutValues = clutValues ?? throw new ArgumentNullException(nameof(clutValues)); this.OutputValues = outputValues ?? throw new ArgumentNullException(nameof(outputValues)); @@ -141,18 +141,15 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// public override int GetHashCode() - { - return HashCode.Combine( + => HashCode.Combine( this.Signature, this.Matrix, this.InputValues, this.ClutValues, this.OutputValues); - } - private Matrix4x4 CreateMatrix(float[,] matrix) - { - return new Matrix4x4( + private static Matrix4x4 CreateMatrix(float[,] matrix) + => new( matrix[0, 0], matrix[0, 1], matrix[0, 2], @@ -169,6 +166,5 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc 0, 0, 1); - } } } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccLutAToBTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccLutAToBTagDataEntry.cs index 21d46b016..0c338dabd 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccLutAToBTagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccLutAToBTagDataEntry.cs @@ -53,13 +53,13 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc IccProfileTag tagSignature) : base(IccTypeSignature.LutAToB, tagSignature) { - this.VerifyMatrix(matrix3x3, matrix3x1); + VerifyMatrix(matrix3x3, matrix3x1); this.VerifyCurve(curveA, nameof(curveA)); this.VerifyCurve(curveB, nameof(curveB)); this.VerifyCurve(curveM, nameof(curveM)); - this.Matrix3x3 = this.CreateMatrix3x3(matrix3x3); - this.Matrix3x1 = this.CreateMatrix3x1(matrix3x1); + this.Matrix3x3 = CreateMatrix3x3(matrix3x3); + this.Matrix3x1 = CreateMatrix3x1(matrix3x1); this.CurveA = curveA; this.CurveB = curveB; this.CurveM = curveM; @@ -212,29 +212,23 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc } private bool IsAClutMMatrixB() - { - return this.CurveB != null - && this.Matrix3x3 != null - && this.Matrix3x1 != null - && this.CurveM != null - && this.ClutValues != null - && this.CurveA != null; - } + => this.CurveB != null + && this.Matrix3x3 != null + && this.Matrix3x1 != null + && this.CurveM != null + && this.ClutValues != null + && this.CurveA != null; private bool IsMMatrixB() - { - return this.CurveB != null - && this.Matrix3x3 != null - && this.Matrix3x1 != null - && this.CurveM != null; - } + => this.CurveB != null + && this.Matrix3x3 != null + && this.Matrix3x1 != null + && this.CurveM != null; private bool IsAClutB() - { - return this.CurveB != null - && this.ClutValues != null - && this.CurveA != null; - } + => this.CurveB != null + && this.ClutValues != null + && this.CurveA != null; private bool IsB() => this.CurveB != null; @@ -242,12 +236,12 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { if (curves != null) { - bool isNotCurve = curves.Any(t => !(t is IccParametricCurveTagDataEntry) && !(t is IccCurveTagDataEntry)); + bool isNotCurve = curves.Any(t => t is not IccParametricCurveTagDataEntry and not IccCurveTagDataEntry); Guard.IsFalse(isNotCurve, nameof(name), $"{nameof(name)} must be of type {nameof(IccParametricCurveTagDataEntry)} or {nameof(IccCurveTagDataEntry)}"); } } - private void VerifyMatrix(float[,] matrix3x3, float[] matrix3x1) + private static void VerifyMatrix(float[,] matrix3x3, float[] matrix3x1) { if (matrix3x1 != null) { @@ -261,7 +255,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc } } - private Vector3? CreateMatrix3x1(float[] matrix) + private static Vector3? CreateMatrix3x1(float[] matrix) { if (matrix is null) { @@ -271,7 +265,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc return new Vector3(matrix[0], matrix[1], matrix[2]); } - private Matrix4x4? CreateMatrix3x3(float[,] matrix) + private static Matrix4x4? CreateMatrix3x3(float[,] matrix) { if (matrix is null) { diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccLutBToATagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccLutBToATagDataEntry.cs index 89b010180..2c4487bca 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccLutBToATagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccLutBToATagDataEntry.cs @@ -53,13 +53,13 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc IccProfileTag tagSignature) : base(IccTypeSignature.LutBToA, tagSignature) { - this.VerifyMatrix(matrix3x3, matrix3x1); + VerifyMatrix(matrix3x3, matrix3x1); this.VerifyCurve(curveA, nameof(curveA)); this.VerifyCurve(curveB, nameof(curveB)); this.VerifyCurve(curveM, nameof(curveM)); - this.Matrix3x3 = this.CreateMatrix3x3(matrix3x3); - this.Matrix3x1 = this.CreateMatrix3x1(matrix3x1); + this.Matrix3x3 = CreateMatrix3x3(matrix3x3); + this.Matrix3x1 = CreateMatrix3x1(matrix3x1); this.CurveA = curveA; this.CurveB = curveB; this.CurveM = curveM; @@ -167,9 +167,9 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc && this.Matrix3x3.Equals(other.Matrix3x3) && this.Matrix3x1.Equals(other.Matrix3x1) && this.ClutValues.Equals(other.ClutValues) - && this.EqualsCurve(this.CurveB, other.CurveB) - && this.EqualsCurve(this.CurveM, other.CurveM) - && this.EqualsCurve(this.CurveA, other.CurveA); + && EqualsCurve(this.CurveB, other.CurveB) + && EqualsCurve(this.CurveM, other.CurveM) + && EqualsCurve(this.CurveA, other.CurveA); } /// @@ -192,7 +192,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc return hashCode.ToHashCode(); } - private bool EqualsCurve(IccTagDataEntry[] thisCurves, IccTagDataEntry[] entryCurves) + private static bool EqualsCurve(IccTagDataEntry[] thisCurves, IccTagDataEntry[] entryCurves) { bool thisNull = thisCurves is null; bool entryNull = entryCurves is null; @@ -211,29 +211,13 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc } private bool IsBMatrixMClutA() - { - return this.CurveB != null - && this.Matrix3x3 != null - && this.Matrix3x1 != null - && this.CurveM != null - && this.ClutValues != null - && this.CurveA != null; - } + => this.CurveB != null && this.Matrix3x3 != null && this.Matrix3x1 != null && this.CurveM != null && this.ClutValues != null && this.CurveA != null; private bool IsBMatrixM() - { - return this.CurveB != null - && this.Matrix3x3 != null - && this.Matrix3x1 != null - && this.CurveM != null; - } + => this.CurveB != null && this.Matrix3x3 != null && this.Matrix3x1 != null && this.CurveM != null; private bool IsBClutA() - { - return this.CurveB != null - && this.ClutValues != null - && this.CurveA != null; - } + => this.CurveB != null && this.ClutValues != null && this.CurveA != null; private bool IsB() => this.CurveB != null; @@ -241,12 +225,12 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { if (curves != null) { - bool isNotCurve = curves.Any(t => !(t is IccParametricCurveTagDataEntry) && !(t is IccCurveTagDataEntry)); + bool isNotCurve = curves.Any(t => t is not IccParametricCurveTagDataEntry and not IccCurveTagDataEntry); Guard.IsFalse(isNotCurve, nameof(name), $"{nameof(name)} must be of type {nameof(IccParametricCurveTagDataEntry)} or {nameof(IccCurveTagDataEntry)}"); } } - private void VerifyMatrix(float[,] matrix3x3, float[] matrix3x1) + private static void VerifyMatrix(float[,] matrix3x3, float[] matrix3x1) { if (matrix3x1 != null) { @@ -260,7 +244,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc } } - private Vector3? CreateMatrix3x1(float[] matrix) + private static Vector3? CreateMatrix3x1(float[] matrix) { if (matrix is null) { @@ -270,7 +254,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc return new Vector3(matrix[0], matrix[1], matrix[2]); } - private Matrix4x4? CreateMatrix3x3(float[,] matrix) + private static Matrix4x4? CreateMatrix3x3(float[,] matrix) { if (matrix is null) { diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccNamedColor2TagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccNamedColor2TagDataEntry.cs index c2c959d29..8541d287d 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccNamedColor2TagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccNamedColor2TagDataEntry.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -121,9 +121,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// public override bool Equals(IccTagDataEntry other) - { - return other is IccNamedColor2TagDataEntry entry && this.Equals(entry); - } + => other is IccNamedColor2TagDataEntry entry && this.Equals(entry); /// public bool Equals(IccNamedColor2TagDataEntry other) @@ -140,28 +138,24 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc return base.Equals(other) && this.CoordinateCount == other.CoordinateCount - && string.Equals(this.Prefix, other.Prefix) - && string.Equals(this.Suffix, other.Suffix) + && string.Equals(this.Prefix, other.Prefix, StringComparison.OrdinalIgnoreCase) + && string.Equals(this.Suffix, other.Suffix, StringComparison.OrdinalIgnoreCase) && this.VendorFlags == other.VendorFlags && this.Colors.AsSpan().SequenceEqual(other.Colors); } /// public override bool Equals(object obj) - { - return obj is IccNamedColor2TagDataEntry other && this.Equals(other); - } + => obj is IccNamedColor2TagDataEntry other && this.Equals(other); /// public override int GetHashCode() - { - return HashCode.Combine( + => HashCode.Combine( this.Signature, this.CoordinateCount, this.Prefix, this.Suffix, this.VendorFlags, this.Colors); - } } } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccSignatureTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccSignatureTagDataEntry.cs index 148450de6..2924a5dc6 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccSignatureTagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccSignatureTagDataEntry.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -27,9 +27,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// Tag Signature public IccSignatureTagDataEntry(string signatureData, IccProfileTag tagSignature) : base(IccTypeSignature.Signature, tagSignature) - { - this.SignatureData = signatureData ?? throw new ArgumentNullException(nameof(signatureData)); - } + => this.SignatureData = signatureData ?? throw new ArgumentNullException(nameof(signatureData)); /// /// Gets the signature data @@ -38,9 +36,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// public override bool Equals(IccTagDataEntry other) - { - return other is IccSignatureTagDataEntry entry && this.Equals(entry); - } + => other is IccSignatureTagDataEntry entry && this.Equals(entry); /// public bool Equals(IccSignatureTagDataEntry other) @@ -55,14 +51,13 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc return true; } - return base.Equals(other) && string.Equals(this.SignatureData, other.SignatureData); + return base.Equals(other) + && string.Equals(this.SignatureData, other.SignatureData, StringComparison.OrdinalIgnoreCase); } /// public override bool Equals(object obj) - { - return obj is IccSignatureTagDataEntry other && this.Equals(other); - } + => obj is IccSignatureTagDataEntry other && this.Equals(other); /// public override int GetHashCode() => HashCode.Combine(this.Signature, this.SignatureData); diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccTextDescriptionTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccTextDescriptionTagDataEntry.cs index 1d9da5398..6fb2aca20 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccTextDescriptionTagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccTextDescriptionTagDataEntry.cs @@ -104,7 +104,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc return new IccMultiLocalizedUnicodeTagDataEntry(new[] { localString }, textEntry.TagSignature); - CultureInfo GetCulture(uint value) + static CultureInfo GetCulture(uint value) { if (value == 0) { @@ -122,7 +122,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc && p3 >= 0x41 && p3 <= 0x5A && p4 >= 0x41 && p4 <= 0x5A) { - var culture = new string(new[] { (char)p1, (char)p2, '-', (char)p3, (char)p4 }); + string culture = new(new[] { (char)p1, (char)p2, '-', (char)p3, (char)p4 }); return new CultureInfo(culture); } @@ -132,9 +132,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// public override bool Equals(IccTagDataEntry other) - { - return other is IccTextDescriptionTagDataEntry entry && this.Equals(entry); - } + => other is IccTextDescriptionTagDataEntry entry && this.Equals(entry); /// public bool Equals(IccTextDescriptionTagDataEntry other) @@ -150,29 +148,25 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc } return base.Equals(other) - && string.Equals(this.Ascii, other.Ascii) - && string.Equals(this.Unicode, other.Unicode) - && string.Equals(this.ScriptCode, other.ScriptCode) + && string.Equals(this.Ascii, other.Ascii, StringComparison.OrdinalIgnoreCase) + && string.Equals(this.Unicode, other.Unicode, StringComparison.OrdinalIgnoreCase) + && string.Equals(this.ScriptCode, other.ScriptCode, StringComparison.OrdinalIgnoreCase) && this.UnicodeLanguageCode == other.UnicodeLanguageCode && this.ScriptCodeCode == other.ScriptCodeCode; } /// public override bool Equals(object obj) - { - return obj is IccTextDescriptionTagDataEntry other && this.Equals(other); - } + => obj is IccTextDescriptionTagDataEntry other && this.Equals(other); /// public override int GetHashCode() - { - return HashCode.Combine( + => HashCode.Combine( this.Signature, this.Ascii, this.Unicode, this.ScriptCode, this.UnicodeLanguageCode, this.ScriptCodeCode); - } } } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccTextTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccTextTagDataEntry.cs index 4af43a1a8..9463f665a 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccTextTagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccTextTagDataEntry.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -26,9 +26,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// Tag Signature public IccTextTagDataEntry(string text, IccProfileTag tagSignature) : base(IccTypeSignature.Text, tagSignature) - { - this.Text = text ?? throw new ArgumentNullException(nameof(text)); - } + => this.Text = text ?? throw new ArgumentNullException(nameof(text)); /// /// Gets the Text @@ -37,9 +35,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// public override bool Equals(IccTagDataEntry other) - { - return other is IccTextTagDataEntry entry && this.Equals(entry); - } + => other is IccTextTagDataEntry entry && this.Equals(entry); /// public bool Equals(IccTextTagDataEntry other) @@ -54,14 +50,12 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc return true; } - return base.Equals(other) && string.Equals(this.Text, other.Text); + return base.Equals(other) && string.Equals(this.Text, other.Text, StringComparison.OrdinalIgnoreCase); } /// public override bool Equals(object obj) - { - return obj is IccTextTagDataEntry other && this.Equals(other); - } + => obj is IccTextTagDataEntry other && this.Equals(other); /// public override int GetHashCode() => HashCode.Combine(this.Signature, this.Text); diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccUcrBgTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccUcrBgTagDataEntry.cs index e48c9d3b3..d806ca2a5 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccUcrBgTagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccUcrBgTagDataEntry.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -54,9 +54,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// public override bool Equals(IccTagDataEntry other) - { - return other is IccUcrBgTagDataEntry entry && this.Equals(entry); - } + => other is IccUcrBgTagDataEntry entry && this.Equals(entry); /// public bool Equals(IccUcrBgTagDataEntry other) @@ -74,23 +72,19 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc return base.Equals(other) && this.UcrCurve.AsSpan().SequenceEqual(other.UcrCurve) && this.BgCurve.AsSpan().SequenceEqual(other.BgCurve) - && string.Equals(this.Description, other.Description); + && string.Equals(this.Description, other.Description, StringComparison.OrdinalIgnoreCase); } /// public override bool Equals(object obj) - { - return obj is IccUcrBgTagDataEntry other && this.Equals(other); - } + => obj is IccUcrBgTagDataEntry other && this.Equals(other); /// public override int GetHashCode() - { - return HashCode.Combine( + => HashCode.Combine( this.Signature, this.UcrCurve, this.BgCurve, this.Description); - } } } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccXyzTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccXyzTagDataEntry.cs index 319ea8fde..8a3080240 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccXyzTagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccXyzTagDataEntry.cs @@ -1,9 +1,8 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; using System.Numerics; -using System.Runtime.CompilerServices; namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { @@ -28,9 +27,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// Tag Signature public IccXyzTagDataEntry(Vector3[] data, IccProfileTag tagSignature) : base(IccTypeSignature.Xyz, tagSignature) - { - this.Data = data ?? throw new ArgumentNullException(nameof(data)); - } + => this.Data = data ?? throw new ArgumentNullException(nameof(data)); /// /// Gets the XYZ numbers. @@ -50,8 +47,13 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// public bool Equals(IccXyzTagDataEntry other) - { - return this.Equals((IccTagDataEntry)other); - } + => this.Equals((IccTagDataEntry)other); + + /// + public override bool Equals(object obj) + => this.Equals(obj as IccXyzTagDataEntry); + + public override int GetHashCode() + => HashCode.Combine(base.GetHashCode(), this.Data); } } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccLocalizedString.cs b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccLocalizedString.cs index 20ca0248a..63f97d45c 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccLocalizedString.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccLocalizedString.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -50,5 +50,11 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// public override string ToString() => $"{this.Culture.Name}: {this.Text}"; + + public override bool Equals(object obj) + => obj is IccLocalizedString iccLocalizedString && this.Equals(iccLocalizedString); + + public override int GetHashCode() + => HashCode.Combine(this.Culture, this.Text); } } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccLut.cs b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccLut.cs index dfe186d7d..b5709db4d 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccLut.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccLut.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -15,9 +15,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// /// The LUT values public IccLut(float[] values) - { - this.Values = values ?? throw new ArgumentNullException(nameof(values)); - } + => this.Values = values ?? throw new ArgumentNullException(nameof(values)); /// /// Initializes a new instance of the struct. @@ -68,5 +66,13 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc return this.Values.AsSpan().SequenceEqual(other.Values); } + + /// + public override bool Equals(object obj) + => obj is IccLut iccLut && this.Equals(iccLut); + + /// + public override int GetHashCode() + => this.Values.GetHashCode(); } } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccNamedColor.cs b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccNamedColor.cs index a0e767a7c..8010f78bc 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccNamedColor.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccNamedColor.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -71,20 +71,16 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// public bool Equals(IccNamedColor other) - { - return this.Name.Equals(other.Name) - && this.PcsCoordinates.AsSpan().SequenceEqual(other.PcsCoordinates) - && this.DeviceCoordinates.AsSpan().SequenceEqual(other.DeviceCoordinates); - } + => this.Name.Equals(other.Name, StringComparison.OrdinalIgnoreCase) + && this.PcsCoordinates.AsSpan().SequenceEqual(other.PcsCoordinates) + && this.DeviceCoordinates.AsSpan().SequenceEqual(other.DeviceCoordinates); /// public override int GetHashCode() - { - return HashCode.Combine( + => HashCode.Combine( this.Name, this.PcsCoordinates, this.DeviceCoordinates); - } /// public override string ToString() => this.Name; diff --git a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccProfileId.cs b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccProfileId.cs index 6633d2a68..b4e6e573b 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccProfileId.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccProfileId.cs @@ -1,7 +1,8 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; +using System.Globalization; namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { @@ -13,7 +14,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// /// A profile ID with all values set to zero /// - public static readonly IccProfileId Zero = default; + public static readonly IccProfileId Zero; /// /// Initializes a new instance of the struct. @@ -67,10 +68,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// /// True if the parameter is equal to the parameter; otherwise, false. /// - public static bool operator ==(IccProfileId left, IccProfileId right) - { - return left.Equals(right); - } + public static bool operator ==(IccProfileId left, IccProfileId right) => left.Equals(right); /// /// Compares two objects for equality. @@ -80,10 +78,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// /// True if the parameter is not equal to the parameter; otherwise, false. /// - public static bool operator !=(IccProfileId left, IccProfileId right) - { - return !left.Equals(right); - } + public static bool operator !=(IccProfileId left, IccProfileId right) => !left.Equals(right); /// public override bool Equals(object obj) => obj is IccProfileId other && this.Equals(other); @@ -97,17 +92,15 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// public override int GetHashCode() - { - return HashCode.Combine( + => HashCode.Combine( this.Part1, this.Part2, this.Part3, this.Part4); - } /// public override string ToString() => $"{ToHex(this.Part1)}-{ToHex(this.Part2)}-{ToHex(this.Part3)}-{ToHex(this.Part4)}"; - private static string ToHex(uint value) => value.ToString("X").PadLeft(8, '0'); + private static string ToHex(uint value) => value.ToString("X", CultureInfo.InvariantCulture).PadLeft(8, '0'); } } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccVersion.cs b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccVersion.cs index f8f2b653a..4b8cb91f7 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccVersion.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccVersion.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -38,6 +38,28 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// public int Patch { get; } + /// + /// Returns a value indicating whether the two values are equal. + /// + /// The first value. + /// The second value. + /// if the two value are equal; otherwise, . + public static bool operator ==(IccVersion left, IccVersion right) + => left.Equals(right); + + /// + /// Returns a value indicating whether the two values are not equal. + /// + /// The first value. + /// The second value. + /// if the two value are not equal; otherwise, . + public static bool operator !=(IccVersion left, IccVersion right) + => !(left == right); + + /// + public override bool Equals(object obj) + => obj is IccVersion iccVersion && this.Equals(iccVersion); + /// public bool Equals(IccVersion other) => this.Major == other.Major && @@ -46,8 +68,10 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// public override string ToString() - { - return string.Join(".", this.Major, this.Minor, this.Patch); - } + => string.Join(".", this.Major, this.Minor, this.Patch); + + /// + public override int GetHashCode() + => HashCode.Combine(this.Major, this.Minor, this.Patch); } } diff --git a/src/ImageSharp/Metadata/Profiles/IPTC/IptcProfile.cs b/src/ImageSharp/Metadata/Profiles/IPTC/IptcProfile.cs index ec3eed265..bc94e9555 100644 --- a/src/ImageSharp/Metadata/Profiles/IPTC/IptcProfile.cs +++ b/src/ImageSharp/Metadata/Profiles/IPTC/IptcProfile.cs @@ -5,6 +5,7 @@ using System; using System.Buffers.Binary; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Globalization; using System.Text; using SixLabors.ImageSharp.Metadata.Profiles.IPTC; @@ -102,7 +103,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Iptc /// The values found with the specified tag. public List GetValues(IptcTag tag) { - var iptcValues = new List(); + List iptcValues = new(); foreach (IptcValue iptcValue in this.Values) { if (iptcValue.Tag == tag) @@ -149,7 +150,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Iptc bool removed = false; for (int i = this.values.Count - 1; i >= 0; i--) { - if (this.values[i].Tag == tag && this.values[i].Value.Equals(value)) + if (this.values[i].Tag == tag && this.values[i].Value.Equals(value, StringComparison.OrdinalIgnoreCase)) { this.values.RemoveAt(i); removed = true; @@ -226,16 +227,17 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Iptc /// /// The tag of the iptc value. /// The datetime. + /// Iptc tag is not a time or date type. public void SetDateTimeValue(IptcTag tag, DateTimeOffset dateTimeOffset) { if (!tag.IsDate() && !tag.IsTime()) { - throw new ArgumentException("iptc tag is not a time or date type"); + throw new ArgumentException("Iptc tag is not a time or date type."); } string formattedDate = tag.IsDate() - ? dateTimeOffset.ToString("yyyyMMdd", System.Globalization.CultureInfo.InvariantCulture) - : dateTimeOffset.ToString("HHmmsszzzz", System.Globalization.CultureInfo.InvariantCulture) + ? dateTimeOffset.ToString("yyyyMMdd", CultureInfo.InvariantCulture) + : dateTimeOffset.ToString("HHmmsszzzz", CultureInfo.InvariantCulture) .Replace(":", string.Empty); this.SetValue(tag, Encoding.UTF8, formattedDate); @@ -329,7 +331,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Iptc bool isValidTagMarker = this.Data[offset++] == IptcTagMarkerByte; byte recordNumber = this.Data[offset++]; bool isValidRecordNumber = recordNumber is >= 1 and <= 9; - var tag = (IptcTag)this.Data[offset++]; + IptcTag tag = (IptcTag)this.Data[offset++]; bool isValidEntry = isValidTagMarker && isValidRecordNumber; bool isApplicationRecord = recordNumber == (byte)IptcRecordNumber.Application; diff --git a/src/ImageSharp/Metadata/Profiles/XMP/XmpProfile.cs b/src/ImageSharp/Metadata/Profiles/XMP/XmpProfile.cs index 06595b991..095beb24a 100644 --- a/src/ImageSharp/Metadata/Profiles/XMP/XmpProfile.cs +++ b/src/ImageSharp/Metadata/Profiles/XMP/XmpProfile.cs @@ -67,15 +67,15 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Xmp } } - using var stream = new MemoryStream(byteArray, 0, count); - using var reader = new StreamReader(stream, Encoding.UTF8); + using MemoryStream stream = new(byteArray, 0, count); + using StreamReader reader = new(stream, Encoding.UTF8); return XDocument.Load(reader); } /// /// Convert the content of this into a byte array. /// - /// The + /// The public byte[] ToByteArray() { byte[] result = new byte[this.Data.Length]; diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/HalfSingle.cs b/src/ImageSharp/PixelFormats/PixelImplementations/HalfSingle.cs index a415f41cc..84354a5c2 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/HalfSingle.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/HalfSingle.cs @@ -18,8 +18,8 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Initializes a new instance of the struct. /// - /// The single component. - public HalfSingle(float single) => this.PackedValue = HalfTypeHelper.Pack(single); + /// The single component value. + public HalfSingle(float value) => this.PackedValue = HalfTypeHelper.Pack(value); /// public ushort PackedValue { get; set; } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs index 55dd80af1..d15a46d69 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs @@ -240,6 +240,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// The . /// + /// Hexadecimal string is not in the correct format. [MethodImpl(InliningOptions.ShortMethod)] public static Rgba32 ParseHex(string hex) { @@ -432,7 +433,7 @@ namespace SixLabors.ImageSharp.PixelFormats public readonly string ToHex() { uint hexOrder = (uint)((this.A << 0) | (this.B << 8) | (this.G << 16) | (this.R << 24)); - return hexOrder.ToString("X8"); + return hexOrder.ToString("X8", CultureInfo.InvariantCulture); } /// diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.cs b/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.cs index 93037fcbc..7973ee3dc 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.cs @@ -2,6 +2,7 @@ // Licensed under the Six Labors Split License. using System; +using System.Globalization; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -188,7 +189,7 @@ namespace SixLabors.ImageSharp.PixelFormats Vector4 vector = this.ToVector4() * Max; vector += Half; uint hexOrder = (uint)((byte)vector.W | ((byte)vector.Z << 8) | ((byte)vector.Y << 16) | ((byte)vector.X << 24)); - return hexOrder.ToString("X8"); + return hexOrder.ToString("X8", CultureInfo.InvariantCulture); } /// diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs index 9d2a2f1b2..0662ffb71 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs @@ -20,11 +20,14 @@ namespace SixLabors.ImageSharp.PixelFormats where TPixel : unmanaged, IPixel { private static readonly Lazy LazyInfo = new(() => PixelTypeInfo.Create(), true); + private static readonly Lazy> LazyInstance = new(() => default(TPixel).CreatePixelOperations(), true); /// /// Gets the global instance for the pixel type /// - public static PixelOperations Instance { get; } = default(TPixel).CreatePixelOperations(); +#pragma warning disable CA1000 // Do not declare static members on generic types + public static PixelOperations Instance => LazyInstance.Value; +#pragma warning restore CA1000 // Do not declare static members on generic types /// /// Gets the pixel type info for the given . diff --git a/src/ImageSharp/Primitives/DenseMatrix{T}.cs b/src/ImageSharp/Primitives/DenseMatrix{T}.cs index 471e4f6b2..7eee4a1b0 100644 --- a/src/ImageSharp/Primitives/DenseMatrix{T}.cs +++ b/src/ImageSharp/Primitives/DenseMatrix{T}.cs @@ -16,31 +16,6 @@ namespace SixLabors.ImageSharp public readonly struct DenseMatrix : IEquatable> where T : struct, IEquatable { - /// - /// The 1D representation of the dense matrix. - /// - public readonly T[] Data; - - /// - /// Gets the number of columns in the dense matrix. - /// - public readonly int Columns; - - /// - /// Gets the number of rows in the dense matrix. - /// - public readonly int Rows; - - /// - /// Gets the size of the dense matrix. - /// - public readonly Size Size; - - /// - /// Gets the number of items in the array. - /// - public readonly int Count; - /// /// Initializes a new instance of the struct. /// @@ -96,10 +71,35 @@ namespace SixLabors.ImageSharp } } + /// + /// Gets the 1D representation of the dense matrix. + /// + public readonly T[] Data { get; } + + /// + /// Gets the number of columns in the dense matrix. + /// + public readonly int Columns { get; } + + /// + /// Gets the number of rows in the dense matrix. + /// + public readonly int Rows { get; } + + /// + /// Gets the size of the dense matrix. + /// + public readonly Size Size { get; } + + /// + /// Gets the number of items in the array. + /// + public readonly int Count { get; } + /// /// Gets a span wrapping the . /// - public Span Span => new Span(this.Data); + public Span Span => new(this.Data); /// /// Gets or sets the item at the specified position. @@ -125,7 +125,7 @@ namespace SixLabors.ImageSharp /// The representation on the source data. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator DenseMatrix(T[,] data) => new DenseMatrix(data); + public static implicit operator DenseMatrix(T[,] data) => new(data); /// /// Performs an implicit conversion from a to a . @@ -139,7 +139,7 @@ namespace SixLabors.ImageSharp public static implicit operator T[,](in DenseMatrix data) #pragma warning restore SA1008 // Opening parenthesis should be spaced correctly { - var result = new T[data.Rows, data.Columns]; + T[,] result = new T[data.Rows, data.Columns]; for (int y = 0; y < data.Rows; y++) { @@ -178,7 +178,7 @@ namespace SixLabors.ImageSharp [MethodImpl(MethodImplOptions.AggressiveInlining)] public DenseMatrix Transpose() { - var result = new DenseMatrix(this.Rows, this.Columns); + DenseMatrix result = new DenseMatrix(this.Rows, this.Columns); for (int y = 0; y < this.Rows; y++) { diff --git a/src/ImageSharp/Primitives/LongRational.cs b/src/ImageSharp/Primitives/LongRational.cs index a181084aa..062036a57 100644 --- a/src/ImageSharp/Primitives/LongRational.cs +++ b/src/ImageSharp/Primitives/LongRational.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -66,23 +66,21 @@ namespace SixLabors.ImageSharp /// public bool IsZero => this.Denominator == 1 && this.Numerator == 0; + /// + public override bool Equals(object obj) + => obj is LongRational longRational && this.Equals(longRational); + /// public bool Equals(LongRational other) - { - return this.Numerator == other.Numerator && this.Denominator == other.Denominator; - } + => this.Numerator == other.Numerator && this.Denominator == other.Denominator; /// public override int GetHashCode() - { - return ((this.Numerator * 397) ^ this.Denominator).GetHashCode(); - } + => HashCode.Combine(this.Numerator, this.Denominator); /// public override string ToString() - { - return this.ToString(CultureInfo.InvariantCulture); - } + => this.ToString(CultureInfo.InvariantCulture); /// /// Converts the numeric value of this instance to its equivalent string representation using @@ -119,10 +117,11 @@ namespace SixLabors.ImageSharp return this.Numerator.ToString(provider); } - var sb = new StringBuilder(); - sb.Append(this.Numerator.ToString(provider)); - sb.Append('/'); - sb.Append(this.Denominator.ToString(provider)); + StringBuilder sb = new(); + sb.Append(this.Numerator.ToString(provider)) + .Append('/') + .Append(this.Denominator.ToString(provider)); + return sb.ToString(); } diff --git a/src/ImageSharp/Primitives/Point.cs b/src/ImageSharp/Primitives/Point.cs index 89db9befb..356595cb4 100644 --- a/src/ImageSharp/Primitives/Point.cs +++ b/src/ImageSharp/Primitives/Point.cs @@ -21,7 +21,7 @@ namespace SixLabors.ImageSharp /// /// Represents a that has X and Y values set to zero. /// - public static readonly Point Empty = default; + public static readonly Point Empty; /// /// Initializes a new instance of the struct. @@ -77,28 +77,28 @@ namespace SixLabors.ImageSharp /// /// The point. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator PointF(Point point) => new PointF(point.X, point.Y); + public static implicit operator PointF(Point point) => new(point.X, point.Y); /// /// Creates a with the coordinates of the specified . /// /// The point. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator Vector2(Point point) => new Vector2(point.X, point.Y); + public static implicit operator Vector2(Point point) => new(point.X, point.Y); /// /// Creates a with the coordinates of the specified . /// /// The point. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static explicit operator Size(Point point) => new Size(point.X, point.Y); + public static explicit operator Size(Point point) => new(point.X, point.Y); /// /// Negates the given point by multiplying all values by -1. /// /// The source point. /// The negated point. - public static Point operator -(Point value) => new Point(-value.X, -value.Y); + public static Point operator -(Point value) => new(-value.X, -value.Y); /// /// Translates a by a given . @@ -143,7 +143,7 @@ namespace SixLabors.ImageSharp /// Divisor of type . /// Result of type . public static Point operator /(Point left, int right) - => new Point(left.X / right, left.Y / right); + => new(left.X / right, left.Y / right); /// /// Compares two objects for equality. @@ -174,7 +174,7 @@ namespace SixLabors.ImageSharp /// The size on the right hand of the operand. /// The . [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Point Add(Point point, Size size) => new Point(unchecked(point.X + size.Width), unchecked(point.Y + size.Height)); + public static Point Add(Point point, Size size) => new(unchecked(point.X + size.Width), unchecked(point.Y + size.Height)); /// /// Translates a by the negative of a given value. @@ -183,7 +183,7 @@ namespace SixLabors.ImageSharp /// The value on the right hand of the operand. /// The . [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Point Multiply(Point point, int value) => new Point(unchecked(point.X * value), unchecked(point.Y * value)); + public static Point Multiply(Point point, int value) => new(unchecked(point.X * value), unchecked(point.Y * value)); /// /// Translates a by the negative of a given . @@ -192,7 +192,7 @@ namespace SixLabors.ImageSharp /// The size on the right hand of the operand. /// The . [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Point Subtract(Point point, Size size) => new Point(unchecked(point.X - size.Width), unchecked(point.Y - size.Height)); + public static Point Subtract(Point point, Size size) => new(unchecked(point.X - size.Width), unchecked(point.Y - size.Height)); /// /// Converts a to a by performing a ceiling operation on all the coordinates. @@ -200,7 +200,7 @@ namespace SixLabors.ImageSharp /// The point. /// The . [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Point Ceiling(PointF point) => new Point(unchecked((int)MathF.Ceiling(point.X)), unchecked((int)MathF.Ceiling(point.Y))); + public static Point Ceiling(PointF point) => new(unchecked((int)MathF.Ceiling(point.X)), unchecked((int)MathF.Ceiling(point.Y))); /// /// Converts a to a by performing a round operation on all the coordinates. @@ -208,7 +208,7 @@ namespace SixLabors.ImageSharp /// The point. /// The . [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Point Round(PointF point) => new Point(unchecked((int)MathF.Round(point.X)), unchecked((int)MathF.Round(point.Y))); + public static Point Round(PointF point) => new(unchecked((int)MathF.Round(point.X)), unchecked((int)MathF.Round(point.Y))); /// /// Converts a to a by performing a round operation on all the coordinates. @@ -216,7 +216,7 @@ namespace SixLabors.ImageSharp /// The vector. /// The . [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Point Round(Vector2 vector) => new Point(unchecked((int)MathF.Round(vector.X)), unchecked((int)MathF.Round(vector.Y))); + public static Point Round(Vector2 vector) => new(unchecked((int)MathF.Round(vector.X)), unchecked((int)MathF.Round(vector.Y))); /// /// Converts a to a by performing a truncate operation on all the coordinates. @@ -224,7 +224,7 @@ namespace SixLabors.ImageSharp /// The point. /// The . [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Point Truncate(PointF point) => new Point(unchecked((int)point.X), unchecked((int)point.Y)); + public static Point Truncate(PointF point) => new(unchecked((int)point.X), unchecked((int)point.Y)); /// /// Transforms a point by a specified 3x2 matrix. diff --git a/src/ImageSharp/Primitives/PointF.cs b/src/ImageSharp/Primitives/PointF.cs index 9817f04f3..d701f3d54 100644 --- a/src/ImageSharp/Primitives/PointF.cs +++ b/src/ImageSharp/Primitives/PointF.cs @@ -21,7 +21,7 @@ namespace SixLabors.ImageSharp /// /// Represents a that has X and Y values set to zero. /// - public static readonly PointF Empty = default; + public static readonly PointF Empty; /// /// Initializes a new instance of the struct. @@ -69,7 +69,7 @@ namespace SixLabors.ImageSharp /// The . /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator PointF(Vector2 vector) => new PointF(vector.X, vector.Y); + public static implicit operator PointF(Vector2 vector) => new(vector.X, vector.Y); /// /// Creates a with the coordinates of the specified . @@ -79,7 +79,7 @@ namespace SixLabors.ImageSharp /// The . /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator Vector2(PointF point) => new Vector2(point.X, point.Y); + public static implicit operator Vector2(PointF point) => new(point.X, point.Y); /// /// Creates a with the coordinates of the specified by truncating each of the coordinates. @@ -96,7 +96,7 @@ namespace SixLabors.ImageSharp /// /// The source point. /// The negated point. - public static PointF operator -(PointF value) => new PointF(-value.X, -value.Y); + public static PointF operator -(PointF value) => new(-value.X, -value.Y); /// /// Translates a by a given . @@ -161,7 +161,7 @@ namespace SixLabors.ImageSharp /// Divisor of type . /// Result of type . public static PointF operator /(PointF left, float right) - => new PointF(left.X / right, left.Y / right); + => new(left.X / right, left.Y / right); /// /// Compares two objects for equality. @@ -200,7 +200,7 @@ namespace SixLabors.ImageSharp /// The size on the right hand of the operand. /// The . [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static PointF Add(PointF point, SizeF size) => new PointF(point.X + size.Width, point.Y + size.Height); + public static PointF Add(PointF point, SizeF size) => new(point.X + size.Width, point.Y + size.Height); /// /// Translates a by the given . @@ -209,7 +209,7 @@ namespace SixLabors.ImageSharp /// The point on the right hand of the operand. /// The . [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static PointF Add(PointF point, PointF pointb) => new PointF(point.X + pointb.X, point.Y + pointb.Y); + public static PointF Add(PointF point, PointF pointb) => new(point.X + pointb.X, point.Y + pointb.Y); /// /// Translates a by the negative of a given . @@ -218,7 +218,7 @@ namespace SixLabors.ImageSharp /// The size on the right hand of the operand. /// The . [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static PointF Subtract(PointF point, SizeF size) => new PointF(point.X - size.Width, point.Y - size.Height); + public static PointF Subtract(PointF point, SizeF size) => new(point.X - size.Width, point.Y - size.Height); /// /// Translates a by the negative of a given . @@ -227,7 +227,7 @@ namespace SixLabors.ImageSharp /// The point on the right hand of the operand. /// The . [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static PointF Subtract(PointF point, PointF pointb) => new PointF(point.X - pointb.X, point.Y - pointb.Y); + public static PointF Subtract(PointF point, PointF pointb) => new(point.X - pointb.X, point.Y - pointb.Y); /// /// Translates a by the multiplying the X and Y by the given value. @@ -236,7 +236,7 @@ namespace SixLabors.ImageSharp /// The value on the right hand of the operand. /// The . [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static PointF Multiply(PointF point, float right) => new PointF(point.X * right, point.Y * right); + public static PointF Multiply(PointF point, float right) => new(point.X * right, point.Y * right); /// /// Transforms a point by a specified 3x2 matrix. @@ -284,7 +284,7 @@ namespace SixLabors.ImageSharp public override string ToString() => $"PointF [ X={this.X}, Y={this.Y} ]"; /// - public override bool Equals(object obj) => obj is PointF && this.Equals((PointF)obj); + public override bool Equals(object obj) => obj is PointF pointF && this.Equals(pointF); /// [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/ImageSharp/Primitives/Rectangle.cs b/src/ImageSharp/Primitives/Rectangle.cs index 4c70e0dd9..b21aae1fe 100644 --- a/src/ImageSharp/Primitives/Rectangle.cs +++ b/src/ImageSharp/Primitives/Rectangle.cs @@ -20,7 +20,7 @@ namespace SixLabors.ImageSharp /// /// Represents a that has X, Y, Width, and Height values set to zero. /// - public static readonly Rectangle Empty = default; + public static readonly Rectangle Empty; /// /// Initializes a new instance of the struct. diff --git a/src/ImageSharp/Primitives/RectangleF.cs b/src/ImageSharp/Primitives/RectangleF.cs index aa6f4fc23..9719d2b7e 100644 --- a/src/ImageSharp/Primitives/RectangleF.cs +++ b/src/ImageSharp/Primitives/RectangleF.cs @@ -20,7 +20,7 @@ namespace SixLabors.ImageSharp /// /// Represents a that has X, Y, Width, and Height values set to zero. /// - public static readonly RectangleF Empty = default; + public static readonly RectangleF Empty; /// /// Initializes a new instance of the struct. @@ -81,7 +81,7 @@ namespace SixLabors.ImageSharp public PointF Location { [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => new PointF(this.X, this.Y); + get => new(this.X, this.Y); [MethodImpl(MethodImplOptions.AggressiveInlining)] set @@ -98,7 +98,7 @@ namespace SixLabors.ImageSharp public SizeF Size { [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => new SizeF(this.Width, this.Height); + get => new(this.Width, this.Height); [MethodImpl(MethodImplOptions.AggressiveInlining)] set @@ -181,7 +181,7 @@ namespace SixLabors.ImageSharp [MethodImpl(MethodImplOptions.AggressiveInlining)] // ReSharper disable once InconsistentNaming - public static RectangleF FromLTRB(float left, float top, float right, float bottom) => new RectangleF(left, top, right - left, bottom - top); + public static RectangleF FromLTRB(float left, float top, float right, float bottom) => new(left, top, right - left, bottom - top); /// /// Returns the center point of the given . @@ -189,7 +189,7 @@ namespace SixLabors.ImageSharp /// The rectangle. /// The . [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static PointF Center(RectangleF rectangle) => new PointF(rectangle.Left + (rectangle.Width / 2), rectangle.Top + (rectangle.Height / 2)); + public static PointF Center(RectangleF rectangle) => new(rectangle.Left + (rectangle.Width / 2), rectangle.Top + (rectangle.Height / 2)); /// /// Creates a rectangle that represents the intersection between and @@ -372,15 +372,11 @@ namespace SixLabors.ImageSharp /// public override int GetHashCode() - { - return HashCode.Combine(this.X, this.Y, this.Width, this.Height); - } + => HashCode.Combine(this.X, this.Y, this.Width, this.Height); /// public override string ToString() - { - return $"RectangleF [ X={this.X}, Y={this.Y}, Width={this.Width}, Height={this.Height} ]"; - } + => $"RectangleF [ X={this.X}, Y={this.Y}, Width={this.Width}, Height={this.Height} ]"; /// public override bool Equals(object obj) => obj is RectangleF other && this.Equals(other); diff --git a/src/ImageSharp/Primitives/Size.cs b/src/ImageSharp/Primitives/Size.cs index 83bd39213..0e55b6845 100644 --- a/src/ImageSharp/Primitives/Size.cs +++ b/src/ImageSharp/Primitives/Size.cs @@ -20,7 +20,7 @@ namespace SixLabors.ImageSharp /// /// Represents a that has Width and Height values set to zero. /// - public static readonly Size Empty = default; + public static readonly Size Empty; /// /// Initializes a new instance of the struct. diff --git a/src/ImageSharp/Primitives/SizeF.cs b/src/ImageSharp/Primitives/SizeF.cs index 4e2fba4e9..fed62e512 100644 --- a/src/ImageSharp/Primitives/SizeF.cs +++ b/src/ImageSharp/Primitives/SizeF.cs @@ -20,7 +20,7 @@ namespace SixLabors.ImageSharp /// /// Represents a that has Width and Height values set to zero. /// - public static readonly SizeF Empty = default; + public static readonly SizeF Empty; /// /// Initializes a new instance of the struct. @@ -78,7 +78,7 @@ namespace SixLabors.ImageSharp /// The . /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator Vector2(SizeF point) => new Vector2(point.Width, point.Height); + public static implicit operator Vector2(SizeF point) => new(point.Width, point.Height); /// /// Creates a with the dimensions of the specified by truncating each of the dimensions. @@ -88,14 +88,14 @@ namespace SixLabors.ImageSharp /// The . /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static explicit operator Size(SizeF size) => new Size(unchecked((int)size.Width), unchecked((int)size.Height)); + public static explicit operator Size(SizeF size) => new(unchecked((int)size.Width), unchecked((int)size.Height)); /// /// Converts the given into a . /// /// The size. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static explicit operator PointF(SizeF size) => new PointF(size.Width, size.Height); + public static explicit operator PointF(SizeF size) => new(size.Width, size.Height); /// /// Computes the sum of adding two sizes. @@ -142,7 +142,7 @@ namespace SixLabors.ImageSharp /// Divisor of type . /// Result of type . public static SizeF operator /(SizeF left, float right) - => new SizeF(left.Width / right, left.Height / right); + => new(left.Width / right, left.Height / right); /// /// Compares two objects for equality. @@ -173,7 +173,7 @@ namespace SixLabors.ImageSharp /// The size on the right hand of the operand. /// The . [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SizeF Add(SizeF left, SizeF right) => new SizeF(left.Width + right.Width, left.Height + right.Height); + public static SizeF Add(SizeF left, SizeF right) => new(left.Width + right.Width, left.Height + right.Height); /// /// Contracts a by another . @@ -182,7 +182,7 @@ namespace SixLabors.ImageSharp /// The size on the right hand of the operand. /// The . [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SizeF Subtract(SizeF left, SizeF right) => new SizeF(left.Width - right.Width, left.Height - right.Height); + public static SizeF Subtract(SizeF left, SizeF right) => new(left.Width - right.Width, left.Height - right.Height); /// /// Transforms a size by the given matrix. @@ -228,6 +228,6 @@ namespace SixLabors.ImageSharp /// Multiplier of type . /// Product of type SizeF. private static SizeF Multiply(SizeF size, float multiplier) => - new SizeF(size.Width * multiplier, size.Height * multiplier); + new(size.Width * multiplier, size.Height * multiplier); } } diff --git a/src/ImageSharp/Processing/Processors/Convolution/KernelSamplingMap.cs b/src/ImageSharp/Processing/Processors/Convolution/KernelSamplingMap.cs index a455df412..a4ae9cb4c 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/KernelSamplingMap.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/KernelSamplingMap.cs @@ -60,8 +60,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution int minX = bounds.X; int maxX = bounds.Right - 1; - this.BuildOffsets(this.yOffsets, bounds.Height, kernelHeight, minY, maxY, yBorderMode); - this.BuildOffsets(this.xOffsets, bounds.Width, kernelWidth, minX, maxX, xBorderMode); + BuildOffsets(this.yOffsets, bounds.Height, kernelHeight, minY, maxY, yBorderMode); + BuildOffsets(this.xOffsets, bounds.Width, kernelWidth, minX, maxX, xBorderMode); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -83,7 +83,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void BuildOffsets(IMemoryOwner offsets, int boundsSize, int kernelSize, int min, int max, BorderWrappingMode borderMode) + private static void BuildOffsets(IMemoryOwner offsets, int boundsSize, int kernelSize, int min, int max, BorderWrappingMode borderMode) { int radius = kernelSize >> 1; Span span = offsets.GetSpan(); @@ -97,13 +97,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution } } - this.CorrectBorder(span, kernelSize, min, max, borderMode); + CorrectBorder(span, kernelSize, min, max, borderMode); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void CorrectBorder(Span span, int kernelSize, int min, int max, BorderWrappingMode borderMode) + private static void CorrectBorder(Span span, int kernelSize, int min, int max, BorderWrappingMode borderMode) { - var affectedSize = (kernelSize >> 1) * kernelSize; + int affectedSize = (kernelSize >> 1) * kernelSize; ref int spanBase = ref MemoryMarshal.GetReference(span); if (affectedSize > 0) { @@ -114,20 +114,20 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution Numerics.Clamp(span[^affectedSize..], min, max); break; case BorderWrappingMode.Mirror: - var min2dec = min + min - 1; + int min2dec = min + min - 1; for (int i = 0; i < affectedSize; i++) { - var value = span[i]; + int value = span[i]; if (value < min) { span[i] = min2dec - value; } } - var max2inc = max + max + 1; + int max2inc = max + max + 1; for (int i = span.Length - affectedSize; i < span.Length; i++) { - var value = span[i]; + int value = span[i]; if (value > max) { span[i] = max2inc - value; @@ -136,20 +136,20 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution break; case BorderWrappingMode.Bounce: - var min2 = min + min; + int min2 = min + min; for (int i = 0; i < affectedSize; i++) { - var value = span[i]; + int value = span[i]; if (value < min) { span[i] = min2 - value; } } - var max2 = max + max; + int max2 = max + max; for (int i = span.Length - affectedSize; i < span.Length; i++) { - var value = span[i]; + int value = span[i]; if (value > max) { span[i] = max2 - value; @@ -158,10 +158,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution break; case BorderWrappingMode.Wrap: - var diff = max - min + 1; + int diff = max - min + 1; for (int i = 0; i < affectedSize; i++) { - var value = span[i]; + int value = span[i]; if (value < min) { span[i] = diff + value; @@ -170,7 +170,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution for (int i = span.Length - affectedSize; i < span.Length; i++) { - var value = span[i]; + int value = span[i]; if (value > max) { span[i] = value - diff; diff --git a/src/ImageSharp/Processing/Processors/Convolution/Kernels/EdgeDetector2DKernel.cs b/src/ImageSharp/Processing/Processors/Convolution/Kernels/EdgeDetector2DKernel.cs index 90c2575fc..ff1bba22d 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/Kernels/EdgeDetector2DKernel.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/Kernels/EdgeDetector2DKernel.cs @@ -13,30 +13,30 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// /// An edge detection kernel containing two Kayyali operators. /// - public static EdgeDetector2DKernel KayyaliKernel = new EdgeDetector2DKernel(KayyaliKernels.KayyaliX, KayyaliKernels.KayyaliY); + public static readonly EdgeDetector2DKernel KayyaliKernel = new(KayyaliKernels.KayyaliX, KayyaliKernels.KayyaliY); /// /// An edge detection kernel containing two Prewitt operators. /// . /// - public static EdgeDetector2DKernel PrewittKernel = new EdgeDetector2DKernel(PrewittKernels.PrewittX, PrewittKernels.PrewittY); + public static readonly EdgeDetector2DKernel PrewittKernel = new(PrewittKernels.PrewittX, PrewittKernels.PrewittY); /// /// An edge detection kernel containing two Roberts-Cross operators. /// . /// - public static EdgeDetector2DKernel RobertsCrossKernel = new EdgeDetector2DKernel(RobertsCrossKernels.RobertsCrossX, RobertsCrossKernels.RobertsCrossY); + public static readonly EdgeDetector2DKernel RobertsCrossKernel = new(RobertsCrossKernels.RobertsCrossX, RobertsCrossKernels.RobertsCrossY); /// /// An edge detection kernel containing two Scharr operators. /// - public static EdgeDetector2DKernel ScharrKernel = new EdgeDetector2DKernel(ScharrKernels.ScharrX, ScharrKernels.ScharrY); + public static readonly EdgeDetector2DKernel ScharrKernel = new(ScharrKernels.ScharrX, ScharrKernels.ScharrY); /// /// An edge detection kernel containing two Sobel operators. /// . /// - public static EdgeDetector2DKernel SobelKernel = new EdgeDetector2DKernel(SobelKernels.SobelX, SobelKernels.SobelY); + public static readonly EdgeDetector2DKernel SobelKernel = new(SobelKernels.SobelX, SobelKernels.SobelY); /// /// Initializes a new instance of the struct. diff --git a/src/ImageSharp/Processing/Processors/Convolution/Kernels/EdgeDetectorCompassKernel.cs b/src/ImageSharp/Processing/Processors/Convolution/Kernels/EdgeDetectorCompassKernel.cs index 002f35c3d..41d3c8ad2 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/Kernels/EdgeDetectorCompassKernel.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/Kernels/EdgeDetectorCompassKernel.cs @@ -14,8 +14,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// An edge detection kenel comprised of Kirsch gradient operators. /// . /// - public static EdgeDetectorCompassKernel Kirsch = - new EdgeDetectorCompassKernel( + public static readonly EdgeDetectorCompassKernel Kirsch = + new( KirschKernels.North, KirschKernels.NorthWest, KirschKernels.West, @@ -29,8 +29,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// An edge detection kenel comprised of Robinson gradient operators. /// /// - public static EdgeDetectorCompassKernel Robinson = - new EdgeDetectorCompassKernel( + public static readonly EdgeDetectorCompassKernel Robinson = + new( RobinsonKernels.North, RobinsonKernels.NorthWest, RobinsonKernels.West, diff --git a/src/ImageSharp/Processing/Processors/Convolution/Kernels/EdgeDetectorKernel.cs b/src/ImageSharp/Processing/Processors/Convolution/Kernels/EdgeDetectorKernel.cs index 064088432..25007846c 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/Kernels/EdgeDetectorKernel.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/Kernels/EdgeDetectorKernel.cs @@ -14,19 +14,19 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// An edge detection kernel containing a 3x3 Laplacian operator. /// /// - public static EdgeDetectorKernel Laplacian3x3 = new EdgeDetectorKernel(LaplacianKernels.Laplacian3x3); + public static readonly EdgeDetectorKernel Laplacian3x3 = new(LaplacianKernels.Laplacian3x3); /// /// An edge detection kernel containing a 5x5 Laplacian operator. /// /// - public static EdgeDetectorKernel Laplacian5x5 = new EdgeDetectorKernel(LaplacianKernels.Laplacian5x5); + public static readonly EdgeDetectorKernel Laplacian5x5 = new(LaplacianKernels.Laplacian5x5); /// /// An edge detection kernel containing a Laplacian of Gaussian operator. /// . /// - public static EdgeDetectorKernel LaplacianOfGaussian = new EdgeDetectorKernel(LaplacianKernels.LaplacianOfGaussianXY); + public static readonly EdgeDetectorKernel LaplacianOfGaussian = new(LaplacianKernels.LaplacianOfGaussianXY); /// /// Initializes a new instance of the struct. diff --git a/src/ImageSharp/Processing/Processors/Dithering/ErroDither.KnownTypes.cs b/src/ImageSharp/Processing/Processors/Dithering/ErroDither.KnownTypes.cs index 435cafb52..2c9ce2419 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/ErroDither.KnownTypes.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/ErroDither.KnownTypes.cs @@ -11,178 +11,178 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering /// /// Applies error diffusion based dithering using the Atkinson image dithering algorithm. /// - public static ErrorDither Atkinson = CreateAtkinson(); + public static readonly ErrorDither Atkinson = CreateAtkinson(); /// /// Applies error diffusion based dithering using the Burks image dithering algorithm. /// - public static ErrorDither Burkes = CreateBurks(); + public static readonly ErrorDither Burkes = CreateBurks(); /// /// Applies error diffusion based dithering using the Floyd–Steinberg image dithering algorithm. /// - public static ErrorDither FloydSteinberg = CreateFloydSteinberg(); + public static readonly ErrorDither FloydSteinberg = CreateFloydSteinberg(); /// /// Applies error diffusion based dithering using the Jarvis, Judice, Ninke image dithering algorithm. /// - public static ErrorDither JarvisJudiceNinke = CreateJarvisJudiceNinke(); + public static readonly ErrorDither JarvisJudiceNinke = CreateJarvisJudiceNinke(); /// /// Applies error diffusion based dithering using the Sierra2 image dithering algorithm. /// - public static ErrorDither Sierra2 = CreateSierra2(); + public static readonly ErrorDither Sierra2 = CreateSierra2(); /// /// Applies error diffusion based dithering using the Sierra3 image dithering algorithm. /// - public static ErrorDither Sierra3 = CreateSierra3(); + public static readonly ErrorDither Sierra3 = CreateSierra3(); /// /// Applies error diffusion based dithering using the Sierra Lite image dithering algorithm. /// - public static ErrorDither SierraLite = CreateSierraLite(); + public static readonly ErrorDither SierraLite = CreateSierraLite(); /// /// Applies error diffusion based dithering using the Stevenson-Arce image dithering algorithm. /// - public static ErrorDither StevensonArce = CreateStevensonArce(); + public static readonly ErrorDither StevensonArce = CreateStevensonArce(); /// /// Applies error diffusion based dithering using the Stucki image dithering algorithm. /// - public static ErrorDither Stucki = CreateStucki(); + public static readonly ErrorDither Stucki = CreateStucki(); private static ErrorDither CreateAtkinson() { - const float Divisor = 8F; - const int Offset = 1; + const float divisor = 8F; + const int offset = 1; - var matrix = new float[,] + float[,] matrix = { - { 0, 0, 1 / Divisor, 1 / Divisor }, - { 1 / Divisor, 1 / Divisor, 1 / Divisor, 0 }, - { 0, 1 / Divisor, 0, 0 } + { 0, 0, 1 / divisor, 1 / divisor }, + { 1 / divisor, 1 / divisor, 1 / divisor, 0 }, + { 0, 1 / divisor, 0, 0 } }; - return new ErrorDither(matrix, Offset); + return new ErrorDither(matrix, offset); } private static ErrorDither CreateBurks() { - const float Divisor = 32F; - const int Offset = 2; + const float divisor = 32F; + const int offset = 2; - var matrix = new float[,] + float[,] matrix = { - { 0, 0, 0, 8 / Divisor, 4 / Divisor }, - { 2 / Divisor, 4 / Divisor, 8 / Divisor, 4 / Divisor, 2 / Divisor } + { 0, 0, 0, 8 / divisor, 4 / divisor }, + { 2 / divisor, 4 / divisor, 8 / divisor, 4 / divisor, 2 / divisor } }; - return new ErrorDither(matrix, Offset); + return new ErrorDither(matrix, offset); } private static ErrorDither CreateFloydSteinberg() { - const float Divisor = 16F; - const int Offset = 1; + const float divisor = 16F; + const int offset = 1; - var matrix = new float[,] + float[,] matrix = { - { 0, 0, 7 / Divisor }, - { 3 / Divisor, 5 / Divisor, 1 / Divisor } + { 0, 0, 7 / divisor }, + { 3 / divisor, 5 / divisor, 1 / divisor } }; - return new ErrorDither(matrix, Offset); + return new ErrorDither(matrix, offset); } private static ErrorDither CreateJarvisJudiceNinke() { - const float Divisor = 48F; - const int Offset = 2; + const float divisor = 48F; + const int offset = 2; - var matrix = new float[,] + float[,] matrix = { - { 0, 0, 0, 7 / Divisor, 5 / Divisor }, - { 3 / Divisor, 5 / Divisor, 7 / Divisor, 5 / Divisor, 3 / Divisor }, - { 1 / Divisor, 3 / Divisor, 5 / Divisor, 3 / Divisor, 1 / Divisor } + { 0, 0, 0, 7 / divisor, 5 / divisor }, + { 3 / divisor, 5 / divisor, 7 / divisor, 5 / divisor, 3 / divisor }, + { 1 / divisor, 3 / divisor, 5 / divisor, 3 / divisor, 1 / divisor } }; - return new ErrorDither(matrix, Offset); + return new ErrorDither(matrix, offset); } private static ErrorDither CreateSierra2() { - const float Divisor = 16F; - const int Offset = 2; + const float divisor = 16F; + const int offset = 2; - var matrix = new float[,] + float[,] matrix = { - { 0, 0, 0, 4 / Divisor, 3 / Divisor }, - { 1 / Divisor, 2 / Divisor, 3 / Divisor, 2 / Divisor, 1 / Divisor } + { 0, 0, 0, 4 / divisor, 3 / divisor }, + { 1 / divisor, 2 / divisor, 3 / divisor, 2 / divisor, 1 / divisor } }; - return new ErrorDither(matrix, Offset); + return new ErrorDither(matrix, offset); } private static ErrorDither CreateSierra3() { - const float Divisor = 32F; - const int Offset = 2; + const float divisor = 32F; + const int offset = 2; - var matrix = new float[,] + float[,] matrix = { - { 0, 0, 0, 5 / Divisor, 3 / Divisor }, - { 2 / Divisor, 4 / Divisor, 5 / Divisor, 4 / Divisor, 2 / Divisor }, - { 0, 2 / Divisor, 3 / Divisor, 2 / Divisor, 0 } + { 0, 0, 0, 5 / divisor, 3 / divisor }, + { 2 / divisor, 4 / divisor, 5 / divisor, 4 / divisor, 2 / divisor }, + { 0, 2 / divisor, 3 / divisor, 2 / divisor, 0 } }; - return new ErrorDither(matrix, Offset); + return new ErrorDither(matrix, offset); } private static ErrorDither CreateSierraLite() { - const float Divisor = 4F; - const int Offset = 1; + const float divisor = 4F; + const int offset = 1; - var matrix = new float[,] + float[,] matrix = { - { 0, 0, 2 / Divisor }, - { 1 / Divisor, 1 / Divisor, 0 } + { 0, 0, 2 / divisor }, + { 1 / divisor, 1 / divisor, 0 } }; - return new ErrorDither(matrix, Offset); + return new ErrorDither(matrix, offset); } private static ErrorDither CreateStevensonArce() { - const float Divisor = 200F; - const int Offset = 3; + const float divisor = 200F; + const int offset = 3; - var matrix = new float[,] + float[,] matrix = { - { 0, 0, 0, 0, 0, 32 / Divisor, 0 }, - { 12 / Divisor, 0, 26 / Divisor, 0, 30 / Divisor, 0, 16 / Divisor }, - { 0, 12 / Divisor, 0, 26 / Divisor, 0, 12 / Divisor, 0 }, - { 5 / Divisor, 0, 12 / Divisor, 0, 12 / Divisor, 0, 5 / Divisor } + { 0, 0, 0, 0, 0, 32 / divisor, 0 }, + { 12 / divisor, 0, 26 / divisor, 0, 30 / divisor, 0, 16 / divisor }, + { 0, 12 / divisor, 0, 26 / divisor, 0, 12 / divisor, 0 }, + { 5 / divisor, 0, 12 / divisor, 0, 12 / divisor, 0, 5 / divisor } }; - return new ErrorDither(matrix, Offset); + return new ErrorDither(matrix, offset); } private static ErrorDither CreateStucki() { - const float Divisor = 42F; - const int Offset = 2; + const float divisor = 42F; + const int offset = 2; - var matrix = new float[,] + float[,] matrix = { - { 0, 0, 0, 8 / Divisor, 4 / Divisor }, - { 2 / Divisor, 4 / Divisor, 8 / Divisor, 4 / Divisor, 2 / Divisor }, - { 1 / Divisor, 2 / Divisor, 4 / Divisor, 2 / Divisor, 1 / Divisor } + { 0, 0, 0, 8 / divisor, 4 / divisor }, + { 2 / divisor, 4 / divisor, 8 / divisor, 4 / divisor, 2 / divisor }, + { 1 / divisor, 2 / divisor, 4 / divisor, 2 / divisor, 1 / divisor } }; - return new ErrorDither(matrix, Offset); + return new ErrorDither(matrix, offset); } } } diff --git a/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.KnownTypes.cs b/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.KnownTypes.cs index a6838d246..f036273c2 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.KnownTypes.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.KnownTypes.cs @@ -11,26 +11,26 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering /// /// Applies order dithering using the 2x2 Bayer dithering matrix. /// - public static OrderedDither Bayer2x2 = new OrderedDither(2); + public static readonly OrderedDither Bayer2x2 = new(2); /// /// Applies order dithering using the 4x4 Bayer dithering matrix. /// - public static OrderedDither Bayer4x4 = new OrderedDither(4); + public static readonly OrderedDither Bayer4x4 = new(4); /// /// Applies order dithering using the 8x8 Bayer dithering matrix. /// - public static OrderedDither Bayer8x8 = new OrderedDither(8); + public static readonly OrderedDither Bayer8x8 = new(8); /// /// Applies order dithering using the 16x16 Bayer dithering matrix. /// - public static OrderedDither Bayer16x16 = new OrderedDither(16); + public static readonly OrderedDither Bayer16x16 = new(16); /// /// Applies order dithering using the 3x3 ordered dithering matrix. /// - public static OrderedDither Ordered3x3 = new OrderedDither(3); + public static readonly OrderedDither Ordered3x3 = new(3); } } diff --git a/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor{TPixel}.cs index 248c21641..4933b9f75 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor{TPixel}.cs @@ -3,6 +3,7 @@ using System; using System.Buffers; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Quantization; @@ -35,7 +36,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering ReadOnlySpan sourcePalette = definition.Palette.Span; this.paletteOwner = this.Configuration.MemoryAllocator.Allocate(sourcePalette.Length); - Color.ToPixel(this.Configuration, sourcePalette, this.paletteOwner.Memory.Span); + Color.ToPixel(sourcePalette, this.paletteOwner.Memory.Span); this.ditherProcessor = new DitherProcessor( this.Configuration, @@ -46,7 +47,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering /// protected override void OnFrameApply(ImageFrame source) { - var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds()); + Rectangle interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds()); this.dither.ApplyPaletteDither(in this.ditherProcessor, source, interest); } @@ -74,6 +75,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering /// . /// /// Internal for AOT + [SuppressMessage( + "Design", + "CA1001:Types that own disposable fields should be disposable", + Justification = "https://github.com/dotnet/roslyn-analyzers/issues/6151")] internal readonly struct DitherProcessor : IPaletteDitherImageProcessor, IDisposable { private readonly EuclideanPixelMap pixelMap; diff --git a/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor{TPixel}.cs index cf56d0338..4d33b848b 100644 --- a/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor{TPixel}.cs @@ -30,24 +30,18 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects /// The source area to process for the current processor instance. public OilPaintingProcessor(Configuration configuration, OilPaintingProcessor definition, Image source, Rectangle sourceRectangle) : base(configuration, source, sourceRectangle) - { - this.definition = definition; - } + => this.definition = definition; /// protected override void OnFrameApply(ImageFrame source) { - int brushSize = this.definition.BrushSize; - if (brushSize <= 0 || brushSize > source.Height || brushSize > source.Width) - { - throw new ArgumentOutOfRangeException(nameof(brushSize)); - } + int brushSize = Math.Clamp(this.definition.BrushSize, 1, Math.Min(source.Width, source.Height)); using Buffer2D targetPixels = this.Configuration.MemoryAllocator.Allocate2D(source.Size()); source.CopyTo(targetPixels); - var operation = new RowIntervalOperation(this.SourceRectangle, targetPixels, source.PixelBuffer, this.Configuration, brushSize >> 1, this.definition.Levels); + RowIntervalOperation operation = new(this.SourceRectangle, targetPixels, source.PixelBuffer, this.Configuration, brushSize >> 1, this.definition.Levels); ParallelRowIterator.IterateRowIntervals( this.Configuration, this.SourceRectangle, @@ -147,7 +141,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects int offsetX = x + fxr; offsetX = Numerics.Clamp(offsetX, 0, maxX); - var vector = sourceOffsetRow[offsetX].ToVector4(); + Vector4 vector = sourceOffsetRow[offsetX].ToVector4(); float sourceRed = vector.X; float sourceBlue = vector.Z; diff --git a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationProcessor{TPixel}.cs index d6d69f161..518b19c4c 100644 --- a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationProcessor{TPixel}.cs @@ -628,7 +628,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization this.processor.ClipHistogram(histogram, this.processor.ClipLimit); } - cdfMinSpan[cdfX] += this.processor.CalculateCdf(ref cdfBase, ref histogramBase, histogram.Length - 1); + cdfMinSpan[cdfX] += CalculateCdf(ref cdfBase, ref histogramBase, histogram.Length - 1); cdfX++; } diff --git a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationSlidingWindowProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationSlidingWindowProcessor{TPixel}.cs index a2f346be0..b7e5819e0 100644 --- a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationSlidingWindowProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationSlidingWindowProcessor{TPixel}.cs @@ -7,7 +7,6 @@ using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading.Tasks; -using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; @@ -57,20 +56,21 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization { MemoryAllocator memoryAllocator = this.Configuration.MemoryAllocator; - var parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = this.Configuration.MaxDegreeOfParallelism }; + ParallelOptions parallelOptions = new() + { MaxDegreeOfParallelism = this.Configuration.MaxDegreeOfParallelism }; int tileWidth = source.Width / this.Tiles; int tileHeight = tileWidth; int pixelInTile = tileWidth * tileHeight; int halfTileHeight = tileHeight / 2; int halfTileWidth = halfTileHeight; - var slidingWindowInfos = new SlidingWindowInfos(tileWidth, tileHeight, halfTileWidth, halfTileHeight, pixelInTile); + SlidingWindowInfos slidingWindowInfos = new(tileWidth, tileHeight, halfTileWidth, halfTileHeight, pixelInTile); // TODO: If the process was able to be switched to operate in parallel rows instead of columns // then we could take advantage of batching and allocate per-row buffers only once per batch. using Buffer2D targetPixels = this.Configuration.MemoryAllocator.Allocate2D(source.Width, source.Height); // Process the inner tiles, which do not require to check the borders. - var innerOperation = new SlidingWindowOperation( + SlidingWindowOperation innerOperation = new( this.Configuration, this, source, @@ -88,7 +88,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization innerOperation.Invoke); // Process the left border of the image. - var leftBorderOperation = new SlidingWindowOperation( + SlidingWindowOperation leftBorderOperation = new( this.Configuration, this, source, @@ -106,7 +106,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization leftBorderOperation.Invoke); // Process the right border of the image. - var rightBorderOperation = new SlidingWindowOperation( + SlidingWindowOperation rightBorderOperation = new( this.Configuration, this, source, @@ -124,7 +124,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization rightBorderOperation.Invoke); // Process the top border of the image. - var topBorderOperation = new SlidingWindowOperation( + SlidingWindowOperation topBorderOperation = new( this.Configuration, this, source, @@ -142,7 +142,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization topBorderOperation.Invoke); // Process the bottom border of the image. - var bottomBorderOperation = new SlidingWindowOperation( + SlidingWindowOperation bottomBorderOperation = new( this.Configuration, this, source, @@ -171,7 +171,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization /// The y position. /// The width in pixels of a tile. /// The configuration. - private void CopyPixelRow( + private static void CopyPixelRow( ImageFrame source, Span rowPixels, int x, @@ -224,7 +224,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization return; } - this.CopyPixelRowFast(source.PixelBuffer, rowPixels, x, y, tileWidth, configuration); + CopyPixelRowFast(source.PixelBuffer, rowPixels, x, y, tileWidth, configuration); } /// @@ -237,7 +237,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization /// The width in pixels of a tile. /// The configuration. [MethodImpl(InliningOptions.ShortMethod)] - private void CopyPixelRowFast( + private static void CopyPixelRowFast( Buffer2D source, Span rowPixels, int x, @@ -254,7 +254,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization /// The number of different luminance levels. /// The grey values span length. [MethodImpl(InliningOptions.ShortMethod)] - private void AddPixelsToHistogram(ref Vector4 greyValuesBase, ref int histogramBase, int luminanceLevels, int length) + private static void AddPixelsToHistogram(ref Vector4 greyValuesBase, ref int histogramBase, int luminanceLevels, int length) { for (nint idx = 0; idx < length; idx++) { @@ -271,7 +271,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization /// The number of different luminance levels. /// The grey values span length. [MethodImpl(InliningOptions.ShortMethod)] - private void RemovePixelsFromHistogram(ref Vector4 greyValuesBase, ref int histogramBase, int luminanceLevels, int length) + private static void RemovePixelsFromHistogram(ref Vector4 greyValuesBase, ref int histogramBase, int luminanceLevels, int length) { for (int idx = 0; idx < length; idx++) { @@ -356,14 +356,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization { if (this.useFastPath) { - this.processor.CopyPixelRowFast(this.source.PixelBuffer, pixelRow, x - this.swInfos.HalfTileWidth, dy, this.swInfos.TileWidth, this.configuration); + CopyPixelRowFast(this.source.PixelBuffer, pixelRow, x - this.swInfos.HalfTileWidth, dy, this.swInfos.TileWidth, this.configuration); } else { - this.processor.CopyPixelRow(this.source, pixelRow, x - this.swInfos.HalfTileWidth, dy, this.swInfos.TileWidth, this.configuration); + CopyPixelRow(this.source, pixelRow, x - this.swInfos.HalfTileWidth, dy, this.swInfos.TileWidth, this.configuration); } - this.processor.AddPixelsToHistogram(ref pixelRowBase, ref histogramBase, this.processor.LuminanceLevels, pixelRow.Length); + AddPixelsToHistogram(ref pixelRowBase, ref histogramBase, this.processor.LuminanceLevels, pixelRow.Length); } for (int y = this.yStart; y < this.yEnd; y++) @@ -377,8 +377,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization // Calculate the cumulative distribution function, which will map each input pixel in the current tile to a new value. int cdfMin = this.processor.ClipHistogramEnabled - ? this.processor.CalculateCdf(ref cdfBase, ref histogramCopyBase, histogram.Length - 1) - : this.processor.CalculateCdf(ref cdfBase, ref histogramBase, histogram.Length - 1); + ? CalculateCdf(ref cdfBase, ref histogramCopyBase, histogram.Length - 1) + : CalculateCdf(ref cdfBase, ref histogramBase, histogram.Length - 1); float numberOfPixelsMinusCdfMin = this.swInfos.PixelInTile - cdfMin; @@ -390,26 +390,26 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization // Remove top most row from the histogram, mirroring rows which exceeds the borders. if (this.useFastPath) { - this.processor.CopyPixelRowFast(this.source.PixelBuffer, pixelRow, x - this.swInfos.HalfTileWidth, y - this.swInfos.HalfTileWidth, this.swInfos.TileWidth, this.configuration); + CopyPixelRowFast(this.source.PixelBuffer, pixelRow, x - this.swInfos.HalfTileWidth, y - this.swInfos.HalfTileWidth, this.swInfos.TileWidth, this.configuration); } else { - this.processor.CopyPixelRow(this.source, pixelRow, x - this.swInfos.HalfTileWidth, y - this.swInfos.HalfTileWidth, this.swInfos.TileWidth, this.configuration); + CopyPixelRow(this.source, pixelRow, x - this.swInfos.HalfTileWidth, y - this.swInfos.HalfTileWidth, this.swInfos.TileWidth, this.configuration); } - this.processor.RemovePixelsFromHistogram(ref pixelRowBase, ref histogramBase, this.processor.LuminanceLevels, pixelRow.Length); + RemovePixelsFromHistogram(ref pixelRowBase, ref histogramBase, this.processor.LuminanceLevels, pixelRow.Length); // Add new bottom row to the histogram, mirroring rows which exceeds the borders. if (this.useFastPath) { - this.processor.CopyPixelRowFast(this.source.PixelBuffer, pixelRow, x - this.swInfos.HalfTileWidth, y + this.swInfos.HalfTileWidth, this.swInfos.TileWidth, this.configuration); + CopyPixelRowFast(this.source.PixelBuffer, pixelRow, x - this.swInfos.HalfTileWidth, y + this.swInfos.HalfTileWidth, this.swInfos.TileWidth, this.configuration); } else { - this.processor.CopyPixelRow(this.source, pixelRow, x - this.swInfos.HalfTileWidth, y + this.swInfos.HalfTileWidth, this.swInfos.TileWidth, this.configuration); + CopyPixelRow(this.source, pixelRow, x - this.swInfos.HalfTileWidth, y + this.swInfos.HalfTileWidth, this.swInfos.TileWidth, this.configuration); } - this.processor.AddPixelsToHistogram(ref pixelRowBase, ref histogramBase, this.processor.LuminanceLevels, pixelRow.Length); + AddPixelsToHistogram(ref pixelRowBase, ref histogramBase, this.processor.LuminanceLevels, pixelRow.Length); } } } diff --git a/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs index c27118be4..c4b925efe 100644 --- a/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs @@ -68,7 +68,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization using IMemoryOwner cdfBuffer = memoryAllocator.Allocate(this.LuminanceLevels, AllocationOptions.Clean); // Calculate the cumulative distribution function, which will map each input pixel to a new value. - int cdfMin = this.CalculateCdf( + int cdfMin = CalculateCdf( ref MemoryMarshal.GetReference(cdfBuffer.GetSpan()), ref MemoryMarshal.GetReference(histogram), histogram.Length - 1); diff --git a/src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationOptions.cs b/src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationOptions.cs index 71fbc6e5b..0e9bfa7e4 100644 --- a/src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationOptions.cs +++ b/src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationOptions.cs @@ -25,7 +25,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization /// It is recommended to use clipping when the AdaptiveTileInterpolation method is used, to suppress artifacts which can occur on the borders of the tiles. /// Defaults to false. /// - public bool ClipHistogram { get; set; } = false; + public bool ClipHistogram { get; set; } /// /// Gets or sets the histogram clip limit. Adaptive histogram equalization may cause noise to be amplified in near constant diff --git a/src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationProcessor{TPixel}.cs index 4c32c5fd9..021379907 100644 --- a/src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationProcessor{TPixel}.cs @@ -2,6 +2,7 @@ // Licensed under the Six Labors Split License. using System; +using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using SixLabors.ImageSharp.PixelFormats; @@ -67,7 +68,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization /// The reference to the histogram of the input image. /// Index of the maximum of the histogram. /// The first none zero value of the cdf. - public int CalculateCdf(ref int cdfBase, ref int histogramBase, int maxIdx) + public static int CalculateCdf(ref int cdfBase, ref int histogramBase, int maxIdx) { int histSum = 0; int cdfMin = 0; @@ -142,7 +143,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization public static int GetLuminance(TPixel sourcePixel, int luminanceLevels) { // TODO: We need a bulk per span equivalent. - var vector = sourcePixel.ToVector4(); + Vector4 vector = sourcePixel.ToVector4(); return ColorNumerics.GetBT709Luminance(ref vector, luminanceLevels); } } diff --git a/src/ImageSharp/Processing/Processors/Quantization/EuclideanPixelMap{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/EuclideanPixelMap{TPixel}.cs index 981e1cf60..d06661d07 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/EuclideanPixelMap{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/EuclideanPixelMap{TPixel}.cs @@ -23,7 +23,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization { private Rgba32[] rgbaPalette; - // Do not make this readonly! Struct value would be always copied on non-readonly method calls. + /// + /// Do not make this readonly! Struct value would be always copied on non-readonly method calls. + /// private ColorDistanceCache cache; private readonly Configuration configuration; diff --git a/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer{TPixel}.cs index a066bfdc4..b3aa58acf 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer{TPixel}.cs @@ -3,6 +3,7 @@ using System; using System.Buffers; +using System.Diagnostics.CodeAnalysis; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -16,6 +17,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// /// /// The pixel format. + [SuppressMessage( + "Design", + "CA1001:Types that own disposable fields should be disposable", + Justification = "https://github.com/dotnet/roslyn-analyzers/issues/6151")] public struct OctreeQuantizer : IQuantizer where TPixel : unmanaged, IPixel { @@ -48,7 +53,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization this.paletteOwner = configuration.MemoryAllocator.Allocate(this.maxColors, AllocationOptions.Clean); this.pixelMap = default; this.palette = default; - this.isDithering = !(this.Options.Dither is null); + this.isDithering = this.Options.Dither is not null; this.isDisposed = false; } @@ -473,7 +478,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization if (this.leaf) { // Set the color of the palette entry - var vector = Vector3.Clamp( + Vector3 vector = Vector3.Clamp( new Vector3(this.red, this.green, this.blue) / this.pixelCount, Vector3.Zero, new Vector3(255)); diff --git a/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer.cs b/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer.cs index ab0f1548f..cc4b4a33f 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer.cs @@ -54,9 +54,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization // since the palette is unchanging. This allows a reduction of memory usage across // multi frame gifs using a global palette. int length = Math.Min(this.colorPalette.Length, options.MaxColors); - var palette = new TPixel[length]; + TPixel[] palette = new TPixel[length]; - Color.ToPixel(configuration, this.colorPalette.Span, palette.AsSpan()); + Color.ToPixel(this.colorPalette.Span, palette.AsSpan()); return new PaletteQuantizer(configuration, options, palette); } } diff --git a/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer{TPixel}.cs index 5196070e4..1fcdbc5b1 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer{TPixel}.cs @@ -2,6 +2,7 @@ // Licensed under the Six Labors Split License. using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; @@ -13,6 +14,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// /// /// The pixel format. + [SuppressMessage( + "Design", + "CA1001:Types that own disposable fields should be disposable", + Justification = "https://github.com/dotnet/roslyn-analyzers/issues/6151")] internal struct PaletteQuantizer : IQuantizer where TPixel : unmanaged, IPixel { diff --git a/src/ImageSharp/Processing/Processors/Quantization/WuQuantizer{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/WuQuantizer{TPixel}.cs index 39c753722..5f04669b7 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/WuQuantizer{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/WuQuantizer{TPixel}.cs @@ -3,6 +3,7 @@ using System; using System.Buffers; +using System.Diagnostics.CodeAnalysis; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -31,6 +32,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// /// /// The pixel format. + [SuppressMessage( + "Design", + "CA1001:Types that own disposable fields should be disposable", + Justification = "https://github.com/dotnet/roslyn-analyzers/issues/6151")] internal struct WuQuantizer : IQuantizer where TPixel : unmanaged, IPixel { @@ -97,7 +102,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization this.isDisposed = false; this.pixelMap = default; this.palette = default; - this.isDithering = this.isDithering = !(this.Options.Dither is null); + this.isDithering = this.isDithering = this.Options.Dither is not null; } /// @@ -256,58 +261,51 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// The direction. /// The moment. /// The result. + /// Invalid direction. private static Moment Bottom(ref Box cube, int direction, ReadOnlySpan moments) - { - switch (direction) + => direction switch { // Red - case 3: - return -moments[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMax, cube.AMax)] - + moments[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMax, cube.AMin)] - + moments[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMin, cube.AMax)] - - moments[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMin, cube.AMin)] - + moments[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMax, cube.AMax)] - - moments[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMax, cube.AMin)] - - moments[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMin, cube.AMax)] - + moments[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMin, cube.AMin)]; + 3 => -moments[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMax, cube.AMax)] + + moments[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMax, cube.AMin)] + + moments[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMin, cube.AMax)] + - moments[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMin, cube.AMin)] + + moments[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMax, cube.AMax)] + - moments[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMax, cube.AMin)] + - moments[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMin, cube.AMax)] + + moments[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMin, cube.AMin)], // Green - case 2: - return -moments[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMax, cube.AMax)] - + moments[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMax, cube.AMin)] - + moments[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMin, cube.AMax)] - - moments[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMin, cube.AMin)] - + moments[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMax, cube.AMax)] - - moments[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMax, cube.AMin)] - - moments[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMin, cube.AMax)] - + moments[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMin, cube.AMin)]; + 2 => -moments[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMax, cube.AMax)] + + moments[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMax, cube.AMin)] + + moments[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMin, cube.AMax)] + - moments[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMin, cube.AMin)] + + moments[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMax, cube.AMax)] + - moments[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMax, cube.AMin)] + - moments[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMin, cube.AMax)] + + moments[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMin, cube.AMin)], // Blue - case 1: - return -moments[GetPaletteIndex(cube.RMax, cube.GMax, cube.BMin, cube.AMax)] - + moments[GetPaletteIndex(cube.RMax, cube.GMax, cube.BMin, cube.AMin)] - + moments[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMin, cube.AMax)] - - moments[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMin, cube.AMin)] - + moments[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMin, cube.AMax)] - - moments[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMin, cube.AMin)] - - moments[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMin, cube.AMax)] - + moments[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMin, cube.AMin)]; + 1 => -moments[GetPaletteIndex(cube.RMax, cube.GMax, cube.BMin, cube.AMax)] + + moments[GetPaletteIndex(cube.RMax, cube.GMax, cube.BMin, cube.AMin)] + + moments[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMin, cube.AMax)] + - moments[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMin, cube.AMin)] + + moments[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMin, cube.AMax)] + - moments[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMin, cube.AMin)] + - moments[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMin, cube.AMax)] + + moments[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMin, cube.AMin)], // Alpha - case 0: - return -moments[GetPaletteIndex(cube.RMax, cube.GMax, cube.BMax, cube.AMin)] - + moments[GetPaletteIndex(cube.RMax, cube.GMax, cube.BMin, cube.AMin)] - + moments[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMax, cube.AMin)] - - moments[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMin, cube.AMin)] - + moments[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMax, cube.AMin)] - - moments[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMin, cube.AMin)] - - moments[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMax, cube.AMin)] - + moments[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMin, cube.AMin)]; - - default: - throw new ArgumentOutOfRangeException(nameof(direction)); - } - } + 0 => -moments[GetPaletteIndex(cube.RMax, cube.GMax, cube.BMax, cube.AMin)] + + moments[GetPaletteIndex(cube.RMax, cube.GMax, cube.BMin, cube.AMin)] + + moments[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMax, cube.AMin)] + - moments[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMin, cube.AMin)] + + moments[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMax, cube.AMin)] + - moments[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMin, cube.AMin)] + - moments[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMax, cube.AMin)] + + moments[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMin, cube.AMin)], + _ => throw new ArgumentOutOfRangeException(nameof(direction)), + }; /// /// Computes remainder of Volume(cube, moment), substituting position for RMax, GMax, BMax, or AMax (depending on direction). @@ -317,58 +315,51 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// The position. /// The moment. /// The result. + /// Invalid direction. private static Moment Top(ref Box cube, int direction, int position, ReadOnlySpan moments) - { - switch (direction) + => direction switch { // Red - case 3: - return moments[GetPaletteIndex(position, cube.GMax, cube.BMax, cube.AMax)] - - moments[GetPaletteIndex(position, cube.GMax, cube.BMax, cube.AMin)] - - moments[GetPaletteIndex(position, cube.GMax, cube.BMin, cube.AMax)] - + moments[GetPaletteIndex(position, cube.GMax, cube.BMin, cube.AMin)] - - moments[GetPaletteIndex(position, cube.GMin, cube.BMax, cube.AMax)] - + moments[GetPaletteIndex(position, cube.GMin, cube.BMax, cube.AMin)] - + moments[GetPaletteIndex(position, cube.GMin, cube.BMin, cube.AMax)] - - moments[GetPaletteIndex(position, cube.GMin, cube.BMin, cube.AMin)]; + 3 => moments[GetPaletteIndex(position, cube.GMax, cube.BMax, cube.AMax)] + - moments[GetPaletteIndex(position, cube.GMax, cube.BMax, cube.AMin)] + - moments[GetPaletteIndex(position, cube.GMax, cube.BMin, cube.AMax)] + + moments[GetPaletteIndex(position, cube.GMax, cube.BMin, cube.AMin)] + - moments[GetPaletteIndex(position, cube.GMin, cube.BMax, cube.AMax)] + + moments[GetPaletteIndex(position, cube.GMin, cube.BMax, cube.AMin)] + + moments[GetPaletteIndex(position, cube.GMin, cube.BMin, cube.AMax)] + - moments[GetPaletteIndex(position, cube.GMin, cube.BMin, cube.AMin)], // Green - case 2: - return moments[GetPaletteIndex(cube.RMax, position, cube.BMax, cube.AMax)] - - moments[GetPaletteIndex(cube.RMax, position, cube.BMax, cube.AMin)] - - moments[GetPaletteIndex(cube.RMax, position, cube.BMin, cube.AMax)] - + moments[GetPaletteIndex(cube.RMax, position, cube.BMin, cube.AMin)] - - moments[GetPaletteIndex(cube.RMin, position, cube.BMax, cube.AMax)] - + moments[GetPaletteIndex(cube.RMin, position, cube.BMax, cube.AMin)] - + moments[GetPaletteIndex(cube.RMin, position, cube.BMin, cube.AMax)] - - moments[GetPaletteIndex(cube.RMin, position, cube.BMin, cube.AMin)]; + 2 => moments[GetPaletteIndex(cube.RMax, position, cube.BMax, cube.AMax)] + - moments[GetPaletteIndex(cube.RMax, position, cube.BMax, cube.AMin)] + - moments[GetPaletteIndex(cube.RMax, position, cube.BMin, cube.AMax)] + + moments[GetPaletteIndex(cube.RMax, position, cube.BMin, cube.AMin)] + - moments[GetPaletteIndex(cube.RMin, position, cube.BMax, cube.AMax)] + + moments[GetPaletteIndex(cube.RMin, position, cube.BMax, cube.AMin)] + + moments[GetPaletteIndex(cube.RMin, position, cube.BMin, cube.AMax)] + - moments[GetPaletteIndex(cube.RMin, position, cube.BMin, cube.AMin)], // Blue - case 1: - return moments[GetPaletteIndex(cube.RMax, cube.GMax, position, cube.AMax)] - - moments[GetPaletteIndex(cube.RMax, cube.GMax, position, cube.AMin)] - - moments[GetPaletteIndex(cube.RMax, cube.GMin, position, cube.AMax)] - + moments[GetPaletteIndex(cube.RMax, cube.GMin, position, cube.AMin)] - - moments[GetPaletteIndex(cube.RMin, cube.GMax, position, cube.AMax)] - + moments[GetPaletteIndex(cube.RMin, cube.GMax, position, cube.AMin)] - + moments[GetPaletteIndex(cube.RMin, cube.GMin, position, cube.AMax)] - - moments[GetPaletteIndex(cube.RMin, cube.GMin, position, cube.AMin)]; + 1 => moments[GetPaletteIndex(cube.RMax, cube.GMax, position, cube.AMax)] + - moments[GetPaletteIndex(cube.RMax, cube.GMax, position, cube.AMin)] + - moments[GetPaletteIndex(cube.RMax, cube.GMin, position, cube.AMax)] + + moments[GetPaletteIndex(cube.RMax, cube.GMin, position, cube.AMin)] + - moments[GetPaletteIndex(cube.RMin, cube.GMax, position, cube.AMax)] + + moments[GetPaletteIndex(cube.RMin, cube.GMax, position, cube.AMin)] + + moments[GetPaletteIndex(cube.RMin, cube.GMin, position, cube.AMax)] + - moments[GetPaletteIndex(cube.RMin, cube.GMin, position, cube.AMin)], // Alpha - case 0: - return moments[GetPaletteIndex(cube.RMax, cube.GMax, cube.BMax, position)] - - moments[GetPaletteIndex(cube.RMax, cube.GMax, cube.BMin, position)] - - moments[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMax, position)] - + moments[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMin, position)] - - moments[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMax, position)] - + moments[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMin, position)] - + moments[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMax, position)] - - moments[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMin, position)]; - - default: - throw new ArgumentOutOfRangeException(nameof(direction)); - } - } + 0 => moments[GetPaletteIndex(cube.RMax, cube.GMax, cube.BMax, position)] + - moments[GetPaletteIndex(cube.RMax, cube.GMax, cube.BMin, position)] + - moments[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMax, position)] + + moments[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMin, position)] + - moments[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMax, position)] + + moments[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMin, position)] + + moments[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMax, position)] + - moments[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMin, position)], + _ => throw new ArgumentOutOfRangeException(nameof(direction)), + }; /// /// Builds a 3-D color histogram of counts, r/g/b, c^2. @@ -498,7 +489,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization - momentSpan[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMin, cube.AMax)] + momentSpan[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMin, cube.AMin)]; - var vector = new Vector4(volume.R, volume.G, volume.B, volume.A); + Vector4 vector = new(volume.R, volume.G, volume.B, volume.A); return variance.Moment2 - (Vector4.Dot(vector, vector) / volume.Weight); } @@ -533,7 +524,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization continue; } - var vector = new Vector4(half.R, half.G, half.B, half.A); + Vector4 vector = new(half.R, half.G, half.B, half.A); float temp = Vector4.Dot(vector, vector) / half.Weight; half = whole - half; @@ -816,7 +807,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization x.A += y.A; x.Weight++; - var vector = new Vector4(y.R, y.G, y.B, y.A); + Vector4 vector = new(y.R, y.G, y.B, y.A); x.Moment2 += Vector4.Dot(vector, vector); return x; diff --git a/src/ImageSharp/Processing/Processors/Transforms/Linear/FlipProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/Linear/FlipProcessor{TPixel}.cs index 7dc8b7365..3f4e18b8c 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Linear/FlipProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Linear/FlipProcessor{TPixel}.cs @@ -27,10 +27,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// The source for the current processor instance. /// The source area to process for the current processor instance. public FlipProcessor(Configuration configuration, FlipProcessor definition, Image source, Rectangle sourceRectangle) - : base(configuration, source, sourceRectangle) - { - this.definition = definition; - } + : base(configuration, source, sourceRectangle) => this.definition = definition; /// protected override void OnFrameApply(ImageFrame source) @@ -39,10 +36,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms { // No default needed as we have already set the pixels. case FlipMode.Vertical: - this.FlipX(source.PixelBuffer, this.Configuration); + FlipX(source.PixelBuffer, this.Configuration); break; case FlipMode.Horizontal: - this.FlipY(source, this.Configuration); + FlipY(source, this.Configuration); break; } } @@ -52,7 +49,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// /// The source image to apply the process to. /// The configuration. - private void FlipX(Buffer2D source, Configuration configuration) + private static void FlipX(Buffer2D source, Configuration configuration) { int height = source.Height; using IMemoryOwner tempBuffer = configuration.MemoryAllocator.Allocate(source.Width); @@ -74,7 +71,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// /// The source image to apply the process to. /// The configuration. - private void FlipY(ImageFrame source, Configuration configuration) + private static void FlipY(ImageFrame source, Configuration configuration) { var operation = new RowOperation(source.PixelBuffer); ParallelRowIterator.IterateRows( diff --git a/src/ImageSharp/Processing/Processors/Transforms/Linear/RotateProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/Linear/RotateProcessor{TPixel}.cs index 8e26675d8..8f6ba2896 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Linear/RotateProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Linear/RotateProcessor{TPixel}.cs @@ -104,19 +104,19 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms if (MathF.Abs(degrees - 90) < Constants.Epsilon) { - this.Rotate90(source, destination, configuration); + Rotate90(source, destination, configuration); return true; } if (MathF.Abs(degrees - 180) < Constants.Epsilon) { - this.Rotate180(source, destination, configuration); + Rotate180(source, destination, configuration); return true; } if (MathF.Abs(degrees - 270) < Constants.Epsilon) { - this.Rotate270(source, destination, configuration); + Rotate270(source, destination, configuration); return true; } @@ -129,7 +129,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// The source image. /// The destination image. /// The configuration. - private void Rotate180(ImageFrame source, ImageFrame destination, Configuration configuration) + private static void Rotate180(ImageFrame source, ImageFrame destination, Configuration configuration) { var operation = new Rotate180RowOperation(source.Width, source.Height, source.PixelBuffer, destination.PixelBuffer); ParallelRowIterator.IterateRows( @@ -144,7 +144,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// The source image. /// The destination image. /// The configuration. - private void Rotate270(ImageFrame source, ImageFrame destination, Configuration configuration) + private static void Rotate270(ImageFrame source, ImageFrame destination, Configuration configuration) { var operation = new Rotate270RowIntervalOperation(destination.Bounds(), source.Width, source.Height, source.PixelBuffer, destination.PixelBuffer); ParallelRowIterator.IterateRowIntervals( @@ -159,7 +159,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// The source image. /// The destination image. /// The configuration. - private void Rotate90(ImageFrame source, ImageFrame destination, Configuration configuration) + private static void Rotate90(ImageFrame source, ImageFrame destination, Configuration configuration) { var operation = new Rotate90RowOperation(destination.Bounds(), source.Width, source.Height, source.PixelBuffer, destination.PixelBuffer); ParallelRowIterator.IterateRows( diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/CubicResampler.cs b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/CubicResampler.cs index 4a87c1ea9..53dfb466f 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/CubicResampler.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/CubicResampler.cs @@ -23,31 +23,31 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// This filter produces a reasonably sharp edge, but without a the pronounced gradient change on large /// scale image enlargements that a 'Lagrange' filter can produce. /// - public static CubicResampler CatmullRom = new CubicResampler(2, 0, .5F); + public static readonly CubicResampler CatmullRom = new(2, 0, .5F); /// /// The Hermite filter is type of smoothed triangular interpolation Filter, /// This filter rounds off strong edges while preserving flat 'color levels' in the original image. /// - public static CubicResampler Hermite = new CubicResampler(2, 0, 0); + public static readonly CubicResampler Hermite = new(2, 0, 0); /// /// The function implements the Mitchell-Netravali algorithm as described on /// Wikipedia /// - public static CubicResampler MitchellNetravali = new CubicResampler(2, .3333333F, .3333333F); + public static readonly CubicResampler MitchellNetravali = new(2, .3333333F, .3333333F); /// /// The function implements the Robidoux algorithm. /// /// - public static CubicResampler Robidoux = new CubicResampler(2, .37821575509399867F, .31089212245300067F); + public static readonly CubicResampler Robidoux = new(2, .37821575509399867F, .31089212245300067F); /// /// The function implements the Robidoux Sharp algorithm. /// /// - public static CubicResampler RobidouxSharp = new CubicResampler(2, .2620145123990142F, .3689927438004929F); + public static readonly CubicResampler RobidouxSharp = new(2, .2620145123990142F, .3689927438004929F); /// /// The function implements the spline algorithm. @@ -57,7 +57,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// The function implements the Robidoux Sharp algorithm. /// /// - public static CubicResampler Spline = new CubicResampler(2, 1, 0); + public static readonly CubicResampler Spline = new(2, 1, 0); /// /// Initializes a new instance of the struct. diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/LanczosResampler.cs b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/LanczosResampler.cs index 23d8efa62..30bc5b5de 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/LanczosResampler.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/LanczosResampler.cs @@ -15,22 +15,22 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// /// Implements the Lanczos kernel algorithm with a radius of 2. /// - public static LanczosResampler Lanczos2 = new LanczosResampler(2); + public static readonly LanczosResampler Lanczos2 = new(2); /// /// Implements the Lanczos kernel algorithm with a radius of 3. /// - public static LanczosResampler Lanczos3 = new LanczosResampler(3); + public static readonly LanczosResampler Lanczos3 = new(3); /// /// Implements the Lanczos kernel algorithm with a radius of 5. /// - public static LanczosResampler Lanczos5 = new LanczosResampler(5); + public static readonly LanczosResampler Lanczos5 = new(5); /// /// Implements the Lanczos kernel algorithm with a radius of 8. /// - public static LanczosResampler Lanczos8 = new LanczosResampler(8); + public static readonly LanczosResampler Lanczos8 = new(8); /// /// Initializes a new instance of the struct. diff --git a/src/ImageSharp/Processing/ResizeOptions.cs b/src/ImageSharp/Processing/ResizeOptions.cs index 3c31c7628..c7b862c1a 100644 --- a/src/ImageSharp/Processing/ResizeOptions.cs +++ b/src/ImageSharp/Processing/ResizeOptions.cs @@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.Processing /// Gets or sets a value indicating whether to compress /// or expand individual pixel colors the value on processing. /// - public bool Compand { get; set; } = false; + public bool Compand { get; set; } /// /// Gets or sets the target rectangle to resize into. diff --git a/tests/ImageSharp.Tests/Advanced/AdvancedImageExtensionsTests.cs b/tests/ImageSharp.Tests/Advanced/AdvancedImageExtensionsTests.cs index 063ba63cd..6ecb606f5 100644 --- a/tests/ImageSharp.Tests/Advanced/AdvancedImageExtensionsTests.cs +++ b/tests/ImageSharp.Tests/Advanced/AdvancedImageExtensionsTests.cs @@ -4,7 +4,6 @@ using System; using System.Linq; using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; @@ -50,7 +49,7 @@ namespace SixLabors.ImageSharp.Tests.Advanced image.Mutate(c => c.Resize(8, 8)); Assert.False(memoryGroup.IsValid); - Assert.ThrowsAny(() => _ = memoryGroup.First()); + Assert.ThrowsAny(() => _ = memoryGroup[0]); Assert.ThrowsAny(() => _ = memory.Span); } diff --git a/tests/ImageSharp.Tests/Colorspaces/Conversion/CieXyzAndCieXyyConversionTest.cs b/tests/ImageSharp.Tests/Colorspaces/Conversion/CieXyzAndCieXyyConversionTest.cs index 10d18d63c..0cd258bd9 100644 --- a/tests/ImageSharp.Tests/Colorspaces/Conversion/CieXyzAndCieXyyConversionTest.cs +++ b/tests/ImageSharp.Tests/Colorspaces/Conversion/CieXyzAndCieXyyConversionTest.cs @@ -36,8 +36,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion Span actualSpan = new CieXyz[5]; // Act - var actual = Converter.ToCieXyz(input); - Converter.Convert(inputSpan, actualSpan); + var actual = ColorSpaceConverter.ToCieXyz(input); + ColorSpaceConverter.Convert(inputSpan, actualSpan); // Assert Assert.Equal(expected, actual, ColorSpaceComparer); @@ -64,8 +64,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion Span actualSpan = new CieXyy[5]; // Act - var actual = Converter.ToCieXyy(input); - Converter.Convert(inputSpan, actualSpan); + var actual = ColorSpaceConverter.ToCieXyy(input); + ColorSpaceConverter.Convert(inputSpan, actualSpan); // Assert Assert.Equal(expected, actual, ColorSpaceComparer); diff --git a/tests/ImageSharp.Tests/Colorspaces/Conversion/CmykAndHslConversionTests.cs b/tests/ImageSharp.Tests/Colorspaces/Conversion/CmykAndHslConversionTests.cs index 9e08d572f..095b5e125 100644 --- a/tests/ImageSharp.Tests/Colorspaces/Conversion/CmykAndHslConversionTests.cs +++ b/tests/ImageSharp.Tests/Colorspaces/Conversion/CmykAndHslConversionTests.cs @@ -34,8 +34,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion Span actualSpan = new Hsl[5]; // Act - var actual = Converter.ToHsl(input); - Converter.Convert(inputSpan, actualSpan); + var actual = ColorSpaceConverter.ToHsl(input); + ColorSpaceConverter.Convert(inputSpan, actualSpan); // Assert Assert.Equal(expected, actual, ColorSpaceComparer); @@ -64,8 +64,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion Span actualSpan = new Cmyk[5]; // Act - var actual = Converter.ToCmyk(input); - Converter.Convert(inputSpan, actualSpan); + var actual = ColorSpaceConverter.ToCmyk(input); + ColorSpaceConverter.Convert(inputSpan, actualSpan); // Assert Assert.Equal(expected, actual, ColorSpaceComparer); diff --git a/tests/ImageSharp.Tests/Colorspaces/Conversion/CmykAndHsvConversionTests.cs b/tests/ImageSharp.Tests/Colorspaces/Conversion/CmykAndHsvConversionTests.cs index 44de7383a..770840e9b 100644 --- a/tests/ImageSharp.Tests/Colorspaces/Conversion/CmykAndHsvConversionTests.cs +++ b/tests/ImageSharp.Tests/Colorspaces/Conversion/CmykAndHsvConversionTests.cs @@ -34,8 +34,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion Span actualSpan = new Hsv[5]; // Act - var actual = Converter.ToHsv(input); - Converter.Convert(inputSpan, actualSpan); + var actual = ColorSpaceConverter.ToHsv(input); + ColorSpaceConverter.Convert(inputSpan, actualSpan); // Assert Assert.Equal(expected, actual, ColorSpaceComparer); @@ -64,8 +64,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion Span actualSpan = new Cmyk[5]; // Act - var actual = Converter.ToCmyk(input); - Converter.Convert(inputSpan, actualSpan); + var actual = ColorSpaceConverter.ToCmyk(input); + ColorSpaceConverter.Convert(inputSpan, actualSpan); // Assert Assert.Equal(expected, actual, ColorSpaceComparer); diff --git a/tests/ImageSharp.Tests/Colorspaces/Conversion/CmykAndYCbCrConversionTests.cs b/tests/ImageSharp.Tests/Colorspaces/Conversion/CmykAndYCbCrConversionTests.cs index 9c156b18d..a67af332d 100644 --- a/tests/ImageSharp.Tests/Colorspaces/Conversion/CmykAndYCbCrConversionTests.cs +++ b/tests/ImageSharp.Tests/Colorspaces/Conversion/CmykAndYCbCrConversionTests.cs @@ -34,8 +34,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion Span actualSpan = new YCbCr[5]; // Act - var actual = Converter.ToYCbCr(input); - Converter.Convert(inputSpan, actualSpan); + var actual = ColorSpaceConverter.ToYCbCr(input); + ColorSpaceConverter.Convert(inputSpan, actualSpan); // Assert Assert.Equal(expected, actual, ColorSpaceComparer); diff --git a/tests/ImageSharp.Tests/Colorspaces/Conversion/RgbAndCmykConversionTest.cs b/tests/ImageSharp.Tests/Colorspaces/Conversion/RgbAndCmykConversionTest.cs index 3f2386637..04abcf978 100644 --- a/tests/ImageSharp.Tests/Colorspaces/Conversion/RgbAndCmykConversionTest.cs +++ b/tests/ImageSharp.Tests/Colorspaces/Conversion/RgbAndCmykConversionTest.cs @@ -40,8 +40,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion Span actualSpan = new Rgb[5]; // Act - var actual = Converter.ToRgb(input); - Converter.Convert(inputSpan, actualSpan); + var actual = ColorSpaceConverter.ToRgb(input); + ColorSpaceConverter.Convert(inputSpan, actualSpan); // Assert Assert.Equal(Rgb.DefaultWorkingSpace, actual.WorkingSpace, ColorSpaceComparer); @@ -72,8 +72,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion Span actualSpan = new Cmyk[5]; // Act - var actual = Converter.ToCmyk(input); - Converter.Convert(inputSpan, actualSpan); + var actual = ColorSpaceConverter.ToCmyk(input); + ColorSpaceConverter.Convert(inputSpan, actualSpan); // Assert Assert.Equal(expected, actual, ColorSpaceComparer); diff --git a/tests/ImageSharp.Tests/Colorspaces/Conversion/RgbAndHslConversionTest.cs b/tests/ImageSharp.Tests/Colorspaces/Conversion/RgbAndHslConversionTest.cs index a5fd9ca77..f1075f866 100644 --- a/tests/ImageSharp.Tests/Colorspaces/Conversion/RgbAndHslConversionTest.cs +++ b/tests/ImageSharp.Tests/Colorspaces/Conversion/RgbAndHslConversionTest.cs @@ -43,8 +43,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion Span actualSpan = new Rgb[5]; // Act - var actual = Converter.ToRgb(input); - Converter.Convert(inputSpan, actualSpan); + var actual = ColorSpaceConverter.ToRgb(input); + ColorSpaceConverter.Convert(inputSpan, actualSpan); // Assert Assert.Equal(Rgb.DefaultWorkingSpace, actual.WorkingSpace, ColorSpaceComparer); @@ -78,8 +78,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion Span actualSpan = new Hsl[5]; // Act - var actual = Converter.ToHsl(input); - Converter.Convert(inputSpan, actualSpan); + var actual = ColorSpaceConverter.ToHsl(input); + ColorSpaceConverter.Convert(inputSpan, actualSpan); // Assert Assert.Equal(expected, actual, ColorSpaceComparer); diff --git a/tests/ImageSharp.Tests/Colorspaces/Conversion/RgbAndHsvConversionTest.cs b/tests/ImageSharp.Tests/Colorspaces/Conversion/RgbAndHsvConversionTest.cs index e7e95e792..2d801b540 100644 --- a/tests/ImageSharp.Tests/Colorspaces/Conversion/RgbAndHsvConversionTest.cs +++ b/tests/ImageSharp.Tests/Colorspaces/Conversion/RgbAndHsvConversionTest.cs @@ -42,8 +42,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion Span actualSpan = new Rgb[5]; // Act - var actual = Converter.ToRgb(input); - Converter.Convert(inputSpan, actualSpan); + var actual = ColorSpaceConverter.ToRgb(input); + ColorSpaceConverter.Convert(inputSpan, actualSpan); // Assert Assert.Equal(Rgb.DefaultWorkingSpace, actual.WorkingSpace, ColorSpaceComparer); @@ -76,8 +76,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion Span actualSpan = new Hsv[5]; // Act - var actual = Converter.ToHsv(input); - Converter.Convert(inputSpan, actualSpan); + var actual = ColorSpaceConverter.ToHsv(input); + ColorSpaceConverter.Convert(inputSpan, actualSpan); // Assert Assert.Equal(expected, actual, ColorSpaceComparer); diff --git a/tests/ImageSharp.Tests/Colorspaces/Conversion/RgbAndYCbCrConversionTest.cs b/tests/ImageSharp.Tests/Colorspaces/Conversion/RgbAndYCbCrConversionTest.cs index 297b4ad13..0b4193c1a 100644 --- a/tests/ImageSharp.Tests/Colorspaces/Conversion/RgbAndYCbCrConversionTest.cs +++ b/tests/ImageSharp.Tests/Colorspaces/Conversion/RgbAndYCbCrConversionTest.cs @@ -71,8 +71,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion Span actualSpan = new YCbCr[5]; // Act - var actual = Converter.ToYCbCr(input); - Converter.Convert(inputSpan, actualSpan); + var actual = ColorSpaceConverter.ToYCbCr(input); + ColorSpaceConverter.Convert(inputSpan, actualSpan); // Assert Assert.Equal(expected, actual, ColorSpaceComparer); diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs index c6f74869e..deeff0992 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs @@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg public void GetConverterThrowsExceptionOnInvalidColorSpace() { var invalidColorSpace = (JpegColorSpace)(-1); - Assert.Throws(() => JpegColorConverterBase.GetConverter(invalidColorSpace, 8)); + Assert.Throws(() => JpegColorConverterBase.GetConverter(invalidColorSpace, 8)); } [Fact] @@ -47,7 +47,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg { // Valid precisions: 8 & 12 bit int invalidPrecision = 9; - Assert.Throws(() => JpegColorConverterBase.GetConverter(JpegColorSpace.YCbCr, invalidPrecision)); + Assert.Throws(() => JpegColorConverterBase.GetConverter(JpegColorSpace.YCbCr, invalidPrecision)); } [Theory] diff --git a/tests/ImageSharp.Tests/Formats/Tiff/BigTiffMetadataTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/BigTiffMetadataTests.cs index bb26d182b..9ce45d3f3 100644 --- a/tests/ImageSharp.Tests/Formats/Tiff/BigTiffMetadataTests.cs +++ b/tests/ImageSharp.Tests/Formats/Tiff/BigTiffMetadataTests.cs @@ -245,7 +245,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff private static void WriteLong8(TiffStreamWriter writer, byte[] buffer, ulong value) { - if (writer.IsLittleEndian) + if (TiffStreamWriter.IsLittleEndian) { BinaryPrimitives.WriteUInt64LittleEndian(buffer, value); } diff --git a/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderHeaderTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderHeaderTests.cs index 6874019a0..2d594319e 100644 --- a/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderHeaderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderHeaderTests.cs @@ -25,7 +25,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff using (var writer = new TiffStreamWriter(stream)) { - long firstIfdMarker = encoder.WriteHeader(writer); + long firstIfdMarker = TiffEncoderCore.WriteHeader(writer); } Assert.Equal(new byte[] { 0x49, 0x49, 42, 0, 0x00, 0x00, 0x00, 0x00 }, stream.ToArray()); @@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff using (var writer = new TiffStreamWriter(stream)) { - long firstIfdMarker = encoder.WriteHeader(writer); + long firstIfdMarker = TiffEncoderCore.WriteHeader(writer); Assert.Equal(4, firstIfdMarker); } } diff --git a/tests/ImageSharp.Tests/Formats/Tiff/Utils/TiffWriterTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/Utils/TiffWriterTests.cs index cc3277981..253381985 100644 --- a/tests/ImageSharp.Tests/Formats/Tiff/Utils/TiffWriterTests.cs +++ b/tests/ImageSharp.Tests/Formats/Tiff/Utils/TiffWriterTests.cs @@ -16,7 +16,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff.Utils { using var stream = new MemoryStream(); using var writer = new TiffStreamWriter(stream); - Assert.True(writer.IsLittleEndian); + Assert.True(TiffStreamWriter.IsLittleEndian); } [Theory] diff --git a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/IccReaderTests.cs b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/IccReaderTests.cs index a21a4f049..184a6c42e 100644 --- a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/IccReaderTests.cs +++ b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/IccReaderTests.cs @@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.Icc { IccReader reader = this.CreateReader(); - IccProfile output = reader.Read(IccTestDataProfiles.Header_Random_Array); + IccProfile output = IccReader.Read(IccTestDataProfiles.Header_Random_Array); Assert.Equal(0, output.Entries.Length); Assert.NotNull(output.Header); @@ -45,7 +45,7 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.Icc { IccReader reader = this.CreateReader(); - IccProfile output = reader.Read(IccTestDataProfiles.Profile_Random_Array); + IccProfile output = IccReader.Read(IccTestDataProfiles.Profile_Random_Array); Assert.Equal(2, output.Entries.Length); Assert.True(ReferenceEquals(output.Entries[0], output.Entries[1])); diff --git a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/IccWriterTests.cs b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/IccWriterTests.cs index 7aa587a32..039d12663 100644 --- a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/IccWriterTests.cs +++ b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/IccWriterTests.cs @@ -18,7 +18,7 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.Icc { Header = IccTestDataProfiles.Header_Random_Write }; - byte[] output = writer.Write(profile); + byte[] output = IccWriter.Write(profile); Assert.Equal(IccTestDataProfiles.Header_Random_Array, output); } @@ -28,7 +28,7 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.Icc { IccWriter writer = this.CreateWriter(); - byte[] output = writer.Write(IccTestDataProfiles.Profile_Random_Val); + byte[] output = IccWriter.Write(IccTestDataProfiles.Profile_Random_Val); Assert.Equal(IccTestDataProfiles.Profile_Random_Array, output); } From ac84e4986d95e12116add03578ce70aeee0efb5c Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 6 Sep 2022 23:44:16 +1000 Subject: [PATCH 15/20] Fix CA1854 for NET 7 --- src/ImageSharp/Formats/Png/PngHeader.cs | 22 ++-- .../Compressors/TiffCcittCompressor.cs | 108 +++++++++--------- .../Metadata/Profiles/ICC/IccProfile.cs | 7 +- 3 files changed, 67 insertions(+), 70 deletions(-) diff --git a/src/ImageSharp/Formats/Png/PngHeader.cs b/src/ImageSharp/Formats/Png/PngHeader.cs index 0837e0063..3e4609aad 100644 --- a/src/ImageSharp/Formats/Png/PngHeader.cs +++ b/src/ImageSharp/Formats/Png/PngHeader.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; @@ -104,7 +104,7 @@ namespace SixLabors.ImageSharp.Formats.Png } // The png specification only defines 'None' and 'Adam7' as interlaced methods. - if (this.InterlaceMethod != PngInterlaceMode.None && this.InterlaceMethod != PngInterlaceMode.Adam7) + if (this.InterlaceMethod is not PngInterlaceMode.None and not PngInterlaceMode.Adam7) { throw new NotSupportedException($"Invalid interlace method. Expected 'None' or 'Adam7'. Was '{this.InterlaceMethod}'."); } @@ -132,15 +132,13 @@ namespace SixLabors.ImageSharp.Formats.Png /// The data to parse. /// The parsed PngHeader. public static PngHeader Parse(ReadOnlySpan data) - { - return new PngHeader( - width: BinaryPrimitives.ReadInt32BigEndian(data[..4]), - height: BinaryPrimitives.ReadInt32BigEndian(data.Slice(4, 4)), - bitDepth: data[8], - colorType: (PngColorType)data[9], - compressionMethod: data[10], - filterMethod: data[11], - interlaceMethod: (PngInterlaceMode)data[12]); - } + => new( + width: BinaryPrimitives.ReadInt32BigEndian(data[..4]), + height: BinaryPrimitives.ReadInt32BigEndian(data.Slice(4, 4)), + bitDepth: data[8], + colorType: (PngColorType)data[9], + compressionMethod: data[10], + filterMethod: data[11], + interlaceMethod: (PngInterlaceMode)data[12]); } } diff --git a/src/ImageSharp/Formats/Tiff/Compression/Compressors/TiffCcittCompressor.cs b/src/ImageSharp/Formats/Tiff/Compression/Compressors/TiffCcittCompressor.cs index 8ff41ed07..c43f24774 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/Compressors/TiffCcittCompressor.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/Compressors/TiffCcittCompressor.cs @@ -199,46 +199,46 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors { codeLength = 0; - if (WhiteLen5MakeupCodes.ContainsKey(runLength)) + if (WhiteLen5MakeupCodes.TryGetValue(runLength, out uint value)) { codeLength = 5; - return WhiteLen5MakeupCodes[runLength]; + return value; } - if (WhiteLen6MakeupCodes.ContainsKey(runLength)) + if (WhiteLen6MakeupCodes.TryGetValue(runLength, out value)) { codeLength = 6; - return WhiteLen6MakeupCodes[runLength]; + return value; } - if (WhiteLen7MakeupCodes.ContainsKey(runLength)) + if (WhiteLen7MakeupCodes.TryGetValue(runLength, out value)) { codeLength = 7; - return WhiteLen7MakeupCodes[runLength]; + return value; } - if (WhiteLen8MakeupCodes.ContainsKey(runLength)) + if (WhiteLen8MakeupCodes.TryGetValue(runLength, out value)) { codeLength = 8; - return WhiteLen8MakeupCodes[runLength]; + return value; } - if (WhiteLen9MakeupCodes.ContainsKey(runLength)) + if (WhiteLen9MakeupCodes.TryGetValue(runLength, out value)) { codeLength = 9; - return WhiteLen9MakeupCodes[runLength]; + return value; } - if (WhiteLen11MakeupCodes.ContainsKey(runLength)) + if (WhiteLen11MakeupCodes.TryGetValue(runLength, out value)) { codeLength = 11; - return WhiteLen11MakeupCodes[runLength]; + return value; } - if (WhiteLen12MakeupCodes.ContainsKey(runLength)) + if (WhiteLen12MakeupCodes.TryGetValue(runLength, out value)) { codeLength = 12; - return WhiteLen12MakeupCodes[runLength]; + return value; } return 0; @@ -248,28 +248,28 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors { codeLength = 0; - if (BlackLen10MakeupCodes.ContainsKey(runLength)) + if (BlackLen10MakeupCodes.TryGetValue(runLength, out uint value)) { codeLength = 10; - return BlackLen10MakeupCodes[runLength]; + return value; } - if (BlackLen11MakeupCodes.ContainsKey(runLength)) + if (BlackLen11MakeupCodes.TryGetValue(runLength, out value)) { codeLength = 11; - return BlackLen11MakeupCodes[runLength]; + return value; } - if (BlackLen12MakeupCodes.ContainsKey(runLength)) + if (BlackLen12MakeupCodes.TryGetValue(runLength, out value)) { codeLength = 12; - return BlackLen12MakeupCodes[runLength]; + return value; } - if (BlackLen13MakeupCodes.ContainsKey(runLength)) + if (BlackLen13MakeupCodes.TryGetValue(runLength, out value)) { codeLength = 13; - return BlackLen13MakeupCodes[runLength]; + return value; } return 0; @@ -279,34 +279,34 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors { codeLength = 0; - if (WhiteLen4TermCodes.ContainsKey(runLength)) + if (WhiteLen4TermCodes.TryGetValue(runLength, out uint value)) { codeLength = 4; - return WhiteLen4TermCodes[runLength]; + return value; } - if (WhiteLen5TermCodes.ContainsKey(runLength)) + if (WhiteLen5TermCodes.TryGetValue(runLength, out value)) { codeLength = 5; - return WhiteLen5TermCodes[runLength]; + return value; } - if (WhiteLen6TermCodes.ContainsKey(runLength)) + if (WhiteLen6TermCodes.TryGetValue(runLength, out value)) { codeLength = 6; - return WhiteLen6TermCodes[runLength]; + return value; } - if (WhiteLen7TermCodes.ContainsKey(runLength)) + if (WhiteLen7TermCodes.TryGetValue(runLength, out value)) { codeLength = 7; - return WhiteLen7TermCodes[runLength]; + return value; } - if (WhiteLen8TermCodes.ContainsKey(runLength)) + if (WhiteLen8TermCodes.TryGetValue(runLength, out value)) { codeLength = 8; - return WhiteLen8TermCodes[runLength]; + return value; } return 0; @@ -316,70 +316,70 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors { codeLength = 0; - if (BlackLen2TermCodes.ContainsKey(runLength)) + if (BlackLen2TermCodes.TryGetValue(runLength, out uint value)) { codeLength = 2; - return BlackLen2TermCodes[runLength]; + return value; } - if (BlackLen3TermCodes.ContainsKey(runLength)) + if (BlackLen3TermCodes.TryGetValue(runLength, out value)) { codeLength = 3; - return BlackLen3TermCodes[runLength]; + return value; } - if (BlackLen4TermCodes.ContainsKey(runLength)) + if (BlackLen4TermCodes.TryGetValue(runLength, out value)) { codeLength = 4; - return BlackLen4TermCodes[runLength]; + return value; } - if (BlackLen5TermCodes.ContainsKey(runLength)) + if (BlackLen5TermCodes.TryGetValue(runLength, out value)) { codeLength = 5; - return BlackLen5TermCodes[runLength]; + return value; } - if (BlackLen6TermCodes.ContainsKey(runLength)) + if (BlackLen6TermCodes.TryGetValue(runLength, out value)) { codeLength = 6; - return BlackLen6TermCodes[runLength]; + return value; } - if (BlackLen7TermCodes.ContainsKey(runLength)) + if (BlackLen7TermCodes.TryGetValue(runLength, out value)) { codeLength = 7; - return BlackLen7TermCodes[runLength]; + return value; } - if (BlackLen8TermCodes.ContainsKey(runLength)) + if (BlackLen8TermCodes.TryGetValue(runLength, out value)) { codeLength = 8; - return BlackLen8TermCodes[runLength]; + return value; } - if (BlackLen9TermCodes.ContainsKey(runLength)) + if (BlackLen9TermCodes.TryGetValue(runLength, out value)) { codeLength = 9; - return BlackLen9TermCodes[runLength]; + return value; } - if (BlackLen10TermCodes.ContainsKey(runLength)) + if (BlackLen10TermCodes.TryGetValue(runLength, out value)) { codeLength = 10; - return BlackLen10TermCodes[runLength]; + return value; } - if (BlackLen11TermCodes.ContainsKey(runLength)) + if (BlackLen11TermCodes.TryGetValue(runLength, out value)) { codeLength = 11; - return BlackLen11TermCodes[runLength]; + return value; } - if (BlackLen12TermCodes.ContainsKey(runLength)) + if (BlackLen12TermCodes.TryGetValue(runLength, out value)) { codeLength = 12; - return BlackLen12TermCodes[runLength]; + return value; } return 0; diff --git a/src/ImageSharp/Metadata/Profiles/ICC/IccProfile.cs b/src/ImageSharp/Metadata/Profiles/ICC/IccProfile.cs index 3752be1ba..39b726f90 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/IccProfile.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/IccProfile.cs @@ -113,9 +113,6 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc Buffer.BlockCopy(data, renderingIntentPos, temp, 4, 4); Buffer.BlockCopy(data, profileIdPos, temp, 8, 16); -#pragma warning disable CA5351 // Do Not Use Broken Cryptographic Algorithms - using MD5 md5 = MD5.Create(); -#pragma warning restore CA5351 // Do Not Use Broken Cryptographic Algorithms try { // Zero out some values @@ -124,7 +121,9 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc Array.Clear(data, profileIdPos, 16); // Calculate hash - byte[] hash = md5.ComputeHash(data); +#pragma warning disable CA5351 // Do Not Use Broken Cryptographic Algorithms + byte[] hash = MD5.HashData(data); +#pragma warning restore CA5351 // Do Not Use Broken Cryptographic Algorithms // Read values from hash IccDataReader reader = new(hash); From 90c85c01a11cc0e3790c38982ca013abf6973446 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 6 Sep 2022 23:54:27 +1000 Subject: [PATCH 16/20] Cleanup and remove unused index --- .../Formats/Webp/Lossy/Vp8Encoding.cs | 58 +++++++++---------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/src/ImageSharp/Formats/Webp/Lossy/Vp8Encoding.cs b/src/ImageSharp/Formats/Webp/Lossy/Vp8Encoding.cs index 4b94c840d..32d96cba9 100644 --- a/src/ImageSharp/Formats/Webp/Lossy/Vp8Encoding.cs +++ b/src/ImageSharp/Formats/Webp/Lossy/Vp8Encoding.cs @@ -103,19 +103,19 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy // second half of the vectors will just contain random value we'll never // use nor store. ref short inputRef = ref MemoryMarshal.GetReference(input); - var in0 = Vector128.Create(Unsafe.As(ref inputRef), 0); - var in1 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref inputRef, 4)), 0); - var in2 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref inputRef, 8)), 0); - var in3 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref inputRef, 12)), 0); + Vector128 in0 = Vector128.Create(Unsafe.As(ref inputRef), 0); + Vector128 in1 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref inputRef, 4)), 0); + Vector128 in2 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref inputRef, 8)), 0); + Vector128 in3 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref inputRef, 12)), 0); // a00 a10 a20 a30 x x x x // a01 a11 a21 a31 x x x x // a02 a12 a22 a32 x x x x // a03 a13 a23 a33 x x x x - var inb0 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref inputRef, 16)), 0); - var inb1 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref inputRef, 20)), 0); - var inb2 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref inputRef, 24)), 0); - var inb3 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref inputRef, 28)), 0); + Vector128 inb0 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref inputRef, 16)), 0); + Vector128 inb1 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref inputRef, 20)), 0); + Vector128 inb2 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref inputRef, 24)), 0); + Vector128 inb3 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref inputRef, 28)), 0); in0 = Sse2.UnpackLow(in0, inb0); in1 = Sse2.UnpackLow(in1, inb1); @@ -196,10 +196,10 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy // second half of the vectors will just contain random value we'll never // use nor store. ref short inputRef = ref MemoryMarshal.GetReference(input); - var in0 = Vector128.Create(Unsafe.As(ref inputRef), 0); - var in1 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref inputRef, 4)), 0); - var in2 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref inputRef, 8)), 0); - var in3 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref inputRef, 12)), 0); + Vector128 in0 = Vector128.Create(Unsafe.As(ref inputRef), 0); + Vector128 in1 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref inputRef, 4)), 0); + Vector128 in2 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref inputRef, 8)), 0); + Vector128 in3 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref inputRef, 12)), 0); // a00 a10 a20 a30 x x x x // a01 a11 a21 a31 x x x x @@ -374,16 +374,16 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy ref byte referenceRef = ref MemoryMarshal.GetReference(reference); // Load src. - var src0 = Vector128.Create(Unsafe.As(ref srcRef), 0); - var src1 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref srcRef, WebpConstants.Bps)), 0); - var src2 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref srcRef, WebpConstants.Bps * 2)), 0); - var src3 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref srcRef, WebpConstants.Bps * 3)), 0); + Vector128 src0 = Vector128.Create(Unsafe.As(ref srcRef), 0); + Vector128 src1 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref srcRef, WebpConstants.Bps)), 0); + Vector128 src2 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref srcRef, WebpConstants.Bps * 2)), 0); + Vector128 src3 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref srcRef, WebpConstants.Bps * 3)), 0); // Load ref. - var ref0 = Vector128.Create(Unsafe.As(ref referenceRef), 0); - var ref1 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref referenceRef, WebpConstants.Bps)), 0); - var ref2 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref referenceRef, WebpConstants.Bps * 2)), 0); - var ref3 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref referenceRef, WebpConstants.Bps * 3)), 0); + Vector128 ref0 = Vector128.Create(Unsafe.As(ref referenceRef), 0); + Vector128 ref1 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref referenceRef, WebpConstants.Bps)), 0); + Vector128 ref2 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref referenceRef, WebpConstants.Bps * 2)), 0); + Vector128 ref3 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref referenceRef, WebpConstants.Bps * 3)), 0); // Convert both to 16 bit. Vector128 srcLow0 = Sse2.UnpackLow(src0.AsByte(), Vector128.Zero); @@ -434,16 +434,16 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy ref byte referenceRef = ref MemoryMarshal.GetReference(reference); // Load src. - var src0 = Vector128.Create(Unsafe.As(ref srcRef), 0); - var src1 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref srcRef, WebpConstants.Bps)), 0); - var src2 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref srcRef, WebpConstants.Bps * 2)), 0); - var src3 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref srcRef, WebpConstants.Bps * 3)), 0); + Vector128 src0 = Vector128.Create(Unsafe.As(ref srcRef), 0); + Vector128 src1 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref srcRef, WebpConstants.Bps)), 0); + Vector128 src2 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref srcRef, WebpConstants.Bps * 2)), 0); + Vector128 src3 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref srcRef, WebpConstants.Bps * 3)), 0); // Load ref. - var ref0 = Vector128.Create(Unsafe.As(ref referenceRef), 0); - var ref1 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref referenceRef, WebpConstants.Bps)), 0); - var ref2 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref referenceRef, WebpConstants.Bps * 2)), 0); - var ref3 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref referenceRef, WebpConstants.Bps * 3)), 0); + Vector128 ref0 = Vector128.Create(Unsafe.As(ref referenceRef), 0); + Vector128 ref1 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref referenceRef, WebpConstants.Bps)), 0); + Vector128 ref2 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref referenceRef, WebpConstants.Bps * 2)), 0); + Vector128 ref3 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref referenceRef, WebpConstants.Bps * 3)), 0); // 00 01 02 03 * // 10 11 12 13 * @@ -654,7 +654,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy // luma 16x16 prediction (paragraph 12.3). public static void EncPredLuma16(Span dst, Span left, Span top) { - DcMode(dst[..], left, top, 16, 16, 5); + DcMode(dst, left, top, 16, 16, 5); VerticalPred(dst[I16VE16..], top, 16); HorizontalPred(dst[I16HE16..], left, 16); TrueMotion(dst[I16TM16..], left, top, 16); From 0e465102f47ddb6af3032d979e25e3d5841a43c0 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 6 Sep 2022 23:54:44 +1000 Subject: [PATCH 17/20] Use culture for NET 7 --- src/ImageSharp/Formats/Png/PngDecoderCore.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs index b7cd5dd93..3d9fc68fa 100644 --- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs @@ -4,6 +4,7 @@ using System; using System.Buffers; using System.Buffers.Binary; +using System.Globalization; using System.IO; using System.IO.Compression; using System.Runtime.CompilerServices; @@ -1258,7 +1259,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// The to parse. /// The parsed . - private static int ParseInt32(ReadOnlySpan span) => int.Parse(span); + private static int ParseInt32(ReadOnlySpan span) => int.Parse(span, provider: CultureInfo.InvariantCulture); /// /// Sets the in to , @@ -1358,8 +1359,7 @@ namespace SixLabors.ImageSharp.Formats.Png } else if (IsXmpTextData(keywordBytes)) { - XmpProfile xmpProfile = new(data[dataStartIdx..].ToArray()); - metadata.XmpProfile = xmpProfile; + metadata.XmpProfile = new XmpProfile(data[dataStartIdx..].ToArray()); } else { From e25734a2d934736ca9a38edd17a0493f6b8b90b1 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 7 Sep 2022 07:51:06 +1000 Subject: [PATCH 18/20] Reverse unsealing --- .../Implementation/Converters/HunterLabToCieXyzConverter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HunterLabToCieXyzConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HunterLabToCieXyzConverter.cs index ead2f37d8..424b43b12 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HunterLabToCieXyzConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HunterLabToCieXyzConverter.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// Color converter between and /// - internal class HunterLabToCieXyzConverter : CieXyzAndHunterLabConverterBase + internal sealed class HunterLabToCieXyzConverter : CieXyzAndHunterLabConverterBase { /// /// Performs the conversion from the input to an instance of type. From 9b29319ea97835e9960cdf142ecb103b047bd7cc Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 7 Sep 2022 08:00:53 +1000 Subject: [PATCH 19/20] Reverse breaking change. --- src/ImageSharp/Color/Color.cs | 6 +++++- .../Processors/Dithering/PaletteDitherProcessor{TPixel}.cs | 2 +- .../Processing/Processors/Quantization/PaletteQuantizer.cs | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/ImageSharp/Color/Color.cs b/src/ImageSharp/Color/Color.cs index 17e0964d0..9cff680e4 100644 --- a/src/ImageSharp/Color/Color.cs +++ b/src/ImageSharp/Color/Color.cs @@ -287,12 +287,16 @@ namespace SixLabors.ImageSharp /// Bulk converts a span of to a span of a specified type. /// /// The pixel type to convert to. + /// The configuration. /// The source color span. /// The destination pixel span. [MethodImpl(InliningOptions.ShortMethod)] - public static void ToPixel(ReadOnlySpan source, Span destination) +#pragma warning disable RCS1163 // Unused parameter. + public static void ToPixel(Configuration configuration, ReadOnlySpan source, Span destination) +#pragma warning restore RCS1163 // Unused parameter. where TPixel : unmanaged, IPixel { + // TODO: Investigate bulk operations utilizing configuration parameter here. Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); for (int i = 0; i < source.Length; i++) { diff --git a/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor{TPixel}.cs index 4933b9f75..5b336d78f 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor{TPixel}.cs @@ -36,7 +36,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering ReadOnlySpan sourcePalette = definition.Palette.Span; this.paletteOwner = this.Configuration.MemoryAllocator.Allocate(sourcePalette.Length); - Color.ToPixel(sourcePalette, this.paletteOwner.Memory.Span); + Color.ToPixel(this.Configuration, sourcePalette, this.paletteOwner.Memory.Span); this.ditherProcessor = new DitherProcessor( this.Configuration, diff --git a/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer.cs b/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer.cs index cc4b4a33f..30043abfb 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer.cs @@ -56,7 +56,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization int length = Math.Min(this.colorPalette.Length, options.MaxColors); TPixel[] palette = new TPixel[length]; - Color.ToPixel(this.colorPalette.Span, palette.AsSpan()); + Color.ToPixel(configuration, this.colorPalette.Span, palette.AsSpan()); return new PaletteQuantizer(configuration, options, palette); } } From e9049e278b456ab55571ceff87eda04bc6ee94e7 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 12 Sep 2022 10:58:13 +1000 Subject: [PATCH 20/20] Throw for unsupported App0 markers. --- src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs index 3d65021a7..50c08eb77 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs @@ -744,9 +744,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg } stream.Read(this.temp, 0, JFifMarker.Length); - remaining -= JFifMarker.Length; + if (!JFifMarker.TryParse(this.temp, out this.jFif)) + { + JpegThrowHelper.ThrowNotSupportedException("Unknown App0 Marker - Expected JFIF."); + } - _ = JFifMarker.TryParse(this.temp, out this.jFif); + remaining -= JFifMarker.Length; // TODO: thumbnail if (remaining > 0)