diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgb96.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgb96.cs index 405ed40a14..83333a377e 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgb96.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgb96.cs @@ -18,7 +18,9 @@ namespace SixLabors.ImageSharp.PixelFormats [StructLayout(LayoutKind.Sequential)] public partial struct Rgb96 : IPixel { - private const float Max = uint.MaxValue; + private const float InvMax = 1.0f / uint.MaxValue; + + private const double Max = uint.MaxValue; /// /// Gets or sets the red component. @@ -86,6 +88,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void FromVector4(Vector4 vector) { + vector = Numerics.Clamp(vector, Vector4.Zero, Vector4.One); this.R = (uint)(vector.X * Max); this.G = (uint)(vector.Y * Max); this.B = (uint)(vector.Z * Max); @@ -94,9 +97,9 @@ namespace SixLabors.ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public Vector4 ToVector4() => new( - this.R / Max, - this.G / Max, - this.B / Max, + this.R * InvMax, + this.G * InvMax, + this.B * InvMax, 1.0f); /// diff --git a/tests/ImageSharp.Tests/ConfigurationTests.cs b/tests/ImageSharp.Tests/ConfigurationTests.cs index 7497e1b4cc..eda8626b13 100644 --- a/tests/ImageSharp.Tests/ConfigurationTests.cs +++ b/tests/ImageSharp.Tests/ConfigurationTests.cs @@ -8,7 +8,6 @@ using Moq; using SixLabors.ImageSharp.Formats.Bmp; using SixLabors.ImageSharp.IO; using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.Tests.Memory; using Xunit; // ReSharper disable InconsistentNaming @@ -23,7 +22,7 @@ namespace SixLabors.ImageSharp.Tests public Configuration DefaultConfiguration { get; } - private readonly int expectedDefaultConfigurationCount = 8; + private readonly int expectedDefaultConfigurationCount = 9; public ConfigurationTests() { diff --git a/tests/ImageSharp.Tests/Formats/Exr/ImageExtensionsTest.cs b/tests/ImageSharp.Tests/Formats/Exr/ImageExtensionsTest.cs new file mode 100644 index 0000000000..9ff506efad --- /dev/null +++ b/tests/ImageSharp.Tests/Formats/Exr/ImageExtensionsTest.cs @@ -0,0 +1,156 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System.IO; +using System.Threading.Tasks; +using SixLabors.ImageSharp.Formats; +using SixLabors.ImageSharp.Formats.OpenExr; +using SixLabors.ImageSharp.PixelFormats; +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Formats.Exr +{ + [Trait("Format", "Exr")] + public class ImageExtensionsTest + { + [Fact] + public void SaveAsExr_Path() + { + string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensionsTest)); + string file = Path.Combine(dir, "SaveAsExr_Path.exr"); + + using (var image = new Image(10, 10)) + { + image.SaveAsOpenExr(file); + } + + using (Image.Load(file, out IImageFormat mime)) + { + Assert.Equal("image/x-exr", mime.DefaultMimeType); + } + } + + [Fact] + public async Task SaveAsExrAsync_Path() + { + string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensionsTest)); + string file = Path.Combine(dir, "SaveAsExrAsync_Path.exr"); + + using (var image = new Image(10, 10)) + { + await image.SaveAsOpenExrAsync(file); + } + + using (Image.Load(file, out IImageFormat mime)) + { + Assert.Equal("image/x-exr", mime.DefaultMimeType); + } + } + + [Fact] + public void SaveAsExr_Path_Encoder() + { + string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensions)); + string file = Path.Combine(dir, "SaveAsExr_Path_Encoder.exr"); + + using (var image = new Image(10, 10)) + { + image.SaveAsOpenExr(file, new ExrEncoder()); + } + + using (Image.Load(file, out IImageFormat mime)) + { + Assert.Equal("image/x-exr", mime.DefaultMimeType); + } + } + + [Fact] + public async Task SaveAsExrAsync_Path_Encoder() + { + string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensions)); + string file = Path.Combine(dir, "SaveAsExrAsync_Path_Encoder.tiff"); + + using (var image = new Image(10, 10)) + { + await image.SaveAsOpenExrAsync(file, new ExrEncoder()); + } + + using (Image.Load(file, out IImageFormat mime)) + { + Assert.Equal("image/x-exr", mime.DefaultMimeType); + } + } + + [Fact] + public void SaveAsExr_Stream() + { + using var memoryStream = new MemoryStream(); + + using (var image = new Image(10, 10)) + { + image.SaveAsOpenExr(memoryStream); + } + + memoryStream.Position = 0; + + using (Image.Load(memoryStream, out IImageFormat mime)) + { + Assert.Equal("image/x-exr", mime.DefaultMimeType); + } + } + + [Fact] + public async Task SaveAsExrAsync_StreamAsync() + { + using var memoryStream = new MemoryStream(); + + using (var image = new Image(10, 10)) + { + await image.SaveAsOpenExrAsync(memoryStream); + } + + memoryStream.Position = 0; + + using (Image.Load(memoryStream, out IImageFormat mime)) + { + Assert.Equal("image/x-exr", mime.DefaultMimeType); + } + } + + [Fact] + public void SaveAsExr_Stream_Encoder() + { + using var memoryStream = new MemoryStream(); + + using (var image = new Image(10, 10)) + { + image.SaveAsOpenExr(memoryStream, new ExrEncoder()); + } + + memoryStream.Position = 0; + + using (Image.Load(memoryStream, out IImageFormat mime)) + { + Assert.Equal("image/x-exr", mime.DefaultMimeType); + } + } + + [Fact] + public async Task SaveAsExrAsync_Stream_Encoder() + { + using var memoryStream = new MemoryStream(); + + using (var image = new Image(10, 10)) + { + await image.SaveAsOpenExrAsync(memoryStream, new ExrEncoder()); + } + + memoryStream.Position = 0; + + using (Image.Load(memoryStream, out IImageFormat mime)) + { + Assert.Equal("image/x-exr", mime.DefaultMimeType); + } + } + } +} diff --git a/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs b/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs index 5a8425c1fe..7686f77d95 100644 --- a/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs +++ b/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs @@ -85,11 +85,11 @@ namespace SixLabors.ImageSharp.Tests.Formats public static readonly TheoryData QuantizerNames = new() { - nameof(KnownQuantizers.Octree), - nameof(KnownQuantizers.WebSafe), - nameof(KnownQuantizers.Werner), - nameof(KnownQuantizers.Wu) - }; + nameof(KnownQuantizers.Octree), + nameof(KnownQuantizers.WebSafe), + nameof(KnownQuantizers.Werner), + nameof(KnownQuantizers.Wu) + }; [Theory] [WithFile(TestImages.Png.CalliphoraPartial, nameof(QuantizerNames), PixelTypes.Rgba32)] @@ -156,6 +156,11 @@ namespace SixLabors.ImageSharp.Tests.Formats { image.SaveAsTiff(output); } + + using (FileStream output = File.OpenWrite(Path.Combine(path, $"{file.FileNameWithoutExtension}.exr"))) + { + image.SaveAsOpenExr(output); + } } } } @@ -210,6 +215,9 @@ namespace SixLabors.ImageSharp.Tests.Formats [InlineData(100, 100, "tiff")] [InlineData(100, 10, "tiff")] [InlineData(10, 100, "tiff")] + [InlineData(100, 100, "exr")] + [InlineData(100, 10, "exr")] + [InlineData(10, 100, "exr")] public void CanIdentifyImageLoadedFromBytes(int width, int height, string extension) {