diff --git a/ImageSharp.sln b/ImageSharp.sln
index 7ccd92c07d..13dd2fba7e 100644
--- a/ImageSharp.sln
+++ b/ImageSharp.sln
@@ -37,8 +37,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{815C0625-CD3
ProjectSection(SolutionItems) = preProject
src\Directory.Build.props = src\Directory.Build.props
src\Directory.Build.targets = src\Directory.Build.targets
- src\README.md = src\README.md
src\ImageSharp.ruleset = src\ImageSharp.ruleset
+ src\README.md = src\README.md
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageSharp", "src\ImageSharp\ImageSharp.csproj", "{2AA31A1F-142C-43F4-8687-09ABCA4B3A26}"
@@ -215,6 +215,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "issues", "issues", "{5C9B68
ProjectSection(SolutionItems) = preProject
tests\Images\Input\Jpg\issues\issue-1076-invalid-subsampling.jpg = tests\Images\Input\Jpg\issues\issue-1076-invalid-subsampling.jpg
tests\Images\Input\Jpg\issues\issue-1221-identify-multi-frame.jpg = tests\Images\Input\Jpg\issues\issue-1221-identify-multi-frame.jpg
+ tests\Images\Input\Jpg\issues\issue-2067-comment.jpg = tests\Images\Input\Jpg\issues\issue-2067-comment.jpg
tests\Images\Input\Jpg\issues\issue1006-incorrect-resize.jpg = tests\Images\Input\Jpg\issues\issue1006-incorrect-resize.jpg
tests\Images\Input\Jpg\issues\issue1049-exif-resize.jpg = tests\Images\Input\Jpg\issues\issue1049-exif-resize.jpg
tests\Images\Input\Jpg\issues\Issue159-MissingFF00-Progressive-Bedroom.jpg = tests\Images\Input\Jpg\issues\Issue159-MissingFF00-Progressive-Bedroom.jpg
@@ -238,7 +239,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "issues", "issues", "{5C9B68
tests\Images\Input\Jpg\issues\issue750-exif-tranform.jpg = tests\Images\Input\Jpg\issues\issue750-exif-tranform.jpg
tests\Images\Input\Jpg\issues\Issue845-Incorrect-Quality99.jpg = tests\Images\Input\Jpg\issues\Issue845-Incorrect-Quality99.jpg
tests\Images\Input\Jpg\issues\issue855-incorrect-colorspace.jpg = tests\Images\Input\Jpg\issues\issue855-incorrect-colorspace.jpg
- tests\Images\Input\Jpg\issues\issue-2067-comment.jpg = tests\Images\Input\Jpg\issues\issue-2067-comment.jpg
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "fuzz", "fuzz", "{516A3532-6AC2-417B-AD79-9BD5D0D378A0}"
diff --git a/src/ImageSharp/Configuration.cs b/src/ImageSharp/Configuration.cs
index abcbcb58f8..7a2374fb6a 100644
--- a/src/ImageSharp/Configuration.cs
+++ b/src/ImageSharp/Configuration.cs
@@ -226,7 +226,7 @@ public sealed class Configuration
new TgaConfigurationModule(),
new TiffConfigurationModule(),
new WebpConfigurationModule(),
- new ExrConfigurationModule());
+ new ExrConfigurationModule(),
new QoiConfigurationModule(),
new IcoConfigurationModule(),
new CurConfigurationModule());
diff --git a/src/ImageSharp/Formats/OpenExr/Compression/Decompressors/ZipExrCompression.cs b/src/ImageSharp/Formats/OpenExr/Compression/Decompressors/ZipExrCompression.cs
index e315af8e8f..1797bd44b3 100644
--- a/src/ImageSharp/Formats/OpenExr/Compression/Decompressors/ZipExrCompression.cs
+++ b/src/ImageSharp/Formats/OpenExr/Compression/Decompressors/ZipExrCompression.cs
@@ -29,7 +29,7 @@ internal class ZipExrCompression : ExrBaseDecompressor
return left > 0 ? left : 0;
});
inflateStream.AllocateNewBytes((int)this.UncompressedBytes, true);
- DeflateStream dataStream = inflateStream.CompressedStream;
+ DeflateStream dataStream = inflateStream.CompressedStream!;
int totalRead = 0;
while (totalRead < buffer.Length)
diff --git a/src/ImageSharp/Formats/OpenExr/ExrConfigurationModule.cs b/src/ImageSharp/Formats/OpenExr/ExrConfigurationModule.cs
index 0b0058805d..c0322728aa 100644
--- a/src/ImageSharp/Formats/OpenExr/ExrConfigurationModule.cs
+++ b/src/ImageSharp/Formats/OpenExr/ExrConfigurationModule.cs
@@ -6,13 +6,13 @@ namespace SixLabors.ImageSharp.Formats.OpenExr;
///
/// Registers the image encoders, decoders and mime type detectors for the OpenExr format.
///
-public sealed class ExrConfigurationModule : IConfigurationModule
+public sealed class ExrConfigurationModule : IImageFormatConfigurationModule
{
///
public void Configure(Configuration configuration)
{
configuration.ImageFormatsManager.SetEncoder(ExrFormat.Instance, new ExrEncoder());
- configuration.ImageFormatsManager.SetDecoder(ExrFormat.Instance, new ExrDecoder());
+ configuration.ImageFormatsManager.SetDecoder(ExrFormat.Instance, ExrDecoder.Instance);
configuration.ImageFormatsManager.AddImageFormatDetector(new ExrImageFormatDetector());
}
}
diff --git a/src/ImageSharp/Formats/OpenExr/ExrDecoder.cs b/src/ImageSharp/Formats/OpenExr/ExrDecoder.cs
index dcbe80c277..84d441eb72 100644
--- a/src/ImageSharp/Formats/OpenExr/ExrDecoder.cs
+++ b/src/ImageSharp/Formats/OpenExr/ExrDecoder.cs
@@ -8,39 +8,41 @@ namespace SixLabors.ImageSharp.Formats.OpenExr;
///
/// Image decoder for generating an image out of a OpenExr stream.
///
-public class ExrDecoder : IImageDecoderSpecialized
+public class ExrDecoder : ImageDecoder
{
+ private ExrDecoder()
+ {
+ }
+
+ ///
+ /// Gets the shared instance.
+ ///
+ public static ExrDecoder Instance { get; } = new();
+
///
- IImageInfo IImageInfoDetector.Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken)
+ protected override ImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken)
{
Guard.NotNull(options, nameof(options));
Guard.NotNull(stream, nameof(stream));
- return new ExrDecoderCore(new() { GeneralOptions = options }).Identify(options.Configuration, stream, cancellationToken);
+ return new ExrDecoderCore(new ExrDecoderOptions { GeneralOptions = options }).Identify(options.Configuration, stream, cancellationToken);
}
- ///
- Image IImageDecoder.Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken)
- => ((IImageDecoderSpecialized)this).Decode(new() { GeneralOptions = options }, stream, cancellationToken);
-
- ///
- Image IImageDecoder.Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken)
- => ((IImageDecoderSpecialized)this).Decode(new() { GeneralOptions = options }, stream, cancellationToken);
-
- ///
- Image IImageDecoderSpecialized.Decode(ExrDecoderOptions options, Stream stream, CancellationToken cancellationToken)
+ ////
+ protected override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken)
{
Guard.NotNull(options, nameof(options));
Guard.NotNull(stream, nameof(stream));
- Image image = new ExrDecoderCore(options).Decode(options.GeneralOptions.Configuration, stream, cancellationToken);
+ ExrDecoderCore decoder = new(new ExrDecoderOptions { GeneralOptions = options });
+ Image image = decoder.Decode(options.Configuration, stream, cancellationToken);
- ImageDecoderUtilities.Resize(options.GeneralOptions, image);
+ ScaleToTargetSize(options, image);
return image;
}
///
- Image IImageDecoderSpecialized.Decode(ExrDecoderOptions options, Stream stream, CancellationToken cancellationToken)
- => ((IImageDecoderSpecialized)this).Decode(options, stream, cancellationToken);
+ protected override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken)
+ => this.Decode(options, stream, cancellationToken);
}
diff --git a/src/ImageSharp/Formats/OpenExr/ExrDecoderCore.cs b/src/ImageSharp/Formats/OpenExr/ExrDecoderCore.cs
index 3e554fb74d..6eaf56fde3 100644
--- a/src/ImageSharp/Formats/OpenExr/ExrDecoderCore.cs
+++ b/src/ImageSharp/Formats/OpenExr/ExrDecoderCore.cs
@@ -1,5 +1,6 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
+#nullable disable
using System.Buffers;
using System.Buffers.Binary;
@@ -16,7 +17,7 @@ namespace SixLabors.ImageSharp.Formats.OpenExr;
///
/// Performs the OpenExr decoding operation.
///
-internal sealed class ExrDecoderCore : IImageDecoderInternals
+internal sealed class ExrDecoderCore : ImageDecoderCore
{
///
/// Reusable buffer.
@@ -43,15 +44,12 @@ internal sealed class ExrDecoderCore : IImageDecoderInternals
///
/// The options.
public ExrDecoderCore(ExrDecoderOptions options)
+ : base(options.GeneralOptions)
{
- this.Options = options.GeneralOptions;
this.configuration = options.GeneralOptions.Configuration;
this.memoryAllocator = this.configuration.MemoryAllocator;
}
- ///
- public DecoderOptions Options { get; }
-
///
/// Gets the dimensions of the image.
///
@@ -84,8 +82,7 @@ internal sealed class ExrDecoderCore : IImageDecoderInternals
private ExrHeaderAttributes HeaderAttributes { get; set; }
///
- public Image Decode(BufferedReadStream stream, CancellationToken cancellationToken)
- where TPixel : unmanaged, IPixel
+ protected override Image Decode(BufferedReadStream stream, CancellationToken cancellationToken)
{
this.ReadExrHeader(stream);
if (!this.IsSupportedCompression())
@@ -162,7 +159,7 @@ internal sealed class ExrDecoderCore : IImageDecoderInternals
for (int x = 0; x < width; x++)
{
HalfVector4 pixelValue = new(redPixelData[x], greenPixelData[x], bluePixelData[x], hasAlpha ? alphaPixelData[x] : 1.0f);
- color.FromVector4(pixelValue.ToVector4());
+ TPixel.FromVector4(pixelValue.ToVector4());
pixelRow[x] = color;
}
}
@@ -219,7 +216,7 @@ internal sealed class ExrDecoderCore : IImageDecoderInternals
for (int x = 0; x < width; x++)
{
Rgba128 pixelValue = new(redPixelData[x], greenPixelData[x], bluePixelData[x], hasAlpha ? alphaPixelData[x] : uint.MaxValue);
- color.FromVector4(pixelValue.ToVector4());
+ TPixel.FromVector4(pixelValue.ToVector4());
pixelRow[x] = color;
}
}
@@ -366,13 +363,13 @@ internal sealed class ExrDecoderCore : IImageDecoderInternals
}
///
- public IImageInfo Identify(BufferedReadStream stream, CancellationToken cancellationToken)
+ protected override ImageInfo Identify(BufferedReadStream stream, CancellationToken cancellationToken)
{
ExrHeaderAttributes header = this.ReadExrHeader(stream);
int bitsPerPixel = this.CalculateBitsPerPixel();
- return new ImageInfo(new PixelTypeInfo(bitsPerPixel), this.Width, this.Height, new ImageMetadata());
+ return new ImageInfo(new Size((int)header.ScreenWindowWidth, (int)header.AspectRatio), this.metadata);
}
private int CalculateBitsPerPixel()
@@ -430,15 +427,10 @@ internal sealed class ExrDecoderCore : IImageDecoderInternals
this.HeaderAttributes = this.ParseHeaderAttributes(stream);
- if (!this.HeaderAttributes.IsValid())
- {
- ExrThrowHelper.ThrowInvalidImageHeader();
- }
-
- this.Width = this.HeaderAttributes.DataWindow.Value.XMax - this.HeaderAttributes.DataWindow.Value.XMin + 1;
- this.Height = this.HeaderAttributes.DataWindow.Value.YMax - this.HeaderAttributes.DataWindow.Value.YMin + 1;
+ this.Width = this.HeaderAttributes.DataWindow.XMax - this.HeaderAttributes.DataWindow.XMin + 1;
+ this.Height = this.HeaderAttributes.DataWindow.YMax - this.HeaderAttributes.DataWindow.YMin + 1;
this.Channels = this.HeaderAttributes.Channels;
- this.Compression = this.HeaderAttributes.Compression.GetValueOrDefault();
+ this.Compression = this.HeaderAttributes.Compression;
this.metadata = new ImageMetadata();
@@ -448,50 +440,54 @@ internal sealed class ExrDecoderCore : IImageDecoderInternals
private ExrHeaderAttributes ParseHeaderAttributes(BufferedReadStream stream)
{
ExrAttribute attribute = this.ReadAttribute(stream);
- ExrHeaderAttributes header = new();
+ IList channels = null;
+ ExrBox2i? dataWindow = null;
+ ExrCompressionType? compression = null;
+ ExrBox2i? displayWindow = null;
+ ExrLineOrder? lineOrder = null;
+ float? aspectRatio = null;
+ float? screenWindowCenterX = null;
+ float? screenWindowCenterY = null;
+ float? screenWindowWidth = null;
+ uint? tileXSize = null;
+ uint? tileYSize = null;
+ int? chunkCount = null;
while (!attribute.Equals(ExrAttribute.EmptyAttribute))
{
switch (attribute.Name)
{
case ExrConstants.AttributeNames.Channels:
- IList channels = this.ReadChannelList(stream, attribute.Length);
- header.Channels = channels;
+ channels = this.ReadChannelList(stream, attribute.Length);
break;
case ExrConstants.AttributeNames.Compression:
- header.Compression = (ExrCompressionType)stream.ReadByte();
+ compression = (ExrCompressionType)stream.ReadByte();
break;
case ExrConstants.AttributeNames.DataWindow:
- ExrBox2i dataWindow = this.ReadBoxInteger(stream);
- header.DataWindow = dataWindow;
+ dataWindow = this.ReadBoxInteger(stream);
break;
case ExrConstants.AttributeNames.DisplayWindow:
- ExrBox2i displayWindow = this.ReadBoxInteger(stream);
- header.DisplayWindow = displayWindow;
+ displayWindow = this.ReadBoxInteger(stream);
break;
case ExrConstants.AttributeNames.LineOrder:
- ExrLineOrder lineOrder = (ExrLineOrder)stream.ReadByte();
- header.LineOrder = lineOrder;
+ lineOrder = (ExrLineOrder)stream.ReadByte();
break;
case ExrConstants.AttributeNames.PixelAspectRatio:
- float aspectRatio = stream.ReadSingle(this.buffer);
- header.AspectRatio = aspectRatio;
+ aspectRatio = stream.ReadSingle(this.buffer);
break;
case ExrConstants.AttributeNames.ScreenWindowCenter:
- float screenWindowCenterX = stream.ReadSingle(this.buffer);
- float screenWindowCenterY = stream.ReadSingle(this.buffer);
- header.ScreenWindowCenter = new PointF(screenWindowCenterX, screenWindowCenterY);
+ screenWindowCenterX = stream.ReadSingle(this.buffer);
+ screenWindowCenterY = stream.ReadSingle(this.buffer);
break;
case ExrConstants.AttributeNames.ScreenWindowWidth:
- float screenWindowWidth = stream.ReadSingle(this.buffer);
- header.ScreenWindowWidth = screenWindowWidth;
+ screenWindowWidth = stream.ReadSingle(this.buffer);
break;
case ExrConstants.AttributeNames.Tiles:
- header.TileXSize = this.ReadUnsignedInteger(stream);
- header.TileYSize = this.ReadUnsignedInteger(stream);
+ tileXSize = this.ReadUnsignedInteger(stream);
+ tileYSize = this.ReadUnsignedInteger(stream);
break;
case ExrConstants.AttributeNames.ChunkCount:
- header.ChunkCount = this.ReadSignedInteger(stream);
+ chunkCount = this.ReadSignedInteger(stream);
break;
default:
// Skip unknown attribute bytes.
@@ -502,6 +498,18 @@ internal sealed class ExrDecoderCore : IImageDecoderInternals
attribute = this.ReadAttribute(stream);
}
+ ExrHeaderAttributes header = new(
+ channels,
+ compression.Value,
+ dataWindow.Value,
+ displayWindow.Value,
+ lineOrder.Value,
+ aspectRatio.Value,
+ screenWindowWidth.Value,
+ new PointF(screenWindowCenterX.Value, screenWindowCenterY.Value),
+ tileXSize,
+ tileYSize,
+ chunkCount);
return header;
}
diff --git a/src/ImageSharp/Formats/OpenExr/ExrDecoderOptions.cs b/src/ImageSharp/Formats/OpenExr/ExrDecoderOptions.cs
index f29e9cfb92..c0b419b937 100644
--- a/src/ImageSharp/Formats/OpenExr/ExrDecoderOptions.cs
+++ b/src/ImageSharp/Formats/OpenExr/ExrDecoderOptions.cs
@@ -9,5 +9,5 @@ namespace SixLabors.ImageSharp.Formats.OpenExr;
public sealed class ExrDecoderOptions : ISpecializedDecoderOptions
{
///
- public DecoderOptions GeneralOptions { get; set; } = new();
+ public DecoderOptions GeneralOptions { get; init; } = new();
}
diff --git a/src/ImageSharp/Formats/OpenExr/ExrEncoder.cs b/src/ImageSharp/Formats/OpenExr/ExrEncoder.cs
index 54145afdac..9960efd686 100644
--- a/src/ImageSharp/Formats/OpenExr/ExrEncoder.cs
+++ b/src/ImageSharp/Formats/OpenExr/ExrEncoder.cs
@@ -1,34 +1,22 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
-using SixLabors.ImageSharp.Advanced;
-using SixLabors.ImageSharp.PixelFormats;
-
namespace SixLabors.ImageSharp.Formats.OpenExr;
///
/// Image encoder for writing an image to a stream in the OpenExr Format.
///
-public sealed class ExrEncoder : IImageEncoder, IExrEncoderOptions
+public sealed class ExrEncoder : ImageEncoder
{
///
/// Gets or sets the pixel type of the image.
///
public ExrPixelType? PixelType { get; set; }
- ///
- public void Encode(Image image, Stream stream)
- where TPixel : unmanaged, IPixel
- {
- ExrEncoderCore encoder = new(this, image.GetMemoryAllocator());
- encoder.Encode(image, stream);
- }
-
- ///
- public Task EncodeAsync(Image image, Stream stream, CancellationToken cancellationToken)
- where TPixel : unmanaged, IPixel
+ ///
+ protected override void Encode(Image image, Stream stream, CancellationToken cancellationToken)
{
- ExrEncoderCore encoder = new(this, image.GetMemoryAllocator());
- return encoder.EncodeAsync(image, stream, cancellationToken);
+ ExrEncoderCore encoder = new(this, image.Configuration, image.Configuration.MemoryAllocator);
+ encoder.Encode(image, stream, cancellationToken);
}
}
diff --git a/src/ImageSharp/Formats/OpenExr/ExrEncoderCore.cs b/src/ImageSharp/Formats/OpenExr/ExrEncoderCore.cs
index 21fb0ade49..740b71e12b 100644
--- a/src/ImageSharp/Formats/OpenExr/ExrEncoderCore.cs
+++ b/src/ImageSharp/Formats/OpenExr/ExrEncoderCore.cs
@@ -5,6 +5,7 @@ using System.Buffers;
using System.Buffers.Binary;
using System.Numerics;
using System.Runtime.CompilerServices;
+using System.Threading.Channels;
using SixLabors.ImageSharp.Formats.OpenExr.Compression;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Metadata;
@@ -15,7 +16,7 @@ namespace SixLabors.ImageSharp.Formats.OpenExr;
///
/// Image encoder for writing an image to a stream in the OpenExr format.
///
-internal sealed class ExrEncoderCore : IImageEncoderInternals
+internal sealed class ExrEncoderCore
{
///
/// Reusable buffer.
@@ -27,6 +28,16 @@ internal sealed class ExrEncoderCore : IImageEncoderInternals
///
private readonly MemoryAllocator memoryAllocator;
+ ///
+ /// The global configuration.
+ ///
+ private Configuration configuration;
+
+ ///
+ /// The encoder with options.
+ ///
+ private readonly ExrEncoder encoder;
+
///
/// The pixel type of the image.
///
@@ -35,12 +46,14 @@ internal sealed class ExrEncoderCore : IImageEncoderInternals
///
/// Initializes a new instance of the class.
///
- /// The encoder options.
+ /// The encoder with options.
+ /// The configuration.
/// The memory manager.
- public ExrEncoderCore(IExrEncoderOptions options, MemoryAllocator memoryAllocator)
+ public ExrEncoderCore(ExrEncoder encoder, Configuration configuration, MemoryAllocator memoryAllocator)
{
+ this.configuration = configuration;
+ this.encoder = encoder;
this.memoryAllocator = memoryAllocator;
- this.pixelType = options.PixelType;
}
///
@@ -63,22 +76,28 @@ internal sealed class ExrEncoderCore : IImageEncoderInternals
this.pixelType ??= exrMetadata.PixelType;
int width = image.Width;
int height = image.Height;
- var header = new ExrHeaderAttributes()
- {
- Compression = ExrCompressionType.None,
- AspectRatio = 1.0f,
- DataWindow = new ExrBox2i(0, 0, width - 1, height - 1),
- DisplayWindow = new ExrBox2i(0, 0, width - 1, height - 1),
- LineOrder = ExrLineOrder.IncreasingY,
- ScreenWindowCenter = new PointF(0.0f, 0.0f),
- ScreenWindowWidth = 1,
- Channels = new List()
- {
- new(ExrConstants.ChannelNames.Blue, this.pixelType.Value, 0, 1, 1),
- new(ExrConstants.ChannelNames.Green, this.pixelType.Value, 0, 1, 1),
- new(ExrConstants.ChannelNames.Red, this.pixelType.Value, 0, 1, 1),
- }
- };
+ ExrCompressionType compression = ExrCompressionType.None;
+ float aspectRatio = 1.0f;
+ ExrBox2i dataWindow = new(0, 0, width - 1, height - 1);
+ ExrBox2i displayWindow = new(0, 0, width - 1, height - 1);
+ ExrLineOrder lineOrder = ExrLineOrder.IncreasingY;
+ PointF screenWindowCenter = new(0.0f, 0.0f);
+ int screenWindowWidth = 1;
+ List channels =
+ [
+ new(ExrConstants.ChannelNames.Blue, this.pixelType.Value, 0, 1, 1),
+ new(ExrConstants.ChannelNames.Green, this.pixelType.Value, 0, 1, 1),
+ new(ExrConstants.ChannelNames.Red, this.pixelType.Value, 0, 1, 1),
+ ];
+ ExrHeaderAttributes header = new(
+ channels,
+ compression,
+ dataWindow,
+ displayWindow,
+ lineOrder,
+ aspectRatio,
+ screenWindowWidth,
+ screenWindowCenter);
// Write magick bytes.
BinaryPrimitives.WriteInt32LittleEndian(this.buffer, ExrConstants.MagickBytes);
@@ -171,7 +190,7 @@ internal sealed class ExrEncoderCore : IImageEncoderInternals
for (int x = 0; x < width; x++)
{
Vector4 vector4 = pixelRowSpan[x].ToVector4();
- rgb.FromVector4(vector4);
+ Rgb96.FromVector4(vector4);
redBuffer[x] = rgb.R;
greenBuffer[x] = rgb.G;
@@ -193,13 +212,13 @@ internal sealed class ExrEncoderCore : IImageEncoderInternals
private void WriteHeader(Stream stream, ExrHeaderAttributes header)
{
this.WriteChannels(stream, header.Channels);
- this.WriteCompression(stream, header.Compression.Value);
- this.WriteDataWindow(stream, header.DataWindow.Value);
- this.WriteDisplayWindow(stream, header.DisplayWindow.Value);
- this.WritePixelAspectRatio(stream, header.AspectRatio.Value);
- this.WriteLineOrder(stream, header.LineOrder.Value);
- this.WriteScreenWindowCenter(stream, header.ScreenWindowCenter.Value);
- this.WriteScreenWindowWidth(stream, header.ScreenWindowWidth.Value);
+ this.WriteCompression(stream, header.Compression);
+ this.WriteDataWindow(stream, header.DataWindow);
+ this.WriteDisplayWindow(stream, header.DisplayWindow);
+ this.WritePixelAspectRatio(stream, header.AspectRatio);
+ this.WriteLineOrder(stream, header.LineOrder);
+ this.WriteScreenWindowCenter(stream, header.ScreenWindowCenter);
+ this.WriteScreenWindowWidth(stream, header.ScreenWindowWidth);
stream.WriteByte(0);
}
diff --git a/src/ImageSharp/Formats/OpenExr/ExrHeaderAttributes.cs b/src/ImageSharp/Formats/OpenExr/ExrHeaderAttributes.cs
index b3b3cdb604..4cec4fbc58 100644
--- a/src/ImageSharp/Formats/OpenExr/ExrHeaderAttributes.cs
+++ b/src/ImageSharp/Formats/OpenExr/ExrHeaderAttributes.cs
@@ -7,70 +7,51 @@ namespace SixLabors.ImageSharp.Formats.OpenExr;
internal class ExrHeaderAttributes
{
+ public ExrHeaderAttributes(
+ IList channels,
+ ExrCompressionType compression,
+ ExrBox2i dataWindow,
+ ExrBox2i displayWindow,
+ ExrLineOrder lineOrder,
+ float aspectRatio,
+ float screenWindowWidth,
+ PointF screenWindowCenter,
+ uint? tileXSize = null,
+ uint? tileYSize = null,
+ int? chunkCount = null)
+ {
+ this.Channels = channels;
+ this.Compression = compression;
+ this.DataWindow = dataWindow;
+ this.DisplayWindow = displayWindow;
+ this.LineOrder = lineOrder;
+ this.AspectRatio = aspectRatio;
+ this.ScreenWindowWidth = screenWindowWidth;
+ this.ScreenWindowCenter = screenWindowCenter;
+ this.TileXSize = tileXSize;
+ this.TileYSize = tileYSize;
+ this.ChunkCount = chunkCount;
+ }
+
public IList Channels { get; set; }
- public ExrCompressionType? Compression { get; set; }
+ public ExrCompressionType Compression { get; set; }
- public ExrBox2i? DataWindow { get; set; }
+ public ExrBox2i DataWindow { get; set; }
- public ExrBox2i? DisplayWindow { get; set; }
+ public ExrBox2i DisplayWindow { get; set; }
- public ExrLineOrder? LineOrder { get; set; }
+ public ExrLineOrder LineOrder { get; set; }
- public float? AspectRatio { get; set; }
+ public float AspectRatio { get; set; }
- public float? ScreenWindowWidth { get; set; }
+ public float ScreenWindowWidth { get; set; }
- public PointF? ScreenWindowCenter { get; set; }
+ public PointF ScreenWindowCenter { get; set; }
public uint? TileXSize { get; set; }
public uint? TileYSize { get; set; }
public int? ChunkCount { get; set; }
-
- public bool IsValid()
- {
- if (!this.Compression.HasValue)
- {
- return false;
- }
-
- if (!this.DataWindow.HasValue)
- {
- return false;
- }
-
- if (!this.DisplayWindow.HasValue)
- {
- return false;
- }
-
- if (!this.LineOrder.HasValue)
- {
- return false;
- }
-
- if (!this.AspectRatio.HasValue)
- {
- return false;
- }
-
- if (!this.ScreenWindowWidth.HasValue)
- {
- return false;
- }
-
- if (!this.ScreenWindowCenter.HasValue)
- {
- return false;
- }
-
- if (this.Channels is null)
- {
- return false;
- }
-
- return true;
- }
}
diff --git a/src/ImageSharp/Formats/OpenExr/ExrImageFormatDetector.cs b/src/ImageSharp/Formats/OpenExr/ExrImageFormatDetector.cs
index c14ab947a9..2f97e74048 100644
--- a/src/ImageSharp/Formats/OpenExr/ExrImageFormatDetector.cs
+++ b/src/ImageSharp/Formats/OpenExr/ExrImageFormatDetector.cs
@@ -2,6 +2,8 @@
// Licensed under the Six Labors Split License.
using System.Buffers.Binary;
+using System.Diagnostics.CodeAnalysis;
+using SixLabors.ImageSharp.Formats.Qoi;
namespace SixLabors.ImageSharp.Formats.OpenExr;
@@ -13,9 +15,6 @@ public sealed class ExrImageFormatDetector : IImageFormatDetector
///
public int HeaderSize => 4;
- ///
- public IImageFormat DetectFormat(ReadOnlySpan header) => this.IsSupportedFileFormat(header) ? ExrFormat.Instance : null;
-
private bool IsSupportedFileFormat(ReadOnlySpan header)
{
if (header.Length >= this.HeaderSize)
@@ -26,4 +25,11 @@ public sealed class ExrImageFormatDetector : IImageFormatDetector
return false;
}
+
+ ///
+ public bool TryDetectFormat(ReadOnlySpan header, [NotNullWhen(true)] out IImageFormat? format)
+ {
+ format = this.IsSupportedFileFormat(header) ? QoiFormat.Instance : null;
+ return format != null;
+ }
}
diff --git a/src/ImageSharp/Formats/OpenExr/ExrMetadata.cs b/src/ImageSharp/Formats/OpenExr/ExrMetadata.cs
index 8b090d6842..9cb58e9e67 100644
--- a/src/ImageSharp/Formats/OpenExr/ExrMetadata.cs
+++ b/src/ImageSharp/Formats/OpenExr/ExrMetadata.cs
@@ -1,12 +1,15 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
+using System.Numerics;
+using SixLabors.ImageSharp.PixelFormats;
+
namespace SixLabors.ImageSharp.Formats.OpenExr;
///
/// Provides OpenExr specific metadata information for the image.
///
-public class ExrMetadata : IDeepCloneable
+public class ExrMetadata : IFormatMetadata
{
///
/// Initializes a new instance of the class.
@@ -26,6 +29,17 @@ public class ExrMetadata : IDeepCloneable
///
public ExrPixelType PixelType { get; set; } = ExrPixelType.Float;
+ public static ExrMetadata FromFormatConnectingMetadata(FormatConnectingMetadata metadata) => throw new NotImplementedException();
+
+ 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();
+
+ ExrMetadata IDeepCloneable.DeepClone() => throw new NotImplementedException();
}
diff --git a/src/ImageSharp/Formats/OpenExr/MetadataExtensions.cs b/src/ImageSharp/Formats/OpenExr/MetadataExtensions.cs
deleted file mode 100644
index 2af0a57b07..0000000000
--- a/src/ImageSharp/Formats/OpenExr/MetadataExtensions.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Six Labors Split License.
-
-using SixLabors.ImageSharp.Formats.OpenExr;
-using SixLabors.ImageSharp.Metadata;
-
-namespace SixLabors.ImageSharp;
-
-///
-/// Extension methods for the type.
-///
-public static partial class MetadataExtensions
-{
- ///
- /// Gets the open exr format specific metadata for the image.
- ///
- /// The metadata this method extends.
- /// The .
- public static ExrMetadata GetExrMetadata(this ImageMetadata metadata) => metadata.GetFormatMetadata(ExrFormat.Instance);
-}
diff --git a/src/ImageSharp/Formats/_Generated/ImageExtensions.Save.cs b/src/ImageSharp/Formats/_Generated/ImageExtensions.Save.cs
index f3aaf6182b..ca4ad0e06c 100644
--- a/src/ImageSharp/Formats/_Generated/ImageExtensions.Save.cs
+++ b/src/ImageSharp/Formats/_Generated/ImageExtensions.Save.cs
@@ -7,13 +7,13 @@ using SixLabors.ImageSharp.Formats.Cur;
using SixLabors.ImageSharp.Formats.Gif;
using SixLabors.ImageSharp.Formats.Ico;
using SixLabors.ImageSharp.Formats.Jpeg;
-using SixLabors.ImageSharp.Formats.OpenExr;
using SixLabors.ImageSharp.Formats.Pbm;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.Formats.Qoi;
using SixLabors.ImageSharp.Formats.Tga;
using SixLabors.ImageSharp.Formats.Tiff;
using SixLabors.ImageSharp.Formats.Webp;
+using SixLabors.ImageSharp.Formats.OpenExr;
namespace SixLabors.ImageSharp;
@@ -1144,24 +1144,95 @@ public static partial class ImageExtensions
encoder ?? source.Configuration.ImageFormatsManager.GetEncoder(WebpFormat.Instance),
cancellationToken);
- encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(TiffFormat.Instance),
- cancellationToken);
+ ///
+ /// Saves the image to the given stream with the Exr format.
+ ///
+ /// The image this method extends.
+ /// The file path to save the image to.
+ /// Thrown if the path is null.
+ public static void SaveAsExr(this Image source, string path) => SaveAsExr(source, path, default);
///
- /// Saves the image to the given stream with the Open Exr format.
+ /// Saves the image to the given stream with the Exr format.
///
/// The image this method extends.
- /// The stream to save the image to.
+ /// The file path to save the image to.
+ /// Thrown if the path is null.
+ /// A representing the asynchronous operation.
+ public static Task SaveAsExrAsync(this Image source, string path) => SaveAsExrAsync(source, path, default);
+
+ ///
+ /// Saves the image to the given stream with the Exr format.
+ ///
+ /// The image this method extends.
+ /// The file path to save the image to.
+ /// The token to monitor for cancellation requests.
+ /// Thrown if the path is null.
+ /// A representing the asynchronous operation.
+ public static Task SaveAsExrAsync(this Image source, string path, CancellationToken cancellationToken)
+ => SaveAsExrAsync(source, path, default, cancellationToken);
+
+ ///
+ /// Saves the image to the given stream with the Exr format.
+ ///
+ /// The image this method extends.
+ /// The file path to save the image to.
/// The encoder to save the image with.
+ /// Thrown if the path is null.
+ public static void SaveAsExr(this Image source, string path, ExrEncoder encoder) =>
+ source.Save(
+ path,
+ encoder ?? source.Configuration.ImageFormatsManager.GetEncoder(ExrFormat.Instance));
+
+ ///
+ /// Saves the image to the given stream with the Exr format.
+ ///
+ /// The image this method extends.
+ /// The file path to save the image to.
+ /// The encoder to save the image with.
+ /// The token to monitor for cancellation requests.
+ /// Thrown if the path is null.
+ /// A representing the asynchronous operation.
+ public static Task SaveAsExrAsync(this Image source, string path, ExrEncoder encoder, CancellationToken cancellationToken = default)
+ => source.SaveAsync(
+ path,
+ encoder ?? source.Configuration.ImageFormatsManager.GetEncoder(ExrFormat.Instance),
+ cancellationToken);
+
+ ///
+ /// Saves the image to the given stream with the Exr format.
+ ///
+ /// The image this method extends.
+ /// The stream to save the image to.
+ /// Thrown if the stream is null.
+ public static void SaveAsExr(this Image source, Stream stream)
+ => SaveAsExr(source, stream, default);
+
+ ///
+ /// Saves the image to the given stream with the Exr format.
+ ///
+ /// The image this method extends.
+ /// The stream to save the image to.
+ /// The token to monitor for cancellation requests.
/// Thrown if the stream is null.
/// A representing the asynchronous operation.
- public static void SaveAsOpenExr(this Image source, Stream stream, ExrEncoder encoder)
+ public static Task SaveAsExrAsync(this Image source, Stream stream, CancellationToken cancellationToken = default)
+ => SaveAsExrAsync(source, stream, default, cancellationToken);
+
+ ///
+ /// Saves the image to the given stream with the Exr format.
+ ///
+ /// The image this method extends.
+ /// The stream to save the image to.
+ /// The encoder to save the image with.
+ /// Thrown if the stream is null.
+ public static void SaveAsExr(this Image source, Stream stream, ExrEncoder encoder)
=> source.Save(
- stream,
- encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(ExrFormat.Instance));
+ stream,
+ encoder ?? source.Configuration.ImageFormatsManager.GetEncoder(ExrFormat.Instance));
///
- /// Saves the image to the given stream with the Open Exr format.
+ /// Saves the image to the given stream with the Exr format.
///
/// The image this method extends.
/// The stream to save the image to.
@@ -1169,11 +1240,10 @@ public static partial class ImageExtensions
/// The token to monitor for cancellation requests.
/// Thrown if the stream is null.
/// A representing the asynchronous operation.
- public static Task SaveAsOpenExrAsync(this Image source, Stream stream, ExrEncoder encoder, CancellationToken cancellationToken = default) =>
- source.SaveAsync(
- stream,
- encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(ExrFormat.Instance),
- cancellationToken);
-
+ public static Task SaveAsExrAsync(this Image source, Stream stream, ExrEncoder encoder, CancellationToken cancellationToken = default)
+ => source.SaveAsync(
+ stream,
+ encoder ?? source.Configuration.ImageFormatsManager.GetEncoder(ExrFormat.Instance),
+ cancellationToken);
}
diff --git a/src/ImageSharp/Formats/_Generated/ImageMetadataExtensions.cs b/src/ImageSharp/Formats/_Generated/ImageMetadataExtensions.cs
index e35d00ed39..31a25fcede 100644
--- a/src/ImageSharp/Formats/_Generated/ImageMetadataExtensions.cs
+++ b/src/ImageSharp/Formats/_Generated/ImageMetadataExtensions.cs
@@ -14,6 +14,7 @@ using SixLabors.ImageSharp.Formats.Qoi;
using SixLabors.ImageSharp.Formats.Tga;
using SixLabors.ImageSharp.Formats.Tiff;
using SixLabors.ImageSharp.Formats.Webp;
+using SixLabors.ImageSharp.Formats.OpenExr;
namespace SixLabors.ImageSharp;
@@ -242,6 +243,26 @@ public static class ImageMetadataExtensions
/// The new
public static WebpMetadata CloneWebpMetadata(this ImageMetadata source) => source.CloneFormatMetadata(WebpFormat.Instance);
+ ///
+ /// Gets the from .
+ /// If none is found, an instance is created either by conversion from the decoded image format metadata
+ /// or the requested format default constructor.
+ /// This instance will be added to the metadata for future requests.
+ ///
+ /// The image metadata.
+ ///
+ /// The
+ ///
+ public static ExrMetadata GetExrMetadata(this ImageMetadata source) => source.GetFormatMetadata(ExrFormat.Instance);
+
+ ///
+ /// Creates a new cloned instance of from the .
+ /// The instance is created via
+ ///
+ /// The image metadata.
+ /// The new
+ public static ExrMetadata CloneExrMetadata(this ImageMetadata source) => source.CloneFormatMetadata(ExrFormat.Instance);
+
///
/// Gets the from .
diff --git a/src/ImageSharp/Formats/_Generated/_Formats.ttinclude b/src/ImageSharp/Formats/_Generated/_Formats.ttinclude
index 2d6129c4c0..c1c69c5b5b 100644
--- a/src/ImageSharp/Formats/_Generated/_Formats.ttinclude
+++ b/src/ImageSharp/Formats/_Generated/_Formats.ttinclude
@@ -14,7 +14,8 @@
"Qoi",
"Tga",
"Tiff",
- "Webp"
+ "Webp",
+ "Exr"
];
private static readonly string[] frameFormats = [
diff --git a/src/ImageSharp/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj
index 2c7172387f..32a5f0073e 100644
--- a/src/ImageSharp/ImageSharp.csproj
+++ b/src/ImageSharp/ImageSharp.csproj
@@ -56,6 +56,11 @@
True
InlineArray.tt
+
+ True
+ True
+ ImageExtensions.Save.tt
+
True
True
@@ -141,11 +146,6 @@
True
PorterDuffFunctions.Generated.tt
-
- True
- True
- ImageExtensions.Save.tt
-
diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgb96.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgb96.cs
index 620e305a21..165f13b07e 100644
--- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgb96.cs
+++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgb96.cs
@@ -72,27 +72,10 @@ public partial struct Rgb96 : IPixel
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Rgb96 left, Rgb96 right) => !left.Equals(right);
- ///
- public PixelOperations CreatePixelOperations() => new();
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void FromScaledVector4(Vector4 vector) => this.FromVector4(vector);
-
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToScaledVector4() => this.ToVector4();
- ///
- [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);
- }
-
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToVector4() => new(
@@ -103,71 +86,48 @@ public partial struct Rgb96 : IPixel
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void FromBgra5551(Bgra5551 source) => this.FromScaledVector4(source.ToScaledVector4());
+ public override int GetHashCode() => HashCode.Combine(this.R, this.G, this.B);
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void FromArgb32(Argb32 source) => this.FromScaledVector4(source.ToScaledVector4());
+ public bool Equals(Rgb96 other) => this.R.Equals(other.R) && this.G.Equals(other.G) && this.B.Equals(other.B);
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void FromBgr24(Bgr24 source) => this.FromScaledVector4(source.ToScaledVector4());
+ public override string ToString() => FormattableString.Invariant($"Rgb96({this.R}, {this.G}, {this.B})");
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void FromBgra32(Bgra32 source) => this.FromScaledVector4(source.ToScaledVector4());
+ public static PixelOperations CreatePixelOperations() => throw new NotImplementedException();
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void FromL8(L8 source) => this.FromScaledVector4(source.ToScaledVector4());
+ public static Rgb96 FromScaledVector4(Vector4 source) => throw new NotImplementedException();
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void FromL16(L16 source) => this.FromScaledVector4(source.ToScaledVector4());
+ public static Rgb96 FromVector4(Vector4 source) => throw new NotImplementedException();
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void FromLa16(La16 source) => this.FromScaledVector4(source.ToScaledVector4());
+ public static Rgb96 FromAbgr32(Abgr32 source) => throw new NotImplementedException();
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void FromLa32(La32 source) => this.FromScaledVector4(source.ToScaledVector4());
+ public static Rgb96 FromArgb32(Argb32 source) => throw new NotImplementedException();
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void FromRgb24(Rgb24 source) => this.FromScaledVector4(source.ToScaledVector4());
+ public static Rgb96 FromBgra5551(Bgra5551 source) => throw new NotImplementedException();
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void FromRgba32(Rgba32 source) => this.FromScaledVector4(source.ToScaledVector4());
+ public static Rgb96 FromBgr24(Bgr24 source) => throw new NotImplementedException();
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void FromAbgr32(Abgr32 source) => this.FromScaledVector4(source.ToScaledVector4());
+ public static Rgb96 FromBgra32(Bgra32 source) => throw new NotImplementedException();
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToRgba32(ref Rgba32 dest) => dest.FromScaledVector4(this.ToScaledVector4());
+ public static Rgb96 FromL8(L8 source) => throw new NotImplementedException();
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void FromRgb48(Rgb48 source) => this.FromScaledVector4(source.ToScaledVector4());
+ public static Rgb96 FromL16(L16 source) => throw new NotImplementedException();
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void FromRgba64(Rgba64 source) => this.FromScaledVector4(source.ToScaledVector4());
+ public static Rgb96 FromLa16(La16 source) => throw new NotImplementedException();
- ///
- public override bool Equals(object obj) => obj is Rgb96 other && this.Equals(other);
+ public static Rgb96 FromLa32(La32 source) => throw new NotImplementedException();
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public override int GetHashCode() => HashCode.Combine(this.R, this.G, this.B);
+ public static Rgb96 FromRgb24(Rgb24 source) => throw new NotImplementedException();
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool Equals(Rgb96 other) => this.R.Equals(other.R) && this.G.Equals(other.G) && this.B.Equals(other.B);
+ public static Rgb96 FromRgba32(Rgba32 source) => throw new NotImplementedException();
- ///
- public override string ToString() => FormattableString.Invariant($"Rgb96({this.R}, {this.G}, {this.B})");
+ public static Rgb96 FromRgb48(Rgb48 source) => throw new NotImplementedException();
+
+ public static Rgb96 FromRgba64(Rgba64 source) => throw new NotImplementedException();
+
+ public static PixelTypeInfo GetPixelTypeInfo() => throw new NotImplementedException();
+
+ public Rgba32 ToRgba32() => throw new NotImplementedException();
}
diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba128.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba128.cs
index 912a62db0c..fd094be599 100644
--- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba128.cs
+++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba128.cs
@@ -79,28 +79,6 @@ public partial struct Rgba128 : IPixel
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Rgba128 left, Rgba128 right) => !left.Equals(right);
- ///
- public PixelOperations CreatePixelOperations() => new();
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void FromScaledVector4(Vector4 vector) => this.FromVector4(vector);
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Vector4 ToScaledVector4() => this.ToVector4();
-
- ///
- [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);
- this.A = (uint)(vector.W * Max);
- }
-
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToVector4() => new(
@@ -111,71 +89,50 @@ public partial struct Rgba128 : IPixel
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void FromBgra5551(Bgra5551 source) => this.FromScaledVector4(source.ToScaledVector4());
+ public override int GetHashCode() => HashCode.Combine(this.R, this.G, this.B, this.A);
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void FromArgb32(Argb32 source) => this.FromScaledVector4(source.ToScaledVector4());
+ public bool Equals(Rgba128 other) => this.R.Equals(other.R) && this.G.Equals(other.G) && this.B.Equals(other.B) && this.A.Equals(other.A);
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void FromBgr24(Bgr24 source) => this.FromScaledVector4(source.ToScaledVector4());
+ public override string ToString() => FormattableString.Invariant($"Rgba128({this.R}, {this.G}, {this.B}, {this.A})");
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void FromBgra32(Bgra32 source) => this.FromScaledVector4(source.ToScaledVector4());
+ public static PixelOperations CreatePixelOperations() => throw new NotImplementedException();
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void FromL8(L8 source) => this.FromScaledVector4(source.ToScaledVector4());
+ public static Rgba128 FromScaledVector4(Vector4 source) => throw new NotImplementedException();
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void FromL16(L16 source) => this.FromScaledVector4(source.ToScaledVector4());
+ public static Rgba128 FromVector4(Vector4 source) => throw new NotImplementedException();
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void FromLa16(La16 source) => this.FromScaledVector4(source.ToScaledVector4());
+ public static Rgba128 FromAbgr32(Abgr32 source) => throw new NotImplementedException();
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void FromLa32(La32 source) => this.FromScaledVector4(source.ToScaledVector4());
+ public static Rgba128 FromArgb32(Argb32 source) => throw new NotImplementedException();
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void FromRgb24(Rgb24 source) => this.FromScaledVector4(source.ToScaledVector4());
+ public static Rgba128 FromBgra5551(Bgra5551 source) => throw new NotImplementedException();
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void FromRgba32(Rgba32 source) => this.FromScaledVector4(source.ToScaledVector4());
+ public static Rgba128 FromBgr24(Bgr24 source) => throw new NotImplementedException();
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void FromAbgr32(Abgr32 source) => this.FromScaledVector4(source.ToScaledVector4());
+ public static Rgba128 FromBgra32(Bgra32 source) => throw new NotImplementedException();
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToRgba32(ref Rgba32 dest) => dest.FromScaledVector4(this.ToScaledVector4());
+ public static Rgba128 FromL8(L8 source) => throw new NotImplementedException();
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void FromRgb48(Rgb48 source) => this.FromScaledVector4(source.ToScaledVector4());
+ public static Rgba128 FromL16(L16 source) => throw new NotImplementedException();
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void FromRgba64(Rgba64 source) => this.FromScaledVector4(source.ToScaledVector4());
+ public static Rgba128 FromLa16(La16 source) => throw new NotImplementedException();
- ///
- public override bool Equals(object obj) => obj is Rgba128 other && this.Equals(other);
+ public static Rgba128 FromLa32(La32 source) => throw new NotImplementedException();
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public override int GetHashCode() => HashCode.Combine(this.R, this.G, this.B, this.A);
+ public static Rgba128 FromRgb24(Rgb24 source) => throw new NotImplementedException();
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool Equals(Rgba128 other) => this.R.Equals(other.R) && this.G.Equals(other.G) && this.B.Equals(other.B) && this.A.Equals(other.A);
+ public static Rgba128 FromRgba32(Rgba32 source) => throw new NotImplementedException();
- ///
- public override string ToString() => FormattableString.Invariant($"Rgba128({this.R}, {this.G}, {this.B}, {this.A})");
+ public static Rgba128 FromRgb48(Rgb48 source) => throw new NotImplementedException();
+
+ public static Rgba128 FromRgba64(Rgba64 source) => throw new NotImplementedException();
+
+ public static PixelTypeInfo GetPixelTypeInfo() => throw new NotImplementedException();
+
+ public Rgba32 ToRgba32() => throw new NotImplementedException();
+
+ public Vector4 ToScaledVector4() => throw new NotImplementedException();
}
diff --git a/tests/ImageSharp.Tests/Formats/Exr/ExrDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Exr/ExrDecoderTests.cs
index 29b75bc9cd..0391ab7c8c 100644
--- a/tests/ImageSharp.Tests/Formats/Exr/ExrDecoderTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Exr/ExrDecoderTests.cs
@@ -10,14 +10,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Exr;
[ValidateDisposedMemoryAllocations]
public class ExrDecoderTests
{
- private static ExrDecoder ExrDecoder => new();
-
[Theory]
[WithFile(TestImages.Exr.Uncompressed, PixelTypes.Rgba32)]
public void ExrDecoder_CanDecode_Uncompressed(TestImageProvider provider)
where TPixel : unmanaged, IPixel
{
- using Image image = provider.GetImage(ExrDecoder);
+ using Image image = provider.GetImage(ExrDecoder.Instance);
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
@@ -27,7 +25,7 @@ public class ExrDecoderTests
public void ExrDecoder_CanDecode_ZipCompressed(TestImageProvider provider)
where TPixel : unmanaged, IPixel
{
- using Image image = provider.GetImage(ExrDecoder);
+ using Image image = provider.GetImage(ExrDecoder.Instance);
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
@@ -37,7 +35,7 @@ public class ExrDecoderTests
public void ExrDecoder_CanDecode_ZipsCompressed(TestImageProvider provider)
where TPixel : unmanaged, IPixel
{
- using Image image = provider.GetImage(ExrDecoder);
+ using Image image = provider.GetImage(ExrDecoder.Instance);
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
@@ -47,7 +45,7 @@ public class ExrDecoderTests
public void ExrDecoder_CanDecode_RunLengthCompressed(TestImageProvider provider)
where TPixel : unmanaged, IPixel
{
- using Image image = provider.GetImage(ExrDecoder);
+ using Image image = provider.GetImage(ExrDecoder.Instance);
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
@@ -57,7 +55,7 @@ public class ExrDecoderTests
public void ExrDecoder_CanDecode_B44Compressed(TestImageProvider provider)
where TPixel : unmanaged, IPixel
{
- using Image image = provider.GetImage(ExrDecoder);
+ using Image image = provider.GetImage(ExrDecoder.Instance);
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
diff --git a/tests/ImageSharp.Tests/Formats/Exr/ImageExtensionsTest.cs b/tests/ImageSharp.Tests/Formats/Exr/ImageExtensionsTest.cs
index 926f5ca909..78ce845d36 100644
--- a/tests/ImageSharp.Tests/Formats/Exr/ImageExtensionsTest.cs
+++ b/tests/ImageSharp.Tests/Formats/Exr/ImageExtensionsTest.cs
@@ -11,56 +11,126 @@ namespace SixLabors.ImageSharp.Tests.Formats.Exr;
public class ImageExtensionsTest
{
[Fact]
- public void SaveAsExr_Stream()
+ public void SaveAsExr_Path()
{
- using var memoryStream = new MemoryStream();
+ string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensionsTest));
+ string file = Path.Combine(dir, "SaveAsExr_Path.exr");
- using (var image = new Image(10, 10))
+ using (Image image = new(10, 10))
{
- image.SaveAsOpenExr(memoryStream, new ExrEncoder());
+ image.SaveAsExr(file);
}
- memoryStream.Position = 0;
+ IImageFormat format = Image.DetectFormat(file);
+ Assert.True(format is ExrFormat);
+ }
+
+ [Fact]
+ public async Task SaveAsExrAsync_Path()
+ {
+ string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensionsTest));
+ string file = Path.Combine(dir, "SaveAsExrAsync_Path.exr");
- using (Image.Load(memoryStream, out IImageFormat mime))
+ using (Image image = new(10, 10))
{
- Assert.Equal("image/x-exr", mime.DefaultMimeType);
+ await image.SaveAsExrAsync(file);
}
+
+ IImageFormat format = Image.DetectFormat(file);
+ Assert.True(format is ExrFormat);
}
[Fact]
- public void SaveAsExr_Stream_Encoder()
+ public void SaveAsExr_Path_Encoder()
+ {
+ string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensions));
+ string file = Path.Combine(dir, "SaveAsExr_Path_Encoder.exr");
+
+ using (Image image = new(10, 10))
+ {
+ image.SaveAsExr(file, new ExrEncoder());
+ }
+
+ IImageFormat format = Image.DetectFormat(file);
+ Assert.True(format is ExrFormat);
+ }
+
+ [Fact]
+ public async Task SaveAsExrAsync_Path_Encoder()
+ {
+ string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensions));
+ string file = Path.Combine(dir, "SaveAsExrAsync_Path_Encoder.tiff");
+
+ using (Image image = new(10, 10))
+ {
+ await image.SaveAsExrAsync(file, new ExrEncoder());
+ }
+
+ IImageFormat format = Image.DetectFormat(file);
+ Assert.True(format is ExrFormat);
+ }
+
+ [Fact]
+ public void SaveAsExr_Stream()
{
- using var memoryStream = new MemoryStream();
+ using MemoryStream memoryStream = new();
- using (var image = new Image(10, 10))
+ using (Image image = new(10, 10))
{
- image.SaveAsOpenExr(memoryStream, new ExrEncoder());
+ image.SaveAsExr(memoryStream);
}
memoryStream.Position = 0;
- using (Image.Load(memoryStream, out IImageFormat mime))
+ IImageFormat format = Image.DetectFormat(memoryStream);
+ Assert.True(format is ExrFormat);
+ }
+
+ [Fact]
+ public async Task SaveAsExrAsync_StreamAsync()
+ {
+ using MemoryStream memoryStream = new();
+
+ using (Image image = new(10, 10))
{
- Assert.Equal("image/x-exr", mime.DefaultMimeType);
+ await image.SaveAsExrAsync(memoryStream);
}
+
+ memoryStream.Position = 0;
+
+ IImageFormat format = Image.DetectFormat(memoryStream);
+ Assert.True(format is ExrFormat);
}
[Fact]
- public async Task SaveAsExrAsync_Stream_Encoder()
+ public void SaveAsExr_Stream_Encoder()
{
- using var memoryStream = new MemoryStream();
+ using MemoryStream memoryStream = new();
- using (var image = new Image(10, 10))
+ using (Image image = new(10, 10))
{
- await image.SaveAsOpenExrAsync(memoryStream, new ExrEncoder());
+ image.SaveAsTiff(memoryStream, new ExrEncoder());
}
memoryStream.Position = 0;
- using (Image.Load(memoryStream, out IImageFormat mime))
+ IImageFormat format = Image.DetectFormat(memoryStream);
+ Assert.True(format is ExrFormat);
+ }
+
+ [Fact]
+ public async Task SaveAsExrAsync_Stream_Encoder()
+ {
+ using MemoryStream memoryStream = new();
+
+ using (Image image = new(10, 10))
{
- Assert.Equal("image/x-exr", mime.DefaultMimeType);
+ await image.SaveAsExrAsync(memoryStream, new ExrEncoder());
}
+
+ memoryStream.Position = 0;
+
+ IImageFormat format = Image.DetectFormat(memoryStream);
+ Assert.True(format is ExrFormat);
}
}
diff --git a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs b/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs
index 4dc3def1f8..9ced51608b 100644
--- a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs
+++ b/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs
@@ -64,7 +64,7 @@ public static partial class TestEnvironment
new TgaConfigurationModule(),
new WebpConfigurationModule(),
new TiffConfigurationModule(),
- new ExrConfigurationModule());
+ new ExrConfigurationModule(),
new QoiConfigurationModule());
IImageEncoder pngEncoder = IsWindows ? SystemDrawingReferenceEncoder.Png : new ImageSharpPngEncoderWithDefaultConfiguration();