From f8c8174b575fedf89e1e2924a8d187794137125b Mon Sep 17 00:00:00 2001 From: Socolin Date: Fri, 19 Dec 2025 00:09:45 -0500 Subject: [PATCH] Rework ApplyIccProfile to use ProcessPixelRowsAsVector4 --- src/ImageSharp/Formats/Png/PngDecoderCore.cs | 54 +++++++------------- 1 file changed, 18 insertions(+), 36 deletions(-) diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs index f7eb0de1f..2a2b07389 100644 --- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs @@ -26,6 +26,7 @@ using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.Metadata.Profiles.Icc; using SixLabors.ImageSharp.Metadata.Profiles.Xmp; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; namespace SixLabors.ImageSharp.Formats.Png; @@ -328,7 +329,7 @@ internal sealed class PngDecoderCore : ImageDecoderCore if (this.Options.TryGetIccProfileForColorConversion(metadata.IccProfile, out IccProfile? iccProfile)) { - ApplyIccProfile(image, iccProfile, CompactSrgbV4Profile.Profile); + ApplyRgbaCompatibleIccProfile(image, iccProfile, CompactSrgbV4Profile.Profile); } return image; @@ -2162,8 +2163,7 @@ internal sealed class PngDecoderCore : ImageDecoderCore private void SwapScanlineBuffers() => (this.scanline, this.previousScanline) = (this.previousScanline, this.scanline); - // FIXME: Maybe this could be a .Mutate(x => x.ApplyIccProfile(destinationProfile)) ? Nothing related to png here - private static void ApplyIccProfile(Image image, IccProfile sourceProfile, IccProfile destinationProfile) + private static void ApplyRgbaCompatibleIccProfile(Image image, IccProfile sourceProfile, IccProfile destinationProfile) where TPixel : unmanaged, IPixel { ColorConversionOptions options = new() @@ -2174,45 +2174,27 @@ internal sealed class PngDecoderCore : ImageDecoderCore ColorProfileConverter converter = new(options); - image.ProcessPixelRows(pixelAccessor => - { - using IMemoryOwner rgbBuffer = image.Configuration.MemoryAllocator.Allocate(pixelAccessor.Width * 3); - using IMemoryOwner alphaBuffer = image.Configuration.MemoryAllocator.Allocate(pixelAccessor.Width); - Span rgbPacked = rgbBuffer.Memory.Span; - ref float rgbPackedRef = ref MemoryMarshal.GetReference(rgbPacked); - Span alphaPacked = alphaBuffer.Memory.Span; - ref float alphaPackedRef = ref MemoryMarshal.GetReference(alphaPacked); - - for (int y = 0; y < pixelAccessor.Height; y++) + image.Mutate(o => o.ProcessPixelRowsAsVector4((pixelsRow, _) => { - Span pixelsRow = pixelAccessor.GetRowSpan(y); - int rgbIdx = 0; - for (int x = 0; x < pixelsRow.Length; x++, rgbIdx += 3) + using IMemoryOwner rgbBuffer = image.Configuration.MemoryAllocator.Allocate(pixelsRow.Length); + Span rgbPacked = rgbBuffer.Memory.Span; + ref Rgb rgbPackedRef = ref MemoryMarshal.GetReference(rgbPacked); + + for (int x = 0; x < pixelsRow.Length; x++) { - Vector4 rgba = pixelsRow[x].ToScaledVector4(); - Unsafe.Add(ref rgbPackedRef, rgbIdx) = rgba.X; - Unsafe.Add(ref rgbPackedRef, rgbIdx + 1) = rgba.Y; - Unsafe.Add(ref rgbPackedRef, rgbIdx + 2) = rgba.Z; - Unsafe.Add(ref alphaPackedRef, x) = rgba.W; + Unsafe.Add(ref rgbPackedRef, x) = Rgb.FromScaledVector4(pixelsRow[x]); } - Span source = MemoryMarshal.Cast(rgbPacked); - Span destination = MemoryMarshal.Cast(rgbPacked); - converter.Convert(source, destination); + converter.Convert(rgbPacked, rgbPacked); - rgbIdx = 0; - for (int x = 0; x < pixelsRow.Length; x++, rgbIdx += 3) - { - float r = Unsafe.Add(ref rgbPackedRef, rgbIdx); - float g = Unsafe.Add(ref rgbPackedRef, rgbIdx + 1); - float b = Unsafe.Add(ref rgbPackedRef, rgbIdx + 2); - float a = Unsafe.Add(ref alphaPackedRef, x); + Span pixelsRowAsFloats = MemoryMarshal.Cast(pixelsRow); + ref float pixelsRowAsFloatsRef = ref MemoryMarshal.GetReference(pixelsRowAsFloats); - pixelsRow[x] = TPixel.FromScaledVector4(new Vector4(r, g, b, a)); + int cIdx = 0; + for (int x = 0; x < pixelsRow.Length; x++, cIdx += 4) + { + Unsafe.As(ref Unsafe.Add(ref pixelsRowAsFloatsRef, cIdx)) = rgbPacked[x]; } - } - } - ); + })); } - }