diff --git a/src/ImageSharp/Formats/Bmp/BmpImageFormatDetector.cs b/src/ImageSharp/Formats/Bmp/BmpImageFormatDetector.cs index 162c8ed399..01dd3157ef 100644 --- a/src/ImageSharp/Formats/Bmp/BmpImageFormatDetector.cs +++ b/src/ImageSharp/Formats/Bmp/BmpImageFormatDetector.cs @@ -2,6 +2,7 @@ // Licensed under the Six Labors Split License. using System.Buffers.Binary; +using System.Diagnostics.CodeAnalysis; namespace SixLabors.ImageSharp.Formats.Bmp; @@ -14,9 +15,11 @@ public sealed class BmpImageFormatDetector : IImageFormatDetector public int HeaderSize => 2; /// - public IImageFormat? DetectFormat(ReadOnlySpan header) + public bool TryDetectFormat(ReadOnlySpan header, [NotNullWhen(true)] out IImageFormat? format) { - return this.IsSupportedFileFormat(header) ? BmpFormat.Instance : null; + format = this.IsSupportedFileFormat(header) ? BmpFormat.Instance : null; + + return format != null; } private bool IsSupportedFileFormat(ReadOnlySpan header) @@ -24,7 +27,8 @@ public sealed class BmpImageFormatDetector : IImageFormatDetector if (header.Length >= this.HeaderSize) { short fileTypeMarker = BinaryPrimitives.ReadInt16LittleEndian(header); - return fileTypeMarker == BmpConstants.TypeMarkers.Bitmap || fileTypeMarker == BmpConstants.TypeMarkers.BitmapArray; + return fileTypeMarker == BmpConstants.TypeMarkers.Bitmap || + fileTypeMarker == BmpConstants.TypeMarkers.BitmapArray; } return false; diff --git a/src/ImageSharp/Formats/Gif/GifImageFormatDetector.cs b/src/ImageSharp/Formats/Gif/GifImageFormatDetector.cs index db3d429046..ffda8075af 100644 --- a/src/ImageSharp/Formats/Gif/GifImageFormatDetector.cs +++ b/src/ImageSharp/Formats/Gif/GifImageFormatDetector.cs @@ -1,6 +1,8 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +using System.Diagnostics.CodeAnalysis; + namespace SixLabors.ImageSharp.Formats.Gif; /// @@ -12,9 +14,10 @@ public sealed class GifImageFormatDetector : IImageFormatDetector public int HeaderSize => 6; /// - public IImageFormat? DetectFormat(ReadOnlySpan header) + public bool TryDetectFormat(ReadOnlySpan header, [NotNullWhen(true)] out IImageFormat? format) { - return this.IsSupportedFileFormat(header) ? GifFormat.Instance : null; + format = this.IsSupportedFileFormat(header) ? GifFormat.Instance : null; + return format != null; } private bool IsSupportedFileFormat(ReadOnlySpan header) diff --git a/src/ImageSharp/Formats/IImageFormatDetector.cs b/src/ImageSharp/Formats/IImageFormatDetector.cs index e1bdc41f8f..86750a7106 100644 --- a/src/ImageSharp/Formats/IImageFormatDetector.cs +++ b/src/ImageSharp/Formats/IImageFormatDetector.cs @@ -1,6 +1,8 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +using System.Diagnostics.CodeAnalysis; + namespace SixLabors.ImageSharp.Formats; /// @@ -18,6 +20,7 @@ public interface IImageFormatDetector /// Detect mimetype /// /// The containing the file header. - /// returns the mime type of detected otherwise returns null - IImageFormat? DetectFormat(ReadOnlySpan header); + /// The mime type of detected otherwise returns null + /// returns true when format was detected otherwise false. + bool TryDetectFormat(ReadOnlySpan header, [NotNullWhen(true)] out IImageFormat? format); } diff --git a/src/ImageSharp/Formats/Jpeg/JpegImageFormatDetector.cs b/src/ImageSharp/Formats/Jpeg/JpegImageFormatDetector.cs index 3bf7346ff3..4daf9fd97b 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegImageFormatDetector.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegImageFormatDetector.cs @@ -1,6 +1,8 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +using System.Diagnostics.CodeAnalysis; + namespace SixLabors.ImageSharp.Formats.Jpeg; /// @@ -12,8 +14,11 @@ public sealed class JpegImageFormatDetector : IImageFormatDetector public int HeaderSize => 11; /// - public IImageFormat? DetectFormat(ReadOnlySpan header) - => this.IsSupportedFileFormat(header) ? JpegFormat.Instance : null; + public bool TryDetectFormat(ReadOnlySpan header, [NotNullWhen(true)] out IImageFormat? format) + { + format = this.IsSupportedFileFormat(header) ? JpegFormat.Instance : null; + return format != null; + } private bool IsSupportedFileFormat(ReadOnlySpan header) => header.Length >= this.HeaderSize diff --git a/src/ImageSharp/Formats/Pbm/PbmImageFormatDetector.cs b/src/ImageSharp/Formats/Pbm/PbmImageFormatDetector.cs index 021cff2670..a50a2ddb69 100644 --- a/src/ImageSharp/Formats/Pbm/PbmImageFormatDetector.cs +++ b/src/ImageSharp/Formats/Pbm/PbmImageFormatDetector.cs @@ -1,6 +1,8 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +using System.Diagnostics.CodeAnalysis; + namespace SixLabors.ImageSharp.Formats.Pbm; /// @@ -16,7 +18,11 @@ public sealed class PbmImageFormatDetector : IImageFormatDetector public int HeaderSize => 2; /// - public IImageFormat? DetectFormat(ReadOnlySpan header) => IsSupportedFileFormat(header) ? PbmFormat.Instance : null; + public bool TryDetectFormat(ReadOnlySpan header, [NotNullWhen(true)] out IImageFormat? format) + { + format = IsSupportedFileFormat(header) ? PbmFormat.Instance : null; + return format != null; + } private static bool IsSupportedFileFormat(ReadOnlySpan header) { diff --git a/src/ImageSharp/Formats/Png/PngImageFormatDetector.cs b/src/ImageSharp/Formats/Png/PngImageFormatDetector.cs index 2e20668248..1b574d49bb 100644 --- a/src/ImageSharp/Formats/Png/PngImageFormatDetector.cs +++ b/src/ImageSharp/Formats/Png/PngImageFormatDetector.cs @@ -2,6 +2,7 @@ // Licensed under the Six Labors Split License. using System.Buffers.Binary; +using System.Diagnostics.CodeAnalysis; namespace SixLabors.ImageSharp.Formats.Png; @@ -14,9 +15,10 @@ public sealed class PngImageFormatDetector : IImageFormatDetector public int HeaderSize => 8; /// - public IImageFormat? DetectFormat(ReadOnlySpan header) + public bool TryDetectFormat(ReadOnlySpan header, [NotNullWhen(true)] out IImageFormat? format) { - return this.IsSupportedFileFormat(header) ? PngFormat.Instance : null; + format = this.IsSupportedFileFormat(header) ? PngFormat.Instance : null; + return format != null; } private bool IsSupportedFileFormat(ReadOnlySpan header) diff --git a/src/ImageSharp/Formats/Tga/TgaImageFormatDetector.cs b/src/ImageSharp/Formats/Tga/TgaImageFormatDetector.cs index 13d4e784c9..ad76bc3fbd 100644 --- a/src/ImageSharp/Formats/Tga/TgaImageFormatDetector.cs +++ b/src/ImageSharp/Formats/Tga/TgaImageFormatDetector.cs @@ -1,6 +1,8 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +using System.Diagnostics.CodeAnalysis; + namespace SixLabors.ImageSharp.Formats.Tga; /// @@ -12,9 +14,10 @@ public sealed class TgaImageFormatDetector : IImageFormatDetector public int HeaderSize => 16; /// - public IImageFormat? DetectFormat(ReadOnlySpan header) + public bool TryDetectFormat(ReadOnlySpan header, [NotNullWhen(true)] out IImageFormat? format) { - return this.IsSupportedFileFormat(header) ? TgaFormat.Instance : null; + format = this.IsSupportedFileFormat(header) ? TgaFormat.Instance : null; + return format != null; } private bool IsSupportedFileFormat(ReadOnlySpan header) diff --git a/src/ImageSharp/Formats/Tiff/TiffImageFormatDetector.cs b/src/ImageSharp/Formats/Tiff/TiffImageFormatDetector.cs index 9af6a659e3..6382037ed3 100644 --- a/src/ImageSharp/Formats/Tiff/TiffImageFormatDetector.cs +++ b/src/ImageSharp/Formats/Tiff/TiffImageFormatDetector.cs @@ -1,6 +1,8 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +using System.Diagnostics.CodeAnalysis; + namespace SixLabors.ImageSharp.Formats.Tiff; /// @@ -12,14 +14,10 @@ public sealed class TiffImageFormatDetector : IImageFormatDetector public int HeaderSize => 8; /// - public IImageFormat? DetectFormat(ReadOnlySpan header) + public bool TryDetectFormat(ReadOnlySpan header, [NotNullWhen(true)] out IImageFormat? format) { - if (this.IsSupportedFileFormat(header)) - { - return TiffFormat.Instance; - } - - return null; + format = this.IsSupportedFileFormat(header) ? TiffFormat.Instance : null; + return format != null; } private bool IsSupportedFileFormat(ReadOnlySpan header) diff --git a/src/ImageSharp/Formats/Webp/WebpImageFormatDetector.cs b/src/ImageSharp/Formats/Webp/WebpImageFormatDetector.cs index 3b30a2cfb5..2b91aa95fe 100644 --- a/src/ImageSharp/Formats/Webp/WebpImageFormatDetector.cs +++ b/src/ImageSharp/Formats/Webp/WebpImageFormatDetector.cs @@ -1,6 +1,8 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +using System.Diagnostics.CodeAnalysis; + namespace SixLabors.ImageSharp.Formats.Webp; /// @@ -12,8 +14,11 @@ public sealed class WebpImageFormatDetector : IImageFormatDetector public int HeaderSize => 12; /// - public IImageFormat? DetectFormat(ReadOnlySpan header) - => this.IsSupportedFileFormat(header) ? WebpFormat.Instance : null; + public bool TryDetectFormat(ReadOnlySpan header, [NotNullWhen(true)] out IImageFormat? format) + { + format = this.IsSupportedFileFormat(header) ? WebpFormat.Instance : null; + return format != null; + } private bool IsSupportedFileFormat(ReadOnlySpan header) => header.Length >= this.HeaderSize && IsRiffContainer(header) && IsWebpFile(header); diff --git a/src/ImageSharp/Image.Decode.cs b/src/ImageSharp/Image.Decode.cs index 806a0f471b..a556cbceb3 100644 --- a/src/ImageSharp/Image.Decode.cs +++ b/src/ImageSharp/Image.Decode.cs @@ -82,8 +82,7 @@ public abstract partial class Image { if (formatDetector.HeaderSize <= headerSize) { - IImageFormat attemptFormat = formatDetector.DetectFormat(headersBuffer); - if (attemptFormat != null) + if (formatDetector.TryDetectFormat(headersBuffer, out IImageFormat attemptFormat)) { format = attemptFormat; } diff --git a/src/ImageSharp/Image.FromBytes.cs b/src/ImageSharp/Image.FromBytes.cs index 0d36e397c1..922448c826 100644 --- a/src/ImageSharp/Image.FromBytes.cs +++ b/src/ImageSharp/Image.FromBytes.cs @@ -39,9 +39,7 @@ public abstract partial class Image foreach (IImageFormatDetector detector in configuration.ImageFormatsManager.FormatDetectors) { - IImageFormat? f = detector.DetectFormat(data); - - if (f != null) + if (detector.TryDetectFormat(data, out IImageFormat? f)) { return f; } diff --git a/tests/ImageSharp.Tests/Image/MockImageFormatDetector.cs b/tests/ImageSharp.Tests/Image/MockImageFormatDetector.cs index d0576c828b..8564eaa5bb 100644 --- a/tests/ImageSharp.Tests/Image/MockImageFormatDetector.cs +++ b/tests/ImageSharp.Tests/Image/MockImageFormatDetector.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +using System.Diagnostics.CodeAnalysis; using SixLabors.ImageSharp.Formats; namespace SixLabors.ImageSharp.Tests; @@ -19,8 +20,10 @@ public class MockImageFormatDetector : IImageFormatDetector public int HeaderSize => 1; - public IImageFormat DetectFormat(ReadOnlySpan header) + public bool TryDetectFormat(ReadOnlySpan header, [NotNullWhen(true)] out IImageFormat? format) { - return this.localImageFormatMock; + format = this.localImageFormatMock; + + return true; } } diff --git a/tests/ImageSharp.Tests/TestFormat.cs b/tests/ImageSharp.Tests/TestFormat.cs index f3176f16c5..bfad231949 100644 --- a/tests/ImageSharp.Tests/TestFormat.cs +++ b/tests/ImageSharp.Tests/TestFormat.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +using System.Diagnostics.CodeAnalysis; using System.Numerics; using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.PixelFormats; @@ -174,14 +175,11 @@ public class TestFormat : IImageFormatConfigurationModule, IImageFormat public int HeaderSize => this.testFormat.HeaderSize; - public IImageFormat DetectFormat(ReadOnlySpan header) + public bool TryDetectFormat(ReadOnlySpan header, [NotNullWhen(true)] out IImageFormat? format) { - if (this.testFormat.IsSupportedFileFormat(header)) - { - return this.testFormat; - } + format = this.testFormat.IsSupportedFileFormat(header) ? this.testFormat : null; - return null; + return format != null; } public TestHeader(TestFormat testFormat) => this.testFormat = testFormat;