From 8c0c85442cec2a1753335e897151109b625b02be Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Fri, 27 Mar 2026 19:20:53 +0100 Subject: [PATCH] Set exr pixel type when decoding an image --- src/ImageSharp/Formats/Exr/ExrDecoderCore.cs | 18 +++++++++++++--- src/ImageSharp/Formats/Exr/ExrMetadata.cs | 14 ++++++------- .../Formats/Exr/ExrDecoderTests.cs | 21 +++++++++++++++++++ 3 files changed, 43 insertions(+), 10 deletions(-) diff --git a/src/ImageSharp/Formats/Exr/ExrDecoderCore.cs b/src/ImageSharp/Formats/Exr/ExrDecoderCore.cs index 4f3f113536..9cff42a4e0 100644 --- a/src/ImageSharp/Formats/Exr/ExrDecoderCore.cs +++ b/src/ImageSharp/Formats/Exr/ExrDecoderCore.cs @@ -43,6 +43,11 @@ internal sealed class ExrDecoderCore : ImageDecoderCore /// private ImageMetadata metadata; + /// + /// The exr specific metadata. + /// + private ExrMetadata exrMetadata; + /// /// Initializes a new instance of the class. /// @@ -74,6 +79,11 @@ internal sealed class ExrDecoderCore : ImageDecoderCore /// private ExrCompression Compression { get; set; } + /// + /// Gets or sets the pixel type. + /// + private ExrPixelType PixelType { get; set; } + /// /// Gets or sets the header attributes. /// @@ -88,12 +98,10 @@ internal sealed class ExrDecoderCore : ImageDecoderCore ExrThrowHelper.ThrowNotSupported($"Compression {this.Compression} is not yet supported"); } - ExrPixelType pixelType = this.ValidateChannels(); - Image image = new(this.configuration, this.Width, this.Height, this.metadata); Buffer2D pixels = image.GetRootFramePixelBuffer(); - switch (pixelType) + switch (this.PixelType) { case ExrPixelType.Half: case ExrPixelType.Float: @@ -422,9 +430,13 @@ internal sealed class ExrDecoderCore : ImageDecoderCore this.Height = this.HeaderAttributes.DataWindow.YMax - this.HeaderAttributes.DataWindow.YMin + 1; this.Channels = this.HeaderAttributes.Channels; this.Compression = this.HeaderAttributes.Compression; + this.PixelType = this.ValidateChannels(); this.metadata = new ImageMetadata(); + this.exrMetadata = this.metadata.GetExrMetadata(); + this.exrMetadata.PixelType = this.PixelType; + return this.HeaderAttributes; } diff --git a/src/ImageSharp/Formats/Exr/ExrMetadata.cs b/src/ImageSharp/Formats/Exr/ExrMetadata.cs index 32b9ef3c55..b32da8f038 100644 --- a/src/ImageSharp/Formats/Exr/ExrMetadata.cs +++ b/src/ImageSharp/Formats/Exr/ExrMetadata.cs @@ -28,24 +28,24 @@ public class ExrMetadata : IFormatMetadata /// /// Gets or sets the pixel format. /// - public ExrPixelType PixelType { get; set; } = ExrPixelType.Float; - - /// - public static ExrMetadata FromFormatConnectingMetadata(FormatConnectingMetadata metadata) => throw new NotImplementedException(); + public ExrPixelType PixelType { get; set; } = ExrPixelType.Half; /// public void AfterImageApply(Image destination, Matrix4x4 matrix) where TPixel : unmanaged, IPixel => throw new NotImplementedException(); - /// - public IDeepCloneable DeepClone() => new ExrMetadata(this); - /// public PixelTypeInfo GetPixelTypeInfo() => throw new NotImplementedException(); /// public FormatConnectingMetadata ToFormatConnectingMetadata() => throw new NotImplementedException(); + /// + public static ExrMetadata FromFormatConnectingMetadata(FormatConnectingMetadata metadata) => throw new NotImplementedException(); + /// ExrMetadata IDeepCloneable.DeepClone() => throw new NotImplementedException(); + + /// + public IDeepCloneable DeepClone() => new ExrMetadata(this); } diff --git a/tests/ImageSharp.Tests/Formats/Exr/ExrDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Exr/ExrDecoderTests.cs index 34cad442f1..0077523ad2 100644 --- a/tests/ImageSharp.Tests/Formats/Exr/ExrDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Exr/ExrDecoderTests.cs @@ -2,6 +2,7 @@ // Licensed under the Six Labors Split License. using SixLabors.ImageSharp.Formats.Exr; +using SixLabors.ImageSharp.Formats.Exr.Constants; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; using SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs; @@ -21,19 +22,35 @@ public class ExrDecoderTests TestFile testFile = TestFile.Create(imagePath); using MemoryStream stream = new(testFile.Bytes, false); ImageInfo imageInfo = Image.Identify(stream); + Assert.NotNull(imageInfo); Assert.Equal(expectedWidth, imageInfo.Width); Assert.Equal(expectedHeight, imageInfo.Height); } + [Theory] + [InlineData(TestImages.Exr.Uncompressed)] + public void ExrDecoder_Identify_DetectsCorrectPixelType(string imagePath) + { + TestFile testFile = TestFile.Create(imagePath); + using MemoryStream stream = new(testFile.Bytes, false); + ImageInfo imageInfo = Image.Identify(stream); + ExrMetadata exrMetaData = imageInfo.Metadata.GetExrMetadata(); + + Assert.NotNull(imageInfo); + Assert.Equal(ExrPixelType.Float, exrMetaData.PixelType); + } + [Theory] [WithFile(TestImages.Exr.Uncompressed, PixelTypes.Rgba32)] public void ExrDecoder_CanDecode_Uncompressed_Rgba_ExrPixelType_Half(TestImageProvider provider) where TPixel : unmanaged, IPixel { using Image image = provider.GetImage(ExrDecoder.Instance); + ExrMetadata exrMetaData = image.Metadata.GetExrMetadata(); image.DebugSave(provider); image.CompareToOriginal(provider, ImageComparer.Exact, ReferenceDecoder); + Assert.Equal(ExrPixelType.Half, exrMetaData.PixelType); } [Theory] @@ -42,10 +59,12 @@ public class ExrDecoderTests where TPixel : unmanaged, IPixel { using Image image = provider.GetImage(ExrDecoder.Instance); + ExrMetadata exrMetaData = image.Metadata.GetExrMetadata(); image.DebugSave(provider); // There is a 0,0059% difference to the Reference decoder. image.CompareToOriginal(provider, ImageComparer.Tolerant(0.0005f), ReferenceDecoder); + Assert.Equal(ExrPixelType.Float, exrMetaData.PixelType); } [Theory] @@ -54,10 +73,12 @@ public class ExrDecoderTests where TPixel : unmanaged, IPixel { using Image image = provider.GetImage(ExrDecoder.Instance); + ExrMetadata exrMetaData = image.Metadata.GetExrMetadata(); image.DebugSave(provider); // Compare to referene output, since the reference decoder does not support this pixel type. image.CompareToReferenceOutput(provider); + Assert.Equal(ExrPixelType.UnsignedInt, exrMetaData.PixelType); } [Theory]