diff --git a/src/ImageSharp/Formats/WebP/Lossless/LosslessUtils.cs b/src/ImageSharp/Formats/WebP/Lossless/LosslessUtils.cs index 523b0d804b..53decbab6f 100644 --- a/src/ImageSharp/Formats/WebP/Lossless/LosslessUtils.cs +++ b/src/ImageSharp/Formats/WebP/Lossless/LosslessUtils.cs @@ -103,7 +103,29 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossless public static void AddGreenToBlueAndRed(Span pixelData) { #if SUPPORTS_RUNTIME_INTRINSICS - if (Sse.IsSupported) + if (Ssse3.IsSupported) + { + var mask = Vector128.Create(1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13, 255); + int numPixels = pixelData.Length; + int i; + fixed (uint* p = pixelData) + { + for (i = 0; i + 4 <= numPixels; i += 4) + { + var idx = p + i; + Vector128 input = Sse2.LoadVector128((ushort*)idx).AsByte(); + Vector128 in0g0g = Ssse3.Shuffle(input, mask); + Vector128 output = Sse2.Add(input, in0g0g); + Sse2.Store((byte*)idx, output.AsByte()); + } + + if (i != numPixels) + { + AddGreenToBlueAndRedNoneVectorized(pixelData.Slice(i)); + } + } + } + else if (Sse.IsSupported) { var mask = SimdUtils.Shuffle.MmShuffle(2, 2, 0, 0); int numPixels = pixelData.Length; @@ -123,18 +145,18 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossless if (i != numPixels) { - AddGreenToBlueAndRedSequential(pixelData.Slice(i)); + AddGreenToBlueAndRedNoneVectorized(pixelData.Slice(i)); } } } else #endif { - AddGreenToBlueAndRedSequential(pixelData); + AddGreenToBlueAndRedNoneVectorized(pixelData); } } - private static void AddGreenToBlueAndRedSequential(Span pixelData) + private static void AddGreenToBlueAndRedNoneVectorized(Span pixelData) { int numPixels = pixelData.Length; for (int i = 0; i < numPixels; i++) @@ -151,7 +173,29 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossless public static void SubtractGreenFromBlueAndRed(Span pixelData) { #if SUPPORTS_RUNTIME_INTRINSICS - if (Sse.IsSupported) + if (Ssse3.IsSupported) + { + var mask = Vector128.Create(1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13, 255); + int numPixels = pixelData.Length; + int i; + fixed (uint* p = pixelData) + { + for (i = 0; i + 4 <= numPixels; i += 4) + { + var idx = p + i; + Vector128 input = Sse2.LoadVector128((ushort*)idx).AsByte(); + Vector128 in0g0g = Ssse3.Shuffle(input, mask); + Vector128 output = Sse2.Subtract(input, in0g0g); + Sse2.Store((byte*)idx, output.AsByte()); + } + + if (i != numPixels) + { + SubtractGreenFromBlueAndRedNoneVectorized(pixelData.Slice(i)); + } + } + } + else if (Sse.IsSupported) { var mask = SimdUtils.Shuffle.MmShuffle(2, 2, 0, 0); int numPixels = pixelData.Length; @@ -171,18 +215,18 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossless if (i != numPixels) { - SubtractGreenFromBlueAndRedSequential(pixelData.Slice(i)); + SubtractGreenFromBlueAndRedNoneVectorized(pixelData.Slice(i)); } } } else #endif { - SubtractGreenFromBlueAndRedSequential(pixelData); + SubtractGreenFromBlueAndRedNoneVectorized(pixelData); } } - private static void SubtractGreenFromBlueAndRedSequential(Span pixelData) + private static void SubtractGreenFromBlueAndRedNoneVectorized(Span pixelData) { int numPixels = pixelData.Length; for (int i = 0; i < numPixels; i++)