From c3d4e4d8f4585b2325017bc7ccf0d428bc41841d Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Mon, 1 Apr 2019 00:56:11 +0200 Subject: [PATCH] all pixel types implemented except RgbaVector --- .../Argb32.PixelOperations.Generated.cs | 4 +- .../Bgr24.PixelOperations.Generated.cs | 4 +- .../Bgra32.PixelOperations.Generated.cs | 4 +- .../Rgb24.PixelOperations.Generated.cs | 4 +- .../Generated/_Common.ttinclude | 4 +- .../Rgba32.PixelOperations.cs | 6 +- .../RgbaVector.PixelOperations.cs | 6 ++ .../PixelFormats/PixelOperations{TPixel}.cs | 20 +---- .../Utils/Vector4Converters.Default.cs | 74 +++++++++++++++++-- .../Utils/Vector4Converters.RgbaCompatible.cs | 46 ++++-------- .../PixelFormats/Utils/Vector4Converters.cs | 48 ++++++++++++ .../PixelOperations/PixelOperationsTests.cs | 8 +- 12 files changed, 158 insertions(+), 70 deletions(-) create mode 100644 src/ImageSharp/PixelFormats/Utils/Vector4Converters.cs diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs index e832bc97f..c49f3f834 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs @@ -44,13 +44,13 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void FromVector4(Configuration configuration, Span sourceVectors, Span destPixels, PixelConversionModifiers modifiers) { - Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, false); + Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, modifiers.Remove(PixelConversionModifiers.Scale)); } /// internal override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors, PixelConversionModifiers modifiers) { - Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, false); + Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, modifiers.Remove(PixelConversionModifiers.Scale)); } /// internal override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs index f1885c71b..a9eca8994 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs @@ -44,13 +44,13 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void FromVector4(Configuration configuration, Span sourceVectors, Span destPixels, PixelConversionModifiers modifiers) { - Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, false); + Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, modifiers.Remove(PixelConversionModifiers.Scale)); } /// internal override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors, PixelConversionModifiers modifiers) { - Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, false); + Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, modifiers.Remove(PixelConversionModifiers.Scale)); } /// diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs index 2409f6784..73eddc235 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs @@ -44,13 +44,13 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void FromVector4(Configuration configuration, Span sourceVectors, Span destPixels, PixelConversionModifiers modifiers) { - Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, false); + Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, modifiers.Remove(PixelConversionModifiers.Scale)); } /// internal override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors, PixelConversionModifiers modifiers) { - Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, false); + Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, modifiers.Remove(PixelConversionModifiers.Scale)); } /// internal override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs index ddf9813ab..1648f5341 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs @@ -44,13 +44,13 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void FromVector4(Configuration configuration, Span sourceVectors, Span destPixels, PixelConversionModifiers modifiers) { - Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, false); + Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, modifiers.Remove(PixelConversionModifiers.Scale)); } /// internal override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors, PixelConversionModifiers modifiers) { - Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, false); + Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, modifiers.Remove(PixelConversionModifiers.Scale)); } /// diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude index 0ff5b8605..6286eaf72 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude @@ -113,13 +113,13 @@ using System.Runtime.InteropServices; /// internal override void FromVector4(Configuration configuration, Span sourceVectors, Span<<#=pixelType#>> destPixels, PixelConversionModifiers modifiers) { - Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, false); + Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, modifiers.Remove(PixelConversionModifiers.Scale)); } /// internal override void ToVector4(Configuration configuration, ReadOnlySpan<<#=pixelType#>> sourcePixels, Span destVectors, PixelConversionModifiers modifiers) { - Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, false); + Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, modifiers.Remove(PixelConversionModifiers.Scale)); } <#+ } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.PixelOperations.cs index 7e8bb7f29..aa9b82be7 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.PixelOperations.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.PixelOperations.cs @@ -4,6 +4,8 @@ using System; using System.Numerics; using System.Runtime.InteropServices; + +using SixLabors.ImageSharp.PixelFormats.Utils; using SixLabors.Memory; namespace SixLabors.ImageSharp.PixelFormats @@ -28,10 +30,10 @@ namespace SixLabors.ImageSharp.PixelFormats Guard.DestinationShouldNotBeTooShort(sourcePixels, destVectors, nameof(destVectors)); destVectors = destVectors.Slice(0, sourcePixels.Length); - SimdUtils.BulkConvertByteToNormalizedFloat( MemoryMarshal.Cast(sourcePixels), MemoryMarshal.Cast(destVectors)); + Vector4Converters.ApplyForwardConversionModifiers(destVectors, modifiers); } /// @@ -44,7 +46,7 @@ namespace SixLabors.ImageSharp.PixelFormats Guard.DestinationShouldNotBeTooShort(sourceVectors, destPixels, nameof(destPixels)); destPixels = destPixels.Slice(0, sourceVectors.Length); - + Vector4Converters.ApplyBackwardConversionModifiers(sourceVectors, modifiers); SimdUtils.BulkConvertNormalizedFloatToByteClampOverflows( MemoryMarshal.Cast(sourceVectors), MemoryMarshal.Cast(destPixels)); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs index 777d0da6d..3c4d951ee 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs @@ -5,6 +5,8 @@ using System; using System.Numerics; using System.Runtime.InteropServices; +using SixLabors.ImageSharp.PixelFormats.Utils; + namespace SixLabors.ImageSharp.PixelFormats { /// @@ -26,6 +28,8 @@ namespace SixLabors.ImageSharp.PixelFormats { Guard.DestinationShouldNotBeTooShort(sourceVectors, destinationColors, nameof(destinationColors)); + Vector4Converters.ApplyBackwardConversionModifiers(sourceVectors, modifiers); + // TODO: Repeating previous override behavior here. Not sure if this is correct! if (modifiers.IsDefined(PixelConversionModifiers.Scale)) { @@ -55,6 +59,8 @@ namespace SixLabors.ImageSharp.PixelFormats { MemoryMarshal.Cast(sourcePixels).CopyTo(destVectors); } + + Vector4Converters.ApplyForwardConversionModifiers(destVectors, modifiers); } } } diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs index ea5bc876f..53181e7a9 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs @@ -37,16 +37,8 @@ namespace SixLabors.ImageSharp.PixelFormats PixelConversionModifiers modifiers) { Guard.NotNull(configuration, nameof(configuration)); - Guard.DestinationShouldNotBeTooShort(sourceVectors, destPixels, nameof(destPixels)); - if (modifiers.IsDefined(PixelConversionModifiers.Scale)) - { - Utils.Vector4Converters.Default.DangerousFromScaledVector4(sourceVectors, destPixels); - } - else - { - Utils.Vector4Converters.Default.DangerousFromVector4(sourceVectors, destPixels); - } + Utils.Vector4Converters.Default.FromVector4(sourceVectors, destPixels, modifiers); } /// @@ -82,16 +74,8 @@ namespace SixLabors.ImageSharp.PixelFormats PixelConversionModifiers modifiers) { Guard.NotNull(configuration, nameof(configuration)); - Guard.DestinationShouldNotBeTooShort(sourcePixels, destVectors, nameof(destVectors)); - if (modifiers.IsDefined(PixelConversionModifiers.Scale)) - { - Utils.Vector4Converters.Default.DangerousToScaledVector4(sourcePixels, destVectors); - } - else - { - Utils.Vector4Converters.Default.DangerousToVector4(sourcePixels, destVectors); - } + Utils.Vector4Converters.Default.ToVector4(sourcePixels, destVectors, modifiers); } /// diff --git a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.Default.cs b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.Default.cs index e784e3b5a..4c4e60276 100644 --- a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.Default.cs +++ b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.Default.cs @@ -6,6 +6,8 @@ using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using SixLabors.ImageSharp.ColorSpaces.Companding; + namespace SixLabors.ImageSharp.PixelFormats.Utils { /// @@ -15,13 +17,75 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils { /// /// Provides default implementations for batched to/from conversion. - /// WARNING: The methods are operating without bounds checking and input validation! + /// WARNING: The methods prefixed with "Unsafe" are operating without bounds checking and input validation! /// Input validation is the responsibility of the caller! /// public static class Default { [MethodImpl(InliningOptions.ShortMethod)] - internal static void DangerousFromVector4( + public static void FromVector4( + Span sourceVectors, + Span destPixels, + PixelConversionModifiers modifiers) + where TPixel : struct, IPixel + { + Guard.DestinationShouldNotBeTooShort(sourceVectors, destPixels, nameof(destPixels)); + + UnsafeFromVector4(sourceVectors, destPixels, modifiers); + } + + [MethodImpl(InliningOptions.ShortMethod)] + public static void ToVector4( + ReadOnlySpan sourcePixels, + Span destVectors, + PixelConversionModifiers modifiers) + where TPixel : struct, IPixel + { + Guard.DestinationShouldNotBeTooShort(sourcePixels, destVectors, nameof(destVectors)); + + UnsafeToVector4(sourcePixels, destVectors, modifiers); + } + + [MethodImpl(InliningOptions.ShortMethod)] + public static void UnsafeFromVector4( + Span sourceVectors, + Span destPixels, + PixelConversionModifiers modifiers) + where TPixel : struct, IPixel + { + ApplyBackwardConversionModifiers(sourceVectors, modifiers); + + if (modifiers.IsDefined(PixelConversionModifiers.Scale)) + { + UnsafeFromScaledVector4Core(sourceVectors, destPixels); + } + else + { + UnsafeFromVector4Core(sourceVectors, destPixels); + } + } + + [MethodImpl(InliningOptions.ShortMethod)] + public static void UnsafeToVector4( + ReadOnlySpan sourcePixels, + Span destVectors, + PixelConversionModifiers modifiers) + where TPixel : struct, IPixel + { + if (modifiers.IsDefined(PixelConversionModifiers.Scale)) + { + UnsafeToScaledVector4Core(sourcePixels, destVectors); + } + else + { + UnsafeToVector4Core(sourcePixels, destVectors); + } + + ApplyForwardConversionModifiers(destVectors, modifiers); + } + + [MethodImpl(InliningOptions.ShortMethod)] + private static void UnsafeFromVector4Core( ReadOnlySpan sourceVectors, Span destPixels) where TPixel : struct, IPixel @@ -38,7 +102,7 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils } [MethodImpl(InliningOptions.ShortMethod)] - internal static void DangerousToVector4( + private static void UnsafeToVector4Core( ReadOnlySpan sourcePixels, Span destVectors) where TPixel : struct, IPixel @@ -55,7 +119,7 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils } [MethodImpl(InliningOptions.ShortMethod)] - internal static void DangerousFromScaledVector4( + private static void UnsafeFromScaledVector4Core( ReadOnlySpan sourceVectors, Span destinationColors) where TPixel : struct, IPixel @@ -72,7 +136,7 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils } [MethodImpl(InliningOptions.ShortMethod)] - internal static void DangerousToScaledVector4( + private static void UnsafeToScaledVector4Core( ReadOnlySpan sourceColors, Span destinationVectors) where TPixel : struct, IPixel diff --git a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs index 006ebe828..efe4dc69a 100644 --- a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs +++ b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs @@ -7,6 +7,8 @@ using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using SixLabors.ImageSharp.ColorSpaces.Companding; + namespace SixLabors.ImageSharp.PixelFormats.Utils { /// @@ -41,7 +43,7 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils PixelOperations pixelOperations, ReadOnlySpan sourcePixels, Span destVectors, - bool scaled) + PixelConversionModifiers modifiers) where TPixel : struct, IPixel { Guard.NotNull(configuration, nameof(configuration)); @@ -52,7 +54,7 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils // Not worth for small buffers: if (count < Vector4ConversionThreshold) { - ToVector4Fallback(sourcePixels, destVectors, scaled); + Default.UnsafeToVector4(sourcePixels, destVectors, modifiers); return; } @@ -70,6 +72,9 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils MemoryMarshal.Cast(destVectors.Slice(0, countWithoutLastItem))); destVectors[countWithoutLastItem] = sourcePixels[countWithoutLastItem].ToVector4(); + + // TODO: Investigate optimized 1-pass approach! + ApplyForwardConversionModifiers(destVectors, modifiers); } /// @@ -83,9 +88,9 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils internal static void FromVector4( Configuration configuration, PixelOperations pixelOperations, - ReadOnlySpan sourceVectors, + Span sourceVectors, Span destPixels, - bool scaled) + PixelConversionModifiers modifiers) where TPixel : struct, IPixel { Guard.NotNull(configuration, nameof(configuration)); @@ -96,11 +101,14 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils // Not worth for small buffers: if (count < Vector4ConversionThreshold) { - FromVector4Fallback(sourceVectors, destPixels, scaled); + Default.UnsafeFromVector4(sourceVectors, destPixels, modifiers); return; } + // TODO: Investigate optimized 1-pass approach! + ApplyBackwardConversionModifiers(sourceVectors, modifiers); + // For the opposite direction it's not easy to implement the trick used in RunRgba32CompatibleToVector4Conversion, // so let's allocate a temporary buffer as usually: using (IMemoryOwner tempBuffer = configuration.MemoryAllocator.Allocate(count)) @@ -115,34 +123,6 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils } } - [MethodImpl(InliningOptions.ColdPath)] - private static void ToVector4Fallback(ReadOnlySpan sourcePixels, Span destVectors, bool scaled) - where TPixel : struct, IPixel - { - if (scaled) - { - Default.DangerousToScaledVector4(sourcePixels, destVectors); - } - else - { - Default.DangerousToVector4(sourcePixels, destVectors); - } - } - - [MethodImpl(InliningOptions.ColdPath)] - private static void FromVector4Fallback(ReadOnlySpan sourceVectors, Span destPixels, bool scaled) - where TPixel : struct, IPixel - { - if (scaled) - { - Default.DangerousFromScaledVector4(sourceVectors, destPixels); - } - else - { - Default.DangerousFromVector4(sourceVectors, destPixels); - } - } - private static int CalculateVector4ConversionThreshold() { if (!Vector.IsHardwareAccelerated) diff --git a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.cs b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.cs new file mode 100644 index 000000000..447869a7d --- /dev/null +++ b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.cs @@ -0,0 +1,48 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Numerics; +using System.Runtime.CompilerServices; + +using SixLabors.ImageSharp.ColorSpaces.Companding; + +namespace SixLabors.ImageSharp.PixelFormats.Utils +{ + internal static partial class Vector4Converters + { + /// + /// Apply modifiers used requested by ToVector4() conversion. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void ApplyForwardConversionModifiers(Span vectors, PixelConversionModifiers modifiers) + { + if (modifiers.IsDefined(PixelConversionModifiers.SRgbCompand)) + { + SRgbCompanding.Expand(vectors); + } + + if (modifiers.IsDefined(PixelConversionModifiers.Premultiply)) + { + Vector4Utils.Premultiply(vectors); + } + } + + /// + /// Apply modifiers used requested by FromVector4() conversion. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void ApplyBackwardConversionModifiers(Span vectors, PixelConversionModifiers modifiers) + { + if (modifiers.IsDefined(PixelConversionModifiers.Premultiply)) + { + Vector4Utils.UnPremultiply(vectors); + } + + if (modifiers.IsDefined(PixelConversionModifiers.SRgbCompand)) + { + SRgbCompanding.Compress(vectors); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs index 9433e19c9..f51c79034 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs @@ -148,7 +148,11 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.FromVector4(this.Configuration, s, d.GetSpan(), PixelConversionModifiers.SRgbCompand | PixelConversionModifiers.Scale) + (s, d) => Operations.FromVector4( + this.Configuration, + s, + d.GetSpan(), + PixelConversionModifiers.SRgbCompand | PixelConversionModifiers.Scale) ); } @@ -230,7 +234,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations this.Configuration, s, d.GetSpan(), - PixelConversionModifiers.SRgbCompand | PixelConversionModifiers.Premultiply) + PixelConversionModifiers.SRgbCompand | PixelConversionModifiers.Premultiply | PixelConversionModifiers.Scale) ); }