diff --git a/src/ImageSharp/Formats/Exr/ExrMetadata.cs b/src/ImageSharp/Formats/Exr/ExrMetadata.cs index 1fa724657f..22762289ce 100644 --- a/src/ImageSharp/Formats/Exr/ExrMetadata.cs +++ b/src/ImageSharp/Formats/Exr/ExrMetadata.cs @@ -95,14 +95,52 @@ public class ExrMetadata : IFormatMetadata } /// - public FormatConnectingMetadata ToFormatConnectingMetadata() => new() + public FormatConnectingMetadata ToFormatConnectingMetadata() { - EncodingType = this.Compression is ExrCompression.B44 or ExrCompression.B44A or ExrCompression.Pxr24 ? EncodingType.Lossy : EncodingType.Lossless, - PixelTypeInfo = this.GetPixelTypeInfo() - }; + EncodingType type = this.Compression is ExrCompression.B44 or ExrCompression.B44A or ExrCompression.Pxr24 + ? EncodingType.Lossy + : EncodingType.Lossless; + + return new() + { + EncodingType = type, + PixelTypeInfo = this.GetPixelTypeInfo() + }; + } /// - public static ExrMetadata FromFormatConnectingMetadata(FormatConnectingMetadata metadata) => new() { PixelType = ExrPixelType.Half }; + public static ExrMetadata FromFormatConnectingMetadata(FormatConnectingMetadata metadata) + { + PixelTypeInfo pixelTypeInfo = metadata.PixelTypeInfo; + PixelComponentInfo? info = pixelTypeInfo.ComponentInfo; + PixelColorType colorType = pixelTypeInfo.ColorType; + + int bitsPerComponent = info?.GetMaximumComponentPrecision() + ?? (pixelTypeInfo.BitsPerPixel <= 16 ? 16 : 32); + + int componentCount = info?.ComponentCount ?? 0; + ExrImageDataType imageDataType = colorType switch + { + PixelColorType.Luminance => ExrImageDataType.Gray, + PixelColorType.RGB or PixelColorType.BGR => ExrImageDataType.Rgb, + PixelColorType.RGB | PixelColorType.Alpha + or PixelColorType.BGR | PixelColorType.Alpha + or PixelColorType.Luminance | PixelColorType.Alpha => ExrImageDataType.Rgba, + _ => componentCount switch + { + >= 4 => ExrImageDataType.Rgba, + >= 3 => ExrImageDataType.Rgb, + 1 => ExrImageDataType.Gray, + _ => ExrImageDataType.Unknown, + } + }; + + return new() + { + PixelType = bitsPerComponent <= 16 ? ExrPixelType.Half : ExrPixelType.Float, + ImageDataType = imageDataType, + }; + } /// ExrMetadata IDeepCloneable.DeepClone() => new(this); diff --git a/tests/ImageSharp.Tests/Formats/Exr/ExrMetadataTests.cs b/tests/ImageSharp.Tests/Formats/Exr/ExrMetadataTests.cs index 2cbbf0ec31..7b7917dbc4 100644 --- a/tests/ImageSharp.Tests/Formats/Exr/ExrMetadataTests.cs +++ b/tests/ImageSharp.Tests/Formats/Exr/ExrMetadataTests.cs @@ -1,8 +1,10 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Formats.Exr; using SixLabors.ImageSharp.Formats.Exr.Constants; +using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Tests.Formats.Exr; @@ -85,4 +87,32 @@ public class ExrMetadataTests Assert.NotNull(metadata); Assert.Equal(expectedCompression, metadata.Compression); } + + [Theory] + [InlineData(PixelColorType.Binary, 1, ExrImageDataType.Unknown, ExrPixelType.Half)] + [InlineData(PixelColorType.Indexed, 8, ExrImageDataType.Unknown, ExrPixelType.Half)] + [InlineData(PixelColorType.Luminance, 16, ExrImageDataType.Gray, ExrPixelType.Half)] + [InlineData(PixelColorType.RGB, 48, ExrImageDataType.Rgb, ExrPixelType.Float)] + [InlineData(PixelColorType.BGR, 48, ExrImageDataType.Rgb, ExrPixelType.Float)] + [InlineData(PixelColorType.RGB | PixelColorType.Alpha, 64, ExrImageDataType.Rgba, ExrPixelType.Float)] + [InlineData(PixelColorType.BGR | PixelColorType.Alpha, 64, ExrImageDataType.Rgba, ExrPixelType.Float)] + [InlineData(PixelColorType.Luminance | PixelColorType.Alpha, 32, ExrImageDataType.Rgba, ExrPixelType.Float)] + [InlineData(PixelColorType.YCbCr, 48, ExrImageDataType.Unknown, ExrPixelType.Float)] + [InlineData(PixelColorType.CMYK, 64, ExrImageDataType.Unknown, ExrPixelType.Float)] + [InlineData(PixelColorType.YCCK, 64, ExrImageDataType.Unknown, ExrPixelType.Float)] + public void FromFormatConnectingMetadata_ConvertColorTypeAsExpected(PixelColorType pixelColorType, int bitsPerPixel, ExrImageDataType expectedImageDataType, ExrPixelType expectedPixelType) + { + FormatConnectingMetadata formatConnectingMetadata = new() + { + PixelTypeInfo = new PixelTypeInfo(bitsPerPixel) + { + ColorType = pixelColorType, + }, + }; + + ExrMetadata actual = ExrMetadata.FromFormatConnectingMetadata(formatConnectingMetadata); + + Assert.Equal(expectedImageDataType, actual.ImageDataType); + Assert.Equal(expectedPixelType, actual.PixelType); + } }