Browse Source

Set exr pixel type when decoding an image

pull/3096/head
Brian Popow 2 months ago
parent
commit
8c0c85442c
  1. 18
      src/ImageSharp/Formats/Exr/ExrDecoderCore.cs
  2. 14
      src/ImageSharp/Formats/Exr/ExrMetadata.cs
  3. 21
      tests/ImageSharp.Tests/Formats/Exr/ExrDecoderTests.cs

18
src/ImageSharp/Formats/Exr/ExrDecoderCore.cs

@ -43,6 +43,11 @@ internal sealed class ExrDecoderCore : ImageDecoderCore
/// </summary>
private ImageMetadata metadata;
/// <summary>
/// The exr specific metadata.
/// </summary>
private ExrMetadata exrMetadata;
/// <summary>
/// Initializes a new instance of the <see cref="ExrDecoderCore"/> class.
/// </summary>
@ -74,6 +79,11 @@ internal sealed class ExrDecoderCore : ImageDecoderCore
/// </summary>
private ExrCompression Compression { get; set; }
/// <summary>
/// Gets or sets the pixel type.
/// </summary>
private ExrPixelType PixelType { get; set; }
/// <summary>
/// Gets or sets the header attributes.
/// </summary>
@ -88,12 +98,10 @@ internal sealed class ExrDecoderCore : ImageDecoderCore
ExrThrowHelper.ThrowNotSupported($"Compression {this.Compression} is not yet supported");
}
ExrPixelType pixelType = this.ValidateChannels();
Image<TPixel> image = new(this.configuration, this.Width, this.Height, this.metadata);
Buffer2D<TPixel> 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;
}

14
src/ImageSharp/Formats/Exr/ExrMetadata.cs

@ -28,24 +28,24 @@ public class ExrMetadata : IFormatMetadata<ExrMetadata>
/// <summary>
/// Gets or sets the pixel format.
/// </summary>
public ExrPixelType PixelType { get; set; } = ExrPixelType.Float;
/// <inheritdoc/>
public static ExrMetadata FromFormatConnectingMetadata(FormatConnectingMetadata metadata) => throw new NotImplementedException();
public ExrPixelType PixelType { get; set; } = ExrPixelType.Half;
/// <inheritdoc/>
public void AfterImageApply<TPixel>(Image<TPixel> destination, Matrix4x4 matrix)
where TPixel : unmanaged, IPixel<TPixel> => throw new NotImplementedException();
/// <inheritdoc/>
public IDeepCloneable DeepClone() => new ExrMetadata(this);
/// <inheritdoc/>
public PixelTypeInfo GetPixelTypeInfo() => throw new NotImplementedException();
/// <inheritdoc/>
public FormatConnectingMetadata ToFormatConnectingMetadata() => throw new NotImplementedException();
/// <inheritdoc/>
public static ExrMetadata FromFormatConnectingMetadata(FormatConnectingMetadata metadata) => throw new NotImplementedException();
/// <inheritdoc/>
ExrMetadata IDeepCloneable<ExrMetadata>.DeepClone() => throw new NotImplementedException();
/// <inheritdoc/>
public IDeepCloneable DeepClone() => new ExrMetadata(this);
}

21
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<TPixel>(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<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using Image<TPixel> 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<TPixel>
{
using Image<TPixel> 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<TPixel>
{
using Image<TPixel> 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]

Loading…
Cancel
Save