Browse Source

Merge pull request #3105 from SixLabors/js/fix-3104

Fix JPEG SIMD slicing and padding length handling.
pull/3107/head
James Jackson-South 3 months ago
committed by GitHub
parent
commit
043ee2b325
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 14
      src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs
  2. 6
      src/ImageSharp/Formats/Jpeg/Components/Encoder/SpectralConverter{TPixel}.cs

14
src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs

@ -752,7 +752,7 @@ internal static partial class SimdUtils
/// Implementation is based on MagicScaler code: /// Implementation is based on MagicScaler code:
/// https://github.com/saucecontrol/PhotoSauce/blob/b5811908041200488aa18fdfd17df5fc457415dc/src/MagicScaler/Magic/Processors/ConvertersFloat.cs#L80-L182 /// https://github.com/saucecontrol/PhotoSauce/blob/b5811908041200488aa18fdfd17df5fc457415dc/src/MagicScaler/Magic/Processors/ConvertersFloat.cs#L80-L182
/// </remarks> /// </remarks>
internal static unsafe void ByteToNormalizedFloat( internal static void ByteToNormalizedFloat(
ReadOnlySpan<byte> source, ReadOnlySpan<byte> source,
Span<float> destination) Span<float> destination)
{ {
@ -1172,8 +1172,10 @@ internal static partial class SimdUtils
Vector256<byte> rgb, rg, bx; Vector256<byte> rgb, rg, bx;
Vector256<float> r, g, b; Vector256<float> r, g, b;
// Each iteration consumes 8 Rgb24 pixels (24 bytes) but starts with a 32-byte load,
// so we need 3 extra pixels of addressable slack beyond the vectorized chunk.
const int bytesPerRgbStride = 24; const int bytesPerRgbStride = 24;
nuint count = (uint)source.Length / 8; nuint count = source.Length > 3 ? (uint)(source.Length - 3) / 8 : 0;
for (nuint i = 0; i < count; i++) for (nuint i = 0; i < count; i++)
{ {
rgb = Avx2.PermuteVar8x32(Unsafe.AddByteOffset(ref rgbByteSpan, (uint)(bytesPerRgbStride * i)).AsUInt32(), extractToLanesMask).AsByte(); rgb = Avx2.PermuteVar8x32(Unsafe.AddByteOffset(ref rgbByteSpan, (uint)(bytesPerRgbStride * i)).AsUInt32(), extractToLanesMask).AsByte();
@ -1193,10 +1195,10 @@ internal static partial class SimdUtils
} }
int sliceCount = (int)(count * 8); int sliceCount = (int)(count * 8);
redChannel = redChannel.Slice(sliceCount); redChannel = redChannel[sliceCount..];
greenChannel = greenChannel.Slice(sliceCount); greenChannel = greenChannel[sliceCount..];
blueChannel = blueChannel.Slice(sliceCount); blueChannel = blueChannel[sliceCount..];
source = source.Slice(sliceCount); source = source[sliceCount..];
} }
} }
} }

6
src/ImageSharp/Formats/Jpeg/Components/Encoder/SpectralConverter{TPixel}.cs

@ -114,9 +114,9 @@ internal class SpectralConverter<TPixel> : SpectralConverter, IDisposable
Span<TPixel> sourceRow = this.pixelBuffer.DangerousGetRowSpan(srcIndex); Span<TPixel> sourceRow = this.pixelBuffer.DangerousGetRowSpan(srcIndex);
PixelOperations<TPixel>.Instance.UnpackIntoRgbPlanes(rLane, gLane, bLane, sourceRow); PixelOperations<TPixel>.Instance.UnpackIntoRgbPlanes(rLane, gLane, bLane, sourceRow);
rLane.Slice(paddingStartIndex).Fill(rLane[paddingStartIndex - 1]); rLane.Slice(paddingStartIndex, paddedPixelsCount).Fill(rLane[paddingStartIndex - 1]);
gLane.Slice(paddingStartIndex).Fill(gLane[paddingStartIndex - 1]); gLane.Slice(paddingStartIndex, paddedPixelsCount).Fill(gLane[paddingStartIndex - 1]);
bLane.Slice(paddingStartIndex).Fill(bLane[paddingStartIndex - 1]); bLane.Slice(paddingStartIndex, paddedPixelsCount).Fill(bLane[paddingStartIndex - 1]);
// Convert from rgb24 to target pixel type // Convert from rgb24 to target pixel type
JpegColorConverterBase.ComponentValues values = new(this.componentProcessors, y); JpegColorConverterBase.ComponentValues values = new(this.componentProcessors, y);

Loading…
Cancel
Save