diff --git a/src/ImageSharp/Advanced/AdvancedImageExtensions.cs b/src/ImageSharp/Advanced/AdvancedImageExtensions.cs
index 4fa07931e..c3a9c212e 100644
--- a/src/ImageSharp/Advanced/AdvancedImageExtensions.cs
+++ b/src/ImageSharp/Advanced/AdvancedImageExtensions.cs
@@ -19,9 +19,9 @@ public static class AdvancedImageExtensions
///
/// The source image.
/// The target file path to save the image to.
- /// The file path is null.
- /// No encoder available for provided path.
/// The matching .
+ /// The file path is null.
+ /// No encoder available for provided path.
public static IImageEncoder DetectEncoder(this Image source, string filePath)
{
Guard.NotNull(filePath, nameof(filePath));
@@ -30,27 +30,27 @@ public static class AdvancedImageExtensions
if (!source.GetConfiguration().ImageFormatsManager.TryFindFormatByFileExtension(ext, out IImageFormat? format))
{
StringBuilder sb = new();
- sb.AppendLine(CultureInfo.InvariantCulture, $"No encoder was found for extension '{ext}'. Registered encoders include:");
+ sb = sb.AppendLine(CultureInfo.InvariantCulture, $"No encoder was found for extension '{ext}'. Registered encoders include:");
foreach (IImageFormat fmt in source.GetConfiguration().ImageFormats)
{
- sb.AppendFormat(CultureInfo.InvariantCulture, " - {0} : {1}{2}", fmt.Name, string.Join(", ", fmt.FileExtensions), Environment.NewLine);
+ sb = sb.AppendFormat(CultureInfo.InvariantCulture, " - {0} : {1}{2}", fmt.Name, string.Join(", ", fmt.FileExtensions), Environment.NewLine);
}
- throw new NotSupportedException(sb.ToString());
+ throw new UnknownImageFormatException(sb.ToString());
}
- IImageEncoder? encoder = source.GetConfiguration().ImageFormatsManager.FindEncoder(format);
+ IImageEncoder? encoder = source.GetConfiguration().ImageFormatsManager.GetEncoder(format);
if (encoder is null)
{
StringBuilder sb = new();
- sb.AppendLine(CultureInfo.InvariantCulture, $"No encoder was found for extension '{ext}' using image format '{format.Name}'. Registered encoders include:");
+ sb = sb.AppendLine(CultureInfo.InvariantCulture, $"No encoder was found for extension '{ext}' using image format '{format.Name}'. Registered encoders include:");
foreach (KeyValuePair enc in source.GetConfiguration().ImageFormatsManager.ImageEncoders)
{
- sb.AppendFormat(CultureInfo.InvariantCulture, " - {0} : {1}{2}", enc.Key, enc.Value.GetType().Name, Environment.NewLine);
+ sb = sb.AppendFormat(CultureInfo.InvariantCulture, " - {0} : {1}{2}", enc.Key, enc.Value.GetType().Name, Environment.NewLine);
}
- throw new NotSupportedException(sb.ToString());
+ throw new UnknownImageFormatException(sb.ToString());
}
return encoder;
diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoder.cs b/src/ImageSharp/Formats/Bmp/BmpDecoder.cs
index 15c213f88..da6556b36 100644
--- a/src/ImageSharp/Formats/Bmp/BmpDecoder.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpDecoder.cs
@@ -20,7 +20,7 @@ public sealed class BmpDecoder : SpecializedImageDecoder
public static BmpDecoder Instance { get; } = new();
///
- protected override IImageInfo 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));
diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
index 4bdb7257a..fd0497d9a 100644
--- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
@@ -209,7 +209,7 @@ internal sealed class BmpDecoderCore : IImageDecoderInternals
}
///
- public IImageInfo Identify(BufferedReadStream stream, CancellationToken cancellationToken)
+ public ImageInfo Identify(BufferedReadStream stream, CancellationToken cancellationToken)
{
this.ReadImageHeaders(stream, out _, out _);
return new ImageInfo(new PixelTypeInfo(this.infoHeader.BitsPerPixel), this.infoHeader.Width, this.infoHeader.Height, this.metadata);
diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
index 53cb066f0..9f1e85639 100644
--- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
@@ -215,15 +215,15 @@ internal sealed class BmpEncoderCore : IImageEncoderInternals
BmpInfoHeader infoHeader = new(
headerSize: infoHeaderSize,
- height: height,
width: width,
- bitsPerPixel: bpp,
+ height: height,
planes: 1,
+ bitsPerPixel: bpp,
imageSize: height * bytesPerLine,
- clrUsed: 0,
- clrImportant: 0,
xPelsPerMeter: hResolution,
- yPelsPerMeter: vResolution);
+ yPelsPerMeter: vResolution,
+ clrUsed: 0,
+ clrImportant: 0);
if ((this.infoHeaderType is BmpInfoHeaderType.WinVersion4 or BmpInfoHeaderType.WinVersion5) && this.bitsPerPixel == BmpBitsPerPixel.Pixel32)
{
@@ -470,7 +470,7 @@ internal sealed class BmpEncoderCore : IImageEncoderInternals
using IQuantizer frameQuantizer = this.quantizer.CreatePixelSpecificQuantizer(this.configuration);
frameQuantizer.BuildPalette(this.pixelSamplingStrategy, image);
- using IndexedImageFrame quantized = frameQuantizer.QuantizeFrame(image.Frames.RootFrame, image.Bounds());
+ using IndexedImageFrame quantized = frameQuantizer.QuantizeFrame(image.Frames.RootFrame, image.Bounds);
ReadOnlySpan quantizedColorPalette = quantized.Palette.Span;
this.WriteColorPalette(stream, quantizedColorPalette, colorPalette);
@@ -541,7 +541,7 @@ internal sealed class BmpEncoderCore : IImageEncoderInternals
frameQuantizer.BuildPalette(this.pixelSamplingStrategy, image);
- using IndexedImageFrame quantized = frameQuantizer.QuantizeFrame(image.Frames.RootFrame, image.Bounds());
+ using IndexedImageFrame quantized = frameQuantizer.QuantizeFrame(image.Frames.RootFrame, image.Bounds);
using IMemoryOwner colorPaletteBuffer = this.memoryAllocator.Allocate(ColorPaletteSize4Bit, AllocationOptions.Clean);
Span colorPalette = colorPaletteBuffer.GetSpan();
@@ -588,7 +588,7 @@ internal sealed class BmpEncoderCore : IImageEncoderInternals
frameQuantizer.BuildPalette(this.pixelSamplingStrategy, image);
- using IndexedImageFrame quantized = frameQuantizer.QuantizeFrame(image.Frames.RootFrame, image.Bounds());
+ using IndexedImageFrame quantized = frameQuantizer.QuantizeFrame(image.Frames.RootFrame, image.Bounds);
using IMemoryOwner colorPaletteBuffer = this.memoryAllocator.Allocate(ColorPaletteSize2Bit, AllocationOptions.Clean);
Span colorPalette = colorPaletteBuffer.GetSpan();
@@ -644,7 +644,7 @@ internal sealed class BmpEncoderCore : IImageEncoderInternals
frameQuantizer.BuildPalette(this.pixelSamplingStrategy, image);
- using IndexedImageFrame quantized = frameQuantizer.QuantizeFrame(image.Frames.RootFrame, image.Bounds());
+ using IndexedImageFrame quantized = frameQuantizer.QuantizeFrame(image.Frames.RootFrame, image.Bounds);
using IMemoryOwner colorPaletteBuffer = this.memoryAllocator.Allocate(ColorPaletteSize1Bit, AllocationOptions.Clean);
Span colorPalette = colorPaletteBuffer.GetSpan();
diff --git a/src/ImageSharp/Formats/Gif/GifDecoder.cs b/src/ImageSharp/Formats/Gif/GifDecoder.cs
index e08fc6230..6dbb07a13 100644
--- a/src/ImageSharp/Formats/Gif/GifDecoder.cs
+++ b/src/ImageSharp/Formats/Gif/GifDecoder.cs
@@ -20,7 +20,7 @@ public sealed class GifDecoder : ImageDecoder
public static GifDecoder Instance { get; } = new();
///
- protected override IImageInfo 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));
diff --git a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
index d67372419..8c5915800 100644
--- a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
+++ b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
@@ -175,7 +175,7 @@ internal sealed class GifDecoderCore : IImageDecoderInternals
}
///
- public IImageInfo Identify(BufferedReadStream stream, CancellationToken cancellationToken)
+ public ImageInfo Identify(BufferedReadStream stream, CancellationToken cancellationToken)
{
try
{
diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs
index c35ee9985..9cc045d45 100644
--- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs
+++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs
@@ -99,12 +99,12 @@ internal sealed class GifEncoderCore : IImageEncoderInternals
if (useGlobalTable)
{
frameQuantizer.BuildPalette(this.pixelSamplingStrategy, image);
- quantized = frameQuantizer.QuantizeFrame(image.Frames.RootFrame, image.Bounds());
+ quantized = frameQuantizer.QuantizeFrame(image.Frames.RootFrame, image.Bounds);
}
else
{
frameQuantizer.BuildPalette(this.pixelSamplingStrategy, image.Frames.RootFrame);
- quantized = frameQuantizer.QuantizeFrame(image.Frames.RootFrame, image.Bounds());
+ quantized = frameQuantizer.QuantizeFrame(image.Frames.RootFrame, image.Bounds);
}
}
diff --git a/src/ImageSharp/Formats/IImageDecoder.cs b/src/ImageSharp/Formats/IImageDecoder.cs
index 3729c98d9..eca2939bc 100644
--- a/src/ImageSharp/Formats/IImageDecoder.cs
+++ b/src/ImageSharp/Formats/IImageDecoder.cs
@@ -15,9 +15,9 @@ public interface IImageDecoder
///
/// The general decoder options.
/// The containing image data.
- /// The object.
+ /// The object.
/// Thrown if the encoded image contains errors.
- public IImageInfo Identify(DecoderOptions options, Stream stream);
+ public ImageInfo Identify(DecoderOptions options, Stream stream);
///
/// Reads the raw image information from the specified stream.
@@ -27,7 +27,7 @@ public interface IImageDecoder
/// The token to monitor for cancellation requests.
/// The object.
/// Thrown if the encoded image contains errors.
- public Task IdentifyAsync(DecoderOptions options, Stream stream, CancellationToken cancellationToken = default);
+ public Task IdentifyAsync(DecoderOptions options, Stream stream, CancellationToken cancellationToken = default);
///
/// Decodes the image from the specified stream to an of a specific pixel type.
diff --git a/src/ImageSharp/Formats/IImageDecoderInternals.cs b/src/ImageSharp/Formats/IImageDecoderInternals.cs
index d8cb1c662..06fb59764 100644
--- a/src/ImageSharp/Formats/IImageDecoderInternals.cs
+++ b/src/ImageSharp/Formats/IImageDecoderInternals.cs
@@ -41,10 +41,10 @@ internal interface IImageDecoderInternals
///
/// The containing image data.
/// The token to monitor for cancellation requests.
- /// The .
+ /// The .
///
/// Cancellable synchronous method. In case of cancellation,
/// an shall be thrown which will be handled on the call site.
///
- IImageInfo Identify(BufferedReadStream stream, CancellationToken cancellationToken);
+ ImageInfo Identify(BufferedReadStream stream, CancellationToken cancellationToken);
}
diff --git a/src/ImageSharp/Formats/ImageDecoder.cs b/src/ImageSharp/Formats/ImageDecoder.cs
index 591f85df2..ebb45d701 100644
--- a/src/ImageSharp/Formats/ImageDecoder.cs
+++ b/src/ImageSharp/Formats/ImageDecoder.cs
@@ -1,6 +1,5 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
-#nullable disable
using SixLabors.ImageSharp.IO;
using SixLabors.ImageSharp.PixelFormats;
@@ -17,49 +16,85 @@ public abstract class ImageDecoder : IImageDecoder
///
public Image Decode(DecoderOptions options, Stream stream)
where TPixel : unmanaged, IPixel
- => WithSeekableStream(
- options,
- stream,
- s => this.Decode(options, s, default));
+ {
+ Image image = WithSeekableStream(
+ options,
+ stream,
+ s => this.Decode(options, s, default));
+
+ this.SetDecoderFormat(options.Configuration, image);
+
+ return image;
+ }
///
public Image Decode(DecoderOptions options, Stream stream)
- => WithSeekableStream(
- options,
- stream,
- s => this.Decode(options, s, default));
+ {
+ Image image = WithSeekableStream(
+ options,
+ stream,
+ s => this.Decode(options, s, default));
+
+ this.SetDecoderFormat(options.Configuration, image);
+
+ return image;
+ }
///
- public Task> DecodeAsync(DecoderOptions options, Stream stream, CancellationToken cancellationToken = default)
+ public async Task> DecodeAsync(DecoderOptions options, Stream stream, CancellationToken cancellationToken = default)
where TPixel : unmanaged, IPixel
- => WithSeekableMemoryStreamAsync(
- options,
- stream,
- (s, ct) => this.Decode(options, s, ct),
- cancellationToken);
+ {
+ Image image = await WithSeekableMemoryStreamAsync(
+ options,
+ stream,
+ (s, ct) => this.Decode(options, s, ct),
+ cancellationToken).ConfigureAwait(false);
+
+ this.SetDecoderFormat(options.Configuration, image);
+
+ return image;
+ }
///
- public Task DecodeAsync(DecoderOptions options, Stream stream, CancellationToken cancellationToken = default)
- => WithSeekableMemoryStreamAsync(
+ public async Task DecodeAsync(DecoderOptions options, Stream stream, CancellationToken cancellationToken = default)
+ {
+ Image image = await WithSeekableMemoryStreamAsync(
options,
stream,
(s, ct) => this.Decode(options, s, ct),
- cancellationToken);
+ cancellationToken).ConfigureAwait(false);
+
+ this.SetDecoderFormat(options.Configuration, image);
+
+ return image;
+ }
///
- public IImageInfo Identify(DecoderOptions options, Stream stream)
- => WithSeekableStream(
- options,
- stream,
- s => this.Identify(options, s, default));
+ public ImageInfo Identify(DecoderOptions options, Stream stream)
+ {
+ ImageInfo info = WithSeekableStream(
+ options,
+ stream,
+ s => this.Identify(options, s, default));
+
+ this.SetDecoderFormat(options.Configuration, info);
+
+ return info;
+ }
///
- public Task IdentifyAsync(DecoderOptions options, Stream stream, CancellationToken cancellationToken = default)
- => WithSeekableMemoryStreamAsync(
- options,
- stream,
- (s, ct) => this.Identify(options, s, ct),
- cancellationToken);
+ public async Task IdentifyAsync(DecoderOptions options, Stream stream, CancellationToken cancellationToken = default)
+ {
+ ImageInfo info = await WithSeekableMemoryStreamAsync(
+ options,
+ stream,
+ (s, ct) => this.Identify(options, s, ct),
+ cancellationToken).ConfigureAwait(false);
+
+ this.SetDecoderFormat(options.Configuration, info);
+
+ return info;
+ }
///
/// Decodes the image from the specified stream to an of a specific pixel type.
@@ -98,9 +133,9 @@ public abstract class ImageDecoder : IImageDecoder
/// The general decoder options.
/// The containing image data.
/// The token to monitor for cancellation requests.
- /// The object.
+ /// The object.
/// Thrown if the encoded image contains errors.
- protected abstract IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken);
+ protected abstract ImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken);
///
/// Performs a scaling operation against the decoded image. If the target size is not set, or the image size
@@ -114,7 +149,7 @@ public abstract class ImageDecoder : IImageDecoder
{
ResizeOptions resizeOptions = new()
{
- Size = options.TargetSize.Value,
+ Size = options.TargetSize!.Value,
Sampler = options.Sampler,
Mode = ResizeMode.Max
};
@@ -137,7 +172,7 @@ public abstract class ImageDecoder : IImageDecoder
}
Size targetSize = options.TargetSize.Value;
- Size currentSize = image.Size();
+ Size currentSize = image.Size;
return currentSize.Width != targetSize.Width && currentSize.Height != targetSize.Height;
}
@@ -252,4 +287,20 @@ public abstract class ImageDecoder : IImageDecoder
memoryStream.Position = 0;
return await action(memoryStream, position, cancellationToken).ConfigureAwait(false);
}
+
+ internal void SetDecoderFormat(Configuration configuration, Image image)
+ {
+ if (configuration.ImageFormatsManager.TryFindFormatByDecoder(this, out IImageFormat? format))
+ {
+ image.Metadata.DecodedImageFormat = format;
+ }
+ }
+
+ internal void SetDecoderFormat(Configuration configuration, ImageInfo info)
+ {
+ if (configuration.ImageFormatsManager.TryFindFormatByDecoder(this, out IImageFormat? format))
+ {
+ info.Metadata.DecodedImageFormat = format;
+ }
+ }
}
diff --git a/src/ImageSharp/Formats/ImageDecoderUtilities.cs b/src/ImageSharp/Formats/ImageDecoderUtilities.cs
index 2a5b91b09..e2c61c8eb 100644
--- a/src/ImageSharp/Formats/ImageDecoderUtilities.cs
+++ b/src/ImageSharp/Formats/ImageDecoderUtilities.cs
@@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.Formats;
///
internal static class ImageDecoderUtilities
{
- internal static IImageInfo Identify(
+ internal static ImageInfo Identify(
this IImageDecoderInternals decoder,
Configuration configuration,
Stream stream,
diff --git a/src/ImageSharp/Formats/ImageExtensions.Save.cs b/src/ImageSharp/Formats/ImageExtensions.Save.cs
index 6249f8dc7..71458333f 100644
--- a/src/ImageSharp/Formats/ImageExtensions.Save.cs
+++ b/src/ImageSharp/Formats/ImageExtensions.Save.cs
@@ -58,7 +58,7 @@ public static partial class ImageExtensions
public static void SaveAsBmp(this Image source, string path, BmpEncoder encoder) =>
source.Save(
path,
- encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(BmpFormat.Instance));
+ encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(BmpFormat.Instance));
///
/// Saves the image to the given stream with the Bmp format.
@@ -72,7 +72,7 @@ public static partial class ImageExtensions
public static Task SaveAsBmpAsync(this Image source, string path, BmpEncoder encoder, CancellationToken cancellationToken = default)
=> source.SaveAsync(
path,
- encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(BmpFormat.Instance),
+ encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(BmpFormat.Instance),
cancellationToken);
///
@@ -105,7 +105,7 @@ public static partial class ImageExtensions
public static void SaveAsBmp(this Image source, Stream stream, BmpEncoder encoder)
=> source.Save(
stream,
- encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(BmpFormat.Instance));
+ encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(BmpFormat.Instance));
///
/// Saves the image to the given stream with the Bmp format.
@@ -119,7 +119,7 @@ public static partial class ImageExtensions
public static Task SaveAsBmpAsync(this Image source, Stream stream, BmpEncoder encoder, CancellationToken cancellationToken = default)
=> source.SaveAsync(
stream,
- encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(BmpFormat.Instance),
+ encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(BmpFormat.Instance),
cancellationToken);
///
@@ -160,7 +160,7 @@ public static partial class ImageExtensions
public static void SaveAsGif(this Image source, string path, GifEncoder encoder) =>
source.Save(
path,
- encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(GifFormat.Instance));
+ encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(GifFormat.Instance));
///
/// Saves the image to the given stream with the Gif format.
@@ -174,7 +174,7 @@ public static partial class ImageExtensions
public static Task SaveAsGifAsync(this Image source, string path, GifEncoder encoder, CancellationToken cancellationToken = default)
=> source.SaveAsync(
path,
- encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(GifFormat.Instance),
+ encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(GifFormat.Instance),
cancellationToken);
///
@@ -207,7 +207,7 @@ public static partial class ImageExtensions
public static void SaveAsGif(this Image source, Stream stream, GifEncoder encoder)
=> source.Save(
stream,
- encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(GifFormat.Instance));
+ encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(GifFormat.Instance));
///
/// Saves the image to the given stream with the Gif format.
@@ -221,7 +221,7 @@ public static partial class ImageExtensions
public static Task SaveAsGifAsync(this Image source, Stream stream, GifEncoder encoder, CancellationToken cancellationToken = default)
=> source.SaveAsync(
stream,
- encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(GifFormat.Instance),
+ encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(GifFormat.Instance),
cancellationToken);
///
@@ -262,7 +262,7 @@ public static partial class ImageExtensions
public static void SaveAsJpeg(this Image source, string path, JpegEncoder encoder) =>
source.Save(
path,
- encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(JpegFormat.Instance));
+ encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(JpegFormat.Instance));
///
/// Saves the image to the given stream with the Jpeg format.
@@ -276,7 +276,7 @@ public static partial class ImageExtensions
public static Task SaveAsJpegAsync(this Image source, string path, JpegEncoder encoder, CancellationToken cancellationToken = default)
=> source.SaveAsync(
path,
- encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(JpegFormat.Instance),
+ encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(JpegFormat.Instance),
cancellationToken);
///
@@ -309,7 +309,7 @@ public static partial class ImageExtensions
public static void SaveAsJpeg(this Image source, Stream stream, JpegEncoder encoder)
=> source.Save(
stream,
- encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(JpegFormat.Instance));
+ encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(JpegFormat.Instance));
///
/// Saves the image to the given stream with the Jpeg format.
@@ -323,7 +323,7 @@ public static partial class ImageExtensions
public static Task SaveAsJpegAsync(this Image source, Stream stream, JpegEncoder encoder, CancellationToken cancellationToken = default)
=> source.SaveAsync(
stream,
- encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(JpegFormat.Instance),
+ encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(JpegFormat.Instance),
cancellationToken);
///
@@ -364,7 +364,7 @@ public static partial class ImageExtensions
public static void SaveAsPbm(this Image source, string path, PbmEncoder encoder) =>
source.Save(
path,
- encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(PbmFormat.Instance));
+ encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(PbmFormat.Instance));
///
/// Saves the image to the given stream with the Pbm format.
@@ -378,7 +378,7 @@ public static partial class ImageExtensions
public static Task SaveAsPbmAsync(this Image source, string path, PbmEncoder encoder, CancellationToken cancellationToken = default)
=> source.SaveAsync(
path,
- encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(PbmFormat.Instance),
+ encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(PbmFormat.Instance),
cancellationToken);
///
@@ -411,7 +411,7 @@ public static partial class ImageExtensions
public static void SaveAsPbm(this Image source, Stream stream, PbmEncoder encoder)
=> source.Save(
stream,
- encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(PbmFormat.Instance));
+ encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(PbmFormat.Instance));
///
/// Saves the image to the given stream with the Pbm format.
@@ -425,7 +425,7 @@ public static partial class ImageExtensions
public static Task SaveAsPbmAsync(this Image source, Stream stream, PbmEncoder encoder, CancellationToken cancellationToken = default)
=> source.SaveAsync(
stream,
- encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(PbmFormat.Instance),
+ encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(PbmFormat.Instance),
cancellationToken);
///
@@ -466,7 +466,7 @@ public static partial class ImageExtensions
public static void SaveAsPng(this Image source, string path, PngEncoder encoder) =>
source.Save(
path,
- encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(PngFormat.Instance));
+ encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(PngFormat.Instance));
///
/// Saves the image to the given stream with the Png format.
@@ -480,7 +480,7 @@ public static partial class ImageExtensions
public static Task SaveAsPngAsync(this Image source, string path, PngEncoder encoder, CancellationToken cancellationToken = default)
=> source.SaveAsync(
path,
- encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(PngFormat.Instance),
+ encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(PngFormat.Instance),
cancellationToken);
///
@@ -513,7 +513,7 @@ public static partial class ImageExtensions
public static void SaveAsPng(this Image source, Stream stream, PngEncoder encoder)
=> source.Save(
stream,
- encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(PngFormat.Instance));
+ encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(PngFormat.Instance));
///
/// Saves the image to the given stream with the Png format.
@@ -527,7 +527,7 @@ public static partial class ImageExtensions
public static Task SaveAsPngAsync(this Image source, Stream stream, PngEncoder encoder, CancellationToken cancellationToken = default)
=> source.SaveAsync(
stream,
- encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(PngFormat.Instance),
+ encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(PngFormat.Instance),
cancellationToken);
///
@@ -568,7 +568,7 @@ public static partial class ImageExtensions
public static void SaveAsTga(this Image source, string path, TgaEncoder encoder) =>
source.Save(
path,
- encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(TgaFormat.Instance));
+ encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(TgaFormat.Instance));
///
/// Saves the image to the given stream with the Tga format.
@@ -582,7 +582,7 @@ public static partial class ImageExtensions
public static Task SaveAsTgaAsync(this Image source, string path, TgaEncoder encoder, CancellationToken cancellationToken = default)
=> source.SaveAsync(
path,
- encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(TgaFormat.Instance),
+ encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(TgaFormat.Instance),
cancellationToken);
///
@@ -615,7 +615,7 @@ public static partial class ImageExtensions
public static void SaveAsTga(this Image source, Stream stream, TgaEncoder encoder)
=> source.Save(
stream,
- encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(TgaFormat.Instance));
+ encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(TgaFormat.Instance));
///
/// Saves the image to the given stream with the Tga format.
@@ -629,7 +629,7 @@ public static partial class ImageExtensions
public static Task SaveAsTgaAsync(this Image source, Stream stream, TgaEncoder encoder, CancellationToken cancellationToken = default)
=> source.SaveAsync(
stream,
- encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(TgaFormat.Instance),
+ encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(TgaFormat.Instance),
cancellationToken);
///
@@ -670,7 +670,7 @@ public static partial class ImageExtensions
public static void SaveAsWebp(this Image source, string path, WebpEncoder encoder) =>
source.Save(
path,
- encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(WebpFormat.Instance));
+ encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(WebpFormat.Instance));
///
/// Saves the image to the given stream with the Webp format.
@@ -684,7 +684,7 @@ public static partial class ImageExtensions
public static Task SaveAsWebpAsync(this Image source, string path, WebpEncoder encoder, CancellationToken cancellationToken = default)
=> source.SaveAsync(
path,
- encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(WebpFormat.Instance),
+ encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(WebpFormat.Instance),
cancellationToken);
///
@@ -717,7 +717,7 @@ public static partial class ImageExtensions
public static void SaveAsWebp(this Image source, Stream stream, WebpEncoder encoder)
=> source.Save(
stream,
- encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(WebpFormat.Instance));
+ encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(WebpFormat.Instance));
///
/// Saves the image to the given stream with the Webp format.
@@ -731,7 +731,7 @@ public static partial class ImageExtensions
public static Task SaveAsWebpAsync(this Image source, Stream stream, WebpEncoder encoder, CancellationToken cancellationToken = default)
=> source.SaveAsync(
stream,
- encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(WebpFormat.Instance),
+ encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(WebpFormat.Instance),
cancellationToken);
///
@@ -772,7 +772,7 @@ public static partial class ImageExtensions
public static void SaveAsTiff(this Image source, string path, TiffEncoder encoder) =>
source.Save(
path,
- encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(TiffFormat.Instance));
+ encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(TiffFormat.Instance));
///
/// Saves the image to the given stream with the Tiff format.
@@ -786,7 +786,7 @@ public static partial class ImageExtensions
public static Task SaveAsTiffAsync(this Image source, string path, TiffEncoder encoder, CancellationToken cancellationToken = default)
=> source.SaveAsync(
path,
- encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(TiffFormat.Instance),
+ encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(TiffFormat.Instance),
cancellationToken);
///
@@ -819,7 +819,7 @@ public static partial class ImageExtensions
public static void SaveAsTiff(this Image source, Stream stream, TiffEncoder encoder)
=> source.Save(
stream,
- encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(TiffFormat.Instance));
+ encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(TiffFormat.Instance));
///
/// Saves the image to the given stream with the Tiff format.
@@ -833,7 +833,7 @@ public static partial class ImageExtensions
public static Task SaveAsTiffAsync(this Image source, Stream stream, TiffEncoder encoder, CancellationToken cancellationToken = default)
=> source.SaveAsync(
stream,
- encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(TiffFormat.Instance),
+ encoder ?? source.GetConfiguration().ImageFormatsManager.GetEncoder(TiffFormat.Instance),
cancellationToken);
}
diff --git a/src/ImageSharp/Formats/ImageFormatManager.cs b/src/ImageSharp/Formats/ImageFormatManager.cs
index d058e80c9..8b4e320c5 100644
--- a/src/ImageSharp/Formats/ImageFormatManager.cs
+++ b/src/ImageSharp/Formats/ImageFormatManager.cs
@@ -3,6 +3,8 @@
using System.Collections.Concurrent;
using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using System.Text;
namespace SixLabors.ImageSharp.Formats;
@@ -91,9 +93,13 @@ public class ImageFormatManager
///
/// For the specified file extensions type find the e .
///
- /// The extension to discover
- /// The if found otherwise null
- /// False if no format was found
+ /// The extension to return the format for.
+ ///
+ /// When this method returns, contains the format that matches the given extension;
+ /// otherwise, the default value for the type of the parameter.
+ /// This parameter is passed uninitialized.
+ ///
+ /// if a match is found; otherwise,
public bool TryFindFormatByFileExtension(string extension, [NotNullWhen(true)] out IImageFormat? format)
{
Guard.NotNullOrWhiteSpace(extension, nameof(extension));
@@ -106,16 +112,30 @@ public class ImageFormatManager
format = this.imageFormats.FirstOrDefault(x =>
x.FileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase));
- return format != null;
+ return format is not null;
}
///
/// For the specified mime type find the .
///
- /// The mime-type to discover
- /// The if found; otherwise null
- public IImageFormat? FindFormatByMimeType(string mimeType)
- => this.imageFormats.FirstOrDefault(x => x.MimeTypes.Contains(mimeType, StringComparer.OrdinalIgnoreCase));
+ /// The mime-type to return the format for.
+ ///
+ /// When this method returns, contains the format that matches the given mime-type;
+ /// otherwise, the default value for the type of the parameter.
+ /// This parameter is passed uninitialized.
+ ///
+ /// if a match is found; otherwise,
+ public bool TryFindFormatByMimeType(string mimeType, [NotNullWhen(true)] out IImageFormat? format)
+ {
+ format = this.imageFormats.FirstOrDefault(x => x.MimeTypes.Contains(mimeType, StringComparer.OrdinalIgnoreCase));
+ return format is not null;
+ }
+
+ internal bool TryFindFormatByDecoder(IImageDecoder decoder, [NotNullWhen(true)] out IImageFormat? format)
+ {
+ format = this.mimeTypeDecoders.FirstOrDefault(x => x.Value.GetType() == decoder.GetType()).Key;
+ return format is not null;
+ }
///
/// Sets a specific image encoder as the encoder for a specific image format.
@@ -163,32 +183,54 @@ public class ImageFormatManager
/// For the specified mime type find the decoder.
///
/// The format to discover
- /// The if found otherwise null
- public IImageDecoder? FindDecoder(IImageFormat format)
+ /// The .
+ /// The format is not registered.
+ public IImageDecoder GetDecoder(IImageFormat format)
{
Guard.NotNull(format, nameof(format));
- return this.mimeTypeDecoders.TryGetValue(format, out IImageDecoder? decoder)
- ? decoder
- : null;
+ if (!this.mimeTypeDecoders.TryGetValue(format, out IImageDecoder? decoder))
+ {
+ ThrowInvalidDecoder(this);
+ }
+
+ return decoder;
}
///
/// For the specified mime type find the encoder.
///
/// The format to discover
- /// The if found otherwise null
- public IImageEncoder? FindEncoder(IImageFormat format)
+ /// The .
+ /// The format is not registered.
+ public IImageEncoder GetEncoder(IImageFormat format)
{
Guard.NotNull(format, nameof(format));
- return this.mimeTypeEncoders.TryGetValue(format, out IImageEncoder? encoder)
- ? encoder
- : null;
+ if (!this.mimeTypeEncoders.TryGetValue(format, out IImageEncoder? encoder))
+ {
+ ThrowInvalidDecoder(this);
+ }
+
+ return encoder;
}
///
/// Sets the max header size.
///
private void SetMaxHeaderSize() => this.MaxHeaderSize = this.imageFormatDetectors.Max(x => x.HeaderSize);
+
+ [DoesNotReturn]
+ internal static void ThrowInvalidDecoder(ImageFormatManager manager)
+ {
+ StringBuilder sb = new();
+ sb = sb.AppendLine("Image cannot be loaded. Available decoders:");
+
+ foreach (KeyValuePair val in manager.ImageDecoders)
+ {
+ sb = sb.AppendFormat(CultureInfo.InvariantCulture, " - {0} : {1}{2}", val.Key.Name, val.Value.GetType().Name, Environment.NewLine);
+ }
+
+ throw new UnknownImageFormatException(sb.ToString());
+ }
}
diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs
index b8a142d28..026c542dd 100644
--- a/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs
+++ b/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs
@@ -20,7 +20,7 @@ public sealed class JpegDecoder : SpecializedImageDecoder
public static JpegDecoder Instance { get; } = new();
///
- protected override IImageInfo 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));
diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
index f21ccdb62..511ec1ba1 100644
--- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
+++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
@@ -225,7 +225,7 @@ internal sealed class JpegDecoderCore : IRawJpegData, IImageDecoderInternals
}
///
- public IImageInfo Identify(BufferedReadStream stream, CancellationToken cancellationToken)
+ public ImageInfo Identify(BufferedReadStream stream, CancellationToken cancellationToken)
{
this.ParseStream(stream, spectralConverter: null, cancellationToken);
this.InitExifProfile();
diff --git a/src/ImageSharp/Formats/Pbm/PbmDecoder.cs b/src/ImageSharp/Formats/Pbm/PbmDecoder.cs
index f7b32b5fc..a7dd8a0eb 100644
--- a/src/ImageSharp/Formats/Pbm/PbmDecoder.cs
+++ b/src/ImageSharp/Formats/Pbm/PbmDecoder.cs
@@ -36,7 +36,7 @@ public sealed class PbmDecoder : ImageDecoder
public static PbmDecoder Instance { get; } = new();
///
- protected override IImageInfo 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));
diff --git a/src/ImageSharp/Formats/Pbm/PbmDecoderCore.cs b/src/ImageSharp/Formats/Pbm/PbmDecoderCore.cs
index 139cb2fcc..c5e0b0071 100644
--- a/src/ImageSharp/Formats/Pbm/PbmDecoderCore.cs
+++ b/src/ImageSharp/Formats/Pbm/PbmDecoderCore.cs
@@ -83,7 +83,7 @@ internal sealed class PbmDecoderCore : IImageDecoderInternals
}
///
- public IImageInfo Identify(BufferedReadStream stream, CancellationToken cancellationToken)
+ public ImageInfo Identify(BufferedReadStream stream, CancellationToken cancellationToken)
{
this.ProcessHeader(stream);
diff --git a/src/ImageSharp/Formats/Pbm/PbmEncoderCore.cs b/src/ImageSharp/Formats/Pbm/PbmEncoderCore.cs
index 7c7860c58..4a07173a1 100644
--- a/src/ImageSharp/Formats/Pbm/PbmEncoderCore.cs
+++ b/src/ImageSharp/Formats/Pbm/PbmEncoderCore.cs
@@ -68,7 +68,7 @@ internal sealed class PbmEncoderCore : IImageEncoderInternals
this.SanitizeAndSetEncoderOptions(image);
byte signature = this.DeduceSignature();
- this.WriteHeader(stream, signature, image.Size());
+ this.WriteHeader(stream, signature, image.Size);
this.WritePixels(stream, image.Frames.RootFrame);
diff --git a/src/ImageSharp/Formats/PixelTypeInfo.cs b/src/ImageSharp/Formats/PixelTypeInfo.cs
index 79ea884ce..1328c6528 100644
--- a/src/ImageSharp/Formats/PixelTypeInfo.cs
+++ b/src/ImageSharp/Formats/PixelTypeInfo.cs
@@ -4,6 +4,9 @@
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.PixelFormats;
+// TODO: Review this class as it's used to represent 2 different things.
+// 1.The encoded image pixel format.
+// 2. The pixel format of the decoded image.
namespace SixLabors.ImageSharp.Formats;
///
@@ -16,9 +19,7 @@ public class PixelTypeInfo
///
/// Color depth, in number of bits per pixel.
public PixelTypeInfo(int bitsPerPixel)
- {
- this.BitsPerPixel = bitsPerPixel;
- }
+ => this.BitsPerPixel = bitsPerPixel;
///
/// Initializes a new instance of the class.
@@ -43,12 +44,10 @@ public class PixelTypeInfo
public PixelAlphaRepresentation? AlphaRepresentation { get; }
internal static PixelTypeInfo Create()
- where TPixel : unmanaged, IPixel =>
- new PixelTypeInfo(Unsafe.SizeOf() * 8);
+ where TPixel : unmanaged, IPixel
+ => new(Unsafe.SizeOf() * 8);
internal static PixelTypeInfo Create(PixelAlphaRepresentation alpha)
where TPixel : unmanaged, IPixel
- {
- return new PixelTypeInfo(Unsafe.SizeOf() * 8, alpha);
- }
+ => new(Unsafe.SizeOf() * 8, alpha);
}
diff --git a/src/ImageSharp/Formats/Png/PngDecoder.cs b/src/ImageSharp/Formats/Png/PngDecoder.cs
index 56e76da10..f273ac2b9 100644
--- a/src/ImageSharp/Formats/Png/PngDecoder.cs
+++ b/src/ImageSharp/Formats/Png/PngDecoder.cs
@@ -20,7 +20,7 @@ public sealed class PngDecoder : ImageDecoder
public static PngDecoder Instance { get; } = new();
///
- protected override IImageInfo 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));
@@ -49,7 +49,7 @@ public sealed class PngDecoder : ImageDecoder
Guard.NotNull(stream, nameof(stream));
PngDecoderCore decoder = new(options, true);
- IImageInfo info = decoder.Identify(options.Configuration, stream, cancellationToken);
+ ImageInfo info = decoder.Identify(options.Configuration, stream, cancellationToken);
stream.Position = 0;
PngMetadata meta = info.Metadata.GetPngMetadata();
diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs
index 37cc8b2f6..3b2f100e0 100644
--- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs
+++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs
@@ -247,7 +247,7 @@ internal sealed class PngDecoderCore : IImageDecoderInternals
}
///
- public IImageInfo Identify(BufferedReadStream stream, CancellationToken cancellationToken)
+ public ImageInfo Identify(BufferedReadStream stream, CancellationToken cancellationToken)
{
ImageMetadata metadata = new();
PngMetadata pngMetadata = metadata.GetPngMetadata();
diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs
index 8b3dcc159..5a66fc7d4 100644
--- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs
+++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs
@@ -1300,7 +1300,7 @@ internal sealed class PngEncoderCore : IImageEncoderInternals, IDisposable
using IQuantizer frameQuantizer = quantizer.CreatePixelSpecificQuantizer(image.GetConfiguration());
frameQuantizer.BuildPalette(encoder.PixelSamplingStrategy, image);
- return frameQuantizer.QuantizeFrame(image.Frames.RootFrame, image.Bounds());
+ return frameQuantizer.QuantizeFrame(image.Frames.RootFrame, image.Bounds);
}
///
diff --git a/src/ImageSharp/Formats/SpecializedImageDecoder{T}.cs b/src/ImageSharp/Formats/SpecializedImageDecoder{T}.cs
index fa6461464..59fa59bb9 100644
--- a/src/ImageSharp/Formats/SpecializedImageDecoder{T}.cs
+++ b/src/ImageSharp/Formats/SpecializedImageDecoder{T}.cs
@@ -17,34 +17,54 @@ public abstract class SpecializedImageDecoder : ImageDecoder, ISpecializedIma
///
public Image Decode(T options, Stream stream)
where TPixel : unmanaged, IPixel
- => WithSeekableStream(
+ {
+ Image image = WithSeekableStream(
options.GeneralOptions,
stream,
s => this.Decode(options, s, default));
+ this.SetDecoderFormat(options.GeneralOptions.Configuration, image);
+ return image;
+ }
+
///
public Image Decode(T options, Stream stream)
- => WithSeekableStream(
+ {
+ Image image = WithSeekableStream(
options.GeneralOptions,
stream,
s => this.Decode(options, s, default));
+ this.SetDecoderFormat(options.GeneralOptions.Configuration, image);
+ return image;
+ }
+
///
- public Task> DecodeAsync(T options, Stream stream, CancellationToken cancellationToken = default)
+ public async Task> DecodeAsync(T options, Stream stream, CancellationToken cancellationToken = default)
where TPixel : unmanaged, IPixel
- => WithSeekableMemoryStreamAsync(
+ {
+ Image image = await WithSeekableMemoryStreamAsync(
options.GeneralOptions,
stream,
(s, ct) => this.Decode(options, s, ct),
- cancellationToken);
+ cancellationToken).ConfigureAwait(false);
+
+ this.SetDecoderFormat(options.GeneralOptions.Configuration, image);
+ return image;
+ }
///
- public Task DecodeAsync(T options, Stream stream, CancellationToken cancellationToken = default)
- => WithSeekableMemoryStreamAsync(
+ public async Task DecodeAsync(T options, Stream stream, CancellationToken cancellationToken = default)
+ {
+ Image image = await WithSeekableMemoryStreamAsync(
options.GeneralOptions,
stream,
(s, ct) => this.Decode(options, s, ct),
- cancellationToken);
+ cancellationToken).ConfigureAwait(false);
+
+ this.SetDecoderFormat(options.GeneralOptions.Configuration, image);
+ return image;
+ }
///
/// Decodes the image from the specified stream to an of a specific pixel type.
diff --git a/src/ImageSharp/Formats/Tga/TgaDecoder.cs b/src/ImageSharp/Formats/Tga/TgaDecoder.cs
index f6f1e6762..e7ff894da 100644
--- a/src/ImageSharp/Formats/Tga/TgaDecoder.cs
+++ b/src/ImageSharp/Formats/Tga/TgaDecoder.cs
@@ -20,7 +20,7 @@ public sealed class TgaDecoder : ImageDecoder
public static TgaDecoder Instance { get; } = new();
///
- protected override IImageInfo 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));
diff --git a/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs b/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs
index ebb47b775..9c32471fd 100644
--- a/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs
+++ b/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs
@@ -647,7 +647,7 @@ internal sealed class TgaDecoderCore : IImageDecoderInternals
}
///
- public IImageInfo Identify(BufferedReadStream stream, CancellationToken cancellationToken)
+ public ImageInfo Identify(BufferedReadStream stream, CancellationToken cancellationToken)
{
this.ReadFileHeader(stream);
return new ImageInfo(
diff --git a/src/ImageSharp/Formats/Tiff/TiffDecoder.cs b/src/ImageSharp/Formats/Tiff/TiffDecoder.cs
index 3ec9b3d68..e9dee4ee4 100644
--- a/src/ImageSharp/Formats/Tiff/TiffDecoder.cs
+++ b/src/ImageSharp/Formats/Tiff/TiffDecoder.cs
@@ -20,7 +20,7 @@ public class TiffDecoder : ImageDecoder
public static TiffDecoder Instance { get; } = new();
///
- protected override IImageInfo 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));
diff --git a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs
index 887d4eda4..e74c53e22 100644
--- a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs
+++ b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs
@@ -213,7 +213,7 @@ internal class TiffDecoderCore : IImageDecoderInternals
}
///
- public IImageInfo Identify(BufferedReadStream stream, CancellationToken cancellationToken)
+ public ImageInfo Identify(BufferedReadStream stream, CancellationToken cancellationToken)
{
this.inputStream = stream;
DirectoryReader reader = new(stream, this.configuration.MemoryAllocator);
diff --git a/src/ImageSharp/Formats/Webp/WebpDecoder.cs b/src/ImageSharp/Formats/Webp/WebpDecoder.cs
index 7a97b86a7..daa5eaf4f 100644
--- a/src/ImageSharp/Formats/Webp/WebpDecoder.cs
+++ b/src/ImageSharp/Formats/Webp/WebpDecoder.cs
@@ -20,7 +20,7 @@ public sealed class WebpDecoder : ImageDecoder
public static WebpDecoder Instance { get; } = new();
///
- protected override IImageInfo 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));
diff --git a/src/ImageSharp/Formats/Webp/WebpDecoderCore.cs b/src/ImageSharp/Formats/Webp/WebpDecoderCore.cs
index d313ebf76..29be86e22 100644
--- a/src/ImageSharp/Formats/Webp/WebpDecoderCore.cs
+++ b/src/ImageSharp/Formats/Webp/WebpDecoderCore.cs
@@ -145,7 +145,7 @@ internal sealed class WebpDecoderCore : IImageDecoderInternals, IDisposable
}
///
- public IImageInfo Identify(BufferedReadStream stream, CancellationToken cancellationToken)
+ public ImageInfo Identify(BufferedReadStream stream, CancellationToken cancellationToken)
{
this.currentStream = stream;
diff --git a/src/ImageSharp/IImage.cs b/src/ImageSharp/IImage.cs
deleted file mode 100644
index 9940a7954..000000000
--- a/src/ImageSharp/IImage.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Six Labors Split License.
-
-namespace SixLabors.ImageSharp;
-
-///
-/// Encapsulates the properties and methods that describe an image.
-///
-public interface IImage : IImageInfo, IDisposable
-{
-}
diff --git a/src/ImageSharp/IImageInfo.cs b/src/ImageSharp/IImageInfo.cs
deleted file mode 100644
index 32ca9a9a2..000000000
--- a/src/ImageSharp/IImageInfo.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Six Labors Split License.
-
-using SixLabors.ImageSharp.Formats;
-using SixLabors.ImageSharp.Metadata;
-
-namespace SixLabors.ImageSharp;
-
-///
-/// Encapsulates properties that describe basic image information including dimensions, pixel type information
-/// and additional metadata.
-///
-public interface IImageInfo
-{
- ///
- /// Gets information about the image pixels.
- ///
- PixelTypeInfo PixelType { get; }
-
- ///
- /// Gets the width.
- ///
- int Width { get; }
-
- ///
- /// Gets the height.
- ///
- int Height { get; }
-
- ///
- /// Gets the metadata of the image.
- ///
- ImageMetadata Metadata { get; }
-}
diff --git a/src/ImageSharp/Image.Decode.cs b/src/ImageSharp/Image.Decode.cs
index a556cbceb..ae38144c0 100644
--- a/src/ImageSharp/Image.Decode.cs
+++ b/src/ImageSharp/Image.Decode.cs
@@ -1,6 +1,5 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
-#nullable disable
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Memory;
@@ -45,6 +44,7 @@ public abstract partial class Image
/// The general configuration.
/// The image stream to read the header from.
/// The mime type or null if none found.
+ /// The input format is not recognized.
private static IImageFormat InternalDetectFormat(Configuration configuration, Stream stream)
{
// We take a minimum of the stream length vs the max header size and always check below
@@ -52,7 +52,7 @@ public abstract partial class Image
int headerSize = (int)Math.Min(configuration.MaxHeaderSize, stream.Length);
if (headerSize <= 0)
{
- return null;
+ ImageFormatManager.ThrowInvalidDecoder(configuration.ImageFormatsManager);
}
// Header sizes are so small, that headersBuffer will be always stackalloc-ed in practice,
@@ -77,19 +77,21 @@ public abstract partial class Image
// Does the given stream contain enough data to fit in the header for the format
// and does that data match the format specification?
// Individual formats should still check since they are public.
- IImageFormat format = null;
+ IImageFormat? format = null;
foreach (IImageFormatDetector formatDetector in configuration.ImageFormatsManager.FormatDetectors)
{
- if (formatDetector.HeaderSize <= headerSize)
+ if (formatDetector.HeaderSize <= headerSize && formatDetector.TryDetectFormat(headersBuffer, out IImageFormat? attemptFormat))
{
- if (formatDetector.TryDetectFormat(headersBuffer, out IImageFormat attemptFormat))
- {
- format = attemptFormat;
- }
+ format = attemptFormat;
}
}
- return format;
+ if (format is null)
+ {
+ ImageFormatManager.ThrowInvalidDecoder(configuration.ImageFormatsManager);
+ }
+
+ return format!;
}
///
@@ -97,15 +99,11 @@ public abstract partial class Image
///
/// The general decoder options.
/// The image stream to read the header from.
- /// The IImageFormat.
- /// The image format or null if none found.
- private static IImageDecoder DiscoverDecoder(DecoderOptions options, Stream stream, out IImageFormat format)
+ /// The .
+ private static IImageDecoder DiscoverDecoder(DecoderOptions options, Stream stream)
{
- format = InternalDetectFormat(options.Configuration, stream);
-
- return format != null
- ? options.Configuration.ImageFormatsManager.FindDecoder(format)
- : null;
+ IImageFormat format = InternalDetectFormat(options.Configuration, stream);
+ return options.Configuration.ImageFormatsManager.GetDecoder(format);
}
///
@@ -117,60 +115,36 @@ public abstract partial class Image
///
/// A new .
///
- private static (Image Image, IImageFormat Format) Decode(DecoderOptions options, Stream stream)
+ private static Image Decode(DecoderOptions options, Stream stream)
where TPixel : unmanaged, IPixel
{
- IImageDecoder decoder = DiscoverDecoder(options, stream, out IImageFormat format);
- if (decoder is null)
- {
- return (null, null);
- }
-
- Image img = decoder.Decode(options, stream);
- return (img, format);
+ IImageDecoder decoder = DiscoverDecoder(options, stream);
+ return decoder.Decode(options, stream);
}
- private static async Task<(Image Image, IImageFormat Format)> DecodeAsync(
+ private static Task> DecodeAsync(
DecoderOptions options,
Stream stream,
CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel
{
- IImageDecoder decoder = DiscoverDecoder(options, stream, out IImageFormat format);
- if (decoder is null)
- {
- return (null, null);
- }
-
- Image img = await decoder.DecodeAsync(options, stream, cancellationToken).ConfigureAwait(false);
- return (img, format);
+ IImageDecoder decoder = DiscoverDecoder(options, stream);
+ return decoder.DecodeAsync(options, stream, cancellationToken);
}
- private static (Image Image, IImageFormat Format) Decode(DecoderOptions options, Stream stream)
+ private static Image Decode(DecoderOptions options, Stream stream)
{
- IImageDecoder decoder = DiscoverDecoder(options, stream, out IImageFormat format);
- if (decoder is null)
- {
- return (null, null);
- }
-
- Image img = decoder.Decode(options, stream);
- return (img, format);
+ IImageDecoder decoder = DiscoverDecoder(options, stream);
+ return decoder.Decode(options, stream);
}
- private static async Task<(Image Image, IImageFormat Format)> DecodeAsync(
+ private static Task DecodeAsync(
DecoderOptions options,
Stream stream,
CancellationToken cancellationToken)
{
- IImageDecoder decoder = DiscoverDecoder(options, stream, out IImageFormat format);
- if (decoder is null)
- {
- return (null, null);
- }
-
- Image img = await decoder.DecodeAsync(options, stream, cancellationToken).ConfigureAwait(false);
- return (img, format);
+ IImageDecoder decoder = DiscoverDecoder(options, stream);
+ return decoder.DecodeAsync(options, stream, cancellationToken);
}
///
@@ -178,14 +152,11 @@ public abstract partial class Image
///
/// The general decoder options.
/// The stream.
- ///
- /// The or null if a suitable info detector is not found.
- ///
- private static (IImageInfo ImageInfo, IImageFormat Format) InternalIdentify(DecoderOptions options, Stream stream)
+ /// The .
+ private static ImageInfo InternalIdentify(DecoderOptions options, Stream stream)
{
- IImageDecoder decoder = DiscoverDecoder(options, stream, out IImageFormat format);
- IImageInfo info = decoder?.Identify(options, stream);
- return (info, format);
+ IImageDecoder decoder = DiscoverDecoder(options, stream);
+ return decoder.Identify(options, stream);
}
///
@@ -194,22 +165,13 @@ public abstract partial class Image
/// The general decoder options.
/// The stream.
/// The token to monitor for cancellation requests.
- ///
- /// The or null if a suitable info detector is not found.
- ///
- private static async Task<(IImageInfo ImageInfo, IImageFormat Format)> InternalIdentifyAsync(
+ /// The .
+ private static Task InternalIdentifyAsync(
DecoderOptions options,
Stream stream,
CancellationToken cancellationToken)
{
- IImageDecoder decoder = DiscoverDecoder(options, stream, out IImageFormat format);
-
- if (decoder is null)
- {
- return (null, null);
- }
-
- IImageInfo info = await decoder.IdentifyAsync(options, stream, cancellationToken).ConfigureAwait(false);
- return (info, format);
+ IImageDecoder decoder = DiscoverDecoder(options, stream);
+ return decoder.IdentifyAsync(options, stream, cancellationToken);
}
}
diff --git a/src/ImageSharp/Image.FromBytes.cs b/src/ImageSharp/Image.FromBytes.cs
index 7a2e9d736..96ef84510 100644
--- a/src/ImageSharp/Image.FromBytes.cs
+++ b/src/ImageSharp/Image.FromBytes.cs
@@ -1,7 +1,6 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
-using System.Diagnostics.CodeAnalysis;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.PixelFormats;
@@ -15,215 +14,129 @@ public abstract partial class Image
///
/// By reading the header on the provided byte span this calculates the images format.
///
- /// The byte span containing encoded image data to read the header from.
- /// The format or null if none found.
- /// returns true when format was detected otherwise false.
- public static bool TryDetectFormat(ReadOnlySpan data, [NotNullWhen(true)] out IImageFormat? format)
- => TryDetectFormat(DecoderOptions.Default, data, out format);
+ /// The byte span containing encoded image data to read the header from.
+ /// The .
+ /// The image format is not supported.
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
+ public static IImageFormat DetectFormat(ReadOnlySpan buffer)
+ => DetectFormat(DecoderOptions.Default, buffer);
///
/// By reading the header on the provided byte span this calculates the images format.
///
/// The general decoder options.
- /// The byte span containing encoded image data to read the header from.
- /// The mime type or null if none found.
+ /// The byte span containing encoded image data to read the header from.
+ /// The .
/// The options are null.
- /// returns true when format was detected otherwise false.
- public static bool TryDetectFormat(DecoderOptions options, ReadOnlySpan data, [NotNullWhen(true)] out IImageFormat? format)
+ /// The image format is not supported.
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
+ public static unsafe IImageFormat DetectFormat(DecoderOptions options, ReadOnlySpan buffer)
{
Guard.NotNull(options, nameof(options.Configuration));
- Configuration configuration = options.Configuration;
- int maxHeaderSize = configuration.MaxHeaderSize;
- if (maxHeaderSize <= 0)
+ fixed (byte* ptr = buffer)
{
- format = null;
- return false;
+ using UnmanagedMemoryStream stream = new(ptr, buffer.Length);
+ return DetectFormat(options, stream);
}
-
- foreach (IImageFormatDetector detector in configuration.ImageFormatsManager.FormatDetectors)
- {
- if (detector.TryDetectFormat(data, out format))
- {
- return true;
- }
- }
-
- format = default;
- return false;
}
///
/// Reads the raw image information from the specified stream without fully decoding it.
///
- /// The byte span containing encoded image data to read the header from.
- /// The data is null.
- /// The data is not readable.
- ///
- /// The or null if suitable info detector not found.
- ///
- public static IImageInfo Identify(ReadOnlySpan data) => Identify(data, out IImageFormat _);
-
- ///
- /// Reads the raw image information from the specified stream without fully decoding it.
- ///
- /// The byte array containing encoded image data to read the header from.
- /// The format type of the decoded image.
- /// The data is null.
- /// The data is not readable.
- ///
- /// The or null if suitable info detector not found.
- ///
- public static IImageInfo Identify(ReadOnlySpan data, out IImageFormat format)
- => Identify(DecoderOptions.Default, data, out format);
+ /// The byte array containing encoded image data to read the header from.
+ /// The .
+ /// The image format is not supported.
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
+ public static ImageInfo Identify(ReadOnlySpan buffer)
+ => Identify(DecoderOptions.Default, buffer);
///
/// Reads the raw image information from the specified span of bytes without fully decoding it.
///
/// The general decoder options.
- /// The byte span containing encoded image data to read the header from.
- /// The format type of the decoded image.
- /// The configuration is null.
- /// The data is null.
- /// The data is not readable.
- ///
- /// The or null if suitable info detector is not found.
- ///
- public static unsafe IImageInfo Identify(DecoderOptions options, ReadOnlySpan data, out IImageFormat format)
+ /// The byte span containing encoded image data to read the header from.
+ /// The .
+ /// The options are null.
+ /// The image format is not supported.
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
+ public static unsafe ImageInfo Identify(DecoderOptions options, ReadOnlySpan buffer)
{
- fixed (byte* ptr = data)
+ fixed (byte* ptr = buffer)
{
- using var stream = new UnmanagedMemoryStream(ptr, data.Length);
- return Identify(options, stream, out format);
+ using UnmanagedMemoryStream stream = new(ptr, buffer.Length);
+ return Identify(options, stream);
}
}
///
- /// Load a new instance of from the given encoded byte span.
- ///
- /// The byte span containing encoded image data.
- /// The pixel format.
- /// Image format not recognised.
- /// Image contains invalid content.
- /// Image format is not supported.
- /// A new .
- public static Image Load(ReadOnlySpan data)
- where TPixel : unmanaged, IPixel
- => Load(DecoderOptions.Default, data);
-
- ///
- /// Load a new instance of from the given encoded byte span.
+ /// Creates a new instance of the class from the given byte span.
+ /// The pixel format is automatically determined by the decoder.
///
- /// The byte span containing image data.
- /// The mime type of the decoded image.
- /// The pixel format.
- /// Image format not recognised.
- /// Image contains invalid content.
- /// Image format is not supported.
- /// A new .
- public static Image Load(ReadOnlySpan data, out IImageFormat format)
- where TPixel : unmanaged, IPixel
- => Load(DecoderOptions.Default, data, out format);
+ /// The byte span containing encoded image data.
+ /// .
+ /// The image format is not supported.
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
+ /// The .
+ public static Image Load(ReadOnlySpan buffer)
+ => Load(DecoderOptions.Default, buffer);
///
- /// Load a new instance of from the given encoded byte span.
+ /// Creates a new instance of the class from the given byte span.
+ /// The pixel format is automatically determined by the decoder.
///
/// The general decoder options.
- /// The byte span containing encoded image data.
- /// The pixel format.
+ /// The byte span containing encoded image data.
+ /// .
/// The options are null.
- /// Image format not recognised.
- /// Image contains invalid content.
- /// Image format is not supported.
- /// A new .
- public static unsafe Image Load(DecoderOptions options, ReadOnlySpan data)
- where TPixel : unmanaged, IPixel
+ /// The image format is not supported.
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
+ public static unsafe Image Load(DecoderOptions options, ReadOnlySpan buffer)
{
- fixed (byte* ptr = data)
+ fixed (byte* ptr = buffer)
{
- using var stream = new UnmanagedMemoryStream(ptr, data.Length);
- return Load(options, stream);
+ using UnmanagedMemoryStream stream = new(ptr, buffer.Length);
+ return Load(options, stream);
}
}
///
- /// Load a new instance of from the given encoded byte span.
+ /// Creates a new instance of the class from the given byte span.
///
- /// The general decoder options.
- /// The byte span containing image data.
- /// The of the decoded image.
/// The pixel format.
- /// The options are null.
- /// Image format not recognised.
- /// Image contains invalid content.
- /// Image format is not supported.
- /// A new .
- public static unsafe Image Load(
- DecoderOptions options,
- ReadOnlySpan data,
- out IImageFormat format)
+ /// The byte span containing encoded image data.
+ /// .
+ /// The image format is not supported.
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
+ public static Image Load(ReadOnlySpan data)
where TPixel : unmanaged, IPixel
- {
- fixed (byte* ptr = data)
- {
- using var stream = new UnmanagedMemoryStream(ptr, data.Length);
- return Load(options, stream, out format);
- }
- }
-
- ///
- /// Load a new instance of from the given encoded byte span.
- ///
- /// The byte span containing image data.
- /// Image format not recognised.
- /// Image contains invalid content.
- /// Image format is not supported.
- /// The .
- public static Image Load(ReadOnlySpan data)
- => Load(DecoderOptions.Default, data);
-
- ///
- /// Load a new instance of from the given encoded byte array.
- ///
- /// The byte span containing image data.
- /// The detected format.
- /// The decoder is null.
- /// Image format not recognised.
- /// Image contains invalid content.
- /// Image format is not supported.
- /// The .
- public static Image Load(ReadOnlySpan data, out IImageFormat format)
- => Load(DecoderOptions.Default, data, out format);
-
- ///
- /// Decodes a new instance of from the given encoded byte span.
- ///
- /// The general decoder options.
- /// The byte span containing image data.
- /// The .
- public static Image Load(DecoderOptions options, ReadOnlySpan data)
- => Load(options, data, out _);
+ => Load(DecoderOptions.Default, data);
///
- /// Load a new instance of from the given encoded byte span.
+ /// Creates a new instance of the class from the given byte span.
///
+ /// The pixel format.
/// The general decoder options.
- /// The byte span containing image data.
- /// The of the decoded image.>
+ /// The byte span containing encoded image data.
+ /// .
/// The options are null.
- /// Image format not recognised.
- /// Image contains invalid content.
- /// Image format is not supported.
- /// The .
- public static unsafe Image Load(
- DecoderOptions options,
- ReadOnlySpan data,
- out IImageFormat format)
+ /// The image format is not supported.
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
+ public static unsafe Image Load(DecoderOptions options, ReadOnlySpan data)
+ where TPixel : unmanaged, IPixel
{
fixed (byte* ptr = data)
{
- using var stream = new UnmanagedMemoryStream(ptr, data.Length);
- return Load(options, stream, out format);
+ using UnmanagedMemoryStream stream = new(ptr, data.Length);
+ return Load(options, stream);
}
}
}
diff --git a/src/ImageSharp/Image.FromFile.cs b/src/ImageSharp/Image.FromFile.cs
index cd27e2882..24a737493 100644
--- a/src/ImageSharp/Image.FromFile.cs
+++ b/src/ImageSharp/Image.FromFile.cs
@@ -1,7 +1,6 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
-using System.Diagnostics.CodeAnalysis;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.PixelFormats;
@@ -13,298 +12,238 @@ namespace SixLabors.ImageSharp;
public abstract partial class Image
{
///
- /// By reading the header on the provided file this calculates the images mime type.
+ /// Detects the encoded image format type from the specified file.
///
- /// The image file to open and to read the header from.
- /// The mime type or null if none found.
- /// returns true when format was detected otherwise false.
- public static bool TryDetectFormat(string filePath, [NotNullWhen(true)] out IImageFormat? format)
- => TryDetectFormat(DecoderOptions.Default, filePath, out format);
+ /// The image file to open and to read the header from.
+ /// The .
+ /// The path is null.
+ /// The file stream is not readable or the image format is not supported.
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
+ public static IImageFormat DetectFormat(string path)
+ => DetectFormat(DecoderOptions.Default, path);
///
- /// By reading the header on the provided file this calculates the images mime type.
+ /// Detects the encoded image format type from the specified file.
///
/// The general decoder options.
- /// The image file to open and to read the header from.
- /// The mime type or null if none found.
- /// The configuration is null.
- /// returns true when format was detected otherwise false.
- public static bool TryDetectFormat(DecoderOptions options, string filePath, [NotNullWhen(true)] out IImageFormat? format)
+ /// The image file to open and to read the header from.
+ /// The .
+ /// The options are null.
+ /// The path is null.
+ /// The file stream is not readable or the image format is not supported.
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
+ public static IImageFormat DetectFormat(DecoderOptions options, string path)
{
Guard.NotNull(options, nameof(options));
- using Stream file = options.Configuration.FileSystem.OpenRead(filePath);
- return TryDetectFormat(options, file, out format);
+ using Stream file = options.Configuration.FileSystem.OpenRead(path);
+ return DetectFormat(options, file);
}
///
- /// Reads the raw image information from the specified stream without fully decoding it.
+ /// Detects the encoded image format type from the specified file.
///
- /// The image file to open and to read the header from.
- ///
- /// The or null if suitable info detector not found.
- ///
- public static IImageInfo Identify(string filePath)
- => Identify(filePath, out IImageFormat _);
-
- ///
- /// Reads the raw image information from the specified stream without fully decoding it.
- ///
- /// The image file to open and to read the header from.
- /// The format type of the decoded image.
- ///
- /// The or null if suitable info detector not found.
- ///
- public static IImageInfo Identify(string filePath, out IImageFormat format)
- => Identify(DecoderOptions.Default, filePath, out format);
+ /// The image file to open and to read the header from.
+ /// The token to monitor for cancellation requests.
+ /// A representing the asynchronous operation.
+ public static Task DetectFormatAsync(
+ string path,
+ CancellationToken cancellationToken = default)
+ => DetectFormatAsync(DecoderOptions.Default, path, cancellationToken);
///
- /// Reads the raw image information from the specified stream without fully decoding it.
+ /// Detects the encoded image format type from the specified file.
///
/// The general decoder options.
- /// The image file to open and to read the header from.
- /// The format type of the decoded image.
- /// The configuration is null.
- ///
- /// The or null if suitable info detector is not found.
- ///
- public static IImageInfo Identify(DecoderOptions options, string filePath, out IImageFormat format)
+ /// The image file to open and to read the header from.
+ /// The token to monitor for cancellation requests.
+ /// A representing the asynchronous operation.
+ /// The options are null.
+ /// The path is null.
+ /// The file stream is not readable or the image format is not supported.
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
+ public static async Task DetectFormatAsync(
+ DecoderOptions options,
+ string path,
+ CancellationToken cancellationToken = default)
{
Guard.NotNull(options, nameof(options));
- using Stream file = options.Configuration.FileSystem.OpenRead(filePath);
- return Identify(options, file, out format);
+
+ using Stream stream = options.Configuration.FileSystem.OpenRead(path);
+ return await DetectFormatAsync(options, stream, cancellationToken).ConfigureAwait(false);
}
///
- /// Reads the raw image information from the specified stream without fully decoding it.
+ /// Reads the raw image information from the specified file path without fully decoding it.
+ /// A return value indicates whether the operation succeeded.
///
- /// The image file to open and to read the header from.
- /// The token to monitor for cancellation requests.
- /// The configuration is null.
- ///
- /// The representing the asynchronous operation with the parameter type
- /// property set to null if suitable info detector is not found.
- ///
- public static Task IdentifyAsync(string filePath, CancellationToken cancellationToken = default)
- => IdentifyAsync(DecoderOptions.Default, filePath, cancellationToken);
+ /// The image file to open and to read the header from.
+ /// if the information can be read; otherwise,
+ /// The path is null.
+ /// The file stream is not readable or the image format is not supported.
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
+ public static ImageInfo Identify(string path)
+ => Identify(DecoderOptions.Default, path);
///
- /// Reads the raw image information from the specified stream without fully decoding it.
+ /// Reads the raw image information from the specified file path without fully decoding it.
///
/// The general decoder options.
- /// The image file to open and to read the header from.
- /// The token to monitor for cancellation requests.
- /// The configuration is null.
- ///
- /// The representing the asynchronous operation with the parameter type
- /// property set to null if suitable info detector is not found.
- ///
- public static async Task IdentifyAsync(
- DecoderOptions options,
- string filePath,
- CancellationToken cancellationToken = default)
+ /// The image file to open and to read the header from.
+ /// The .
+ /// The options are null.
+ /// The path is null.
+ /// The file stream is not readable or the image format is not supported.
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
+ public static ImageInfo Identify(DecoderOptions options, string path)
{
- (IImageInfo ImageInfo, IImageFormat Format) res =
- await IdentifyWithFormatAsync(options, filePath, cancellationToken).ConfigureAwait(false);
- return res.ImageInfo;
+ Guard.NotNull(options, nameof(options));
+
+ using Stream stream = options.Configuration.FileSystem.OpenRead(path);
+ return Identify(options, stream);
}
///
/// Reads the raw image information from the specified stream without fully decoding it.
///
- /// The image file to open and to read the header from.
+ /// The image file to open and to read the header from.
/// The token to monitor for cancellation requests.
- /// The configuration is null.
+ /// The options are null.
///
- /// The representing the asynchronous operation with the parameter type
- /// property set to null if suitable info detector is not found.
+ /// The representing the asynchronous operation.
///
- public static Task<(IImageInfo ImageInfo, IImageFormat Format)> IdentifyWithFormatAsync(
- string filePath,
- CancellationToken cancellationToken = default)
- => IdentifyWithFormatAsync(DecoderOptions.Default, filePath, cancellationToken);
+ /// The path is null.
+ /// The file stream is not readable or the image format is not supported.
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
+ public static Task IdentifyAsync(string path, CancellationToken cancellationToken = default)
+ => IdentifyAsync(DecoderOptions.Default, path, cancellationToken);
///
/// Reads the raw image information from the specified stream without fully decoding it.
///
/// The general decoder options.
- /// The image file to open and to read the header from.
+ /// The image file to open and to read the header from.
/// The token to monitor for cancellation requests.
- /// The configuration is null.
///
- /// The representing the asynchronous operation with the parameter type
- /// property set to null if suitable info detector is not found.
+ /// The representing the asynchronous operation.
///
- public static async Task<(IImageInfo ImageInfo, IImageFormat Format)> IdentifyWithFormatAsync(
+ /// The options are null.
+ /// The path is null.
+ /// The file stream is not readable or the image format is not supported.
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
+ public static async Task IdentifyAsync(
DecoderOptions options,
- string filePath,
+ string path,
CancellationToken cancellationToken = default)
{
Guard.NotNull(options, nameof(options));
- using Stream stream = options.Configuration.FileSystem.OpenRead(filePath);
- return await IdentifyWithFormatAsync(options, stream, cancellationToken)
- .ConfigureAwait(false);
+ using Stream stream = options.Configuration.FileSystem.OpenRead(path);
+ return await IdentifyAsync(options, stream, cancellationToken).ConfigureAwait(false);
}
///
- /// Create a new instance of the class from the given file.
+ /// Creates a new instance of the class from the given file path.
+ /// The pixel format is automatically determined by the decoder.
///
/// The file path to the image.
- ///
- /// Thrown if the stream is not readable nor seekable.
- ///
- /// The .
+ /// .
+ /// The path is null.
+ /// The file stream is not readable or the image format is not supported.
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
public static Image Load(string path)
=> Load(DecoderOptions.Default, path);
///
- /// Create a new instance of the class from the given file.
- ///
- /// The file path to the image.
- /// The mime type of the decoded image.
- ///
- /// Thrown if the stream is not readable nor seekable.
- ///
- /// A new .
- public static Image Load(string path, out IImageFormat format)
- => Load(DecoderOptions.Default, path, out format);
-
- ///
- /// Create a new instance of the class from the given file.
+ /// Creates a new instance of the class from the given file path.
+ /// The pixel format is automatically determined by the decoder.
///
/// The general decoder options.
/// The file path to the image.
- /// The configuration is null.
+ /// .
+ /// The options are null.
/// The path is null.
- /// Image format not recognised.
- /// Image format is not supported.
- /// Image contains invalid content.
- /// The .
+ /// The file stream is not readable or the image format is not supported.
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
public static Image Load(DecoderOptions options, string path)
- => Load(options, path, out _);
-
- ///
- /// Create a new instance of the class from the given file.
- ///
- /// The general decoder options.
- /// The file path to the image.
- /// The token to monitor for cancellation requests.
- /// The configuration is null.
- /// The path is null.
- /// Image format not recognised.
- /// Image format is not supported.
- /// Image contains invalid content.
- /// A representing the asynchronous operation.
- public static async Task LoadAsync(
- DecoderOptions options,
- string path,
- CancellationToken cancellationToken = default)
{
+ Guard.NotNull(options, nameof(options));
+ Guard.NotNull(path, nameof(path));
+
using Stream stream = options.Configuration.FileSystem.OpenRead(path);
- (Image img, _) = await LoadWithFormatAsync(options, stream, cancellationToken)
- .ConfigureAwait(false);
- return img;
+ return Load(options, stream);
}
///
- /// Create a new instance of the class from the given file.
+ /// Creates a new instance of the class from the given file path.
+ /// The pixel format is automatically determined by the decoder.
///
/// The file path to the image.
/// The token to monitor for cancellation requests.
- /// The configuration is null.
- /// The path is null.
- /// The decoder is null.
- /// Image format not recognised.
- /// Image format is not supported.
- /// Image contains invalid content.
/// A representing the asynchronous operation.
+ /// The path is null.
+ /// The file stream is not readable or the image format is not supported.
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
public static Task LoadAsync(string path, CancellationToken cancellationToken = default)
=> LoadAsync(DecoderOptions.Default, path, cancellationToken);
///
- /// Create a new instance of the class from the given file.
- ///
- /// The file path to the image.
- /// The token to monitor for cancellation requests.
- /// The configuration is null.
- /// The path is null.
- /// Image format not recognised.
- /// Image contains invalid content.
- /// Image format is not supported.
- /// The pixel format.
- /// A representing the asynchronous operation.
- public static Task> LoadAsync(string path, CancellationToken cancellationToken = default)
- where TPixel : unmanaged, IPixel
- => LoadAsync(DecoderOptions.Default, path, cancellationToken);
-
- ///
- /// Create a new instance of the class from the given file.
+ /// Creates a new instance of the class from the given file path.
+ /// The pixel format is automatically determined by the decoder.
///
/// The general decoder options.
/// The file path to the image.
/// The token to monitor for cancellation requests.
- /// The configuration is null.
- /// The path is null.
- /// Image format not recognised.
- /// Image format is not supported.
- /// Image contains invalid content.
- /// The pixel format.
/// A representing the asynchronous operation.
- public static async Task> LoadAsync(
+ /// The options are null.
+ /// The path is null.
+ /// The file stream is not readable or the image format is not supported.
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
+ public static async Task LoadAsync(
DecoderOptions options,
string path,
CancellationToken cancellationToken = default)
- where TPixel : unmanaged, IPixel
{
- Guard.NotNull(options, nameof(options));
-
using Stream stream = options.Configuration.FileSystem.OpenRead(path);
- (Image img, _) =
- await LoadWithFormatAsync(options, stream, cancellationToken).ConfigureAwait(false);
- return img;
+ return await LoadAsync(options, stream, cancellationToken).ConfigureAwait(false);
}
///
- /// Create a new instance of the class from the given file.
+ /// Creates a new instance of the class from the given file path.
///
+ /// The pixel format.
/// The file path to the image.
+ /// .
/// The path is null.
- /// Image format not recognised.
- /// Image contains invalid content.
- /// Image format is not supported.
- /// The pixel format.
- /// A new .
+ /// The file stream is not readable or the image format is not supported.
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
public static Image Load(string path)
where TPixel : unmanaged, IPixel
=> Load(DecoderOptions.Default, path);
///
- /// Create a new instance of the class from the given file.
+ /// Creates a new instance of the class from the given file path.
///
- /// The file path to the image.
- /// The mime type of the decoded image.
- /// The path is null.
- /// Image format not recognised.
- /// Image contains invalid content.
- /// Image format is not supported.
/// The pixel format.
- /// A new .
- public static Image Load(string path, out IImageFormat format)
- where TPixel : unmanaged, IPixel
- => Load(DecoderOptions.Default, path, out format);
-
- ///
- /// Create a new instance of the class from the given file.
- ///
/// The general decoder options.
/// The file path to the image.
- /// The configuration is null.
+ /// .
+ /// The options are null.
/// The path is null.
- /// Image format not recognised.
- /// Image format is not supported.
- /// Image contains invalid content.
- /// The pixel format.
- /// A new .
+ /// The file stream is not readable or the image format is not supported.
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
public static Image Load(DecoderOptions options, string path)
where TPixel : unmanaged, IPixel
{
@@ -316,47 +255,43 @@ public abstract partial class Image
}
///
- /// Create a new instance of the class from the given file.
+ /// Creates a new instance of the class from the given file path.
///
- /// The general decoder options.
+ /// The pixel format.
/// The file path to the image.
- /// The mime type of the decoded image.
- /// The configuration is null.
+ /// The token to monitor for cancellation requests.
+ /// A representing the asynchronous operation.
/// The path is null.
- /// Image format not recognised.
- /// Image format is not supported.
- /// Image contains invalid content.
- /// The pixel format.
- /// A new .
- public static Image Load(DecoderOptions options, string path, out IImageFormat format)
+ /// The file stream is not readable or the image format is not supported.
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
+ public static Task> LoadAsync(string path, CancellationToken cancellationToken = default)
where TPixel : unmanaged, IPixel
- {
- Guard.NotNull(options, nameof(options));
- Guard.NotNull(path, nameof(path));
-
- using Stream stream = options.Configuration.FileSystem.OpenRead(path);
- return Load(options, stream, out format);
- }
+ => LoadAsync(DecoderOptions.Default, path, cancellationToken);
///
- /// Create a new instance of the class from the given file.
- /// The pixel type is selected by the decoder.
+ /// Creates a new instance of the class from the given file path.
///
+ /// The pixel format.
/// The general decoder options.
/// The file path to the image.
- /// The mime type of the decoded image.
- /// The configuration is null.
+ /// The token to monitor for cancellation requests.
+ /// A representing the asynchronous operation.
+ /// The options are null.
/// The path is null.
- /// Image format not recognised.
- /// Image format is not supported.
- /// Image contains invalid content.
- /// A new .
- public static Image Load(DecoderOptions options, string path, out IImageFormat format)
+ /// The file stream is not readable or the image format is not supported.
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
+ public static async Task> LoadAsync(
+ DecoderOptions options,
+ string path,
+ CancellationToken cancellationToken = default)
+ where TPixel : unmanaged, IPixel
{
Guard.NotNull(options, nameof(options));
Guard.NotNull(path, nameof(path));
using Stream stream = options.Configuration.FileSystem.OpenRead(path);
- return Load(options, stream, out format);
+ return await LoadAsync(options, stream, cancellationToken).ConfigureAwait(false);
}
}
diff --git a/src/ImageSharp/Image.FromStream.cs b/src/ImageSharp/Image.FromStream.cs
index 63b9b5c1b..1748ca00e 100644
--- a/src/ImageSharp/Image.FromStream.cs
+++ b/src/ImageSharp/Image.FromStream.cs
@@ -1,9 +1,6 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
-using System.Diagnostics.CodeAnalysis;
-using System.Globalization;
-using System.Text;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.IO;
using SixLabors.ImageSharp.PixelFormats;
@@ -16,54 +13,62 @@ namespace SixLabors.ImageSharp;
public abstract partial class Image
{
///
- /// By reading the header on the provided stream this calculates the images format type.
+ /// Detects the encoded image format type from the specified stream.
///
/// The image stream to read the header from.
- /// The format type or null if none found.
+ /// The .
/// The stream is null.
- /// The stream is not readable.
- /// returns true when format was detected otherwise false.
- public static bool TryDetectFormat(Stream stream, [NotNullWhen(true)] out IImageFormat? format)
- => TryDetectFormat(DecoderOptions.Default, stream, out format);
+ /// The stream is not readable or the image format is not supported.
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
+ public static IImageFormat DetectFormat(Stream stream)
+ => DetectFormat(DecoderOptions.Default, stream);
///
- /// By reading the header on the provided stream this calculates the images format type.
+ /// Detects the encoded image format type from the specified stream.
///
/// The general decoder options.
/// The image stream to read the header from.
- /// The format type or null if none found.
+ /// if a match is found; otherwise,
/// The options are null.
/// The stream is null.
- /// The stream is not readable.
- /// returns true when format was detected otherwise false.
- public static bool TryDetectFormat(DecoderOptions options, Stream stream, [NotNullWhen(true)] out IImageFormat? format)
- {
- format = WithSeekableStream(options, stream, s => InternalDetectFormat(options.Configuration, s));
- return format != null;
- }
+ /// The stream is not readable or the image format is not supported.
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
+ public static IImageFormat DetectFormat(DecoderOptions options, Stream stream)
+ => WithSeekableStream(options, stream, s => InternalDetectFormat(options.Configuration, s));
///
- /// By reading the header on the provided stream this calculates the images format type.
+ /// Detects the encoded image format type from the specified stream.
///
/// The image stream to read the header from.
/// The token to monitor for cancellation requests.
+ /// A representing the asynchronous operation.
/// The stream is null.
- /// The stream is not readable.
- /// A representing the asynchronous operation or null if none is found.
- public static Task DetectFormatAsync(Stream stream, CancellationToken cancellationToken = default)
+ /// The stream is not readable or the image format is not supported.
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
+ public static Task DetectFormatAsync(
+ Stream stream,
+ CancellationToken cancellationToken = default)
=> DetectFormatAsync(DecoderOptions.Default, stream, cancellationToken);
///
- /// By reading the header on the provided stream this calculates the images format type.
+ /// Detects the encoded image format type from the specified stream.
///
/// The general decoder options.
/// The image stream to read the header from.
/// The token to monitor for cancellation requests.
+ /// A representing the asynchronous operation.
/// The options are null.
/// The stream is null.
- /// The stream is not readable.
- /// A representing the asynchronous operation.
- public static Task DetectFormatAsync(DecoderOptions options, Stream stream, CancellationToken cancellationToken = default)
+ /// The stream is not readable or the image format is not supported.
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
+ public static Task DetectFormatAsync(
+ DecoderOptions options,
+ Stream stream,
+ CancellationToken cancellationToken = default)
=> WithSeekableStreamAsync(
options,
stream,
@@ -74,136 +79,60 @@ public abstract partial class Image
/// Reads the raw image information from the specified stream without fully decoding it.
///
/// The image stream to read the header from.
+ /// if the information can be read; otherwise,
/// The stream is null.
- /// The stream is not readable.
- /// Image contains invalid content.
- ///
- /// The or null if a suitable info detector is not found.
- ///
- public static IImageInfo Identify(Stream stream)
- => Identify(stream, out IImageFormat _);
-
- ///
- /// Reads the raw image information from the specified stream without fully decoding it.
- ///
- /// The image stream to read the header from.
- /// The token to monitor for cancellation requests.
- /// The stream is null.
- /// The stream is not readable.
- /// Image contains invalid content.
- ///
- /// A representing the asynchronous operation or null if
- /// a suitable detector is not found.
- ///
- public static Task IdentifyAsync(Stream stream, CancellationToken cancellationToken = default)
- => IdentifyAsync(DecoderOptions.Default, stream, cancellationToken);
-
- ///
- /// Reads the raw image information from the specified stream without fully decoding it.
- ///
- /// The image stream to read the header from.
- /// The format type of the decoded image.
- /// The stream is null.
- /// The stream is not readable.
- /// Image contains invalid content.
- ///
- /// The or null if a suitable info detector is not found.
- ///
- public static IImageInfo Identify(Stream stream, out IImageFormat format)
- => Identify(DecoderOptions.Default, stream, out format);
+ /// The stream is not readable or the image format is not supported.
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
+ public static ImageInfo Identify(Stream stream)
+ => Identify(DecoderOptions.Default, stream);
///
/// Reads the raw image information from the specified stream without fully decoding it.
///
/// The general decoder options.
/// The image stream to read the information from.
+ /// The .
/// The options are null.
/// The stream is null.
- /// The stream is not readable.
- /// Image contains invalid content.
- ///
- /// The or null if a suitable info detector is not found.
- ///
- public static IImageInfo Identify(DecoderOptions options, Stream stream)
- => Identify(options, stream, out _);
+ /// The stream is not readable or the image format is not supported.
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
+ public static ImageInfo Identify(DecoderOptions options, Stream stream)
+ => WithSeekableStream(options, stream, s => InternalIdentify(options, s));
///
/// Reads the raw image information from the specified stream without fully decoding it.
///
- /// The general decoder options.
/// The image stream to read the information from.
/// The token to monitor for cancellation requests.
- /// The options are null.
- /// The stream is null.
- /// The stream is not readable.
- /// Image contains invalid content.
///
- /// A representing the asynchronous operation or null if
- /// a suitable detector is not found.
+ /// The representing the asynchronous operation.
///
- public static async Task IdentifyAsync(
- DecoderOptions options,
+ /// The stream is null.
+ /// The stream is not readable or the image format is not supported.
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
+ public static Task IdentifyAsync(
Stream stream,
CancellationToken cancellationToken = default)
- {
- (IImageInfo ImageInfo, IImageFormat Format) res = await IdentifyWithFormatAsync(options, stream, cancellationToken).ConfigureAwait(false);
- return res.ImageInfo;
- }
+ => IdentifyAsync(DecoderOptions.Default, stream, cancellationToken);
///
/// Reads the raw image information from the specified stream without fully decoding it.
///
/// The general decoder options.
/// The image stream to read the information from.
- /// The format type of the decoded image.
- /// The options are null.
- /// The stream is null.
- /// The stream is not readable.
- /// Image contains invalid content.
- ///
- /// The or null if a suitable info detector is not found.
- ///
- public static IImageInfo Identify(DecoderOptions options, Stream stream, out IImageFormat format)
- {
- (IImageInfo ImageInfo, IImageFormat Format) data = WithSeekableStream(options, stream, s => InternalIdentify(options, s));
-
- format = data.Format;
- return data.ImageInfo;
- }
-
- ///
- /// Reads the raw image information from the specified stream without fully decoding it.
- ///
- /// The image stream to read the information from.
/// The token to monitor for cancellation requests.
- /// The options are null.
- /// The stream is null.
- /// The stream is not readable.
- /// Image contains invalid content.
///
- /// The representing the asynchronous operation with the parameter type
- /// property set to null if suitable info detector is not found.
+ /// The representing the asynchronous operation.
///
- public static Task<(IImageInfo ImageInfo, IImageFormat Format)> IdentifyWithFormatAsync(
- Stream stream,
- CancellationToken cancellationToken = default)
- => IdentifyWithFormatAsync(DecoderOptions.Default, stream, cancellationToken);
-
- ///
- /// Reads the raw image information from the specified stream without fully decoding it.
- ///
- /// The general decoder options.
- /// The image stream to read the information from.
- /// The token to monitor for cancellation requests.
/// The options are null.
/// The stream is null.
- /// The stream is not readable.
- /// Image contains invalid content.
- ///
- /// The representing the asynchronous operation with the parameter type
- /// property set to null if suitable info detector is not found.
- ///
- public static Task<(IImageInfo ImageInfo, IImageFormat Format)> IdentifyWithFormatAsync(
+ /// The stream is not readable or the image format is not supported.
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
+ public static Task IdentifyAsync(
DecoderOptions options,
Stream stream,
CancellationToken cancellationToken = default)
@@ -214,301 +143,130 @@ public abstract partial class Image
cancellationToken);
///
- /// Decode a new instance of the class from the given stream.
- /// The pixel format is selected by the decoder.
+ /// Creates a new instance of the class from the given stream.
+ /// The pixel format is automatically determined by the decoder.
///
/// The stream containing image information.
- /// The format type of the decoded image.
+ /// .
/// The stream is null.
/// The stream is not readable or the image format is not supported.
- /// Image format not recognised.
- /// Image contains invalid content.
- /// The .
- public static Image Load(Stream stream, out IImageFormat format)
- => Load(DecoderOptions.Default, stream, out format);
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
+ public static Image Load(Stream stream)
+ => Load(DecoderOptions.Default, stream);
///
- /// Decode a new instance of the class from the given stream.
- /// The pixel format is selected by the decoder.
- ///
- /// The stream containing image information.
- /// The token to monitor for cancellation requests.
- /// The stream is null.
- /// The stream is not readable or the image format is not supported.
- /// Image format not recognised.
- /// Image contains invalid content.
- /// A representing the asynchronous operation.
- public static Task<(Image Image, IImageFormat Format)> LoadWithFormatAsync(Stream stream, CancellationToken cancellationToken = default)
- => LoadWithFormatAsync(DecoderOptions.Default, stream, cancellationToken);
-
- ///
- /// Decode a new instance of the class from the given stream.
- /// The pixel format is selected by the decoder.
+ /// Creates a new instance of the class from the given stream.
+ /// The pixel format is automatically determined by the decoder.
///
+ /// The general decoder options.
/// The stream containing image information.
+ /// .
+ /// The options are null.
/// The stream is null.
/// The stream is not readable or the image format is not supported.
- /// Image format not recognised.
- /// Image contains invalid content.
- /// The .
- public static Image Load(Stream stream) => Load(DecoderOptions.Default, stream);
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
+ public static Image Load(DecoderOptions options, Stream stream)
+ => WithSeekableStream(options, stream, s => Decode(options, s));
///
- /// Decode a new instance of the class from the given stream.
- /// The pixel format is selected by the decoder.
+ /// Creates a new instance of the class from the given stream.
+ /// The pixel format is automatically determined by the decoder.
///
/// The stream containing image information.
/// The token to monitor for cancellation requests.
+ /// A representing the asynchronous operation.
/// The stream is null.
/// The stream is not readable or the image format is not supported.
- /// Image format not recognised.
- /// Image contains invalid content.
- /// A representing the asynchronous operation.
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
public static Task LoadAsync(Stream stream, CancellationToken cancellationToken = default)
=> LoadAsync(DecoderOptions.Default, stream, cancellationToken);
///
- /// Decode a new instance of the class from the given stream.
- ///
- /// The general decoder options.
- /// The stream containing image information.
- /// The options are null.
- /// The stream is null.
- /// The stream is not readable or the image format is not supported.
- /// Image format not recognised.
- /// Image contains invalid content.
- /// A new .
- public static Image Load(DecoderOptions options, Stream stream)
- => Load(options, stream, out _);
-
- ///
- /// Decode a new instance of the class from the given stream.
+ /// Creates a new instance of the class from the given stream.
+ /// The pixel format is automatically determined by the decoder.
///
/// The general decoder options.
/// The stream containing image information.
/// The token to monitor for cancellation requests.
+ /// A representing the asynchronous operation.
/// The options are null.
/// The stream is null.
/// The stream is not readable or the image format is not supported.
- /// Image format not recognised.
- /// Image contains invalid content.
- /// A representing the asynchronous operation.
- public static async Task LoadAsync(DecoderOptions options, Stream stream, CancellationToken cancellationToken = default)
- => (await LoadWithFormatAsync(options, stream, cancellationToken).ConfigureAwait(false)).Image;
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
+ public static Task LoadAsync(
+ DecoderOptions options,
+ Stream stream,
+ CancellationToken cancellationToken = default)
+ => WithSeekableStreamAsync(options, stream, (s, ct) => DecodeAsync(options, s, ct), cancellationToken);
///
- /// Create a new instance of the class from the given stream.
+ /// Creates a new instance of the class from the given stream.
///
+ /// The pixel format.
/// The stream containing image information.
+ /// .
/// The stream is null.
/// The stream is not readable or the image format is not supported.
- /// Image format not recognised.
- /// Image contains invalid content.
- /// The pixel format.
- /// A new .
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
public static Image Load(Stream stream)
where TPixel : unmanaged, IPixel
=> Load(DecoderOptions.Default, stream);
///
- /// Create a new instance of the class from the given stream.
- ///
- /// The stream containing image information.
- /// The token to monitor for cancellation requests.
- /// The stream is null.
- /// The stream is not readable or the image format is not supported.
- /// Image format not recognised.
- /// Image contains invalid content.
- /// The pixel format.
- /// A representing the asynchronous operation.
- public static Task> LoadAsync(Stream stream, CancellationToken cancellationToken = default)
- where TPixel : unmanaged, IPixel
- => LoadAsync(DecoderOptions.Default, stream, cancellationToken);
-
- ///
- /// Create a new instance of the class from the given stream.
- ///
- /// The stream containing image information.
- /// The format type of the decoded image.
- /// The stream is null.
- /// The stream is not readable or the image format is not supported.
- /// Image format not recognised.
- /// Image contains invalid content.
- /// The pixel format.
- /// A new .
- public static Image Load(Stream stream, out IImageFormat format)
- where TPixel : unmanaged, IPixel
- => Load(DecoderOptions.Default, stream, out format);
-
- ///
- /// Create a new instance of the class from the given stream.
+ /// Creates a new instance of the class from the given stream.
///
- /// The stream containing image information.
- /// The token to monitor for cancellation requests.
- /// The stream is null.
- /// The stream is not readable or the image format is not supported.
- /// Image format not recognised.
- /// Image contains invalid content.
/// The pixel format.
- /// A representing the asynchronous operation.
- public static Task<(Image Image, IImageFormat Format)> LoadWithFormatAsync(Stream stream, CancellationToken cancellationToken = default)
- where TPixel : unmanaged, IPixel
- => LoadWithFormatAsync(DecoderOptions.Default, stream, cancellationToken);
-
- ///
- /// Create a new instance of the class from the given stream.
- ///
/// The general decoder options.
/// The stream containing image information.
+ /// .
/// The options are null.
/// The stream is null.
/// The stream is not readable or the image format is not supported.
- /// Image format not recognised.
- /// Image contains invalid content.
- /// The pixel format.
- /// A new .
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
public static Image Load(DecoderOptions options, Stream stream)
where TPixel : unmanaged, IPixel
- => Load(options, stream, out IImageFormat _);
+ => WithSeekableStream(options, stream, s => Decode(options, s));
///
- /// Create a new instance of the class from the given stream.
+ /// Creates a new instance of the class from the given stream.
///
- /// The general decoder options.
- /// The stream containing image information.
- /// The format type of the decoded image.
- /// The options are null.
- /// The stream is null.
- /// The stream is not readable or the image format is not supported.
- /// Image format not recognised.
- /// Image contains invalid content.
/// The pixel format.
- /// A representing the asynchronous operation.
- public static Image Load(DecoderOptions options, Stream stream, out IImageFormat format)
- where TPixel : unmanaged, IPixel
- {
- (Image Image, IImageFormat Format) data = WithSeekableStream(options, stream, s => Decode(options, s));
-
- format = data.Format;
-
- if (data.Image is null)
- {
- ThrowNotLoaded(options);
- }
-
- return data.Image;
- }
-
- ///
- /// Create a new instance of the class from the given stream.
- ///
- /// The general decoder options.
/// The stream containing image information.
/// The token to monitor for cancellation requests.
- /// The options are null.
- /// The stream is null.
- /// The stream is not readable or the image format is not supported.
- /// Image format not recognised.
- /// Image contains invalid content.
- /// A representing the asynchronous operation.
- public static async Task<(Image Image, IImageFormat Format)> LoadWithFormatAsync(
- DecoderOptions options,
- Stream stream,
- CancellationToken cancellationToken = default)
- {
- (Image Image, IImageFormat Format) data =
- await WithSeekableStreamAsync(options, stream, (s, ct) => DecodeAsync(options, s, ct), cancellationToken)
- .ConfigureAwait(false);
-
- if (data.Image is null)
- {
- ThrowNotLoaded(options);
- }
-
- return data;
- }
-
- ///
- /// Create a new instance of the class from the given stream.
- ///
- /// The general decoder options.
- /// The stream containing image information.
- /// The token to monitor for cancellation requests.
- /// The options are null.
+ /// A representing the asynchronous operation.
/// The stream is null.
/// The stream is not readable or the image format is not supported.
- /// Image format not recognised.
- /// Image contains invalid content.
- /// The pixel format.
- /// A representing the asynchronous operation.
- public static async Task<(Image Image, IImageFormat Format)> LoadWithFormatAsync(
- DecoderOptions options,
- Stream stream,
- CancellationToken cancellationToken = default)
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
+ public static Task> LoadAsync(Stream stream, CancellationToken cancellationToken = default)
where TPixel : unmanaged, IPixel
- {
- (Image Image, IImageFormat Format) data =
- await WithSeekableStreamAsync(options, stream, (s, ct) => DecodeAsync(options, s, ct), cancellationToken)
- .ConfigureAwait(false);
-
- if (data.Image is null)
- {
- ThrowNotLoaded(options);
- }
-
- return data;
- }
+ => LoadAsync(DecoderOptions.Default, stream, cancellationToken);
///
- /// Create a new instance of the class from the given stream.
+ /// Creates a new instance of the class from the given stream.
///
+ /// The pixel format.
/// The general decoder options.
/// The stream containing image information.
/// The token to monitor for cancellation requests.
+ /// A representing the asynchronous operation.
/// The options are null.
/// The stream is null.
/// The stream is not readable or the image format is not supported.
- /// Image format not recognised.
- /// Image contains invalid content.
- /// The pixel format.
- /// A representing the asynchronous operation.
- public static async Task> LoadAsync(
+ /// The encoded image contains invalid content.
+ /// The encoded image format is unknown.
+ public static Task> LoadAsync(
DecoderOptions options,
Stream stream,
CancellationToken cancellationToken = default)
where TPixel : unmanaged, IPixel
- {
- (Image img, _) = await LoadWithFormatAsync(options, stream, cancellationToken)
- .ConfigureAwait(false);
- return img;
- }
-
- ///
- /// Decode a new instance of the class from the given stream.
- /// The pixel format is selected by the decoder.
- ///
- /// The general decoder options.
- /// The stream containing image information.
- /// The format type of the decoded image.
- /// The options are null.
- /// The stream is null.
- /// The stream is not readable or the image format is not supported.
- /// Image format not recognised.
- /// Image contains invalid content.
- /// A new .
- public static Image Load(DecoderOptions options, Stream stream, out IImageFormat format)
- {
- (Image img, IImageFormat fmt) = WithSeekableStream(options, stream, s => Decode(options, s));
-
- format = fmt;
-
- if (img is null)
- {
- ThrowNotLoaded(options);
- }
-
- return img;
- }
+ => WithSeekableStreamAsync(options, stream, (s, ct) => DecodeAsync(options, s, ct), cancellationToken);
///
/// Performs the given action against the stream ensuring that it is seekable.
@@ -591,18 +349,4 @@ public abstract partial class Image
return await action(memoryStream, cancellationToken).ConfigureAwait(false);
}
-
- [DoesNotReturn]
- private static void ThrowNotLoaded(DecoderOptions options)
- {
- StringBuilder sb = new();
- sb.AppendLine("Image cannot be loaded. Available decoders:");
-
- foreach (KeyValuePair val in options.Configuration.ImageFormatsManager.ImageDecoders)
- {
- sb.AppendFormat(CultureInfo.InvariantCulture, " - {0} : {1}{2}", val.Key.Name, val.Value.GetType().Name, Environment.NewLine);
- }
-
- throw new UnknownImageFormatException(sb.ToString());
- }
}
diff --git a/src/ImageSharp/Image.LoadPixelData.cs b/src/ImageSharp/Image.LoadPixelData.cs
index 9a37adb3c..53b672b7d 100644
--- a/src/ImageSharp/Image.LoadPixelData.cs
+++ b/src/ImageSharp/Image.LoadPixelData.cs
@@ -72,7 +72,7 @@ public abstract partial class Image
int count = width * height;
Guard.MustBeGreaterThanOrEqualTo(data.Length, count, nameof(data));
- var image = new Image(configuration, width, height);
+ Image image = new(configuration, width, height);
data = data[..count];
data.CopyTo(image.Frames.RootFrame.PixelBuffer.FastMemoryGroup);
diff --git a/src/ImageSharp/Image.cs b/src/ImageSharp/Image.cs
index 2df86b109..65b2d68b0 100644
--- a/src/ImageSharp/Image.cs
+++ b/src/ImageSharp/Image.cs
@@ -14,11 +14,9 @@ namespace SixLabors.ImageSharp;
/// For the non-generic type, the pixel type is only known at runtime.
/// is always implemented by a pixel-specific instance.
///
-public abstract partial class Image : IImage, IConfigurationProvider
+public abstract partial class Image : ImageInfo, IDisposable, IConfigurationProvider
{
private bool isDisposed;
-
- private Size size;
private readonly Configuration configuration;
///
@@ -27,16 +25,12 @@ public abstract partial class Image : IImage, IConfigurationProvider
///
/// The configuration which allows altering default behaviour or extending the library.
///
- /// The .
- /// The .
- /// The .
+ /// The pixel type information.
+ /// The image metadata.
+ /// The size in px units.
protected Image(Configuration configuration, PixelTypeInfo pixelType, ImageMetadata metadata, Size size)
- {
- this.configuration = configuration ?? Configuration.Default;
- this.PixelType = pixelType;
- this.size = size;
- this.Metadata = metadata ?? new ImageMetadata();
- }
+ : base(pixelType, size, metadata)
+ => this.configuration = configuration ?? Configuration.Default;
///
/// Initializes a new instance of the class.
@@ -61,18 +55,6 @@ public abstract partial class Image : IImage, IConfigurationProvider
///
protected abstract ImageFrameCollection NonGenericFrameCollection { get; }
- ///
- public PixelTypeInfo PixelType { get; }
-
- ///
- public int Width => this.size.Width;
-
- ///
- public int Height => this.size.Height;
-
- ///
- public ImageMetadata Metadata { get; }
-
///
/// Gets the frames of the image as (non-generic) .
///
@@ -148,7 +130,7 @@ public abstract partial class Image : IImage, IConfigurationProvider
/// Update the size of the image after mutation.
///
/// The .
- protected void UpdateSize(Size size) => this.size = size;
+ protected void UpdateSize(Size size) => this.Size = size;
///
/// Disposes the object and frees resources for the Garbage Collector.
diff --git a/src/ImageSharp/ImageExtensions.cs b/src/ImageSharp/ImageExtensions.cs
index 7cd8a7b2f..04930a268 100644
--- a/src/ImageSharp/ImageExtensions.cs
+++ b/src/ImageSharp/ImageExtensions.cs
@@ -95,7 +95,7 @@ public static partial class ImageExtensions
throw new NotSupportedException("Cannot write to the stream.");
}
- IImageEncoder encoder = source.GetConfiguration().ImageFormatsManager.FindEncoder(format);
+ IImageEncoder encoder = source.GetConfiguration().ImageFormatsManager.GetEncoder(format);
if (encoder is null)
{
@@ -139,7 +139,7 @@ public static partial class ImageExtensions
throw new NotSupportedException("Cannot write to the stream.");
}
- IImageEncoder encoder = source.GetConfiguration().ImageFormatsManager.FindEncoder(format);
+ IImageEncoder encoder = source.GetConfiguration().ImageFormatsManager.GetEncoder(format);
if (encoder is null)
{
diff --git a/src/ImageSharp/ImageInfo.cs b/src/ImageSharp/ImageInfo.cs
index 5142a91a6..9a6452ab8 100644
--- a/src/ImageSharp/ImageInfo.cs
+++ b/src/ImageSharp/ImageInfo.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Six Labors.
+// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using SixLabors.ImageSharp.Formats;
@@ -9,32 +9,60 @@ namespace SixLabors.ImageSharp;
///
/// Contains information about the image including dimensions, pixel type information and additional metadata
///
-internal sealed class ImageInfo : IImageInfo
+public class ImageInfo
{
///
/// Initializes a new instance of the class.
///
- /// The image pixel type information.
- /// The width of the image in pixels.
- /// The height of the image in pixels.
- /// The images metadata.
+ /// The pixel type information.
+ /// The width of the image in px units.
+ /// The height of the image in px units.
+ /// The image metadata.
public ImageInfo(PixelTypeInfo pixelType, int width, int height, ImageMetadata metadata)
+ : this(pixelType, new(width, height), metadata)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The pixel type information.
+ /// The size of the image in px units.
+ /// The image metadata.
+ public ImageInfo(PixelTypeInfo pixelType, Size size, ImageMetadata metadata)
{
this.PixelType = pixelType;
- this.Width = width;
- this.Height = height;
- this.Metadata = metadata;
+ this.Metadata = metadata ?? new ImageMetadata();
+ this.Size = size;
}
- ///
+ ///
+ /// Gets information about the image pixels.
+ ///
public PixelTypeInfo PixelType { get; }
- ///
- public int Width { get; }
+ ///
+ /// Gets the image width in px units.
+ ///
+ public int Width => this.Size.Width;
- ///
- public int Height { get; }
+ ///
+ /// Gets the image height in px units.
+ ///
+ public int Height => this.Size.Height;
- ///
+ ///
+ /// Gets any metadata associated wit The image.
+ ///
public ImageMetadata Metadata { get; }
+
+ ///
+ /// Gets the size of the image in px units.
+ ///
+ public Size Size { get; internal set; }
+
+ ///
+ /// Gets the bounds of the image.
+ ///
+ public Rectangle Bounds => new(0, 0, this.Width, this.Height);
}
diff --git a/src/ImageSharp/ImageInfoExtensions.cs b/src/ImageSharp/ImageInfoExtensions.cs
deleted file mode 100644
index 9dfc89289..000000000
--- a/src/ImageSharp/ImageInfoExtensions.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Six Labors Split License.
-
-namespace SixLabors.ImageSharp;
-
-///
-/// Extension methods that allow the addition of geometry calculating methods to the type
-///
-public static class ImageInfoExtensions
-{
- ///
- /// Gets the bounds of the image.
- ///
- /// The image info
- /// The
- public static Size Size(this IImageInfo info) => new Size(info.Width, info.Height);
-
- ///
- /// Gets the bounds of the image.
- ///
- /// The image info
- /// The
- public static Rectangle Bounds(this IImageInfo info) => new Rectangle(0, 0, info.Width, info.Height);
-}
diff --git a/src/ImageSharp/Image{TPixel}.cs b/src/ImageSharp/Image{TPixel}.cs
index 31fd01509..9e3cc065c 100644
--- a/src/ImageSharp/Image{TPixel}.cs
+++ b/src/ImageSharp/Image{TPixel}.cs
@@ -411,7 +411,7 @@ public sealed class Image : Image
this.frames[i].SwapOrCopyPixelsBufferFrom(sourceFrames[i]);
}
- this.UpdateSize(pixelSource.Size());
+ this.UpdateSize(pixelSource.Size);
}
private static Size ValidateFramesAndGetSize(IEnumerable> frames)
diff --git a/src/ImageSharp/Metadata/ImageMetadata.cs b/src/ImageSharp/Metadata/ImageMetadata.cs
index 785f38941..f54fc5c7a 100644
--- a/src/ImageSharp/Metadata/ImageMetadata.cs
+++ b/src/ImageSharp/Metadata/ImageMetadata.cs
@@ -1,6 +1,5 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
-#nullable disable
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Metadata.Profiles.Exif;
@@ -69,6 +68,10 @@ public sealed class ImageMetadata : IDeepCloneable
this.IccProfile = other.IccProfile?.DeepClone();
this.IptcProfile = other.IptcProfile?.DeepClone();
this.XmpProfile = other.XmpProfile?.DeepClone();
+
+ // NOTE: This clone is actually shallow but we share the same format
+ // instances for all images in the configuration.
+ this.DecodedImageFormat = other.DecodedImageFormat;
}
///
@@ -137,22 +140,27 @@ public sealed class ImageMetadata : IDeepCloneable
///
/// Gets or sets the Exif profile.
///
- public ExifProfile ExifProfile { get; set; }
+ public ExifProfile? ExifProfile { get; set; }
///
/// Gets or sets the XMP profile.
///
- public XmpProfile XmpProfile { get; set; }
+ public XmpProfile? XmpProfile { get; set; }
///
/// Gets or sets the ICC profile.
///
- public IccProfile IccProfile { get; set; }
+ public IccProfile? IccProfile { get; set; }
///
/// Gets or sets the IPTC profile.
///
- public IptcProfile IptcProfile { get; set; }
+ public IptcProfile? IptcProfile { get; set; }
+
+ ///
+ /// Gets the original format, if any, the image was decode from.
+ ///
+ public IImageFormat? DecodedImageFormat { get; internal set; }
///
/// Gets the metadata value associated with the specified key.
@@ -165,7 +173,7 @@ public sealed class ImageMetadata : IDeepCloneable
public TFormatMetadata GetFormatMetadata(IImageFormat key)
where TFormatMetadata : class, IDeepCloneable
{
- if (this.formatMetadata.TryGetValue(key, out IDeepCloneable meta))
+ if (this.formatMetadata.TryGetValue(key, out IDeepCloneable? meta))
{
return (TFormatMetadata)meta;
}
diff --git a/src/ImageSharp/Processing/DefaultImageProcessorContext{TPixel}.cs b/src/ImageSharp/Processing/DefaultImageProcessorContext{TPixel}.cs
index 9893bceab..208455b90 100644
--- a/src/ImageSharp/Processing/DefaultImageProcessorContext{TPixel}.cs
+++ b/src/ImageSharp/Processing/DefaultImageProcessorContext{TPixel}.cs
@@ -95,5 +95,5 @@ internal class DefaultImageProcessorContext : IInternalImageProcessingCo
return this;
}
- private Rectangle GetCurrentBounds() => this.destination?.Bounds() ?? this.source.Bounds();
+ private Rectangle GetCurrentBounds() => this.destination?.Bounds ?? this.source.Bounds;
}
diff --git a/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs b/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs
index ac0d36751..82e639f1b 100644
--- a/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs
+++ b/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs
@@ -78,7 +78,7 @@ internal class DrawImageProcessor : ImageProcessor
int locationY = this.Location.Y;
// Align start/end positions.
- Rectangle bounds = targetImage.Bounds();
+ Rectangle bounds = targetImage.Bounds;
int minX = Math.Max(this.Location.X, sourceRectangle.X);
int maxX = Math.Min(this.Location.X + bounds.Width, sourceRectangle.Right);
diff --git a/src/ImageSharp/Processing/Processors/Transforms/EntropyCropProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/EntropyCropProcessor{TPixel}.cs
index 1ba62aa9e..9afc852b5 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/EntropyCropProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/EntropyCropProcessor{TPixel}.cs
@@ -27,9 +27,7 @@ internal class EntropyCropProcessor : ImageProcessor
/// The source area to process for the current processor instance.
public EntropyCropProcessor(Configuration configuration, EntropyCropProcessor definition, Image source, Rectangle sourceRectangle)
: base(configuration, source, sourceRectangle)
- {
- this.definition = definition;
- }
+ => this.definition = definition;
///
protected override void BeforeImageApply()
@@ -38,7 +36,7 @@ internal class EntropyCropProcessor : ImageProcessor
// TODO: This is clunky. We should add behavior enum to ExtractFrame.
// All frames have be the same size so we only need to calculate the correct dimensions for the first frame
- using (var temp = new Image(this.Configuration, this.Source.Metadata.DeepClone(), new[] { this.Source.Frames.RootFrame.Clone() }))
+ using (Image temp = new(this.Configuration, this.Source.Metadata.DeepClone(), new[] { this.Source.Frames.RootFrame.Clone() }))
{
Configuration configuration = this.Source.GetConfiguration();
@@ -52,7 +50,7 @@ internal class EntropyCropProcessor : ImageProcessor
rectangle = GetFilteredBoundingRectangle(temp.Frames.RootFrame, 0);
}
- new CropProcessor(rectangle, this.Source.Size()).Execute(this.Configuration, this.Source, this.SourceRectangle);
+ new CropProcessor(rectangle, this.Source.Size).Execute(this.Configuration, this.Source, this.SourceRectangle);
base.BeforeImageApply();
}
@@ -77,7 +75,7 @@ internal class EntropyCropProcessor : ImageProcessor
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static Rectangle GetBoundingRectangle(Point topLeft, Point bottomRight)
- => new Rectangle(
+ => new(
topLeft.X,
topLeft.Y,
bottomRight.X - topLeft.X,
@@ -99,29 +97,13 @@ internal class EntropyCropProcessor : ImageProcessor
int height = bitmap.Height;
Point topLeft = default;
Point bottomRight = default;
-
- Func, int, int, float, bool> delegateFunc;
-
- // Determine which channel to check against
- switch (channel)
+ Func, int, int, float, bool> delegateFunc = channel switch
{
- case RgbaComponent.R:
- delegateFunc = (pixels, x, y, b) => MathF.Abs(pixels[x, y].ToVector4().X - b) > Constants.Epsilon;
- break;
-
- case RgbaComponent.G:
- delegateFunc = (pixels, x, y, b) => MathF.Abs(pixels[x, y].ToVector4().Y - b) > Constants.Epsilon;
- break;
-
- case RgbaComponent.B:
- delegateFunc = (pixels, x, y, b) => MathF.Abs(pixels[x, y].ToVector4().Z - b) > Constants.Epsilon;
- break;
-
- default:
- delegateFunc = (pixels, x, y, b) => MathF.Abs(pixels[x, y].ToVector4().W - b) > Constants.Epsilon;
- break;
- }
-
+ RgbaComponent.R => (pixels, x, y, b) => MathF.Abs(pixels[x, y].ToVector4().X - b) > Constants.Epsilon,
+ RgbaComponent.G => (pixels, x, y, b) => MathF.Abs(pixels[x, y].ToVector4().Y - b) > Constants.Epsilon,
+ RgbaComponent.B => (pixels, x, y, b) => MathF.Abs(pixels[x, y].ToVector4().Z - b) > Constants.Epsilon,
+ _ => (pixels, x, y, b) => MathF.Abs(pixels[x, y].ToVector4().W - b) > Constants.Epsilon,
+ };
int GetMinY(ImageFrame pixels)
{
for (int y = 0; y < height; y++)
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Linear/RotateProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/Linear/RotateProcessor{TPixel}.cs
index ac50337f6..3ffb1ab51 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Linear/RotateProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Linear/RotateProcessor{TPixel}.cs
@@ -43,7 +43,7 @@ internal class RotateProcessor : AffineTransformProcessor
///
protected override void AfterImageApply(Image destination)
{
- ExifProfile profile = destination.Metadata.ExifProfile;
+ ExifProfile? profile = destination.Metadata.ExifProfile;
if (profile is null)
{
return;
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs
index 4fbd7cfd2..ba96e76ae 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs
@@ -82,7 +82,7 @@ internal class ResizeProcessor : TransformProcessor, IResampling
return;
}
- var interest = Rectangle.Intersect(destinationRectangle, destination.Bounds());
+ var interest = Rectangle.Intersect(destinationRectangle, destination.Bounds);
if (sampler is NearestNeighborResampler)
{
diff --git a/src/ImageSharp/Processing/Processors/Transforms/TransformProcessorHelpers.cs b/src/ImageSharp/Processing/Processors/Transforms/TransformProcessorHelpers.cs
index 8e7452679..172d7d677 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/TransformProcessorHelpers.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/TransformProcessorHelpers.cs
@@ -19,7 +19,7 @@ internal static class TransformProcessorHelpers
public static void UpdateDimensionalMetadata(Image image)
where TPixel : unmanaged, IPixel
{
- ExifProfile profile = image.Metadata.ExifProfile;
+ ExifProfile? profile = image.Metadata.ExifProfile;
if (profile is null)
{
return;
diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/IdentifyJpeg.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/IdentifyJpeg.cs
index aed3e4c03..d5ad59b00 100644
--- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/IdentifyJpeg.cs
+++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/IdentifyJpeg.cs
@@ -22,7 +22,7 @@ public class IdentifyJpeg
public void ReadImages() => this.jpegBytes ??= File.ReadAllBytes(this.TestImageFullPath);
[Benchmark]
- public IImageInfo Identify()
+ public ImageInfo Identify()
{
using MemoryStream memoryStream = new(this.jpegBytes);
return JpegDecoder.Instance.Identify(DecoderOptions.Default, memoryStream);
diff --git a/tests/ImageSharp.Benchmarks/Codecs/Png/DecodeFilteredPng.cs b/tests/ImageSharp.Benchmarks/Codecs/Png/DecodeFilteredPng.cs
index 74f500666..986c1431c 100644
--- a/tests/ImageSharp.Benchmarks/Codecs/Png/DecodeFilteredPng.cs
+++ b/tests/ImageSharp.Benchmarks/Codecs/Png/DecodeFilteredPng.cs
@@ -56,8 +56,8 @@ public class DecodeFilteredPng
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static Size LoadPng(byte[] bytes)
{
- using var image = Image.Load(bytes);
- return image.Size();
+ using Image image = Image.Load(bytes);
+ return image.Size;
}
private static string TestImageFullPath(string path)
diff --git a/tests/ImageSharp.Benchmarks/Codecs/Png/DecodePng.cs b/tests/ImageSharp.Benchmarks/Codecs/Png/DecodePng.cs
index a73d62859..c23fa25cc 100644
--- a/tests/ImageSharp.Benchmarks/Codecs/Png/DecodePng.cs
+++ b/tests/ImageSharp.Benchmarks/Codecs/Png/DecodePng.cs
@@ -22,26 +22,21 @@ public class DecodePng
[GlobalSetup]
public void ReadImages()
- {
- if (this.pngBytes == null)
- {
- this.pngBytes = File.ReadAllBytes(this.TestImageFullPath);
- }
- }
+ => this.pngBytes ??= File.ReadAllBytes(this.TestImageFullPath);
[Benchmark(Baseline = true, Description = "System.Drawing Png")]
public SDSize PngSystemDrawing()
{
- using var memoryStream = new MemoryStream(this.pngBytes);
- using var image = SDImage.FromStream(memoryStream);
+ using MemoryStream memoryStream = new(this.pngBytes);
+ using SDImage image = SDImage.FromStream(memoryStream);
return image.Size;
}
[Benchmark(Description = "ImageSharp Png")]
public Size PngImageSharp()
{
- using var memoryStream = new MemoryStream(this.pngBytes);
- using var image = Image.Load(memoryStream);
- return image.Size();
+ using MemoryStream memoryStream = new(this.pngBytes);
+ using Image image = Image.Load(memoryStream);
+ return image.Size;
}
}
diff --git a/tests/ImageSharp.Benchmarks/Codecs/Tiff/DecodeTiff.cs b/tests/ImageSharp.Benchmarks/Codecs/Tiff/DecodeTiff.cs
index 4edb251fa..83f5fdd21 100644
--- a/tests/ImageSharp.Benchmarks/Codecs/Tiff/DecodeTiff.cs
+++ b/tests/ImageSharp.Benchmarks/Codecs/Tiff/DecodeTiff.cs
@@ -69,20 +69,16 @@ public class DecodeTiff
[Benchmark(Baseline = true, Description = "System.Drawing Tiff")]
public SDSize TiffSystemDrawing()
{
- using (var memoryStream = new MemoryStream(this.data))
- using (var image = SDImage.FromStream(memoryStream))
- {
- return image.Size;
- }
+ using MemoryStream memoryStream = new(this.data);
+ using SDImage image = SDImage.FromStream(memoryStream);
+ return image.Size;
}
[Benchmark(Description = "ImageSharp Tiff")]
public Size TiffCore()
{
- using (var ms = new MemoryStream(this.data))
- using (var image = Image.Load(ms))
- {
- return image.Size();
- }
+ using MemoryStream ms = new(this.data);
+ using Image image = Image.Load(ms);
+ return image.Size;
}
}
diff --git a/tests/ImageSharp.Benchmarks/Processing/Diffuse.cs b/tests/ImageSharp.Benchmarks/Processing/Diffuse.cs
index 7d6a52af2..c74c4a858 100644
--- a/tests/ImageSharp.Benchmarks/Processing/Diffuse.cs
+++ b/tests/ImageSharp.Benchmarks/Processing/Diffuse.cs
@@ -13,19 +13,19 @@ public class Diffuse
[Benchmark]
public Size DoDiffuse()
{
- using var image = new Image(Configuration.Default, 800, 800, Color.BlanchedAlmond);
+ using Image image = new(Configuration.Default, 800, 800, Color.BlanchedAlmond);
image.Mutate(x => x.Dither(KnownDitherings.FloydSteinberg));
- return image.Size();
+ return image.Size;
}
[Benchmark]
public Size DoDither()
{
- using var image = new Image(Configuration.Default, 800, 800, Color.BlanchedAlmond);
+ using Image image = new(Configuration.Default, 800, 800, Color.BlanchedAlmond);
image.Mutate(x => x.Dither());
- return image.Size();
+ return image.Size;
}
}
diff --git a/tests/ImageSharp.Benchmarks/Processing/Rotate.cs b/tests/ImageSharp.Benchmarks/Processing/Rotate.cs
index c392d9964..b9b0f6b3d 100644
--- a/tests/ImageSharp.Benchmarks/Processing/Rotate.cs
+++ b/tests/ImageSharp.Benchmarks/Processing/Rotate.cs
@@ -13,10 +13,10 @@ public class Rotate
[Benchmark]
public Size DoRotate()
{
- using var image = new Image(Configuration.Default, 400, 400, Color.BlanchedAlmond);
+ using Image image = new(Configuration.Default, 400, 400, Color.BlanchedAlmond);
image.Mutate(x => x.Rotate(37.5F));
- return image.Size();
+ return image.Size;
}
}
diff --git a/tests/ImageSharp.Benchmarks/Processing/Skew.cs b/tests/ImageSharp.Benchmarks/Processing/Skew.cs
index bc64382c1..26f2e7d2d 100644
--- a/tests/ImageSharp.Benchmarks/Processing/Skew.cs
+++ b/tests/ImageSharp.Benchmarks/Processing/Skew.cs
@@ -13,10 +13,10 @@ public class Skew
[Benchmark]
public Size DoSkew()
{
- using var image = new Image(Configuration.Default, 400, 400, Color.BlanchedAlmond);
+ using Image image = new(Configuration.Default, 400, 400, Color.BlanchedAlmond);
image.Mutate(x => x.Skew(20, 10));
- return image.Size();
+ return image.Size;
}
}
diff --git a/tests/ImageSharp.Tests/Advanced/AdvancedImageExtensionsTests.cs b/tests/ImageSharp.Tests/Advanced/AdvancedImageExtensionsTests.cs
index 03e062cc0..57a90c77b 100644
--- a/tests/ImageSharp.Tests/Advanced/AdvancedImageExtensionsTests.cs
+++ b/tests/ImageSharp.Tests/Advanced/AdvancedImageExtensionsTests.cs
@@ -30,7 +30,7 @@ public class AdvancedImageExtensionsTests
IMemoryGroup memoryGroup = image.GetPixelMemoryGroup();
// Assert:
- VerifyMemoryGroupDataMatchesTestPattern(provider, memoryGroup, image.Size());
+ VerifyMemoryGroupDataMatchesTestPattern(provider, memoryGroup, image.Size);
}
[Theory]
@@ -57,23 +57,23 @@ public class AdvancedImageExtensionsTests
where TPixel : unmanaged, IPixel
{
using Image image0 = provider.GetImage();
- var targetBuffer = new TPixel[image0.Width * image0.Height];
+ TPixel[] targetBuffer = new TPixel[image0.Width * image0.Height];
Assert.True(image0.DangerousTryGetSinglePixelMemory(out Memory sourceBuffer));
sourceBuffer.CopyTo(targetBuffer);
- var managerOfExternalMemory = new TestMemoryManager(targetBuffer);
+ TestMemoryManager managerOfExternalMemory = new(targetBuffer);
Memory externalMemory = managerOfExternalMemory.Memory;
- using (var image1 = Image.WrapMemory(externalMemory, image0.Width, image0.Height))
+ using (Image image1 = Image.WrapMemory(externalMemory, image0.Width, image0.Height))
{
- VerifyMemoryGroupDataMatchesTestPattern(provider, image1.GetPixelMemoryGroup(), image1.Size());
+ VerifyMemoryGroupDataMatchesTestPattern(provider, image1.GetPixelMemoryGroup(), image1.Size);
}
// Make sure externalMemory works after destruction:
- VerifyMemoryGroupDataMatchesTestPattern(provider, image0.GetPixelMemoryGroup(), image0.Size());
+ VerifyMemoryGroupDataMatchesTestPattern(provider, image0.GetPixelMemoryGroup(), image0.Size);
}
private static void VerifyMemoryGroupDataMatchesTestPattern(
diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs
index e6eb389be..e76f21d0e 100644
--- a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs
@@ -473,9 +473,9 @@ public class BmpDecoderTests
[InlineData(Bit1Pal1, 1)]
public void Identify_DetectsCorrectPixelType(string imagePath, int expectedPixelSize)
{
- var testFile = TestFile.Create(imagePath);
- using var stream = new MemoryStream(testFile.Bytes, false);
- IImageInfo imageInfo = Image.Identify(stream);
+ TestFile testFile = TestFile.Create(imagePath);
+ using MemoryStream stream = new(testFile.Bytes, false);
+ ImageInfo imageInfo = Image.Identify(stream);
Assert.NotNull(imageInfo);
Assert.Equal(expectedPixelSize, imageInfo.PixelType?.BitsPerPixel);
}
@@ -491,9 +491,9 @@ public class BmpDecoderTests
[InlineData(RLE8Inverted, 491, 272)]
public void Identify_DetectsCorrectWidthAndHeight(string imagePath, int expectedWidth, int expectedHeight)
{
- var testFile = TestFile.Create(imagePath);
- using var stream = new MemoryStream(testFile.Bytes, false);
- IImageInfo imageInfo = Image.Identify(stream);
+ 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);
@@ -503,8 +503,8 @@ public class BmpDecoderTests
[MemberData(nameof(RatioFiles))]
public void Decode_VerifyRatio(string imagePath, int xResolution, int yResolution, PixelResolutionUnit resolutionUnit)
{
- var testFile = TestFile.Create(imagePath);
- using var stream = new MemoryStream(testFile.Bytes, false);
+ TestFile testFile = TestFile.Create(imagePath);
+ using MemoryStream stream = new(testFile.Bytes, false);
using Image image = BmpDecoder.Instance.Decode(DecoderOptions.Default, stream);
ImageMetadata meta = image.Metadata;
Assert.Equal(xResolution, meta.HorizontalResolution);
diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpMetadataTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpMetadataTests.cs
index f4ce54670..1d8435671 100644
--- a/tests/ImageSharp.Tests/Formats/Bmp/BmpMetadataTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpMetadataTests.cs
@@ -14,8 +14,9 @@ public class BmpMetadataTests
[Fact]
public void CloneIsDeep()
{
- var meta = new BmpMetadata { BitsPerPixel = BmpBitsPerPixel.Pixel24, InfoHeaderType = BmpInfoHeaderType.Os2Version2 };
- var clone = (BmpMetadata)meta.DeepClone();
+ BmpMetadata meta = new()
+ { BitsPerPixel = BmpBitsPerPixel.Pixel24, InfoHeaderType = BmpInfoHeaderType.Os2Version2 };
+ BmpMetadata clone = (BmpMetadata)meta.DeepClone();
clone.BitsPerPixel = BmpBitsPerPixel.Pixel32;
clone.InfoHeaderType = BmpInfoHeaderType.WinVersion2;
@@ -35,15 +36,13 @@ public class BmpMetadataTests
[InlineData(Os2v2, BmpInfoHeaderType.Os2Version2)]
public void Identify_DetectsCorrectBitmapInfoHeaderType(string imagePath, BmpInfoHeaderType expectedInfoHeaderType)
{
- var testFile = TestFile.Create(imagePath);
- using (var stream = new MemoryStream(testFile.Bytes, false))
- {
- IImageInfo imageInfo = Image.Identify(stream);
- Assert.NotNull(imageInfo);
- BmpMetadata bitmapMetadata = imageInfo.Metadata.GetBmpMetadata();
- Assert.NotNull(bitmapMetadata);
- Assert.Equal(expectedInfoHeaderType, bitmapMetadata.InfoHeaderType);
- }
+ TestFile testFile = TestFile.Create(imagePath);
+ using MemoryStream stream = new(testFile.Bytes, false);
+ ImageInfo imageInfo = Image.Identify(stream);
+ Assert.NotNull(imageInfo);
+ BmpMetadata bitmapMetadata = imageInfo.Metadata.GetBmpMetadata();
+ Assert.NotNull(bitmapMetadata);
+ Assert.Equal(expectedInfoHeaderType, bitmapMetadata.InfoHeaderType);
}
[Theory]
@@ -51,12 +50,10 @@ public class BmpMetadataTests
public void Decoder_CanReadColorProfile(TestImageProvider provider)
where TPixel : unmanaged, IPixel
{
- using (Image image = provider.GetImage(BmpDecoder.Instance))
- {
- ImageSharp.Metadata.ImageMetadata metaData = image.Metadata;
- Assert.NotNull(metaData);
- Assert.NotNull(metaData.IccProfile);
- Assert.Equal(16, metaData.IccProfile.Entries.Length);
- }
+ using Image image = provider.GetImage(BmpDecoder.Instance);
+ ImageSharp.Metadata.ImageMetadata metaData = image.Metadata;
+ Assert.NotNull(metaData);
+ Assert.NotNull(metaData.IccProfile);
+ Assert.Equal(16, metaData.IccProfile.Entries.Length);
}
}
diff --git a/tests/ImageSharp.Tests/Formats/Bmp/ImageExtensionsTest.cs b/tests/ImageSharp.Tests/Formats/Bmp/ImageExtensionsTest.cs
index fbf9b20a9..14b017bee 100644
--- a/tests/ImageSharp.Tests/Formats/Bmp/ImageExtensionsTest.cs
+++ b/tests/ImageSharp.Tests/Formats/Bmp/ImageExtensionsTest.cs
@@ -15,15 +15,13 @@ public class ImageExtensionsTest
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensionsTest));
string file = Path.Combine(dir, "SaveAsBmp_Path.bmp");
- using (var image = new Image(10, 10))
+ using (Image image = new(10, 10))
{
image.SaveAsBmp(file);
}
- using (Image.Load(file, out IImageFormat mime))
- {
- Assert.Equal("image/bmp", mime.DefaultMimeType);
- }
+ IImageFormat format = Image.DetectFormat(file);
+ Assert.True(format is BmpFormat);
}
[Fact]
@@ -32,15 +30,13 @@ public class ImageExtensionsTest
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensionsTest));
string file = Path.Combine(dir, "SaveAsBmpAsync_Path.bmp");
- using (var image = new Image(10, 10))
+ using (Image image = new(10, 10))
{
await image.SaveAsBmpAsync(file);
}
- using (Image.Load(file, out IImageFormat mime))
- {
- Assert.Equal("image/bmp", mime.DefaultMimeType);
- }
+ IImageFormat format = Image.DetectFormat(file);
+ Assert.True(format is BmpFormat);
}
[Fact]
@@ -49,15 +45,13 @@ public class ImageExtensionsTest
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensions));
string file = Path.Combine(dir, "SaveAsBmp_Path_Encoder.bmp");
- using (var image = new Image(10, 10))
+ using (Image image = new(10, 10))
{
image.SaveAsBmp(file, new BmpEncoder());
}
- using (Image.Load(file, out IImageFormat mime))
- {
- Assert.Equal("image/bmp", mime.DefaultMimeType);
- }
+ IImageFormat format = Image.DetectFormat(file);
+ Assert.True(format is BmpFormat);
}
[Fact]
@@ -66,86 +60,76 @@ public class ImageExtensionsTest
string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageExtensions));
string file = Path.Combine(dir, "SaveAsBmpAsync_Path_Encoder.bmp");
- using (var image = new Image(10, 10))
+ using (Image image = new(10, 10))
{
await image.SaveAsBmpAsync(file, new BmpEncoder());
}
- using (Image.Load(file, out IImageFormat mime))
- {
- Assert.Equal("image/bmp", mime.DefaultMimeType);
- }
+ IImageFormat format = Image.DetectFormat(file);
+ Assert.True(format is BmpFormat);
}
[Fact]
public void SaveAsBmp_Stream()
{
- using var memoryStream = new MemoryStream();
+ using MemoryStream memoryStream = new();
- using (var image = new Image(10, 10))
+ using (Image image = new(10, 10))
{
image.SaveAsBmp(memoryStream);
}
memoryStream.Position = 0;
- using (Image.Load(memoryStream, out IImageFormat mime))
- {
- Assert.Equal("image/bmp", mime.DefaultMimeType);
- }
+ IImageFormat format = Image.DetectFormat(memoryStream);
+ Assert.True(format is BmpFormat);
}
[Fact]
public async Task SaveAsBmpAsync_StreamAsync()
{
- using var memoryStream = new MemoryStream();
+ using MemoryStream memoryStream = new();
- using (var image = new Image(10, 10))
+ using (Image